The contract verifies that all borrowed tokens are used in the swap by comparing the borrow token balance before the borrow to the balance after the swap. The invariant is: afterSwapBorrowTokenbalance == prevBorrowTokenBalance, which assumes the contract holds no borrow tokens before the borrow.
When the flash loan asset (collateral token) equals the borrow token, the contract already holds borrow tokens before the borrow—from the flash loan and user collateral. After the swap (borrow token → collateral, same token), the contract receives borrow tokens back. The final balance will exceed prevBorrowTokenBalance, causing the check to revert even when the operation is valid.
Likelihood (low):
createLeveragedPosition accepts _flashLoanToken and _borrowToken as separate parameters with no validation that they differ.
An owner or integrator can call with _flashLoanToken == _borrowToken (e.g., flash loan USDC and borrow USDC against USDC collateral).
The protocol may expand to support same-token leverage strategies where collateral and borrow token are identical.
Impact (low):
Valid operations revert with "Borrow token left in contract" when collateral token equals borrow token.
DoS for users attempting same-token leverage positions.
Confusing failure mode: the revert suggests leftover tokens when the real cause is the check's incorrect assumption.
Option A: Explicitly disallow collateral == borrow token at entry point:
Option B: Make the balance check conditional when tokens differ, or use a different invariant (e.g., require leftover borrow tokens ≤ prevBorrowTokenBalance when same-token flows are supported):
Severity: Low
Location: src/Stratax.sol:499-519
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.