etape4ignition
This commit is contained in:
@@ -56,6 +56,17 @@
|
||||
| **Privilèges owner** | `transferOwnership` / `renounceOwnership` | **Pas de mint** : en soutenance tu expliques que l’admin ne peut pas diluer la supply, seulement transférer le rôle admin. | Sujet ch. IV (sécurité, démo minimale) |
|
||||
| **Fichier contrat prévu** | `FGC42Forge.sol` | Nom de fichier explicite pour la **code review**. | Sujet ch. IV (`code/`, noms lisibles) |
|
||||
|
||||
### ERC-20 dans le code, BEP-20 à l’évaluation (mémo soutenance)
|
||||
|
||||
| Question | Réponse courte |
|
||||
|----------|----------------|
|
||||
| Le sujet cite **ERC-20** ? | Oui, comme norme **générique** EVM ; sur **BSC** le sujet attend le standard de la chaîne : **BEP-20**. |
|
||||
| Pourquoi `import ERC20` et pas `BEP20` ? | OpenZeppelin (et la quasi-totalité des projets BSC) utilisent le contrat **`ERC20`** ; l’interface est la même. |
|
||||
| Qu’est-ce qui fait « BEP-20 » ? | Le **déploiement sur BNB Chain** (testnet 97) + respect de l’interface (`transfer`, `balanceOf`, etc.) ; **BscScan** qualifie le contrat en **BEP-20**. |
|
||||
| Phrase à dire le jour J | *« Mon token est **BEP-20** sur BSC Testnet ; le Solidity hérite d’**OpenZeppelin ERC20**, l’équivalent ERC-20 sur cette chaîne. »* |
|
||||
|
||||
Réf. : [sujet § ERC-20 / BEP-20](../sujets/tokenizer.md#erc-20-et-bep-20-éclaircissement) · [02-web3 § 6](02-web3-comprendre.md#6-standards-erc-20-et-bep-20)
|
||||
|
||||
### Lore / justification (pour `documentation/` et whitepaper léger)
|
||||
|
||||
| Aspect | Texte proposé |
|
||||
|
||||
@@ -2,53 +2,177 @@
|
||||
|
||||
> **Sujet (ch. IV) :** dossier **`code/`** à la racine du dépôt école ; maîtriser la toolchain (Hardhat cité) ; code commenté plus tard (étape 3).
|
||||
> **Prérequis :** étape 1 ✅ (réseau BSC Testnet 97, tBNB sur **FGC_account**).
|
||||
> **Lire d’abord (recommandé) :** [Hardhat et alternatives](03-hardhat-et-alternatives.md) · [Ressources Solidity / Hardhat](ressources-solidity-hardhat.md) (§ 2 + § 8 plan minimum).
|
||||
> **Lire d’abord (recommandé) :** [Hardhat et alternatives](../03-hardhat-et-alternatives.md) · [Ressources Solidity / Hardhat](../ressources-solidity-hardhat.md) (§ 2 + § 8 plan minimum).
|
||||
|
||||
---
|
||||
|
||||
## Objectif
|
||||
## Objectif (en une phrase)
|
||||
|
||||
Avoir un projet **Node + Hardhat** compilable dans `tokenizerRendu/code/`, prêt pour le contrat **FGC42Forge** (étape 3).
|
||||
Tu installes sur ta machine une **chaîne d’outils** (Node + Hardhat) qui va **compiler** du Solidity, **lancer des tests** et **déployer** sur BSC Testnet — sans écrire encore ton token **FGC42Forge** (étape 3).
|
||||
|
||||
### Rappel pédagogique : qui fait quoi ?
|
||||
|
||||
| Élément | Rôle |
|
||||
|--------|------|
|
||||
| **Solidity** | Langage des contrats (`FGC42Forge.sol`, plus tard). |
|
||||
| **Hardhat** | Programme Node.js : compile, tests, scripts de déploiement. |
|
||||
| **OpenZeppelin** | Bibliothèque de contrats éprouvés (`ERC20`, `Ownable`) — installée maintenant, utilisée à l’étape 3. |
|
||||
| **`.env`** | Fichier local avec RPC + clé privée — lu par `hardhat.config.js`, **jamais** dans Git. |
|
||||
|
||||
---
|
||||
|
||||
## À faire (checklist)
|
||||
## Vue d’ensemble des sous-étapes
|
||||
|
||||
### A. Environnement
|
||||
1. **A** — Vérifier Node.js et se placer dans `tokenizerRendu/code/`
|
||||
2. **B** — Créer `package.json` et installer Hardhat
|
||||
3. **C** — Lancer `npx hardhat init` (assistant interactif)
|
||||
4. **D** — Installer OpenZeppelin + `dotenv`
|
||||
5. **E** — Configurer `hardhat.config.js` pour **BSC Testnet (chainId 97)**
|
||||
6. **F** — Créer `.env` (secret) et `.env.example` (modèle pour le rendu)
|
||||
7. **G** — `npx hardhat compile` (preuve que tout fonctionne)
|
||||
8. **H** — Compléter `code/README.md`
|
||||
|
||||
- [ ] **Node.js** ≥ 18 : `node -v` dans le terminal
|
||||
- [ ] Répertoire de travail : `tokenizerRendu/code/`
|
||||
Durée indicative : **30–45 min** la première fois (surtout la lecture des menus `hardhat init`).
|
||||
|
||||
### B. Créer le projet Hardhat
|
||||
---
|
||||
|
||||
Depuis la racine du dépôt tokenizer :
|
||||
## A. Environnement
|
||||
|
||||
### Où travailler ?
|
||||
|
||||
Le sujet demande le code dans **`tokenizerRendu/code/`** (dépôt de rendu), pas à la racine `tokenizer/` du dépôt de travail.
|
||||
|
||||
```bash
|
||||
cd /home/fgras-ca/projets/42School/tokenizer/tokenizerRendu/code
|
||||
pwd # doit finir par .../tokenizerRendu/code
|
||||
```
|
||||
|
||||
### Node.js
|
||||
|
||||
```bash
|
||||
node -v # idéalement ≥ 18 (ex. v20, v22)
|
||||
npm -v
|
||||
```
|
||||
|
||||
Si `node` est introuvable : installer [Node.js LTS](https://nodejs.org/) ou utiliser `nvm`.
|
||||
|
||||
**Checklist :**
|
||||
|
||||
- [ ] `node -v` OK
|
||||
- [ ] Tu es dans `tokenizerRendu/code/`
|
||||
|
||||
---
|
||||
|
||||
## B. Créer le projet npm
|
||||
|
||||
`npm init -y` crée un **`package.json`** minimal : nom du projet, scripts, liste des dépendances.
|
||||
|
||||
```bash
|
||||
cd tokenizerRendu/code
|
||||
npm init -y
|
||||
```
|
||||
|
||||
Tu dois voir un fichier `package.json` apparaître dans `code/`.
|
||||
|
||||
Puis installer Hardhat et le **toolbox** (plugins officiels : tests, Ethers, etc.) :
|
||||
|
||||
```bash
|
||||
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox
|
||||
```
|
||||
|
||||
- `--save-dev` = outils de développement uniquement (pas besoin sur la blockchain).
|
||||
- Première install : **téléchargement** depuis le registre npm → connexion Internet requise.
|
||||
|
||||
**Checklist :**
|
||||
|
||||
- [ ] `package.json` présent
|
||||
- [ ] Dossier `node_modules/` créé (ignoré par Git via `.gitignore` parent)
|
||||
|
||||
---
|
||||
|
||||
## C. Assistant d’initialisation Hardhat
|
||||
|
||||
Tu as installé **Hardhat 3** (ex. `3.20.x` via `npm install hardhat`). À partir de la v3, la commande a changé :
|
||||
|
||||
```bash
|
||||
npx hardhat --init
|
||||
```
|
||||
|
||||
> **Erreur HHE3** avec `npx hardhat init` ? C’est normal : l’ancienne sous-commande `init` n’existe plus. Le message te dit d’utiliser **`--init`** (avec deux tirets).
|
||||
|
||||
Lance **`npx hardhat --init` dans ton terminal** (pas dans un environnement non interactif) : Hardhat affiche le logo et te pose des questions.
|
||||
|
||||
`npx` exécute le binaire Hardhat **sans** l’installer globalement.
|
||||
|
||||
### Variante (tutos Hardhat 2 uniquement)
|
||||
|
||||
Si tu veux coller aux vieux tutos (`hardhat init` + `hardhat.config.js` + `npx hardhat compile`), tu peux **épingler Hardhat 2** avant d’initialiser :
|
||||
|
||||
```bash
|
||||
npm uninstall hardhat @nomicfoundation/hardhat-toolbox
|
||||
npm install --save-dev hardhat@2.22.19 @nomicfoundation/hardhat-toolbox@5
|
||||
npx hardhat init
|
||||
```
|
||||
|
||||
Lors de `hardhat init`, choisir :
|
||||
Pour ce projet 42, **Hardhat 3 + `--init`** convient très bien ; on adaptera la config réseau BSC après l’assistant (souvent `hardhat.config.ts` + `npx hardhat build` au lieu de `compile`).
|
||||
|
||||
- **Create a TypeScript project** ou **JavaScript** (les deux conviennent ; JavaScript = plus simple pour 42)
|
||||
- Générer un `hardhat.config` et un exemple `contracts/Lock.sol` — tu pourras **supprimer** `Lock.sol` à l’étape 3
|
||||
### Choix recommandés (JavaScript, plus simple pour ce projet)
|
||||
|
||||
Puis :
|
||||
Les libellés peuvent varier légèrement selon la version de Hardhat ; l’idée :
|
||||
|
||||
| Question | Choix conseillé | Pourquoi |
|
||||
|----------|-----------------|----------|
|
||||
| Type de projet | **Create a JavaScript project** | Moins de config TypeScript pour commencer |
|
||||
| Emplacement du config | **Oui** / racine de `code/` | `hardhat.config.js` à côté de `package.json` |
|
||||
| Projet vide ou exemple ? | **Oui, exemple** (Lock) | Tu vérifies compile + tests ; Lock supprimé à l’étape 3 |
|
||||
| `.gitignore` dans `code/` ? | **Non** si déjà couvert par `tokenizerRendu/.gitignore` | Évite les doublons ; le parent ignore déjà `node_modules`, `cache`, `artifacts` |
|
||||
|
||||
### Arborescence typique après init
|
||||
|
||||
```
|
||||
tokenizerRendu/code/
|
||||
├── contracts/
|
||||
│ └── Lock.sol # exemple — temporaire
|
||||
├── test/
|
||||
│ └── Lock.js # tests de l’exemple
|
||||
├── scripts/
|
||||
│ └── (deploy Lock, etc.)
|
||||
├── hardhat.config.js
|
||||
├── package.json
|
||||
└── package-lock.json
|
||||
```
|
||||
|
||||
**Checklist :**
|
||||
|
||||
- [ ] `hardhat.config.js` existe
|
||||
- [ ] `contracts/Lock.sol` existe (pour l’instant)
|
||||
|
||||
---
|
||||
|
||||
## D. OpenZeppelin et dotenv
|
||||
|
||||
```bash
|
||||
npm install @openzeppelin/contracts
|
||||
npm install dotenv
|
||||
```
|
||||
|
||||
### C. Configurer BSC Testnet (sans déployer encore)
|
||||
- **OpenZeppelin** : tu n’importes rien encore ; c’est pour l’étape 3 (`import "@openzeppelin/contracts/..."`).
|
||||
- **dotenv** : charge les variables du fichier `.env` dans `process.env` au lancement de Hardhat.
|
||||
|
||||
Dans `hardhat.config.js`, ajouter le réseau (les clés viendront du `.env` à l’étape 4) :
|
||||
**Checklist :**
|
||||
|
||||
- [ ] Les deux paquets listés dans `package.json` → `dependencies` ou `devDependencies`
|
||||
|
||||
---
|
||||
|
||||
## E. Configurer BSC Testnet dans `hardhat.config.js`
|
||||
|
||||
Ouvre `hardhat.config.js` et remplace son contenu par (ou fusionne proprement si tu préfères) :
|
||||
|
||||
```javascript
|
||||
require("@nomicfoundation/hardhat-toolbox");
|
||||
require("dotenv").config();
|
||||
|
||||
/** @type import('hardhat/config').HardhatUserConfig */
|
||||
module.exports = {
|
||||
solidity: "0.8.24",
|
||||
networks: {
|
||||
@@ -61,49 +185,127 @@ module.exports = {
|
||||
};
|
||||
```
|
||||
|
||||
```bash
|
||||
npm install dotenv
|
||||
```
|
||||
### Ce que signifient les lignes importantes
|
||||
|
||||
Créer **`tokenizerRendu/code/.env`** (jamais commité) :
|
||||
- **`solidity: "0.8.24"`** : version du compilateur pour tous les contrats (alignée avec OpenZeppelin récent).
|
||||
- **`bscTestnet`** : nom **local** du réseau ; tu l’utiliseras plus tard avec `--network bscTestnet`.
|
||||
- **`chainId: 97`** : identifiant officiel BNB Smart Chain **Testnet** (doit correspondre à MetaMask).
|
||||
- **`accounts`** : si `PRIVATE_KEY` est vide, tableau vide → compile/tests locaux OK ; **déploiement** testnet nécessitera la clé (étape déploiement).
|
||||
|
||||
Tu ne déploies **pas** sur le testnet dans cette étape : tu prépares seulement la config.
|
||||
|
||||
**Checklist :**
|
||||
|
||||
- [ ] `require("dotenv").config();` présent
|
||||
- [ ] `chainId: 97` présent
|
||||
|
||||
---
|
||||
|
||||
## F. Fichiers `.env` et `.env.example`
|
||||
|
||||
### Sécurité (à lire une fois pour toute la suite)
|
||||
|
||||
- La **clé privée** = contrôle total du compte → **compte de test uniquement** (FGC_account).
|
||||
- **Ne jamais** : commit Git, capture d’écran publique, message Discord/chat avec la clé.
|
||||
- Si tu as un `.env` à la racine `tokenizer/` (dépôt travail), le secret pour Hardhat doit vivre dans **`tokenizerRendu/code/.env`** (celui que lit `hardhat.config.js`).
|
||||
|
||||
### `tokenizerRendu/code/.env` (local, ignoré par Git)
|
||||
|
||||
Crée le fichier à la main :
|
||||
|
||||
```env
|
||||
BSC_TESTNET_RPC=https://data-seed-prebsc-1-s1.binance.org:8545/
|
||||
PRIVATE_KEY=0x... # MetaMask → FGC_account → Détails → Afficher clé privée (compte TEST uniquement)
|
||||
PRIVATE_KEY=0x................................................................
|
||||
```
|
||||
|
||||
Créer **`tokenizerRendu/code/.env.example`** (sans vraie clé) pour le rendu :
|
||||
**Obtenir la clé (MetaMask)** : compte **FGC_account** → ⋮ → **Détails du compte** → **Afficher la clé privée** (mot de passe MetaMask) → copier **avec** le préfixe `0x`.
|
||||
|
||||
### `tokenizerRendu/code/.env.example` (à committer)
|
||||
|
||||
Même structure, **sans** vraie clé :
|
||||
|
||||
```env
|
||||
BSC_TESTNET_RPC=https://data-seed-prebsc-1-s1.binance.org:8545/
|
||||
PRIVATE_KEY=
|
||||
```
|
||||
|
||||
Vérifier que `code/.gitignore` contient `.env` (ou le `.gitignore` parent du rendu).
|
||||
Le `.gitignore` du rendu (`tokenizerRendu/.gitignore`) contient déjà `.env` et autorise `.env.example` via `!.env.example`.
|
||||
|
||||
### D. Vérifier que tout compile
|
||||
**Checklist :**
|
||||
|
||||
- [ ] `.env` créé dans **`code/`** (pas seulement à la racine tokenizer)
|
||||
- [ ] `.env.example` créé
|
||||
- [ ] `git status` ne liste **pas** `.env` comme fichier à committer
|
||||
|
||||
---
|
||||
|
||||
## G. Vérifier la compilation
|
||||
|
||||
```bash
|
||||
npx hardhat compile
|
||||
```
|
||||
|
||||
→ doit se terminer sans erreur (même avec le contrat exemple Lock).
|
||||
### Sortie attendue (succès)
|
||||
|
||||
### E. Mettre à jour `code/README.md`
|
||||
Quelque chose comme :
|
||||
|
||||
Courte section : comment `npm install`, `npx hardhat compile`, où est le `.env.example`.
|
||||
```
|
||||
Compiled 1 Solidity file successfully (evm target: paris).
|
||||
```
|
||||
|
||||
Des dossiers **`cache/`** et **`artifacts/`** apparaissent (déjà ignorés par Git).
|
||||
|
||||
### Tests optionnels (exemple Lock)
|
||||
|
||||
```bash
|
||||
npx hardhat test
|
||||
```
|
||||
|
||||
Si les tests passent, Hardhat + toolbox sont bien branchés. Ce n’est pas obligatoire pour valider l’étape 2, mais c’est rassurant.
|
||||
|
||||
### Dépannage rapide
|
||||
|
||||
| Problème | Piste |
|
||||
|----------|--------|
|
||||
| **HHE3** — `No Hardhat config` + « run with **--init** » | Utiliser `npx hardhat --init` (Hardhat 3), pas `npx hardhat init` |
|
||||
| **HHE11** — pas de shell interactif | Lancer `--init` dans **ton** terminal Cursor / système |
|
||||
| `Cannot find module '@nomicfoundation/hardhat-toolbox'` | Relancer `npm install` dans `code/` |
|
||||
| Erreur Solidity / version | Vérifier `solidity` dans `hardhat.config.js` et la version en tête de `Lock.sol` |
|
||||
| `PRIVATE_KEY` / invalid account | Normal si clé mal formatée ; **compile** ne nécessite pas la clé. Corriger avant déploiement. |
|
||||
| Permission réseau npm | Vérifier proxy / réseau ; réessayer `npm install` |
|
||||
|
||||
**Checklist :**
|
||||
|
||||
- [ ] `npx hardhat compile` **sans erreur**
|
||||
|
||||
---
|
||||
|
||||
## Livrable pour vérification
|
||||
## H. Mettre à jour `code/README.md`
|
||||
|
||||
Envoie dans le chat :
|
||||
Ajoute une section courte (en français pour ton suivi ; README école final plus tard si besoin) :
|
||||
|
||||
- Prérequis : Node ≥ 18
|
||||
- `cd code && npm install`
|
||||
- Copier `.env.example` → `.env` et remplir `PRIVATE_KEY`
|
||||
- `npx hardhat compile`
|
||||
- Prochaine étape : contrat **FGC42Forge** (étape 3)
|
||||
|
||||
---
|
||||
|
||||
## Livrable pour vérification (dans le chat)
|
||||
|
||||
1. « Étape 2 terminée »
|
||||
2. Résultat de `npx hardhat compile` (succès)
|
||||
3. Confirmation : `.env` **non** commité, `.env.example` présent
|
||||
2. Copier **uniquement** la dernière ligne de succès de `npx hardhat compile` (pas de `.env`)
|
||||
3. Confirmer : `.env.example` présent, `.env` **non** commité
|
||||
|
||||
**Ne pas envoyer** la clé privée dans le chat.
|
||||
**Ne pas envoyer** la clé privée.
|
||||
|
||||
---
|
||||
|
||||
## Après cette étape
|
||||
|
||||
- **Étape 3** : supprimer `Lock.sol`, ajouter `FGC42Forge.sol` (supply 1 000 000, pas de mint, `Ownable`), tests.
|
||||
- **Déploiement testnet** : plus tard, avec `npx hardhat run scripts/... --network bscTestnet`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
75
docs/pedagogie/etapes/etape-04-deploy-testnet.md
Normal file
75
docs/pedagogie/etapes/etape-04-deploy-testnet.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Étape 4 — Déployer sur BSC Testnet + dossier `deployment/`
|
||||
|
||||
> **Prérequis :** étapes 1–3 ✅ (`FGC42Forge.sol`, tests Mocha OK, `bscTestnet` dans `hardhat.config.ts`, `.env` local).
|
||||
> **Sujet :** déploiement sur **chaîne publique de test**, adresse + réseau dans le dépôt Git, explorer (BscScan).
|
||||
|
||||
---
|
||||
|
||||
## Objectif
|
||||
|
||||
Avoir le contrat **FGC42Forge** déployé sur **BNB Smart Chain Testnet** (chainId **97**), avec l’adresse documentée dans `tokenizerRendu/deployment/` et le README école.
|
||||
|
||||
---
|
||||
|
||||
## 4.1 — Module Ignition (déjà dans le repo)
|
||||
|
||||
Fichier : `tokenizerRendu/code/ignition/modules/FGC42Forge.ts`
|
||||
|
||||
Il déclare uniquement `m.contract("FGC42Forge")` : pas d’arguments, le constructeur Solidity fait le mint.
|
||||
|
||||
Vérifier la compile :
|
||||
|
||||
```bash
|
||||
cd tokenizerRendu/code
|
||||
npx hardhat build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4.2 — Lancer le déploiement (à faire **toi-même**)
|
||||
|
||||
```bash
|
||||
cd tokenizerRendu/code
|
||||
npx hardhat ignition deploy --network bscTestnet ignition/modules/FGC42Forge.ts
|
||||
```
|
||||
|
||||
| Problème possible | Piste |
|
||||
|-------------------|--------|
|
||||
| `ENV_VAR_NOT_FOUND` / clé manquante | `code/.env` avec `PRIVATE_KEY` et `BSC_TESTNET_RPC` |
|
||||
| `insufficient funds` | Recharger **tBNB** sur le compte deployer |
|
||||
| Mauvais réseau | MetaMask pas requis ici ; Hardhat signe avec `PRIVATE_KEY` |
|
||||
|
||||
**Ne pas** coller la clé privée dans le chat.
|
||||
|
||||
---
|
||||
|
||||
## 4.3 — Enregistrer l’adresse
|
||||
|
||||
1. `cp deployment/addresses.json.example deployment/addresses.json`
|
||||
2. Remplir `address`, `deployer`, `deployedAt`, `explorer` (URL BscScan).
|
||||
3. Mettre à jour `tokenizerRendu/README.md` (table Token).
|
||||
|
||||
---
|
||||
|
||||
## 4.4 — Vérifier sur BscScan (sujet)
|
||||
|
||||
- Ouvrir l’adresse sur https://testnet.bscscan.com/
|
||||
- Vérifier **nom / symbole** du token si l’explorer les affiche.
|
||||
- Option **Verify and Publish** : uploader le source (Hardhat artifact / standard JSON).
|
||||
|
||||
---
|
||||
|
||||
## Livrable pour vérification (chat)
|
||||
|
||||
1. « Étape 4 deploy OK »
|
||||
2. Adresse du contrat `0x...` (publique)
|
||||
3. Lien BscScan
|
||||
4. Confirmation : `deployment/addresses.json` rempli, pas de secret commité
|
||||
|
||||
---
|
||||
|
||||
## Références
|
||||
|
||||
- [deployment/README.md](../../../tokenizerRendu/deployment/README.md)
|
||||
- [decisions-projet.md](../decisions-projet.md)
|
||||
- [sujet ch. IV](../../sujets/tokenizer.md)
|
||||
@@ -17,9 +17,9 @@
|
||||
| # | Fichier guide | Objectif | Statut |
|
||||
|---|---------------|----------|--------|
|
||||
| **1** | [etapes/etape-01-cadrage-wallet-testnet.md](etapes/etape-01-cadrage-wallet-testnet.md) | Décisions token + BSC testnet + tBNB | ✅ **Validée** (0,1 tBNB Telegram) |
|
||||
| **2** | [etapes/etape-02-init-hardhat.md](etapes/etape-02-init-hardhat.md) | Init Hardhat dans `tokenizerRendu/code/` | 🔄 **En cours** |
|
||||
| **3** | *(à venir)* | Contrat BEP-20 + tests | ⏳ |
|
||||
| **4** | *(à venir)* | Dossier `deployment/` + deploy + BscScan | ⏳ |
|
||||
| **2** | [etapes/etape-02-init-hardhat.md](etapes/etape-02-init-hardhat.md) | Init Hardhat dans `tokenizerRendu/code/` | ✅ |
|
||||
| **3** | *(contrat + tests)* | `FGC42Forge.sol` + tests Mocha | ✅ |
|
||||
| **4** | [etapes/etape-04-deploy-testnet.md](etapes/etape-04-deploy-testnet.md) | Dossier `deployment/` + deploy + BscScan | 🔄 **En cours** |
|
||||
| **5** | *(à venir)* | `documentation/` utilisateur + README école (choix, adresse) | ⏳ |
|
||||
| **6** | *(à venir)* | Démo minimale + préparation code review | ⏳ |
|
||||
| **7** | *(à venir)* | Bonus multisig (optionnel) | ⏳ |
|
||||
|
||||
Reference in New Issue
Block a user