0

I am working on using Proxy contracts in solidity 0.4.24, I have deployed the logic contract and the proxy contract as well using the address of logic contract as the implementation contract address.

Here is the first version of the logic contract

pragma solidity 0.4.24;

contract Initializable {

  bool private initialized;
  bool private initializing;

  modifier initializer() {
    require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");

    bool wasInitializing = initializing;
    initializing = true;
    initialized = true;

    _;

    initializing = wasInitializing;
  }

  function isConstructor() private view returns (bool) {
    uint256 cs;
    assembly { cs := extcodesize(address) }
    return cs == 0;
  }

  uint256[48] private ______gap;
  uint256 internal first;
}

contract MyContract is Initializable {
    function initialize(uint256 _first) external initializer {
        first = _first;
    }

    function returnFirst() external view returns (uint) {
        return first;
    }
}

Now i have written a new version of the implementation contract which goes like this

pragma solidity 0.4.24;


contract Initializable {
  bool private initialized;
  bool private initializing;

  modifier initializer() {
    require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");

    bool wasInitializing = initializing;
    initializing = true;
    initialized = true;

    _;

    initializing = wasInitializing;
  }

  function isConstructor() private view returns (bool) {
    uint256 cs;
    assembly { cs := extcodesize(address) }
    return cs == 0;
  }

  uint256 internal second;
  uint256[47] private ______gap;
  uint256 internal first;
}

contract MyContract is Initializable {
    function initialize(uint256 _first) external initializer {
        first = _first;
    }

    function returnFirst() external view returns (uint) {
        return first;
    }
}

contract MyContractV2 is MyContract {
    // ISSUE HERE ******
    bool private initializedV2;

    function initializeV2(uint256 _second) external {
        require(!initializedV2,"contract already initialized");
        second = _second;
        initializedV2 = true;
    }

    function returnSecond() external view returns (uint) {
        return second;
    }
}

The issue i have is if i specify the value of initializedV2 variable as false in MyContractV2, the initializeV2 method does not work and fails on gas estimation in remix. However if i keep the variable uninitialized the method succeeds and i am able to make changes in the storage structure of the proxy contract.

Why does the error occur ?

1

1 Answer 1

0

Why are you checking if the contract is initialized? That is handled in Initializable.sol smart contract of the Openzeppelin Upgradable contracts. It seems you are having a logic error.

See here: Initializable.sol

For more clarity read: Using Multiple Initializers in Upgradable Smart Contract (Check my gist as well)

Ensure that you:

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

remember for any other openZeppelin imports ONLY use

openzeppelin/contracts-upgradeable/ for upgradable smart contracts.

Your Answer

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

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