Populární témata
#
Bonk Eco continues to show strength amid $USELESS rally
#
Pump.fun to raise $1B token sale, traders speculating on airdrop
#
Boop.Fun leading the way with a new launchpad on Solana.
Vítejte zpět u Sherlockova článku o zranitelnosti, kde upozorňujeme na závažnou zranitelnost odhalenou během Sherlockova auditu.
Tento týden se zabýváme nesprávným výpočtem výše kolaterálu, který byl zjištěn v soutěži @plaza_finance ze strany @0xadrii, @KupiaSecurity, @f,
@farman1094_ a @0xnovaman33.

Shrnutí chyby zabezpečení:
V příkazu getRedeemAmount(...) kontrakt vypočítá úroveň kolaterálu pro odkupy BOND pomocí stavu po uskutečnění obchodu:
Aktuální kód (zranitelná)
collateralLevel =
((tvl - (částka vkladu * BOND_TARGET_PRICE)) * PŘESNOST)
/ ((bondSupply - částka vkladu) * BOND_TARGET_PRICE);
Vzhledem k tomu, že při zpětném odkupu se pak tato odhadovaná úroveň zajištění používá k rozhodnutí, zda zaplatit maximální cenu (100 USD), může útočník koupit BOND za smíšené (někdy diskontované) sazby za vytvoření, dokud (současná) úroveň kolaterálu neklesne ≤ 1,2, a poté vyplatit všechny DLUHOPISY za limit 100 USD – počítáno s vytvořenou částkou vkladu, která posune odhadovanou úroveň zajištění zpět nad 1,2. To umožňuje útočníkovi extrahovat ETH ("bezrizikový" spread), dokud aktuální úroveň kolaterálu poolu nedosáhne prahové hodnoty.
Kroky útoku:
1) Fáze nastavení
Parametry příkladu poolu:
- poolReserve = 120 ETH, bondSupply = 3000, levSupply = 200, cena ETH = 3075 $
Cenová pravidla:
Vytvořit (koupit) BOND:
- Pokud ≤ kolaterál 1,2: creationRate = tvl * 0,8 / bondSupply
- Jinak: creationRate = 100 $
Vyplatit (prodat) DLUHOPIS:
- Pokud je odhadovaný kolaterálÚroveň ≤ 1,2: redeemRate = tvl * 0,8 / dluhopisNabídka
- Jinak: redeemRate = 100 USD
2) Fáze A – Nákup dluhopisů za smíšené/diskontní ceny
- Nakupte BOND a zároveň sledujte (aktuální) kolaterálÚroveň = tvl / (bondSupply * 100).
- K prvnímu nákupu dochází, zatímco kolaterálÚroveň > 1,2 → mint poblíž 100 USD za DLUHOPIS.
- Následné nákupy stlačí aktuální úroveň zajištění pod 1,2 → mint při diskontované míře tvorby (např. ~94,07 $), čímž se levně hromadí velký zůstatek BOND.
3) Fáze B – Vyplacení všech DLUHOPISŮ za maximální cenu
- Call redeem(BOND, depositAmount = attackerBondBalance, ...)
- Kontrakt vypočítá odhadovanou úroveň kolaterálu pomocí stavu po splacení (bondSupply - depositAmount) a (tvl - depositAmount * 100) a (v příkladu) získá hodnotu > 1,2
- Protože tato odhadovaná hodnota překračuje prahovou hodnotu, redeemRate je nastavena na maximální hodnotu 100 USD, což útočníkovi umožňuje vybrat všechny nahromaděné dluhopisy za 100 USD.
4) Realizace zisku
- Rozdíl mezi diskontovanými nákupy a prodeji za 100 USD přináší čistý zisk ETH.
- V číslech PoC: utracení 60 ETH během dvou nákupů přináší ~61,89 ETH při zpětném odkupu → ~1,89 ETH zisk.
- Útočník může iterovat, dokud aktuální úroveň zajištění poolu neklesne na ~1,2, a extrahuje zhruba: extrahovatelné USD ≈ ethPrice × poolReserve − 120 × bondSupply
Jaký to bude mít dopad?
Přímá extrakce prostředků / únik hodnoty: Útočník razí za zvýhodněné sazby a vyplácí za 100 USD, čímž odčerpává ETH z poolu.
Neomezeno do prahové hodnoty: Může pokračovat, dokud se aktuální úroveň zajištění poolu nesníží na ≈ 1,2.
Systémová cenová nekonzistence: Vytváří arbitráž, za kterou poctiví uživatelé platí prostřednictvím horších rezerv/výsledků poolu.
Hlavní příčina:
Použití poobchodního stavu pro ocenění odkupu
Kód vypočítá collateralLevel, jako by k odkupu již došlo:
použití (tvl - částka vkladu*100) a (bondSupply - částka vkladu)
collateralLevel =
((tvl - (částka vkladu * BOND_TARGET_PRICE)) * PŘESNOST)
/ ((bondSupply - částka vkladu) * BOND_TARGET_PRICE);
1. To umožňuje útočníkovi zvolit depositAmount tak, aby odhadovaná úroveň překročila prahovou hodnotu (> 1,2), čímž se odemkne sazba redemptionRate 100 USD, i když by to aktuální stav poolu neodůvodňoval.
2. Bránění prahových hodnot u manipulované metriky
Rozhodnutí o stropu 100 USD závisí na této manipulovatelné odhadované úrovni kolaterálu, nikoli na aktuální (předobchodní) úrovni, což umožňuje hraní cen.
Zmírnění rizik:
Vypočítejte cenu za odkup z aktuálního stavu fondu, nikoli z odhadovaných zůstatků po vyplacení. Navrhovaná oprava projektu je správná:
- collateralLevel = ((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRECISION)
- / ((bondSupply - částka vkladu) * BOND_TARGET_PRICE);
+ collateralLevel = (tvl * PRECISION) / (bondSupply * BOND_TARGET_PRICE);
Dodatečné kalení (doporučeno):
1. Monotónnost ceny: Zajistěte, aby se cena za vyplacení nezvýšila se zvyšující se částkou vkladu (žádné "prodejte více, získejte lepší jednotkovou cenu").
2. Ceny založené na invariantech: Odvodit vytvořit/vyplatit z jednoho invariantního účtu, aby symetrie nákupu/prodeje zabránila jednostranné arbitráži.
3. Kontrola skluzu: Vyžaduje uživatelem zadané minimální/maximální sazby pro vytvoření i uplatnění.
4. Omezení a omezení: Limity pro vyplacení na výkon a na blok pro omezení škod, pokud jsou dosaženy prahové hodnoty.
5. Konzistence napříč cestami: Zarovnejte cesty pro vytváření a uplatňování tak, aby používaly stejnou definici úrovně kolaterálu (pouze aktuální stav).
Jsme hrdí na to, že jsme tímto objevem pomohli zajistit @plaza_finance.
Když je to nezbytně nutné zabezpečit, je Sherlock tou správnou volbou.
2,79K
Top
Hodnocení
Oblíbené