Subiecte populare
#
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.
Bine ați revenit la Sherlock's Vulnerability Spotlight, unde evidențiem o vulnerabilitate de impact descoperită în timpul unui audit Sherlock.
Săptămâna aceasta, examinăm un calcul incorect al nivelului de garanție găsit în concursul @plaza_finance de @0xadrii, @KupiaSecurity, @f,
@farman1094_ și @0xnovaman33.

Rezumatul vulnerabilității:
În getRedeemAmount(...), contractul calculează nivelul de garanție pentru răscumpărările BOND folosind starea post-tranzacționare:
Codul curent (vulnerabil)
collateralLevel =
((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRECIZIE)
/ ((bondSupply - depositAmount) * BOND_TARGET_PRICE);
Deoarece prețul de răscumpărare folosește apoi acest nivel de garanție estimat pentru a decide dacă să plătească prețul maxim (100 USD), un atacator poate cumpăra BOND la rate de creare mixte (uneori reduse) până când nivelul de garanție (curent) scade ≤ 1,2 și apoi răscumpără toate BOND la limita de 100 USD - calculând cu un depositAmount creat care împinge nivelul de garanție estimat înapoi peste 1,2. Acest lucru permite atacatorului să extragă ETH ("spread-free risk") până când nivelul actual de garanție al pool-ului atinge pragul.
Pașii de atac:
1) Faza de configurare
Parametri de exemplu de bazin:
- poolReserve = 120 ETH, bondSupply = 3000, levSupply = 200, preț ETH = 3075 USD
Reguli de prețuri:
Creați (cumpărați) OBLIGAȚIUNI:
- Dacă collateralLevel ≤ 1.2: creationRate = tvl * 0.8 / bondSupply
- Altfel: creationRate = 100 USD
Răscumpărați (vindeți) OBLIGAȚIUNI:
- Dacă garanția estimatăNivel ≤ 1.2: redeemRate = tvl * 0.8 / bondSupply
- Altfel: redeemRate = 100 USD
2) Faza A – Cumpărați OBLIGAȚIUNI la rate mixte/reduse
- Cumpărați BOND în timp ce monitorizați (curent) collateralLevel = tvl / (bondSupply * 100).
- Prima cumpărare are loc în timp ce collateralLevel > 1,2 → se apropie de 100 USD per BOND.
- Achizițiile ulterioare împing collateralLevel curent sub 1,2 → monetă la o rată de creare redusă (de exemplu, ~ 94,07 USD), acumulând un sold mare de obligațiuni ieftin.
3) Faza B – Răscumpărați toate OBLIGAȚIUNILE la prețul maxim
- Răscumpărare apel(BOND, depositAmount = atacantBondBalance, ...)
- Contractul calculează nivelul estimat al garanției folosind starea post-răscumpărare (bondSupply - depositAmount) și (tvl - depositAmount * 100) și (în exemplu) obține o valoare > 1,2
- Deoarece valoarea estimată depășește pragul, redeemRate este setat la maximum 100 USD, permițând atacatorului să încaseze toate OBLIGAȚIUNILE acumulate la 100 USD
4) Realizarea profitului
- Diferența dintre achizițiile reduse și vânzările de 100 USD produce profit net ETH.
- În cifrele PoC: cheltuirea a 60 ETH în două achiziții returnează ~61,89 ETH la răscumpărare → ~1,89 ETH profit.
- Atacatorul poate itera până când nivelul actual de garanție al pool-ului scade la ~1,2, extrângând aproximativ: extragibile USD ≈ ethPrice × poolReserve − 120 × bondSupply
Care este impactul?
Extragerea directă a fondurilor / scurgerea valorii: Atacatorul emite la rate reduse și răscumpără la 100 USD, sifonând ETH din fond.
Nelimitat până la prag: Poate continua până când nivelul actual de garanție al pool-ului se micșorează la ≈ 1,2.
Inconsecvența sistemică a prețurilor: Creează arbitraj pentru care utilizatorii onești plătesc prin rezerve/rezultate mai proaste.
Cauza principală:
Utilizarea stării post-tranzacționare pentru răscumpărarea prețurilor
Codul calculează collateralLevel ca și cum răscumpărarea a avut loc deja:
utilizări (tvl - depositAmount*100) și (bondSupply - depositAmount)
collateralLevel =
((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRECIZIE)
/ ((bondSupply - depositAmount) * BOND_TARGET_PRICE);
1. Acest lucru permite unui atacator să aleagă depositAmount astfel încât nivelul estimat să depășească pragul (> 1.2), deblocând redemptionRate de 100 USD, chiar și atunci când starea curentă a pool-ului nu ar justifica acest lucru.
2. Limitarea pragului pe o metrică manipulată
Decizia privind plafonul de 100 USD depinde de acest nivel de garanție estimat manipulabil, mai degrabă decât de nivelul actual (pre-tranzacționare), permițând jocul de preț.
Atenuarea:
Calculați prețul de răscumpărare din starea curentă a pool-ului, nu din soldurile estimate post-răscumpărare. Remedierea sugerată de proiect este corectă:
- collateralLevel = ((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRECIZIE)
- / ((bondSupply - depositAmount) * BOND_TARGET_PRICE);
+ collateralLevel = (tvl * PRECIZIE) / (bondSupply * BOND_TARGET_PRICE);
Întărire suplimentară (recomandată):
1. Monotonia prețului: Asigurați-vă că prețul de răscumpărare nu crește pe măsură ce depositSuma crește (fără "vindeți mai mult, obțineți un preț unitar mai bun").
2. Prețuri bazate pe invariante: Derivați creați/răscumpărați dintr-un singur invariant, astfel încât simetria de cumpărare/vânzare să prevină arbitrajul unilateral.
3. Verificări de alunecare: Solicitați rate minime/maxime furnizate de utilizator atât pentru creare, cât și pentru valorificare.
4. Cap & throttle: Limite de răscumpărare per tx și per bloc pentru a limita daunele dacă se apropie pragurile.
5. Consecvență între căi: Aliniați căile de creare și răscumpărare pentru a utiliza aceeași definiție a nivelului de garanție (numai starea curentă).
Suntem mândri că am ajutat la asigurarea @plaza_finance prin această descoperire.
Când trebuie neapărat să fie sigur, Sherlock este alegerea potrivită.
3,27K
Limită superioară
Clasament
Favorite

