Stratax Contracts

First Flight #57
Beginner FriendlyDeFi
100 EXP
Submission Details
Impact: high
Likelihood: high

`_executeOpenOperation` passes incorrect `_asset` parameter to `_call1InchSwap`, causing wrong token balance to be used as `returnAmount` in the fallback path

Author Revealed upon completion

[H-1] _executeOpenOperation passes wrong token to _call1InchSwap, causing DoS or incorrect accounting

Description

In Stratax::_executeOpenOperation (L513-514), flashParams.borrowToken is passed as the second parameter to _call1InchSwap, but it should be _asset (the collateral token). This parameter is used in the fallback branch of _call1InchSwap (L625) to query the contract's token balance when the 1inch router returns no data:

// L513-514: borrowToken passed instead of collateralToken
uint256 returnAmount =
_call1InchSwap(flashParams.oneInchSwapData, flashParams.borrowToken, flashParams.minReturnAmount);
// L623-625: fallback queries wrong token balance
} else {
returnAmount = IERC20(_asset).balanceOf(address(this));
}

Since all borrowToken was already swapped away, the balance query returns ~0, causing require(returnAmount >= totalDebt) to fail.

Risk

When the 1inch swap function returns no data, createLeveragedPosition always reverts, making leveraged position creation impossible through those swap routes. If the contract holds pre-existing borrowToken, the stale balance could bypass checks, leading to incorrect flash loan repayment accounting.

Proof of Concept

function test_H1_wrongAssetCausesRevert() public {
// Setup: deploy Stratax with a mock 1inch router that swaps correctly but returns NO data
// Mock router does: pull WETH from caller, send USDC to recipient, return nothing
uint256 collateralAmount = 1000 * 1e6; // 1000 USDC
uint256 flashLoanAmount = 2000 * 1e6;
uint256 borrowAmount = 1 * 1e18; // 1 WETH
usdc.mint(ownerTrader, collateralAmount);
bytes memory swapData = abi.encodeWithSelector(
Mock1inchRouterNoReturn.swap.selector, address(weth), address(usdc), borrowAmount, address(stratax));
vm.startPrank(ownerTrader);
usdc.approve(address(stratax), collateralAmount);
// Reverts: fallback queries WETH balance (0) instead of USDC balance (swap output)
vm.expectRevert();
stratax.createLeveragedPosition(
address(usdc), flashLoanAmount, collateralAmount, address(weth), borrowAmount, swapData, flashLoanAmount);
vm.stopPrank();
}

Full runnable test: test/audit/H1_WrongAssetInSwap.t.sol

Recommended Mitigation

Pass the collateral token address instead of borrowToken:

uint256 returnAmount =
- _call1InchSwap(flashParams.oneInchSwapData, flashParams.borrowToken, flashParams.minReturnAmount);
+ _call1InchSwap(flashParams.oneInchSwapData, flashParams.collateralToken, flashParams.minReturnAmount);

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!