Due to an inefficient mechanism of fee/collateral distributions for pool holders in LiquidationPool, liquidations will be broken after a moderately large number of holders.
This issue is mentioned in the list of known issues, but its severity is underestimated. The protocol couldn't be acknowledged about critical issues.
The main invariant of collateralised stablecoins is: Issued stable coin value <= collateral value * collateral factor (or euro value < collateral value / collateralRate in terms of The Standard protocol), where 0 <= collateral factor <= 1. This invariant should be valid both for each position and for the whole protocol.
There are two cases of invariant break for a position:
collateral value * collateral factor < Issued stable coin value <= collateral value - in such cases, the position is liquidated, collateral is sold, and its value is enough to repay (burn) all issued stablecoins.
Issued stable coin value > collateral value - in such cases, the position is also liquidated, collateral is sold, but its value is not enough to repay (burn) all issued stablecoins:
X - issued stablecoins, Y - repaid and burnt during liquidation stablecoins where Y < X. X-Y is the protocol's bad debt. It means if all users close their positions, X-Y stablecoins are still issued. But this amount is backed by nothing.
When the protocol has bad debt, the fair price of a stablecoin = (Issued stablecoins - Bad debt) / Issued stablecoins and it is < 1. It means that the stablecoin tends to be unpegged.
To return the peg, the protocol must buy stablecoins from the market and burn them. It means that Bad debt is the direct protocol loss.
Declared protocol Compatibilities: Any EVM chains with live Chainlink data feeds and live Uniswap pools.
A lot of EVM blockchains have a block gas limit of several tens of millions.
During liquidations (LiquidationPoolManager::runLiquidation), methods LiquidationPool::distributeFees and LiquidationPool::distributeAssets are called. There are loops by holders array in these methods. There is no limit for holders amount but even on quite a small holders amount (several hundreds) LiquidationPoolManager::runLiquidation will require gas more than the block limit on many EVM chains.
PoC. This test should be run with hardhat blockGasLimit: 20000000000 and should be placed in test/liquidationPoolManager.js inside describe('runLiquidation', async () => { block
Output:
It shows that the gas usage of LiquidationPoolManager::runLiquidation transaction increases linearly and even several hundred holders with a very small amount of staked EURO/TST will lead to a huge liquidation transaction gas amount. Which will lead to a permanent DDoS of liquidations (until upgrade).
Even in Arbitrum with its huge block gas limit, sooner or later liquidation transaction cost will be higher than the profit from liquidations.
Broken/delayed liquidations on a falling market will lead to loss of protocol funds due to undercollateralisation of minted EUROs.
Manual review
Fee and assets distributions must be totally rewritten. A scheme like in Convex or Shiba TopDog should be used.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.