2

I am having trouble understanding the scope with delegatecall method. Here are my two contracts:

contract Caller {
     uint public testVar = 88;
     uint public myVariable = 6;

     function delegatecallExample(address _contract, uint newVar) public {
         _contract.delegatecall(bytes4(keccak256("updateMyVariable(uint256)")), newVar);
     }

}

contract CalledContract {
    uint public myVariable = 5;

    function updateMyVariable(uint newVar) public payable {
        myVariable = newVar;
    }

}

After deploying to a fresh remix instance, calling Caller.delegatecallExample with CalledContracts address and lets say 111, I observe that CalledContracts first declared variable (testVar in this case) is changed to 111 instead of myVariable. So what is the scope of delegatecall?

1

To expand on Henk's answer, an important implementation detail is that the storage layout is also used from the calling contract.

Since you declare testVar first, as far as CalledContract is concerned, it is in the same storage location as the CalledContract myVariable. Thus, when delegate call sets myVariable, it is actually updating the storage of testVar.

If you switch the declaration order to:

contract Caller {
     uint public myVariable = 6;
     uint public testVar = 88;

     function delegatecallExample(address _contract, uint newVar) public {
         _contract.delegatecall(bytes4(keccak256("updateMyVariable(uint256)")), newVar);
     }

}

it will update myVariable instead of testVar.

| improve this answer | |
2

This is the correct behaviour for delegatecall. delegatecall is like call, but the difference is the storage context functions run in. When calling another contract, any functions that contract runs access their own storage. With delegatecall, however, the called contract accesses the storage of the caller.

In your example, Caller delegatecalls CalledContract. The function updateMyVariable accesses and updates the first element in storage of Caller, which is testVar, because myVariable points to the first storage element.

Docs on call and delegatecall

| improve this answer | |
1

I don't think your question was directly answered in the previous responses.

When any function is called - delegatecall or otherwise - the EVM loads the requisite pointers & values into that call frame's volatile stack/memory.

So unless you explicitly:

a) align caller+delegate contract storage

b) explicitly pass in the caller contract's storage reference addresses as arguments to use in the function's call frame

your storage pointers are left up to the Delegate's standard function context.

Correct me if I'm wrong. I'm inducing.

| improve this answer | |

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.