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 V3arrow-up-right

  • 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?