Open c4-bot-1 opened 2 months ago
kalinbas marked the issue as disagree with severity
We agree with this finding and will remove the check. But this should be at max a medium risk as there is no direct loss of funds, but its more of a DOS (which could be resolved by using flashbots for example).
kalinbas (sponsor) confirmed
Hi @kalinbas , I think the same issue has been reported and it's sorted as QA https://github.com/code-423n4/2024-03-revert-lend-findings/issues/124
Thanks, @ktg9 ! Good observation!
However the mentioned submission only factors the AutoRange.sol
transformer, which introduces the milder impact. This finding also includes the AutoExit.sol
case where a DOS leads to a significantly more serious impact. Here are the arguments
AutoExit.sol
is documented to:
Lets a v3 position to be automatically removed (limit order) or swapped to the opposite token (stop loss order) when it reaches a certain tick.
Here are short definitions of the 2 operations from Investopedia:
A limit order guarantees that an order is filled at or better than a specific price level. Limit orders can be used in conjunction with stop orders to prevent large downside losses.
A stop-loss is designed to limit an investor's loss on a security position that makes an unfavorable move.
Both of those operations are very time-bound, especially the Stop Loss
order, where the idea is that the position owner configures a threshold at which he should exit the market or else his position will sustain losses. In case the price(ticks) drop below that threshold, DOSing execution even for a shorter amount of time can seriously affect the position, especially if it is a big one and the market is very active and volatile (like in a bull run) - the longer the position does NOT exit the market, the greater the losses.
DOSing here will not cost much compared to how it can affect a position.
The reason why the mentioned submission was qualified as QA is because:
AutoRange.sol
is DOSed this will prevent the position to be rebalanced when it goes out-of-range which is also a time-bound operation and can cause losses or missed profits(depending on the goals the position owner had when configuring the positions) and the duration it was kept out of range.AutoRange.sol
and not the one described aboveHi @BogoCvetkov , thank you for your response. Note that I'm not the judge .
The function AutoExit.execute
will be called by an operator (likely a bot) and this operator is the one who provide ExecuteParams
, not the user who call AutoExit.configureToken
. I believe the bot has the responsibility to provide the correct liquidity
at the time it calls execute
.
So I think judge's comment on the original issue still true here.
Like the issues with liquidations, there is no real point to this attack, as it neither profits nor truly halts the protocol. It only causes a transaction from an operator to fail and donates a minuscule amount of assets to the protocol. Therefore, I am downgrading it to low.
I think judge @jhsagd76 will take a look.
Thanks for the comment!
The issue here can occur regardless of the parameters the bot provides, since it can still be front-run with another transaction that changes the liquidity.
The difference here is that if the order is not executed in time it can lead to losses - thats the main idea of the AutoExit.sol
contract. The loss here occur, because the position is prevented from exiting the market (when it should) -this is why it's called a stop loss order.
I've provided enough arguments above, so let's see what the judge thinks
I think the attack in AutoExit is more convincing, although passing specific parameters in auto range might produce a similar effect. However, since this exploitation is based on MEV, we should assume that the parameters in the original tx are not edge. This report elaborates more thoroughly on the exploitation scenarios and impacts, giving me the confidence to mark it as M.
I would like to consider them as two different vulnerability paths. The path in AutoRange was judged as L in the original competition, and the path in AutoExit is now judged as M.
jhsagd76 marked the issue as satisfactory
jhsagd76 marked the issue as selected for report
jhsagd76 changed the severity to 2 (Med Risk)
Lines of code
https://github.com/revert-finance/lend/blob/dcfa79924c0e0ba009b21697e5d42d938ad9e5e3/src/automators/AutoExit.sol#L130 https://github.com/revert-finance/lend/blob/dcfa79924c0e0ba009b21697e5d42d938ad9e5e3/src/transformers/AutoRange.sol#L139
Vulnerability details
Impact
An exploiter can block the execution of AutoExit and AutoRange transformers, which leads to the following consequences:
Limit orders
&Stoploss orders
- position owners won't be able to exit a bad market and will suffer lossesAutorange orders
- positions that go out-of-range won't be rebalanced leading to missed profits or direct lossesVulnerability details
The
AutoRange.sol
andAutoExit.sol
contracts serve the following functionality in Revert Lend:AutoRange.sol
contractAutoExit
contractBoth of those contracts implement an
execute()
function that respectively transforms an NFT position based on the parameters provided to it. It can only be called by revert controlled bots (operators) which owners have approved for their position or by theV3Vault
through it'stransform()
function.The problem in both of those contracts is that the
execute()
function includes a validation that allows malicious users to DOS transaction execution and thus compromise the safety and integrity of the managed positions.AutoExit::execute()
https://github.com/revert-finance/lend/blob/audit/src/automators/AutoExit.sol#L130
AutoRange::execute()
https://github.com/revert-finance/lend/blob/audit/src/transformers/AutoRange.sol#L139
The problematic validation shared in both function is this one:
The check is meant to ensure that the execution parameters the transaction was initiated with, are executed under the same conditions (the same liquidity) that were present when revert bots calculated them off-chain.
The main issue here arises from the fact that liquidity of a position inside
NonfungiblePositionManager
can be manipulated by anyone. More specificallyNonfungiblePositionManager::increaseLiquidity()
can be called freely, which means that liquidity can be added to any NFT position without restriction.This can be validated by looking at
NonfungiblePositionManager::increaseLiquidity()
https://github.com/Uniswap/v3-periphery/blob/697c2474757ea89fec12a4e6db16a574fe259610/contracts/NonfungiblePositionManager.sol#L198C14-L198C31
All of this allows any attacker to exploit the check at practically zero cost
POC
I've coded a POC to prove how for the cost of
1 wei
(basically free) an attacker prevents a stop loss order for a position from being executed.I've added the following test to
AutoExit.t.sol
, reusing the logic from thetestStopLoss()
testRecommended mitigation steps
Consider removing the problematic check from both functions, since it can cause more harm than good in this particular scenario.
Assessed type
DoS