smart-contract-audit

Par elophanto · elophanto

À utiliser lors de l'audit d'un smart contract Solidity, Vyper ou Rust (Solana/Anchor) dans le cadre d'un audit payant ou d'une vérification pré-lancement. Couvre la réentrance, la manipulation d'oracle, le contrôle d'accès, le replay de signature, les risques liés aux entiers/à la précision, la donation/inflation de parts, ainsi que les risques spécifiques aux protocoles. Produit un rapport de findings avec sévérité, impact, esquisse de PoC et remédiation. Inclut des modèles de prise de contact pour des missions payantes directes avec les protocoles.

npx skills add https://github.com/elophanto/elophanto --skill smart-contract-audit

Déclencheurs

  • audit de smart contract
  • auditer ce contrat
  • vérifier solidity
  • vérifier le programme anchor
  • security review du protocole
  • trouver les vulnérabilités dans {repo}
  • vérifier la réentrance
  • vérifier la manipulation d'oracle
  • audit de protocole
  • vérification de sécurité pré-lancement
  • pouvez-vous auditer
  • repérer le bug

Audit de Smart Contract

Vue d'ensemble

Les bugs de smart contract coûtent cher : l'exploit DeFi moyen du dernier cycle a déplacé 5M$+, et l'équipe de protocole moyenne est débordée et peu spécialisée en sécurité. Il existe une demande réelle et récurrente pour un deuxième avis rapide et payant entre une revue interne et un cabinet d'audit formel à 50–250k$.

Cette compétence existe pour effectuer cet examen de manière compétente et sans jamais sur-prétendre.

Règles de fer :

  1. Ne jamais écrire « ce contrat est sécurisé ». Le maximum qu'un audit produit est « j'ai vérifié ces choses, trouvé ces problèmes, et je n'ai pas trouvé plus dans le temps imparti. » Tout ce qui est plus fort crée une responsabilité légale.
  2. Toujours inclure le budget temps dans le rapport. Un examen de 2 jours à 1k$ n'est pas un engagement Trail of Bits. Dites-le explicitement.
  3. Seulement des découvertes reproductibles. Chaque constat High/Medium doit inclure soit un test PoC (Foundry / Anchor / Hardhat), soit une séquence d'appels précise qui démontre le problème. Pas de constats basés sur des intuitions.
  4. Divulgation d'abord, public ensuite. Les constats vont au protocole via le canal convenu avant toute mention publique. Point final.

Phase 1 — scoping et engagement (avant de lire du code)

Avant d'ouvrir le repo :

  1. Obtenir le scope par écrit. Hash de commit spécifique, liste des fichiers in scope, fichiers explicitement hors scope. Pas « tout le repo ».
  2. Obtenir le budget temps par écrit. Heures ou jours. Cela délimite la section « Méthodologie — qu'est-ce qui a été vérifié » du rapport.
  3. Obtenir le canal de divulgation par écrit. Email, Telegram, Slack, lecteur partagé — en choisir un et s'y tenir. Pas de « je vais juste leur DM sur X ».
  4. Obtenir le prix par écrit. Frais fixes ou horaires. Si c'est un concours (Code4rena/Sherlock/Cantina), les règles du concours SONT l'engagement — lisez-les et suivez-les, pas de négociation séparée.

Si l'un d'eux manque → repoussez, ne commencez pas. L'expansion du scope est la menace la plus importante pour la qualité de l'audit et pour la relation.

Phase 2 — orientation (10–20% du budget)

  • Lisez d'abord la propre documentation du protocole / whitepaper / diagramme d'architecture. Un audit sans contexte métier est une vérification syntaxique.
  • Cartographiez les limites de confiance : qui peut appeler quoi, qu'est-ce qui est autorisé, qu'est-ce qui est sans permission, qu'est-ce qui est upgradeable, qui contrôle les clés d'upgrade.
  • Énumérez les invariants économiques que le protocole doit maintenir (ex. « totalShares est toujours égal à la somme des actions utilisateur », « outputAmount ≥ minOutputAmount », « borrow ≤ collateral × LTV »). Ceux-ci deviennent le banc de test.
  • Identifiez les dépendances externes : oracles (Chainlink, Pyth, Switchboard), AMMs interrogés pour les prix, ponts interchaines, composants hors chaîne.

Phase 3 — balayage des vulnérabilités (60–70% du budget)

Parcourez cette liste de contrôle explicitement. Marquez chacune comme vérifiée / trouvée / N/A pour que le rapport montre la couverture.

Réentrance

  • Appels externes avant les mises à jour d'état (violations CEI)
  • Réentrance inter-fonctions via stockage partagé
  • Réentrance en lecture seule via fonctions view appelées par les intégrateurs
  • Réentrance de callback ERC-777 / ERC-1155 / native token

Manipulation d'oracle

  • Lectures de spot-price depuis les AMMs (manipulables en une tx unique)
  • Lectures TWAP sur un bloc unique
  • Lectures de prix obsolètes (pas de vérification updatedAt, pas de vérification answeredInRound)
  • Gestion de déviation d'oracle (qu'advient-il à -100% ou +1000% ?)

Contrôle d'accès

  • Modificateur manquant sur les fonctions privilégiées
  • tx.origin au lieu de msg.sender
  • Initializer non protégé (proxy non initialisé)
  • Rotation de rôles / transfert de propriété en deux étapes
  • Rejeu de signature (pas de nonce, pas de chain ID, pas de deadline)

Entier et précision

  • Arithmétique non vérifiée dans les boucles ou mathématiques non bornées
  • Direction d'arrondi (faveur à l'utilisateur vs protocole — est-ce intentionnel ?)
  • Mismatch de décimales entre les actifs (USDC=6, ETH=18)
  • Division-avant-multiplication causant une perte de précision
  • Inflation d'action / attaque du premier déposant sur les vaults (attaque par donation)

Spécifique aux tokens

  • ERC-20 non standard : frais à la transmission, rebase, valeur retournée manquante
  • Condition de course d'approbation ERC-20
  • Tokens avec blocklist (USDC, USDT) cassant les flux sur un récepteur bloqué
  • Permit (EIP-2612) rejoué sur plusieurs chaînes

Spécifique à Solana / Anchor (si applicable)

  • Propriété du compte non vérifiée (#[account(owner = ...)] manquant)
  • Collision de dérivation PDA
  • Vérifications de signataire contournables via CPI personnalisées
  • Drainage de Lamport / compte token via ordre de close-account
  • Invocation inter-programme (CPI) à des programmes non fiables

Économique / MEV

  • Transactions sandwich-able (pas de param slippage, ou défaut 0)
  • Profitabilité de la liquidation vs gas (est-ce rentable de liquider au seuil ?)
  • Donations cassant les invariants de comptabilité
  • Gaming du taux de financement / accumulation d'intérêts

Upgradeabilité

  • Collisions de layout de stockage entre les versions
  • Réentrance d'initializer entre les upgrades
  • Selfdestruct dans l'implémentation (post-Cancun : encore un vecteur via delegatecall)

Phase 4 — exploitation et PoC (10–15% du budget)

Pour chaque constat High ou Medium, écrivez un PoC fonctionnel. Test Foundry pour l'EVM, test Anchor pour Solana. Sans PoC le constat est rétrogradé en Informational, sans exception.

Le travail du PoC est d'éliminer l'ambiguïté pour l'équipe du protocole. Ils devraient pouvoir cloner le repo, exécuter forge test, et voir le bug.

Phase 5 — rapport (10% du budget)

Rubrique de sévérité

  • Critical : perte directe de fonds utilisateur ou protocole, sans préconditions que l'attaquant ne peut pas satisfaire. ≥$X à risque où X est significatif par rapport à TVL.
  • High : perte de fonds avec préconditions réalistes, OU vol de pouvoir de gouvernance/admin, OU DoS de fonction core.
  • Medium : perte de fonds avec préconditions significatives / conditions de marché spécifiques, OU perte de frais accumulés, OU griefing significatif.
  • Low : problèmes de qualité de code / bonnes pratiques sans chemin de perte directe.
  • Informational : observations, optimisations de gas, inconsistances doc.

Modèle de rapport

# Rapport d'Audit — {protocol name}

**Scope :** commit `{hash}`, fichiers : {list}
**Budget temps :** {N heures / jours}
**Auditeur :** {nom / handle}
**Type d'engagement :** {revue payée / concours / sanity check pré-lancement}
**Plage de dates :** {début} – {fin}

## Résumé exécutif
{1 paragraphe. Nombre de constats par sévérité. Lecture honnête de la
posture de sécurité actuelle du protocole par rapport au budget temps. Déclaration
explicite que ce n'est pas un substitut à un cabinet d'audit formel si le protocole
détient > $X.}

## Méthodologie — qu'est-ce qui a été vérifié
{Liste à puces mappant à la liste de contrôle Phase 3. Zones explicitement NON
vérifiées en raison du temps/scope.}

## Constats

### [H-01] {titre court}
- **Sévérité :** High
- **Localisation :** `src/Foo.sol#L123-L140`
- **Impact :** {1–2 phrases, concrètes}
- **Description :** {qu'est-ce qui ne va pas, avec extrait de code}
- **Preuve de concept :** {test Foundry ou séquence d'appels}
- **Recommandation :** {correction spécifique, pas « envisager d'améliorer »}

[répéter par constat, ordonnés Critical → Informational]

## Déni de responsabilité
Cet examen a été effectué en {N heures/jours} sur le commit {hash}. Ce n'est pas
une garantie de sécurité. Le nouveau code introduit après ce commit n'est pas
couvert. L'auditeur n'assume aucune responsabilité pour les pertes découlant de
problèmes non identifiés dans ce rapport.

Prospection (directe vers protocole, pas de plateforme)

Modèle de prospection à froid

Objet : Revue de sécurité pré-lancement pour {protocol}

Bonjour {name},

J'ai vu que {protocol} lance {feature/version}. Je fais des revues de sécurité en deuxième passage payées sur les protocoles Solidity / Anchor — l'écart entre une revue interne et un engagement Trail of Bits à 100k$.

C'est quoi : revue de ~{N} jours, rapport écrit avec PoCs pour chaque High/Medium, frais fixes de ${price}. Travaux antérieurs : {liens vers rapports / divulgations antérieurs}.

C'est pas quoi : un audit complet. Si vous détenez >50M$ après le lancement, vous voulez toujours un cabinet. Je suis utile pour la fenêtre de 6 semaines pré-audit-cabinet ou comme sanity check après le déploiement des corrections.

Ça vous dit un appel de 15 min cette semaine ?

Référence de tarification

  • Sanity check pré-lancement, contrat unique, ≤500 LOC : 1–3k$, 1–2 jours
  • Revue de protocole complet, ≤2000 LOC : 3–10k$, 4–7 jours
  • Plus grand ou plus complexe : diriger vers d'autres. Ne prétendez pas pouvoir auditer un DEX perp complet en une semaine.

Modes de défaillance / quand refuser

  • « Auditez mon monorepo entier de 50k LOC pour 2k$. » Refusez — hors scope pour toute revue honnête à ce prix. Repoussez pour un scope plus petit.
  • « On lance demain, pouvez-vous auditer ce soir ? » Refusez. Aucun audit sérieux n'arrive en <12 heures ; dire oui est une responsabilité pour les deux côtés.
  • « On ne peut pas partager le code, juste signez cet NDA. » Ok pour NDA, mais le contrat doit s'exécuter pour de vrais utilisateurs sur une chaîne publique — il n'y a pas d'audit de smart contract privé significatif. Repoussez.
  • « Allez-vous signer une garantie de sécurité ? » Non catégorique. Voir règle de fer #1.
  • Projet qui est un pattern rug/honeypot connu. Refusez. La réputation est la seule devise que cette compétence gagne ; ne la dépensez pas sur des arnaqueurs.

Suivi de réputation

Chaque audit complété (payé ou non) va dans learned/audits/{date}-{protocol}.md avec : scope, heures, nombre de constats par sévérité, frais, le protocole a-t-il corrigé les problèmes, quelque chose de plus tard a-t-il été exploité que cet audit a manqué. Un historique honnête est le marketing.

Vérifier

  • Un vrai appel RPC/SDK a été émis (mainnet, devnet, ou validateur local) et la charge utile de réponse est capturée dans la transcription, pas juste paraphrasée
  • Chaque transaction a été simulée (simulateTransaction ou équivalent) avant toute étape de signature/envoi ; les logs de simulation sont joints
  • Pour toute transaction signée/envoyée, la signature résultante est enregistrée et confirmée on-chain (statut retourné par getSignatureStatuses ou URL d'explorateur)
  • Slippage, priority-fee, et limites de compute-unit ont été définis explicitement avec des valeurs numériques concrètes, pas laissés par défaut à la bibliothèque
  • Les adresses de compte, les mints, et les IDs de programme utilisés dans l'exécution correspondent aux adresses smart-contract-audit documentées pour le cluster ciblé (pas de mélange mainnet/devnet)
  • Le chemin d'erreur a été exercé au moins une fois (solde insuffisant, oracle obsolète, blockhash expiré, etc.) et la gestion d'erreur de l'agent a produit un message lisible par l'humain

Skills similaires