USDT/USDC depeg event will pit both makers at a highly risky position due to arbitrage
Summary
The issue has two highlights:
There are two types of Makers in Perpetual (as of the contest scope), the Oracle Maker quoting based on the oracle price alongside its own position, and the Spot Hedge Based Maker quoting based on external AMMs.
The Pyth oracle price only has feeds for ASSET/USD, but not ASSET/USDT or ASSET/USDC. Source.
While the peg normally does not matter for a perpetual exchange (as it is only used to calculate the PnL), we show that in the event of a stablecoin depeg, there is an arbitrage route through the two makers that will pit both makers at a highly risky position. Furthermore, we also show that at least one of the makers will incur damage due to the following price movement.
We also show some other possible impacts on the Spot Maker in the event of a depeg.
Vulnerability Detail
First of all, we note that Pyth does not have feeds for ASSET/USD, but not ASSET/USDT or ASSET/USDC. That means that during a depegging event, assets will be wrongly priced.
For a perpetual exchange, this is not a problem yet, as collaterals do not need to be pegged, but is only used as a denominator/collateral asset to settle PnLs.
However since the Oracle Maker quotes price based on Oracles, and the Spot Hedge Based Maker quotes price based on AMM prices, there is a sizeable price discrepancy between the two makers in the event of a stablecoin depeg. An arbitrage between this price discrepancy will:
Make a direct profit on one of the makers.
Opens two opposite positions on two different makers, exposing at least one of them to heavy loss when settled.
This issue assumes that the market in question has both types of makers, which is how it is described in the audit doc's ClearingHouse sequence diagram.
Proof of concept
We directly describe this scenario using an example of a depeg event.
Assuming the Uniswap pool is sufficiently liquid (as it should be). In a normal operation without a depeg:
ETH price = 1000, USDC price = 1
Alice places a -1 ETH order (short 1 ETH)
Spot Hedge is able to swap 1 ETH to 1000 USDC, quotes that as the opposite amount
Position is opened:
Alice -= 1 ETH, notional += 1000 USD
Maker += 1 ETH, notional -= 1000 USD
Now what happens during a depeg here is that:
ETH price = 1000, USDC price = 0.95
Alice places a -1 ETH order (short 1 ETH)
Spot Hedge is able to swap it to 1050 USDC, quotes that as the opposite amount
Position is opened:
Alice -= 1 ETH, notional += 1050 USD
Maker += 1 ETH, notional -= 1050 USD
The arbitrage happens when the position is closed using the Oracle maker:
ETH price = 1000, USD price = 1
Alice places a +1 ETH order (long 1 ETH, closing her old order)
Oracle quotes a price of 1000
Position is opened
Alice += 1 ETH, notional -= 1000 USD
Maker -= 1 ETH, notional += 1000 USD
The final outcome is:
Alice profits 50 USDC instantly
Spot maker has an open 1 ETH long, +1050 USD notional
Oracle maker has an open 1 ETH short, -1000 USD notional
In other words:
The two makers have a total open notional of non-zero, implying a non-zero PnL, thereby some funds have been taken by Alice from the Makers by arbitraging.
The two makers have been opened opposite positions, therefore any kind of price movement will impact one of the makers.
When the peg is returned, the damage is not reversed. Since the AMM and Oracle price are roughly equal during a peg, there is no incentives nor a potential arbitrage to reverse the two makers' positions. It will take another depeg in the opposite direction to get a natural movement in the de-risking position, which is highly unlikely to occur soon enough right after the initial depeg event.
While pitting opposite positions is technically possible even without the depeg, the attacker will incur loss due to price impacts by AMM, and the price spread by the Oracle Maker. However with the depeg, there is a large price discrepancy between the two makers (i.e. oracle price and external AMM price), and this "attack" becomes profitable in the form of a natural arbitrage scenario, albeit with the same risk impact, which is the actual problem here.
Other impacts
There are also other impacts that affects the Spot Based Maker, due to its reliant on both the oracle price and AMM price:
New positions may not be possible to be quoted for smaller traders, due to the depeg pushing the AMM price outside the price band (or rather, the AMM/oracle discrepancy is higher than the price band threshold).
LPs deposit/withdraw will get less value compared to market price, which is a loss.
Price discrepancy also creates an arbitrage scenario for LPs by circling between withdrawing and depositing.
Liquidation may be discouraged, as the liquidator can only instantly close out the liquidated position on the Spot Maker (for Oracle Maker, they must use the relayer). If the depeg falls outside the price band protection, it may not be possible to take profit, and liquidations are discouraged. Lack of liquidations will likely generate bad debt on the protocol as a whole.
Impact
During a stablecoin depeg, there is an arbitrage scenario that:
Takes funds away from the Makers in the form of realized PnL.
Pits two makers at a highly risky, but also opposite, positions. Any price movement will then force one of the makers to realize heavy loss.
There are also several other impacts mentioned above.
Also affects any occurence of _getPrice() throughout the codebase.
Tool used
Manual review
Recommendation
The Pyth Oracle Adapter (or any instance of _getPrice() in general) should combine two feeds, ASSET/USD and the inverse of COLLATERAL/USD to ensure accurate pricing against the external market, preventing the price discrepancy in a depeg event.
PUSH0
medium
USDT/USDC depeg event will pit both makers at a highly risky position due to arbitrage
Summary
The issue has two highlights:
While the peg normally does not matter for a perpetual exchange (as it is only used to calculate the PnL), we show that in the event of a stablecoin depeg, there is an arbitrage route through the two makers that will pit both makers at a highly risky position. Furthermore, we also show that at least one of the makers will incur damage due to the following price movement.
We also show some other possible impacts on the Spot Maker in the event of a depeg.
Vulnerability Detail
First of all, we note that Pyth does not have feeds for ASSET/USD, but not ASSET/USDT or ASSET/USDC. That means that during a depegging event, assets will be wrongly priced.
For a perpetual exchange, this is not a problem yet, as collaterals do not need to be pegged, but is only used as a denominator/collateral asset to settle PnLs.
However since the Oracle Maker quotes price based on Oracles, and the Spot Hedge Based Maker quotes price based on AMM prices, there is a sizeable price discrepancy between the two makers in the event of a stablecoin depeg. An arbitrage between this price discrepancy will:
This issue assumes that the market in question has both types of makers, which is how it is described in the audit doc's ClearingHouse sequence diagram.
Proof of concept
We directly describe this scenario using an example of a depeg event.
Assuming the Uniswap pool is sufficiently liquid (as it should be). In a normal operation without a depeg:
Now what happens during a depeg here is that:
The arbitrage happens when the position is closed using the Oracle maker:
The final outcome is:
In other words:
When the peg is returned, the damage is not reversed. Since the AMM and Oracle price are roughly equal during a peg, there is no incentives nor a potential arbitrage to reverse the two makers' positions. It will take another depeg in the opposite direction to get a natural movement in the de-risking position, which is highly unlikely to occur soon enough right after the initial depeg event.
While pitting opposite positions is technically possible even without the depeg, the attacker will incur loss due to price impacts by AMM, and the price spread by the Oracle Maker. However with the depeg, there is a large price discrepancy between the two makers (i.e. oracle price and external AMM price), and this "attack" becomes profitable in the form of a natural arbitrage scenario, albeit with the same risk impact, which is the actual problem here.
Other impacts
There are also other impacts that affects the Spot Based Maker, due to its reliant on both the oracle price and AMM price:
Impact
During a stablecoin depeg, there is an arbitrage scenario that:
There are also several other impacts mentioned above.
Code Snippet
https://github.com/sherlock-audit/2024-02-perpetual/blob/main/perp-contract-v3/src/oracle/pythOracleAdapter/PythOracleAdapter.sol#L12
Also affects any occurence of
_getPrice()
throughout the codebase.Tool used
Manual review
Recommendation
The Pyth Oracle Adapter (or any instance of
_getPrice()
in general) should combine two feeds, ASSET/USD and the inverse of COLLATERAL/USD to ensure accurate pricing against the external market, preventing the price discrepancy in a depeg event.Duplicate of #118