0

I am trying to write an upgradable smart contract in Remix. This involves a Proxy contract, a Logic_0_1_0 contract, and a Logic_0_2_0 contract.

I uploaded Proxy and Logic_0_1_0 only, and the delegatecall in magicFunction worked fine, giving the event of a = 7. However, when I deployed Logic_0_2_0, without even calling updateLogic() in Proxy, the magicFunction stopped giving events. Even after remapping Proxy to point to Logic_0_2_0, I was unable to get any event in the transaction logs at all.

This is my code, across the 3 files.

//proxy.sol
pragma solidity ^0.5.0;

contract Proxy {
    // Sets the position in memory of the logicAddress to a high
    // number. This prevents potential overwriting of memory when
    // using delegatecall on Logic contracts.
    bytes32 private constant logicPosition = keccak256("ucot.logic.address");

    constructor (address logicAddress) public {
        updateLogic(logicAddress); 
    }

    //Updates the address
    function updateLogic(address newLogicAddress) public {
        _setLogic(newLogicAddress);
        // (bool ok,) = newLogicAddress.delegatecall(
        //     abi.encodeWithSignature("initialise()"));
        // if (!ok) revert();
    }

    // Sets the logic contract address
    function _setLogic(address _logicAddress) internal {
        bytes32 position = logicPosition;
        assembly {
            sstore(position, _logicAddress)
        }
    }
    // Returns the logic contract address
    function _getLogic() public view returns (address logic) {
        bytes32 position = logicPosition;
        assembly {
            logic := sload(position)
        }
    }

    // Passes on the call of magic function to Logic.
    function magicFunction() public {
        address logicAddress = _getLogic();
        assembly {
            let ptr := mload(0x40)
            calldatacopy(ptr, 0x0, calldatasize) 
            let ok := delegatecall(gas, logicAddress, ptr, calldatasize, 0x0, 0)
        }

    }
}

//logic.sol
pragma solidity ^0.5.0;

contract Logic_0_1_0 {

    uint a;

    // Set a to 7, and then emit an event
    event result(uint val);
    function magicFunction() public returns (uint) {
        a = 7;
        emit result(a); 
    }
}

//logic2.sol
pragma solidity ^0.5.0;

import "./logic.sol";

contract Logic_0_2_0 is Logic_0_1_0 {

    // Set a to 9, and then emit an event
    // Should overload the previous magicFunction
    function magicFunction() public returns (uint) {
        a = 9;
        emit result(a); 
    }
}

And here is a screenshot of the transaction I get in the Remix console Remix Screenshot

I am still relatively new to smart contract coding, and blockchain in general, so any advice is appreciated.

New contributor
Kevin Zhu is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
  • I've tried to reproduce the issue, but everything was OK. Try reloading the page and redeploying your contracts. Another option is to test your contracts on testnet - this may be working if it is a remix bug. – Igor Sobolev Aug 14 at 10:22
  • Yep, I've confirmed it is a bug with Remix. Looking more closely, I discovered that it was actually the act of compiling (ctrl+s) that would break these functions. magicFunction() would work, and then after compiling logic2, it would break. It wasn't the event not being returned, but the entire function not being called. We can see that in the "to" field of my screenshot, the address of the proxy contract appears twice. I have tested it on a private testnet and confirmed it works normally. Thanks for the help :) – Kevin Zhu Aug 16 at 2:19

Your Answer

Kevin Zhu is a new contributor. Be nice, and check out our Code of Conduct.

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.