stent - poolAmountAdjustment set but not unset in swapProfitToCollateralToken
sherlock-admin opened this issue · comments
stent
high
poolAmountAdjustment set but not unset in swapProfitToCollateralToken
Summary
In DecreasePositionCollateralUtils.swapProfitToCollateralToken
poolAmountAdjustment is increased before the swap but only decreased if the swap fails.
Vulnerability Detail
poolAmountAdjustment is set to poolAmountDelta
in DecreasePositionCollateralUtils.swapProfitToCollateralToken
. If the swap fails then the value is set to 0 again, but if the swap is successful the value is left as poolAmountDelta.
poolAmountAdjustment is used to calculate the next pool amounts in SwapPriceingUtils.getNextPoolAmountsParams. Any call path involving a swap will be affected since the price impact calculation depends on
SwapPricingUtils.getPriceImpactUsd(via
SwapUtils._swap`).
Impact
If the poolAmountAdjustment value is not set to 0 then it will cause the accounting to be wrong for the price impact calculation which affects fees etc that the user pays. The large poolAmountAdjustment is the more fees subsequent users could pay.
Code Snippet
params.contracts.dataStore.setInt(Keys.poolAmountAdjustmentKey(params.market.marketToken, pnlToken), poolAmountDelta);
try params.contracts.swapHandler.swap(
SwapUtils.SwapParams(
params.contracts.dataStore,
params.contracts.eventEmitter,
params.contracts.oracle,
Bank(payable(params.market.marketToken)),
params.orderKey,
pnlToken, // tokenIn
profitAmount, // amountIn
swapPathMarkets, // markets
0, // minOutputAmount
params.market.marketToken, // receiver
params.order.uiFeeReceiver(), // uiFeeReceiver
false // shouldUnwrapNativeToken
)
) returns (address /* tokenOut */, uint256 swapOutputAmount) {
return (true, swapOutputAmount);
} catch Error(string memory reason) {
emit SwapUtils.SwapReverted(reason, "");
} catch (bytes memory reasonBytes) {
(string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes);
emit SwapUtils.SwapReverted(reason, reasonBytes);
}
params.contracts.dataStore.setInt(Keys.poolAmountAdjustmentKey(params.market.marketToken, pnlToken), 0);
// contract & func: SwapUtil._swap
int256 priceImpactUsd = SwapPricingUtils.getPriceImpactUsd(
SwapPricingUtils.GetPriceImpactUsdParams(
params.dataStore,
_params.market,
_params.tokenIn,
cache.tokenOut,
cache.tokenInPrice.midPrice(),
cache.tokenOutPrice.midPrice(),
(fees.amountAfterFees * cache.tokenInPrice.midPrice()).toInt256(),
-(fees.amountAfterFees * cache.tokenInPrice.midPrice()).toInt256()
)
);
Tool used
Manual Review
Recommendation
Set poolAmountAdjustment to 0 for successful swaps.
Duplicate of #235