# Fiche de soutenance — Tokenizer (FGC42Forge) > 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. La section 5 pose le vocabulaire. La section **6.5** résume **toute la stack** (définition + emboîtement). Les sections 6 à 10 détaillent choix, Solidity, outils et fabrication. La section 12 est le script de démo. La section 13 est la revue de code, fichier par fichier. --- ## 1. Ce que tu as fait, en une histoire Le sujet 42 *Tokenizer* (v1.1), en partenariat avec **BNB Chain**, demande de créer un **jeton numérique** sur une blockchain publique, **sans argent réel**, de le déployer, de documenter comment on l’utilise, et de pouvoir expliquer le code. Tu as créé **FGC42Forge**, symbole **FG42**. C’est un jeton **fongible** : une unité en vaut une autre, comme des pièces identiques, pas comme un NFT unique. Sur BNB Smart Chain, ce standard s’appelle **BEP-20**. Techniquement, le code est celui d’un **ERC-20** Ethereum, parce que BSC est une chaîne **EVM** (machine virtuelle Ethereum — voir section 5) : elle exécute les mêmes smart contracts Solidity qu’Ethereum. BscScan affiche « BEP-20 » à cause de la chaîne, pas parce que tu as écrit une norme différente. **1 000 000 FG42** ont été créés **une seule fois**, au moment du déploiement, et envoyés au compte qui a déployé. Ensuite, plus personne ne peut en fabriquer. On ne peut que les **transférer**. Il n’y a pas de fonction `burn` (destruction), pas de pause, pas de liste noire. Le contrat est déjà en ligne sur **BNB Smart Chain Testnet** (identifiant de chaîne **97**), à l’adresse : `0x0c76df26A1149fDc22C8f994975705271b070fF4` Le compte qui a payé le déploiement et qui est devenu `owner` s’appelle **FGC_account** : `0xB6bE1878BfaF1FFC8503E752b1D733Ad7b93603c` Transaction de création : `0xb6a0ec09d4db0e9f0686aca6ad5d8ca71cecaf8d43405eeed214736bb8574072` (bloc `137872368`, le 2026-10-20). Le code source a été **publié et vérifié** sur BscScan : l’explorateur a recompilé le source et obtenu le **même bytecode** que celui déjà enregistré à cette adresse. Ça prouve que le programme on-chain est bien celui du dépôt. Le bonus du sujet (un **multisig** : plusieurs signatures pour une action sensible) n’a **pas** été fait. Tu l’assumes : l’obligatoire est complet, le bonus n’est noté que si l’obligatoire est parfait, et tu as choisi un contrat simple à défendre. --- ## 2. Deux dépôts, ne pas les mélanger | | Dépôt de travail (`main`) | Dépôt école | |---|---|---| | Où | Racine `tokenizer/` | Le **contenu** de `tokenizerRendu/` doit être la **racine** Git Vogosphere | | Contenu | `docs/` (cette fiche, sujet traduit, notes) + `tokenizerRendu/` | `README.md`, `code/`, `deployment/`, `documentation/` | | À montrer | À toi, pour réviser | Au correcteur | La branche **`rendu-tokenizer`** a volontairement **retiré** `docs/` pour ne garder que le paquet école. La fiche n’y est plus : c’est normal. Elle vit sur **`main`**, dans `docs/pedagogie/`. Sur le PC école : le Git Vogosphere doit avoir **à sa racine** le README du token, pas un dossier parent `tokenizerRendu/`. Sinon la structure demandée par le sujet n’est pas respectée. --- ## 3. Pitch à dire (environ une minute) « J’ai créé un token BEP-20, FGC42Forge, symbole FG42, sur le testnet public de BNB Smart Chain. Le nom contient 42, comme le demande le sujet. Il n’y a pas d’argent réel : le gas se paie en tBNB, obtenu via un faucet. Le contrat est écrit en Solidity. Je n’ai pas réécrit transfer ou balanceOf : j’hérite de l’ERC-20 d’OpenZeppelin, plus Ownable pour savoir qui est l’administrateur. Au constructeur, le contrat émet une seule fois un million de jetons vers le déployeur. Il n’existe aucune fonction publique pour en créer d’autres ensuite. L’owner peut transférer le rôle d’admin, mais il ne peut pas augmenter l’offre. J’ai développé avec Hardhat 3 : compilation, deux tests automatisés, déploiement avec Ignition. L’adresse et le réseau sont dans le README et dans deployment/addresses.json. Le contrat est vérifié sur BscScan. La démo, c’est un transfer entre deux comptes MetaMask, visible sur l’explorateur. Le bonus multisig n’est pas implémenté. » --- ## 4. Chiffres à avoir sous les yeux | Élément | Valeur | Où le montrer | |---------|--------|----------------| | Nom / symbole | FGC42Forge / FG42 | README, BscScan, MetaMask | | Réseau | BSC Testnet, chainId **97** | README, MetaMask | | Contrat | `0x0c76df26A1149fDc22C8f994975705271b070fF4` | README, `deployment/addresses.json` | | Owner / deployer | `0xB6bE1878BfaF1FFC8503E752b1D733Ad7b93603c` | `addresses.json`, BscScan | | Supply | 1 000 000, **18 décimales** | contrat `INITIAL_SUPPLY`, page token | | Page contrat | https://testnet.bscscan.com/address/0x0c76df26A1149fDc22C8f994975705271b070fF4 | onglet Contract = code vérifié | | Page token | https://testnet.bscscan.com/token/0x0c76df26A1149fDc22C8f994975705271b070fF4 | supply, holders, transfers | | Tests | 2 tests Mocha, tous verts | `code/test/FGC42Forge.ts` | ### Chain ID — testnet **97** vs mainnet **56** (BNB Smart Chain) Oui : pour **BNB Smart Chain** (BSC), les identifiants officiels sont : | Réseau | Chain ID | Monnaie gas | Explorateur | Projet FGC42Forge | |--------|----------|-------------|-------------|-------------------| | **BSC Testnet** | **97** | **tBNB** (sans valeur réelle) | `testnet.bscscan.com` | **Oui** — seul réseau utilisé | | **BSC Mainnet** | **56** | **BNB** (vraie valeur) | `bscscan.com` | **Non** — sujet = pas d’argent réel | **À retenir à l’oral :** - Ton contrat et tes FG42 existent **uniquement** sur le testnet (**97**). Rien n’est déployé sur le mainnet (**56**). - MetaMask doit afficher **BNB Smart Chain Testnet** et **97** avant toute démo. Si tu es sur **56**, tu ne verras pas le bon contrat ni les bons FG42 (autre chaîne, autre état). - Ton **adresse compte** `0xB6bE…` est la **même** sur 97 et 56 (même clé EVM), mais les soldes et les contrats ne sont **pas** les mêmes : le testnet et le mainnet sont deux registres séparés. - Pour comparaison (hors BSC) : Ethereum mainnet = chainId **1**. Ce n’est pas la chaîne du projet, mais le même type d’adresse `0x`. Les valeurs **97** et **56** sont dans le README, `deployment/addresses.json` (`chainId: 97`) et la config MetaMask documentée dans `documentation/README.md`. **18 décimales** : en interne la blockchain ne stocke pas « 1,5 FG42 ». Elle stocke un entier. 1 FG42 affiché = `1 * 10^18` unités. Le million du constructeur, c’est donc `1_000_000 * 10^18`. MetaMask fait la conversion pour l’affichage. Si on oublie les décimales, on croit transférer 1 jeton alors qu’on transfère une fraction infime, ou l’inverse. --- ## 5. Les notions, assez pour les expliquer ### EVM (Ethereum Virtual Machine) **EVM** = **Ethereum Virtual Machine** (machine virtuelle Ethereum). En bref : c’est le **moteur d’exécution** qui fait tourner les **smart contracts** sur une blockchain compatible. Quand tu déploies `FGC42Forge`, ce n’est pas ton PC qui exécute le code en permanence : chaque nœud du réseau **BSC Testnet** possède une EVM qui exécute le **bytecode** du contrat quand quelqu’un appelle `transfer`, `balanceOf`, etc. | Idée | Explication simple | |------|-------------------| | **À quoi ça sert** | Exécuter du code **déterministe** et **partagé** : même entrée → même résultat pour tous les validateurs du réseau. | | **Lien avec Solidity** | Tu écris en **Solidity** ; le compilateur **solc** (via Hardhat) produit du **bytecode EVM** + une **ABI**. C’est ce bytecode qui est stocké on-chain à l’adresse du contrat. | | **Chaînes « EVM »** | Blockchains qui parlent le **même langage machine** qu’Ethereum : **Ethereum**, **BNB Smart Chain**, Polygon, etc. | | **Ton projet** | **BSC Testnet (chainId 97)** est une chaîne EVM → tu peux utiliser **Solidity**, **OpenZeppelin ERC20**, **MetaMask**, **adresses `0x…`**. | | **BEP-20 vs ERC-20** | **ERC-20** = nom de la norme côté Ethereum / Solidity. **BEP-20** = même logique sur BNB Chain ; l’explorateur BscScan affiche BEP-20 parce que la **chaîne** est BSC, pas parce que le code Solidity change. | | **Adresse wallet** | Sur toutes les chaînes EVM, **la même clé** donne **la même adresse** `0x…` (ex. FGC_account). En revanche, **chaque chainId** (97, 56, 1…) a son **propre registre** : soldes et contrats ne sont pas partagés entre testnet et mainnet. | | **Ce que l’EVM n’est pas** | Ce n’est pas Bitcoin (autre modèle, pas Solidity). Ce n’est pas Hardhat ni MetaMask : ce sont des outils **autour** de l’EVM. | **Phrase soutenance (EVM en 20 s)** : « BSC est une blockchain **compatible EVM** : on écrit en Solidity, le bytecode s’exécute comme sur Ethereum. Mon token suit l’interface ERC-20 dans le code ; sur le testnet BSC, on l’appelle un **BEP-20**. » **Où le voir dans le dépôt** : contrat `code/contracts/FGC42Forge.sol` ; réseau `chainId: 97` dans `deployment/addresses.json` et `hardhat.config.ts` (`bscTestnet`). --- ### Blockchain, compte, contrat Une blockchain publique est un registre partagé. Une **transaction** est un ordre signé (déployer un contrat, transférer des jetons) que le réseau exécute et enregistre. Une **adresse `0x` + 40 hex** identifie soit un **compte** (contrôlé par une clé privée, comme FGC_account), soit un **contrat** (un programme dont le bytecode est stocké à cette adresse). Les deux se ressemblent. La différence : un compte a une clé ; un contrat a du code. **Gas** : chaque écriture coûte du calcul au réseau. On le paie dans la monnaie **native** de la chaîne, pas dans FG42. Sur le testnet, cette monnaie s’appelle **tBNB**. Elle n’a pas de valeur réelle. On l’obtient par le faucet BNB Chain (site ou bot Telegram officiel). Sans tBNB, MetaMask ne peut ni déployer ni envoyer de FG42 : le jeton bouge, mais la transaction elle-même se paie en tBNB. **Testnet vs mainnet** : le testnet est une chaîne publique de répétition. Le sujet interdit d’exiger de l’argent réel. Tu n’as rien déployé sur le mainnet BSC (chainId 56). Ne branche pas MetaMask sur le mainnet pendant la démo. **RPC** : l’URL d’un nœud qui parle au réseau (`https://data-seed-prebsc-1-s1.binance.org:8545/`). MetaMask et Hardhat utilisent tous les deux un RPC pour lire les soldes et envoyer des transactions. Ce n’est pas un secret. ### Token, ERC-20, BEP-20 Un **token** ici n’est pas un fichier. C’est un contrat qui tient une table « adresse → solde » et des fonctions standard : - `name`, `symbol`, `decimals` : l’identité affichée - `totalSupply` : combien d’unités existent - `balanceOf(compte)` : le solde d’une adresse - `transfer(destinataire, montant)` : l’expéditeur envoie ses propres jetons - `approve` + `transferFrom` : autoriser un tiers à dépenser jusqu’à un plafond (`allowance`) **Fongible** : le solde est un nombre. 100 FG42 de A valent 100 FG42 de B. Un NFT (ERC-721) serait un objet numéroté : hors sujet. **ERC-20** est la norme Ethereum. **BEP-20** est le même contrat d’interface sur BNB Chain. Dans le code tu importes `ERC20` d’OpenZeppelin. À l’oral tu dis : « standard BEP-20, implémenté avec l’ERC-20 OpenZeppelin, déployé sur BSC ». Le **nom** `FGC42Forge` contient **42** (obligation du sujet). FGC = tes initiales, Forge = les jetons sont « forgés » une fois au déploiement. Le **symbole** (ticker) est `FG42`, celui qu’on publie sur l’explorateur. ### Mint, supply fixe, owner **Mint** = créer des jetons et augmenter `totalSupply`. OpenZeppelin fournit `_mint`, une fonction **interne** : seul le contrat peut l’appeler, pas un utilisateur depuis MetaMask. Dans ton constructeur, `_mint(msg.sender, INITIAL_SUPPLY)` s’exécute **une fois**, quand la transaction de déploiement crée le contrat. `msg.sender` est le compte qui paie cette transaction, donc FGC_account. Après ça, aucune fonction publique ne rappelle `_mint`. L’offre est figée. **Ownable** ajoute un `owner`. Au départ c’est aussi le déployeur (`Ownable(msg.sender)`). Il peut `transferOwnership` (donner l’admin à une autre adresse) ou `renounceOwnership` (plus personne n’est owner). Dans **ce** contrat, être owner ne donne **aucun** pouvoir sur les jetons : il n’y a pas de `onlyOwner` sur un mint, pas de taxe, pas de gel. Si on te demande « à quoi sert l’owner alors ? », la réponse honnête est : le rôle existe parce que le modèle OpenZeppelin le pose, et pour montrer que tu as réfléchi aux privilèges ; il n’augmente pas l’offre. Un owner compromis ne peut pas imprimer des FG42 avec ce contrat. Il pourrait seulement céder le rôle vide, ou tu pourrais plus tard ajouter des fonctions `onlyOwner` — ce que tu n’as pas fait. ### Clé privée, seed, .env La **seed** (12 ou 24 mots) et la **clé privée** contrôlent le compte. L’adresse `0xB6bE…` est publique, on peut la mettre dans le README. La clé ne doit jamais être dans Git, sur un slide, ni à l’écran en soutenance. Hardhat, pour déployer, a besoin de signer. La clé du compte **de test** est dans `code/.env`, fichier ignoré par Git. Le modèle commité est `code/.env.example` : il montre les noms de variables, pas le secret. `PRIVATE_KEY` est la clé (64 hex), **pas** l’adresse du wallet. Confondre les deux est l’erreur classique : Hardhat ne peut pas signer avec une adresse. MetaMask garde la même clé dans l’extension. Hardhat et MetaMask peuvent être le **même** compte (FGC_account) : l’un signe en ligne de commande, l’autre signe dans le navigateur. --- ## 6. Pourquoi cette stack (le « pourquoi » du README) Le sujet demande d’expliquer les choix, pas seulement de lister des outils. **BNB Smart Chain Testnet.** Le PDF est en partenariat BNB. La chaîne supporte les smart contracts, elle est publique, l’explorateur est BscScan, le gas de test est gratuit via faucet. Ethereum testnet aurait été valable avec un ERC-20, à justifier. Tu as suivi la piste du partenaire. **Solidity.** C’est le langage des contrats EVM. Le fichier évalué est `tokenizerRendu/code/contracts/FGC42Forge.sol`. Version du projet : **0.8.34** (`pragma` et `hardhat.config.ts`). Les versions 0.8.x empêchent par défaut certains overflows d’entiers. **OpenZeppelin.** Bibliothèque auditée. Réécrire `transfer` soi-même est le meilleur moyen d’introduire un bug (oubli d’événement, mauvais calcul de solde, pas de protection sur le destinataire zéro). Tu composes un contrat court par-dessus un standard connu. **Hardhat 3.** Outil Node.js qui compile Solidity, lance des tests et parle au réseau. Le sujet cite aussi Remix, Truffle, Foundry. Tu peux les nommer : - **Remix** : IDE dans le navigateur, bien pour un contrat isolé, moins pratique pour un dépôt avec tests reproductibles. - **Truffle** : ancien framework compile / migrate / test, peu actif face à Hardhat. - **Foundry** : outils en Rust (`forge`), très rapides ; tu es resté sur Node parce que le projet Hardhat couvre compile, test et deploy. Hardhat se lance **depuis `code/`**, parce que `hardhat.config.ts` est là. À la racine du dépôt, `npx hardhat` répond « No Hardhat config file found ». Ce n’est pas une panne. **Ignition.** Système de déploiement de Hardhat. Le fichier `code/ignition/modules/FGC42Forge.ts` dit : « déploie le contrat FGC42Forge ». Il n’y a pas d’argument de constructeur : le constructeur Solidity n’en prend pas. La commande : ```bash cd code npx hardhat ignition deploy --network bscTestnet ignition/modules/FGC42Forge.ts ``` `--network bscTestnet` choisit l’entrée du `hardhat.config.ts` : URL RPC + compte `PRIVATE_KEY`. Sans ce flag, Hardhat ne va pas sur BSC. **Mocha + ethers.** Mocha est le lanceur de tests. ethers.js est la bibliothèque qui déploie le contrat sur une **chaîne simulée locale** pendant `npx hardhat test`. Ces tests ne coûtent pas de tBNB et ne touchent pas le contrat déjà en ligne. Ils prouvent le comportement **avant** ou **à côté** du déploiement public. **TypeScript.** La config Hardhat, le module Ignition et les tests sont en `.ts`. Le contrat, lui, reste en Solidity. Ce ne sont pas deux langages pour la même chose : Solidity = programme on-chain ; TypeScript = outillage autour. **MetaMask.** Extension navigateur. Elle n’est pas dans le dépôt. Elle sert à la **démo humaine** : importer le token par son adresse, voir le solde, cliquer Envoyer. Hardhat sert au développeur. Les deux parlent au même réseau. **BscScan.** Explorateur. Il montre l’adresse, le bytecode, les transactions, et, une fois la vérif faite, le Solidity lisible. Le sujet demande de publier le contrat sur un explorateur et de mettre l’adresse dans Git. La vérification du source n’est pas écrite mot pour mot dans le PDF ; c’est la preuve que tu montres en review. → Détail outil par outil et **emboîtement** : section **6.5** ci-dessous (à réviser avant la soutenance). --- ## 6.5 Stack complète — définition, rôles, emboîtement Cette section reprend chaque brique du projet : **ce que c’est**, **son rôle pour FGC42Forge**, **où ça vit dans le dépôt**, et **comment ça s’enchaîne** avec le reste. Tu peux t’en servir comme trame si l’évaluateur demande « explique-moi ta toolchain ». ### Vue d’ensemble (schéma) ``` Solidity (FGC42Forge.sol) → décrit le token (règles on-chain : supply, transfer…) ↓ import OpenZeppelin (ERC20, Ownable) → code standard audité, compilé avec ton fichier ↓ compile / test / deploy Hardhat 3 → atelier sur ta machine (Node.js) : solc, tests, réseau ├─ Ignition → sous-partie Hardhat : déploiement reproductible └─ toolbox → Mocha (lance les tests) + ethers (parle au contrat) ↓ transaction signée BSC Testnet (chainId 97) → enregistre le bytecode à l’adresse 0x0c76…0fF4 ↓ lecture publique BscScan → explorateur : tx, token, source vérifié MetaMask → wallet utilisateur : import FG42, transfer, gas en tBNB ``` **Flux en une phrase :** tu **décris** le jeton en Solidity, tu **t’appuies** sur OpenZeppelin, **Hardhat** compile et teste hors ligne puis **déploie** via Ignition ; le résultat est **public** sur le testnet ; **BscScan** le prouve ; **MetaMask** montre l’usage réel sans Hardhat. **Point clé soutenance :** après le deploy, le token **ne dépend plus** de Hardhat ni de ton PC. Hardhat a servi à **fabriquer** le contrat ; MetaMask + BscScan servent à **montrer** qu’il vit on-chain. --- ### Solidity — `code/contracts/FGC42Forge.sol` | | | |---|---| | **C’est quoi ?** | Langage des smart contracts **EVM**. Ton contrat est le **programme** exécuté par les nœuds de BSC. | | **Rôle dans le projet** | Définit **FGC42Forge** : nom, symbole, supply fixe au constructeur, héritage ERC20 + Ownable. **C’est le cœur du sujet** (code review). | | **Où / comment** | `pragma solidity ^0.8.34` ; une cinquantaine de lignes ; pas de `mint` public. | | **Ce que ce n’est pas** | Pas le langage des tests (TypeScript) ni de la config Hardhat. | | **Qui compile** | **Hardhat** appelle **solc** → bytecode + ABI. | | **Phrase soutenance** | « Le livrable on-chain est un contrat Solidity minimal : constructeur qui mint une fois un million FG42 au déployeur, le reste c’est l’ERC-20 OpenZeppelin. » | --- ### OpenZeppelin — `@openzeppelin/contracts` | | | |---|---| | **C’est quoi ?** | Bibliothèque Solidity **auditée**, installée via npm (`dependencies` dans `package.json`). | | **Rôle dans le projet** | Fournit **`ERC20`** (BEP-20 fonctionnel) et **`Ownable`** (admin sans mint dans ton design). Tu n’as pas réécrit `transfer` / `balanceOf`. | | **Où / comment** | `import {ERC20} from "..."` et `import {Ownable} from "..."` dans `FGC42Forge.sol`. | | **Ce que ce n’est pas** | Pas un outil qui tourne à part : du **code source** fusionné au tien à la compilation. | | **Lien suivant** | Le compilateur (via Hardhat) inclut ces fichiers ; **BscScan** voit tout via `FGC42Forge_flat.sol`. | | **Phrase soutenance** | « J’ai choisi OpenZeppelin pour respecter le standard sans réinventer les fonctions sensibles. » | #### Détail OpenZeppelin — paquet, ERC20, Ownable (v5) **Installation.** Paquet npm `@openzeppelin/contracts` (version **5.x**, ex. `^5.6.1` dans `package.json`). Installé avec `npm install @openzeppelin/contracts`. Les fichiers `.sol` vivent dans `node_modules/@openzeppelin/contracts/` ; tu ne les édites pas. Au **deploy**, le compilateur **fusionne** ton contrat et OpenZeppelin en **un seul bytecode** à l’adresse `0x0c76…` : il n’y a pas un « contrat OpenZeppelin » séparé sur la chaîne, seulement **FGC42Forge** qui contient ce code. **Pourquoi OpenZeppelin plutôt que tout écrire ?** L’ERC-20 est une norme avec des détails faciles à rater (soldes, `allowance`, événements `Transfer` / `Approval`, protection contre transfert vers adresse nulle, `revert` si solde insuffisant). OpenZeppelin est une implémentation **largement utilisée et auditée** ; le sujet attend un standard de chaîne (BEP-20), pas une réécriture amateur de `transfer`. **Classe `ERC20` — ce que ton contrat hérite (tu ne le réécris pas dans `FGC42Forge.sol`) :** | Fonction / donnée | Rôle | Utilisé en démo ? | |-------------------|------|-------------------| | `name()` | `FGC42Forge` | Oui — MetaMask, BscScan | | `symbol()` | `FG42` | Oui | | `decimals()` | `18` (défaut OZ) | Oui — affichage wallet | | `totalSupply()` | 1 000 000 × 10¹⁸ après le constructeur | Oui — page token | | `balanceOf(adresse)` | Solde d’un compte | Oui | | `transfer(dest, amount)` | Envoyer ses propres jetons | Oui — MetaMask | | `approve(spender, amount)` | Autoriser un tiers à dépenser | Non en démo (hérité, standard) | | `transferFrom(...)` | Dépense via `allowance` | Non en démo (hérité) | | `allowance(owner, spender)` | Plafond d’autorisation | Non en démo | | Événement `Transfer` | Trace from / to / value | Oui — test Hardhat + BscScan | | `_mint(account, amount)` | **Interne** — créer des jetons | **Une fois** dans ton constructeur | Tu appelles **`_mint` une seule fois** dans le constructeur. OpenZeppelin ne te force pas à exposer un `mint()` public : tant que tu n’ajoutes pas de fonction publique qui rappelle `_mint`, personne ne peut augmenter l’offre après le deploy. **Classe `Ownable` (OpenZeppelin v5) — administration :** | Élément | Comportement dans FGC42Forge | |---------|------------------------------| | Constructeur `Ownable(msg.sender)` | Le **déployeur** devient `owner` dès le deploy | | `owner()` | Lecture de l’adresse admin (souvent FGC_account) | | `transferOwnership(nouveau)` | L’owner peut céder le rôle (personne ne peut mint FG42 via ça) | | `renounceOwnership()` | L’owner peut renoncer (plus d’owner) | | Modificateur `onlyOwner` | Restreint une fonction à l’owner — **tu ne l’utilises sur aucune fonction custom** | **Point soutenance :** `Ownable` montre que tu as pensé à « qui administre le contrat ». Dans **ton** design, l’owner **ne crée pas** de FG42 supplémentaires et **ne vole pas** les soldes : il n’y a pas de fonction sensible protégée par `onlyOwner` dans ton fichier. **v4 vs v5 (piège classique).** En OpenZeppelin **v5**, `Ownable` exige l’owner initial dans le constructeur : `Ownable(msg.sender)`. En v4, le owner était parfois fixé différemment. Ton code est aligné **v5**. **BEP-20 vs ERC20 dans le dépôt.** Tu importes le symbole Solidity **`ERC20`**. Sur BSC, l’explorateur et la doc parlent **BEP-20** pour le même comportement. Ce n’est pas un second fichier `BEP20.sol` à écrire. **Où voir tout le code OZ en correction ?** `deployment/FGC42Forge_flat.sol` (résultat de `hardhat flatten`) contient FGC42Forge + ERC20 + Ownable + dépendances, dans l’ordre, pour BscScan. --- ### Hardhat 3 — dossier `code/` | | | |---|---| | **C’est quoi ?** | **Toolchain** Node.js pour smart contracts EVM : compiler, tester, connecter aux RPC, tâches CLI. | | **Rôle dans le projet** | Compile `FGC42Forge.sol`, lance **2 tests** locaux, configure **bscTestnet**, supporte **Ignition** et **flatten** pour BscScan. | | **Où / comment** | `hardhat.config.ts` ; commandes depuis **`code/`** uniquement (`npx hardhat build`, `test`, `ignition deploy`). | | **Ce que ce n’est pas** | Ni wallet, ni blockchain, ni explorateur. **Pas nécessaire** pour utiliser FG42 après deploy. | | **Alternatives (sujet)** | Remix (navigateur), Truffle (legacy), Foundry (Rust) — tu as gardé Hardhat pour tests + deploy dans un repo Git. | | **Phrase soutenance** | « Hardhat est mon atelier : compile, teste sur chaîne simulée, et envoie le deploy sur le testnet avec ma clé dans le .env local. » | --- ### Hardhat Ignition — `code/ignition/modules/FGC42Forge.ts` | | | |---|---| | **C’est quoi ?** | Sous-système **Hardhat** de déploiement **déclaratif** (module TypeScript = « quoi déployer »). | | **Rôle dans le projet** | Une ligne : `m.contract("FGC42Forge")`. Pas d’args → constructeur Solidity vide de paramètres. Produit la tx de **création** du contrat. | | **Où / comment** | `npx hardhat ignition deploy --network bscTestnet ignition/modules/FGC42Forge.ts` | | **Ce que ce n’est pas** | Pas le contrat lui-même ; pas l’adresse officielle dans Git (c’est **`deployment/addresses.json`**). | | **Piège** | Redéployer = **nouvelle** adresse. En eval, tu montres le contrat **déjà** à `0x0c76…`. | | **Phrase soutenance** | « Ignition automatise le deploy : le même module peut le reproduire, mais mon rendu documente l’adresse déjà en production sur le testnet. » | --- ### ethers.js + Mocha — `code/test/FGC42Forge.ts` | | | |---|---| | **C’est quoi ?** | **Mocha** : framework qui exécute les tests (`describe` / `it`). **ethers** : bibliothèque pour déployer et appeler des contrats (adresses, signatures, appels de fonctions). | | **Rôle dans le projet** | Hardhat 3 les branche via `hardhat-toolbox-mocha-ethers`. Tests : métadonnées + supply au deployer + **transfer** + événement `Transfer`. | | **Où / comment** | `await network.create()` puis `ethers.deployContract("FGC42Forge")` ; `npx hardhat test --grep FGC42Forge` → **2 passing**. | | **Ce que ce n’est pas** | Pas on-chain pendant les tests : chaîne **simulée** dans le processus Hardhat, **sans** tBNB. | | **Lien avec MetaMask** | Même logique d’appel (`transfer`), mais en test c’est **ethers** qui signe avec des comptes fictifs Hardhat. | | **Phrase soutenance** | « Les tests Mocha + ethers valident le comportement ERC-20 avant ou en parallèle du deploy réel, sans coût de gas. » | --- ### MetaMask — hors dépôt Git | | | |---|---| | **C’est quoi ?** | Extension **wallet** : comptes `0x…`, réseaux (chainId), signature de transactions, affichage des tokens. | | **Rôle dans le projet** | **Démo utilisateur** : réseau BSC Testnet (97), import FG42 par **adresse du contrat**, **transfer** entre comptes (ex. FGC_account → demo). Gas en **tBNB**, pas en FG42. | | **Où / comment** | Procédure dans `tokenizerRendu/documentation/README.md`. Même RPC que `BSC_TESTNET_RPC` dans `.env`. | | **Ce que ce n’est pas** | Pas utilisé pour compiler ni pour le premier deploy (Hardhat + `PRIVATE_KEY` dans `.env`). | | **Lien avec Hardhat** | Peut être le **même** compte (FGC_account) : clé dans MetaMask **et** dans `.env` pour Ignition — jamais la clé dans Git. | | **Phrase soutenance** | « MetaMask prouve qu’un utilisateur peut importer FG42 et transférer ; Hardhat, lui, prouve que le code est correct en amont. » | --- ### BscScan — explorateur testnet | | | |---|---| | **C’est quoi ?** | **Explorateur de blocs** pour BNB Chain : adresses, transactions, contrats, pages **token** BEP-20. | | **Rôle dans le projet** | Preuve **publique** : tx de création, supply 1M, transfers ; onglet **Contract** avec **source vérifié** (flatten + optimizer 200). | | **Où / comment** | URLs dans README et `deployment/addresses.json` ; fiche technique `deployment/BSCSCAN_VERIFICATION.md`. | | **Ce que ce n’est pas** | Pas un outil de développement : tu ne « codes » pas dessus ; tu **publies** et **montres**. | | **Lien avec Hardhat** | `npx hardhat flatten` → `FGC42Forge_flat.sol` pour le formulaire « Verify & Publish ». | | **Phrase soutenance** | « BscScan est la vitrine du sujet : adresse dans Git, contrat visible et vérifié, historique des transfers pour la démo. » | --- ### Tableau récap — qui fait quoi, quand ? | Étape | Outil(s) | Machine / lieu | |-------|----------|----------------| | Écrire le token | Solidity + OpenZeppelin | Fichiers dans `code/contracts/` | | Vérifier sans gas | Hardhat + Mocha + ethers | Local, `npx hardhat test` | | Mettre en ligne | Hardhat + Ignition + `.env` | Tx vers BSC Testnet | | Enregistrer la preuve | `addresses.json`, README | Git rendu | | Prouver le source | Hardhat flatten + BscScan | Web | | Montrer l’usage | MetaMask + BscScan | Navigateur, soutenance | --- ### Phrase d’ensemble (45 s) — toolchain complète « Mon token est défini en **Solidity** dans `FGC42Forge.sol`, en m’appuyant sur **OpenZeppelin** pour l’ERC-20 et Ownable. **Hardhat** compile ce code, **Mocha** et **ethers** passent deux tests sur une chaîne locale, puis **Ignition** a déployé sur **BSC Testnet**. L’adresse est dans le README et `deployment/addresses.json`. **BscScan** affiche le contrat vérifié et les transfers. Pour la démo, **MetaMask** importe FG42 et envoie des jetons ; le gas reste en tBNB. Une fois déployé, le jeton vit sur la chaîne : Hardhat n’est plus nécessaire pour l’utiliser. » --- ## 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 → **Détail complet** (ERC20, Ownable, tableau des fonctions, v5) : section **6.5**, sous-partie **« Détail OpenZeppelin »**. En bref : `@openzeppelin/contracts` v5 ; imports `ERC20` + `Ownable` ; `_mint` une fois au constructeur ; pas de `mint` public. ### 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). | Commande | Ce qu’elle fait vraiment | |----------|--------------------------| | `npm install` | Télécharge Hardhat, OpenZeppelin, ethers, Mocha, décrits dans `package.json`. Crée `node_modules/`, qui n’est pas commité. | | `cp .env.example .env` | Prépare les secrets locaux. À éditer à la main. Inutile pour les tests seuls. Indispensable pour un **nouveau** deploy. | | `npx hardhat build` | Compile les `.sol`. Hardhat télécharge le compilateur solc si besoin. Produit des artefacts locaux (`artifacts/`, ignorés). | | `npx hardhat test --grep FGC42Forge` | Lance **uniquement** les 2 tests du token. Résultat attendu : 2 passing. | | `npx hardhat test` | Lance aussi les tests du fichier **Counter**, un exemple livré par `hardhat --init`. Ce n’est pas ton token. Si un correcteur le voit, tu dis que c’est le template, le livrable est FGC42Forge. | | `npx hardhat ignition deploy --network bscTestnet …` | Envoie la transaction de création sur le testnet. Coûte du tBNB. Crée une **nouvelle** adresse de contrat. Le déploiement **déjà fait** n’a pas besoin d’être rejoué en soutenance. | | `npx hardhat flatten contracts/FGC42Forge.sol` | Colle ton fichier et les sources OpenZeppelin importées en **un seul** fichier. C’est `deployment/FGC42Forge_flat.sol`, utilisé pour la vérif BscScan en mode « single file ». | `npx` exécute le Hardhat **du projet**, pas un Hardhat installé au hasard sur la machine. --- ## 11. Les deux tests, phrase par phrase Fichier : `tokenizerRendu/code/test/FGC42Forge.ts`. Hardhat 3 ouvre une chaîne locale avec `await network.create()`, puis `ethers`. Personne n’est sur Internet. **Test 1 — « expose le nom, le symbole et la supply fixe au déployeur ».** Il déploie FGC42Forge avec le premier compte de test. Il vérifie `name == FGC42Forge`, `symbol == FG42`, `decimals == 18`, `totalSupply` égal au million en unités internes, ce solde entièrement chez le déployeur, et `owner()` égal à ce déployeur. Donc : identité, offre, destinataire du mint, admin. **Test 2 — « permet un transfer ERC-20 classique ».** Deux comptes : déployeur et destinataire. On transfère 1000 jetons (encore fois 10^18). Le test vérifie l’événement `Transfer` (from, to, montant) et que la somme des deux soldes n’a pas changé : le destinataire a +1000, le déployeur a supply − 1000. Ça montre qu’un transfer **déplace** des jetons, il n’en crée pas. Ce que les tests ne couvrent pas, et que tu peux dire si on te le demande : `approve` / `transferFrom` (hérités, non redéfinis), l’échec d’un transfer plus gros que le solde (OpenZeppelin revert), le comportement sur le vrai testnet. La démo MetaMask couvre le transfer réel. --- ## 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). | Moment | Tu ouvres | Tu expliques | |--------|-----------|----------------| | 1 | `tokenizerRendu/README.md` | Le sujet, le nom avec 42, la chaîne, l’adresse, les 5 choix techniques | | 2 | `documentation/README.md` | Un tiers peut importer FG42 et envoyer sans lire Solidity. Sécurité : testnet, pas de mint, owner limité | | 3 | BscScan page **token** | Supply 1 000 000, historique de transfers | | 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 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. Si MetaMask ou le faucet bloque le jour J : la page token a déjà des transfers passés (démo déjà faite FGC_account → demo_account). Tu montres l’historique et tu dis que le réseau de test est parfois capricieux. Mieux vaut que le live marche ; l’historique est le filet. --- ## 13. Revue de code — quoi dire devant chaque fichier ### `code/contracts/FGC42Forge.sol` (le seul fichier qui compte vraiment) Le fichier fait une cinquantaine de lignes. Presque tout le comportement est **hérité**. 1. `SPDX-License-Identifier: MIT` et `pragma solidity ^0.8.34` : licence, et compilateur 0.8.34 minimum dans la famille 0.8. 2. `import {ERC20}` et `import {Ownable}` : tu ne copies pas ces centaines de lignes dans ton fichier. Le compilateur les lit dans `node_modules/@openzeppelin`. 3. `contract FGC42Forge is ERC20, Ownable` : ton contrat **est** un ERC-20 et **est** Ownable. Il reçoit leurs fonctions. 4. `INITIAL_SUPPLY` est une constante : 1 million fois 10^18. `private` : lisible seulement dans ce contrat. Elle ne change jamais. 5. Le constructeur appelle d’abord `ERC20("FGC42Forge", "FG42")` (nom et symbole stockés), puis `Ownable(msg.sender)` (admin = déployeur), puis `_mint(msg.sender, INITIAL_SUPPLY)`. 6. Le bloc de commentaire en bas liste les fonctions héritées que tu n’as pas réécrites : `transfer`, `approve`, `transferFrom`, `balanceOf`, `owner`, `transferOwnership`, etc. Les dire montre que tu sais que « pas de code » ne veut pas dire « pas de fonction ». Question piège : « Où est écrit transfer ? » — Dans OpenZeppelin `ERC20.sol`, pas dans ton fichier. En revue tu peux ouvrir le fichier aplati `deployment/FGC42Forge_flat.sol` : tout y est dans l’ordre, y compris `function transfer`. Question piège : « Peut-on mint après ? » — Non. `_mint` n’est pas exposé. Chercher `function mint` dans ton contrat ne donne rien. Question piège : « Que se passe-t-il si je transfer plus que mon solde ? » — OpenZeppelin annule toute la transaction (revert). Les soldes restent comme avant. Le gas de l’échec est consommé. Question piège : « C’est un BEP-20 ou un ERC-20 ? » — Les deux formulations. Interface ERC-20, qualification BEP-20 parce que la chaîne est BSC. ### `code/hardhat.config.ts` Il enregistre le plugin Mocha/ethers, fixe Solidity **0.8.34**, et décrit le réseau `bscTestnet` : type HTTP, URL lue dans `BSC_TESTNET_RPC`, compte lu dans `PRIVATE_KEY`. Il y a aussi deux réseaux simulés du template (`hardhatMainnet`, `hardhatOp`) : tu ne t’en sers pas pour le token. Deux profils de compilateur : `default` sans optimizer, `production` avec optimizer **activé, 200 runs**. L’optimizer réduit le bytecode. Le déploiement Ignition / la vérif BscScan utilisent l’optimizer 200. Si on recompile « à la main » sans optimizer, le bytecode ne matche pas : c’est normal, ce n’est pas le même réglage. ### `code/ignition/modules/FGC42Forge.ts` `buildModule` + `m.contract("FGC42Forge")`. Pas de paramètre. Ignition envoie une transaction dont le data est le bytecode + l’appel du constructeur. Le retour `{ token }` permet à Ignition de retenir l’adresse produite. ### `deployment/addresses.json` C’est la trace **versionnée** du déploiement réel : réseau, chainId, adresse, deployer, tx, bloc, drapeau `bscscanVerified`. Le dossier `code/ignition/deployments/` est un journal local, ignoré par Git. Si on te demande « où est l’adresse officielle ? », c’est ce JSON et le README, pas le cache Ignition. ### `deployment/BSCSCAN_VERIFICATION.md` et `FGC42Forge_flat.sol` BscScan en mode single file ne sait pas aller chercher tes `import` dans `node_modules`. `flatten` produit un seul .sol. Tu l’as collé dans « Verify and publish », optimizer Yes, 200 runs, licence MIT, constructeur sans argument. Nuance à connaître pour ne pas te contredire : le projet **local** est en Solidity **0.8.34**. Après la vérif, BscScan **affiche** le compilateur `v0.8.24+commit.89d56535`. La vérif a réussi (bytecode identique) avec le fichier aplati et l’optimizer 200. Si on te pose la question, tu ne inventes pas : tu dis que le `pragma` du dépôt est 0.8.34, que l’écran BscScan indique 0.8.24, et que le critère qui compte est le **match de bytecode**, déjà obtenu. Le détail est dans `BSCSCAN_VERIFICATION.md`. ### `documentation/README.md` Guide utilisateur, pas cours Hardhat. Présentation, réseau, import MetaMask (adresse du contrat, 18 décimales, symbole FG42), lecture BscScan, transfer, tableau sécurité, et un whitepaper court : rôle pédagogique, ce qui existe (transfer, approve), ce qui n’existe pas (mint, burn, pause, multisig). `documentation/STACK-GLOSSAIRE-ET-PARCOURS.md` est le même genre d’explications que cette fiche, mais **dans le rendu**, pour un correcteur qui n’a pas `docs/`. ### Fichiers à ne pas défendre comme le projet `Counter.sol`, `Counter.t.sol`, `test/Counter.ts`, `ignition/modules/Counter.ts`, `scripts/send-op-tx.ts` : générés par l’init Hardhat. Tu peux dire que tu les as laissés. Le token du sujet est uniquement FGC42Forge. --- ## 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 ». **L’owner est-il dangereux ?** Il peut changer l’adresse `owner`. Il ne peut pas piocher dans les soldes des autres ni augmenter l’offre. Un transfer part toujours du signataire de la transaction (`msg.sender`), pas de l’owner. **Et si quelqu’un a la clé de FGC_account ?** Cette personne possède les FG42 encore sur ce compte, le tBNB restant, et le rôle owner. Elle ne peut pas en fabriquer de nouveaux. C’est pour ça que la clé reste hors du Git et que le compte ne porte pas de vrais fonds. **Pourquoi pas de burn ?** Pas demandé. L’offre reste à 1 000 000 pour que `totalSupply` soit un chiffre stable en démo. **Pourquoi pas de multisig ?** Le bonus du chapitre V demande plusieurs signataires avant une action sensible. Tu ne l’as pas implémenté pour garder un obligatoire simple et explicable. Le README le dit. Le bonus n’est évalué que si l’obligatoire est sans faute ; tu ne le présentes pas comme fait. **Le token a-t-il une valeur ?** Non. Testnet. Le dire évite la confusion avec un vrai actif. **Approve, c’est quoi le risque ?** `approve(spender, montant)` autorise une autre adresse à appeler `transferFrom` sur tes jetons, dans la limite du montant. Tu ne t’en sers pas dans la démo. Si on te le demande : ne jamais approve un contrat inconnu pour une somme illimitée. Ici aucun contrat tiers n’est prévu. --- ## 15. Carte « on me demande X → j’ouvre Y » | On te demande | Fichier dans le rendu | |---------------|------------------------| | Choix et pourquoi | `README.md` section Choix techniques | | Adresse, réseau, deployer | `README.md` et `deployment/addresses.json` | | Utiliser le token sans coder | `documentation/README.md` | | Définition Hardhat, MetaMask, alternatives | `documentation/STACK-GLOSSAIRE-ET-PARCOURS.md` | | Le programme du jeton | `code/contracts/FGC42Forge.sol` | | Preuve automatique | `code/test/FGC42Forge.ts` | | Comment c’est compilé et sur quel réseau | `code/hardhat.config.ts` | | Comment redéployer | `code/ignition/modules/FGC42Forge.ts` et `deployment/README.md` | | Preuve explorateur | `deployment/BSCSCAN_VERIFICATION.md` | | Le source tel que BscScan l’a reçu | `deployment/FGC42Forge_flat.sol` | Grille des obligations du PDF (nom avec 42, testnet, 3 dossiers, README, code commenté, démo, doc utilisateur) : [`sujet-exigences-rendu.md`](sujet-exigences-rendu.md). Checklist clics : [`checklist-demo-evaluation.md`](checklist-demo-evaluation.md).