_call1InchSwap Trusts Return Data Without Balance VerificationThe _call1InchSwap function executes a low-level call to the 1inch router using arbitrary calldata provided by the owner. It determines the swap output amount by decoding the return data from the external call, rather than measuring the actual token balance change in the contract.
Two issues compound here:
returnAmount is trusted from external return data without independent verification
_swapParams is raw calldata that can invoke any function on the 1inch router, not just swap() — there is no function selector validation
Likelihood:
The 1inch router is trusted infrastructure and should return accurate values under normal operation
However, calling arbitrary functions on the router via raw calldata introduces an unpredictable surface area
If the router is upgraded or a non-swap function is called, the return data format may not match the expected (uint256, uint256) decoding
Impact:
The returnAmount value flows into surplus calculations at lines 529-531 (_executeOpenOperation) and 592-594 (_executeUnwindOperation)
If returnAmount is higher than actual tokens received: aavePool.supply() will be called with more tokens than the contract holds, causing a revert
If returnAmount is lower than actual tokens received: surplus tokens are not supplied to Aave, potentially leaving dust in the contract
Mitigating factor: Flash loan atomicity provides a strong backstop — if the contract can't repay the flash loan, the entire transaction reverts, preventing fund loss
How the issue manifests:
Owner crafts _oneInchSwapData that calls a non-standard function on the 1inch router
The function succeeds but returns data in a different format than (uint256, uint256)
abi.decode(result, (uint256, uint256)) produces an incorrect returnAmount (could be garbage or zero)
If the decoded value is very high, the surplus calculation returnAmount - totalDebt overestimates, and aavePool.supply() reverts due to insufficient balance
The entire flash loan transaction reverts — no fund loss but the operation fails unexpectedly
Expected outcome: The operation reverts with an opaque Aave error rather than the expected "Insufficient return amount from swap" message, making debugging difficult.
The root cause is that the function relies on external return data for a critical accounting value instead of independently measuring the actual token balance change. The fix should use a before/after balance measurement pattern.
Primary fix — Measure actual balance change:
Why this works:
The balance change is measured independently from the external call's return data — it reflects actual tokens received regardless of what the router returns
Eliminates the dependency on the return data format, making the function resilient to router upgrades or non-standard function calls
The balanceOf calls add ~2,600 gas each (warm SLOAD) — negligible compared to the swap gas cost
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.