From 6c0408737e1f837de78374b042bbe05630fe975d Mon Sep 17 00:00:00 2001 From: Ladebeze66 Date: Mon, 9 Nov 2026 10:53:26 +0100 Subject: [PATCH] fichesoutenance --- docs/pedagogie/fiche-soutenance-tokenizer.md | 283 ++++++++++++++++++- 1 file changed, 275 insertions(+), 8 deletions(-) diff --git a/docs/pedagogie/fiche-soutenance-tokenizer.md b/docs/pedagogie/fiche-soutenance-tokenizer.md index 13e19e2..6eddeec 100644 --- a/docs/pedagogie/fiche-soutenance-tokenizer.md +++ b/docs/pedagogie/fiche-soutenance-tokenizer.md @@ -3,7 +3,7 @@ > Fichier **perso**, hors dépôt école. Il sert à **réexpliquer le projet à voix haute** après une pause. > Le correcteur, lui, ne voit que `tokenizerRendu/` (README, `code/`, `deployment/`, `documentation/`). -Lis les sections 1 à 4 pour le récit. Les sections 5 à 8 sont le cours technique. La section 9 est le script de démo. La section 10 est la revue de code, fichier par fichier. +Lis les sections 1 à 4 pour le récit. La section 5 pose le vocabulaire. Les sections 6 à 9 détaillent Solidity, chaque outil, et la fabrication du jeton dans l’ordre. La section 12 est le script de démo. La section 13 est la revue de code, fichier par fichier. --- @@ -157,7 +157,274 @@ npx hardhat ignition deploy --network bscTestnet ignition/modules/FGC42Forge.ts --- -## 7. Ce que font les commandes +## 7. Solidity, le langage du contrat + +Solidity est le langage dans lequel est écrit **uniquement** le programme qui vit sur la chaîne : `code/contracts/FGC42Forge.sol`. Ce n’est pas le langage des tests ni de la config. Il a été créé pour l’Ethereum Virtual Machine. BSC exécute ce même type de bytecode, donc le même langage sert pour un BEP-20. + +Tu l’écris dans un fichier `.sol`. Hardhat appelle le compilateur **solc**, qui produit du **bytecode** (le binaire déployé) et une **ABI** (la liste des fonctions que MetaMask et ethers savent appeler). Une fois la transaction de déploiement incluse dans un bloc, ce bytecode est figé à une adresse. Modifier le `.sol` sur ton disque ne modifie pas le contrat déjà en ligne : il faudrait déployer un **nouveau** contrat, donc une nouvelle adresse. + +### À quoi ressemble le langage + +Un contrat ressemble à une classe. Il a un état (des variables gardées sur la chaîne) et des fonctions. + +Les mots que tu dois pouvoir définir devant le fichier : + +| Mot dans ton code | Sens | +|-------------------|------| +| `pragma solidity ^0.8.34` | Le fichier se compile avec un solc 0.8 à partir de 0.8.34. Le `^` interdit la branche 0.9. En 0.8, un dépassement d’entier annule la transaction au lieu de boucler silencieusement. | +| `SPDX-License-Identifier: MIT` | Licence du source. BscScan la demande au moment de la vérif. | +| `import {ERC20} from "..."` | Le compilateur va lire un autre fichier. Ici, la bibliothèque OpenZeppelin installée dans `node_modules`. Tu n’as pas recopié `transfer` à la main. | +| `contract FGC42Forge is ERC20, Ownable` | Déclare le programme. `is` veut dire héritage : FGC42Forge possède les variables et les fonctions de ERC20 et de Ownable. | +| `uint256` | Entier non signé de 256 bits. Les soldes et les montants sont toujours des entiers. Solidity n’a pas de nombres à virgule. | +| `address` | Un compte ou un contrat, 20 octets, affiché `0x` + 40 hex. | +| `string` | Texte. Le nom et le symbole sont des `string`, stockés par le constructeur d’ERC20. | +| `private constant` | `constant` : valeur fixée à la compilation, pas un stockage coûteux qui change. `private` : aucune autre contrat ni aucun appel extérieur ne peut lire cette variable directement. Le million, lui, est visible via `totalSupply()`, qui est public. | +| `constructor` | Fonction appelée **une seule fois**, dans la transaction qui crée le contrat. Après, elle n’existe plus comme fonction appelable. | +| `msg.sender` | L’adresse qui a signé la transaction en cours. Dans le constructeur, c’est le déployeur. Dans `transfer`, c’est celui qui envoie ses jetons. | +| `_mint(...)` | Fonction **interne** d’OpenZeppelin (le `_` est une convention). Seul ton contrat peut l’appeler. Un utilisateur MetaMask ne peut pas l’appeler de l’extérieur. | + +Visibilités à connaître même si tu ne les as pas toutes écrites : + +- `public` : appelable de l’extérieur et depuis le contrat. `name()`, `transfer()`, `owner()` sont publics. +- `external` : appelable seulement de l’extérieur. +- `internal` : le contrat et ses héritiers. `_mint` est internal. +- `private` : ce fichier seulement. + +Une fonction qui ne fait que lire (`view`, comme `balanceOf`) ne coûte pas de gas quand on l’appelle via un nœud pour afficher un solde. Une fonction qui écrit (`transfer`, le constructeur) est une transaction : elle est signée, payée en tBNB, et enregistrée dans un bloc. + +Si une condition échoue, Solidity **annule toute la transaction** (`revert`). OpenZeppelin le fait quand on transfère plus que son solde. L’état d’avant est restauré. Le gas déjà consommé n’est pas rendu. + +Les **événements** (`event Transfer`) n’ajoutent pas de logique. Ils laissent une trace dans le reçu de la transaction. BscScan s’en sert pour l’onglet Transfers. Ton test vérifie que `transfer` émet bien cet événement. + +Dans ERC20, les soldes sont un `mapping(address => uint256)` : une table adresse → montant. Tu ne l’as pas écrite. Elle est dans OpenZeppelin. `balanceOf` lit cette table. `transfer` soustrait chez l’expéditeur et ajoute chez le destinataire. + +`1_000_000 * (10 ** 18)` : les underscores sont seulement visuels (un million). `10 ** 18` est l’exposant. Comme `decimals()` vaut 18, un wallet qui affiche « 1 FG42 » divise l’entier interne par 10^18. + +### Ce que tu as choisi de ne pas écrire + +Tu n’as pas redéfini `transfer`, `approve`, `transferFrom`. Les redéfinir est utile pour une taxe ou une liste noire ; ici ça n’apporterait qu’un risque de bug. Le fichier reste court : héritage, constante, constructeur. + +Tu n’as pas ajouté `function mint(address to, uint256 amount) public onlyOwner`. Cette fonction existe dans d’autres jetons (OpenZeppelin `ERC20Preset` ou un mint manuel). L’ajouter aurait rendu l’offre diluable. Le sujet demande de réfléchir aux privilèges : ton choix est « le seul privilège de création est le déploiement lui-même ». + +--- + +## 8. Les outils, un par un, et comment tu t’en es servi + +Rien de tout cela n’est « la blockchain ». Ce sont les instruments pour écrire le contrat, le tester, le payer, et le montrer. + +### Node.js et npm + +**Node.js** exécute du JavaScript sur ta machine. **npm** installe les bibliothèques listées dans `code/package.json`. + +Tu t’en sers ainsi, dans `tokenizerRendu/code/` : + +```bash +node -v # doit répondre, idéalement 18 ou plus +npm install # lit package.json et package-lock.json, crée node_modules/ +``` + +`node_modules/` n’est pas dans Git : trop gros, et régénérable. Sur une autre machine, `npm install` suffit. Hardhat, ethers, Mocha, TypeScript, OpenZeppelin et dotenv arrivent par là. + +`npx hardhat ...` lance le binaire Hardhat **de ce** `node_modules`, pas un Hardhat installé ailleurs sur l’ordinateur. + +### MetaMask + +Extension de navigateur. Elle garde la seed et les clés, affiche les réseaux, signe les transactions. + +Comment tu l’as utilisé : + +1. Créer un compte dédié, nommé **FGC_account**. Son adresse publique est `0xB6bE1878BfaF1FFC8503E752b1D733Ad7b93603c`. Cette adresse est la même sur toutes les chaînes EVM. Ce qui change, c’est le réseau sélectionné en haut de MetaMask (chainId 97 pour le testnet BSC, 56 pour le mainnet BSC, 1 pour Ethereum). Les soldes ne se mélangent pas. +2. Ajouter le réseau à la main si besoin : nom « BNB Smart Chain Testnet », RPC `https://data-seed-prebsc-1-s1.binance.org:8545/`, chain ID `97`, symbole `tBNB`, explorateur `https://testnet.bscscan.com`. +3. Obtenir du **tBNB** : coller l’adresse publique dans le faucet BNB (site ou bot Telegram officiel). Ce n’est pas un bouton « générer » dans MetaMask. Le faucet envoie une transaction vers toi. +4. Pour la démo : menu Tokens → Importer, coller l’adresse **du contrat** `0x0c76…0fF4`. MetaMask interroge `symbol()` et `decimals()` et affiche FG42. Puis Envoyer vers un second compte. MetaMask demande une signature ; le gas est prélevé en tBNB. + +La seed et la clé privée s’affichent dans MetaMask → détails du compte. Tu les copies **une fois** dans `code/.env` pour que Hardhat puisse signer. Tu ne les mets ni dans Git, ni dans la fiche, ni à l’écran en soutenance. + +Bitcoin n’utilise pas cette adresse `0x`. Un wallet Bitcoin, même avec la même seed, dérive une autre clé et une adresse du type `bc1…`. + +### Faucet + +Page ou bot qui envoie du tBNB à une adresse de test. Sans ce solde, le déploiement et les transfers échouent faute de gas. Les FG42 ne paient pas le gas. + +### Hardhat 3 + +Framework dans `code/`. Il ne déploie rien tant que tu ne lui demandes pas un réseau. + +Mise en place, une fois, dans `code/` : + +```bash +npm init -y +npm install --save-dev hardhat +npx hardhat --init +``` + +Sur Hardhat 3, l’assistant s’appelle `npx hardhat --init` (avec les deux tirets). Il pose des questions (toolbox Mocha + ethers) et crée `hardhat.config.ts`, `contracts/`, `test/`, `ignition/`, plus un exemple **Counter** que tu as laissé. Le token évalué n’est pas Counter. + +Ensuite tu installes la bibliothèque de contrats et le lecteur de `.env` : + +```bash +npm install @openzeppelin/contracts dotenv +``` + +OpenZeppelin est une **dépendance de production** (`dependencies` dans `package.json`) parce que le source du token l’importe. Hardhat, Mocha, TypeScript sont en `devDependencies` : ils servent à compiler et tester, ils ne sont pas déployés on-chain. Seul le bytecode compilé part sur la chaîne. + +Le fichier `hardhat.config.ts` dit trois choses : plugin de tests, version Solidity 0.8.34, et le réseau `bscTestnet` (URL + clé lues dans `.env`). + +Usage quotidien : + +| Action | Commande dans `code/` | +|--------|------------------------| +| Compiler | `npx hardhat build` | +| Tester sans réseau | `npx hardhat test --grep FGC42Forge` | +| Déployer pour de vrai | `npx hardhat ignition deploy --network bscTestnet ignition/modules/FGC42Forge.ts` | +| Fusionner les sources pour BscScan | `npx hardhat flatten contracts/FGC42Forge.sol` | + +`--network bscTestnet` est le nom que **tu** as donné dans la config. Il ne faut pas l’inventer au moment de la commande. + +Les tests utilisent une chaîne simulée dans le processus Hardhat. Ils ne consomment pas le tBNB et n’écrivent pas à l’adresse `0x0c76…`. + +### dotenv et `.env` + +`import "dotenv/config"` dans la config charge `code/.env` au lancement. Deux variables : + +- `BSC_TESTNET_RPC` : l’URL du nœud, la même famille que dans MetaMask. Publique. +- `PRIVATE_KEY` : la clé du compte qui signe, 64 hex, **pas** l’adresse `0xB6bE…`. Si tu colles l’adresse, Hardhat ne peut pas signer. + +`.env.example` est commité avec des valeurs vides ou l’URL publique. `.env` est dans `.gitignore`. + +### TypeScript, Mocha, Chai, ethers + +Les fichiers `.ts` ne sont pas déployés. + +- **TypeScript** : JavaScript avec types. Config, module Ignition, tests. +- **Mocha** : lance les `describe` / `it` de `test/FGC42Forge.ts`. +- **Chai** : `expect(...).to.equal(...)`. +- **ethers v6** : parle à la chaîne. Dans les tests, `ethers.deployContract("FGC42Forge")` déploie sur le réseau simulé. `token.transfer(...)` appelle la fonction du contrat. Hardhat 3 expose ethers via `await network.create()`, pas via un `hre.ethers` global de Hardhat 2. + +### OpenZeppelin + +Paquet npm `@openzeppelin/contracts` version 5. Le chemin d’import est `@openzeppelin/contracts/token/ERC20/ERC20.sol`. Tu hérites de `ERC20` et de `Ownable`. Tu ne modifies pas les fichiers dans `node_modules`. Si tu changeais de version majeure, il faudrait relire le constructeur : en v5, `Ownable` prend l’owner initial en argument, ce que ton code fait avec `Ownable(msg.sender)`. + +### Hardhat Ignition + +Fichier `ignition/modules/FGC42Forge.ts`. C’est un petit programme TypeScript qui décrit le déploiement : « crée un contrat nommé FGC42Forge ». Comme le constructeur Solidity n’a pas de paramètre, le module n’en passe pas. + +Ignition envoie la transaction, attend le reçu, et note l’adresse. Cette adresse de **ce** déploiement est recopiée à la main dans `deployment/addresses.json` et le README. Relancer Ignition créerait un **second** contrat, à une autre adresse, avec un nouveau million de jetons. En soutenance tu ne relances pas le deploy : le contrat à montrer est celui déjà vérifié. + +### BscScan + +Site `testnet.bscscan.com`. Tu l’utilises pour : + +- coller l’adresse et voir la transaction de création ; +- ouvrir l’onglet token (supply, holders, transfers) ; +- vérifier le source : Contract → Verify and publish → Solidity single file → coller `FGC42Forge_flat.sol`, optimizer Yes, 200 runs, licence MIT, constructeur vide. + +L’explorateur recompile. Si le bytecode obtenu est celui déjà stocké à l’adresse, il affiche le source. C’est la preuve que le dépôt correspond au programme on-chain. + +--- + +## 9. Création du jeton, dans l’ordre + +C’est le chemin que tu racontes si on te demande « comment tu as procédé ». Chaque étape a un résultat visible. + +### Étape A — Décider avant d’écrire + +Tu fixes, par écrit, ce que le contrat devra respecter : + +- chaîne : BSC Testnet, chainId 97, gas en tBNB ; +- nom `FGC42Forge` (contient 42), symbole `FG42` ; +- standard BEP-20 via OpenZeppelin ERC20 ; +- 1 000 000 jetons, 18 décimales, mint une seule fois au déployeur ; +- pas de mint public, pas de burn, pas de multisig. + +Ces choix sont ceux du README. Les changer après le déploiement ne change pas le contrat déjà en ligne. + +### Étape B — Le compte qui paiera + +1. Installer MetaMask, créer **FGC_account**. +2. Ajouter le réseau BSC Testnet (chainId 97, RPC, symbole tBNB). +3. Copier l’adresse publique dans le faucet et attendre le tBNB. +4. Vérifier sur BscScan que l’adresse a un solde tBNB. Sans ça, l’étape F échoue. + +### Étape C — L’atelier Hardhat + +```bash +cd tokenizerRendu/code +npm init -y +npm install --save-dev hardhat +npx hardhat --init +npm install @openzeppelin/contracts dotenv +``` + +Tu copies `.env.example` vers `.env`. Dans MetaMask : détails du compte → afficher la clé privée. Tu la mets dans `PRIVATE_KEY`. Tu vérifies que `hardhat.config.ts` a bien le bloc `bscTestnet` avec `BSC_TESTNET_RPC` et `PRIVATE_KEY`. + +`npx hardhat build` doit passer. À ce stade le seul contrat est encore l’exemple Counter. C’est normal. + +### Étape D — Écrire le contrat + +Tu crées `contracts/FGC42Forge.sol` : + +1. Licence MIT et `pragma solidity ^0.8.34`. +2. Importer `ERC20` et `Ownable`. +3. `contract FGC42Forge is ERC20, Ownable`. +4. Constante `INITIAL_SUPPLY = 1_000_000 * (10 ** 18)`. +5. Constructeur : `ERC20("FGC42Forge", "FG42")`, `Ownable(msg.sender)`, puis `_mint(msg.sender, INITIAL_SUPPLY)`. + +Tu n’ajoutes pas d’autre fonction. `npx hardhat build` doit recompiler sans erreur. Une erreur d’import veut dire qu’OpenZeppelin n’est pas installé ou que le chemin est faux. Une erreur sur `Ownable()` sans argument voudrait dire une vieille version 4 : en v5 l’owner initial est obligatoire. + +### Étape E — Prouver le comportement avant de payer du gas + +Tu écris `test/FGC42Forge.ts` (les deux scénarios de la section 11). Puis : + +```bash +npx hardhat test --grep FGC42Forge +``` + +Tu attends « 2 passing ». Si un test échoue, tu corriges le `.sol` **avant** le déploiement. Un contrat déjà déployé ne se corrige pas sur place. + +### Étape F — Déployer + +Le compte du `.env` doit être celui qui a le tBNB (FGC_account). + +```bash +npx hardhat ignition deploy --network bscTestnet ignition/modules/FGC42Forge.ts +``` + +Hardhat affiche une estimation de gas et demande confirmation. La transaction part vers le RPC BSC. Le réseau l’inclut dans un bloc. Ignition affiche l’adresse du nouveau contrat. + +Cette adresse (`0x0c76df26A1149fDc22C8f994975705271b070fF4`) n’existait pas avant. Le constructeur s’est exécuté dans cette transaction : FGC_account a reçu 1 000 000 FG42 et est devenu `owner`. Tu retrouves la tx `0xb6a0ec09…4072` sur BscScan. + +Tu recopies réseau, chainId, adresse, deployer, hash et bloc dans `deployment/addresses.json` et dans le tableau du README. C’est cette copie qui est le livrable Git, pas le cache `ignition/deployments/`. + +### Étape G — Vérifier le source sur BscScan + +```bash +npx hardhat flatten contracts/FGC42Forge.sol > ../deployment/FGC42Forge_flat.sol +``` + +Sur testnet.bscscan.com, page du contrat → Verify and Publish : + +- compilateur : single file ; +- optimiser : oui, 200 runs ; +- licence MIT ; +- pas d’argument de constructeur ; +- coller le fichier aplati ; +- le nom du contrat à cocher est `FGC42Forge` (le fichier contient aussi les contrats OpenZeppelin). + +Quand le bytecode matche, l’onglet Contract devient lisible. Le `pragma` local est 0.8.34 ; l’interface BscScan peut afficher `v0.8.24+commit.89d56535`. Tu t’en tiens au fait : la vérif a réussi, le détail est dans `deployment/BSCSCAN_VERIFICATION.md`. + +### Étape H — Le rendre utilisable par quelqu’un d’autre + +1. Dans MetaMask, importer le token par l’adresse du contrat. +2. Envoyer par exemple 100 FG42 vers un second compte de test. +3. Montrer le transfer sur la page token BscScan. `totalSupply` reste 1 000 000. +4. Écrire `documentation/README.md` : ce qu’est le jeton, le réseau, l’adresse, les clics MetaMask, les limites (pas de mint, pas de valeur réelle). + +À partir de là le sujet est couvert : code commenté, déploiement public, adresse dans le dépôt, explorateur, doc d’utilisation, démo de transfer. + +--- + +## 10. Ce que font les commandes Toutes les commandes Hardhat : d’abord `cd` dans `tokenizerRendu/code` (sur le dépôt de travail) ou `code/` (si la racine Git école est déjà le rendu). @@ -175,7 +442,7 @@ Toutes les commandes Hardhat : d’abord `cd` dans `tokenizerRendu/code` (sur le --- -## 8. Les deux tests, phrase par phrase +## 11. Les deux tests, phrase par phrase Fichier : `tokenizerRendu/code/test/FGC42Forge.ts`. @@ -191,7 +458,7 @@ Ce que les tests ne couvrent pas, et que tu peux dire si on te le demande : `app --- -## 9. Déroulé oral et démo +## 12. Déroulé oral et démo Prépare avant : MetaMask sur **BNB Smart Chain Testnet**, FGC_account avec un peu de tBNB et des FG42, un second compte (demo) avec le token importé, trois onglets (README du rendu, page contrat `#code`, page token). @@ -203,7 +470,7 @@ Prépare avant : MetaMask sur **BNB Smart Chain Testnet**, FGC_account avec un p | 4 | BscScan page **contrat**, onglet Contract | Code vérifié, correspond au dépôt | | 5 | MetaMask | Transfer d’un petit montant (100 FG42) vers le second compte. Le gas est en tBNB | | 6 | BscScan Transfers | La tx apparaît ; le second solde a augmenté ; `totalSupply` n’a pas bougé | -| 7 | `code/contracts/FGC42Forge.sol` | Revue ligne à ligne, section 10 | +| 7 | `code/contracts/FGC42Forge.sol` | Revue ligne à ligne, section 13 | | 8 | Si on le demande | `cd code && npx hardhat test --grep FGC42Forge` | Phrase de fin sur ce que le projet t’a appris (le chapitre III du sujet) : écrire un contrat Solidity, le faire vivre sur une chaîne publique (adresse, gas, explorateur), et raisonner sur qui a le droit de créer des jetons. @@ -212,7 +479,7 @@ Si MetaMask ou le faucet bloque le jour J : la page token a déjà des transfers --- -## 10. Revue de code — quoi dire devant chaque fichier +## 13. Revue de code — quoi dire devant chaque fichier ### `code/contracts/FGC42Forge.sol` (le seul fichier qui compte vraiment) @@ -265,7 +532,7 @@ Guide utilisateur, pas cours Hardhat. Présentation, réseau, import MetaMask (a --- -## 11. Sécurité — réponses développées +## 14. Sécurité — réponses développées **Qui peut créer des FG42 après le deploy ?** Personne. La seule création est dans le constructeur. Pas de `mint` public, pas de rôle « minter ». @@ -290,7 +557,7 @@ Non. Testnet. Le dire évite la confusion avec un vrai actif. --- -## 12. Carte « on me demande X → j’ouvre Y » +## 15. Carte « on me demande X → j’ouvre Y » | On te demande | Fichier dans le rendu | |---------------|------------------------|