1

I have the following sample code:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.7;

import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/ERC20.sol';

contract ERC20TotalSupplyTest is ERC20 {
    event Msg(address addr);

    constructor() ERC20('simple', 'TST') {
        emit Msg(address(this));
        totalSupply();
        IERC20 token = IERC20(address(this));
        token.totalSupply(); //this line reverts the transaction
    }
}

I can compile the smart contract. If I leave out the last line, the contract deploys fine. With the last line, I cannot deploy the contract as the deployment is reverted.

In my real project, the constructor is calling another smart contract that then casts the ERC20 smart contract to the IERC20 interface and calls a method on it.

Can someone explain why token.totalSupply(); causes the deployment of the smart contract to be reverted while totalSupply(); executes without a problem?

The Msg event logs the final address of the contract. If this address is available to the event, I guess the right address must be available to the IERC20 cast? Or does the IERC20(address(this)) cast assumes that the contract has already been deployed to the blockchain, which is not the case yet?

2 Answers 2

1

If I modify the contract as follows:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.7;

import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/ERC20.sol';

contract ERC20TotalSupplyTest is ERC20 {
    event Msg(address addr);

    bytes public byteCode;
    uint public byteCodeLength;

    constructor() ERC20('simple', 'TST') {
        emit Msg(address(this));
        totalSupply();
        byteCode = address(this).code;
        byteCodeLength = byteCode.length;

        //IERC20 token = IERC20(address(this));
        //token.totalSupply(); //this line reverts the transaction
    }
}

I can inspect the deployed contract and verify that the byteCode at address(this) is empty during the constructor call. That is why IERC20(address(this)).totalSupply(); must fail in the constructor.

1
  • 1
    The bytecode is deployed after the constructor finalizes correctly, so no external calls are possible during the constructor execution. Public and internal function calls are possible from the constructor.
    – Ismael
    Jun 14, 2022 at 13:45
0

it does'nt make any point of using IERC20 token = IERC20(address(this));, This can be only use where you use interface.

3
  • I posted an example where my problem was isolated. In my real project, I had smart contract A and B. The constructor of A called a function of B. In this function, B received the address of A and tried to call a function on A. This is not possible as is explained in my answer. Jun 15, 2022 at 15:42
  • how can it be possible, like how you are connecting by providing address in constructor, you can connect A with B but then you cannot connect B with A.
    – DereK
    Jun 16, 2022 at 11:51
  • share an code please for better understading.
    – DereK
    Jun 16, 2022 at 11:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.