1

After reading this article about Solidity call() and delegateCall(): https://medium.com/coinmonks/delegatecall-calling-another-contract-function-in-solidity-b579f804178c

I have the following questions:

It mentions in the end (Wrap Up section):

  • If we know the ABI of the target function, we can directly use the target function signature
  • If we don’t know the ABI of the target function, we can use call(), or delegatecall(). But in the case of delegatecall(), we need to care about the order of the field variable.

But if we look at the call() and delegateCall() for the Calculator contract example, we still needed the Calculator address and the function signature as well, as per the line of code below. So what is the difference then? call() and delegateCall() also need the ABI of the target function.

function addValuesWithDelegateCall(address calculator, uint256 a, uint256 b) public returns (uint256) {
        (bool success, bytes memory result) = calculator.delegatecall(abi.encodeWithSignature("add(uint256,uint256)", a, b));
        emit AddedValuesByDelegateCall(a, b, success);
        return abi.decode(result, (uint256));
    }
    
    function addValuesWithCall(address calculator, uint256 a, uint256 b) public returns (uint256) {
        (bool success, bytes memory result) = calculator.call(abi.encodeWithSignature("add(uint256,uint256)", a, b));
        emit AddedValuesByCall(a, b, success);
        return abi.decode(result, (uint256));
    }

It also mentions:

In Ethereum function call can be expressed by bytecode as long as 4 + 32 * N bytes. And this bytecode consists of two parts

What does N represent?

1

1 Answer 1

2

N represents the number of arguments that the function takes.

For a function: add(uint256,uint256), N would be 2 and hence the function call would be 4 + 32*2 = 68 bytes long

The difference is that when contract A executes delegatecall to contract B, B's code is executed with contract A's storage, msg.sender and msg.value.

To give you a simpler example:

pragma solidity >0.8.0;

contract Receiver {
    string greeting = "Hello";
    
    event Greeting(string greeting);
    
    function greet() external  {
        emit Greeting(greeting);
    }
}

contract Sender {
    string greeting = "Hi";
    
    function delegatedGreeting(address _contract) external {
        (bool success,) = _contract.delegatecall(
            abi.encodeWithSignature("greet()")
        );
    }
    
    function callGreeting(address _contract) external {
        (bool success,) = _contract.call(
            abi.encodeWithSignature("greet()")
        );
    }
}

You can try this on Remix. Here are the event logs:

    Greeting event after call from Sender to Receiver.greet:
    {
        "event": "Greeting",
        "args": {
            "0": "Hello",
            "greeting": "Hello"
        }

    Greeting event after delegating call from Sender to Receiver.greet:
    {
        "event": "Greeting",
        "args": {
            "0": "Hi",
            "greeting": "Hi"
        }
    }

Your Answer

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

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