The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: medium
Valid

Swap function is using block.timestamp as expiration deadline and amountOutMinimum has no slippage protection

Summary

In the swap function, there are two issues we need to address, the block.timestamp set as expiration deadline and the minimumAmountOut do not provide slippage protection.

Vulnerability Details

Let's tackle first, the block.timestamp set as deadline (line 233), this can be manipulated by the miner and he is free to decide whenever time he chooses to include the swap transaction in a block. Block.timestamp is a moving value like time so it means the deadline is always the current block, therefore in reality there is no deadline set.

File: SmartVaultV3.sol
224: function swap(bytes32 _inToken, bytes32 _outToken, uint256 _amount) external onlyOwner {
225: uint256 swapFee = _amount * ISmartVaultManagerV3(manager).swapFeeRate() / ISmartVaultManagerV3(manager).HUNDRED_PC();
226: address inToken = getSwapAddressFor(_inToken);
227: uint256 minimumAmountOut = calculateMinimumAmountOut(_inToken, _outToken, _amount);
228: ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
229: tokenIn: inToken,
230: tokenOut: getSwapAddressFor(_outToken),
231: fee: 3000,
232: recipient: address(this),
233: deadline: block.timestamp, // @ audit , do not provide real deadline
234: amountIn: _amount - swapFee,
235: amountOutMinimum: minimumAmountOut,
236: sqrtPriceLimitX96: 0
237: });
238: inToken == ISmartVaultManagerV3(manager).weth() ?
239: executeNativeSwapAndFee(params, swapFee) : // sending swap fee to protocol
240: executeERC20SwapAndFee(params, swapFee); // sending swap fee to protocol
241: }
242:

Then, let's talk about calculation of minimumAmountOut, this formula simply just provide the minimum token out so it can still maintain the collateral rate after the swap. There is no mention of slippage protection here because it depends solely on the price from chainlink data feed. The problem could happen here is if there is a sudden volatility price, chainlink data feed just provide the price (line 221), and the calculation just simply process it without slippage protection.

File: SmartVaultV3.sol
216: function calculateMinimumAmountOut(bytes32 _inTokenSymbol, bytes32 _outTokenSymbol, uint256 _amount) private view returns (uint256) {
217: ISmartVaultManagerV3 _manager = ISmartVaultManagerV3(manager);
218: uint256 requiredCollateralValue = minted * _manager.collateralRate() / _manager.HUNDRED_PC();
219: uint256 collateralValueMinusSwapValue = euroCollateral() - calculator.tokenToEur(getToken(_inTokenSymbol), _amount);
220: return collateralValueMinusSwapValue >= requiredCollateralValue ?
221: 0 : calculator.eurToToken(getToken(_outTokenSymbol), requiredCollateralValue - collateralValueMinusSwapValue);
222: }
223:

Proof of Concept

Consider this scenario

1 User perform a swap transaction with block.timestamp set as deadline and no slippage protection.

2 Since the deadline is block.timestamp, it is dependent on the miner discretion on what block it could be processed.

3 The transaction is already pending in mempool and still waiting to be included in the block for processing.

4 After many blocks have passed, price already change significantly and since there is no slippage protection, the transaction was still processed.

5 After the transaction was processed, the result is no longer what has been expected by the user. The price is sub-optimal and result to bad losses to user.

Impact

For invalid deadline check, it can bring user's trade in unfavorable position since there is no definite deadline.

For missing slippage protection, user has no control in minimum token it can get from the swap eventually result to a bad trade and losses to user.

Tools Used

Manual review

Recommendations

Deadline data should be provided by the input parameter set by user in the form of unix timestamp and not depend on retrieving data from block.timestamp.
You may refer to this site https://www.unixtimestamp.com/ as a reference for input data.

For slippage protection, please provide input parameter set by user so he has control on the minimum output token and not depend solely on the execution of third-party oracle data price feed.

Updates

Lead Judging Commences

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Slippage-issue

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

deadline-check

Support

FAQs

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