_call1InchSwap issues a raw low-level .call() against oneInchRouter using entirely user-supplied bytes, including the function selector. No field in the calldata is validated: not the source token, destination token, function selector, or dstReceiver address.
Before the call, the contract approves the router for the full borrow amount. By crafting calldata where the 1inch SwapDescription.dstReceiver points to an attacker-controlled address, all swap proceeds can be routed away from address(this), draining the flash-loaned collateral.
Likelihood:
A compromised or phished owner key is sufficient to execute this — the protocol relies entirely on the owner acting correctly with no on-chain constraint on swap destinations
When ownership becomes transferable via the planned ERC-721 model, any token holder can exploit this path
Impact:
All Aave-borrowed tokens approved to the router can be routed to an arbitrary address in a single transaction
The balance-read fallback (IERC20(_asset).balanceOf) reads total contract balance rather than swap delta, which can produce an inflated returnAmount that passes the minReturnAmount check even when actual swap output went elsewhere
The 1inch AggregationRouterV5.swap() function accepts a SwapDescription struct that includes a dstReceiver field. A caller can set this field to any address. The Stratax contract never decodes or validates this struct before the call.
The core issue is that _call1InchSwap trusts the router's return value and the contract's existing balance rather than computing actual swap output as balanceAfter - balanceBefore.
Replace the raw .call() with a balance-delta pattern and validate the swap description on-chain in _call1InchSwap:
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.