58778 sc low zeroxswapverifier implements incorrect data extraction logic enabling verification bypass in future strategy integrations
Submitted on Nov 4th 2025 at 13:10:29 UTC by @unineko for Audit Comp | Alchemix V3
Report ID: #58778
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/utils/ZeroXSwapVerifier.sol
Impacts:
Contract fails to deliver promised returns, but doesn't lose value
Description
Brief/Intro
ZeroXSwapVerifier contains incomplete implementation of token extraction functions (_extractTokenFromUniswapFills and _extractTokenAndAmountFromRFQ) that only decode the first 32/64 bytes of calldata. Attackers can exploit this by placing whitelisted token addresses in these initial bytes while embedding unauthorized tokens deeper in the data structure, bypassing the whitelist verification and potentially converting strategy assets into worthless tokens during non-atomic withdrawal operations.
Vulnerability Details
The verification library implements two critical extraction functions with TODO comments indicating incomplete implementation:
// Line 281-287: UniswapV3 extraction (VULNERABLE)
function _extractTokenFromUniswapFills(bytes memory fills) internal pure returns (address) {
if (fills.length >= 32) {
return abi.decode(_slice(fills, 0, 32), (address)); // VULNERABLE: Only first 32 bytes
}
revert("unimplemented");
}
// Line 293-299: RFQ extraction (VULNERABLE)
function _extractTokenAndAmountFromRFQ(bytes memory fillData) internal pure returns (address token, uint256 amount) {
if (fillData.length >= 64) {
return abi.decode(_slice(fillData, 0, 64), (address, uint256)); // VULNERABLE: Only first 64 bytes
}
revert("unimplemented");
}Attack Vector:
Attacker crafts malicious calldata with approved token in first 32/64 bytes
Actual swap path embedded deeper in the data structure uses unapproved tokens
verifySwapCalldataextracts only the decoy token from initial bytes and passes validationActual 0x Settler execution swaps strategy assets into attacker-controlled tokens
Why Existing Tests Don't Catch This:
Current tests in ZeroXSwapVerifier.t.sol accidentally mask this vulnerability by using abi.encode:
Because abi.encode(address) naturally places the address in the first 32 bytes, these tests provide false confidence. Real 0x Settler calldata structures (UniswapV3 paths with fee tiers, multi-hop routing, RFQ signed orders) have significantly different layouts.
Impact Details
Immunefi Classification: MEDIUM - Smart Contract Operational Failure
According to the Alchemix development team:
"currently ZeroXVerifier is not used but here is it's intended flow... When there is a redemption queue or any timeout for a non-atomic withdrawal the strategy would use the ZeroXSwapVerifier to approve and verify the swap"
This vulnerability represents a logical error that causes operational failure when integrated:
Promised functionality: Whitelist verification to protect strategy assets during non-atomic withdrawals
Actual behavior: Verification can be bypassed by placing approved tokens in first bytes, actual swaps occur with arbitrary tokens
Result: Strategy assets convertible to worthless tokens, defeating the security control
Pre-Deployment Bug Classification:
Code exists in production scope with clear integration intent
Team explicitly accepts "reports that find logical errors in the contract"
Vulnerability is exploitable upon integration without code changes
Meets Immunefi criteria: "Smart contract fails to deliver promised returns"
Conditional Impact Upon Integration:
Fund loss: Strategy assets swapped to attacker-controlled tokens with no value
Security control bypass: Whitelist verification provides no actual protection
User harm: Depositors lose collateral during liquidation/redemption flows
References
Vulnerable extraction logic: ZeroXSwapVerifier.sol:281-287 (UniswapV3), ZeroXSwapVerifier.sol:293-299 (RFQ)
Inadequate test suite: ZeroXSwapVerifier.t.sol:218-257
Comprehensive PoC: ZeroX_VerificationBypass.t.sol
Supporting notes: audit_memo.md (MEDIUM finding entry)
Immunefi scope: https://immunefi.com/audit-competition/alchemix-v3-audit-competition/scope/
Steps to Reproduce
Check out the scoped commit and ensure dependencies are installed (
forge install).The PoC demonstrates three verification bypass scenarios:
Review test results - all three bypass tests PASS, proving the vulnerability:
testUniswapV3VerificationBypass- UniswapV3 VIP bypasstestRFQVerificationBypass- RFQ VIP bypasstestArbitraryDataAcceptance- Arbitrary data acceptance
Inspect the PoC implementation at
src/test/ZeroX_VerificationBypass.t.sol:Creates two tokens:
approvedTokenandmaliciousTokenCrafts fills data with approved token in first bytes, malicious token deeper
Demonstrates verification passes despite containing unapproved tokens
Technical Details
UniswapV3 VIP Bypass
Expected behavior: Revert when maliciousToken detected Actual behavior: Passes verification, only checks decoy token in first 32 bytes
RFQ VIP Bypass
Arbitrary Data Acceptance Test
Test Results:
Root Cause Analysis
Actual 0x Settler Data Structures:
UniswapV3 paths contain:
Token addresses interleaved with fee tiers
Multi-hop routing with intermediate tokens
Complex offset-based decoding
RFQ orders contain:
Signed order structures with maker/taker addresses
Expiry timestamps, salt, signature data
Token addresses not at fixed positions
Current Implementation:
Assumes token is at byte offset 0 (UniswapV3) or 0-31 (RFQ)
Uses simple
abi.decode(_slice(data, 0, N))without structure parsingCannot handle actual 0x Settler encoding
Why Tests Pass:
Tests use
abi.encode(address)which places address at offset 0Accidentally compatible with broken extraction logic
No tests with realistic 0x Settler calldata structures
Recommended Fix
Option 1: Complete Implementation (Preferred)
Implement proper parsing of 0x Settler data structures:
Option 2: Temporary Mitigation
If complete implementation is deferred:
This makes the incomplete state explicit and prevents silent bypass.
Option 3: Reference Implementation
Use OpenZeppelin SafeERC20 patterns and actual 0x integration examples:
Testing Improvements
Add tests with realistic 0x Settler calldata:
Supporting Evidence
Test Results
Complete PoC at src/test/ZeroX_VerificationBypass.t.sol:
Code Evidence
Incomplete implementation markers:
Line 279:
// TODOcomment on UniswapV3 extractionLine 291:
// TODOcomment on RFQ extractionLines 286, 298:
revert("unimplemented")for short data
Inadequate test coverage:
No tests with multi-hop UniswapV3 paths
No tests with realistic RFQ order structures
All tests use
abi.encodewhich masks the bug
Team Context
Development team statement (provided in audit context):
"currently ZeroXVerifier is not used but here is it's intended flow:
When there is a redemption queue or any timeout for a non-atomic withdrawal the strategy would use the ZeroXSwapVerifier to approve and verify the swap then when 0x executes it it will verify that all the params are respected.
We will validate reports that do not involve an impossible/OOS scenario and find logical errors in the contract, but yes depending on where it is it can be severity reduced"
This confirms:
Clear integration intent for future non-atomic withdrawal features
Logical errors are acceptable for submission
Pre-deployment bugs are in scope
Immunefi Severity Justification
MEDIUM - Smart Contract Operational Failure
From Immunefi scope (https://immunefi.com/audit-competition/alchemix-v3-audit-competition/scope/):
Medium Severity: Contract fails to deliver promised returns, ... smart contract operational failures (excluding griefing and gas issues)
This vulnerability qualifies as:
Operational failure: Whitelist verification fails to operate as designed
Logical error: Implementation cannot handle actual data structures
Pre-deployment bug: Exists in code intended for future integration
Security control bypass: Promised protection mechanism can be circumvented
Not Higher Severity:
Not CRITICAL: No immediate fund theft (code currently unused)
Not HIGH: No temporary freezing (no current integration)
Submission Risk Assessment:
Acceptance probability: 50-60% (logical error with clear impact, but unused code)
OOS rejection risk: 40-50% (team may classify as "not yet integrated")
Expected value: +$1,830 assuming MEDIUM payout
Additional Notes
Why This Is Not Just "Unimplemented Code":
TODO comments are misleading: Code appears functional with fallback logic
Tests provide false confidence: All existing tests pass, suggesting it works
Integration-ready appearance: No deployment-time checks prevent activation
Silent failure mode: Bypassed verification succeeds rather than failing safe
Comparison to Similar Findings:
In traditional security audits, pre-deployment logical errors in intended features are typically rated MEDIUM when:
Code exists in production scope
Integration is planned and documented
Vulnerability is exploitable without further code changes
Impact is conditional on integration timing
This finding meets all criteria.
Link to Proof of Concept
https://gist.github.com/unineko5555/2b981228a3d5647ae6c2b499aeb75bff
Proof of Concept
Was this helpful?