Skip to main content
Sigvex

Remediating Token Hook Reentrancy

How to prevent reentrancy through ERC-777, ERC-1155, and ERC-4626 callback hooks using the CEI pattern and reentrancy guards.

Remediating Token Hook Reentrancy

Overview

Related Detector: Token Hook Reentrancy

Token standards with mandatory callbacks (ERC-777, ERC-1155, ERC-4626 with ERC-777 underlying) require the same Checks-Effects-Interactions discipline as ETH transfers. Apply ReentrancyGuard to all functions that interact with hook-enabled tokens.

Before (Vulnerable)

function withdraw(uint256 amount) external {
    require(balances[msg.sender] >= amount);
    erc777Token.send(msg.sender, amount, ""); // Callback fires here
    balances[msg.sender] -= amount;            // Too late
}

After (Fixed)

function withdraw(uint256 amount) external nonReentrant {
    require(balances[msg.sender] >= amount);
    balances[msg.sender] -= amount;            // State update first
    erc777Token.send(msg.sender, amount, ""); // Callback fires after
}

Alternative Mitigations

  • Avoid hook-enabled tokens: Use standard ERC-20 transfer instead of ERC-777 send when hooks are not needed.
  • Pull pattern: Let users withdraw (pull) rather than pushing tokens to them.

Common Mistakes

  • Only guarding the obvious function: Token hooks can trigger reentrancy into any public function, not just the one performing the transfer. Guard all state-modifying functions.

References