delegatecall with user-controlled target
A code & audits factor in the v1.7.0 rubric. Measured per protocol on a s cadence.
Methodology how we score #
**What this measures** This factor detects whether any contract in the protocol uses delegatecall where the target address is or can be supplied by an external user without an on-chain allowlist restricting the permissible targets. The assessment is performed by static analysis of the deployed bytecode, specifically looking for DELEGATECALL opcodes preceded by a user-controlled CALLDATALOAD or derived from external input without allowlist enforcement.
**Why it matters** Delegatecall executes external code in the calling contract's storage context. A user-controlled delegatecall target allows an attacker to inject arbitrary logic that reads and writes the calling contract's storage, including modifying ownership, draining funds, or redirecting upgrade authority. Furucombo ($14M, 2021) lost funds when an attacker added Aave's lending pool as a handler in the combo registry, then used a delegatecall to the lending pool's initialize() function to claim ownership of Furucombo and approve fund transfers. The Raft exploit ($3.3M, 2023) involved a similar pattern where delegatecall reached an uninitialized storage slot. This vulnerability class is among the most consistently exploitable in proxy-heavy architectures.
**Green / Yellow / Red** Green: all delegatecall usage is to fixed, hardcoded addresses or to addresses validated against an on-chain allowlist enforced by a multisig or governance process. Yellow: delegatecall targets are restricted by a registry, but the registry itself is modifiable by a single admin key without a timelock. Red: delegatecall target can be supplied directly by an external caller with no on-chain allowlist check.
**Common gray cases** This factor is gray when the protocol's architecture does not use delegatecall at all -- common in simple non-upgradeable protocols. It cannot be assessed when source is unverified.
**Notable historical examples** - **Furucombo** ($14M, 2021): Handler registry allowed attacker-controlled delegatecall target; Aave lending pool initialize() claimed ownership. - **Raft** ($3.3M, 2023): Delegatecall to uninitialized storage slot caused attacker's profit to route to burn address; protocol sunsetted.
Measurement what to look for #
Determine whether any contract uses `delegatecall` where the target address is or can be user-supplied without an on-chain allowlist.