Describe the normal behavior in one or more sentences
Explain the specific issue or problem in one or more sentences
At Stratax.sol:L514:
uint256 returnAmount =
_call1InchSwap(flashParams.oneInchSwapData, flashParams.borrowToken, flashParams.minReturnAmount);
The swap performed here is borrowToken -> collateralToken (i.e., the borrowed tokens from Aave are swapped back to the collateral token to repay the flash loan). The _asset parameter in _call1InchSwap is used in the fallback balance-check path when the 1inch router does not return data (L620-626):
After the swap completes:
borrowToken balance = 0 (all input tokens were consumed by the swap)
collateralToken balance = swap output amount (the tokens received)
Because L514 passes borrowToken as _asset, the fallback path at L625 reads borrowToken.balanceOf(address(this)) = 0, causing returnAmount to be 0. The subsequent require(returnAmount >= _minReturnAmount) at L628 fails, reverting the entire transaction.
Contrast with _executeUnwindOperation (L584), which correctly passes _asset (the flash loan token = the swap output token):
In the unwind case, the swap is collateralToken -> _asset, so _asset is indeed the output token, and the balance check works correctly.
Likelihood:
The vulnerability triggers specifically when the 1inch router implementation does not return data from its swap function
The 1inch aggregation router has multiple versions and aggregator contracts across chains; some implementations return (uint256 returnAmount, uint256 spentAmount) while others are void functions
The protocol explicitly handles this case (the else branch at L623-625 exists precisely for routers that return no data), confirming this is an expected scenario
Impact:
createLeveragedPosition() becomes permanently non-functional when paired with a no-return-data router, as every call to _executeOpenOperation will revert
Users cannot open new leveraged positions, which is the primary purpose of the protocol
Existing positions can still be unwound (L584 is correct), so funds are not permanently locked
The issue is a complete DoS of the position-creation functionality, not a fund loss
The PoC replicates the _call1InchSwap logic in an external SwapHandler contract and uses a MockNoReturnRouter (void swap function that returns no data). Two tests demonstrate:
test_buggy_passesInputToken_reverts: Passes the input token (borrowToken) as _asset -- the balance check reads 0, causing revert
test_fixed_passesOutputToken_succeeds: Passes the output token (collateralToken) as _asset -- the balance check reads the correct swap output, succeeding
Pass _asset (the flash loan token = collateral token = swap output) instead of flashParams.borrowToken at L514:
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.