Réentrance en lecture seule Conic Finance
L'Omnipool ETH de Conic avait des gardes mais supposait que Curve v2 utilisait une adresse ETH spécifique. Un CurveLPOracleV2 l'a contourné, drainant 3,2 M$.
- Date
- Victime
- Conic Finance
- Chaîne(s)
- Statut
- Fonds dérobés
Le 21 juillet 2023, la plateforme Curve-Omnipool Conic Finance a perdu 1 724 ETH (~3,2 millions de dollars) dans un exploit de réentrance en lecture seule. Le protocole avait des gardes de réentrance en place — mais ils s'appuyaient sur une hypothèse incorrecte sur comment les pools ETH Curve v2 représentent ETH en interne, permettant à l'attaquant de glisser entièrement au-delà du garde.
Ce qui s'est passé
L'Omnipool ETH de Conic agrégeait les dépôts utilisateurs sur plusieurs pools de liquidité Curve pour maximiser le rendement. Pour valoriser les tokens LP déposés, Conic utilisait son contrat CurveLPOracleV2 — un oracle récemment déployé qui lisait les pools Curve sous-jacents pour calculer la juste valeur.
La garde de réentrance dans l'oracle était conditionnelle sur une méthode _isETH() qui retournait true si l'une des pièces du pool était l'adresse ETH canonique (0xeeeeeeee...eeeeeeee). Pour les pools correspondant à cette vérification, le contrat acquérait un verrou de réentrance avant de lire l'état. Pour les pools ne correspondant pas, il sautait le verrou.
L'erreur fatale : les pools Curve v2 qui détiennent ETH utilisent l'adresse WETH en interne, pas l'adresse ETH canonique. La méthode _isETH() retournait false pour ces pools, et le contrat procédait sans le verrou de réentrance.
L'attaque :
- Emprunt flash de 20 000 stETH.
- Initiation d'une série de swaps via le pool Curve rETH qui l'a mis dans un état d'exécution partielle.
- En plein exécution — pendant que le pool rETH était internement incohérent — appel de l'oracle Conic pour lire le prix du token LP rETH.
- L'oracle, sans la garde de réentrance, a lu l'état mi-swap manipulé et retourné un prix incorrect (gonflé) pour les tokens LP rETH.
- Dépôt et retrait de positions Conic au taux gonflé, mintant près du double des tokens cncETH pour la même valeur de dépôt.
- Boucle de l'opération, drainage des fonds depuis l'Omnipool, remboursement du prêt flash.
Vol net : 1 724 ETH (~3,2 M$).
Conséquences
- Conic a mis en pause l'Omnipool et publié un post-mortem détaillé.
- L'équipe a annoncé un plan d'indemnisation financé par les revenus du protocole.
- Le CurveLPOracleV2 a été patché pour utiliser la logique de réentrance correcte WETH-aware.
- L'exploit a révélé que le scope de l'audit n'avait pas inclus CurveLPOracleV2 — le contrat avait été déployé après l'audit le plus récent et le même problème de réentrance avait été précédemment identifié et corrigé dans les versions antérieures de l'oracle, mais réintroduit quand V2 a été écrit.
Pourquoi c'est important
L'incident Conic Finance est un cas d'école pour deux modes de défaillance composés :
-
La réentrance en lecture seule est plus difficile à repérer que la réentrance en écriture. La plupart de l'éducation sur la réentrance se concentre sur les attaques qui mutent l'état pendant la réentrée — les gardes checks-effects-interactions se prémunissent spécifiquement contre cela. La réentrance en lecture seule — où la fonction réentrée ne lit que l'état, mais cet état est en pleine mutation — glisse au-delà de l'analyse intuitive parce que « on ne fait que lire » semble sûr. Le
remove_liquidityde Curve v1 est une source particulièrement fertile de bugs de réentrance en lecture seule que les intégrations d'oracle ultérieures manquent à répétition. -
Les bugs corrigés réémergent dans le nouveau code. L'oracle antérieur de Conic avait été audité et corrigé contre la même classe de réentrance ; l'oracle V2, écrit de zéro par la même équipe, a réintroduit le bug parce qu'il ne faisait pas partie du scope d'audit. Le schéma récidive partout où une équipe livre une « réécriture v2 » d'un contrat qui avait été durci en v1 — la connaissance institutionnelle sur les vulnérabilités spécifiques connues ne se transfère pas toujours à travers la réécriture.
La réponse défensive est cohérente : chaque intégration d'oracle qui lit depuis l'état d'un autre protocole doit explicitement gérer la surface de réentrance connue de ce protocole, et toute réécriture d'un contrat précédemment audité doit inclure une ré-audit de la classe de bug spécifique que la correction originale a adressée. Les 3,2 M$ de Conic sont le prix de sauter ces étapes.
Sources & preuves on-chain
- [01]halborn.comhttps://www.halborn.com/blog/post/explained-the-conic-finance-hack-july-2023
- [02]coindesk.comhttps://www.coindesk.com/tech/2023/07/21/defi-protocol-conic-finance-hacked-for-1700-ether
- [03]immunebytes.comhttps://immunebytes.com/blog/conic-finance-detailed-hack-analysis-july-21/