Summary
When depositing into the leverager, if the borrowed token is not token0 or token1, the function has to perform an exactOutput swap, to receive the borrowed token0/token1.
function openLeveragedPosition(LeverageParams calldata lp) external nonReentrant returns (uint256 _id) {
...
{
// we first borrow the maximum amount the user is willing to borrow. Any unused within the swaps is later repaid.
ILendingPool(lendingPool).borrow(lp.denomination, lp.maxBorrowAmount);
IMainnetRouter.ExactOutputParams memory swapParams;
if (a0 > lp.amount0In && up.token0 != lp.denomination) {
swapParams = abi.decode(lp.swapParams1, (IMainnetRouter.ExactOutputParams));
address tokenIn = _getTokenIn(swapParams.path);
require(tokenIn == lp.denomination, "token should be denomination");
IERC20(tokenIn).forceApprove(swapRouter, swapParams.amountInMaximum);
swapParams.amountOut = a0 - lp.amount0In;
IMainnetRouter(swapRouter).exactOutput(swapParams);
IERC20(tokenIn).forceApprove(swapRouter, 0);
}
if (a1 > lp.amount1In && up.token1 != lp.denomination) {
swapParams = abi.decode(lp.swapParams2, (IMainnetRouter.ExactOutputParams));
address tokenIn = _getTokenIn(swapParams.path);
require(tokenIn == lp.denomination, "token should be denomination 2 ");
IERC20(tokenIn).forceApprove(swapRouter, swapParams.amountInMaximum);
swapParams.amountOut = a1 - lp.amount1In;
IMainnetRouter(swapRouter).exactOutput(swapParams);
IERC20(tokenIn).forceApprove(swapRouter, 0);
}
}
if (delta0 > 0) ILendingPool(lendingPool).pushFunds(up.token0, delta0);
if (delta1 > 0) ILendingPool(lendingPool).pushFunds(up.token1, delta1);
...
}In order to validate that the denomination token is the tokenIn, we call the internal _getTokenIn.
function _getTokenIn(bytes memory path) internal pure returns (address) {
while (path.hasMultiplePools()) {
path.skipToken();
}
(, address tokenIn,) = path.decodeFirstPool();
return tokenIn;
}The function intends to skip, the pools until only the initial one is available, to get the tokenIn.
However, path is never changed which causes an infinite loop when the user is trying to do a multi-hop swaps.
Root Cause
When, skipping tokens, path is never changed, causing an infinite loop, for users trying to do multihop swaps.
Internal Pre-conditions
None
External Pre-conditions
- User tries to do a multi-hop swaps
Attack Path
None
Impact
The Leverager::deposit function fails to support multi-hop swaps as intended
Mitigation
Consider overwriting the path when calling skipToken
while (path.hasMultiplePools()) {
- path.skipToken();
+ path = path.skipToken();
}