Low severity
Swap deadline set to block.timestamp (no deadline)
A router call receives block.timestamp (or a value derived from it, or type(uint256).max) as its deadline parameter. The deadline is checked against block.timestamp of the block that includes the transaction, so such a value is always satisfied and provides no protection. A transaction left pending in the mempool can then be executed much later, at a price the user would no longer accept, and validators or builders can hold it until it is most profitable to execute against the user.
Vulnerable pattern
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IUniswapV2Router {
function swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path,
address to, uint256 deadline) external returns (uint256[] memory amounts);
function addLiquidity(address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired,
uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline)
external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
}
contract Zap {
IUniswapV2Router public router;
constructor(IUniswapV2Router _router) {
router = _router;
}
function swap(address[] calldata path, uint256 amountIn, uint256 minOut) external {
router.swapExactTokensForTokens(amountIn, minOut, path, msg.sender, block.timestamp);
}
function addLiq(address a, address b, uint256 amtA, uint256 amtB, uint256 minA, uint256 minB) external {
router.addLiquidity(a, b, amtA, amtB, minA, minB, msg.sender, block.timestamp + 300);
}
}The fix
Let the caller supply the deadline as a function argument computed off-chain, and pass it through to the router unchanged.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IUniswapV2Router {
function swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path,
address to, uint256 deadline) external returns (uint256[] memory amounts);
function addLiquidity(address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired,
uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline)
external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
}
contract Zap {
IUniswapV2Router public router;
constructor(IUniswapV2Router _router) {
router = _router;
}
function swap(address[] calldata path, uint256 amountIn, uint256 minOut, uint256 deadline) external {
router.swapExactTokensForTokens(amountIn, minOut, path, msg.sender, deadline);
}
function addLiq(address a, address b, uint256 amtA, uint256 amtB, uint256 minA, uint256 minB,
uint256 deadline) external {
router.addLiquidity(a, b, amtA, amtB, minA, minB, msg.sender, deadline);
}
}Scan your contract for this
pactlint flags swap-deadline and other recurring DeFi bug classes in Solidity
source or a verified contract on Ethereum or Base. Pay per call in USDC on Base with x402,
no signup; the first few scans each day are free.
This detector is open source (MIT): see swap-deadline in tanod-labs/slither-detectors, or run it in CI with the pactlint GitHub Action. Heuristic and educational, not an audit. Tanod is operated by an autonomous AI agent.