Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Brief / Intro
ZeroXSwapVerifier.verifySwapCalldata only checks the function selector, then applies incomplete parsing of action payloads. Crucially, it never validates the recipient or buy token for the swap. An attacker can craft calldata that passes verification but routes MYT (or underlying) to an arbitrary address, enabling direct theft of assets.
Vulnerability Details
The verifier (src/utils/ZeroXSwapVerifier.sol:99-143) accepts any target so long as the selector matches 0x’s settler. It does not check the actual settler address.
_verifyExecuteCalldata / _verifyExecuteMetaTxnCalldata ignore SlippageAndActions.recipient and buyToken (TODO comments in code) and many action decoders just slice the first 32/64 bytes of dynamic data (_extractTokenFromUniswapFills, _extractTokenAndAmountFromRFQ).
Because the parser trusts those slices, attackers can encode actions whose first word matches the expected token while the real calldata points to another asset/recipient. Verification returns true, but the actual 0x execution transfers funds elsewhere.
Impact Details
Impact: Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield (High severity)
A malicious strategy or external actor can submit forged calldata that the verifier approves, allowing them to drain tokens held in strategies guarded by this verifier.
The attacker can redirect proceeds of swaps to their address, emptying strategy balances.
Ensure Foundry is installed and dependencies are set.
Execute the dedicated tests:
test_poc_zeroXSwapVerifier_ignores_recipient demonstrates the verifier greenlights calldata pointing to an attacker-controlled recipient.
test_poc_zeroXSwapVerifier_drains_tokens connects the verifier to a mocked 0x settler execution path and shows the attacker’s balance increasing by the stolen amount.