Rubriques tendance
#
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.
Bienvenue de nouveau dans le Spotlight sur les Vulnérabilités de Sherlock, où nous mettons en lumière une vulnérabilité impactante découverte lors d'un audit de Sherlock.
Cette semaine, nous examinons un calcul incorrect du niveau de garantie trouvé dans le concours de @plaza_finance par @0xadrii, @KupiaSecurity, @f,
@farman1094_, et @0xnovaman33.

Résumé de la vulnérabilité :
Dans getRedeemAmount(...), le contrat calcule le niveau de garantie pour les échanges de BOND en utilisant l'état post-négociation :
// code actuel (vulnérable)
niveauDeGarantie =
((tvl - (montantDépôt * PRIX_CIBLE_BOND)) * PRÉCISION)
/ ((offreBond - montantDépôt) * PRIX_CIBLE_BOND);
Parce que le prix de rachat utilise ensuite ce niveauDeGarantie estimé pour décider s'il faut payer le prix maximum (100 $), un attaquant peut acheter des BOND à des taux de création mixtes (parfois à prix réduit) jusqu'à ce que le niveau de garantie (actuel) tombe ≤ 1,2, puis racheter tous les BOND au plafond de 100 $—en calculant avec un montantDépôt conçu qui pousse le niveau de garantie estimé au-dessus de 1,2. Cela permet à l'attaquant d'extraire de l'ETH (écart "sans risque") jusqu'à ce que le niveau de garantie actuel du pool atteigne le seuil.
Étapes de l'attaque :
1) Phase de configuration
Exemple de paramètres de pool :
- poolReserve = 120 ETH, bondSupply = 3000, levSupply = 200, prix de l'ETH = 3075 $
Règles de tarification :
Créer (acheter) BOND :
- Si collateralLevel ≤ 1.2 : creationRate = tvl * 0.8 / bondSupply
- Sinon : creationRate = 100 $
Racheter (vendre) BOND :
- Si estimated collateralLevel ≤ 1.2 : redeemRate = tvl * 0.8 / bondSupply
- Sinon : redeemRate = 100 $
2) Phase A – Acheter BOND à des taux mixtes/discountés
- Acheter BOND tout en surveillant le niveau de collatéral (actuel) = tvl / (supplyBOND * 100).
- Le premier achat se produit lorsque le niveau de collatéral > 1.2 → mint près de 100 $ par BOND.
- Les achats suivants font descendre le niveau de collatéral actuel en dessous de 1.2 → mint à un taux de création réduit (par exemple, ~94,07 $), accumulant un grand solde de BOND à bas prix.
3) Phase B – Récupérer tous les BOND au prix maximum
- Appeler redeem(BOND, depositAmount = attackerBondBalance, ...)
- Le contrat calcule le niveau de collatéral estimé en utilisant l'état post-récupération (bondSupply - depositAmount) et (tvl - depositAmount * 100) et (dans l'exemple) obtient une valeur > 1.2
- Parce que cette valeur estimée dépasse le seuil, le redeemRate est fixé au maximum de 100 $, permettant à l'attaquant de retirer tous les BOND accumulés à 100 $
4) Réalisation de profit
- La différence entre les achats à prix réduit et les ventes à 100 $ donne un profit net en ETH.
- Dans les chiffres du PoC : dépenser 60 ETH sur deux achats rapporte ~61,89 ETH lors du rachat → ~1,89 ETH de profit.
- L'attaquant peut itérer jusqu'à ce que le niveau de collatéral du pool tombe à ~1,2, extrayant environ : USD extractible ≈ ethPrice × poolReserve − 120 × bondSupply
Quel est l'impact ?
Extraction directe de fonds / fuite de valeur : L'attaquant crée des jetons à des taux réduits et les échange contre 100 $, siphonnant ainsi de l'ETH du pool.
Illimité jusqu'au seuil : Peut continuer jusqu'à ce que le niveau de collatéral actuel du pool diminue à environ 1,2.
Incohérence systémique des prix : Crée un arbitrage que les utilisateurs honnêtes paient par de pires réserves/résultats du pool.
La cause profonde :
Utilisation de l'état post-négociation pour le prix des rachats
Le code calcule le niveau de garantie comme si le rachat avait déjà eu lieu :
// utilise (tvl - depositAmount*100) et (bondSupply - depositAmount)
collateralLevel =
((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRECISION)
/ ((bondSupply - depositAmount) * BOND_TARGET_PRICE);
1. Cela permet à un attaquant de choisir depositAmount de sorte que le niveau estimé dépasse le seuil (> 1.2), débloquant le $100 redeemRate, même lorsque l'état actuel du pool ne le justifierait pas.
2. Seuil de contrôle sur une métrique manipulée
La décision du plafond de $100 dépend de ce niveau de garantie estimé manipulable plutôt que du niveau actuel (pré-négociation), permettant ainsi de manipuler les prix.
L'atténuation :
Calculez le prix de rachat à partir de l'état actuel du pool, et non des soldes estimés après le rachat. La solution suggérée par le projet est correcte :
- collateralLevel = ((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRECISION)
- / ((bondSupply - depositAmount) * BOND_TARGET_PRICE);
+ collateralLevel = (tvl * PRECISION) / (bondSupply * BOND_TARGET_PRICE);
Renforcement supplémentaire (recommandé) :
1. Monotonie des prix : Assurez-vous que le prix de rachat n'augmente pas à mesure que le montant du dépôt augmente (pas de "vendez plus, obtenez un meilleur prix unitaire").
2. Tarification basée sur l'invariant : Dérivez la création/le rachat d'un seul invariant afin que la symétrie d'achat/vente empêche l'arbitrage unilatéral.
3. Vérifications de glissement : Exiger des taux min/max fournis par l'utilisateur pour la création et le rachat.
4. Limite et régulation : Plafonds de rachat par transaction et par bloc pour limiter les dommages si les seuils sont atteints.
5. Cohérence à travers les chemins : Alignez les chemins de création et de rachat pour utiliser la même définition de niveau de garantie (état actuel uniquement).
Nous sommes fiers d'avoir aidé à sécuriser @plaza_finance grâce à cette découverte.
Quand il faut absolument que ce soit sécurisé, Sherlock est le bon choix.
3,26K
Meilleurs
Classement
Favoris

