DelegateCall in Solidity — With Examples
DelegateCall Solidity
DelegateCall is a unique feature in Solidity, which allows contract A
to execute code in contract B
with contract A
storage, and the preserving the msg
(msg.sender
, msg.value
, etc..).
Today, we will discuss how DelegateCall works and provide some code samples.
Understanding DelegateCall
DelegateCall is a low-level Solidity opcode that allows a contract to execute code from another contract, but it using the state and the storage of the calling contract.
The syntax for DelegateCall is as follows:
(bool success, bytes memory returnData) = address.delegatecall(bytes memory data);
The address
parameter is the address of the contract to execute, and the data
parameter is the encoded function call to execute.
DelegateCall vs. Call
The primary distinction between call
and delegateCall
is how they handle the execution context of the function. When you use call
, the called function executes within the context of the calling contract. This means that the called function has access to the calling contract's storage and code.
On the other hand, when you use delegateCall
, the called function executes in the context of the calling contract's caller. This means that the called function has access to the caller's storage and code, not the calling contract's storage and code.
In simple terms, delegatecCall
enables the called contract to access the storage and code of the calling contract's caller, whereas call
only permits the called contract to use the storage and code of the calling contract.
The difference between call
and delegateCall
is crucial when upgrading smart contracts. By using delegateCall
, you can create a separate contract that contains the upgraded logic, and then call that contract from your main contract using delegateCall
. This way, your main contract retains its storage, and the upgraded logic is executed in the context of the calling contract's caller. This allows for seamless upgrades without losing any data.
DelegateCall Security
As you continue to learn about delegateCall, it's important to gain hands-on experience and training to fully understand the potential risks and vulnerabilities of smart contracts. That's where my smart contract hacking and auditing course comes in.
This course offers high-quality video content and practical hands-on exercises to help you gain valuable knowledge and skills. You will learn how to identify potential security risks and vulnerabilities in smart contracts, as well as best practices for preventing and mitigating those risks.
By completing this course, you will become a more knowledgeable and skilled auditor, increasing your chances of landing a job in the growing field of smart contract auditing.
But the benefits don't stop there. Upon completion of the course, you'll receive a certificate to showcase your newly acquired expertise.
This certificate can be a powerful tool when seeking employment opportunities, demonstrating to potential employers that you have the necessary skills and knowledge to be a successful smart contract auditor.
Whether you're looking to advance your career or simply improve your understanding of smart contract security, this course is the perfect solution. Take your first step toward becoming a top-notch smart contract auditor:
DelegateCall Use Cases
Here are some of the most common use cases for the delegateCall
opcode:
Proxy Contracts:
delegateCall
is often used in proxy contracts, which forward function calls to an implementation contract. By usingdelegateCall
, the implementation contract can be upgraded without changing the address of the proxy contract, since the proxy contract's storage and state will remain unchanged.Modular Contracts:
delegateCall
can be used to create modular contracts. In this design, each module is a separate contract that can be upgraded independently. The modules can usedelegateCall
to interact with each other and with the main contract, allowing for greater flexibility and modularity.Gas Efficiency:
delegateCall
can be used to reduce gas costs. It allows multiple contracts to share the same code without having to copy it into each contract. This can be particularly useful for large contracts that would otherwise exceed the gas limit.Library Contracts:
delegateCall
can be used to implement library contracts that contain reusable code that can be called from multiple contracts. The library contract's functions are executed in the context of the calling contract's caller, allowing the library code to access the caller's storage.Cross-Chain Communication: The
delegateCall
function can be used to enable cross-chain communication between different blockchain networks. By usingdelegateCall
to interact with a bridge contract on another blockchain, contracts on one chain can call functions on the other chain, allowing for interoperability between different blockchain networks.
DelegateCall Examples
Let's look at some code samples to better understand how delegateCall
works:
Example 1: How delegateCall works
In the following example, we have two smart contracts, Contract A
and Contract B
contract A {
uint public a;
function setA(uint _a) public {
a = _a;
}
}
contract B {
address public aAddress;
uint public b;
constructor(address _aAddress) {
aAddress = _aAddress;
}
function setA(uint _a) public {
(bool success, bytes memory result) = aAddress.delegatecall(
abi.encodeWithSignature("setA(uint256)", _a)
);
require(success, "delegatecall failed");
}
function setB(uint _b) public {
b = _b;
}
}
In this example, contract B
has a state variable aAddress
that stores the address of contract A
, which has a state variable a
.
The setA
function in contract B
uses delegatecall
to call the setA
function in contract A
within the context of contract B
.
This allows contract A
to access the storage variables and state of contract B
.
Example 2: Gas-efficient Upgradeable Contracts
One common use case for delegatecall
is to implement proxy contracts that can be upgraded (upgradeable contracts) in a gas-efficient way.
The basic idea is to separate the contract state from the contract logic so that the contract logic can be upgraded without affecting the state.
Here's an example of a proxy upgradable contract that uses delegatecall
:
pragma solidity ^0.8.0;
contract Proxy {
address private _implementation;
function setImplementation(address implementation) external {
_implementation = implementation;
}
fallback() external payable {
address impl = _implementation;
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), impl, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}
In this example, we define a contract called Proxy
that contains a private _implementation
variable. This variable stores the address of the contract that contains the contract logic. We also define a setImplementation
function that allows the contract owner to update the _implementation
variable.
The fallback
function is where the magic happens. It uses delegatecall
to execute the function call in the context of the contract that contains the contract logic. This means that the contract state is still stored in the Proxy
contract, but the contract logic is executed in the context of the _implementation
contract.
Conclusion
We learned what is the DelegateCall opcode in Solidity, an important feature for smart contract developers.
DelegateCall allows a contract to execute code from another contract while using the state and storage of the calling contract.
We explained the fundamental differences between DelegateCall and Call and discussed the risks and vulnerabilities of smart contracts.
DelegateCall can be used to upgrade smart contracts without losing any data. By creating a separate contract containing the upgraded logic and calling that contract from the main contract, developers can upgrade their contracts while retaining the main contract's storage.
We saw some code samples to better understand how DelegateCall works and its most common use cases. Examples include creating proxy contracts, modular contracts, implementing library contracts, and enabling cross-chain communication between different blockchain networks.
Subscribe to my newsletter
Read articles from Johnny Time directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by