Summary
The SmartVaultV3::swap
function lacks a deadline
argument, allowing a malicious miner to hold the transaction until conditions are favorable for their attack. Passing block.timestamp
as the deadline does not ensure immediate execution but allows manipulation by miners.
Vulnerability Details
The absence of a deadline
argument in the SmartVaultV3::swap
function can be exploited by a malicious miner. The use of block.timestamp
as the deadline means the transaction can be delayed until conditions maximize slippage or trigger other unfavorable events, such as liquidations.
function swap(bytes32 _inToken, bytes32 _outToken, uint256 _amount) external onlyOwner {
uint256 swapFee = _amount * ISmartVaultManagerV3(manager).swapFeeRate() / ISmartVaultManagerV3(manager).HUNDRED_PC();
address inToken = getSwapAddressFor(_inToken);
uint256 minimumAmountOut = calculateMinimumAmountOut(_inToken, _outToken, _amount);
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: inToken,
tokenOut: getSwapAddressFor(_outToken),
fee: 3000,
recipient: address(this),
@> deadline: block.timestamp,
amountIn: _amount - swapFee,
amountOutMinimum: minimumAmountOut,
sqrtPriceLimitX96: 0
});
}
Impact
The lack of a specified deadline
could lead to malicious miners delaying the transaction for their benefit, maximizing slippage or triggering unfavorable events.
Tools Used
Manual review
Recommendations
To mitigate this issue, timestamps should be chosen off-chain and provided as an argument by the caller, preventing unnecessary manipulation by miners.
function swap(bytes32 _inToken, bytes32 _outToken, uint256 _amount, uint256 _deadline) external onlyOwner {
uint256 swapFee = _amount * ISmartVaultManagerV3(manager).swapFeeRate() / ISmartVaultManagerV3(manager).HUNDRED_PC();
address inToken = getSwapAddressFor(_inToken);
uint256 minimumAmountOut = calculateMinimumAmountOut(_inToken, _outToken, _amount);
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: inToken,
tokenOut: getSwapAddressFor(_outToken),
fee: 3000,
recipient: address(this),
deadline: _deadline,
amountIn: _amount - swapFee,
amountOutMinimum: minimumAmountOut,
sqrtPriceLimitX96: 0
});
}