Skip to main content
Sigvex

Unsafe Callback Remediation

How to make intentional callbacks safe with reentrancy guards, allowlists, and state finalized before the hook.

Unsafe Callback Remediation

Overview

Related Detector: Unsafe Callback

Callbacks — token-transfer hooks, flash-loan executeOperation, generic notifiers — hand control to an external address by design. Without guardrails, the callee can re-enter, revert strategically, or read half-updated state. Unlike accidental reentrancy, the call is intentional, so the fix is not to remove it but to make it safe: finalize state first, guard against reentry, and constrain who can be called back.

Before (Vulnerable)

function flashLoan(address receiver, uint256 amount) external {
    token.transfer(receiver, amount);
    // Callback runs while the loan is outstanding and state is mid-flight.
    IReceiver(receiver).executeOperation(amount);
    require(token.balanceOf(address(this)) >= reserve, "Not repaid");
}

After (Fixed — reentrancy guard, checks after the hook, effects first)

uint256 private _locked = 1;
modifier nonReentrant() {
    require(_locked == 1, "Reentrant");
    _locked = 2;
    _;
    _locked = 1;
}

function flashLoan(address receiver, uint256 amount) external nonReentrant {
    uint256 before = token.balanceOf(address(this));
    token.transfer(receiver, amount);
    IReceiver(receiver).executeOperation(amount);
    require(token.balanceOf(address(this)) >= before, "Not repaid");  // verify after callback
}

Where the set of valid callback targets is known, keep an allowlist and reject callbacks from anyone else. Never leave critical invariants unchecked across the hook.

Common Mistakes

  • Adding a reentrancy guard but reading a manipulated value (e.g. a pool price) during the callback window elsewhere in the system — see read-only reentrancy.
  • Trusting the callback’s return value as authorization instead of verifying the contract’s own invariants afterward.
  • Forwarding all gas to an untrusted callback, enabling grief via return bombs or deep call stacks.

References