A message from our CEO about the future of Stack Overflow and Stack Exchange. Read now.
76

DELEGATECALL basically says that I'm a contract and I'm allowing (delegating) you to do whatever you want to my storage. DELEGATECALL is a security risk for the sending contract which needs to trust that the receiving contract will treat the storage well. DELEGATECALL was a new opcode that was a bug fix for CALLCODE which did not preserve msg.sender and ...


25

Here is a snippet of D using delegatecall on E from Difference between CALL, CALLCODE and DELEGATECALL contract D { uint public n; address public sender; function delegatecallSetN(address _e, uint _n) { _e.delegatecall(bytes4(keccak256("setN(uint256)")), _n); // D's storage is set, E is not modified } } contract E { uint public n; address ...


11

delegatecall is not supposed to handle return values as it cannot be aware of the length of the other side (unless there would be a dedicated parameter passed to it). Currently, the delegatecall Solidity built-in method does not support supplying the return value size, nor getting the return value out after the call. According to the documentation it ...


7

DELEGATECALL is an instruction interpreted by EVM. So to execute DELEGATECALL you have to have a program (contract) that gets executed on EVM. DELEGATECALL takes six operands, one of them is the address of the calee. So it can only call deployed contracts. Note that so called library is just a special contract which operations are called with DELEGATECALL. ...


6

Update. I'm leaving the answer below in place as it has some interesting points, but I think I've finally got to the bottom of this. The key point is buried in the Subtleties page: A CALL or CREATE can consume at most 63/64 of the gas remaining at the time the CALL is made; if a CALL asks for more than this prescribed maximum, then the inner call ...


6

When, in C, you do b.delegatecall(, what happens is that: the code used is that of B the storage used is that of C And B and C have the same storage layout: both the uint value are located on storage slot 0. with address a and address b located on storage slot 1 So now you are executing B's code with C's storage. And you ask a.delegatecall(bytes4(...


5

Yes, although obviously each contract has to execute the call itself. You can do this 1024 times until you reached the maximum depth. At that depth all new calls will fail. This even lead to vulnerabilities in the past. That said, EIP-150 increased the gas cost of calls so much that you can't reach the maximum depth anymore.


5

OpenZeppelin uses the "unstructured storage" proxy pattern. See the documentation for details: https://docs.openzeppelin.com/sdk/2.5/pattern OpenZeppelin in the proxy patterns blog post (https://blog.openzeppelin.com/proxy-patterns/) explored three proxy pattern options: Inherited Storage Eternal Storage Unstructured Storage An upgradeable contract ...


4

The issue is that the response variable is not a memory pointer, it's a stack variable. When you use it as the pointer for your out data in the delegatecall, you're actually just writing the data to the 0 memory location. This doesn't cause errors because that space is reserved for "scratch space", but it also never loads the result into your return variable....


4

delegatecall returns true on success, so if(_c.delegatecall(bytes4(sha3("setTestInt(uint")),_testInt )) throw will throw if the call is successfull. Try if(!_c.delegatecall(bytes4(sha3("setTestInt(uint")),_testInt ))


4

The problem here is that Solidity call encoder have troubles in encoding dynamic arrays. Here is the example to illustrate this, assuming you have an instance of your first contract in web3.eth: console.log(settingContract.set.getData([10])); 0x6ea9bfc5 0000000000000000000000000000000000000000000000000000000000000020 ...


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 ...


3

Chains of delegatecall(..) will still retain the original msg.sender, storage, balance, etc values from the calling contract. contract A { function indirect() { B.doit(); } function direct() { C.doit(); } } library B { function doit() { C.doit(); } } library C { function doit() { msg.sender.send(...


3

Yes, from Relay you can call Access2 functions, like createEntity. The important code in Relay that makes it happen is its fallback-function: function() { if(!currentVersion.delegatecall(msg.data)) throw; } It is helpful to read the questions and answers on fallback-function to learn more about them. Basically, when you invoke (call) createEntity in ...


3

The delegatecall arguments are incorrect, you should use: function delegatedCalculation(uint firstNumber, uint secondNumber) public { bool status; bytes memory result; (status, result) = linkedContract.delegatecall(abi.encodePacked(bytes4(keccak256("calculate(uint256,uint256)")), firstNumber, secondNumber)); } Or simply you can ...


3

You can use abi.decode(...): abi.decode(bytes memory encodedData, (...)) returns (...): ABI-decodes the given data, while the types are given in parentheses as second argument. Example: (uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes)). Returning structs is not possible with the current ABI. You should add ...


2

Vitalik just added support for delegatecall to Serpent, which answers my question by making my method obsolete. You use it by adding call=delegatecall to your functions calls.


2

Showing the difference between the call, callcode and the delegatecall we can consider the example of the following code : Contracts can interact in three ways Call : By directly calling from a contract through a function which will not set the caller's value but sets the callee's value. And sender in this will be the caller only CallCode : When called ...


2

From what I can gather mstore() will write in 32 byte chunks, therefore mstore(in_pos, 0x04) is still in the same space as in_pos and will overwrite the 4 bytes function signature. What I ended up doing is writing the 4 bytes in the first 32 bytes, the 1st arg in the 2nd 32 bytes and the 2nd arg in the 3rd 32 bytes, then called delegatecall pointing to the ...


2

That string is called the function selector. It is calculated as the first four bytes of the sha3 hash of the signature of the function. The signature is defined as the canonical expression of the basic prototype, i.e. the function name with the parenthesised list of parameter types. Parameter types are split by a single comma - no spaces are used (as you ...


2

Should work if you use tx.origin. However this is usually advised against.


2

You should be safe as the cleanup method seems to be only executable by the owner of the contract (has the onlyOwner modifier, which I guess checks msg.sender == owner). What the linked article refers to is the possibility of another contract inadvertently calling a function on a second contract (which contains a selfdestruct call) using delegatecall, in ...


2

Yes, you can do that if you make your contract upgradable. A brief description of the approach - Create DataLayer of contract as a separate contract(DataStore) and design the main contract in a way so that whenever you are going to kill your contract, you can link your old DataStore to the new Contract. You can read this blog from one of my colleague which ...


2

I think you are misunderstanding the purpose of delegatecall(). It executes the called contract in the context of the calling contract. In other words, it will use the code from the called contract, but the msg and storage from the calling contract. Since it only has access to the calling contract's storage, it can't look up or modify balances or anything ...


2

No, means that if you use delegate call in your contract and the code at the target address contains a line with selfdestruct(someaddress), this code will be executed in your contract context, effectively destroying your contract. This means you should be careful when using delegatecall and only use it in contracts that you wrote or that you know well. ...


2

The fallback function gets called when no other function matches the calldata signature. In this code, the fallback functions is used as a universal function. This is done by forwarding the calldata to the contract at currentVersion. Forwarding the calldata to another smart contract results in it running the proper funcion. There are two ways to do this: ...


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 ...


2

In the same document, it says: As the compiler cannot know where the library will be deployed at, these addresses have to be filled into the final bytecode by a linker and goes on to explain how to do that.


2

You misunderstand what a forwarder does when it uses delegatecall. What delegatecall does is use the code of elsewhere to run in the context of the contract that used delegatecall. So if your instance of TestContractForwarder "delegate calls" the code of TestContract, then you can expect the storage of your instance of TestContractForwarder to be updated. ...


2

These 4 are really very well-know patters. (1) After analysing Delegatecall-based approach, I give up it because of two main reasons: you can only add new variables not delete or change existing ones. So, if you have a struct defined and you want to change a type or add an existing field, if you want to delete a variable etc.... you cannot. Also, it makes ...


Only top voted, non community-wiki answers of a minimum length are eligible