58079 sc low missing from validation in zeroxswapverifier verifyswapcalldata enables direct theft of approved funds
Submitted on Oct 30th 2025 at 13:33:25 UTC by @Novathemachine for Audit Comp | Alchemix V3
Report ID: #58079
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/utils/ZeroXSwapVerifier.sol
Impacts:
Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Brief/Intro
ZeroXSwapVerifier approves malicious 0x routes because _verifyTransferFrom() never checks that the from address equals the owner. Once verified, a route can call transferFrom(owner, attacker, amount) and drain the owner’s approved tokens.
Vulnerability Details
Where: src/utils/ZeroXSwapVerifier.sol ,
_verifyTransferFrom(bytes action, address owner, address targetToken, uint256 targetAmount).What happens: The function decodes
(token, from, to, amount)but only enforcestoken == targetToken. It ignoresfromandto.(address token, , , uint256 amount) = abi.decode( _slice(action, 4), (address, address, address, uint256) ); require(token == targetToken, "IT");Why it’s bad: Any
transferFromembedded in a 0x route that pulls from the victim will pass verification as long as the token matches. With an existing allowance to the 0x spender, funds move directly to an attacker-controlled address.
Impact Details
Impact chosen: Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield.
Any user who approved the 0x spender can lose their entire approved balance in a single verified route. No market or timing constraints limit the loss.
References
Vulnerable code: src/utils/ZeroXSwapVerifier.sol (
_verifyTransferFrom()).
Proof of Concept
Proof of Concept
Add this test to src/test/ZeroXSwapVerifier.t.sol:
Run the test:
Expected result:
verifySwapCalldata()returns true, proving the malicious route is accepted.transferFrom(owner, attacker, amountToSteal)succeeds, and balances reflect the theft.
Was this helpful?