0

I'm trying to figure out why this code reverts. I need to make 10 bottles. This is how I do this:

  1. deploy Logic contract
  2. deploy 10 Proxy contracts
  3. call "upgrade" at each Proxy and pass Logic address
  4. it works

But the problem is when I need to upgrade, I have to call upgrade to every bottle. In the future there might be 50 of them. It would take time and be expensive to call each one.

I got an idea to create a ProxyDelegate contract. Every bottle calls delegate and delegate calls logic. If I need to change bottle logic I need to change only delegate.

So the steps look like this:

  1. deploy Logic contract
  2. deploy 10 Proxy contracts
  3. deploy Proxy Delegate
  4. call "upgrade" at Proxy Delegate and pass Logic address
  5. call "upgrade" at each Proxy and pass Delegate address
  6. it reverts

What am I doing wrong?

http://remix.ethereum.org/

pragma solidity ^0.5.0;

contract BottleStorage
{
    uint public m_FillAmount;
    bool internal m_ProxyInitialized;
}

contract BottleLogic is BottleStorage
{
    function init()
        external 
    {
        require(!m_ProxyInitialized);
        m_FillAmount = 100;
        m_ProxyInitialized = true;
    }

    function drink(uint pAmount)
        external
    {
        uint v =  m_FillAmount - pAmount;
        require(v <= m_FillAmount);
        m_FillAmount = v;
    }

    function fill(uint pAmount)
        external
    {
        uint v =  m_FillAmount + pAmount;
        require(v >= m_FillAmount && v <= 150);
        m_FillAmount = v;
    }
}

contract Proxy is BottleStorage
{
    address public m_Implementation;

    function upgrade(
        address pImplementation
    )
        external
    {
        // access etc.
        m_Implementation = pImplementation;
        BottleLogic(address(this)).init();
    }

    function callDrink(uint pValue)
        external
    {
        address(this).call(abi.encodeWithSignature("drink(uint256)", pValue));
    }

    function callFill(uint pValue)
        external
    {
        address(this).call(abi.encodeWithSignature("fill(uint256)", pValue));
    }

    function ()
    external payable
    {
        address _impl = m_Implementation;
        assembly {
            let ptr := mload(0x40)
            calldatacopy(ptr, 0, calldatasize)
            let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
            let size := returndatasize
            returndatacopy(ptr, 0, size)
            switch result
            case 0 { revert(ptr, size) }
            case 1 { return(ptr, size) }
        }
    }
}

contract ProxyDelegate is Proxy
{

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.