DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

No slippage control for paraswap

Summary

_doDexSwap() function under PerpetualVault.sol swaps the input tokens with output tokens but it doesn't have proper slippage control which can put the protocol on risk in future. While the sequencer does not permit arbitrage opportunities to be arbitrarily captured, the code will continue to result in uncontrollable outputs that might ultimately not result in the output that the protocol expects

function _doDexSwap(
bytes memory data,
bool isCollateralToIndex
) internal returns (uint256 outputAmount) {
(address to, uint256 amount, bytes memory callData) = abi.decode(
data,
(address, uint256, bytes)
);
...
uint256 balBefore = outputToken.balanceOf(address(this));
ParaSwapUtils.swap(to, callData);
outputAmount = IERC20(outputToken).balanceOf(address(this)) - balBefore;
emit DexSwap(
address(inputToken),
amount,
address(outputToken),
outputAmount,
isCollateralToIndex
);
...
}

Vulnerability Details

Although frontrunning is not an issue on L2s, which helps mitigate certain MEV attacks, the absence of defined slippage and potential network congestion could lead to swaps being executed under unfavorable conditions, resulting in losses for users.

Impact

As the minimum output is not set, the loss for users that use this function can be of 100% of their funds. It will make sure that the swap will always be paraswap is executed no matter the market condions.

Tools Used

Manual Review

Recommendations

We recommend setting desired slippage params.

Add a new paramter minimumOutputAmount and if we dont receive this amount from paraswap then revert

function _doDexSwap(
bytes memory data,
bool isCollateralToIndex
) internal returns (uint256 outputAmount) {
//@audit - add new parameter - minOutputAmount a shown below
(address to, uint256 amount, uint256 minOutputAmount, bytes memory callData) = abi.decode(
data,
(address, uint256, uint256, bytes)
);
...
uint256 balBefore = outputToken.balanceOf(address(this));
ParaSwapUtils.swap(to, callData);
outputAmount = IERC20(outputToken).balanceOf(address(this)) - balBefore;
//@audit - have this require statement
require(outputAmount >= minOutputAmount,"Incorrect Token amount received")
emit DexSwap(
address(inputToken),
amount,
address(outputToken),
outputAmount,
isCollateralToIndex
);
...
}
Updates

Lead Judging Commences

n0kto Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid_swap_slippage_and_deadline

Slippage and deadline are handled externally. Paraswap implementation used by the current code (behind the proxy): https://etherscan.io/address/0xdffd706ee98953d3d25a3b8440e34e3a2c9beb2c GMX code: https://github.com/gmx-io/gmx-synthetics/blob/caf3dd8b51ad9ad27b0a399f668e3016fd2c14df/contracts/order/OrderUtils.sol#L150C15-L150C33

Support

FAQs

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