1
pragma solidity >=0.4.22 <0.7.0;
contract D {
  uint public n;
  address public sender;

  function callSetN(address _e, uint256 _n) public {
    _e.call(abi.encode(bytes4(keccak256("setN(uint256)")), _n)); 
  }


  function delegatecallSetN(address _e, uint _n) public {
    _e.delegatecall(abi.encode(bytes4(keccak256("setN(uint256)")), _n));
  }
}

contract E {
  uint public n;
  uint public test;
  address public sender;

  function setN(uint256 _n) public {
    n = _n;
  }
}

That's my 2 example contracts. I am trying to understand call and delegatecall.

Problem 1: When I call callSetN in contract D and pass contract E's address and number: 20, it seems like that E contract's setN function gets called, but n variable doesn't become 20 in contract E.

Problem 2: When I call delegatecallSetN in contract D and pass contract E's address and number: 20, it still calls that function, but now, D contract's variable n doesn't become 20. Also at some point, I realized that for this one, setN doesn't called called at all.

Problem 3: I am starting to wonder why I'd need to use delegateCall in my code at all ? call seems enough and sufficient. Any example ?

Both of the problems seem to be related to how badly I use encode and _n variable.. Any ideas?

2

The problem is that abi.encode() adds padding the its arguments. The results is it is calling E fallback function which does nothing.

It can be resolved by using abi.encodeWithSignature():

  function callSetN(address _e, uint256 _n) public {
    _e.call(abi.encodeWithSignature("setN(uint256)", _n)); 
  }


  function delegatecallSetN(address _e, uint _n) public {
    _e.delegatecall(abi.encodeWithSignature("setN(uint256)", _n));
  }
2

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.