Security Issues with Delegate Calls
Security Issues with Delegate Calls
What is the meaning of the Delegate Call?
A delegate call is a calling mechanism in smart contracts that allow the caller contract to send a message to a target contract, but the execution of the related code is done in the context of the caller, which essentially means that if contract A makes a delegatecall to another contract B, the storage and state changes will happen on the contract A, using the functions inside the contract B, i.e., the contract B will be able to make changes to the storage of contract A. In particular, this operator is useful for creating shared libraries of code that can be shared among multiple contracts.
Security Threats about Delegate Call
Delegate call in Smart Contract Security is considered critical because the storage of the caller contract is modified by the logic inside the callee contract.
Therefore, it needs proper security to ensure that the smart contract is not making unvalidated external calls to suspicious or user-controlled addresses. Otherwise, it will lead to hacks like The DAO and The Punk Protocol Hack.
A simple example of this would be:
In the example shown above, there’s a proxy contract with a “forward” function that takes the callee address and the data which needs to be sent.
Note that there’s no access control validation, and this function can be called by any external user. This will allow an attacker to call the function with a callee address of their own contract and make state-changing sensitive actions to the proxy contract.
Attack Scenario
In the sample code mentioned above from Ethernaut’s Delegation, there are two contracts, “Delegate” and “Delegation.”
The Delegation contract makes a delegate call to the “delegate” contract’s address with the value of “msg.data”.
This is happening inside the fallback function on the Delegation contract. It means that any external user will be able to trigger the delegate call function by making a call to a non-existing function which will then, in turn, trigger the fallback function, executing the delegate call.
There are two cases in which a fallback function is executed in a contract:
- When someone sends ether to a contract, but there’s no receive() function, and a fallback() function exists.
- When the name of the called function does not match with any of the existing functions.
The “msg.data” can also be influenced by the caller while making a call. To exploit the above contract, the following code can be used by the attacker’s contract
address(delegation).call(abi.encodeWithSignature(“pwn()”));
This will lead to the execution of the fallback function with the function signature of “pwn()” passed inside “msg.data”. This will cause the delegation contract to make a call to the delegate contract and execute the pwn() function. The “msg.sender” will become the owner, and the level will be completed.
The Punk Protocol Hack — Case scenario
August 2021 was known for a hack that led to the loss of over $8.9 million in tokens. The hacker of the Punk Protocol Project exploited the access of smart contracts.
This was the case of a missing access control modifier on the initialize function on the CompoundModel code. This allowed the attacker to execute a delegatecall to insert their own contract address in the 1st forgeAddress in the initialize parameters. Later on, the function “withdrawToForge” was executed to withdraw all funds to the attacker’s contract.
Best Practices to Prevent Delegate Call Attacks and Ensure Smart Contract Security
Following are the ways through which Delegate call attacks can be monitored and prevented:
1. Be Vigilant While Making External Calls
Delegate calls to untrusted contracts can open a floodgate to risks and errors of many kinds. These may create unfamiliar codes that may affect the operations of the current contracts or any other contracts that rely on them. If there’s any improper access control or security misconfiguration over the function making the call or the address that is passed in the call can lead to a security issue.
2. Constant State After Delegate Call
Whether performing raw calls or delegate contract calls, assume that malicious codes are always there. This might hinder your control process leading to vulnerabilities. Solidity smart contract library uses a numeric address space. The first variable is stored at 0, next at 1, and further 2, and so on. This helps in identifying the same state variable in both contracts during the delegate call function.
3. Put Assert, Require, and Revert to Their Best Use
Assert and require are the two convenience functions of smart contract security. These can be used as exceptions when certain conditions are not met. For internal errors and invariants, the assert function is put to use. To comprehend and validate the return values from the primary contract to the target contract, the ‘require’ function should be used. With the help of these functions, no violation of codes occurs as they are formally verified.
4. Keep Track of Contract Activities through Events
If you want to secure your smart contracts from any hacks or errors, then keeping an eye on contract activities with the use of events is one way. The contract transactions can be recorded, but, unfortunately, message calls in Blockchain are not recorded. This means that only input events are visible, but the changes made to them are not. Here, events can help perform certain functions in the user interface.
Conclusion
Our cloud-based smart contract security scanner SolidityScan can automatically find vulnerabilities related to insecure delegate calls.

Delegate call is a technical process that needs a professional understanding of contract libraries and the transfer of codes while making calls. Signup for a free trial at https://solidityscan.com/signup