# Votre Premier Bug Bounty — Guide Pratique
Vous avez trouvé un bug. Maintenant il faut le reporter. Voici comment maximiser vos chances de paiement.
Étape 1 : Choisir un Programme
Immunefi
Focus smart contracts. Bounties jusqu'à $10M+.
Avantages :
- Payouts rapides (médiane 7 jours)
- Triagers spécialisés (comprennent Solidity)
- KYC léger
Inconvénients :
- Compétition élevée (programmes populaires = auditeurs pro)
- Scope parfois flou
Code4rena
Contests de 3-7 jours. Pool prize partagé.
Avantages :
- Tous les bugs Medium+ payés (pas seulement le #1)
- Pratique avec feedback de judges
- Communauté active
Inconvénients :
- Variance élevée (duplicates = share du prize)
- Payout 2-4 semaines post-contest
Sherlock
Contests + bug bounty permanent.
Avantages :
- Scope très clair (pas de "out-of-scope" surprises)
- Lead judges de qualité
Inconvénients :
- Bar de qualité élevé (judges sévères)
- Focus protocols DeFi
Étape 2 : Lire le Scope
Lisez TOUT le scope. Les rejets #1 = out-of-scope.
Exemple scope Immunefi :
In Scope
- contracts/core/*
- contracts/periphery/Router.sol
Out of Scope
- Known issues (voir GitHub issues #123, #456)
- Front-running (pas considéré un bug)
- Gas optimizations
- Centralization risks (admin peut upgrader = connu)
Impacts acceptés
Critical : Perte de funds, unauthorized mint
High : Temporary freeze, incorrect accounting
Medium : ...
Red flags :
- "Admin ruggable" (centralization) → out-of-scope
- "Slippage front-running" → connu, pas payé
- "Uninitialized proxy" dans tests/ → test code out-of-scope
Étape 3 : Confirmer le Bug Localement
Avant de submit, prouvez-le à vous-même.
// Bug trouvé : integer overflow dans depositFor
contract Vault {
mapping(address => uint256) public balances;
function depositFor(address user, uint256 amount) external {
balances[user] += amount; // ❌ Pas de check overflow (Solidity 0.7)
}
}
// PoC Foundry
function testOverflow() public {
vault.depositFor(alice, type(uint256).max);
vault.depositFor(alice, 1); // Wrap to 0
assertEq(vault.balances(alice), 0); // ✅ Alice a "déposé" mais balance = 0
// Impact : Alice peut drain les funds via withdraw
}
Étape 4 : Rédiger le Rapport
Structure Standard
# [SEVERITY] Title Court et Descriptif
Summary
1-2 phrases. Quoi, où, impact.
Vulnerability Details
Code vulnérable (snippet).
Explication technique.
Impact
Conséquences concrètes.
Chiffrez si possible (ex: "attacker peut voler 100% du TVL").
Proof of Concept
Code complet reproductible.
Instructions pour run.
Recommendation
Fix minimal.
Code si pertinent.
Exemple Concret
# [HIGH] Unchecked Arithmetic Allows Balance Inflation in depositFor
Summary
Le contrat Vault.sol utilise Solidity 0.7 sans SafeMath dans depositFor, permettant un overflow qui wrap la balance à 0, puis un withdraw pour drainer le vault.
Vulnerability Details
solidity
// Vault.sol L42
function depositFor(address user, uint256 amount) external {
token.transferFrom(msg.sender, address(this), amount);
balances[user] += amount; // ❌ Overflow possible
}
Un attacker peut :
Deposit type(uint256).max - TVL
Deposit 1 de plus → overflow à (1 - TVL)
Withdraw(1) → drains TVL du vault
Impact
High : Perte de 100% du TVL du vault (actuellement $12M sur mainnet).
Requires : attacker possède type(uint256).max tokens (impossible).
Wait, requires est impossible → actually c'est theoretical only.
Revised : Medium. Overflow possible mais économiquement non viable.
Proof of Concept
solidity
function testDepositOverflow() public {
// Setup
vault = new Vault(address(token));
token.mint(address(vault), 1000e18); // TVL
// Attacker tente overflow
token.mint(attacker, type(uint256).max);
vm.startPrank(attacker);
token.approve(address(vault), type(uint256).max);
vault.depositFor(attacker, type(uint256).max);
vault.depositFor(attacker, 1);
// Balance wrapped
assertEq(vault.balances(attacker), 0);
}
Run : forge test --match-test testDepositOverflow -vvv
Recommendation
Utiliser Solidity 0.8+ (checked arithmetic par défaut) ou SafeMath.
solidity
balances[user] = balances[user].add(amount); // SafeMath
Étape 5 : Justifier la Sévérité
Grille Standard (Immunefi)
Critical (5.0) :
- Direct theft of funds (any amount)
- Permanent freezing of funds (any amount)
- Protocol insolvency
High (4.0-4.9) :
- Theft of unclaimed yield
- Temporary freezing of funds
- Unauthorized minting
Medium (3.0-3.9) :
- Incorrect accounting (no loss)
- Griefing (gas cost to fix)
Low (2.0-2.9) :
- Contract fails to deliver promised returns (no loss)
- State not handled correctly
Pièges de Sévérité
// ❌ Faux Critical
function withdrawAll() external onlyOwner {
// "Owner peut rug" → Centralization, pas un bug
}
// ✅ Vrai Critical
function withdraw(uint256 amount) external {
// Manque check balances[msg.sender] >= amount
// → N'importe qui peut withdraw n'importe quel montant
}
// ❌ Faux High (c'est un Medium)
function stake(uint256 amount) external {
totalStaked += amount; // Manque update userStake[msg.sender]
// Impact : accounting incorrect, mais pas de perte directe
}
Étape 6 : Soumettre
Checklist Pré-Soumission
- [ ] Bug confirmé sur la bonne version du code (pas une vieille version déjà fixée)
- [ ] PoC run localement sans erreurs
- [ ] In-scope vérifié (contracts + impact)
- [ ] Pas de duplicate (chercher dans disclosed bugs)
- [ ] Sévérité justifiée avec grille du programme
- [ ] Recommendation réaliste (pas "rewrite everything")
Étiquette
✅ Bon :
- "Hi, I found a potential issue in X. PoC attached."
- Réponses rapides aux questions du triager
- Accepter un downgrade de sévérité si justifié
❌ Mauvais :
- "This is CRITICAL, pay me now"
- Spam de follow-ups (attendre 48h min)
- Argumenter sans cesse si jugé out-of-scope
Étape 7 : Attentes de Paiement
Timeline Typique
Immunefi :
J+0 : Soumission
J+2 : Premier triage
J+5 : Validation par protocol team
J+7 : Payout
Code4rena :
J+0 : Soumission (fin du contest)
J+7 : Judging phase
J+14 : Résultats publiés
J+21 : Payout
Montants Réalistes
Critical : $50k - $500k (top programs)
High : $5k - $50k
Medium : $1k - $5k
Low : $100 - $1k
(Varie énormément selon program TVL et bounty budget)
Raisons de Rejet Courantes
Conseil Final
Votre premier bounty sera probablement un Medium ou un Low. C'est OK. Vous apprenez le process.
Les Criticals viennent avec l'expérience de lire 100+ codebases et reconnaître les patterns à risque.
Continuez à hunt. Le prochain pourrait être le gros.