sherlock-audit / 2024-04-interest-rate-model-judging

9 stars 5 forks source link

Emmanuel - User can open borrow positions that would cause liquidators to be disincentivized from liquidating it due to gas fees #202

Closed sherlock-admin2 closed 4 months ago

sherlock-admin2 commented 4 months ago

Emmanuel

medium

User can open borrow positions that would cause liquidators to be disincentivized from liquidating it due to gas fees

Summary

Opening borrow positions with collateral less than average gas fees on that network, would disincentivize liquidators from liquidating it. Attacker can open many of these positions with multiple accounts, which is equivalent to a large borrow position.

Vulnerability Detail

There is no minimum borrow position that a user is required to open. User can open positions backed by <gasfees collateral, and if it gets liquidatable, liquidators won't want to liquidate it which could lead to insolvency.

In addition, user can deposit <gasFees collateral in each of the markets, and borrow up to gasFees*numberOfMarkets/collateralRatio. Since liquidators have to specify the market to seize from, and user collateral in each market is <gasFees, seizing from any of the markets would result in loss for the liquidator.

Note that protocol will be deployed on ethereum mainnet, where gas fees are very high.

Impact

Since liquidating tiny unhealthy positions would result in loss for liquidator. Liquidators won't want to liquidate them, leading to accrual of bad debt->insolvency

Code Snippet

https://github.com/sherlock-audit/2024-04-interest-rate-model/blob/main/protocol/contracts/Market.sol#L140 https://github.com/sherlock-audit/2024-04-interest-rate-model/blob/main/protocol/contracts/Market.sol#L281

Tool used

Manual Review

Recommendation

borrow,borrowAtMaturity,withdraw,withdrawAtMaturity should enforce a minimum amount of borrow positions that should be opened.

santipu03 commented 4 months ago

From the README:

Are there any off-chain mechanisms or off-chain procedures for the protocol (keeper bots, arbitrage bots, etc.)? We have a liquidation bot that monitors the health of the protocol's accounts and calls the liquidate function.

This issue is invalid because the liquidation bot from the protocol will liquidate all unhealthy positions regardless of the potential profit/losses.

Emedudu commented 4 months ago

Escalate

This would still cause loss of funds for the liquidator bots or any liquidator in general. The protocol will be deployed on ethereum where gas fees are high. This loss would be substantial especially if many accounts do this.

I believe this should be a valid Medium.

sherlock-admin3 commented 4 months ago

Escalate

This would still cause loss of funds for the liquidator bots or any liquidator in general. The protocol will be deployed on ethereum where gas fees are high. This loss would be substantial especially if many accounts do this.

I believe this should be a valid Medium.

You've created a valid escalation!

To remove the escalation from consideration: Delete your comment.

You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.

santipu03 commented 4 months ago

I still believe this issue is invalid based on my initial comment.

cvetanovv commented 4 months ago

I disagree with the escalation.

The impact of this issue is that the protocol will accrue bad debts because there will be no one to liquidate very small positions. But this is not true because bots will be used to take care of this:

We have a liquidation bot that monitors the health of the protocol's accounts and calls the liquidate function.

You are right that for very small positions, it is possible to have some losses when bots liquidate positions, but this is Low severity. However, the main impact of the issue is that the protocol will have bad debt, which is invalid.

Planning to reject the escalation and leave the issue as is.

Emedudu commented 4 months ago

You are right that for very small positions, it is possible to have some losses when bots liquidate positions, but this is Low severity. However, the main impact of the issue is that the protocol will have bad debt, which is invalid.

There is no barrier to creating many small positions that become unhealthy.

Liquidating many of these positions will cause the loss to be significant

Normal Liquidators will take on this loss if they liquidate the position.

Let's say they don't, protocol liquidation bots will take the loss.

I believe liquidation bots get funded by their owners, so if they lose money, then it is actually their owners that lose

cvetanovv commented 4 months ago

I think it's an issue, but it is Low Severity. The main impact is that the protocol can get bad debt, which is invalid. The bots won't allow that.

One more thing that further decreases the severity of this issue is that "Griefing for gas" is an invalid issue, according to the Sherlock documentation.

Emedudu commented 4 months ago

I think this is at least Medium severity because liquidators and protocol liquidation bots will lose funds

Imagine an attacker opening many $5 positions on Ethereum, where gas fees for liquidating a position is $20. By liquidating each of those position, liquidator or protocol loses $15.

Also, here is a link to a similar Sherlock issue that was judged as Medium, despite the protocol being deployed to chains where gas fees are really low: https://github.com/sherlock-audit/2024-02-perpetual-judging/issues/115

santipu03 commented 3 months ago

@Emedudu The issue you mentioned was accepted as medium severity because the Perpetual protocol didn't have any liquidation bots themselves so the risk of bad debt was real. In this case, the liquidation bot of Exactly will prevent the creation of bad debt.

Emedudu commented 3 months ago

Hello @santipu03 ,

Protocol's liquidation bot or not, the issue is that anyone that liquidates such positions will lose funds.

Isn't that a criteria for issue validity on Sherlock?

I think we can at least agree that:

Therefore,severity should be at least a medium

(Which of the above do you disagree with?)

santipu03 commented 3 months ago

Given that the only impact now is increased gas costs on liquidations, this report now is a gas optimization issue, and thus should be invalid according to the Sherlock guidelines:

VII. List of Issue categories that are not considered valid:

  1. Gas optimizations: The user/protocol ends up paying a little extra gas because of this issue.
cvetanovv commented 3 months ago

I completely agree with the lead judge's comments.

The only impact is that the bots will lose money if the positions are smaller than the cost of the gas.

Their loss will be the "Gas - position".

Apart from the fact that the impact is Low, this is also in the "Griefing for gas" category and is invalid.

To all this, we can add this rule:

Gas optimizations: The user/protocol ends up paying a little extra gas because of this issue.

I stand by my initial decision to reject the escalation.

Emedudu commented 3 months ago

This is not "a little extra gas".

Say gas fees on ethereum is $20 Attacker can open 100 $5 positions on ethereum, which will make protocol lose 15*100 = $1500.

Can we call this a small loss?

This can be used to waste as much funds as the attacker wants.

Impact of this is obviously not low Likelihood is obviously high.

I still believe this is at least a medium severity issue

Emedudu commented 3 months ago

We all know what Sherlock means by a gas optimization issue

It is easy to know a gas optimization bug when you see one.

This issue is obviously not a gas optimization issue.

Why should a gas optimization issue have a potential to waste up to tens of thousands of dollars?

cvetanovv commented 3 months ago

Your calculation is not correct. Let's look at the official statistics:

This is Ethereum Average Gas Price: https://etherscan.io/chart/gasprice

Here, we can use a calculator: https://coinbrain.com/converter/eth-0x29e683aeafd03bb6c02055c3ca8b6edb4bb9bae5/usd

We can also use this chart that is easier to visualize the days - https://ycharts.com/indicators/ethereum_average_gas_price

If we take the data for 23 May, the average gas price is $2.35. There is no problem. Even the bots are profitable. However, I agree that there were days in the year when the average price was $10+.

Let's see Sherlock documentation:

Invalid: Gas optimizations: The user/protocol ends up paying a little extra gas because of this issue.

Let's also see what impact you had on the issue itself:

Since liquidating tiny unhealthy positions would result in loss for liquidator. Liquidators won't want to liquidate them, leading to accrual of bad debt->insolvency

This is not true because bots will be used to take care of unhealthy positions.

These are the reasons why I think this issue is Low severity.

Emedudu commented 3 months ago

Your calculation is not correct. Let's look at the official statistics: This is Ethereum Average Gas Price: https://etherscan.io/chart/gasprice Here, we can use a calculator: https://coinbrain.com/converter/eth-0x29e683aeafd03bb6c02055c3ca8b6edb4bb9bae5/usd We can also use this chart that is easier to visualize the days - https://ycharts.com/indicators/ethereum_average_gas_price If we take the data for 23 May, the average gas price is $2.35. There is no problem. Even the bots are profitable. However, I agree that there were days in the year when the average price was $10+.

To calculate the gas cost(in gwei) for a transaction, we do: gas cost=gas units spent on the transaction*average gas price in gwei

Since 1 eth=1_000_000_000 gwei, 1 gwei to USD=eth price/1_000_000_000.

Now, let's calculate gas cost for liquidation:

So, gas cost in gwei for executing liquidate=15.57*597344 = ~9_300_000 gwei

Since 1 eth= $3700(at time of writing), 1 gwei=3700/1_000_000_000=$0.0000037

Therefore, $ gas cost for executing liquidate =0.0000037*9300000=$34.41.

Let's see Sherlock documentation: Invalid: Gas optimizations: The user/protocol ends up paying a little extra gas because of this issue.

If attacker opens a position of $5, and it costs $34 to liquidate it, liquidation bots loses $29. If he opens 100 $5 positions, loss=$2900 I don't believe this is "a little extra gas". Plus in general, gas optimization issues are usually about the protocol spending a higher number of gas units than they ought to. This issue is not about that.

Let's also see what impact you had on the issue itself: Since liquidating tiny unhealthy positions would result in loss for liquidator. Liquidators won't want to liquidate them, leading to accrual of bad debt->insolvency This is not true because bots will be used to take care of unhealthy positions.

It is true that the report's impact did not acknowledge the fact that there are liquidation bots. But the core issue still remains that: anyone(including the protocol's liquidation bots) that liquidates those positions opened by the attacker will be disincentivized.

cvetanovv commented 3 months ago

@Emedudu With that calculation, you showed, and with the average loss of $30 per position, I tend to agree that this does not fall under the "Gas optimizations issue" and is more Medium than Low.

I plan to accept the escalation and make this issue a valid Medium.

0x73696d616f commented 3 months ago

@Emedudu's analysis is too simplistic. The cost of opening these positions also has to be considered. An attacker needs to deposit and borrow using multiple wallets. So the cost of deposit + borrow must be considered. Then, opening 1000 positions or something will increase gas fees as the fee model is based on utilization. And finally, the gas price may vary since the attacker created the positions, it has no guarantee that the gas price will be higher when liquidating. In fact, this argument alone should be able to invalidate the finding. Due to these reasons, this is essentially a griefing attack where someone is fighting against the owner to see who has more funds, which is not valid. If the watson proves that somehow this attack is heavily (because gas price may change) favoured towards the attacker, I agree it may be valid.

0x73696d616f commented 3 months ago

As a note I was curious and calculated gas costs myself. deposit + borrow = 408727 gas deposit + enterMarket = 224770 gas borrow = 241952 gas liquidate = 388886 gas It's true that the borrower may deposit in several markets and borrow in just one, so it's not as simple. Also, the liquidator may not need to seize every single market, in reality less markets should be enough.

He also has to enter markets in each of the markets, or it will not count as collateral. so in reality it's deposit + enterMarket, for each market + borrow on one market If we have a large number of markets, the discrepancy may become bigger. Still, I think the gas costs are too similar for this to be viable.

Emedudu commented 3 months ago

Here are the average gas units: deposit=150441 borrow=167523 liquidate=384973 enterMarket=23675

Let's say there are 3 markets

In total, cost for liquidation bots=5*cost for attacker

0x73696d616f commented 3 months ago

@Emedudu the difference in gas price can not be considered, as the attacker can not possibly know what it will be at the time of liquidation. The attacker has to predict the gas fees to add as collateral in each market. If the predicted gas fees are higher than the real at the time of liquidation, the liquidation is still worth it.

Additionally, we have to consider that such small positions, where each position is at most the size of the gas fees required to liquidate (which can not be predicted), will require much more funds from the attacker size. If the deposit / liquidate gas fees ratio is 0.5, then the attacker is adding 2 wei of collateral for each 1 of gas spent. So if he gets a total collateral of 1 ETH, it's costing 0.5 ETH of gas fees. This means that in case the attacker is indeed liquidated, even at a higher gas price (impossible to predict), the losses are very close.

My judgement is that given these 2 arguments, the cost to the attacker is very close to the cost to the protocol and the attack is not worthy of medium severity.

0x73696d616f commented 3 months ago

I think even in your scenario, the attacker loses more than the liquidator. I assumed the attacker deposit gas fees equivalent to the liquidation cost at 10 gwei, to have some margin, as gas prices average 15, so 10 is more likely to be below the actual gas price. Assumed adjust factor of 0.9 for the debt borrowed.

attacker cost = 571496*4 = 2285984
attacker total collateral = 384973*3*10

bot cost = 384973*2*15 = 11549190
attacker seized collateral = 384973*2*10

attacker debt = 384973*3*10*0.9*0.9 = 9354843
attacker loss = collateral + gas fees - debt = 384973*10*3 + 2285984 - 9354843 = 4480331

bot loss = gas cost - collateral seize = 384973*2*15 - 384973*2*10 = 384973*2*5 = 3849730
Emedudu commented 3 months ago

Given an entity who has the will to choose when to call a function, and another entity who urgently needs to call a function depending on the current market conditions, I think the former is more likely to be favoured by gasPrices.

We can remodify the above calculation:

attacker cost = 571496*4 = 2285984
attacker total collateral = 250000*3*10

bot cost = 384973*3*15 = 17323785
attacker seized collateral = 250000*3*10

attacker debt = 250000*3*10*0.9*0.9 = 6075000
attacker loss = total collateral + gas fees - debt=250000*10*3 + 2285984 - 6075000 = 3710984

bot loss = gas cost - collateral seize = 384973*3*15 - 250000*3*10 = 9823785
0x73696d616f commented 3 months ago

So he's opening positions of 6075000e-9 ETH debt = 22.5 USD at 3700 USD / ETH For this to become significant for liquidations to be rushed, you would need like 1000 positions? 22500 USD. This would require 2285984×1000/30000000 76 blocks. It would probably be the biggest block stuffing event ever and would drive gas prices crazy. Thus, if the collateral in the positions is too small, too much gas is required and the attack becomes inviable. If too much collateral is placed, liquidators still have incentive.

0x73696d616f commented 3 months ago

Also the positions required to liquidate were changed from 2 to 3 which seems less likely.

0x73696d616f commented 3 months ago

This attack seems too theoretical and involves a set of conditions that may or may not be true. I leave this up to the judge.

0x73696d616f commented 3 months ago

Given an entity who has the will to choose when to call a function, and another entity who urgently needs to call a function depending on the current market conditions, I think the former is more likely to be favoured by gasPrices.

The debt is too low for this to be true and the attacker has to predict gas prices.

0x73696d616f commented 3 months ago

Summing up The attack path is not clearly favoured towards the attacker. The bot is trusted to clear some organic bad debt (not much, in the Perennial contest it involved leverage which increases the number of lower sized positions).

Emedudu commented 3 months ago

So he's opening positions of 6075000e-9 ETH debt = 22.5 USD at 3700 USD / ETH For this to become significant for liquidations to be rushed, you would need like 1000 positions? 22500 USD. This would require 2285984×1000/30000000 76 blocks. It would probably be the biggest block stuffing event ever and would drive gas prices crazy. Thus, if the collateral in the positions is too small, too much gas is required and the attack becomes inviable. If too much collateral is placed, liquidators still have incentive.

100 positions , as stated in my example, is enough to demonstrate this. Plus, the attacker doesn't have to open all at the same time, so no need for block stuffing

Also the positions required to liquidate were changed from 2 to 3 which seems less likely.

Yeah I had to modify some parameters, for example, attacker is depositing into each market, less than gas cost of liquidate. That's the point of the attack.

This attack seems too theoretical and involves a set of conditions that may or may not be true. I leave this up to the judge.

Please state the conditions you don't agree with

Summing up The attack path is not clearly favoured towards the attacker. The bot is trusted to clear some organic bad debt (not much, in the Perennial contest it involved leverage which increases the number of lower sized positions).

This report is about liquidators losing funds from liquidating positions opened by attacker, which I think I've been able to prove.

0x73696d616f commented 3 months ago

100 positions , as stated in my example, is enough to demonstrate this.

100 positions is just 2250 debt, which is not enough for the liquidator to rush liquidations.

Plus, the attacker doesn't have to open all at the same time, so no need for block stuffing

If it's not at once, then it's no longer an attack because they can just be liquidated over time too. They will not be all liquidatable at the same time and the gas price can not be played with.

The reason I say this is theoretical is because 1) the gas prices may rise too much due to opening positions, 2) we can not know if the liquidation is in fact rushed or not for debt values such as 2250 USD, thus accounting for gas price diff is unreliable, 3) the attacker has to be able to predict gas prices and the attack may fail horribly. 4) the losses for both parties are too close for the attacker to execute such an attack, which has too many unknowns. 5) we do not know how many markets need to be liquidated.

For these reasons I think it is completely theoretical.

0x73696d616f commented 3 months ago

I think this falls under the rule:

Griefing for gas (frontrunning a transaction to fail, even if can be done perpetually) is considered a DoS of a single block, hence only if the function is clearly time-sensitive, it can be a Medium severity issue.

The attacker is not profiting for this as the gas spent is too much in comparison to the opened position. In your example, the attacker has a debt of 6075000 while it costs 2285984 to open the position, almost 40% upfront cost. Perhaps with leverage these numbers would be more relevant, as was the case in the Perennial contest.

cvetanovv commented 3 months ago

I agree with the last comments of @0x73696d616f. The attack is very difficult to do because we don't know what the cost of the gas will be at the time of liquidation. Therefore, the attack may not be profitable at all.

Even if it is profitable, it will be by a small margin and will be in the "Griefing for gas" or "Gas optimizations" category:

The user/protocol ends up paying a little extra gas because of this issue.

To these points, I will add that the Impact described in the issue itself is invalid because the bots will take care of it.

So, I decided to reject the escalation and leave the issue as it is.

Evert0x commented 3 months ago

Result: Invalid Unique

sherlock-admin4 commented 3 months ago

Escalations have been resolved successfully!

Escalation status: