The L2TokenReceiver
contract uses block.timestamp
as the deadline for transactions in the swap
and increaseLiquidityCurrentRange
functions. This practice does not provide the intended protection against the execution of stale transactions and may lead to unintended consequences if transactions are mined with a delay.
When a miner chooses to include the transaction into a block, its validity is established at that moment, as the block.timestamp
reflects the current timestamp as the deadline.
The contract sets the deadline
for certain operations to block.timestamp
, which is the timestamp of the current block. Since the deadline is checked against the timestamp of the block in which the transaction is included, using block.timestamp
as the deadline
means the check will always pass as long as the transaction is included in any block, rendering the deadline
check ineffective.
Please see the execution flows of swap()
and increaseLiquidityCurrentRange()
.
In the code snippet of the swap
function below, you can see that on line 65, block.timestamp
is utilized as the deadline
.
https://github.com/Cyfrin/2024-01-Morpheus/blob/07c900d22073911afa23b7fa69a4249ab5b713c8/contracts/L2TokenReceiver.sol#L57C1-L71C80
And observe what happens if line 71 calls the exactInputSingle()
function from the SwapRouter
contract in Uniswap V3.
https://github.com/Uniswap/v3-periphery/blob/697c2474757ea89fec12a4e6db16a574fe259610/contracts/SwapRouter.sol#L115C5-L121C6
The exactInputSingle()
function employs the checkDeadline()
modifier at line 119, which effectively compares the same current timestamps at line 8 in the code below.
https://github.com/Uniswap/v3-periphery/blob/697c2474757ea89fec12a4e6db16a574fe259610/contracts/base/PeripheryValidation.sol#L7C1-L10C6
In the provided code snippet for the increaseLiquidityCurrentRange
function, you can see that block.timestamp
is used as the deadline
on line 112.
https://github.com/Cyfrin/2024-01-Morpheus/blob/07c900d22073911afa23b7fa69a4249ab5b713c8/contracts/L2TokenReceiver.sol#L78C1-L117C11
See the line 115 invokes the increaseLiquidity()
function from the NonfungiblePositionManager
contract in Uniswap V3.
https://github.com/Uniswap/v3-periphery/blob/697c2474757ea89fec12a4e6db16a574fe259610/contracts/NonfungiblePositionManager.sol#L198C1-L208C6
The increaseLiquidity()
function utilizes the checkDeadline()
modifier at line 202, effectively comparing the current timestamps as seen on line 8 in the provided code.
https://github.com/Uniswap/v3-periphery/blob/697c2474757ea89fec12a4e6db16a574fe259610/contracts/base/PeripheryValidation.sol#L7C1-L10C6
The ineffective use of deadlines in transaction execution can expose protocol to significant risks, particularly in volatile market conditions.
Transactions intended to manage swaps, liquidity or preempt liquidation events may be delayed by miners, who could prioritize more profitable operations with their subsequent transactions.
This delay could result in the original transaction being executed at a time when market conditions have shifted unfavorably, leading to substantial slippage or making the protocol vulnerable to front-running.
Additionally, miners may intentionally withhold transactions until the point of maximum slippage, exacerbating the protocol's potential losses and undermining the transaction's original intent.
Manual Review
Modify the contract functions to accept a deadline parameter from the caller instead of using block.timestamp
directly within the functions.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.