Source: #179
This issue has been acknowledged by the team but won't be fixed at this time.
0xSlowbug, 0xlemon, Drynooo, Martians, TessKimy, dobrevaleri, j3x, moray5554, silver_eth, xiaoming90
For Liquid Staking Token (LST) collateral supported by the protocol, the protocol cannot enable the depeg check as LST collateral is not a stablecoin (1 wstETH does not peg to 1 ETH). Currently, one (1) wstETH is worth 1.2 ETH. As time goes on, the price of a single wstETH will increase to 1.3, 1.5, 2.0 ETH, and so on. Thus, TokenOracle.isStablecoin
parameter of LST must always be set to false
for wstETH and other LST because the current depeg check is only designed for collateral pegged 1:1 to USD or ETH (aka stablecoin/stableasset). In short, the current depeg check does NOT work for LST that accrued value and is not pegged to a specific value (e.g., 1 ETH).
As a result, the problem is that there is no on-chain threshold/deviation check mechanism for wstETH and LST within the in-scope contracts in the current implementation or codebase that will automatically pause contracts or revert the transaction when the LST's price crosses a certain threshold or deviation that might indicate something has gone wrong.
The Contest's README mentioned that it will monitor the Chainlink's stETH/ETH to detect any black-swan event where the price deviates significantly and will automatically pause the DaoCollateral
. However, that will not be effective and will not work.
When the Usual's monitoring bot detects an anomaly (e.g., LST's exchange rate gets manipulated upwards) in the price from the on-chain Chainlink's stETH/ETH price feed, it submits a transaction to pause the DAOCollateral. However, malicious users can always front-run Usual's pause transaction and arbitrage/drain/exploit the DAOCollateral before the pause transaction is executed.
There are various ways to arbitrage/drain/exploit the DAOCollateral to steal assets due to the lack of a deviation check:
- This can happen whenever there is a gap in the LIDO's wstETH exchange rate and market price. Assuming the LIDO's wstETH exchange rate has a slight delay in updating and reports a price higher than the on-chain market price. This can happen due to many reasons, such as the market reacting faster as they are already aware of the mass slashing before the oracle validators collect and push an update of the price to LIDO.
- As a result, malicious users can purchase discounted wstETH from the market and swap it for ETH0, and they will receive more ETH0 than expected. Next, they can swap the ETH0 for other LST collateral (e.g., rETH) supported by
DAOCollateral
OR hold it until the LIDO's wstETH exchange rate reflects the latest and correct lower price and then swap their ETH0 back to wstETH. - This basically turns Usual protocol into an exit liquidity venue when an adverse event or depeg event happens to a supported LST. Since it is a zero-sum game, the swapper's gain is Usual protocol's loss.
The following is the detailed scenario:
Assume two (2) Liquid Staking Token (LST) is supported by the protocol: wstETH and rETH. Currently, the price of wstETH is fetched from an exchange rate oracle, which is fetched directly from LIDO's wstETH stEthPerToken()
function.
Assume that LIDO validators have a major issue or outrage, resulting in a mass slashing of LIDO validators. The market price of wstETH drops significantly instantly as traders know that the backing ETH is about to decrease a lot (or already has).
However, the problem with using an exchange rate oracle is that there is a delayed response to adverse events. The oracle price (stEthPerToken()
) does not change immediately. Under normal circumstances, Lido’s oracle finalizes a new report every 24 hours (225 Ethereum Consensus Layer epochs). Refer to LIDO's documentation.
Assume the current price of collateral is as follows:
- wstETH = 1.2 ETH
- rETH = 1.2 ETH
There is a major slashing event on the LIDO validator. The market price of wstETH drops to 1 wstETH = 0.5 ETH, but the exchange rate from Lido's oracle or wstETH stEthPerToken()
function still reflects 1 wstETH = 1.2 ETH.
Bob quickly buys 100 wstETH from the market at a value of 50 ETH (a price of 0.5 ETH). He then swaps it for 120 ETH0 because DaoCollateral uses an exchange rate oracle where the price is still 1 wstETH = 1.2 ETH.
Within the same transaction, redeem 120 ETH0 for 120 ETH worth of another LST (rETH).
Through the arbitration process, Bob earned a total of 70 ETH.
120 ETH - 50 ETH (Cost) = 70 ETH (Profit)
Bob will bundle a transaction within the same block, coupled with front-running/high priority fee, and flash-loan to ensure that the exploit succeeds before the DAOCollateral is paused.
Loss of assets, as mentioned in the scenario above.
No response
Some on-chain deviation validation must be implemented for ETH0 to guard against this risk. As mentioned earlier, monitoring the price off-chain, and reacting by submitting pause or countermeasure transaction on-chain is not going to work because there is no guarantee that the transaction will be executed immediately. Anyone can front-run the transaction, and the arrangement of transactions is decentralized and not guaranteed in any manner on Ethereum.
The following are some of the possible solutions:
Solution 1 - Cross-check with market price
Automatically pauses if the wstETH exchange rate deviates from the market price (wstETH Chainlink's price feed) by certain threshold. For instance, within the AbstractOracle.getPrice()
or AbstractOracle._checkDepegPrice()
function, it can implement logic to perform a deviation check.
Assume Chainlink's stETH or wstETH price feed reports a market price of 0.5 due to a mass slashing or a major hack event observed on LIDO validators. The Chainlink reported market price dropped from earlier 1.2 to the current 0.5.
The deviation check will compare the exchange rate/price fetches from LIDO's wstETH contract, and it will detect that some abnormal or black-swan events have occurred and automatically revert the transaction. Note that the LIDO's wstETH contract might not always reflect the latest market price due to some delay in updating the oracle.
Solution 2 - Cross-check with expected price
This approach is adopted by AAVE (See here). LST is expected to grow at a rate of around 5% annually. Thus, if the exchange rate returned from the LIDO's wstETH contract deviates from this, it might indicate that the exchange rate might be manipulated or something has gone wrong, and counter-measures need to be done (in AAVE case, it will cap the price to the maxRatio
.)