The executeOperation function is the Aave V3 flash loan callback that handles both position opening and unwinding. During execution, it performs multiple external calls: token approvals, Aave supply/borrow/repay/withdraw, and a 1inch swap via low-level .call(). The Checks-Effects-Interactions (CEI) pattern requires that all state changes and checks happen before external interactions.
The function has no nonReentrant modifier or reentrancy guard. The 1inch swap executed via _call1InchSwap performs a low-level .call() to an external contract, which can execute arbitrary code. If a malicious token or a token with transfer hooks (e.g., ERC-777 tokens) is involved, the swap callback could re-enter the Stratax contract mid-operation before the flash loan repayment is finalized.
Likelihood:
The owner selects which tokens are used for positions. When the collateral or borrow token is an ERC-777 token or any token with hooks (such as tokensReceived or tokensToSend), an external contract receives a callback during token transfers inside the flash loan callback execution.
The 1inch router .call() also provides an external execution context where arbitrary code can run before the flash loan repayment check completes.
Impact:
A re-entrant call could manipulate Aave position state mid-operation (e.g., calling unwindPosition during an _executeOpenOperation to extract collateral before the position is finalized).
Double-supply or double-borrow scenarios could leave the contract in an inconsistent state relative to its Aave positions.
The attack path below traces how an ERC-777 token used as the borrowToken triggers a tokensReceived hook during the aavePool.borrow() call inside _executeOpenOperation. Because executeOperation has no nonReentrant guard, the hook can re-enter Stratax (e.g., calling unwindPosition) before the open operation's state changes are finalized.
Inherit OpenZeppelin's ReentrancyGuardUpgradeable and apply the nonReentrant modifier to executeOperation. Since Stratax uses the Initializable proxy pattern, the upgradeable variant must be used and its __ReentrancyGuard_init() called during initialize.
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.