Closed c4-bot-4 closed 8 months ago
Picodes changed the severity to 2 (Med Risk)
Picodes marked the issue as duplicate of #527
Picodes marked the issue as not a duplicate
Picodes changed the severity to QA (Quality Assurance)
This is standard when creating Uniswap like pools and you have to use a bit of funds to reprice the pool eventually
The coded PoC demonstrates that a user can force a pool to be really unbalanced almost for free (100 wei of ETH and 100 wei of WBTC). This action will make the following depositor to lose all his deposited value because it will create a huge arbitrage oportunity. When this deposit of new funds is executed the same user can backrun the transaction and get this arbitrage oportunity basically stealing funds from the depositor. As explained in the submition, the more value difference between tokens and decimal discrepances the more funds can be stolen. I see this issue as a really severe one and I propose the same solution as the issue #937 . Also the feature that when swapping reserves can not drop from 100 wei of each token prevent from other users to balance the pool by swapping tokens. I would recommend rereading the submition and validate it as high or medium , thanks
"I would recommend rereading the submition and validate it as high or medium , thanks" -> I am sure you would recommend validating your own submissions. Please make sure to add only fact-based comments :)
Sorry about that :'(
Like #937, this issue is invalid because it doesn't discuss the slippage parameter provided. When adding liquidity in the provided test the user sets the minShare parameter to 0, but it's this parameter that is meant to prevent the sandwich attack from being possible.
Lines of code
https://github.com/code-423n4/2024-01-salty/blob/main/src/pools/Pools.sol#L271 https://github.com/code-423n4/2024-01-salty/blob/main/src/pools/Pools.sol#L90-L165
Vulnerability details
Impact
The first depositor of liquidity/collateral in all different liquidity pools can make the protocol to stop working entirely. The first user that deposits liquidity/collateral in a pool, has the power to establish the ratio between the 2 tokens. The only restriction for depositing the first time is to add a minimum of 100 units of each token in the pool. There is also a really relevant feature of these AMM token pools, when swapping, the resulting reserve amounts have to contain at least 100 units of each token.
These 2 things combined enable anyone being the first depositor to DoS a liquidity pool or even the entire protocol.
Written proof of concept
Take into account the collateral pool that is composed of WETH and WBTC. Suppose that ETH is at 2 000 USD and BTC at 40 000 USD. WETH has 18 decimals and WBTC 8. The first depositor (that can be anyone) deposits the minimum of each token to the pool. Hence 101 units of WETH and 101 units of WBTC.
This single action only costs the following to the user:
As we can see, this deposit of collateral was almost free for the user. But this simple action has DoS the entire protocol.
The ratio of the 2 tokens has been set to be 0.0000000001 ETH = 1 BTC due to difference of decimals, when in reality is 20 ETH = 1 BTC.
Why the protocol suffers from DoS?
The only way to fix this token ratio would be by swapping ETH for BTC and align the price with the market. However, if someone tries to swap any amount in any direction, since the reserve of the output token will decrease to a number smaller than 100, the transaction will revert.
When this situation is reached neither liquidity providers nor swappers will use the liquidity pool.
The only possible way to fix it would be providing liquidity to the pool knowing that the value of your deposited assets will drop to 0. Since it would be a huge lose by the depositor nobody would never be incentivised to do it.
Proof of Concept
Check this foundry test
Setup:
Proof of Concept:
Output traces:
Different severities of the attack
There are 3 different attack situations:
The collateral pool (WETH/WBTC) suffers the attack:
The pool would not be used
Nobody would provide collateral and as a result nobody would use USDS stablecoin
A big number of pool swaps would stop working due to arbitrage paths
Since the WETH/WBTC pool is involved in all possible swaps except of swapTokenIn->swapTokenOut, when the binary search would detect an arbitrage profit in this pool, it would try to swap tokens in this pool and would revert due to any of the reserves dropping below 100 units of the token.
In this situation, the first depositor can also borrow USDS and become not liquidable because when the function will try to remove liquidity, the reserves will drop below 100 units of tokens and the transaction will revert
A pool that involves any of the important tokens for the protocol (WETH, WBTC and SALT):
A pool that involves tokens that are not relevant for the protocol
Note: This attack is mainly possible due to price and decimal difference between tokens. That means that with tokens that are pegged 1:1 and have the same number of decimals, it is not possible to execute this action. For example, in a pool with stablecoins like USDS and DAI that share the same amount of decimals, this attack would not be possible because setting the 1:1 ratio for the 2 tokens would not have any discrepancy with the market and liquidity providers would deposit assets normally. Thus, the liquidity pool would work as expected.
Tools Used
Manual review
Recommended Mitigation Steps
From my point of view the check at the end of each swap to disable draining the whole pool reserves its a good security check for possible price manipulation attacks so I would not change that.
Instead I would disable any user from setting the initial token ratio of a liquidity pool. This way, if the creation of a liquidity pool would be permissioned to the DAO for example, it would set an initial token ratio aligned with the market and it would disable the attack completely.
Assessed type
Error