0

I tested this in Remix and it seems that the ether remains in the delegator contract and doesn't get forwarded. Using the code below to test:

contract SomeContract {
    address public sender;
    uint public value;  


    function callMe()
    public 
    payable {
        sender = msg.sender;
        value = msg.value; 
    }


    function getBalance()
    public
    view
    returns (uint) {
        return address(this).balance;
    }
}


contract CallAnotherContract {
    address public sender;
    uint public value;

    // Check if you can send ETH to non-payable function
    function callTheOtherContract(address _contractAddress) 
    public
    payable {
        (bool success, bytes memory returnData) = (_contractAddress.delegatecall(abi.encode(bytes4(keccak256("callMe()")))));
        require(success);
    }

    function getBalance()
    public
    view
    returns (uint) {
        return address(this).balance;
    }
}
  • 1
    delegatecall basically means "run this other code as though it were my code." So in your code, it's correct that no ether moves to SomeContract. – smarx Jan 24 at 8:57
4

Exactly as @smarx mentioned, delegatecall does not do actual actions to the contract that you gave, a.k.a _contractAddress, but rather copy the code of function callMe() and execute in the CallAnotherContract.

In Solidity's documentation, it states the feature of delegatecall:

The purpose of delegatecall is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used.

And more specifically:

...only the code of the given address is used, all other aspects (storage, balance, …) are taken from the current contract.

To perform the desired action, which is to forward the value to SomeContract when calling callTheOtherContract in CallAnotherContract, we could modify the callTheOtherContract in the following way:

function callTheOtherContract(address _contractAddress) 
    public
    payable 
{
    (bool success, bytes memory returnData) = (_contractAddress.call.value(msg.value)(abi.encode(bytes4(keccak256("callMe()")))));
    require(success);
}

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.