0

We have an issue with delegatecall method.

We want to call contract C2 from C1 (which is supposed to be a pass through contract for the user wallet). When we are calling C2 via C1 even using delegatecall or assembly instruction, the allowance of C1 is getting amended, but not that of the calling wallet. Eventlogs are appended below the code. Both delegatecallSetNum and delegatecallSetNumAssembly methods are behaving in an identical manner.

Code:

pragma solidity ^0.5.16;

contract C1 {

  uint public num;
  address public sender;    

  function c2setNum(address _c2, uint _num) public{
      C2 c2 = C2(_c2);
      c2.setNum(_num);
  }
  function delegatecallSetNum(address c2, uint _num) public {
    c2.delegatecall(abi.encodeWithSignature("setNum(uint256)",_num));
  }


  function delegatecallSetNumAssembly(address c2, uint _num) public {

    address _target = c2;
    bytes memory _data = abi.encodeWithSignature("setNum(uint256)",_num);
    bytes32 response;

    // call contract in current context
    assembly {
        let succeeded := delegatecall(sub(gas, 500000), _target, add(_data, 0x20), mload(_data), 0, 32)
        response := mload(0)      // load delegatecall output
        switch iszero(succeeded)
        case 1 {
            // throw if delegatecall failed
            revert(0, 0)
        }
    }
  }


function getAddr1(address _c2) public view returns (address){
      C2 c2 = C2(_c2);
     return  c2.getAddr();
  }

}

contract C2 {
  uint public num;
  address public sender;

  event AddedValuesByDelegateCall(uint256 a, address addr, bool success);

  function setNum(uint256 _num) public {
    num = _num;
    sender = msg.sender;

    emit AddedValuesByDelegateCall(_num, msg.sender, true);
  }  
    function getAddr() public view returns (address){

        return msg.sender;        
    }
}

Kovan Deployment addresses: C2 : 0xa1891c26352742Cc9d9E0ec3B34C3690D1dEB2E3 C1 : 0x2fC788e36B6B844c4B9a61804ee41fe6128A9901

Eventlog: https://kovan.etherscan.io/tx/0x36fd46c739cf556583f0ebec004d039808b758b0fb04efcad3684f57672ddb2e#eventlog

0

TLDR; When you use delegate call it is editing the storage of the contract that you are calling from (i.e editing C1 with the code being executed in C2).

There exists a special variant of a message call, named delegatecall which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract and msg.sender and msg.value do not change their values. From the Solidity docs


When you call C2 from C1 you are going to be editing the storage of C1 not C2. Delegate call allows a second contract (in your case C2) to edit the storage of the calling contract (C1). So that is why it is amending C1's allowances. If you want to edit C2, I would recommend using a normal .call() rather than the .delegatecall() as this will do what you want (edit C2).

The easiest way to think about this is whatever function you are calling in C2 should be treaded as a script that is going to execute in the context of C1. This also means that if you try to call any functions within C2 it will fail (unless you make an instance of C2 in your script) because it is executing in the context of C1 which does not have that function.

Hope this helps :)

| improve this answer | |
  • So how do we delegte call from C1 but still data of C2 gets modified? We are calling DeFI contracts where we have to use proxy contracts, key requirement is that we want msg.sender to be stored but in C2. – Nitin Goyal May 10 at 10:14
  • You would need to use call not delegatecall if you want C2's data to get modified. If you have to use a proxy delegate call set up, what you can do to get around C2's data not getting modified is inside the function you call, create an instance of C2 (it will feel weird to make an instance of C2 inside C2s function, but trust) and then call the functions you need to in order to change C2's storage. Call C2 from C1. You are editing C1's data. Inside the function, you call in C2, make an instance of C2 and update/change the storage you need to. – Veronica Coutts May 19 at 11:48

Your Answer

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

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