defirisk.co
rubric v1.7.0

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.

Data & output #

Data source
Slither `arbitrary-send-eth` + `controlled-delegatecall` detectors + source review
Output format
Green / Yellow / Red
Evidence artifact
Slither output JSON + contract + function name if flagged
Confidence signal
green = no unfiltered user-controlled external call; yellow = external call with selector filter but no target allowlist; red = fully user-controlled call target and data; gray = source unverified

Scored protocols 0 carry this factor#

No protocols have been scored for this factor yet.

Linked hacks 2 historical incidents#

causalMakina Finance: Permissionless share price oracle update (updateTotalAum) + flash loan Curve pool manipulation → share price inflation → LP drain2026-01-20 · $4M · Permissionless share price oracle update (updateTotalAum) + flash loan Curve pool manipulation → share price inflation → LP drain · Arbitrary call with user-controlled args [via cross-hack: Factor 14: Public Permissionless Functions That Can Re-Trigger Vulnerable State]
relatedCompound Finance: Governance-introduced bug — updated Comptroller vault incorrectly distributed COMP rewards; any user could call `drip()` to refill the vulnerable vault from the Reservoir2021-09-29 · $147M · Governance-introduced bug — updated Comptroller vault incorrectly distributed COMP rewards; any user could call `drip()` to refill the vulnerable vault from the Reservoir · Arbitrary call with user-controlled args [via cross-hack: Factor 14: Public Permissionless Functions That Can Re-Trigger Vulnerable State]
rubric_version v1.7.0factor RD-F-013category 1carried 0critical no