👮
Contract Cops
  • Mastering Ethereum Book
    • What is ethereum?
    • Tokens
    • Oracles
    • Decenralized Applications(DApps)
    • The Ethereum virtual machine
    • Ethereum basics
    • Ethereum clients
    • Cryptography
    • Wallets
    • Transactions
    • Chapter 7 - Smart Contracts & Solidity
    • Side Notes
      • Tokens
      • Smart Contracts and Solidity
  • Cryptography
    • Ethereum Cryptography - Cheatsheet
    • Assymetric vs symmetric cryptography
    • ECDSA vs RSA
    • Elliptic curves and ECDSA
    • Sha-256 Example
    • Sha-256
    • What are the different steps in SHA-256?
  • Ethereum Blocks
    • Block Headers
  • Learning Solidity
    • Storage vs memory
    • Upgradeable contracts
      • Proxy pattern in smart contracts
  • PoS
    • Proof of stake
  • PoW
    • PoW
  • Tokens
    • ERC-1155
    • ERC20
  • Cryptonomics
    • Automated market makers
    • Collateral Tokens
    • Collateralized Stablecoin
    • Fiat currency
    • Liquidity pool
    • Open Position: Meaning and Risk in Trading
    • Slippage
    • Spot price
  • Common Attack Vectors
    • Checking access control
    • Access control issues on critical functions
    • Account Existence Check for low level calls
    • Account Existence Check
    • Common attacks with contract/EOA addresses
    • Arithmetic under/overflow
    • Assert Attack
    • Assert require revert
    • Assert Violation
    • Bad Interface DOS
    • Bad pragma and compiler
    • Block Timestamp Manipulation
    • Bypassing contract check
    • Code With No Effects
    • Code size check vulnerability
    • Constructors with Care
    • Default Visibilities
    • Delegatecall
    • Delegatecall
    • Denial of Service (DoS)
    • DoS with block gas limit
    • Entropy Illusion
    • External contract referencing
    • Flash Loan Attack
    • Floating Point and Precision
    • Function selector abuse
    • Function selector abuse
    • Smart contract gas griefing
    • Hash collision parameters
    • Hash Collisions With Multiple Variable Length Arguments
    • Imprecise arithmetic
    • Improper Array Deletion
    • Incorrect array deletion
    • Incorrect interface
    • Insufficient Gas Griefing
    • Loop through long arrays
    • Message call with hardcoded gas amount
    • Not enough gas for ether transfer
    • Precision Loss in Calculations
    • Oracle Manipulation
    • Public Burn Function
    • Read-only reentrancy
    • Race Conditions/Front Running
    • Reentrancy Attacks
    • Reentrancy
    • Requirement Violation
    • Right-To-Left-Override control character (U+202E)
    • Shadowing State Variables
    • Short Address / Parameter attack
    • Signature Malleability
    • Signature Replay
    • Transaction Order Dependence
    • Tx.Origin Authentication
    • Unchecked CALL Return Values
    • Unexpected ether
    • Uninitialized Storage Pointers
    • Unsafe Ownership Transfer
  • EIP's
    • EIP155
    • EIP55
  • PoW
    • Ethash
    • Scrypt - RFC 7914
  • Questions for self evaluation
    • Questions 23/04/2023 (Nr: 84)
    • Usability guide for questions
  • Frequently asked questions
    • What is the difference between transaction and message?
    • What is the use of a interface or function without implementation?
  • UsefulResources
Powered by GitBook
On this page
  • Storing variables in the EVM is important
  • Delegatecall preventative techniquesIn order to avoid any security issues, delegatecall should always be used with care.Some things to always be on the lookout for:Always remember that delegatecall preserves context. This is really important, as any sent ether/gas/logic to do with the msg.sender can be affected. It is preserved to the delegated transaction to the last contract.Always keep state variables structured the same way as in the contract that you are delegatecalling to. This is especially dangerous, as it can be easily exploited.Solidity introduces a library keyword that is specifically designed to create libraries to delegatecall to. The reason behind their security is that a library is stateless. This means that it can't change the state (doesn't have state itself), can't call functions from itself.
  1. Common Attack Vectors

Delegatecall

PreviousDefault VisibilitiesNextDelegatecall

Last updated 2 years ago

Delegatecall and call are two ways to do external message calls to contracts

Delegatecall and call function almost identically, but delegatecall preserves the context of the caller.

Let's see the difference between them, firstly below is call diagram:

Alt text

And here is a delegatecall diagram:

When we delegatecall to Target contract, the context is on Caller contract, all state change logics reflect on Caller’s storage.

In a nutshell, EOA that calls contract_a, which in hand calls contract_b with delegate call is basically like saying:

contract_a is allowing contract_b to change its state variables. Furthermore, when the delegatecall reaches contract_b, the msg.sender and origin is the EOA (preserved context).

From this, we can derive two important notes:

  1. Delegatecall preserves context

  2. Storage layout must be the same in order to properly use delegatecall

Delegatecall is usually used within the context of libraries to modularize code. When used incorrectly, it opens up a large security issue.

Storing variables in the EVM is important

How EVM saves field variables to Storage? In Ethereum, there are two kinds of space for saving the contract’s field variables. One is “memory” and the other is “storage”.

For example if we have:

contract Test {
        uint256 first; //slot 0
        uint256 second; //slot 1
    }
The EVM has 2²⁵⁶ slot in Smart Contract storage and each slot can save 32-byte size data.

But why is that important?

In the case of delegatecall, the target contract accesses the same storage slots as the calling contract. And again, the order of the slots is defined by the order of the variables.

But what if we change the order so that it doesn’t align with the calling contract anymore?

Let's see the above with an example:

We have contracts HackMe and Lib:

As we discussed above, the order of variables matters when using delegatecall and in Lib this is not respected.

If doSomething in Lib is executed with the context of HackMe the first variable

address public lib

will now be changed instead of someNumber Here is in detail what is going to happen:

  1. lib.delegatecall(doSomething) is invoked

  2. Due to the invokation of doSomething in contract Lib, now address public lib is changed

  3. An attacker that is having the same variable structure is calling his changeOwner function in his Attack contract

  4. This leads again to lib.delegatecall(doSomething) in HackMe which leads to doSomething in contract Lib

  5. Now the address public lib in HackMe is changed to the address of the attacker(casted in number).

  6. Immediately after that when initiate the next line of the changeOwner function, the function doSomething is invoked but this time this is the doSomething function of the Attack contract

  7. Attack contract is now the owner

Let's see the full Attack contract:

Delegatecall preventative techniquesIn order to avoid any security issues, delegatecall should always be used with care.Some things to always be on the lookout for:Always remember that delegatecall preserves context. This is really important, as any sent ether/gas/logic to do with the msg.sender can be affected. It is preserved to the delegated transaction to the last contract.Always keep state variables structured the same way as in the contract that you are delegatecalling to. This is especially dangerous, as it can be easily exploited.Solidity introduces a library keyword that is specifically designed to create libraries to delegatecall to. The reason behind their security is that a library is stateless. This means that it can't change the state (doesn't have state itself), can't call functions from itself.

Alt text
Alt text
Alt text
Delegatecall_slots_attack
Attack_contract_delegatecall