Arbitrary call 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 makes a low-level .call() to a user-supplied target address with user-supplied calldata, where no allowlist of permitted targets or selector-filter is applied. Static analysis examines the bytecode for CALL opcodes where the target or data is derived from external input without validation. This differs from RD-F-012 in that it covers arbitrary external calls (not delegatecalls) with user-controlled destinations.
**Why it matters** An arbitrary call with user-controlled args and target creates a universal relay for any on-chain action: an attacker can supply a target of any contract and calldata encoding any function, using the protocol itself as the caller. This pattern has been exploited in aggregators and routers, where the protocol is trusted by external contracts and an attacker uses it to forward privileged calls. Compound's drip() vulnerability ($147M at risk, 2021) involved a public permissionless function that could refill the vulnerable Comptroller state; Makina Finance ($4.13M, 2026) fell to a permissionless updateTotalAum() call that used manipulable Curve pool state as input.
**Green / Yellow / Red** Green: no .call() with user-supplied target is present, or all external calls use hardcoded targets and selector-filtered calldata. Yellow: arbitrary external calls exist but are gated by a whitelist that is protected by governance or multisig with a timelock. Red: any contract accepts user-supplied target and calldata and forwards them as an external call without an on-chain allowlist.
**Common gray cases** This factor is gray for protocols that do not include aggregation, routing, or meta-transaction functionality -- the pattern is specific to contract architectures that intentionally relay arbitrary calls.
**Notable historical examples** - **Compound Finance** ($147M, 2021): Permissionless drip() function could be called by any address to refill the vulnerable Comptroller. - **Makina Finance** ($4.13M, 2026): Permissionless updateTotalAum() used manipulable Curve pool state; arbitrary state-refill pattern.
Measurement what to look for #
Determine whether any contract performs `.call(target, data)` where target and/or data is user-supplied without a target allowlist or selector filter.