57516 sc low arbitrary external call in zeroxswapverifier leads to theft of unclaimed yield
Submitted on Oct 26th 2025 at 21:33:36 UTC by @dray for Audit Comp | Alchemix V3
Report ID: #57516
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/utils/ZeroXSwapVerifier.sol
Impacts:
Theft of unclaimed yield
Description
Brief/Intro
The ZeroXSwapVerifier.verifySwapCalldata() function fails to validate the from address in TRANSFER_FROM actions within 0x protocol swaps. An attacker can exploit this by crafting a malicious 0x swap payload that includes a transferFrom(strategy, attacker, amount) action, draining all yield tokens approved to the 0x Settler. Since strategies (like the Transmuter) pre-approve the 0x Settler with unlimited allowance, the attacker can steal all tokens held by the strategy contract through a legitimate-looking swap operation.
Vulnerability Details
Root Cause The ZeroXSwapVerifier.sol validates individual actions within 0x protocol swaps, but the _verifyTransferFrom() function fails to check that tokens are being transferred from the user, not from the contract itself:
function _verifyTransferFrom(bytes memory action, address owner, address targetToken, uint256 targetAmount) internal view {
(address token, , , uint256 amount) = abi.decode(
_sliceSkipSelector(action),
(address, address, address, uint256)
);
require(token == targetToken, "Token mismatch");
// ❌ MISSING: Validation that 'from' address is 'owner', not the contract!
// The decoded parameters are: (token, from, to, amount)
// But we never check that 'from == owner'
}
The full signature of the TRANSFER_FROM action (selector 0x8d68a156) is:
The verifier decodes all four parameters but only validates the token parameter. It never checks that from == owner, allowing an attacker to set from to the strategy contract address.
The verifier has several checks, but none prevent this exploit:
Settler validation: Only checks that the target is the legitimate 0x Settler contract Action type validation: TRANSFER_FROM (0x8d68a156) is a valid 0x action type Token validation: The verifier checks token == targetToken, which passes Amount validation: Not enforced for TRANSFER_FROM actions From address validation: COMPLETELY MISSING
Impact Details
Direct Financial Loss Total funds at risk: All tokens approved to the 0x Settler by any strategy contract.
Affected scenarios: Transmuter: All MYT (yield tokens) held in the Transmuter when used with ZeroXSwapVerifier Any strategy: Any ERC20 tokens that strategies approve to the 0x Settler for swap operations Multi-token exposure: If strategies approve multiple tokens, all are at risk
References
Vulnerable contract: ZeroXSwapVerifier.sol (lines 238-249, _verifyTransferFrom function)
Proof of Concept
Proof of Concept
Was this helpful?