The _call1InchSwap() helper function accepts an _asset parameter documented in its NatSpec as the "Address of the asset being swapped to." It has two paths for determining the return amount: a primary path that decodes the router's return data, and a fallback path that reads IERC20(_asset).balanceOf(address(this)) when no return data is available.
In _executeOpenOperation(), the swap direction is borrow token to collateral token (the flash-loaned asset _asset). However, on Stratax.sol on line 514, the function passes flashParams.borrowToken (the source token) instead of _asset (the destination token):
When the 1inch router returns no data, the fallback path in _call1InchSwap() reads the wrong token balance:
After the swap consumes the borrowed tokens, the borrow token balance returns to prevBorrowTokenBalance, which is typically zero. This causes returnAmount to be set to zero (or to a residual borrow token balance from prior operations), rather than the actual collateral tokens received from the swap. The subsequent check on Stratax.sol on line 522 (require(returnAmount >= totalDebt)) then compares this borrow-token-denominated value against a collateral-token-denominated flash loan debt, a cross-denomination comparison that produces meaningless results.
By contrast, _executeUnwindOperation() correctly passes _asset (the flash-loaned debt token, which is the destination of the collateral-to-debt swap) on Stratax.sol on line 584:
This inconsistency between the two call sites confirms the bug in _executeOpenOperation().
This issue has a medium impact as incorrect accounting in the fallback path leads to cross-denomination comparisons in slippage protection and flash loan repayment checks. In the most common fallback scenario (no pre-existing borrow tokens), the operation reverts with a misleading error message. In the less common scenario where the contract holds residual borrow tokens, the checks could pass with meaningless values before failing at a later step. Aave's flash loan enforcement mechanism prevents direct fund loss, as the transaction would ultimately revert if insufficient collateral tokens are available for repayment.
This issue has a low likelihood as the fallback path is only triggered when the 1inch router returns no data, which is uncommon with the standard 1inch aggregation router's swap() function. However, since the code uses a raw .call() with arbitrary calldata on Stratax.sol on line 617, non-standard router functions or proxy configurations could trigger this path.
Pass the correct destination token address (_asset, the flash loan collateral token) to _call1InchSwap() in _executeOpenOperation() by changing flashParams.borrowToken to _asset on Stratax.sol on line 514. This ensures the fallback balance check reads the collateral token balance, maintaining correct denomination throughout all downstream accounting checks.
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.