TP2e année11 livrables
La cagnotte, pour de vrai
Ton premier smart contract en Solidity — d'abord codé à la main dans Remix, puis construit, audité et étendu avec un agent IA (Claude + le skill ethereum-wingman). Et surtout : vérifié à chaque fois.
Par Josselyn C., prof de BTS SIO. Publié le , mis à jour le .
- Outils
- Remix (navigateur) · Claude Code + ethereum-wingman
- Déroulé
- 4 parties · ~10 h · flags A→J à rendre
- Pour qui
- SLAM, 2e année
- Durée
- 1 journée (~10 h)
- Prérequis
- Les bases de JavaScript ou de C# : variables, conditions, fonctions, classes.
- Matériel
- Un navigateur (Chrome) pour Remix, puis Claude Code installé pour la partie agentique. Aucun vrai argent.
Compétences : C1.6 Organiser son développement professionnel, C2.1 Concevoir et développer une solution applicative, C3.5 Assurer la cybersécurité d'une solution applicative
Avant de commencer
Hier tu as joué une cagnotte dans un bac à sable blockchain. Aujourd'hui tu l'écris : un vrai smart contract en Solidity, qui tient l'argent et applique sa règle tout seul. Tu vas le faire deux fois : à la main pour comprendre chaque ligne, puis avec un agent IA pour voir ce que ça change — sans jamais lui faire confiance aveuglément.
Le contrat qu'on construit
Organisateur ──déploie──▶ [ CONTRAT CAGNOTTE ]
objectif : 3 ETH
deadline : dans 2 min
Potes ──contribuent──────▶ (le contrat garde l'argent)
│
à la deadline, le contrat décide SEUL :
total ≥ objectif → verse à l'organisateur
total < objectif → rembourse chaque pote
Exactement la cagnotte d'hier — mais cette fois c'est ton code qui l'exécute, pas un bouton de démo.
Le déroulé de la journée (~10 h)
| Durée | Partie | Ce que tu fais |
|---|---|---|
| ~4 h | 1 · À la main | coder la cagnotte en Solidity de zéro, la déployer, la tester. |
| ~1 h 30 | 2 · La sécurité à la main | le piège de la reentrancy et le patron qui protège. |
| ~3 h | 3 · En agentique | installer le skill, faire auditer / générer / étendre par Claude — et tout re-tester. |
| ~1 h 30 | 4 · Confrontation & bonus | ta version vs celle de l'IA ; défis pour aller plus loin. |
Ce que tu vas apprendre
| Concept | Ce que tu sauras faire |
|---|---|
| Solidity : contrat, variables d'état, fonctions | écrire et structurer un smart contract. |
payable, msg.sender, msg.value | recevoir et envoyer de l'ETH depuis un contrat. |
require, block.timestamp, mapping | poser des règles, gérer le temps et les comptes. |
| Reentrancy & checks-effects-interactions | repérer et corriger une faille classique. |
| Développement assisté par IA (agent + skill) | générer, auditer, étendre — et vérifier du code avec un agent. |
Partie 1 · À la main
Ch.0 — Remix, Solidity, l'EVM
Avant de coder, trois mots à poser.
C'est quoi Solidity ?
Le langage dans lequel on écrit les smart contracts (ceux d'Ethereum et de dizaines d'autres blockchains). Il ressemble à du JavaScript/C# : des variables, des fonctions, des conditions. La différence : une fois déployé, ton programme vit sur la blockchain et personne ne peut le modifier.
C'est quoi l'EVM ?
L'Ethereum Virtual Machine : l'« ordinateur mondial » qui exécute ton contrat, répliqué sur des milliers de machines qui arrivent toutes au même résultat. Ton code Solidity est compilé en instructions pour l'EVM.
C'est quoi Remix ?
Un atelier tout-en-un dans le navigateur : éditeur de code + compilateur + un faux Ethereum (la « Remix VM ») avec des comptes de test à 100 ETH fictifs pour déployer et cliquer sur tes fonctions. Zéro installation.
Ouvre ton atelier
- Va sur
remix.ethereum.org(dans Chrome). - Dans l'explorateur de fichiers à gauche, dossier
contracts, clique l'icône « nouveau fichier ». - Nomme-le
Cagnotte.sol(l'extension.sol= Solidity).
Tu dois voir — un fichier vide Cagnotte.sol ouvert dans l'éditeur, au centre. C'est ta page blanche.
Partie 1 · À la main
Les bases de Solidity (à lire avant de coder)
Tu n'as jamais fait de Solidity, mais tu as déjà programmé (C# en 1re année, JavaScript en Node). Bonne nouvelle : Solidity ressemble beaucoup à ce que tu connais. Ce qui est vraiment neuf, c'est le monde blockchain autour. Voici le pont — lis cette page tranquillement, on y reviendra à chaque étape.
Ce que tu connais déjà (ça ne change pas)
| Ce que tu fais en JS / C# | En Solidity |
|---|---|
une variable : let x = 5 | uint x = 5; |
une condition : if (a > b) { … } | pareil |
une fonction : function f() { … } | function f() public { … } |
| un objet avec ses attributs/méthodes | un contract (comme une classe) |
Comme partout : chaque instruction finit par un ;, le code vit entre { }, les commentaires commencent par //, et la casse compte (total ≠ Total).
Ce qui est NOUVEAU (propre à la blockchain)
Voilà les six nouveautés qui n'existent pas en JS/C#. On les recroisera une par une ; pour l'instant, repère-les :
- Le type
address— un compte sur la blockchain, un peu comme un IBAN (42 caractères). Et les montants se comptent en wei (1 ether = 10¹⁸ wei). - L'état est permanent ET public — une « variable d'état » est écrite sur la blockchain : visible par tout le monde, et conservée pour toujours. Pas de base de données cachée.
- Les variables « magiques » — fournies automatiquement :
msg.sender(qui appelle la fonction),msg.value(combien d'ETH il envoie),block.timestamp(l'heure de la blockchain). payable— une fonction doit être marquéepayablepour accepter de l'argent. Sinon elle le refuse.require— une garde. Si la condition est fausse, tout est annulé (on dit que ça « revert »), comme un paiement bancaire refusé : rien ne reste à moitié fait.- Immuable — une fois déployé, ton code ne peut plus être modifié. Un bug reste un bug (souviens-toi de The DAO, vu hier).
Trois mots de « process »
- Compiler — traduire ton Solidity en instructions que l'EVM comprend. Au passage, ça vérifie la syntaxe (les erreurs en rouge).
- Déployer — envoyer ton contrat (une seule fois) sur la blockchain pour lui donner vie. Il reçoit alors sa propre adresse.
- Transaction & gas — toute action qui modifie l'état (contribuer, finaliser…) est une transaction : elle est signée et coûte du gas (des frais payés en ETH, qui rémunèrent le réseau). Lire une valeur (un getter) est gratuit. Sur la Remix VM, le gas est fictif : déploie et clique sans compter.
Partie 1 · À la main
Ch.1 — Le squelette du contrat
Tout contrat commence par deux lignes administratives, puis le contrat lui-même. Tape ceci :
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Cagnotte {
}
Compile une première fois
- Onglet « Solidity Compiler » (icône à gauche, le « S »).
- Vérifie que la version commence par
0.8.2x. - Clique Compile Cagnotte.sol (ou
Ctrl+S).
Tu dois voir — une pastille verte sur l'icône du compilateur. Ton contrat (vide) compile. C'est la base.
FLAG A
checkpoint
Ton squelette compile (pastille verte).
Recopie la version exacte du compilateur affichée dans Remix (ex. 0.8.26+commit…).
Partie 1 · À la main
Ch.2 — Les variables d'état
Les variables d'état (state variables) sont la mémoire permanente du contrat : elles vivent sur la blockchain tant que le contrat existe. Ajoute-les à l'intérieur des accolades :
address public organisateur;
uint public objectif;
uint public deadline;
uint public total;
bool public finalisee;
mapping(address => uint) public contributions;
Recompile (Ctrl+S) : pastille verte. On a la mémoire du contrat ; maintenant, comment on la remplit.
Ch.3 — Le constructor
Le constructor, c'est comme le constructeur d'une classe en C# — mais il s'exécute une seule fois, au moment du déploiement, et jamais plus ensuite. C'est là qu'on règle l'objectif, la deadline, et qu'on note l'organisateur. Ajoute-le sous les variables :
constructor(uint _objectifEnEther, uint _dureeEnSecondes) {
organisateur = msg.sender;
objectif = _objectifEnEther * 1 ether;
deadline = block.timestamp + _dureeEnSecondes;
}
FLAG B
investigation
Dans la doc Solidity (cherche « ether units »), trouve combien de wei valent 1 ether, et à quoi servent gwei.
1 ether = ______ wei. 1 gwei = ______ wei. À quoi sert le gwei ?
Partie 1 · À la main
Ch.4 — contribuer() : recevoir de l'ETH
Pour qu'un pote puisse envoyer de l'argent au contrat, il faut une fonction payable. Ajoute-la :
function contribuer() public payable {
require(block.timestamp < deadline, "Cagnotte terminee");
require(msg.value > 0, "Montant nul");
contributions[msg.sender] += msg.value;
total += msg.value;
}
Retiens — payable = « cette fonction peut recevoir de l'argent ». msg.value = « combien ». msg.sender = « qui ». Ce trio est le cœur de tout contrat qui manipule de l'ETH.
FLAG C
production
Ajoute une 3e règle à contribuer() : interdire une contribution supérieure à l'objectif entier (pas de « méga-don » qui remplit tout d'un coup). Écris le require toi-même.
Recopie la ligne require que tu as ajoutée.
Ch.5 — finaliser() : verser à l'organisateur
Quand la deadline est passée et l'objectif atteint, le contrat verse tout à l'organisateur :
function finaliser() public {
require(block.timestamp >= deadline, "Pas encore la deadline");
require(!finalisee, "Deja finalisee");
require(total >= objectif, "Objectif non atteint");
finalisee = true;
payable(organisateur).transfer(total);
}
Partie 1 · À la main
Ch.6 — rembourser() : rendre si c'est raté
Si l'objectif n'est pas atteint à la deadline, chaque pote peut récupérer sa mise. On fait un remboursement « à la demande » (chacun appelle pour lui-même) :
function rembourser() public {
require(block.timestamp >= deadline, "Pas encore la deadline");
require(total < objectif, "Objectif atteint");
uint montant = contributions[msg.sender];
require(montant > 0, "Rien a rembourser");
contributions[msg.sender] = 0;
payable(msg.sender).transfer(montant);
}
Recompile. Pastille verte ? Ton contrat est complet. Il fait tout : recevoir, verser, rembourser.
Ch.7 — Compiler proprement
Avant de déployer, lis les messages du compilateur. Deux niveaux :
- Erreurs (rouge) : ça ne compile pas, il faut corriger.
- Avertissements (orange) : ça compile, mais le compilateur te prévient (ex. une variable inutilisée). À lire, pas forcément à corriger.
FLAG D
debug
Dans Remix, change volontairement total >= objectif en total > objectif dans finaliser(). Déploie (Ch.8) une cagnotte d'objectif 2, contribue exactement 2 ETH, atteins la deadline, et essaie de finaliser.
Que se passe-t-il ? Pourquoi ? Remets ensuite le >= et explique la différence.
Partie 1 · À la main
Ch.8 — Déployer sur la Remix VM
Déployer = mettre ton contrat en vie sur une blockchain. Ici, une fausse, locale, pour tester sans risque.
- Onglet « Deploy & Run Transactions » (icône Ethereum, à gauche).
- Dans Environment, choisis Remix VM (ex. « Remix VM (Cancun) »). Tu vois une liste de comptes de test à 100 ETH.
- À côté du bouton orange Deploy, déplie le champ et renseigne les 2 arguments du constructor :
_objectifEnEther = 3,_dureeEnSecondes = 120. - Clique Deploy ... (transact).
Tu dois voir — en bas, sous « Deployed Contracts », ta CAGNOTTE avec une liste de boutons : contribuer (en rouge/orange = payable), finaliser, rembourser, et les getters bleus objectif, total, deadline…
Ch.9 — Jouer les deux scénarios
Scénario A — objectif raté → remboursement
- En haut, dans Value, tape
1et choisis l'unité Ether. Cliquecontribuer.totalpasse à 1 ETH (en wei). - Change de compte (menu Account en haut), remets Value = 1 Ether,
contribuerencore. Total = 2 ETH < objectif 3. - Attends ~2 minutes (la deadline). Puis clique
finaliser: ça revert (« Objectif non atteint »). Logique. - Chaque contributeur clique
rembourser→ il récupère sa mise (regarde son solde remonter).
Scénario B — objectif atteint → versement
- Re-déploie une cagnotte fraîche (objectif 3, durée 120).
- Fais contribuer plusieurs comptes pour un total ≥ 3 ETH.
- Attends la deadline, clique
finaliser: le solde de l'organisateur monte du total. Le contrat s'est vidé, tout seul.
Tu dois voir — dans les deux cas, personne n'a décidé : les require et la règle ont tranché. C'est ton code qui fait la banque.
FLAG E
checkpoint
Scénario A : quel message exact donne le revert de finaliser ? Scénario B : de combien monte le solde de l'organisateur ?
Partie 2 · La sécurité à la main
Ch.10 — Le piège de la reentrancy
Ton rembourser() remet le compteur à zéro avant d'envoyer l'argent. Pourquoi est-ce si important ? Regardons la version naïve, celle que beaucoup de débutants écrivent :
// ⚠️ VERSION DANGEREUSE — ne pas garder
function rembourserNaif() public {
require(total < objectif, "Objectif atteint");
uint montant = contributions[msg.sender];
payable(msg.sender).transfer(montant); // on ENVOIE d'abord
contributions[msg.sender] = 0; // on remet à zéro APRÈS
}
Comment l'attaque marche
Si celui qui reçoit est lui-même un contrat, recevoir de l'ETH peut déclencher du code chez lui. Ce code peut rappeler rembourserNaif() avant que la ligne = 0 ne soit exécutée. Comme son compteur n'est pas encore à zéro, il se fait rembourser une 2e fois. Puis une 3e… jusqu'à vider le contrat. C'est la reentrancy (ré-entrance), et c'est exactement la faille de The DAO en 2016 (~60 M$).
Le patron qui protège : Checks-Effects-Interactions
La règle d'or, dans cet ordre :
| Étape | Dans ton rembourser() |
|---|---|
| Checks (vérifier) | les require(...) |
| Effects (modifier l'état) | contributions[msg.sender] = 0; |
| Interactions (appeler l'extérieur) | transfer(montant); en dernier |
En mettant = 0 avant l'envoi, même si l'attaquant rappelle la fonction, son compteur vaut déjà 0 → le require(montant > 0) bloque. Ta version de départ est déjà correcte : c'est pour ça qu'on l'a écrite ainsi.
FLAG F
sécurité
Explique, avec tes mots, pourquoi mettre contributions[msg.sender] = 0; avant le transfer empêche le double-remboursement.
Partie 3 · En agentique
Ch.11 — Un copilote pour Solidity
Tu sais maintenant écrire un contrat à la main, et repérer un piège de sécurité. Dans un vrai job, tu travailleras avec un agent IA qui code à tes côtés. La règle ne change pas : tu restes le pilote, l'IA est le copilote. Tu dois pouvoir juger, corriger, et vérifier ce qu'elle produit — c'est précisément pour ça qu'on a fait la Partie 1 d'abord.
Le skill ethereum-wingman
On va donner à Claude une expertise Ethereum dédiée : ethereum-wingman (d'Austin Griffith, une figure de l'écosystème). C'est un Agent Skill : une base de connaissances (patterns, standards ERC, pièges de sécurité, bonnes pratiques) que Claude Code charge pour mieux t'aider.
Installer le skill
- Crée un dossier de travail pour ce TP (ex.
cagnotte-ia) et ouvre un terminal dedans. - Lance :
npx skills add austintgriffith/ethereum-wingman
- Ouvre Claude Code dans ce dossier. Vérifie que le skill est bien là : tape
/et chercheethereum-wingmandans la liste, ou demande simplement à Claude : « Quels skills sont disponibles ? »
FLAG G
mise en place
Capture (ou recopie) la preuve que le skill ethereum-wingman est chargé dans ton Claude Code.
Partie 3 · En agentique
Ch.12 — Faire auditer TON contrat
Premier réflexe pro : faire relire son code. Colle ta version naïve (celle du Ch.10, avec le transfer avant le = 0) et demande un audit.
Tu dois voir — l'agent, aidé du skill, doit repérer la reentrancy sur la fonction naïve et recommander le patron checks-effects-interactions (mettre l'état à zéro avant l'envoi), voire suggérer un reentrancy guard.
FLAG H
l'IA voit-elle ce que tu as vu ?
L'agent a-t-il trouvé la reentrancy ? A-t-il proposé la même correction que toi (Partie 2) ? A-t-il signalé AUTRE chose que tu n'avais pas vu ?
Ch.13 — Faire générer la cagnotte (et la vérifier)
Maintenant, demande à l'agent de produire le contrat à partir d'une spécification — comme un vrai cahier des charges.
Et surtout : tu VÉRIFIES
- Copie le contrat généré dans un nouveau fichier Remix (
CagnotteIA.sol). - Compile-le. Il compile du premier coup ? (Note : parfois non — l'IA se trompe aussi.)
- Déploie et teste les 2 scénarios, comme au Ch.9. Fait-il vraiment ce que tu as demandé ?
FLAG I
confrontation
Le contrat de l'IA compile-t-il du premier coup ? Passe-t-il tes 2 scénarios ? Cite UNE différence avec ta version à la main.
Partie 3 · En agentique
Ch.14 — Étendre et débugger avec l'agent
Étendre
Demande une amélioration utile, puis teste-la :
Recompile, redéploie, contribue, et vérifie dans les logs que l'event sort. Teste nbContributeurs().
Débugger
Casse volontairement quelque chose (ex. enlève le payable de contribuer), tente de contribuer dans Remix (ça revert), copie le message d'erreur, et demande :
Tu dois voir — l'agent explique que sans payable la fonction refuse l'ETH, et te dit de le remettre. Tu confirmes en re-testant.
FLAG J
extension & debug
Colle la ligne de ton event dans les logs Remix. Puis : quel bug as-tu fait débugger, et l'agent a-t-il trouvé juste ?
Partie 4 · Confrontation & bonus
Ch.15 — Ta version vs celle de l'IA
Mets côte à côte ton contrat écrit à la main (Partie 1) et celui généré par l'agent (Ch.13). Remplis le tableau honnêtement :
| Critère | À la main | Par l'IA |
|---|---|---|
| Compile du premier coup ? | ||
| Passe les 2 scénarios ? | ||
| Protégé contre la reentrancy ? | ||
| Lisible / commenté ? | ||
| Temps pour l'obtenir |
FLAG K
bilan critique
En 4-5 lignes : qu'apporte l'IA ? Qu'est-ce qu'elle ne remplace PAS ? Pourquoi fallait-il savoir coder à la main d'abord ?
Ch.16 — Défis bonus (pour aller plus loin)
Fini en avance ? Choisis un défi. Chacun peut prendre 1 à 2 h — de quoi occuper toute la journée.
Défi 1 — Déployer sur un vrai réseau de test (Sepolia)
Installe le wallet MetaMask, passe-le sur le réseau de test Sepolia, récupère de l'ETH de test via un faucet, puis dans Remix choisis l'environment « Injected Provider - MetaMask » et déploie ta cagnotte sur Sepolia. Tu verras ta transaction sur sepolia.etherscan.io : ton contrat existe « pour de vrai », publiquement. (Demande au wingman de te guider pas à pas.)
Défi 2 — Un challenge SpeedRun avec le wingman
Le skill connaît les 12 challenges SpeedRun Ethereum. Demande-lui : « Guide-moi dans le challenge "Token Vendor" : un contrat qui vend et rachète un jeton ERC-20. » Suis-le, mais teste chaque étape en Remix.
Défi 3 — Dompter un « gotcha »
Demande au wingman d'expliquer le piège des décimales de jetons (USDC = 6 décimales, la plupart = 18) ou le pattern approve des ERC-20, et écris un mini-exemple qui le met en évidence.
Clôture
Checklist de fin
- ☐ Ma cagnotte (à la main) compile et passe les 2 scénarios.
- ☐ Je sais expliquer pourquoi
= 0va avant letransfer(reentrancy). - ☐ Le skill ethereum-wingman est installé et j'ai fait auditer mon code.
- ☐ J'ai généré, testé et comparé une version IA — et j'ai vérifié qu'elle marche.
- ☐ Mes flags A→K sont remplis.
Mini-quiz (vérifie-toi)
- Quel mot-clé permet à une fonction de recevoir de l'ETH ?
- Que contient
msg.sender? Etmsg.value? - Dans quel ordre : vérifier, modifier l'état, appeler l'extérieur ? Pourquoi ?
- Pourquoi faut-il tester en Remix le code généré par l'IA, même s'il « a l'air bon » ?
- Qui peut appeler
finaliser()une fois la deadline passée ?
(Réponses dans le corrigé prof.)
Glossaire
| Solidity | langage des smart contracts. |
| EVM | l'ordinateur mondial qui exécute les contrats. |
| Remix | IDE Solidity dans le navigateur (éditeur + compile + déploie). |
| wei / ether | unités de montant (1 ether = 10¹⁸ wei). |
| payable | autorise une fonction à recevoir de l'ETH. |
| require | une garde : si faux, la transaction est annulée. |
| reentrancy | faille où un appel externe rappelle la fonction avant la fin. |
| Agent Skill | base de connaissances chargée par un agent IA (ex. ethereum-wingman). |
Compétences mobilisées (référentiel BTS SIO SLAM)
Bloc 2 · Conception et développement d'applications
→ Développer des applications en respectant les standards de programmation
→ Intégrer et tester les fonctionnalités (compilation, déploiement, scénarios de test)
Bloc 3 · Cybersécurité des services informatiques
→ C3.5 Assurer la cybersécurité d'une solution applicative (reentrancy, checks-effects-interactions, audit de code)
Bloc 1 · Support et mise à disposition de services informatiques
→ C1.6 Organiser son développement professionnel (prise en main d'un outillage et d'un agent IA, vérification critique)