Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: low
Invalid

Making the Swap Deadline a Storage Variable Limits Flexibility for reasonable deadline at all times

Summary

The deadline that is passed to swap functions is a storage variable with a setter function. To achieve reasonable deadline for swaps at all times will require calling the setter function almost every hour. If not the deadline will need to be set to a very high amount as deadline.

Passing very high deadline defeats the purpose of the deadline protection. Even Uniswap app considers a deadline of 1 hour as high deadline.

Vulnerability Details

The deadline is that is passed to the swap functions in UniswapV2Adapter.soland UniswapV3Adapter.sol contracts is a storage variable in the inherited BaseAdapter.sol. This deadline storage variable has a setter function that onlyOwner can call.

Due to the reasons stated in the Impact section below, this approach is limits flexibility for reasonable deadline for all swap transactions at all times.

abstract contract BaseAdapter is UUPSUpgradeable, OwnableUpgradeable, ISwapAssetConfig, IDexAdapter {
...
/// @notice The deadline
uint256 deadline;
...
function setDeadline(uint256 _deadline) public onlyOwner {
// revert if the deadline is in the past
if (_deadline < block.timestamp) revert Errors.SwapDeadlineInThePast();
// set the new deadline
deadline = _deadline;
// emit the event
emit LogSetDeadline(_deadline);
}
...
}
File: UniswapV2Adapter.sol
/// @inheritdoc IDexAdapter
function executeSwapExactInputSingle(SwapExactInputSinglePayload calldata swapPayload)
external
returns (uint256 amountOut)
{
// transfer the tokenIn from the send to this contract
IERC20(swapPayload.tokenIn).transferFrom(msg.sender, address(this), swapPayload.amountIn);
// aprove the tokenIn to the swap router
address uniswapV2SwapStrategyRouterCache = uniswapV2SwapStrategyRouter;
IERC20(swapPayload.tokenIn).approve(uniswapV2SwapStrategyRouterCache, swapPayload.amountIn);
// get the expected output amount
uint256 expectedAmountOut = getExpectedOutput(swapPayload.tokenIn, swapPayload.tokenOut, swapPayload.amountIn);
// Calculate the minimum acceptable output based on the slippage tolerance
uint256 amountOutMinimum = calculateAmountOutMin(expectedAmountOut);
address[] memory path = new address[]();
path[0] = swapPayload.tokenIn;
path[1] = swapPayload.tokenOut;
uint256[] memory amountsOut = IUniswapV2Router02(uniswapV2SwapStrategyRouterCache).swapExactTokensForTokens({
amountIn: swapPayload.amountIn,
amountOutMin: amountOutMinimum,
path: path,
to: swapPayload.recipient,
deadline: deadline
});
return amountsOut[1];
}

Impact

  1. If small deadline is updated from time to time, transactions after that deadline will fail causing denial of service until a new deadline is updated. And this cause more gas.

  2. If large deadline is passed, the purpose of deadline protection is deafeated. The deadline protects swap transactions from being held for too long until it is profitable to exploit through sandwich attack.

Tools Used

Manual Review

Recommendations

Consider passing deadline as input to the swap functions which can be calculated on the frontend for every separate swap transaction.

The frontend can get the unix timestamp then add 30 minutes to it to get a deadline at the point of sending the transaction.

Unix timestamp + 1800 seconds = deadline

Updates

Lead Judging Commences

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

[INVALD] Swap Deadline is a Storage Variable and that Limits Flexibility

Support

FAQs

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