diff --git a/fr/1/arrays.md b/fr/1/arrays.md index 564f1e7f84..ca9bcc3e19 100644 --- a/fr/1/arrays.md +++ b/fr/1/arrays.md @@ -46,7 +46,7 @@ Quand vous voulez regrouper des éléments, vous pouvez utiliser un **_tableau_* uint[2] fixedArray; // Un autre Tableau fixe, qui peut contenir 5 `string` : string[5] stringArray; -// un Tableau dynamique, il n'a pas de taille fixe, il peut continuer de grandir : +// un Tableau dynamique. Il n'a pas de taille fixe, il peut continuer de grandir : uint[] dynamicArray; ``` @@ -56,7 +56,7 @@ Vous pouvez aussi créer un tableau de **_structure_**. En utilisant la structur Person[] people; // Tableau dynamique, on peut en rajouter sans limite. ``` -Vous vous rappelez que les variables d'état sont stockées définitivement dans la blockchain ? Il peut donc être utile de créer des tableaux dynamique de structure pour stocker des données structurées dans votre contrat, un peu comme une base de données. +Vous vous rappelez que les variables d'état sont stockées définitivement dans la blockchain ? Il peut donc être utile de créer des tableaux dynamiques de structure pour stocker des données structurées dans votre contrat, un peu comme une base de données. ## Tableaux publics @@ -69,6 +69,6 @@ Les autres contrats vont pouvoir lire (mais pas écrire) ce tableau. C'est donc # A votre tour -Nous allons vouloir stocker une armée de zombies dans notre application. Et nous allons vouloir montrer tous nos zombies à d'autres applications, cette armée devra donc être publique. +Nous allons vouloir stocker une armée de zombies dans notre application. Et nous allons vouloir montrer tous nos zombies à d'autres applications. Cette armée devra donc être publique. 1. Créez un tableau public de **_structures_** `Zombie`, et appelez le `zombies`. diff --git a/fr/1/arraysstructs2.md b/fr/1/arraysstructs2.md index c4782227f6..fe303747f6 100644 --- a/fr/1/arraysstructs2.md +++ b/fr/1/arraysstructs2.md @@ -89,6 +89,6 @@ numbers.push(15); Faisons faire quelque chose à notre fonction createZombie ! -1. Remplissez le corps de la fonction afin qu'elle crée un nouveau `Zombie` et qu'elle l'ajoute au tableau `zombies`. Les noms `name` et `dna` pour le nouveau Zombie devraient provenir des arguments de la fonction. +1. Remplissez le corps de la fonction afin qu'elle créée un nouveau `Zombie` et qu'elle l'ajoute au tableau `zombies`. Les noms `name` et `dna` pour le nouveau Zombie devraient provenir des arguments de la fonction. 2. Faites-le en une ligne de code pour garder les choses concises. diff --git a/fr/1/events.md b/fr/1/events.md index 672a5f2ef7..6f7d0c23ec 100644 --- a/fr/1/events.md +++ b/fr/1/events.md @@ -75,7 +75,7 @@ material: Notre contrat est presque fini ! nous allons maintenant ajouter un **_ évènement _** (event). -Un **_ évènement _** est un moyen pour votre contrat d'indiquer à votre application frontale (front-end) que quelque chose vient d'arriver sur la blockchain, l'application frontale pouvant être «à l'écoute» de certains événements pour prendre des mesures quand ils se produisent. +Un **_ évènement _** est un moyen pour votre contrat d'indiquer à votre application frontale (front-end) que quelque chose vient d'arriver sur la blockchain, l'application frontale pouvant être « à l'écoute » de certains événements pour prendre des mesures quand ils se produisent. Exemple : @@ -101,7 +101,7 @@ YourContract.IntegersAdded(function(error, result) { # A votre tour -A chaque fois qu'un nouveau zombie est créé, nous voulons qu'un évènement informe l'application frontale, ainsi, elle pourra l'afficher. +A chaque fois qu'un nouveau zombie est créé, nous voulons qu'un évènement informe l'application frontale. Ainsi, elle pourra l'afficher. 1. Déclarez un `event` appelé `NewZombie`. Les arguments devront être `zombieId` (un `uint`), `name` (un `string`), et `dna` (un `uint`). diff --git a/fr/1/functions2.md b/fr/1/functions2.md index 9f048b25fd..5e793605ab 100644 --- a/fr/1/functions2.md +++ b/fr/1/functions2.md @@ -66,6 +66,6 @@ Comme vous pouvez le voir, nous avons utilisé le mot-clé `private` après le n # A votre tour. -La fonction `createZombie` de notre contrat est par défaut publique - cela veut dire que n'importe qui peut l'appeler et créer un nouveau Zombie dans notre contrat ! Changeons la en privée. +La fonction `createZombie` de notre contrat est par défaut publique - cela veut dire que n'importe qui peut l'appeler et créer un nouveau Zombie dans notre contrat ! Changeons-la en privée. 1. Modifiez `createZombie` pour que ce soit une fonction privée. N'oubliez pas la convention de nom ! diff --git a/fr/1/functions3.md b/fr/1/functions3.md index b2909a6fbf..51ecb2e2f7 100644 --- a/fr/1/functions3.md +++ b/fr/1/functions3.md @@ -73,7 +73,7 @@ En Solidity, une déclaration de fonction indique le type de la valeur retourné La fonction ci-dessus ne change pas un état en Solidity - c.-à-d. elle ne change pas une valeur et n'écrit rien. -Dans ce cas là, nous pouvons la déclarer comme une fonction **_view_** (vue), cela veut dire qu'elle va seulement voir des données sans les modifier : +Dans ce cas-là, nous pouvons la déclarer comme une fonction **_view_** (vue), cela veut dire qu'elle va seulement voir des données sans les modifier : ``` function sayHello() public view returns (string) { @@ -85,9 +85,9 @@ function _multiply(uint a, uint b) private pure returns (uint) { return a * b; } ``` -Cette fonction ne lit aucune donnée du contrat - elle retourne une valeur qui dépend seulement de ses arguments. Dans ce cas là, nous déclarerons la fonction comme **_pure_**. +Cette fonction ne lit aucune donnée du contrat - elle retourne une valeur qui dépend seulement de ses arguments. Dans ce cas-là, nous déclarerons la fonction comme **_pure_**. -> Remarque: Il peut être difficile de se rappeler quand marquer les fonctions comme étant pure/view. Heureusement, le compilateur Solidity est bon pour vous avertir quand vous devriez utiliser l'un ou l'autre de ces modificateurs. +> Remarque: Il peut être difficile de se rappeler quand marquer les fonctions comme étant pure/view. Heureusement, le compilateur Solidity est bon pour vous avertir quand vous devez utiliser l'un ou l'autre de ces modificateurs. # A votre tour diff --git a/fr/1/keccak256.md b/fr/1/keccak256.md index acf9d1f5e0..19614a2a97 100644 --- a/fr/1/keccak256.md +++ b/fr/1/keccak256.md @@ -60,9 +60,9 @@ Comment faire pour que notre fonction `_generateRandomDna` retourne un `uint` (p Ethereum a la fonction de hachage `keccak256` intégrée, qui est une variante de SHA3. Une fonction de hachage permet fondamentalement de lier une chaîne d'entrée à un nombre hexadécimal aléatoire de 256 bits. Le moindre changement dans la chaîne provoquera un grand changement dans le hachage. -Cela sert à beaucoup de chose pour Ethereum, mais pour l'instant nous allons simplement l'utiliser pour générer un nombre pseudo-aléatoire. +Cela sert à beaucoup de choses pour Ethereum, mais pour l'instant nous allons simplement l'utiliser pour générer un nombre pseudo-aléatoire. -Exemple: +Exemple : ``` //6e91ec6b618bb462a4a6ee5aa2cb0e9cf30f7a052bb467b0ba58b8748c00d2e5 @@ -72,7 +72,7 @@ keccak256("aaaac"); ``` Comme vous pouvez le voir, les valeurs retournées sont complètement différentes alors qu'il y a seulement 1 caractère de changé à l'argument d'entrée. -> Remarque: La génération de nombres aléatoires **sécurisés** dans la blockchain est un problème très complexe. Notre méthode ici n'est pas sécurisée, mais comme la sécurité n'est pas la grande priorité de notre ADN Zombie, cela sera suffisant pour notre usage. +> Remarque : La génération de nombres aléatoires **sécurisés** dans la blockchain est un problème très complexe. Notre méthode ici n'est pas sécurisée, mais comme la sécurité n'est pas la grande priorité de notre ADN Zombie, cela sera suffisant pour notre usage. ## Conversion de type diff --git a/fr/1/puttingittogether.md b/fr/1/puttingittogether.md index 489475518c..6ee65b0ae9 100644 --- a/fr/1/puttingittogether.md +++ b/fr/1/puttingittogether.md @@ -72,7 +72,7 @@ Nous allons créer une fonction publique qui prend un paramètre, le nom du zomb 1. Créez une fonction `public` nommée `createRandomZombie`. Elle devra prendre seulement un paramètre `_name` (un `string`). _(Remarque : déclarez cette fonction `public`. de la même manière que vous avez déclaré la fonction précédente `private`)_ -2. La première ligne de la fonction devra exécuter la fonction `_generateRandomDna` avec comme argument `_name` and stocker le résultat dans un `uint` nommé `randDna`. +2. La première ligne de la fonction devra exécuter la fonction `_generateRandomDna` avec comme argument `_name` et stocker le résultat dans un `uint` nommé `randDna`. 3. La deuxième ligne devra exécuter la fonction `_createZombie` avec comme arguments `_name` et `randDna`. diff --git a/fr/1/structs.md b/fr/1/structs.md index 0d69061ec3..4e3f689119 100644 --- a/fr/1/structs.md +++ b/fr/1/structs.md @@ -44,11 +44,11 @@ struct Person { Les structures vous permettent de créer des types de données plus complexes avec plusieurs propriétés. -> Remarque : Nous venons d'introduire un nouveau type, `string` (Chaîne de caractères). Les chaînes de caractères sont utilisées pour les données UTF-8 de longueur arbitraire. Ex. `string greeting = "Hello world!"` +> Remarque : Nous venons d'introduire un nouveau type, `string` (Chaîne de caractères). Les chaînes de caractères sont utilisées pour les données UTF-8 de longueur arbitraire. Exemple : `string greeting = "Hello world!"` # A votre tour -Dans notre application, nous allons vouloir créer des zombies ! Et les zombies ont plusieurs propriétés, une structure est parfaitement adapté pour ça. +Dans notre application, nous allons vouloir créer des zombies ! Et les zombies ont plusieurs propriétés, une structure est parfaitement adaptée pour ça. 1. Créez une `struct` nommée `Zombie`. diff --git a/fr/1/web3js.md b/fr/1/web3js.md index 08b199ade8..4bd161c52a 100644 --- a/fr/1/web3js.md +++ b/fr/1/web3js.md @@ -69,10 +69,10 @@ function generateZombie(id, name, dna) { } ``` -Notre code JavaScript prends alors les valeurs générées dans `zombieDetails` ci-dessus, et utilise de la magie JavaScript (nous utilisons Vue.js) pour changer les images et appliquer des filtres CSS. Vous obtiendrez tout le code nécessaire dans une prochaine leçon. +Notre code JavaScript prend alors les valeurs générées dans `zombieDetails` ci-dessus, et utilise de la magie JavaScript (nous utilisons Vue.js) pour changer les images et appliquer des filtres CSS. Vous obtiendrez tout le code nécessaire dans une prochaine leçon. # A votre tour d’essayer ! -Allez-y - rentrer un nom dans le champ à droite, et regardez quel zombie vous obtiendrez ! +Allez-y ! Entrez un nom dans le champ à droite, et regardez quel zombie vous obtiendrez ! **Une fois que vous avez un zombie qui vous satisfait, cliquez sur "Prochain Chapitre" ci-dessous pour enregistrer votre zombie et terminer la leçon 1 !** diff --git a/fr/2/00-overview.md b/fr/2/00-overview.md index 8ffaec7fe8..42bd9a0894 100644 --- a/fr/2/00-overview.md +++ b/fr/2/00-overview.md @@ -4,8 +4,8 @@ header: Alors, vous êtes arrivé à la Leçon 2 ! roadmap: roadmap2.jpg --- -Vous m'impressionnez humain ! Vous êtes un meilleur codeur que j'aurais pensé. +Vous m'impressionnez humain ! Vous êtes un meilleur codeur que je ne l'aurais pensé. -La Leçon 2 va vous apprendre à **multiplier votre armée de zombie en les nourrissant avec d'autres formes de vie**. +La leçon 2 va vous apprendre à **multiplier votre armée de zombie en les nourrissant avec d'autres formes de vie**. -Nous allons voir des concepts Solidity plus avancés, nous vous recommandons fortement d'avoir fini la Leçon 1 avant de commencer. +Nous allons voir des concepts Solidity plus avancés, nous vous recommandons fortement d'avoir fini la leçon 1 avant de commencer. diff --git a/fr/2/1-overview.md b/fr/2/1-overview.md index 8b50610eee..6d458b3625 100644 --- a/fr/2/1-overview.md +++ b/fr/2/1-overview.md @@ -11,26 +11,26 @@ material: answer: 1 --- -Avec la Leçon 1, nous avons créé une fonction qui prend un nom, et qui l'utilise pour générer un zombie aléatoire, ce zombie est ajouté à la base de donnée de notre jeu stockée sur la blockchain. +Durant la leçon 1, nous avons créé une fonction qui prend un nom, et qui l'utilise pour générer un zombie aléatoire. Ce zombie est ajouté à la base de données de notre jeu stockée sur la blockchain. -Avec la Leçon 2, nous allons modifier notre application pour qu'elle ressemble plus à un jeu : Nous allons la rendre multijoueur, et nous allons aussi ajouter des manières plus amusantes de créer des zombies, au lieu de les générer juste aléatoirement. +Dans la leçon 2, nous allons modifier notre application pour qu'elle ressemble plus à un jeu : Nous allons la rendre multijoueur, et nous allons aussi ajouter des manières plus amusantes de créer des zombies, au lieu de simplement les générer aléatoirement. -Comment allons nous créer de nouveaux zombies ? En faisant manger d'autres formes de vie à nos zombies ! +Comment allons-nous créer de nouveaux zombies ? En faisant manger d'autres formes de vie à nos zombies ! ## Alimentation des zombies -Quand un zombie mange, il infecte l'hôte avec un virus. Le virus transforme l'hôte en un nouveau zombie qui va rejoindre votre armée. L'ADN du nouveau zombie va être calculée à partir de l'ADN du zombie et de l'ADN de l'hôte. +Quand un zombie mange, il infecte l'hôte avec un virus. Le virus transforme ainsi l'hôte en un nouveau zombie qui rejoindra votre armée. L'ADN du nouveau zombie va être calculé à partir de l'ADN du zombie et de l'ADN de l'hôte. -Et qu'est ce que les zombie préfèrent manger ? +Et qu'est-ce que les zombie préfèrent manger ? -Pour le savoir... Vous allez devoir finir la Leçon 2 ! +Pour le savoir... Vous allez devoir finir la leçon 2 ! # A votre tour -Il y a un petit exemple à droite. Cliquez sur un humain pour voir ce qu'il arrive quand votre zombie le mange ! +Il y a un petit exemple à droite. Cliquez sur un humain pour voir ce qui se passe lorsque votre zombie le mange ! -Vous pouvez voir que l'ADN du nouveau zombie est déterminée par l'ADN de votre zombie et celui de l'hôte. +Vous pouvez voir que l'ADN du nouveau zombie est déterminé par l'ADN de votre zombie et celui de l'hôte. Quand vous êtes prêt, cliquez sur "Prochain Chapitre" et nous allons rendre ce jeu multijoueur. diff --git a/fr/2/10-interactingcontracts.md b/fr/2/10-interactingcontracts.md index 7f30f50ad8..2557fc4010 100644 --- a/fr/2/10-interactingcontracts.md +++ b/fr/2/10-interactingcontracts.md @@ -95,7 +95,7 @@ material: } --- -Il est temps de nourrir nos zombies ! Et qu'est ce que les zombies aiment manger par dessus tout ? +Il est temps de nourrir nos zombies ! Et qu'est-ce que les zombies aiment manger par dessus tout ? Eh bien, il se trouve que les CryptoZombies adorent manger des... @@ -126,11 +126,11 @@ contract LuckyNumber { } } ``` -Cela serait un simple contrat où n'importe qui pourrait stocker son nombre porte-bonheur, et il serait associé à leur adresse Ethereum. Ensuite n'importe qui pourrait regarder leur nombre porte-bonheur en utilisant leur adresse. +Cela serait un simple contrat où n'importe qui pourrait stocker son nombre porte-bonheur, et il serait associé à leur adresse Ethereum. Ensuite, n'importe qui pourrait regarder leur nombre porte-bonheur en utilisant leur adresse. Maintenant, imaginons que nous avons un contrat externe qui voudrait lire les données de ce contrat en utilisant la fonction `getNum`. -Premièrement, nous devrions définir une **_interface_** du contract `LuckyNumber` : +Premièrement, nous devrions définir une **_interface_** du contrat `LuckyNumber` : ``` contract NumberInterface { @@ -138,15 +138,15 @@ contract NumberInterface { } ``` -Vous remarquerez que cela ressemble à la définition d'un contrat, avec quelques différences. Premièrement nous déclarons seulement les fonctions avec lesquelles nous souhaitons interagir - dans ce cas, `getNum` - et nous ne mentionnons aucune autre fonction ou variable. +Vous remarquerez que cela ressemble à la définition d'un contrat, avec quelques nuances. Premièrement, nous déclarons seulement les fonctions avec lesquelles nous souhaitons interagir - dans ce cas, `getNum` - et nous ne mentionnons aucune autre fonction ou variable. -Deuxièmement, nous ne définissons par de corps de fonction, à la place des `{` et `}`, nous finissons simplement la déclaration de la fonction avec un `;`. +Deuxièmement, nous ne définissons pas de corps de fonction. A la place des `{` et `}`, nous finissons simplement la déclaration de la fonction avec un `;`. C'est un peu comme le squelette d'un contrat. C'est comme ça que le compilateur sait que c'est une interface. -En incluant cette interface dans le code de notre dapp, notre contrat sait à quoi ressemble les fonctions de l'autre contrat, comment les appeler, et quelle type de réponse en attendre. +En incluant cette interface dans le code de notre dapp, notre contrat sait à quoi ressemble les fonctions de l'autre contrat, comment les appeler, et quel type de réponse en attendre. -Nous verrons comment appeler les fonctions de l'autre contrat dans la prochaine leçon, pour l'instant nous allons déclarer notre interface pour le contrat CryptoKitties. +Nous verrons comment appeler les fonctions de l'autre contrat dans la prochaine leçon. Pour l'instant, nous allons déclarer notre interface pour le contrat CryptoKitties. # A votre tour @@ -182,10 +182,10 @@ function getKitty(uint256 _id) external view returns ( } ``` -La fonction est un peu différente que ce dont nous avons l'habitude. Vous pouvez voir qu'elle retourne... un tas de différentes valeurs. Si vous venez d'un langage de programmation comme JavaScript, c'est différent - en Solidity une fonction peut retourner plus d'une valeur. +La fonction est un peu différente que ce dont nous avons l'habitude. Vous pouvez voir qu'elle retourne... un tas de différentes valeurs. Si vous venez d'un langage de programmation comme JavaScript, c'est différent - en Solidity, une fonction peut retourner plus d'une valeur. Maintenant que nous savons à quoi ressemble notre fonction, nous pouvons l'utiliser pour créer une interface : -1. Définissez une interface appelée `KittyInterface`. C'est comme déclarer un nouveau contrat - nous utilisons le mot clé `contract`. +1. Définissez une interface appelée `KittyInterface`. C'est comme déclarer un nouveau contrat - nous utilisons le mot-clé `contract`. 2. Dans l'interface, définissez une fonction `getKitty` (qui devrait être un copier/coller de la fonction ci-dessus, mais avec un `;` après la déclaration `returns` au lieu de tout ce qu'il y a entre les `{}`). diff --git a/fr/2/11-interactingcontracts2.md b/fr/2/11-interactingcontracts2.md index 724e1c8119..fe25a63877 100644 --- a/fr/2/11-interactingcontracts2.md +++ b/fr/2/11-interactingcontracts2.md @@ -142,6 +142,6 @@ De cette manière, votre contrat peut interagir avec n'importe quel autre contra # A votre tour -Nous allons configurer notre contrat pour qu'il puisse lire le smart contract CryptoKitties ! +Nous allons configurer notre contrat afin qu'il puisse lire le smart contract CryptoKitties ! -1. J'ai sauvegardé l´adresse du contrat CryptoKitties dans le code pour vous, sous une variable appelée `ckAddress`. A la prochaine ligne, créer une `KittyInterface` nommée `kittyContract`, et initialisez la avec `ckAddress` - de la même manière que nous avons fait avec `numberContract` au dessus. +1. J'ai sauvegardé l´adresse du contrat CryptoKitties dans le code pour vous, sous une variable appelée `ckAddress`. A la prochaine ligne, créez une `KittyInterface` nommée `kittyContract`, et initialisez-la avec `ckAddress` - de la même manière que ce que nous avons fait avec `numberContract` ci-dessus. diff --git a/fr/2/12-multiplereturns.md b/fr/2/12-multiplereturns.md index 21cd643b1d..ad4fb92b86 100644 --- a/fr/2/12-multiplereturns.md +++ b/fr/2/12-multiplereturns.md @@ -147,11 +147,11 @@ function getLastReturnValue() external { # A votre tour -Il est temps d'interagir avec le contrat CryptoKitties ! +Il est temps d'intéragir avec le contrat CryptoKitties ! Nous allons créer une fonction qui récupère les gènes d'un chaton à partir du contrat : -1. Créez une fonction appelée `feedOnKitty`. Elle prendra 2 paramètres `uint`, `_zombieId` et `_kittyId` et elle devra être `public`. +1. Créez une fonction appelée `feedOnKitty`. Elle prendra 2 paramètres `uint`, `_zombieId` et `_kittyId` et devra être `public`. 2. La fonction devra d'abord déclarer un `uint` nommé `kittyDna`. diff --git a/fr/2/13-kittygenes.md b/fr/2/13-kittygenes.md index 446cd9506b..30aae8d675 100644 --- a/fr/2/13-kittygenes.md +++ b/fr/2/13-kittygenes.md @@ -135,13 +135,13 @@ material: La logique de notre fonction est terminée... mais nous allons ajouter une fonctionnalité bonus. -Nous allons faire que les zombies créés à partir de chatons aient une caractéristique unique, qui montrera qu'ils sont des zombie-chats. +Nous allons faire en sorte que les zombies créés à partir de chatons aient une caractéristique unique, qui montrera qu'ils sont des zombie-chats. Pour cela, nous allons ajouter un code spécial chaton à l'ADN du zombie. -Si vous vous rappelez de la leçon 1, nous n'utilisons seulement les 12 premiers chiffres de notre ADN à 16 chiffres pour déterminer l'apparence du zombie. Nous allons utiliser les 2 derniers chiffres inutilisés pour gérer les caractéristiques "spéciales". +Si vous vous rappelez de la leçon 1, nous utilisions seulement les 12 premiers chiffres de notre ADN à 16 chiffres pour déterminer l'apparence du zombie. Nous allons maintenant utiliser les 2 derniers chiffres inutilisés pour gérer les caractéristiques "spéciales". -Les deux derniers chiffres de l'ADN d'un zombie-chat sont `99` (car les chats ont 9 vies). Dans notre code, nous allons dire **si** un zombie provient d'un chat, alors ces deux derniers chiffres d'ADN seront `99`. +Les deux derniers chiffres de l'ADN d'un zombie-chat sont `99` (car les chats ont 9 vies). Dans notre code, nous allons dire que **si** un zombie provient d'un chat, alors les deux derniers chiffres de son ADN seront `99`. ## déclaration `if` (si) @@ -167,6 +167,6 @@ Nous allons implémenter les gènes de chat dans notre code zombie. 3. Dans cette déclaration `if`, nous voulons remplacer les 2 derniers chiffres de l'ADN par `99`. Une façon de le faire est d'utiliser cette logique : `newDna = newDna - newDna % 100 + 99;`. - > Explication : Si `newDna` est `334455`. Alors `newDna % 100` est `55`, donc `newDna - newDna % 100` est `334400`. Enfin on ajoute `99` pour avoir `334499`. + > Explication : Si `newDna` est `334455`. Alors `newDna % 100` est `55`, donc `newDna - newDna % 100` est `334400`. Nous ajoutons ensuite `99` pour avoir `334499`. 4. Enfin, nous avons besoin de changer l'appel de la fonction à l'intérieur de `feedOnKitty`. Quand elle appelle `feedAndMultiply`, ajoutez l'argument `"kitty"` à la fin. diff --git a/fr/2/14-wrappingitup.md b/fr/2/14-wrappingitup.md index e41cf78c40..71f32043e7 100644 --- a/fr/2/14-wrappingitup.md +++ b/fr/2/14-wrappingitup.md @@ -17,9 +17,9 @@ Vous pouvez voir comment cela fonctionne avec la démo à droite. Allez-y, je sa ## Implémentation JavaScript -Une fois que nous sommes prêt à déployer ce contrat sur Ethereum, nous avons juste besoin de compiler et déployer `ZombieFeeding` - vu que c'est notre contrat final qui hérite de `ZombieFactory`, et qui a accès à toutes les fonctions publiques des deux contrats. +Une fois que nous sommes prêts à déployer ce contrat sur Ethereum, nous avons juste besoin de compiler et déployer `ZombieFeeding` - vu que c'est notre contrat final qui hérite de `ZombieFactory`, et qui a accès à toutes les fonctions publiques des deux contrats. -Voici un exemple d'interaction avec notre contrat déployé utilisant JavaScript et web3.js: +Voici un exemple d'intéraction avec notre contrat déployé utilisant JavaScript et web3.js : ``` var abi = /* abi générée par le compilateur */ @@ -59,8 +59,8 @@ ZombieFactory.NewZombie(function(error, result) { # A votre tout d'essayer ! -Choisissez un chaton que vous voulez donner à manger. L'ADN de votre zombie et celui du chaton vont se mélanger, et vous aurez un nouveau zombie dans votre armée ! +Cliquez sur le chaton que vous voulez donner à manger au zombie. L'ADN de votre zombie et celui du chaton vont se mélanger, et vous aurez un nouveau zombie dans votre armée ! Vous avez vu ces jolies jambes de chat sur votre nouveau zombie ? C'est grâce aux chiffres `99` à la fin de notre ADN 😉 -Vous pouvez recommencer si vous le souhaitez. Quand vous avez un zombie qui vous plaît (vous n'en aurez qu'un), continuez et passez au prochain chapitre pour terminer la leçon 2 ! +Vous pouvez recommencer si vous le souhaitez. Quand vous avez un zombie qui vous plaît (vous n'en aurez qu'un !), continuez et passez au prochain chapitre pour terminer la leçon 2 ! diff --git a/fr/2/2-mappings.md b/fr/2/2-mappings.md index 086015ff2f..158f60791a 100644 --- a/fr/2/2-mappings.md +++ b/fr/2/2-mappings.md @@ -78,7 +78,7 @@ material: } --- -Rendons notre jeu multijoueur en attribuant aux zombies de notre base de donnée un propriétaire. +Rendons notre jeu multijoueur en attribuant aux zombies de notre base de données un propriétaire. Pour cela, nous allons avoir besoin de 2 nouveaux types de données : `mapping` (mappage) et `address` (adresse). @@ -92,14 +92,14 @@ Chaque compte a une `address`, qui est l'équivalent d'un numéro de compte banc (Cette adresse appartient à l'équipe de CryptoZombies. Si vous aimez CryptoZombies, vous pouvez nous envoyer quelques Ethers ! 😉 ) -Nous entrerons dans les détails des adresses dans une prochaine leçon, pour l'instant, la seule chose que vous devez comprendre c'est que **une adresse appartient à un utilisateur unique** (ou a un smart contract). +Nous étudierons plus en détail les adresses dans une prochaine leçon. Pour le moment, la seule chose que vous devez comprendre c'est que **une adresse appartient à un utilisateur unique** (ou a un smart contract). Nous pouvons donc l'utiliser comme un ID unique pour définir l'appartenance de nos zombies. Quand un utilisateur crée de nouveaux zombies en interagissant avec notre application, nous pourrons définir l'appartenance de ces zombies à l'adresse Ethereum utilisée pour appeler la fonction. ## Mappages -Dans la Leçon 1 nous avec vu les **_structures_** et les **_tableaux_**. Les **_mappages_** sont une autre façon d'organiser des données en Solidity. +Dans la Leçon 1 nous avons vu les **_structures_** et les **_tableaux_**. Les **_mappages_** sont une autre façon d'organiser des données en Solidity. Voici un exemple de `mapping` : @@ -110,7 +110,7 @@ mapping (address => uint) public accountBalance; mapping (uint => string) userIdToName; ``` -Un mappage est fondamentalement un stockage de valeur-clé pour stocker et rechercher des données. Dans le premier exemple, la clé est une `address` et la valeur est un `uint`, et dans le second exemple, la clé est un `uint` et la valeur un `string`. +Un mappage est fondamentalement un stockage de clé-valeur pour stocker et rechercher des données. Dans le premier exemple, la clé est une `address` et la valeur est un `uint`. Dans le second exemple, la clé est un `uint` et la valeur un `string`. # A votre tour diff --git a/fr/2/3-msgsender.md b/fr/2/3-msgsender.md index 12581d5123..b395412db3 100644 --- a/fr/2/3-msgsender.md +++ b/fr/2/3-msgsender.md @@ -88,9 +88,9 @@ Pour cela, nous allons utiliser quelque-chose appelé `msg.sender` (message.exp ## msg.sender -En Solidity, il existe des variables globales accessibles à toutes les fonctions. L'une d'elles est `msg.sender`, qui faire référence à l'`address` de la personne (ou du smart contract) qui a appelée la fonction actuelle. +En Solidity, il existe des variables globales accessibles à toutes les fonctions. L'une d'elles est `msg.sender`, qui fait référence à l'`address` de la personne (ou du smart contract) qui a appelé la fonction actuelle. -> Remarque : En Solidity, l'exécution d'une fonction nécessite obligatoirement un appel extérieur. Un contrat va juste rester là dans la blockchain à ne rien faire jusqu'à ce que quelqu'un appelle une de ses fonctions. Il y aura toujours un `msg.sender`. +> Remarque : En Solidity, l'exécution d'une fonction nécessite obligatoirement un appel extérieur. Un contrat va juste rester dans la blockchain à ne rien faire jusqu'à ce que quelqu'un appelle une de ses fonctions. Il y aura toujours un `msg.sender`. Voici un exemple d'utilisation de `msg.sender` pour mettre à jour un `mapping`. @@ -112,7 +112,7 @@ function whatIsMyNumber() public view returns (uint) { Dans cet exemple trivial, n'importe qui pourrait appeler `setMyNumber` et stocker un `uint` dans notre contrat, qui serait lié à leur adresse. Ils pourraient ensuite appeler `whatIsMyNumber`, et ils auraient en retour le `uint` qu'ils ont stocké. -Utiliser `msg.sender` apporte de la sécurité à la blockchain Ethereum - la seule manière pour quelqu'un de modifier les données d'un autre serait de lui voler sa clé privée associée à son adresse Ethereum. +Utiliser `msg.sender` apporte de la sécurité à la blockchain Ethereum - la seule manière pour quelqu'un de modifier les données d'un autre serait de lui voler la clé privée associée à son adresse Ethereum. # A votre tour diff --git a/fr/2/4-require.md b/fr/2/4-require.md index 13b5308670..ad26f84ed3 100644 --- a/fr/2/4-require.md +++ b/fr/2/4-require.md @@ -85,9 +85,9 @@ material: } --- -Dans la leçon 1, nous avons fait en sorte que les utilisateurs puissent créer de nouveaux zombies en appelant `createRandomZombie` et en rentrant leur nom. Cependant, si les utilisateurs continuaient d'appeler cette fonction pour créer à l'infini des zombies dans leur armée, le jeu ne serait pas vraiment amusant. +Dans la leçon 1, nous avons fait en sorte que les utilisateurs puissent créer de nouveaux zombies en appelant `createRandomZombie` et en entrant leur nom. Cependant, si les utilisateurs continuaient d'appeler cette fonction pour créer des zombies à l'infini dans leur armée, le jeu ne serait pas vraiment amusant. -Nous allons faire en sorte que chaque joueur puisse appeler cette fonction une seule fois seulement. Ainsi, les nouveaux joueurs vont l'appeler quand ils commenceront le jeu pour créer le premier zombie de leur armée. +Nous allons faire en sorte que chaque joueur puisse appeler cette fonction une seule fois seulement. Ainsi, les nouveaux joueurs vont l'appeler seulement lorsqu'ils commenceront le jeu, pour créer le premier zombie de leur armée. Comment pouvons-nous faire pour que cette fonction soit appelée seulement une fois par joueur ? @@ -105,14 +105,14 @@ function sayHiToVitalik(string _name) public returns (string) { Si vous appelez la fonction avec `sayHiToVitalik("Vitalik")`, elle va renvoyer "Hi!". Si vous l'appelez avec un autre argument, elle va renvoyer une erreur et ne elle ne va pas s’exécuter. -Ainsi `require` est pratique pour vérifier que certaines conditions soient vraies avant d'exécuter une fonction. +Ainsi `require` est pratique pour vérifier que certaines conditions sont vraies avant d'exécuter une fonction. # A votre tour -Dans notre jeu de zombie, nous ne voulons pas qu'un utilisateur puisse créer une infinité de zombie pour son armée en appelant continuellement `createRandomZombie` - le jeu ne serait pas très amusant. +Dans notre jeu de zombie, nous ne voulons pas qu'un utilisateur puisse créer une infinité de zombies pour son armée en appelant continuellement `createRandomZombie` - le jeu ne serait pas très amusant. -Nous allons utiliser `require` pour être sur que la fonction ne s'exécute qu'une seule fois par utilisateur, quand il crée son premier zombie. +Nous allons utiliser `require` pour être sur que la fonction ne s'exécute qu'une seule fois par utilisateur; quand il crée son premier zombie. -1. Ajouter une déclaration `require` au début de `createRandomZombie`. La fonction devra vérifier que `ownerZombieCount[msg.sender]` soit égal à `0`, et renvoyer une erreur au cas contraire. +1. Ajoutez une déclaration `require` au début de `createRandomZombie`. La fonction devra vérifier que `ownerZombieCount[msg.sender]` soit égal à `0`, et renvoyer une erreur au cas contraire. > Remarque : En Solidity, le terme que vous mettez en premier n'a pas d'importance - cela revient au même. Cependant, notre vérificateur de réponse étant vraiment basique, il acceptera seulement une bonne réponse - il faudra que le `ownerZombieCount[msg.sender]` soit en premier. diff --git a/fr/2/5-inheritance.md b/fr/2/5-inheritance.md index e4f1db2505..5b339720a6 100644 --- a/fr/2/5-inheritance.md +++ b/fr/2/5-inheritance.md @@ -112,9 +112,9 @@ contract BabyDoge is Doge { ``` -`BabyDoge` **_hérite_** de `Doge`. Cela veut dire que si vous compilez et déployez `BabyDoge`, il aura accès à `catchphrase()` et à `anotherCatchphrase()` (et n'importe quelle fonction publique que nous définirions dans `Doge`). +`BabyDoge` **_hérite_** de `Doge`. Cela veut dire que si vous compilez et déployez `BabyDoge`, il aura accès à `catchphrase()` et à `anotherCatchphrase()` (et n'importe quelle fonction publique que nous définirons dans `Doge`). -Cela peut être utiliser pour les héritages logiques (comme avec les sous-classes, un `Chat` est un `Animal`). Mais cela peut aussi simplement être utilisé pour organiser votre code en groupant les logiques similaires en différentes classes. +Cela peut être utilisé pour les héritages logiques (comme avec les sous-classes, un `Chat` est un `Animal`). Mais cela peut aussi simplement être utilisé pour organiser votre code en groupant les logiques similaires en différentes classes. # A votre tour diff --git a/fr/2/6-importfiles.md b/fr/2/6-importfiles.md index 2a92996b2a..5a34584a43 100644 --- a/fr/2/6-importfiles.md +++ b/fr/2/6-importfiles.md @@ -67,7 +67,7 @@ Vous remarquerez que nous avons fait un peu de ménage dans notre code à droite Notre code devenant plutôt long, nous l'avons donc séparé en plusieurs fichiers pour mieux le gérer. C'est comme cela que vous devriez gérer les projets Solidity qui ont beaucoup de lignes de code. -Quand vous avez plusieurs fichiers et que vous voulez importer un fichier dans un autre, Solidity utilise le mot clé `import` (importation) : +Quand vous avez plusieurs fichiers et que vous voulez importer un fichier dans un autre, Solidity utilise le mot-clé `import` (importation) : ``` import "./someothercontract.sol"; @@ -83,4 +83,4 @@ Nous avons donc un fichier nommé `someothercontract.sol` dans le même réperto Maintenant que nous avons une structure avec plusieurs fichiers, nous allons avoir besoin d'utiliser `import` pour lire le contenu de l'autre fichier : -1. Importer `zombiefactory.sol` dans notre nouveau fichier `zombiefeeding.sol`. +1. Importez `zombiefactory.sol` dans notre nouveau fichier `zombiefeeding.sol`. diff --git a/fr/2/7-storage.md b/fr/2/7-storage.md index 07a039b9c1..8ac0581cc1 100644 --- a/fr/2/7-storage.md +++ b/fr/2/7-storage.md @@ -71,11 +71,11 @@ material: En Solidity, il y a deux endroits pour stocker les variables - dans le `storage` (stockage) ou dans la `memory` (mémoire). -Le **_stockage_** est utilisé pour les variables stockées de manière permanente dans la blockchain. Les variables **_mémoires_** sont temporaires, et effacées entre les appels de fonction extérieure à votre contrat. C'est un peu comme le disque dur et la mémoire vive de votre ordinateur. +Le **_stockage_** est utilisé pour les variables stockées de manière permanente dans la blockchain. Les variables **_mémoires_** sont temporaires, et effacées entre les appels de fonction extérieurs à votre contrat. C'est un peu comme le disque dur et la mémoire vive de votre ordinateur. -La plupart du temps, vous n'aurez pas besoin d'utiliser ces mots clés car Solidity gère ça tout seul. les variables d'état (déclarées en dehors des fonctions) sont par défaut `storage` et écrites de manière permanente dans la blockchain, alors que les variables déclarées à l'intérieur des fonctions sont `memory` et disparaissent quand l'appel à la fonction est terminé. +La plupart du temps, vous n'aurez pas besoin d'utiliser ces mots-clés car Solidity gère ça tout seul. Les variables d'état (déclarées en dehors des fonctions) sont par défaut `storage` et écrites de manière permanente dans la blockchain, alors que les variables déclarées à l'intérieur des fonctions sont `memory` et disparaissent lorsque l'appel à la fonction est terminé. -Cependant, il peut arriver que vous ayez besoin d'utiliser ces mots clés, surtout quand vous utilisez des **_structures_** et des **_tableaux_** à l'intérieur de fonctions : +Cependant, il peut arriver que vous ayez besoin d'utiliser ces mots-clés, surtout quand vous utilisez des **_structures_** et des **_tableaux_** à l'intérieur de fonctions : ``` contract SandwichFactory { @@ -112,21 +112,21 @@ contract SandwichFactory { } ``` -Ne vous inquiétez pas si nous ne comprenez pas complètement quand utiliser l'un ou l'autre pour l'instant - au cours du tutoriel, nous vous indiquerons quand utiliser `storage` et quand utiliser `memory`, et le compilateur Solidity vous avertira aussi pour vous indiquer quand vous devriez utiliser un de ces mots clés. +Ne vous inquiétez pas si nous ne comprenez pas complètement quand utiliser l'un ou l'autre pour l'instant - au cours du tutoriel, nous vous indiquerons quand utiliser `storage` et quand utiliser `memory`, et le compilateur Solidity vous avertira aussi pour vous indiquer quand vous devriez utiliser un de ces mots-clés. Pour l'instant, vous avez juste besoin de retenir qu'il y aura des cas où vous allez avoir besoin d'utiliser `storage` et `memory` ! # A votre tour -Il est temps de donner à nos zombies la capacités de se nourrir et de se multiplier ! +Il est temps de donner à nos zombies la capacité de se nourrir et de se multiplier ! -Quand un zombie se nourri d'une autre forme de vie, son ADN se combine avec l'autre forme de vie pour créer un nouveau zombie. +Quand un zombie se nourrit d'une autre forme de vie, son ADN se combine avec l'autre forme de vie pour ainsi créer un nouveau zombie. -1. Créez une fonction appelée `feedAndMultiply` qui aura deux paramètres : `_zombieId` (un `uint`) et `_targetDna` (aussi un `uint`). Cette fonction devra être `public`. +1. Créez une fonction appelée `feedAndMultiply` qui aura deux paramètres : `_zombieId` (un `uint`) et `_targetDna` (aussi un `uint`). Cette fonction devra être `public`. 2. Nous ne voulons pas que d'autres personnes puissent nourrir notre zombie ! Nous allons vérifier que nous sommes bien le propriétaire de ce zombie. Ajoutez une déclaration `require` pour vérifier que `msg.sender` est égal au propriétaire du zombie (de la même manière que dans la fonction `createRandomZombie`). -> Remarque : De la même manière, parce que notre validation de réponse est basique, il faudra que `msg.sender` soit en premier, sinon cela ne sera pas validé. Normalement quand vous codez, vous pouvez choisir l'ordre que vous voulez, les 2 étant justes. +> Remarque : De la même manière, parce que notre validation de réponse est basique, il faudra que `msg.sender` soit en premier, sinon cela ne sera pas validé. Normalement lorsque vous codez, vous pouvez choisir l'ordre que vous voulez, les 2 étant justes. 3. Nous allons avoir besoin de l'ADN de ce zombie. La prochaine chose que notre fonction devra faire c'est de déclarer un `Zombie` local nommé `myZombie` (qui sera un pointeur `storage`). Définissez cette variable égale à l'index `_zombieId` de notre tableau `zombies`. diff --git a/fr/2/8-feedandmultiply2.md b/fr/2/8-feedandmultiply2.md index 5291064249..9c4e29de7d 100644 --- a/fr/2/8-feedandmultiply2.md +++ b/fr/2/8-feedandmultiply2.md @@ -100,6 +100,6 @@ Plus tard, nous pourrons faire une formule plus compliquée, comme ajouter un pe > Remarque : Vous pouvez accéder aux propriétés de `myZombie` en utilisant `myZombie.name` et `myZombie.dna` -3. Une fois que nous avons le nouvel ADN, appelons `_createZombie`. Vous pouvez regarder l'onglet `zombiefactory.sol` si vous avez oublié quels arguments cette fonction a besoin pour être appelée. Cette fonction a besoin d'un nom, appelons notre nouveau zombie `NoName` pour l'instant - nous pourrons écrire une fonction pour changer les noms des zombies plus tard. +3. Une fois que nous avons le nouvel ADN, appelons `_createZombie`. Vous pouvez regarder l'onglet `zombiefactory.sol` si vous avez oublié quels sont les arguments que cette fonction a besoin pour être appelée. Cette fonction a besoin d'un nom, appelons notre nouveau zombie `NoName` pour l'instant - nous pourrons écrire une fonction pour changer les noms des zombies plus tard. -> Note: Pour les experts de Solidity, vous avez peut-être remarqué un problème avec notre code ! Ne vous inquiétez-pas, nous corrigerons cela dans le prochain chapitre ;) +> Note: Pour les experts de Solidity, vous avez peut-être remarqué un problème avec notre code ! Ne vous inquiétez pas, nous corrigerons cela dans le prochain chapitre. ;) diff --git a/fr/2/9-internalfunctions.md b/fr/2/9-internalfunctions.md index 21c1172016..0531070ba9 100644 --- a/fr/2/9-internalfunctions.md +++ b/fr/2/9-internalfunctions.md @@ -104,13 +104,13 @@ material: **Le code dans notre leçon précédente avait une erreur !** -Si vous essayer de le compiler, le compilateur renverra une erreur. +Si vous essayez de le compiler, le compilateur renverra une erreur. -Le problème est que nous essayons d'appeler la fonction `_createZombie` à l'intérieur de `ZombieFeeding`, mais `_createZombie` est une fonction `private` de `ZombieFactory`. Cela veut dire que aucun contrat qui hérite de `ZombieFactory` ne peut y accéder. +Le problème est que nous essayons d'appeler la fonction `_createZombie` à l'intérieur de `ZombieFeeding`, mais `_createZombie` est une fonction `private` de `ZombieFactory`. Cela veut dire qu'aucun contrat qui hérite de `ZombieFactory` peut y accéder. ## Interne et externe -En plus de `public` et `private`, Solidity a deux autres visibilité pour les fonctions : `internal` (interne) et `external` (externe). +En plus de `public` et `private`, Solidity a deux autres visibilités pour les fonctions : `internal` (interne) et `external` (externe). `internal` est similaire à `private`, à l'exception qu'elle est aussi accessible aux contrats qui héritent de ce contrat. **(On dirait que c'est ce que l'on veut!)**. diff --git a/fr/3/01-externaldependencies.md b/fr/3/01-externaldependencies.md index 7f508bc8bf..c9686e2221 100644 --- a/fr/3/01-externaldependencies.md +++ b/fr/3/01-externaldependencies.md @@ -158,7 +158,7 @@ C'est peu probable, mais si cela arrive cela rendrait notre DApp complètement i Pour cette raison, c'est souvent utile d'avoir des fonctions qui vous permettent de mettre à jour des portions clés de la DApp. -Par exemple, au lieu d'écrire en dur l'adresse du contrat CryptoKitties dans notre DApp, nous devrions sûrement avoir une fonction `setKittyContractAddress` qui nous permet de changer cette adresse dans le futur au cas où quelque chose arriverait au contrat CryptoKitties. +Par exemple, au lieu d'écrire en dur l'adresse du contrat CryptoKitties dans notre DApp, nous devrions sûrement avoir une fonction `setKittyContractAddress` qui nous permette de changer cette adresse dans le futur au cas où quelque chose arriverait au contrat CryptoKitties. ## A votre tour diff --git a/fr/3/02-ownable.md b/fr/3/02-ownable.md index 4d75dc240a..97b93150ca 100644 --- a/fr/3/02-ownable.md +++ b/fr/3/02-ownable.md @@ -185,13 +185,13 @@ Avez-vous trouvé la faille de sécurité dans le chapitre précédent ? Nous voulons être capable de mettre à jour cette adresse de notre contrat, mais nous ne voulons pas que tout le monde puisse le faire. -Pour gérer une situation comme celle-là, il y a une pratique courante qui consiste à rendre les contrats `Ownable` (avec propriétaire) - ce qui veut dire qu'ils ont un propriétaire (vous) avec des privilèges spéciaux. +Pour gérer une situation comme celle-ci, il y a une pratique courante qui consiste à rendre les contrats `Ownable` (avec propriétaire) - ce qui veut dire qu'ils ont un propriétaire (vous) avec des privilèges spéciaux. ## Le contrat `Ownable` d'OpenZeppelin -Ci-dessous vous trouverez le contrat `Ownable` issu de la bibliothèque Solidity d'**_OpenZeppelin_**. OpenZeppelin est une bibliothèque de smart contracts sécurisés et approuvés par la communauté que vous pouvez utiliser dans vos propres DApps. Après cette leçon, alors que vous allez attendre avec impatience la sortie de la Leçon 4, nous vous recommandons fortement d'aller voir leur site internet pour en apprendre d'avantage ! +Ci-dessous, vous trouverez le contrat `Ownable` issu de la bibliothèque Solidity d'**_OpenZeppelin_**. OpenZeppelin est une bibliothèque de smart contracts sécurisés et approuvés par la communauté que vous pouvez utiliser dans vos propres DApps. Après cette leçon, alors que vous allez attendre avec impatience la sortie de la leçon 4, nous vous recommandons fortement d'aller voir leur site internet pour en apprendre davantage ! -Lisez-le contrat ci-dessous. Vous allez voir des choses que nous ne connaissons pas encore, mais ne vous inquiétez pas, nous en parlerons plus tard. +Lisez le contrat ci-dessous. Vous allez voir des choses que nous ne connaissons pas encore, mais ne vous inquiétez pas, nous en parlerons plus tard. ``` /** @@ -234,26 +234,26 @@ contract Ownable { Quelques nouveautés que nous n'avions pas encore vues : -- Constructeurs : `function Ownable()` est un **_constructor_** (constructeur), c'est une fonction spéciale optionnelle qui a le même nom que le contrat. Elle sera exécutée seulement une fois, lorsque le contrat est créé. +- Constructeurs : `function Ownable()` est un **_constructor_** (constructeur). C'est une fonction spéciale optionnelle qui a le même nom que le contrat. Elle ne sera exécutée qu'une seule fois, lorsque le contrat est créé. - Modificateurs de fonction : `modifier onlyOwner()`. Les modificateurs sont comme des demi-fonctions qui permettent de modifier d'autres fonctions, souvent pour vérifier des conditions avant l'exécution. Dans ce cas, `onlyOwner` peut être utilisé pour limiter l'accès pour que **seulement** (only) le **propriétaire** (owner) du contrat puisse exécuter cette fonction. Nous parlerons plus en détail des modificateurs de fonction dans le prochain chapitre, et ce que cet étrange `_;` fait. -- Mot-clé `indexed` : ne vous inquiétez pas pour celui là, nous n'en avons pas encore besoin. +- Mot-clé `indexed` : ne vous inquiétez pas pour celui-là, nous n'en avons pas encore besoin. -Pour résumer le contrat `Ownable` fait fondamentalement ceci : +Pour résumer, le contrat `Ownable` fait ceci : -1. Quand un contrat est créé, son constructeur défini le `owner` égal à `msg.sender` (la personne qui le déploie) +1. Quand un contrat est créé, son constructeur définit le `owner` égal à `msg.sender` (la personne qui le déploie). -2. Il ajoute un modificateur `onlyOwner`, qui permet de restreindre l'accès à certaines fonctions à seulement le `owner` +2. Il ajoute un modificateur `onlyOwner`, qui permet de restreindre l'accès de certaines fonctions qu'au `owner`. -3. Il vous permet de transférer le contrat à un nouvel `owner` +3. Il vous permet de transférer le contrat à un nouvel `owner`. `onlyOwner` est une condition si courante pour les contrats que la plupart des DApps Solidity commencent par copier/coller ce contrat `Ownable`, et leur premier contrat en hérite. -Vu que nous voulons limiter `setKittyContractAddress` à `onlyOwner`, nous allons faire pareil pour notre contrat. +Vu que nous voulons limiter `setKittyContractAddress` à `onlyOwner`, nous allons en faire de même pour notre contrat. ## A votre tour Nous avons pris de l'avance et avons copié le code du contrat `Ownable` dans un nouveau fichier, `ownable.sol`. Nous allons faire hériter `ZombieFactory` de celui-ci. -1. Modifiez notre code pour `import` le contenu de `ownable.sol`. Si vous ne vous rappelez plus comment faire, regardez `zombiefeeding.sol`. +1. Modifiez notre code pour `import` le contenu de `ownable.sol`. Si vous ne vous souvenez plus comment faire, regardez `zombiefeeding.sol`. 2. Modifiez le contrat `ZombieFactory` pour qu'il hérite de `Ownable`. Pareillement, regardez `zombiefeeding.sol` si vous ne vous rappelez plus comment faire. diff --git a/fr/3/03-onlyowner.md b/fr/3/03-onlyowner.md index a4999666aa..7362e94418 100644 --- a/fr/3/03-onlyowner.md +++ b/fr/3/03-onlyowner.md @@ -185,18 +185,18 @@ material: Maintenant que notre contrat de base `ZombieFactory` hérite de `Ownable`, nous pouvons utiliser le modificateur de fonction `onlyOwner` aussi dans `ZombieFeeding`. -C'est grâce à la façon dont l'héritage fonctionne. Souvenez-vous : +C'est possible car c'est le principe de l'héritage. Souvenez-vous : ``` ZombieFeeding is ZombieFactory ZombieFactory is Ownable ``` -Ainsi `ZombieFeeding` est aussi `Ownable`, et peut accéder aux fonctions / évènements / modificateurs du contrat `Ownable`. Cela s'appliquera aussi à n'importe quel contrat qui héritera de `ZombieFeeding`. +Ainsi, `ZombieFeeding` est aussi `Ownable`, et peut accéder aux fonctions / évènements / modificateurs du contrat `Ownable`. Cela s'appliquera aussi à n'importe quel contrat qui héritera de `ZombieFeeding`. ## Modificateurs de fonction -Un modificateur de fonction ressemble à une fonction, mais utilise le mot clé `modifier` (modificateur) à la place de `function`. Et il ne peut pas être directement appelé comme une fonction - à la place, nous pouvons rajouter le nom du modificateur à la fin de la définition d'une fonction pour changer le fonctionnement de cette fonction. +Un modificateur de fonction ressemble à une fonction, mais utilise le mot-clé `modifier` (modificateur) à la place de `function`. Et il ne peut pas être directement appelé comme une fonction - à la place, nous pouvons rajouter le nom du modificateur à la fin de la définition d'une fonction pour changer le fonctionnement de cette fonction. Regardons cela de plus près avec `onlyOwner` : @@ -223,18 +223,18 @@ contract MyContract is Ownable { } ``` -Vous avez vu le modificateur `onlyOwner` sur la fonction `likeABoss` ? Quand vous appelez `likeABoss`, le code de `onlyOwner` s'exécute **en premier**. Puis, quand il arrive à la déclaration `_;` dans `onlyOwner`, il continu avec le code de `likeABoss`. +Vous avez vu le modificateur `onlyOwner` sur la fonction `likeABoss` ? Quand vous appelez `likeABoss`, le code de `onlyOwner` s'exécute **en premier**. Puis, quand il arrive à la déclaration `_;` dans `onlyOwner`, il continue avec le code de `likeABoss`. -Il peut y avoir d'autres raisons d'utiliser des modificateurs, mais le cas d'utilisation le plus courant est pour rajouter facilement une vérification `require` avant l'exécution d'une fonction. +Il peut y avoir d'autres raisons d'utiliser des modificateurs, mais le cas d'utilisation le plus courant c'est lorsqu'on veut ajouter facilement une vérification `require` avant l'exécution d'une fonction. -Dans le cas de `onlyOwner`, rajouter ce modificateur à une fonction fera en sorte que **seulement** le **propriétaire** du contrat (vous, si vous l'avez déployé) pourra appeler cette fonction. +Dans le cas de `onlyOwner`, ajouter ce modificateur à une fonction fera en sorte que **seulement** le **propriétaire** du contrat (vous, si vous l'avez déployé) pourra appeler cette fonction. -> Remarque : Donner des privilèges spéciaux au propriétaire du contrat comme là est souvent nécessaire, cependant cela pourrait aussi être utilisé malicieusement. Par exemple, le propriétaire pourrait ajouter une fonction de porte dérobée qui lui permettrait de transférer n'importe quel zombie à lui-même ! +> Remarque : Donner des privilèges spéciaux au propriétaire du contrat comme ici est souvent nécessaire. Cependant, cela pourrait aussi être utilisé malicieusement. Par exemple, le propriétaire pourrait ajouter une fonction de porte dérobée qui lui permettrait de transférer n'importe quel zombie à lui-même ! -> C'est donc important de se rappeler que ce n'est pas parce qu'une DApp est sur Ethereum que cela veut dire qu'elle est décentralisée - vous devez lire le code source en entier pour vous assurez que le propriétaire n'a pas de privilèges qui pourraient vous inquiéter. En tant que développeur, il existe un équilibre entre garder le contrôle d'un DApp pour corriger de potentiels bugs, et construire une plateforme sans propriétaire en laquelle vos utilisateurs peuvent avoir confiance pour sécuriser leurs données. +> C'est donc important de se rappeler que ce n'est pas parce qu'une DApp est sur Ethereum que cela veut dire qu'elle est décentralisée - vous devez lire le code source en entier pour vous assurer que le propriétaire n'a pas de privilèges qui pourraient vous inquiéter. En tant que développeur, il existe un équilibre entre garder le contrôle d'un DApp pour corriger de potentiels bugs, et construire une plateforme sans propriétaire en laquelle vos utilisateurs peuvent avoir confiance pour sécuriser leurs données. ## A votre tour -Maintenant nous pouvons restreindre l'accès à `setKittyContractAddress` pour que nous soyons le seul à pouvoir le modifier plus tard. +Désormais, nous pouvons restreindre l'accès à `setKittyContractAddress` pour que nous soyons les seuls à pouvoir le modifier plus tard. 1. Rajoutez le modificateur `onlyOwner` à `setKittyContractAddress`. diff --git a/fr/3/04-gas.md b/fr/3/04-gas.md index b1218dd48b..1a3378e6dd 100644 --- a/fr/3/04-gas.md +++ b/fr/3/04-gas.md @@ -179,21 +179,21 @@ material: } --- -Super ! Maintenant nous savons comment mettre à jour des portions clés de notre DApp tout en empêchant que d'autres personnes modifient notre contrat. +Super ! Maintenant, nous savons comment mettre à jour des portions clés de notre DApp tout en empêchant que d'autres personnes modifient notre contrat. Nous allons voir une autre chose qui différencie Solidity des autres langages de programmation : ## Gas (gaz) - le carburant des DApps Ethereum -En Solidity, vos utilisateurs devront payer à chaque fois qu'ils exécutent une fonction de votre DApp avec une monnaie appelée **_gas_**. Les utilisateurs achètent du gas avec de l'Ether (la monnaie d'Ethereum), vos utilisateurs doivent donc dépenser de l'ETH pour exécuter des fonctions de votre DApp. +En Solidity, vos utilisateurs devront payer à chaque fois qu'ils exécutent une fonction de votre DApp avec une monnaie appelée **_gas_**. Les utilisateurs achètent du gas avec de l'Ether (la monnaie d'Ethereum); vos utilisateurs doivent donc dépenser de l'ETH pour exécuter des fonctions de votre DApp. -La quantité de gas requit pour exécuter une fonction dépend de la complexité de cette fonction. Chaque opération individuelle a un **_coût en gas_** basé approximativement sur la quantité de ressources informatiques nécessaires pour effectuer l'opération (ex: écrire dans le storage est beaucoup plus cher que d'ajouter deux entiers). Le **_coût en gas_** total de votre fonction est la somme du coût de chaque opération individuelle. +La quantité de gas requise pour exécuter une fonction dépend de la complexité de cette fonction. Chaque opération individuelle a un **_coût en gas_** basé approximativement sur la quantité de ressources informatiques nécessaires pour effectuer l'opération (ex : écrire dans le storage est beaucoup plus cher que d'ajouter deux entiers). Le **_coût en gas_** total de votre fonction est la somme du coût de chaque opération individuelle. Parce qu'exécuter des fonctions coûte de l'argent réel pour les utilisateurs, l'optimisation de code est encore plus importante en Solidity que pour les autres langages de programmation. Si votre code est négligé, vos utilisateurs devront payer plus cher pour exécuter vos fonctions - et cela pourrait résulter en des millions de dollars de frais inutiles répartis sur des milliers d'utilisateurs. ## Pourquoi le gas est nécessaire ? -Ethereum est comme un ordinateur gros et lent, mais extrêmement sécurisé. Quand vous exécutez une fonction, chaque nœud du réseau doit exécuter la même fonction pour vérifier le résultat - c'est ces milliers de nœuds vérifiant chaque exécution de fonction qui rendent Ethereum décentralisé et les données immuables et résistantes à la censure. +Ethereum est comme un ordinateur gros et lent, mais extrêmement sécurisé. Quand vous exécutez une fonction, chaque nœud du réseau doit exécuter la même fonction pour vérifier le résultat - ce sont ces milliers de nœuds vérifiant chaque exécution de fonction qui rendent Ethereum décentralisé et les données immuables et résistantes à la censure. Les créateurs d'Ethereum ont voulu être sûrs que personne ne pourrait bloquer le réseau avec une boucle infinie, ou s'accaparer toutes les ressources du réseau avec des calculs vraiment complexes. C'est pour cela que les transactions ne sont pas gratuites, et que les utilisateurs doivent payer pour faire des calculs et pour le stockage. diff --git a/fr/3/05-timeunits.md b/fr/3/05-timeunits.md index 2c15dba445..616a755256 100644 --- a/fr/3/05-timeunits.md +++ b/fr/3/05-timeunits.md @@ -185,7 +185,7 @@ material: La propriété `level` est plutôt explicite. Plus tard, quand nous créerons le système de combat, les zombies avec le plus de victoires vont monter en niveau avec le temps et auront accès à plus d'aptitudes. -La propriété `readyTime` demande un peu plus d'explication. Le but est d'ajouter un "temps de recharge", une durée qu'un zombie doit attendre après avoir mangé ou attaqué avant de pouvoir manger / attaquer de nouveau. Sans ça, un zombie pourrait attaquer et se multiplier 1000 fois par jour, ce qui rendrait le jeu trop facile. +La propriété `readyTime` demande un peu plus d'explication. Le but est d'ajouter un "temps de recharge" (ou "cooldown"), une durée qu'un zombie doit attendre après avoir mangé ou attaqué avant de pouvoir manger / attaquer de nouveau. Sans ça, un zombie pourrait attaquer et se multiplier 1000 fois par jour, ce qui rendrait le jeu trop facile. Afin de savoir combien de temps un zombie doit attendre avant d'attaquer de nouveau, nous pouvons utiliser les unités de temps de Solidity. @@ -197,7 +197,7 @@ La variable `now` (maintenant) va retourner l'horodatage actuel unix (le nombre > Remarque : L'horodatage unix est traditionnellement stocké dans un nombre 32-bit. Cela mènera au problème "Année 2038", quand l'horodatage unix 32-bits aura débordé et cassera beaucoup de système existant. Si nous voulons que notre DApp continue de marcher dans 20 ans, nous pouvons utiliser un nombre 64-bit à la place - mais nos utilisateurs auront besoin de dépenser plus de gas pour utiliser notre DApp pendant ce temps. Décision de conception ! -Solidity a aussi des unités de temps `seconds` (secondes), `minutes`, `hours` (heures), `days` (jours) et `years` (ans). Ils vont se convertir en un `uint` correspondant au nombre de seconde de ce temps. Donc `1 minutes` est `60`, `1 hours` est `3600` (60 secondes x 60 minutes), `1 days` est `86400` (24 heures x 60 minutes x 60 seconds), etc. +Solidity a aussi des unités de temps `seconds` (secondes), `minutes`, `hours` (heures), `days` (jours) et `years` (ans). Ils vont se convertir en un `uint` correspondant au nombre de secondes de ce temps. Donc `1 minutes` est `60`, `1 hours` est `3600` (60 secondes x 60 minutes), `1 days` est `86400` (24 heures x 60 minutes x 60 seconds), etc. Voici un exemple montrant l'utilité de ces unités de temps : @@ -210,8 +210,8 @@ function updateTimestamp() public { } // Retournera `true` si 5 minutes se sont écoulées -// depuis que `updateTimestamp` a été appelé, `false` -// si 5 minutes ne se sont pas passées +// depuis que `updateTimestamp` a été appelée, `false` +// si 5 minutes ne se sont pas écoulées function fiveMinutesHavePassed() public view returns (bool) { return (now >= (lastUpdated + 5 minutes)); } @@ -231,6 +231,6 @@ Ajoutons un temps de recharge à notre DApp, afin que les zombies aient besoin d > Remarque : Le `uint32(...)` est nécessaire car `now` renvoie un `uint256` par défaut. nous devons donc le convertir en un `uint32`. -`now + cooldownTime` sera égal à l'horodatage unix actuel (en secondes) plus le nombre de secondes d'un jour - qui sera égal à l'horodatage unix dans 24h. Plus tard, nous pourrons comparer si le `readyTime` du zombie est supérieur à `now` pour voir si assez de temps s'est écoulé pour utiliser le zombie à nouveau. +`now + cooldownTime` sera égal à l'horodatage unix actuel (en secondes) + le nombre de secondes d'un jour - qui sera égal à l'horodatage unix dans 24h. Plus tard, nous pourrons comparer si le `readyTime` du zombie est supérieur à `now` pour voir si assez de temps s'est écoulé pour utiliser à nouveau le zombie. Nous implémenterons cette fonctionnalité pour limiter les actions en fonction de `readyTime` dans le prochain chapitre. diff --git a/fr/3/06-zombiecooldowns.md b/fr/3/06-zombiecooldowns.md index b052d8943b..f14be2f10b 100644 --- a/fr/3/06-zombiecooldowns.md +++ b/fr/3/06-zombiecooldowns.md @@ -231,4 +231,4 @@ De cette manière, nous pouvons donner à notre fonction une référence à notr 3. Ensuite, créez une fonction appelée `_isReady`. Cette fonction aura aussi 1 paramètre `Zombie storage` appelé `_zombie`. Elle sera une fonction `internal view` et retournera un `bool`. -4. Le corps de cette fonction devra retourner `(_zombie.readyTime <= now)`, qui sera soit `true` soit `false`. Cette fonction nous dira si assez de temps s'est écoulé depuis la dernière fois que le zombie à mangé. +4. Le corps de cette fonction devra retourner `(_zombie.readyTime <= now)`, qui sera soit `true`, soit `false`. Cette fonction nous dira si assez de temps s'est écoulé depuis la dernière fois que le zombie à mangé. diff --git a/fr/3/07-zombiecooldowns2.md b/fr/3/07-zombiecooldowns2.md index c810e8235e..208dc177dc 100644 --- a/fr/3/07-zombiecooldowns2.md +++ b/fr/3/07-zombiecooldowns2.md @@ -208,16 +208,16 @@ material: Maintenant, modifions `feedAndMultiply` pour prendre en compte notre compte à rebours. -Si on regarde cette fonction, on peut voir que nous l'avions rendu `public` dans les leçons précédentes. Une habitude importante de sécurité est d'examiner tous les fonctions `public` et `external`, et essayer d'imaginer de quelles manières les utilisateurs pourraient en abuser. Rappelez-vous, à part si ces fonctions ont un modificateur `onlyOwner`, tout le monde peut appeler ces fonctions avec les données qu'il veut. +Si l'on regarde cette fonction, on peut voir que nous l'avions rendu `public` dans les leçons précédentes. Une habitude importante de sécurité est d'examiner tous les fonctions `public` et `external`, et essayer d'imaginer de quelles manières les utilisateurs pourraient en abuser. Rappelez-vous, à part si ces fonctions ont un modificateur `onlyOwner`, tout le monde peut appeler ces fonctions avec les données qu'il veut. En réexaminant cette fonction en particulier, un utilisateur pourrait appeler directement la fonction avec n'importe quel `_targetDna` ou `_species`. Ça ne correspond pas vraiment à notre jeu - nous voulons qu'ils suivent nos règles ! -En regardant de plus près, cette fonction n'a besoin d'être appelée seulement par `feedOnKitty()`, la façon la plus simple d'empêcher ce genre d'abus et de la rendre `internal`. +En regardant de plus près, cette fonction n'a besoin d'être appelée seulement par `feedOnKitty()`. La façon la plus simple d'empêcher ce genre d'abus est donc de la rendre `internal`. ## A votre tour -1. Actuellement `feedAndMultiply` est une fonction `public`. Rendez là `internal` afin que le contrat soit plus sécurisé. Nous ne voulons pas que les utilisateurs soit capables de l'appeler avec n'importe quel ADN. +1. Actuellement `feedAndMultiply` est une fonction `public`. Rendez-la `internal` afin que le contrat soit plus sécurisé. Nous ne voulons pas que les utilisateurs soit capables de l'appeler avec n'importe quel ADN. -2. Faites en sorte que `feedAndMultiply` prenne notre `cooldownTime` en compte. Premièrement, après avoir défini `myZombie`, ajoutons une déclaration `require` qui vérifie `_isReady()` en lui passant `myZombie`. De cette manière l'utilisateur peut seulement exécuter cette fonction si le compte à rebours du zombie est écoulé. +2. Faites en sorte que `feedAndMultiply` prenne notre `cooldownTime` en compte. Premièrement, après avoir défini `myZombie`, ajoutons une déclaration `require` qui vérifie `_isReady()` en lui passant `myZombie`. De cette manière, l'utilisateur peut seulement exécuter cette fonction si le compte à rebours du zombie est écoulé. 3. A la fin de la fonction, appelez `_triggerCooldown(myZombie)` afin que l'action de manger déclenche le compte à rebours du zombie. diff --git a/fr/3/08-functionmodifiers.md b/fr/3/08-functionmodifiers.md index f8ab2c6535..011b2632a5 100644 --- a/fr/3/08-functionmodifiers.md +++ b/fr/3/08-functionmodifiers.md @@ -181,7 +181,7 @@ Nous allons faire en sorte que les zombies acquièrent des aptitudes spéciales ## Modificateurs de fonction avec arguments -Précédemment nous avons vu l'exemple simple de `onlyOwner`. Mais les modificateurs de fonction peuvent aussi prendre des arguments, par exemple : +Précédemment, nous avons vu l'exemple simple de `onlyOwner`. Mais les modificateurs de fonction peuvent aussi prendre des arguments, par exemple : ``` // Un mappage pour stocker l'âge d'un utilisateur : @@ -202,7 +202,7 @@ function driveCar(uint _userId) public olderThan(16, _userId) { Vous pouvez voir ici que le modificateur `olderThan` prend des arguments comme une fonction. Et que la fonction `driveCar` donne ces arguments au modificateur. -Essayons de faire notre propre `modifier` qui utilise le `level` d'un zombie pour restreindre l'accès a des aptitudes spéciales. +Essayons de faire notre propre `modifier` qui utilise le `level` d'un zombie pour restreindre l'accès à des aptitudes spéciales. ## A votre tour @@ -210,4 +210,4 @@ Essayons de faire notre propre `modifier` qui utilise le `level` d'un zombie pou 2. Le corps devra s'assurer que `zombies[_zombieId].level` soit plus grand ou égal à `_level`. -3. Rappelez vous que la dernière ligne d'un modificateur doit appeler le reste de la fonction avec `_;`. +3. Rappelez-vous que la dernière ligne d'un modificateur doit appeler le reste de la fonction avec `_;`. diff --git a/fr/3/09-zombiemodifiers.md b/fr/3/09-zombiemodifiers.md index 78096f1c21..b59ee8f05e 100644 --- a/fr/3/09-zombiemodifiers.md +++ b/fr/3/09-zombiemodifiers.md @@ -184,7 +184,7 @@ Notre jeu aura quelques incitatifs pour que les gens fassent gagner des niveaux - Pour les zombies de niveau 2 ou plus, les utilisateurs pourront changer leur nom. - Pour les zombies de niveau 20 ou plus, les utilisateurs pourront leur donner un ADN personnalisé. -Nous implémenterons ces fonctions ci-dessous. Voici un exemple de code d'une leçon précédente en référence : +Nous implémenterons les fonctions ci-dessous. Voici un exemple de code d'une leçon précédente en référence : ``` // Un mappage pour stocker l'âge d'un utilisateur : @@ -211,4 +211,4 @@ function driveCar(uint _userId) public olderThan(16, _userId) { 3. Ensuite la fonction devra définir `zombies[_zombieId].name` égal à `_newName`. -4. Créez une autre fonction `changeDna` en dessous de `changeName`. Sa définition et son contenu seront presque identiques à `changeName`, excepté pour le second argument qui sera `_newDna` (un `uint`), et qu'elle devra passer `20` pour l'argument `_level` à `aboveLevel`. Et bien sûr, elle devra définir le `dna` zombie égal à `_newDna` au lieu de définir le nom du zombie. +4. Créez une autre fonction `changeDna` en dessous de `changeName`. Sa définition et son contenu seront presque identiques à `changeName`, exceptés pour le second argument qui sera `_newDna` (un `uint`), et le fait qu'elle devra passer `20` pour l'argument `_level` à `aboveLevel`. Et bien sûr, elle devra définir le `dna` zombie égal à `_newDna` au lieu de définir le nom du zombie. diff --git a/fr/3/10-savinggasview.md b/fr/3/10-savinggasview.md index 08d6b2f4fe..d2fa2b3d68 100644 --- a/fr/3/10-savinggasview.md +++ b/fr/3/10-savinggasview.md @@ -194,19 +194,19 @@ material: Excellent ! Nous avons maintenant des aptitudes spéciales pour nos zombies de niveau supérieur, afin de motiver les utilisateurs à leurs faire gagner des niveaux. Nous pourrons en ajouter plus par la suite si nous le désirons. -Nous allons ajouter une fonction de plus : notre DApp a besoin d'une fonction pour voir toute l'armée de zombie d'un utilisateur - nous allons l'appeler `getZombiesByOwner`. +Nous allons ajouter une fonction de plus : notre DApp a besoin d'une fonction pour voir toute l'armée de zombies d'un utilisateur - nous allons l'appeler `getZombiesByOwner`. -Cette fonction permettra seulement de lire des données depuis la blockchain, cela sera donc une fonction `view`. Ce qui nous amène à un sujet important à propos de l'optimisation de gas : +Cette fonction permettra seulement de lire des données depuis la blockchain ; cela sera donc une fonction `view`. Ce qui nous amène à un sujet important à propos de l'optimisation de gas : ## Les fonctions `view` ne coûtent pas de gas Les fonctions `view` ne coûtent pas de gas quand elles sont appelées extérieurement par un utilisateur. -C'est parce que les fonctions `view` ne changent rien sur la blockchain - elles lisent seulement des données. Marquer une fonction avec `view` indique à `web3.js` qu'il a seulement besoin d'interroger votre nœud local d'Ethereum pour faire marcher la fonction, et il n'a pas besoin de créer une transaction sur la blockchain (qui devra être exécuter sur tous les nœuds et qui coûtera du gas). +C'est parce que les fonctions `view` ne changent rien sur la blockchain - elles lisent seulement des données. Marquer une fonction avec `view` indique à `web3.js` qu'il a seulement besoin d'interroger votre nœud local d'Ethereum pour faire marcher la fonction, et il n'a pas besoin de créer une transaction sur la blockchain (qui devra être exécutée sur tous les nœuds et qui aura un coût en gas). -Nous parlerons de comment configurer web3.js avec notre propre nœud plus tard. Pour l'instant, la chose à retenir est que vous pouvez optimiser la consommation de gas de votre DApp pour vos utilisateurs en utilisant les fonctions `external view` quand c'est possible. +Nous parlerons de comment configurer web3.js avec notre propre nœud plus tard. Pour l'instant, la chose à retenir est que vous pouvez optimiser la consommation de gas de votre DApp pour vos utilisateurs en utilisant les fonctions `external view` lorsque c'est possible. -> Remarque : Si une fonction `view` est appelée intérieurement à partir d'une autre fonction du même contrat qui **n'est pas** une fonction `view`, elle coûtera du gas. C'est parce que l'autre fonction va créer une transaction sur Ethereum, et aura besoin d'être vérifiée par chaque nœud. Ainsi les fonctions `view` sont gratuites seulement quand elles sont appelées depuis l'extérieur. +> Remarque : Si une fonction `view` est appelée intérieurement à partir d'une autre fonction du même contrat qui **n'est pas** une fonction `view`, elle aura un coût en gas. C'est parce que l'autre fonction va créer une transaction sur Ethereum, et aura besoin d'être vérifiée par chaque nœud. Ainsi, les fonctions `view` sont gratuites seulement lorsqu'elles sont appelées depuis l'extérieur. ## A votre tour @@ -214,7 +214,7 @@ Nous allons implémenter une fonction qui retournera toute l'armée de zombies d La logique de cette fonction est un peu compliquée, il nous faudra plusieurs chapitres pour l'implémenter. -1. Créez une nouvelle fonction appelée `getZombiesByOwner` avec un paramètre, une `address` appelée `_owner`. +1. Créez une nouvelle fonction appelée `getZombiesByOwner` avec un paramètre : une `address` appelée `_owner`. 2. Ce sera une fonction `external`, afin que nous puissions l'appeler depuis `web3.js` sans que cela nous coûte de gas. diff --git a/fr/3/11-savinggasstorage.md b/fr/3/11-savinggasstorage.md index ac98c88e24..9fe8c25e63 100644 --- a/fr/3/11-savinggasstorage.md +++ b/fr/3/11-savinggasstorage.md @@ -196,11 +196,11 @@ material: } --- -Une des opérations les plus coûteuse en Solidity est d'utiliser `storage` - particulièrement quand on écrit. +Une des opérations les plus coûteuses en Solidity est d'utiliser `storage` - particulièrement quand on écrit. C'est parce qu'à chaque fois que vous écrivez ou changez un bout d'information, c'est écrit de manière permanente sur la blockchain. Pour toujours ! Des milliers de nœuds à travers le monde vont stocker cette information sur leurs disques durs, et cette quantité d'information continue de grandir au fur et à mesure que la blockchain grandit. Et il y a un prix à cela. -Afin de réduire les coûts, vous voulez éviter d'écrire des données en stockage à part quand c'est absolument nécessaire. Par moment cela peut impliquer une logique de programmation qui a l'air inefficace - comme reconstruire un tableau dans la `memory` à chaque fois que la fonction est appelée au lieu de sauvegarder ce tableau comme une variable afin de le retrouver rapidement. +Afin de réduire les coûts, vous voulez éviter d'écrire des données en stockage, à part quand c'est absolument nécessaire. Par moment, cela peut impliquer une logique de programmation qui a l'air inefficace - comme reconstruire un tableau dans la `memory` à chaque fois que la fonction est appelée, au lieu de sauvegarder ce tableau comme une variable afin de le retrouver rapidement. Dans la plupart des langages de programmation, faire une boucle sur un grand ensemble de données est coûteux. Mais en Solidity, c'est beaucoup moins cher que d'utiliser `storage` s'il y a une fonction `external view`, puisque `view` ne coûte aucun gas. (Et le gas coûte réellement de l'argent pour vos utilisateurs !). @@ -208,7 +208,7 @@ Nous allons voir les boucles `for` dans le prochain chapitre, mais pour l'instan ## Déclarer des tableaux dans la mémoire -Vous pouvez utiliser le mot clé `memory` avec des tableaux afin de créer un nouveau tableau dans une fonction sans avoir besoin de l'écrire dans le stockage. Le tableau existera seulement jusqu'à la fin de l'appel de la fonction, et cela sera beaucoup plus économique, d'un point de vue du gas, que de mettre à jour un tableau dans `storage` - c'est gratuit si c'est une fonction `view` appelée extérieurement. +Vous pouvez utiliser le mot-clé `memory` avec des tableaux afin de créer un nouveau tableau dans une fonction sans avoir besoin de l'écrire dans le stockage. Le tableau existera seulement jusqu'à la fin de l'appel de la fonction, et cela sera beaucoup plus économique (en gas), que de mettre à jour un tableau dans `storage` - c'est gratuit si c'est une fonction `view` appelée extérieurement. Voici comment déclarer un tableau dans la mémoire : @@ -235,6 +235,6 @@ Dans notre fonction `getZombiesByOwner`, nous voulons renvoyer un tableau `uint[ 1. Déclarez une variable `uint[] memory` appelée `result` -2. Définissez la égale à un nouveau tableau de `uint`. La longueur du tableau devra être le nombre de zombies que cet `_owner` possède, qui peut être obtenu à partir de notre `mapping` en faisant : `ownerZombieCount[_owner]`. +2. Définissez-la égale à un nouveau tableau de `uint`. La longueur du tableau devra être le nombre de zombies que cet `_owner` possède, qui peut être obtenu à partir de notre `mapping` en faisant : `ownerZombieCount[_owner]`. -3. A la fin de la fonction, renvoyez `result`. Pour l'instant c'est simplement un tableau vide, mais nous le remplirons dans le prochain chapitre. +3. A la fin de la fonction, renvoyez `result`. Pour l'instant, c'est simplement un tableau vide, mais nous le remplirons dans le prochain chapitre. diff --git a/fr/3/12-forloops.md b/fr/3/12-forloops.md index 1b65c45efa..a840b90008 100644 --- a/fr/3/12-forloops.md +++ b/fr/3/12-forloops.md @@ -214,7 +214,7 @@ Pour notre fonction `getZombiesByOwner`, une implémentation naïve serait de st mapping (address => uint[]) public ownerToZombies ``` -Et à chaque fois que l'on créerait un nouveau zombie, nous utiliserions simplement `ownerToZombies[owner].push(zombieId)` pour l'ajouter au tableau de zombie de son propriétaire. Et `getZombiesByOwner` serait une fonction toute simple : +Et à chaque fois que l'on créerait un nouveau zombie, nous utiliserions simplement `ownerToZombies[owner].push(zombieId)` pour l'ajouter au tableau de zombies de son propriétaire. Et `getZombiesByOwner` serait une fonction toute simple : ``` function getZombiesByOwner(address _owner) external view returns (uint[]) { @@ -224,7 +224,7 @@ function getZombiesByOwner(address _owner) external view returns (uint[]) { ### Le problème avec cette approche -Il serait tentant de faire comme cela par simplicité. Mais regardons ce qu'il arriverait si nous ajoutions plus tard une fonction pour transférer un zombie d'un propriétaire à un autre (Ce que nous allons certainement vouloir dans une prochaine leçon !). +Il serait tentant de faire comme cela par simplicité. Mais regardons ce qui arriverait si nous ajoutons plus tard une fonction pour transférer un zombie d'un propriétaire à un autre (Ce que nous allons certainement vouloir faire dans une prochaine leçon !). La fonction de transfert devra : 1. Ajouter le zombie au tableau `ownerToZombies` du nouveau propriétaire @@ -232,13 +232,13 @@ La fonction de transfert devra : 3. Décaler chaque zombie du tableau de l'ancien propriétaire d'une place pour boucher le trou, et enfin 4. Réduire la taille du tableau de 1. -L'étape 3 serait extrêmement coûteuse en gas, vu que nous aurions besoin de réécrire chaque zombie décalé. Si un propriétaire a 20 zombies, et échange le premier, nous devrions faire 19 écritures pour garder l'ordre du tableau. +L'étape 3 serait extrêmement coûteuse en gas, vu que nous aurions besoin de réécrire chaque zombie décalé. Si un propriétaire a 20 zombies, et échange le premier, nous devrons faire 19 écritures pour garder l'ordre du tableau. -Puisque écrire dans le stockage est une des opérations les plus chères en Solidity, chaque appel à cette fonction de transfert serait extrêmement coûteuse en gas. Et encore pire, cela coûterait un montant de gas différent à chaque appel, en fonction de combien de zombie l'utilisateur a dans son armée et de l'index du zombie transféré. L'utilisateur ne saurait pas combien de gas envoyer. +Puisque écrire dans le stockage est une des opérations les plus chères en Solidity, chaque appel à cette fonction de transfert serait extrêmement coûteuse en gas. Et encore pire, cela coûterait un montant de gas différent à chaque appel, en fonction de combien de zombies l'utilisateur a dans son armée et de l'index du zombie transféré. L'utilisateur ne saurait pas combien de gas envoyer. > Remarque : Bien sûr, nous pourrions juste bouger le dernier zombie du tableau pour combler le trou et réduire la taille du tableau de 1. Mais nous changerions l'ordre de notre armée de zombies à chaque transfert. -Comme les fonctions `view` ne coûtent pas de gas quand elles sont appelées extérieurement, nous pouvons simplement utiliser une boucle `for` dans `getZombiesByOwner` pour parcourir le tableau entier de zombie et construire un tableau de zombies qui appartiennent à un utilisateur spécifique. Ainsi notre fonction `transfer` sera beaucoup moins coûteuse, puisque nous n'aurons pas besoin de réorganiser un tableau dans le stockage, et bien qu'étant contre-intuitive cette approche est moins chère globalement. +Comme les fonctions `view` ne coûtent pas de gas quand elles sont appelées extérieurement, nous pouvons simplement utiliser une boucle `for` dans `getZombiesByOwner` pour parcourir le tableau entier de zombie et construire un tableau de zombies qui appartiennent à un utilisateur spécifique. Ainsi, notre fonction `transfer` sera beaucoup moins coûteuse, puisque nous n'aurons pas besoin de réorganiser un tableau dans le stockage, et bien qu'étant contre-intuitive, cette approche est moins chère globalement. ## Utiliser des boucles `for` @@ -269,11 +269,11 @@ Cette fonction retournera un tableau contenant `[2, 4, 6, 8, 10]`. ## A votre tour -Finissons notre fonction `getZombiesByOwner` en écrivant une boucle `for` qui va parcourir tous les zombies de notre DApp, comparer leur propriétaire afin de voir s'il correspond, et les rajouter à notre tableau `result` avant de le retourner. +Finissons notre fonction `getZombiesByOwner` en écrivant une boucle `for` qui va parcourir tous les zombies de notre DApp, comparer leur propriétaire afin de voir s'il correspond, et les ajouter à notre tableau `result` avant de le retourner. 1. Déclarer un `uint` appelé `counter` qui soit égal à `0`. Nous utiliserons cette variable pour connaître l'index de notre tableau `result`. -2. Déclarez une boucle `for` qui commence à `uint i = 0` et qui va jusqu'à `i < zombies.length`. Cela parcourra tous les zombies de notre tableau. +2. Déclarez une boucle `for` qui commence à `uint i = 0` et qui va jusqu'à `i < zombies.length`. Elle parcourra tous les zombies de notre tableau. 3. Dans cette boucle `for`, faire une déclaration `if` qui va vérifier si `zombieToOwner[i]` est égal à `_owner`. Cela comparera les 2 adresses pour voir si elles sont égales. @@ -281,4 +281,4 @@ Finissons notre fonction `getZombiesByOwner` en écrivant une boucle `for` qui v 1. Ajoutez l'ID du zombie à notre tableau `result` en mettant `result[counter]` égal à `i`. 2. Incrémentez `counter` de 1 (voir l'exemple de boucle `for` ci-dessus). -Et voilà - la fonction va maintenant renvoyer tous les zombies d'un utilisateur `_owner` sans dépenser du gas. +Et voilà ! La fonction va maintenant renvoyer tous les zombies d'un utilisateur `_owner` sans dépenser du gas. diff --git a/fr/3/13-wrappingitup.md b/fr/3/13-wrappingitup.md index abffcf32a9..d314a5872f 100644 --- a/fr/3/13-wrappingitup.md +++ b/fr/3/13-wrappingitup.md @@ -16,12 +16,12 @@ Félicitations ! Vous avez terminé la Leçon 3. ## Récapitulons : -- Nous avons ajouté un moyen de mettre à jour notre contrat CryptoKitties -- Nous avons appris à protéger les fonctions principales avec `onlyOwner` -- Nous avons appris ce qu'est le gas et son optimisation -- Nous avons ajouté niveau et compte à rebours à nos zombies -- Nous avons maintenant des fonctions pour mettre à jour le nom d'un zombie et son ADN une fois que le zombie a un certain niveau -- Et enfin, nous avons maintenant une fonction pour renvoyer l'armée de zombies d'un utilisateur +- Nous avons ajouté un moyen de mettre à jour notre contrat CryptoKitties. +- Nous avons appris à protéger les fonctions principales avec `onlyOwner`. +- Nous avons appris ce qu'est le gas et son optimisation. +- Nous avons ajouté niveau et compte à rebours à nos zombies. +- Nous avons maintenant des fonctions pour mettre à jour le nom d'un zombie et son ADN une fois que le zombie a un certain niveau. +- Et enfin, nous avons maintenant une fonction pour renvoyer l'armée de zombies d'un utilisateur. ## Voici votre récompense diff --git a/fr/4/battle-02.md b/fr/4/battle-02.md index b4d525ad36..3c7dc82bc3 100644 --- a/fr/4/battle-02.md +++ b/fr/4/battle-02.md @@ -257,11 +257,11 @@ Si j'ai un nœud, je pourrais publier une transaction **seulement à mon propre Parce que tout le contenu de la blockchain est visible de tous les participants, c'est un problème difficile, et la solution est au-delà du cadre de ce tutoriel. Vous pouvez lire Cette discussion StackOverflow (en anglais) pour vous faire une idée. Une des possibilités serait d'avoir un **_oracle_** pour avoir accès à une fonction aléatoire en dehors de la blockchain Ethereum. -Bien sur, puisque des dizaine de milliers de nœuds Ethereum sur le réseau rivalisent pour résoudre le prochain bloc, mes chances de résoudre le prochain bloc sont vraiment faibles. Il me faudrait énormément de puissance de calcul et de temps pour réussir à l'exploiter - mais si la récompense est assez élevée (si je pouvais parier 100 000 000$ sur la fonction pile ou face), cela vaudrait la peine de l'attaquer. +Bien sûr, puisque des dizaines de milliers de nœuds Ethereum sur le réseau rivalisent pour résoudre le prochain bloc, mes chances de résoudre le prochain bloc sont vraiment faibles. Il me faudrait énormément de puissance de calcul et de temps pour réussir à l'exploiter - mais si la récompense est assez élevée (si je pouvais parier 100 000 000$ sur la fonction pile ou face), cela vaudrait la peine de l'attaquer. Même si cette fonction aléatoire N'EST PAS sécurisée sur Ethereum, en pratique, à part si notre fonction aléatoire a beaucoup d'argent en jeu, les utilisateurs de votre jeu n'auront sûrement pas assez de ressources pour l'attaquer. -Puisque nous construisons simplement un jeu à des fin de démonstration dans ce tutoriel, et qu'il n'y a pas vraiment d'argent en jeu, nous allons accepter les compromis d'utiliser un générateur de nombre aléatoire simple à implémenter, sachant qu'il n'est pas totalement sûr. +Puisque nous construisons simplement un jeu à des fins de démonstration dans ce tutoriel, et qu'il n'y a pas vraiment d'argent en jeu, nous allons accepter les compromis d'utiliser un générateur de nombre aléatoire simple à implémenter, sachant qu'il n'est pas totalement sûr. Dans une prochaine leçon, il se peut que nous voyons comment utiliser des **_oracles_** (un moyen sécurisé de récupérer des données en dehors d'Ethereum) pour générer une fonction aléatoire depuis l'extérieur de la blockchain. @@ -275,4 +275,4 @@ Nous allons implémenter une fonction de nombre aléatoire que nous pourrons uti 3. La fonction devra d'abord incrémenter `randNonce` (en utilisant la syntaxe `randNonce++`). -4. Enfin, elle devra (en une ligne de code) calculer un `uint` à partir du hachage `keccak256` de `now`, `msg.sender` et `randNonce` - et renvoyer avec `return` cette valeur modulo (%) `_modulus`. (Ouf! C'était un gros morceau, si vous n'avez pas tout suivi, jetez un œil à l'exemple ci-dessus où nous avons généré un nombre aléatoire - la logique est très similaire). +4. Enfin, elle devra (en une ligne de code) calculer un `uint` à partir du hachage `keccak256` de `now`, `msg.sender` et `randNonce` - et renvoyer avec `return` cette valeur modulo (%) `_modulus`. (Ouf ! C'était un gros morceau, si vous n'avez pas tout suivi, jetez un œil à l'exemple ci-dessus où nous avons généré un nombre aléatoire - la logique est très similaire). diff --git a/fr/4/battle-03.md b/fr/4/battle-03.md index 2d6e3443bb..e3544f8096 100644 --- a/fr/4/battle-03.md +++ b/fr/4/battle-03.md @@ -227,16 +227,16 @@ material: } --- -Maintenant que nous avons une source d'aléatoire dans notre contrat, nous pouvons l'utiliser dans nos combats de zombie pour calculer le résultat. +Maintenant que nous avons une source d'aléatoire dans notre contrat, nous pouvons l'utiliser dans nos combats de zombies pour calculer le résultat. -Les combats de zombie fonctionnent ainsi : +Les combats de zombies fonctionnent ainsi : -- Vous choisissez un de vos zombies, et un zombie adversaire à attaquer. -- Si vous êtes le zombie attaquant, vous avez 70% de chance de gagner. Le zombie qui se défend à 30% de chance de gagner. -- Tous les zombies (attaquant et défendant) auront un `winCount` (compteur de victoire) et `lossCount` (compteur de défaite) qui vont évoluer en fonction du résultat du combat. +- Vous choisissez un de vos zombies, et un zombie ennemi à attaquer. +- Si vous êtes le zombie attaquant, vous avez 70% de chances de gagner. Le zombie qui se défend à 30% de chances de gagner. +- Tous les zombies (attaquant et défendant) auront un `winCount` (compteur de victoires) et `lossCount` (compteur de défaites) qui vont évoluer en fonction du résultat du combat. - Si le zombie attaquant gagne, il gagne un niveau et fait naître un nouveau zombie. - S'il perd, rien ne se passe (à part son `lossCount` qui augmente). -- Qu'il gagne ou perdre, le compte à rebours de repos du zombie attaquant est déclenché. +- Qu'il gagne ou perde, le compte à rebours de repos du zombie attaquant est déclenché. Cela fait beaucoup de logique à implémenter, nous allons donc le faire en plusieurs fois au cours des prochains chapitres. diff --git a/fr/4/battle-04.md b/fr/4/battle-04.md index 62f99470a9..e6e0edf9ec 100644 --- a/fr/4/battle-04.md +++ b/fr/4/battle-04.md @@ -284,7 +284,7 @@ Réfléchissez-y, et voyez si vous arrivez à trouver une réponse tout seul. Prenez votre temps, vous pouvez regarder le code des versions précédentes pour avoir des idées... -La réponse se trouve ci-dessous, réfléchissez par vous même avant de continuer. +La réponse se trouve ci-dessous, réfléchissez par vous-même avant de continuer. ## La réponse @@ -302,7 +302,7 @@ Nous sommes de retour à `zombiefeeding.sol`, puisque c'est le premier endroit o 1. Créez un `modifier` appelé `ownerOf` qui aura un paramètre, `_zombieId` (un `uint`). - Le corps devra vérifier avec `require` que `msg.sender` soit égal à `zombieToOwner[_zombieId]`, puis continuer avec la fonction. Vous pouvez regarder la fonction `zombiehelper.sol` si vous ne vous rappelez plus de la syntaxe d'un modificateur. + Le corps devra vérifier avec `require` que `msg.sender` est égal à `zombieToOwner[_zombieId]`, puis continuer avec la fonction. Vous pouvez regarder la fonction `zombiehelper.sol` si vous ne vous rappelez plus de la syntaxe d'un modificateur. 2. Changez la définition de la fonction `feedAndMultiply` afin qu'elle utilise le modificateur `ownerOf`. diff --git a/fr/4/battle-05.md b/fr/4/battle-05.md index de87cc4dd0..3ab20943ab 100644 --- a/fr/4/battle-05.md +++ b/fr/4/battle-05.md @@ -261,6 +261,6 @@ Il y a encore quelques endroits dans `zombiehelper.sol` où nous devons impléme ## A votre tour -1. Mettez à jour `changeName()` pour utiliser `ownerOf` +1. Mettez à jour `changeName()` pour utiliser `ownerOf`. -2. Mettez à jour `changeDna()` pour utiliser `ownerOf` +2. Mettez à jour `changeDna()` pour utiliser `ownerOf`. diff --git a/fr/4/battle-07.md b/fr/4/battle-07.md index 6121b63c59..b4af963e8a 100644 --- a/fr/4/battle-07.md +++ b/fr/4/battle-07.md @@ -262,11 +262,11 @@ material: } --- -Pour notre jeu de zombie, nous allons vouloir comptabiliser le nombre de victoire et de défaite de nos zombies. Ainsi nous pourrons avoir un "classement zombie" dans notre jeu. +Pour notre jeu de zombie, nous allons vouloir comptabiliser le nombre de victoires et de défaites de nos zombies. Ainsi nous pourrons avoir un "classement zombies" dans notre jeu. Nous pouvons stocker ces données de plusieurs façons dans notre DApp - un mappage individuel, une structure classement, ou directement dans la structure `Zombie`. -Chaque méthode a ses avantages et ses inconvénients, dépendamment de comment nous voulons interagir avec ces données. Pour ce tutoriel, nous allons stocker les statistiques dans notre structure `Zombie` par simplicité, et les appeler `winCount` et `lossCount`. +Chaque méthode a ses avantages et ses inconvénients, qui dépendent de comment nous voulons interagir avec ces données. Pour ce tutoriel, nous allons stocker les statistiques dans notre structure `Zombie` par simplicité, et les appeler `winCount` et `lossCount`. Revenons à `zombiefactory.sol`, et ajoutons ces propriétés à notre structure `Zombie`. @@ -278,8 +278,8 @@ Revenons à `zombiefactory.sol`, et ajoutons ces propriétés à notre structure b. `lossCount`, aussi un `uint16` - > Remarque : Rappelez-vous, puisque nous pouvons combiner les `uint`s dans une structure, nous voulons utiliser le plus petit `uint` possible. un `uint8` serait trop petit, car 2^8 = 256 - si nos zombies attaquent tous les jours, en un an cela pourrait être dépassé. Mais 2^16 = 65536 - alors à moins qu'un utilisateur ne fasse que gagner ou que perdre chaque jour pendant 179 ans, nous sommes tranquilles. + > Remarque : Rappelez-vous, puisque nous pouvons combiner les `uint`s dans une structure, nous voulons utiliser le plus petit `uint` possible. un `uint8` serait trop petit, car 2^8 = 256 - si nos zombies attaquent tous les jours, en moins d'un an, cela pourrait être dépassé. Mais 2^16 = 65536 - alors à moins qu'un utilisateur ne fasse que gagner ou que perdre chaque jour pendant 179 ans, nous sommes tranquilles. 2. Maintenant que nous avons de nouvelles propriétés pour notre structure `Zombie`, nous devons changer la définition de notre fonction `_createZombie()`. - Changez la définition de création de zombie pour que chaque nouveau zombie créé est `0` victoire et `0` défaite. + Changez la définition de création de zombie pour que chaque nouveau zombie créé ait `0` victoire et `0` défaite. diff --git a/fr/4/battle-08.md b/fr/4/battle-08.md index 8add487691..e695cf683f 100644 --- a/fr/4/battle-08.md +++ b/fr/4/battle-08.md @@ -242,7 +242,7 @@ material: Maintenant que nous avons un `winCount` et un `lossCount`, nous pouvons les mettre à jour en fonction du zombie qui gagne le combat. -Au chapitre 6 nous avons calculé un nombre aléatoire entre 0 et 100. Nous allons utiliser ce nombre pour déterminer le vainqueur du combat, et mettre à jour en conséquence. +Au chapitre 6, nous avons calculé un nombre aléatoire entre 0 et 100. Nous allons utiliser ce nombre pour déterminer le vainqueur du combat, et mettre à jour en conséquence. ## A votre tour @@ -257,4 +257,4 @@ Au chapitre 6 nous avons calculé un nombre aléatoire entre 0 et 100. Nous allo c. Incrémentez le `lossCount` de `enemyZombie`. (Le nul !!!!!! 😫 😫 😫) - d. Exécutez la fonction `feedAndMultiply`. Regardez `zombiefeeding.sol` pour voir la syntaxe pour l'appeler. Pour le 3ème argument (`_species_`), mettez `"zombie"`. (Cela ne fait rien pour l'instant, mais plus tard nous pourrons ajouter des fonctionnalités supplémentaires pour les zombies générés à partir d'autres zombies). + d. Exécutez la fonction `feedAndMultiply`. Regardez `zombiefeeding.sol` pour voir la syntaxe afin de l'appeler. Pour le 3ème argument (`_species_`), mettez `"zombie"`. (Cela ne fait rien pour l'instant, mais plus tard nous pourrons ajouter des fonctionnalités supplémentaires pour les zombies générés à partir d'autres zombies). diff --git a/fr/4/battle-09.md b/fr/4/battle-09.md index 601bd51f35..25b78d48ef 100644 --- a/fr/4/battle-09.md +++ b/fr/4/battle-09.md @@ -249,7 +249,7 @@ material: } --- -Maintenant que nous avons codé ce qu'il se passe quand notre zombie gagne, voyons voir ce qu'il arrive quand il **perd**. +Maintenant que nous avons codé ce qu'il se passe lorsque notre zombie gagne, voyons voir ce qu'il arrive quand il **perd**. Dans notre jeu, quand les zombies perdent, ils ne perdent pas de niveau - ils rajoutent simplement une défaite à leur compteur `lossCount`, et leur compte à rebours est déclenché afin qu'ils attendent un jour pour attaquer de nouveau. @@ -273,4 +273,4 @@ if (zombieCoins[msg.sender] > 100000000) { b. Incrémentez `winCount` de `enemyZombie`. -2. En dehors de la déclaration `else`, exécutez la fonction `_triggerCooldown` sur `myZombie`. De cette manière le zombie ne peut attaquer qu'une fois par jour. +2. En dehors de la déclaration `else`, exécutez la fonction `_triggerCooldown` sur `myZombie`. De cette manière, le zombie ne peut attaquer qu'une fois par jour. diff --git a/fr/4/payable.md b/fr/4/payable.md index 97ed9434ab..cbaa22cc8f 100644 --- a/fr/4/payable.md +++ b/fr/4/payable.md @@ -231,11 +231,11 @@ material: Nous avons, jusqu'à présent, vu plusieurs **_modificateurs de fonction_**. Il n'est pas forcément évident de se rappeler de tous, nous allons donc les revoir rapidement : -1. Il existe des modificateurs de visibilité qui contrôlent quand et depuis où la fonction peut être appelée : `private` veut dire que la fonction ne peut être appelée que par les autres fonctions à l'intérieur du contrat; `internal` est comme `private` mais en plus, elle peut être appelée par les contrats qui héritent de celui-ci; avec `external`, la fonction ne peut être appelée que depuis l'extérieur du contrat; et enfin avec `public`, elle peut être appelée depuis n'importe où, à l'intérieur et à l'extérieur. +1. Il existe des modificateurs de visibilité qui contrôlent quand et depuis où la fonction peut être appelée : `private` veut dire que la fonction ne peut être appelée que par les autres fonctions à l'intérieur du contrat ; `internal` est comme `private` mais en plus, elle peut être appelée par les contrats qui héritent de celui-ci ; avec `external`, la fonction ne peut être appelée que depuis l'extérieur du contrat ; et enfin avec `public`, elle peut être appelée depuis n'importe où, à l'intérieur et à l'extérieur. -2. Il existe aussi des modificateurs d'état, qui nous indiquent comment la fonction interagit avec la BlockChain : `view` nous indique qu'en exécutant cette fonction, aucune donnée ne sera écrite/modifiée. `pure` nous indique que non seulement aucune donnée ne sera enregistrée sur la BlockChain, mais qu'en plus aucune donnée de la BlockChain ne sera lue. Ces 2 fonctions ne coûtent pas de gas si elles sont appelées depuis l'extérieur du contrat (mais elle coûtent du gas si elles sont appelées à l'intérieur du contrat par une autre fonction). +2. Il existe aussi des modificateurs d'état, qui nous indiquent comment la fonction interagit avec la BlockChain : `view` nous indique qu'en exécutant cette fonction, aucune donnée ne sera écrite/modifiée. `pure` nous indique que non seulement aucune donnée ne sera enregistrée sur la BlockChain, mais qu'en plus aucune donnée de la BlockChain ne sera lue. Ces 2 fonctions ne coûtent pas de gas si elles sont appelées depuis l'extérieur du contrat (mais elle ont un coût en gas si elles sont appelées à l'intérieur du contrat par une autre fonction). -3. Ensuite nous avons les modificateurs personnalisés, que nous avons étudiés à la leçon 3 : `onlyOwner` et `aboveLevel` par exemple. Nous avons pu déterminer des logiques personnalisés pour ceux-ci, afin de choisir de quelles manières ils affectent une fonction. +3. Ensuite, nous avons les modificateurs personnalisés, que nous avons étudiés à la leçon 3 : `onlyOwner` et `aboveLevel` par exemple. Nous avons pu déterminer des logiques personnalisées pour ceux-ci, afin de choisir de quelles manières ils affectent une fonction. On peut aussi ajouter plusieurs modificateurs à la définition d'une fonction : @@ -270,14 +270,14 @@ contract OnlineStore { Ici, `msg.value` est la façon de voir combien d'Ether ont été envoyés au contrat, et `ether` est une unité intégrée. -Quelqu'un va appeler la fonction depuis web3.js (depuis l'interface utilisateur JavaScript de la DApp) de cette manière là : +Quelqu'un va appeler la fonction depuis web3.js (depuis l'interface utilisateur JavaScript de la DApp) de cette manière : ``` // En supposant que `OnlineStore` pointe vers le contrat Ethereum : OnlineStore.buySomething({from: web3.eth.defaultAccount, value: web3.utils.toWei(0.001)}) ``` -On remarque le champs `value` (valeur), où l'appel de la fonction JavaScript indique combien d'`ether` envoyer (0.001). Si vous imaginez la transaction comme une enveloppe, et les paramètres que vous envoyez à l'appel de la fonction comme étant la lettre que vous mettez à l'intérieur, alors ajouter `value` revient au même que d'ajouter du cash à l'intérieur de l'enveloppe - la lettre et l'argent vont être donnés au même moment au destinataire. +On remarque le champ `value` (valeur), où l'appel de la fonction JavaScript indique combien d'`ether` envoyer (0.001). Si vous imaginez la transaction comme une enveloppe, et les paramètres que vous envoyez à l'appel de la fonction comme étant la lettre que vous mettez à l'intérieur, alors ajouter `value` revient au même que d'ajouter du cash à l'intérieur de l'enveloppe - la lettre et l'argent vont être donnés au même moment au destinataire. > Remarque : Si une fonction n'est pas marquée `payable` et que vous essayez de lui envoyer des Ether, la fonction rejettera votre transaction. diff --git a/fr/4/withdraw.md b/fr/4/withdraw.md index a8093d30f4..87d8d3cf89 100644 --- a/fr/4/withdraw.md +++ b/fr/4/withdraw.md @@ -262,14 +262,14 @@ Vous remarquerez que nous utilisons `owner` et `onlyOwner` du contrat `Ownable`, Vous pouvez transférer des Ether à une adresse en utilisant la fonction `transfer`, et `this.balance` retournera la balance totale stockée sur le contrat. Si 100 utilisateurs ont payé 1 Ether à votre contrat, `this.balance` sera égal à 100 Ether. -Vous pouvez utilisez `transfer` pour envoyer des fonds à n'importe quelle adresse Ethereum. Par exemple, vous pouvez avoir une fonction qui renvoie les Ether à `msg.sender` s'il paye trop cher pour un article : +Vous pouvez utiliser `transfer` pour envoyer des fonds à n'importe quelle adresse Ethereum. Par exemple, vous pouvez avoir une fonction qui renvoie les Ether à `msg.sender` s'il paye trop cher pour un article : ``` uint itemFee = 0.001 ether; msg.sender.transfer(msg.value - itemFee); ``` -Ou dans un contrat avec un acheteur et un vendeur, vous pouvez stocker l'adresse du vendeur, et quand quelqu'un achète son article, lui envoyer le montant payés par l'acheteur : `seller.transfer(msg.value)`. +Ou dans un contrat avec un acheteur et un vendeur, vous pouvez stocker l'adresse du vendeur, et quand quelqu'un achète son article, lui envoyer le montant payé par l'acheteur : `seller.transfer(msg.value)`. Ce sont quelques exemples de ce qui rend la programmation Ethereum vraiment cool - vous pouvez avoir des marchés décentralisés qui ne sont contrôlés par personne. diff --git a/fr/4/wrappingitup.md b/fr/4/wrappingitup.md index 8881e1a17e..bdf6e1a7a3 100644 --- a/fr/4/wrappingitup.md +++ b/fr/4/wrappingitup.md @@ -11,12 +11,12 @@ material: answer: 1 --- -Félicitations ! Cela termine la Leçon 4. +Félicitations ! Cela termine la leçon 4. Allez-y et testez votre fonction de combat à droite ! -## Revendiquer votre récompense +## Réclamer votre récompense Après avoir gagné le combat : diff --git a/fr/5/01-erc721-1.md b/fr/5/01-erc721-1.md index e28ddc0d71..28fb5503b5 100644 --- a/fr/5/01-erc721-1.md +++ b/fr/5/01-erc721-1.md @@ -246,33 +246,33 @@ Commençons par les **_tokens_**. Si vous êtes dans la sphère Ethereum depuis un moment, vous avez sûrement entendu parler des tokens - en particulier des **tokens ERC20**. -un **_token_** Ethereum est un smart contract qui suit un ensemble de règles - à savoir, il implémente un ensemble de fonctions standards que tous les autres contrats de tokens partagent, comme `transfer(address _to, uint256 _value)` et `balanceOf(address _owner)`. +Un **_token_** Ethereum est un smart contract qui suit un ensemble de règles - à savoir qu'il implémente un ensemble de fonctions standards que tous les autres contrats de tokens partagent, comme `transfer(address _to, uint256 _value)` et `balanceOf(address _owner)`. Le smart contract a habituellement un mappage interne, `mapping(address => uint256) balances`, qui permet de connaître le solde de chaque adresse. -Un token est simplement un contrat qui permet de connaître combien de ce token chaque personne possède, et qui a certaines fonctions pour permettre aux utilisateurs de transférer leurs tokens à d'autres adresses. +Un token est simplement un contrat qui permet de connaître le montant de ce token que chaque personne possède, et il a certaines fonctions pour permettre aux utilisateurs de transférer leurs tokens à d'autres adresses. ### Pourquoi c'est important ? Puisque tous les tokens ERC20 partagent le même ensemble de fonctions avec les mêmes noms, ils peuvent tous être manipulés de la même manière. -Cela veut dire que si vous construisez une application qui est capable d'interagir avec un token ERC20, elle sera aussi capable d'interagir avec n'importe quel token ERC20. De cette manière, d'autres tokens pourront facilement être ajoutés à votre application sans avoir besoin de personnaliser le code. Vous pourrez simplement rajouter la nouvelle adresse du contrat du token, et boom, votre application pourra utiliser un nouveau token. +Cela veut dire que si vous construisez une application qui est capable d'interagir avec un token ERC20, elle sera aussi capable d'interagir avec n'importe quel token ERC20. De cette manière, d'autres tokens pourront facilement être ajoutés à votre application sans avoir besoin de personnaliser le code. Vous pourrez simplement ajouter la nouvelle adresse du contrat du token, et boom, votre application pourra utiliser un nouveau token ! On pourrait prendre comme exemple un échange. Quand un échange ajoute un nouveau token ERC20, en vérité il a juste besoin d'ajouter un nouveau smart contract. Les utilisateurs pourront utiliser ce contrat pour envoyer des tokens sur l'adresse de l'échange, et l'échange pourra utiliser ce contrat pour renvoyer des tokens aux utilisateurs quand ils voudront retirer. -L'échange a simplement besoin d'implémenter une fois la logique de transfert, et quand il veut ajouter un nouveau token ERC20, il suffit d'ajouter l'adresse du nouveau contrat à sa base de données. +L'échange a simplement besoin d'implémenter la logique de transfert une seule fois, et lorsqu'il veut ajouter un nouveau token ERC20, il suffit d'ajouter l'adresse du nouveau contrat à sa base de données. ### Autres standards des tokens -Les tokens ERC20 sont vraiment pratiques pour servir en tant que monnaie. Mais ils ne sont pas vraiment utiles pour représenter des zombies dans notre jeu de zombie. +Les tokens ERC20 sont vraiment pratiques pour servir en tant que monnaie. Mais ils ne sont pas vraiment utiles pour représenter des zombies dans notre jeu de zombies. Premièrement, les zombies ne sont pas divisibles comme les monnaies - je peux vous envoyer 0.237 ETH, mais je ne peux pas vous envoyer 0.237 d'un zombie. -Deuxièmement, tous les zombies ne sont pas égaux. Votre zombie "**Pierre**" de niveau 2 n'est pas du tout égal à mon zombie de niveau 732 "**H4XF13LD MORRIS 💯💯😎💯💯**". (Tu peux pas test, *Pierre*). +Deuxièmement, tous les zombies ne sont pas égaux. Votre zombie "**Pierre**" de niveau 2 n'est pas du tout égal à mon zombie de niveau 732 "**H4XF13LD MORRIS 💯💯😎💯💯**". (Tu ne peux pas test, *Pierre*). Il existe un autre standard de token qui est beaucoup plus adapté pour les crypto-collectibles comme CryptoZombies — ce sont les **_tokens ERC721._** -Les **_tokens ERC721_** **ne** sont **pas** interchangeable puisqu'ils sont supposés être uniques, et ne sont pas divisibles. Vous pouvez seulement les échanger en entier, et ils ont chacun un ID unique. C'est exactement cela que l'on veut pour rendre nos zombies échangeables. +Les **_tokens ERC721_** **ne** sont **pas** interchangeables puisqu'ils sont supposés être uniques, et ne sont pas divisibles. Vous pouvez seulement les échanger en entier, et ils ont chacun un ID unique. C'est exactement cela que l'on veut pour rendre nos zombies échangeables. > Remarque : En utilisant un standard comme ERC721, nous n'avons pas besoin d'implémenter les logiques qui définissent comment les joueurs vont échanger / vendre les zombies. Si on respecte les spécifications, quelqu'un d'autre pourrait construire une plateforme d'échange pour les actifs crypto-échangeables, et nos zombies ERC721 seraient compatibles avec cette plateforme. C'est un avantage évident d'utiliser un standard de token au lieu d'implémenter sa propre logique d'échange. diff --git a/fr/5/02-erc721-2.md b/fr/5/02-erc721-2.md index b08edb3066..cfb4224cc0 100644 --- a/fr/5/02-erc721-2.md +++ b/fr/5/02-erc721-2.md @@ -280,7 +280,7 @@ C'est la liste des méthodes que nous allons devoir implémenter, c'est ce que n Cela pourrait paraître beaucoup, mais ne vous laissez pas impressionner ! Nous sommes là pour vous accompagner. -> Remarque : Le standard ERC721 est actuellement une *ébauche*, et il n'y a pas d'implémentation officiellement convenue. Pour ce tutoriel nous allons utiliser la version actuelle de la bibliothèque OpenZeppelin, mais il est possible que cela change dans le futur avant une sortie officielle. C'est donc **une** implémentation possible, mais ce n'est pas le standard officiel pour les tokens ERC721. +> Remarque : Le standard ERC721 est actuellement une *ébauche*, et il n'y a pas d'implémentation officiellement convenue. Pour ce tutoriel, nous allons utiliser la version actuelle de la bibliothèque OpenZeppelin, mais il est possible que cela change dans le futur avant une sortie officielle. C'est donc **une** implémentation possible, mais ce n'est pas le standard officiel pour les tokens ERC721. ### Implémenter le contrat d'un token diff --git a/fr/5/04-erc721-4.md b/fr/5/04-erc721-4.md index 2ed283dbf0..c8133ef718 100644 --- a/fr/5/04-erc721-4.md +++ b/fr/5/04-erc721-4.md @@ -332,9 +332,9 @@ material: } --- -Oups ! Nous venons juste de rajouter une erreur dans notre code qui l’empêche de compiler. Est-ce que vous l'avez vue ? +Oups ! Nous venons juste d'ajouter une erreur dans notre code qui l’empêche de compiler. Est-ce que vous l'avez vue ? -Dans le chapitre précédent, nous avons défini une fonction `ownerOf`. Mais si vous vous rappelez la Leçon 4, nous avons aussi créé un `modifier` avec le même nom, `ownerOf`, dans `zombiefeeding.sol`. +Dans le chapitre précédent, nous avons défini une fonction `ownerOf`. Mais si vous vous rappelez de la leçon 4, nous avons aussi créé un `modifier` avec le même nom, `ownerOf`, dans `zombiefeeding.sol`. Si vous essayez de compiler ce code, le compilateur va renvoyer une erreur vous disant qu'il ne peut pas y avoir un modificateur et une fonction avec le même nom. @@ -342,7 +342,7 @@ Pourrions-nous simplement changer le nom de la fonction dans `ZombieOwnership` e Non, nous ne pouvons pas faire ça !!! Rappelez-vous, nous utilisons le standard de token ERC721, ce qui veut dire que d'autres contrats vont s'attendre à ce que notre contrat ait les mêmes fonctions avec exactement les mêmes noms. C'est pour cela que ces standards sont utiles - si un autre contrat sait que notre contrat est conforme au standard ERC721, il peut simplement communiquer avec nous sans rien savoir de nos décisions d'implémentation interne. -Ce qui veut dire que nous allons devoir réorganiser notre code de la Leçon 4 pour changer le nom du `modifier` en quelque chose d'autre. +Ce qui veut dire que nous allons devoir réorganiser notre code de la leçon 4 pour changer le nom du `modifier` en quelque chose d'autre. ## A votre tour diff --git a/fr/5/05-erc721-5.md b/fr/5/05-erc721-5.md index 10dde5404c..f883b8d099 100644 --- a/fr/5/05-erc721-5.md +++ b/fr/5/05-erc721-5.md @@ -321,11 +321,11 @@ function takeOwnership(uint256 _tokenId) public; 1. La première façon est que le propriétaire du token appelle `transfer` (transférer) avec l'`address` de destination, et le `_tokenId` du token qu'il veut transférer. -2. La deuxième façon est que le propriétaire appelle d'abord `approve`, et lui envoie les mêmes informations que ci-dessus. Le contrat va stocker l'adresse qui a été approuvée à prendre un token, souvent dans un `mapping (uint256 => address)`. Ensuite quand quelqu'un va appeler `takeOwnership`, le contrat va vérifier que `msg.sender` a été approuvé par le propriétaire pour prendre le token, et si c'est le cas, il va lui transférer le token. +2. La deuxième façon est que le propriétaire appelle d'abord `approve`, et lui envoie les mêmes informations que ci-dessus. Le contrat va stocker l'adresse qui a été approuvée à prendre un token, souvent dans un `mapping (uint256 => address)`. Ensuite quand quelqu'un va appeler `takeOwnership`, le contrat va vérifier que `msg.sender` a été approuvée par le propriétaire pour prendre le token, et si c'est le cas, il va lui transférer le token. Vous remarquerez que `transfer` et `takeOwnership` contiennent la même logique de transfert, seulement en ordre inverse. (Dans un cas, c'est l'expéditeur du token qui appelle la fonction, dans l'autre c'est le destinataire du token qui l'appelle). -C'est donc logique de mettre cette logique dans sa propre fonction privée, `_transfer`, qui sera appelée par chacune des fonctions. De cette manière nous n'avons pas à réécrire le code deux fois. +C'est donc logique de mettre cette logique dans sa propre fonction privée, `_transfer`, qui sera appelée par chacune des fonctions. De cette manière, nous n'avons pas à réécrire le code deux fois. ## A votre tour @@ -337,10 +337,10 @@ Définissons la logique de `_transfer`. La première chose que notre fonction devra faire est d'incrémenter `ownerZombieCount` pour la personne qui **reçoit** le zombie (`address _to`). Utilisez `++` pour incrémenter. -3. Ensuite, nous allons devoir **réduire** le `ownerZombieCount` de la personne qui **envoie** le zombie (`address _from`). Utilisez `--` pour réduire. +3. Ensuite, nous allons devoir **réduire** le `ownerZombieCount` de la personne qui **envoie** le zombie (`address _from`). Utilisez `--` pour décrémenter. 4. Enfin, nous allons vouloir changer le mappage `zombieToOwner` de ce `_tokenId` afin qu'il pointe vers `_to`. -5. J'ai menti, ce n'était pas la dernière étape. Il reste encore une chose à faire. +5. J'ai menti, ce n'était pas la dernière étape... Il reste encore une chose à faire. - Les specs ERC721 contiennent un évènement `Transfer` (transfert). La dernière ligne de notre fonction devra déclencher `Transfer` avec les bonnes informations - regardez `erc721.sol` pour voir quels arguments doivent être donnés et mettez le en place ici. + Les specs ERC721 contiennent un évènement `Transfer` (transfert). La dernière ligne de notre fonction devra déclencher `Transfer` avec les bonnes informations - regardez `erc721.sol` pour voir quels arguments doivent être donnés et mettez-le en place ici. diff --git a/fr/5/06-erc721-6.md b/fr/5/06-erc721-6.md index 95694b7c55..12b846185b 100644 --- a/fr/5/06-erc721-6.md +++ b/fr/5/06-erc721-6.md @@ -314,7 +314,7 @@ material: } --- -Bien ! C'était la partie difficile — maintenant implémenter la fonction publique `transfer` va être facile, vu que notre fonction `_transfer` fait déjà presque tout le travail. +Bien ! C'était la partie difficile — maintenant, implémenter la fonction publique `transfer` va être facile, vu que notre fonction `_transfer` fait déjà presque tout le travail. ## A votre tour @@ -322,6 +322,6 @@ Bien ! C'était la partie difficile — maintenant implémenter la fonction publ Oui, c'est ça, nous avons déjà un modificateur qui fait ça. Ajoutez donc le modificateur `onlyOwnerOf` à cette fonction. -2. Maintenant le corps de la fonction se réduit à seulement une ligne... il a simplement besoin d'appeler `_transfer`. +2. Maintenant, le corps de la fonction se réduit à seulement une ligne... il a simplement besoin d'appeler `_transfer`. Assurez-vous de passer `msg.sender` pour l'`address _from` comme argument. diff --git a/fr/5/08-erc721-8.md b/fr/5/08-erc721-8.md index c6a6c61147..2428994c61 100644 --- a/fr/5/08-erc721-8.md +++ b/fr/5/08-erc721-8.md @@ -323,13 +323,13 @@ material: Bien, maintenant nous pouvons finir notre implémentation ERC721 avec la dernière fonction ! (Ne vous inquiétez pas, il y a d'autres choses à voir dans la Leçon 5 après ça 😉) -La dernière fonction, `takeOwnership`, devra simplement vérifier que `msg.sender` a été approuvé à prendre ce token / zombie, et appeler `_transfer` si c'est le cas. +La dernière fonction, `takeOwnership`, devra simplement vérifier que `msg.sender` a été approuvée pour prendre ce token / zombie, et appeler `_transfer` si c'est le cas. ## A votre tour 1. Premièrement, nous voulons utiliser une déclaration `require` pour vérifier que `zombieApprovals` pour `_tokenId` soit égal à `msg.sender`. - De cette manière, si `msg.sender` n'a pas été approuvé pour prendre le token, cela va renvoyer une erreur. + De cette manière, si `msg.sender` n'a pas été approuvée pour prendre le token, cela va renvoyer une erreur. 2. Pour pouvoir appeler `_transfer`, nous avons besoin de connaître l’adresse de la personne qui possède le token (pour l'argument `_from`). Par chance, nous pouvons retrouver ça avec notre fonction `ownerOf`. @@ -337,4 +337,4 @@ La dernière fonction, `takeOwnership`, devra simplement vérifier que `msg.send 3. Enfin, appelez `_transfer`, et passez lui tous les arguments nécessaires. (Vous pouvez ici utiliser `msg.sender` pour `_to`, vu que la personne qui appelle la fonction est celle à qui le token devra être envoyé). -> Remarque : Nous aurions pu écrire les étapes 2 et 3 en une seule ligne de code, mais c'est plus clair de séparer les choses. Préférence personnelle. +> Remarque : Nous aurions pu écrire les étapes 2 et 3 en une seule ligne de code, mais c'est plus clair de séparer les choses. Préférence personnelle. 😉 diff --git a/fr/5/09-safemath-1.md b/fr/5/09-safemath-1.md index 0ccb437eec..f91fba2c89 100644 --- a/fr/5/09-safemath-1.md +++ b/fr/5/09-safemath-1.md @@ -419,9 +419,9 @@ Pour prévenir cela, OpenZeppelin a créé une **_bibliothèque_** appelée Safe Mais d'abord, c'est quoi une bibliothèque ? -Une **_bibliothèque_** est un type de contrat spécial en Solidity. Une de leurs fonctionnalités est que cela permet de rajouter des fonctions à un type de données natif. +Une **_bibliothèque_** est un type de contrat spécial en Solidity. Une de leurs fonctionnalités est que cela permet d'ajouter des fonctions à un type de données natif. -Par exemple. avec la bibliothèque SafeMath, nous allons utiliser la syntaxe `using SafeMath for uint256`. La bibliothèque SafeMath a 4 fonctions — `add`, `sub`, `mul`, et `div`. Et maintenant nous pouvons utiliser ces fonctions à partir d'un `uint256` en faisant : +Par exemple, avec la bibliothèque SafeMath, nous allons utiliser la syntaxe `using SafeMath for uint256`. La bibliothèque SafeMath a 4 fonctions — `add`, `sub`, `mul`, et `div`. Et désormais, nous pouvons utiliser ces fonctions à partir d'un `uint256` en faisant : ``` using SafeMath for uint256; @@ -431,11 +431,11 @@ uint256 b = a.add(3); // 5 + 3 = 8 uint256 c = a.mul(2); // 5 * 2 = 10 ``` -Nous verrons ce que font ces fonctions dans le prochain chapitre, pour l'instant, nous allons ajouter la bibliothèque SafeMath à notre contrat. +Nous verrons ce que font ces fonctions dans le prochain chapitre. Pour l'instant, nous allons ajouter la bibliothèque SafeMath à notre contrat. ## A votre tour -Nous avons déjà rajouté la bibliothèque `SafeMath` d'OpenZeppelin pour vous dans `safemath.sol`. Vous pouvez regarder le code si vous voulez, mais nous allons l'étudier en détails dans le prochain chapitre. +Nous avons déjà ajouté la bibliothèque `SafeMath` d'OpenZeppelin pour vous dans `safemath.sol`. Vous pouvez regarder le code si vous voulez, mais nous allons l'étudier en détail dans le prochain chapitre. Pour l'instant, nous allons faire en sorte que notre contrat utilise SafeMath. Nous allons le faire dans ZombieFactory, notre contrat de base - de cette manière nous pourrons l'utiliser dans tous les sous-contrats qui en héritent. diff --git a/fr/5/10-safemath-2.md b/fr/5/10-safemath-2.md index 0973a1294f..baa3c06692 100644 --- a/fr/5/10-safemath-2.md +++ b/fr/5/10-safemath-2.md @@ -416,7 +416,7 @@ library SafeMath { } ``` -Tout d'abord, nous avons le mot-clé `library` (bibliothèque) - les bibliothèques sont similaires aux contrats avec quelques différences. Dans ce cas là, les bibliothèques nous permettent d'utiliser le mot-clé `using` (utiliser), qui va automatiquement rajouter toutes les méthodes de cette bibliothèque à un autre type de donnée : +Tout d'abord, nous avons le mot-clé `library` (bibliothèque) - les bibliothèques sont similaires aux contrats avec quelques différences. Dans ce cas-là, les bibliothèques nous permettent d'utiliser le mot-clé `using` (utiliser), qui va automatiquement ajouter toutes les méthodes de cette bibliothèque à un autre type de données : ``` using SafeMath for uint; @@ -440,7 +440,7 @@ function add(uint256 a, uint256 b) internal pure returns (uint256) { `add` ajoute simplement 2 `uint` comme `+`, mais elle contient aussi une déclaration `assert` (affirme) pour vérifier que la somme est plus grande que `a`. Cela nous protège d'un débordement. -`assert` est la même chose que `require`, et va renvoyer une erreur si ce n'est pas vérifié. La différence entre `assert` et `require` c'est que `require` va rembourser l'utilisateur du gas restant quand la fonction échoue, alors que `assert` non. La plupart du temps vous allez vouloir utiliser `require` dans votre code, `assert` est plutôt utilisé quand quelque chose a vraiment mal tourné avec le code (comme un débordement d'`uint`). +`assert` est la même chose que `require`, et va renvoyer une erreur si ce n'est pas vérifié. La différence entre `assert` et `require` c'est que `require` va rembourser l'utilisateur du gas restant quand la fonction échoue, alors que `assert` non. La plupart du temps, vous allez vouloir utiliser `require` dans votre code, `assert` est plutôt utilisé quand quelque chose a vraiment mal tourné avec le code (comme un débordement d'`uint`). Pour résumer, `add`, `sub`, `mul`, et `div` de SafeMath sont des fonctions qui font les 4 opérations mathématiques basiques, et qui renvoient une erreur en cas de débordement @@ -449,7 +449,7 @@ Pour résumer, `add`, `sub`, `mul`, et `div` de SafeMath sont des fonctions qui Pour prévenir les débordements, nous pouvons voir les endroits dans notre code où nous utilisons `+`, `-`, `*`, ou `/`, et les remplacer par `add`, `sub`, `mul`, `div`. -Ex. A lieu d'écrire : +Ex. Au lieu d'écrire : ``` myUint++; diff --git a/fr/5/11-safemath-3.md b/fr/5/11-safemath-3.md index 4595855939..989099edeb 100644 --- a/fr/5/11-safemath-3.md +++ b/fr/5/11-safemath-3.md @@ -496,7 +496,7 @@ Le code sera exactement le même que SafeMath, à l'exception des instances `uin Nous avons pris de l'avance et avons implémenté ce code pour vous — vous pouvez voir le code dans `safemath.sol`. -Maintenant nous devons l'implémenter dans ZombieFactory. +Nous devons désormais l'implémenter dans ZombieFactory. ## A votre tour diff --git a/fr/5/13-comments.md b/fr/5/13-comments.md index 5d6884d337..0bd5112839 100644 --- a/fr/5/13-comments.md +++ b/fr/5/13-comments.md @@ -385,30 +385,30 @@ Le code Solidity de notre jeu zombie est enfin terminé ! Dans les prochaines leçons, nous allons regarder comment déployer le code sur Ethereum, et comment interagir avec en utilisant Web3.js. -Mais il reste une dernière chose dans la Leçon 5 avant de vous laisser partir : Nous allons voir comment **commenter votre code**. +Mais il reste une dernière chose dans la leçon 5 avant de vous laisser partir : Nous allons voir comment **commenter votre code**. ## Syntaxe pour commenter -Commenter en Solidity est la même chose qu'en JavaScript. Vous avez déjà vu quelques exemples de commentaire sur une seule ligne au cours des leçons de CryptoZombies : +Commenter en Solidity est la même chose qu'en JavaScript. Vous avez déjà vu quelques exemples de commentaires sur une seule ligne au cours des leçons de CryptoZombies : ``` // Ceci est un commentaire sur une seule ligne. C'est une note pour nous-même (ou pour les autres) ``` -Il suffit d'ajouter un `//` n'importe où et vous pouvez commentez. C'est tellement simple que vous devriez le faire tout le temps. +Il suffit d'ajouter un `//` n'importe où et vous pouvez commenter. C'est tellement simple que vous devriez le faire tout le temps. Mais je sais — parfois une seule ligne n'est pas assez. Vous êtes un écrivain né, après tout ! -C'est pourquoi il existe aussi des commentaires multi-ligne : +C'est pourquoi il existe aussi des commentaires multilignes : ``` contract CryptoZombies { - /* Ceci est un commentaire multi-ligne. Je voudrais tous vous + /* Ceci est un commentaire multilignes. Je voudrais tous vous remercier d'avoir pris le temps de faire ce cours de programmation. Je sais que c'est accessible gratuitement, et ça le restera toujours, - mais nous avons quand même mis toute notre énergie pour que ce cours + mais nous avons quand même mis toute notre énergie afin que ce cours soit le meilleur possible. Nous en sommes simplement au début de la programmation sur Blockchain. @@ -424,7 +424,7 @@ contract CryptoZombies { } ``` -C'est une particulièrement bonne habitude de commenter son code pour expliquer le comportement attendu de chaque fonction de votre contrat. De cette manière, un autre développeur (ou vous, après 6 mois loin de votre projet !) peut parcourir votre code pour avoir une compréhension rapide du fonctionnement sans avoir à lire le code en détail. +C'est une bonne habitude de commenter son code pour expliquer le comportement attendu de chaque fonction de votre contrat. De cette manière, un autre développeur (ou vous-même, après 6 mois loin de votre projet !) peut parcourir votre code pour avoir une compréhension rapide du fonctionnement sans avoir à lire le code en détail. Le standard dans la communauté Solidity est d'utiliser un format appelé **_natspec_**, qui ressemble à ça : @@ -433,11 +433,11 @@ Le standard dans la communauté Solidity est d'utiliser un format appelé **_nat /// @author H4XF13LD MORRIS 💯💯😎💯💯 /// @notice Pour l'instant, ce contrat rajoute simplement une fonction multiplication contract Math { - /// @notice Multiplie 2 nombres ensemble + /// @notice Multiplie 2 nombres ensembles /// @param x le premier uint. /// @param y le deuxième uint. /// @return z le résultat de (x * y) - /// @dev Cette fonction ne vérifie pas les débordement pour l'instant + /// @dev Cette fonction ne vérifie pas les débordements pour l'instant function multiply(uint x, uint y) returns (uint z) { // C'est un commentaire normal, qui ne sera pas pris en compte par natspec z = x * y; @@ -449,9 +449,9 @@ contract Math { `@notice` explique à un **utilisateur** ce que le contrat / fonction fait. `@dev` est pour donner plus de détails aux développeurs. -`@param` et `@return` servent à décrire chaque paramètres et ce que la fonction renvoie. +`@param` et `@return` servent à décrire chaque paramètre et ce que la fonction renvoie. -Vous n'avez pas tout le temps besoin d'utiliser tous ces tags pour chaque fonction — tous les tags sont optionnels. Au minimum, laissez une note `@dev` pour expliquer ce que chaque fonction fait. +Vous n'avez pas tout le temps besoin d'utiliser tous ces tags pour chaque fonction — ils sont optionnels. Au minimum, laissez une note `@dev` pour expliquer ce que chaque fonction fait. # A votre tour diff --git a/fr/5/14-wrappingitup.md b/fr/5/14-wrappingitup.md index bdadc10185..d1bbd40033 100644 --- a/fr/5/14-wrappingitup.md +++ b/fr/5/14-wrappingitup.md @@ -12,7 +12,7 @@ material: answer: 1 --- -Félicitations ! Vous avez terminé la Leçon 5. +Félicitations ! Vous avez terminé la leçon 5. Comme récompense, nous vous avons transféré votre propre zombie de niveau 10 **H4XF13LD MORRIS 💯💯😎💯💯** ! @@ -26,10 +26,10 @@ Avant de continuer, vous avez la possibilité de renommer vos zombies en cliquan Dans cette leçon nous avons appris : -- Les tokens, le standard ERC721, et les actifs/zombies échangeables -- Les bibliothèques et comment s'en servir -- Comment empêcher les débordements en utilisant la bibliothèque SafeMath -- Commenter son code et le standard natspec +- Les tokens, le standard ERC721, et les actifs/zombies échangeables. +- Les bibliothèques et comment s'en servir. +- Comment empêcher les débordements en utilisant la bibliothèque SafeMath. +- Commenter son code et le standard natspec. Cette leçon termine le code de notre jeu Solidity ! (Pour l'instant — nous rajouterons peut-être plus de leçons). diff --git a/fr/6/00-overview.md b/fr/6/00-overview.md index b9fa8fff23..5194600b17 100644 --- a/fr/6/00-overview.md +++ b/fr/6/00-overview.md @@ -8,7 +8,7 @@ Hein, vous êtes arrivé jusqu'ici ?! Vous n'êtes pas un CryptoZombie ordinaire... -En finissant la Leçon 5, vous avez prouvé que vous avez une assez bonne compréhension de Solidity. +En finissant la leçon 5, vous avez prouvé que vous avez une assez bonne compréhension de Solidity. Mais aucune DApp n'est terminée sans un moyen pour ses utilisateurs d'interagir avec... diff --git a/fr/6/01.md b/fr/6/01.md index 9f1d27d4ab..aaaa6eb3ca 100644 --- a/fr/6/01.md +++ b/fr/6/01.md @@ -363,7 +363,7 @@ material: --- -En terminant la Leçon 5, notre DApp zombie est terminée. Maintenant, nous allons créer une page web basique où vos utilisateurs pourront interagir avec. +En terminant la leçon 5, notre DApp zombie est terminée. Maintenant, nous allons créer une page web basique où vos utilisateurs pourront interagir avec. Pour cela, nous allons utiliser une bibliothèque JavaScript de la fondation Ethereum appelée **_Web3.js_**. @@ -371,8 +371,8 @@ Pour cela, nous allons utiliser une bibliothèque JavaScript de la fondation Eth Rappelez-vous, le réseau Ethereum est fait de nœuds, dont chacun contient une copie de la blockchain. Quand vous voulez appeler une fonction d'un smart contract, vous avez besoin de faire une demande à l'un de ces nœuds en lui indiquant : - 1. L'adresse du smart contract - 2. La fonction que vous voulez appeler, et + 1. L'adresse du smart contract. + 2. La fonction que vous voulez appeler. 3. Les paramètres que vous voulez donner à la fonction. Les nœuds Ethereum parlent seulement un langage appelé **_JSON-RPC_**, qui n'est pas vraiment lisible par l'homme. Une requête pour indiquer à un nœud que vous voulez appeler une fonction d'un contrat ressemble à ça : @@ -391,7 +391,7 @@ CryptoZombies.methods.createRandomZombie("Vitalik Nakamoto 🤔") .send({ from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", gas: "3000000" }) ``` -Nous vous expliquerons la syntaxe plus en détails dans les prochains chapitres, mais pour l'instant, configurons votre projet pour utiliser Web3.js. +Nous vous expliquerons la syntaxe plus en détail dans les prochains chapitres. Mais pour l'instant, configurons votre projet pour utiliser Web3.js. ## Pour commencer diff --git a/fr/6/02.md b/fr/6/02.md index 0ff2d0fc9f..fbb2bbcc73 100644 --- a/fr/6/02.md +++ b/fr/6/02.md @@ -403,11 +403,11 @@ var web3 = new Web3(new Web3.providers.WebsocketProvider("wss://mainnet.infura.i Cependant, vu que notre DApp va avoir beaucoup d'utilisateurs - et que ces utilisateurs vont ÉCRIRE sur la blockchain et pas seulement lire - nous allons avoir besoin d'un moyen pour ces utilisateurs de signer les transactions avec leurs clés privées. -> Remarque : Ethereum (et les blockchains en général) utilise une paire de clés publique / privée pour signer numériquement les transactions. C'est un peu comme un mot de passe extrêmement compliqué pour signer numériquement. Ainsi, si je change des données sur la blockchain, je peux **prouver** grâce à la clé publique que je suis celui qui les a signées - mais puisque personne ne connaît ma clé privée, personne ne peut créer une transaction à ma place. +> Remarque : Ethereum (et les blockchains en général) utilise une paire de clés publiques / privées pour signer numériquement les transactions. C'est un peu comme un mot de passe extrêmement compliqué pour signer numériquement. Ainsi, si je change des données sur la blockchain, je peux **prouver** grâce à la clé publique que je suis celui qui les a signées - mais puisque personne ne connaît ma clé privée, personne ne peut créer de transaction à ma place. La cryptographie est compliquée, et à part si vous êtes un expert en sécurité et que vous savez vraiment ce que vous faîtes, ce ne sera sûrement pas une bonne idée de vouloir gérer les clés privées vous-même. -Heureusement, vous n'avez pas besoin - il existe déjà des services qui s'en occupent pour vous. Le plus connu est **_MetaMask_**. +Heureusement, vous n'en avez pas besoin - il existe déjà des services qui s'en occupent pour vous. Le plus connu est **_MetaMask_**. ## MetaMask @@ -444,7 +444,7 @@ window.addEventListener('load', function() { Vous pouvez utiliser ce code standard dans toutes les applications que vous créez afin de demander à l'utilisateur d'avoir MetaMask pour utiliser votre DApp. -> Remarque : Il existe d'autres gestionnaires de clés privées que vos utilisateurs pourraient utiliser, comme le navigateur web **Mist**. Cependant, ils implémentent tous la variable `web3` d'une manière similaire, la méthode que nous avons utilisé ci-dessus pour détecter le fournisseur web3 de l'utilisateur marchera aussi. +> Remarque : Il existe d'autres gestionnaires de clés privées que vos utilisateurs pourraient utiliser, comme le navigateur web **Mist**. Cependant, ils implémentent tous la variable `web3` d'une manière similaire, la méthode que nous avons utilisée ci-dessus pour détecter le fournisseur web3 de l'utilisateur fonctionnera aussi. ## A votre tour diff --git a/fr/6/03.md b/fr/6/03.md index 1bc065f530..fa2bc97b30 100644 --- a/fr/6/03.md +++ b/fr/6/03.md @@ -880,7 +880,7 @@ L'autre chose dont Web3.js a besoin pour communiquer avec votre contrat est son ABI veut dire "Application Binary Interface" (Interface Binaire d'Application). Fondamentalement, c'est une représentation des fonctions de votre contrat au format JSON qui indique à Web3.js comment formater les appels aux fonctions pour que votre contrat les comprenne. -Quand vous compilez votre contrat pour le déployer sur Ethereum (ce que nous verrons dans la Leçon 7), le compilateur Solidity vous donnera son ABI, vous aller devoir le copier et le sauvegarder en plus de l'adresse de votre contrat. +Quand vous compilez votre contrat pour le déployer sur Ethereum (ce que nous verrons dans la leçon 7), le compilateur Solidity vous donnera son ABI, vous aller devoir le copier et le sauvegarder en plus de l'adresse de votre contrat. Puisque nous n'avons pas encore vu le déploiement, pour cette leçon nous avons déjà compilé l'ABI pour vous et nous l'avons mis dans le fichier appelé `cryptozombies_abi.js`, stocké dans une variable appelée `cryptoZombiesABI`. diff --git a/fr/6/04.md b/fr/6/04.md index 170dfe2747..68b0440083 100644 --- a/fr/6/04.md +++ b/fr/6/04.md @@ -439,9 +439,9 @@ Web3.js a deux méthodes que nous allons utiliser pour appeler les fonctions de ### Call -`call` est utilisé pour les fonctions `view` et `pure`. Il est exécuté seulement sur le nœud local, et cela ne va pas créer de transaction sur la blockchain. +`call` est utilisée pour les fonctions `view` et `pure`. Elle est exécutée seulement sur le nœud local, et cela ne va pas créer de transaction sur la blockchain. -> **Rappel :** les fonctions `view` et `pure` sont des fonctions en lecture seule et ne changent pas l'état de la blockchain. Elles ne coûtent pas de gas et l'utilisateur n'aura pas besoin de signer de transaction avec MetaMask. +> **Rappel :** les fonctions `view` et `pure` sont des fonctions en lecture seule et ne changent pas l'état de la blockchain. Elles n'ont aucun coût en gas et l'utilisateur n'aura pas besoin de signer de transaction avec MetaMask. En utilisant Web3.js, vous allez appeler (`call`) une fonction nommée `myMethod` avec le paramètre `123` comme ceci : @@ -465,7 +465,7 @@ La syntaxe est quasiment identique que pour `call()`. ## Récupérer les données zombies -Maintenant nous allons voir un vrai exemple de la fonction `call` pour accéder aux données de notre contrat. +Maintenant, nous allons voir un vrai exemple de la fonction `call` pour accéder aux données de notre contrat. Rappelez-vous que nous avions rendu notre tableau de zombies `public` : @@ -477,7 +477,7 @@ En Solidity, quand vous déclarez une variable `public`, cela crée automatiquem Voici comment nous écririons notre fonction JavaScript de notre front-end qui récupérerait un id zombie, interrogerait notre contrat pour ce zombie, et renverrait le résultat : -> Remarque : Tous les exemples de code que nous utilisons dans cette leçon utilisent la **version 1.0** de Web3.js, qui utilise les promesses au lieu des callbacks. Beaucoup de tutoriels que vous allez voir en ligne utilisent une ancienne version de Web3.js. La syntaxe a beaucoup changé avec la version 1.0, si vous copiez du code d'autres tutoriels, assurez-vous qu'ils utilisent la même version que vous ! +> Remarque : Tous les exemples de code que nous utilisons dans cette leçon utilisent la **version 1.0** de Web3.js, qui utilise les promesses au lieu des callbacks. Beaucoup de tutoriels que vous allez voir en ligne utilisent une ancienne version de Web3.js. La syntaxe a beaucoup changé avec la version 1.0 ; si vous copiez du code d'autres tutoriels, assurez-vous qu'ils utilisent la même version que vous ! ``` function getZombieDetails(id) { diff --git a/fr/6/05.md b/fr/6/05.md index e7abd33f33..6cdf3e77a7 100644 --- a/fr/6/05.md +++ b/fr/6/05.md @@ -453,9 +453,9 @@ material: Génial ! Vous avez réussi à écrire du code front-end pour interagir avec votre premier smart contract. -Maintenant essayons de mettre en place quelque chose - disons que nous voulons que la page d'accueil de notre application montre toute l'armée de zombie d'un utilisateur. +Essayons maintenant de mettre en place quelque chose - disons que nous voulons que la page d'accueil de notre application montre toute l'armée de zombie d'un utilisateur. -Évidemment nous allons d'abord devoir utiliser notre fonction `getZombiesByOwner(owner)` pour récupérer tous les IDs des zombies que l'utilisateur possède. +Évidemment, nous allons d'abord devoir utiliser notre fonction `getZombiesByOwner(owner)` pour récupérer tous les IDs des zombies que l'utilisateur possède. Mais notre contrat Solidity s'attend à ce que `owner` soit une `address` Solidity. Comment connaître l'adresse de l'utilisateur de notre application ? @@ -469,7 +469,7 @@ Nous pouvons connaître le compte actif via la variable injectée `web3` : var userAccount = web3.eth.accounts[0] ``` -Puisque l’utilisateur peut changer de compte actif n'importe quand avec MetaMask, notre application a besoin de surveiller cette variable pour voir si elle change et mettre à jour l'interface en conséquence. Par exemple, si la page d'accueil montre l'armée de zombie d'un utilisateur, quand il change de compte dans MetaMask, nous allons vouloir mettre à jour la page pour montrer l'armée de zombie du nouveau compte sélectionné. +Puisque l’utilisateur peut changer de compte actif n'importe quand avec MetaMask, notre application a besoin de surveiller cette variable pour voir si elle change, et de mettre à jour l'interface en conséquence. Par exemple, si la page d'accueil montre l'armée de zombies d'un utilisateur, quand il change de compte dans MetaMask, nous allons vouloir mettre à jour la page pour montrer l'armée de zombies du nouveau compte ainsi sélectionné. Nous pouvons faire ça avec une boucle `setInterval` comme ceci : @@ -488,13 +488,13 @@ Ce code vérifie toutes les 100 millisecondes que `userAccount` est toujours ég ## A votre tour -Faisons en sorte que notre application montre l'armée de zombie de notre utilisateur au chargement initial de la page, et surveille le compte MetaMask actif pour mettre à jour l'interface s'il change. +Faisons en sorte que notre application montre l'armée de zombies de notre utilisateur au chargement initial de la page, et surveille le compte MetaMask actif pour mettre à jour l'interface s'il change. -1. Déclarez une `var` appelée `userAccount`, mais ne lui attribuez pas de valeur +1. Déclarez une `var` appelée `userAccount`, mais ne lui attribuez pas de valeur. -2. À la fin de `startApp()`, copiez/collez le code standard `accountInterval` ci-dessus +2. À la fin de `startApp()`, copiez/collez le code standard `accountInterval` ci-dessus. -3. Remplacez la ligne `updateInterface();` avec un appel à `getZombiesByOwner`, avec comme paramètre `userAccount` +3. Remplacez la ligne `updateInterface();` avec un appel à `getZombiesByOwner`, avec comme paramètre `userAccount`. 4. Mettez à la chaîne une déclaration `then` après `getZombiesByOwner` et passez le résultat à une fonction appelée `displayZombies`. (La syntaxe est : `.then(displayZombies);`). diff --git a/fr/6/06.md b/fr/6/06.md index 74db1faeaf..3280f56cff 100644 --- a/fr/6/06.md +++ b/fr/6/06.md @@ -503,15 +503,15 @@ Rappelez-vous du précédent chapitre, nous avons appelé `displayZombies` à l' [0, 13, 47] ``` -Donc nous voulons que notre fonction `displayZombies` ait le comportement suivant : +Nous voulons donc que notre fonction `displayZombies` ait le comportement suivant : -1. Premièrement, supprimez le contenu de la div `#zombies` s'il y a quelque chose à l'intérieur. (De cette manière, si l'utilisateur change de compte actif dans MetaMask, cela supprimera l'ancienne armée de zombie avant de charger la nouvelle). +1. Premièrement, supprimez le contenu de la div `#zombies` s'il y a quelque chose à l'intérieur. (De cette manière, si l'utilisateur change de compte actif dans MetaMask, cela supprimera l'ancienne armée de zombies avant de charger la nouvelle). -2. Itérez pour chaque `id`, et pour chaque appel `getZombieDetails(id)` afin de récupérer toutes les informations de ce zombie à partir de notre smart contract. Ensuite +2. Itérez pour chaque `id` et pour chaque appel `getZombieDetails(id)`, afin de récupérer toutes les informations de ce zombie à partir de notre smart contract. 3. Mettez ces informations dans un template HTML pour qu'elles soient correctement formatées pour l'affichage, et ajoutez-les à la div `#zombies`. -Pour rappel, nous utilisons simplement du JQuery ici, qui n'a pas de template par défaut, le résultat ne sera pas beau. Voici un exemple simple de comment nous pourrions afficher les données pour chaque zombie : +Pour rappel, nous utilisons simplement du JQuery ici, qui n'a pas de template par défaut. Le résultat ne sera pas beau. Voici un exemple simple de comment nous pourrions afficher les données pour chaque zombie : ``` // On récupère les informations des zombies à partir de notre contrat. On renvoie un objet `zombie` @@ -536,7 +536,7 @@ getZombieDetails(id) Dans l'exemple ci-dessus, nous affichons simplement l'ADN comme une chaîne de caractères. Mais dans votre DApp, vous allez vouloir convertir cela en images pour afficher votre zombie. -Nous avons fait cela en divisant l'ADN en plusieurs chaînes de caractères, et en ayant chaque paire de chiffres qui correspond à une image. De cette manière là : +Nous avons fait cela en divisant l'ADN en plusieurs chaînes de caractères, et en ayant chaque paire de chiffres correspondant à une image. De cette manière : ``` // On obtient un entier entre 1 et 7 qui représente la tête de notre zombie : @@ -550,7 +550,7 @@ Chaque composant est positionné avec du CSS en utilisant le positionnement abso Si vous voulez voir exactement comment nous l'avons implémenté, nous avons rendu Open Source le code de notre composant Vue.js utilisé pour l'apparence des zombies, vous pouvez le voir ici. -Cependant, puisqu'il y a beaucoup de code dans ce fichier, c'est en dehors du cadre de ce tutoriel. Pour cette leçon, nous garderons l'exemple basique de l'implémentation JQuery ci-dessus, et nous vous laissons l'opportunité de faire une implémentation plus belle comme entraînement 😉 +Cependant, puisqu'il y a beaucoup de code dans ce fichier, c'est en dehors du cadre de ce tutoriel. Pour cette leçon, nous garderons l'exemple basique de l'implémentation JQuery ci-dessus, et nous vous laissons l'opportunité de faire une implémentation plus belle comme entraînement. 😉 ## A votre tour diff --git a/fr/6/07.md b/fr/6/07.md index 7d069186ec..e75c438fb5 100644 --- a/fr/6/07.md +++ b/fr/6/07.md @@ -547,15 +547,15 @@ material: Génial ! Maintenant notre interface va détecter le compte MetaMask de l'utilisateur, et va automatiquement afficher son armée de zombie sur la page d'accueil. -Maintenant nous allons voir comment changer les données de notre smart contract avec les fonctions `send`. +Maintenant, nous allons voir comment changer les données de notre smart contract avec les fonctions `send`. Il y a quelques différences majeures avec les fonctions `call` : 1. Envoyer une transaction avec `send` nécessite une adresse `from` de celui qui appelle la fonction (qui devient `msg.sender` dans votre code Solidity). Nous allons vouloir que ce soit l'utilisateur de notre DApp, afin que MetaMask affiche une fenêtre pour lui demander de signer la transaction. -2. Envoyer avec `send` une transaction coûte du gas. +2. Envoyer avec `send` une transaction a un coût en gas. -3. Il y a un certain délais entre le moment où l'utilisateur envoie une transaction avec `send` et le moment où cette transaction prend effet sur la blockchain. C'est parce qu'il faut attendre que la transaction soit incluse dans un bloc, et un bloc est créé toutes les 15 sec environ avec Ethereum. S'il y a beaucoup de transactions en attente, ou si l'utilisateur paye un prix de gas trop bas, notre transaction pourrait attendre plusieurs blocs avant d'être incluse, et cela pourrait prendre plusieurs minutes. +3. Il y a un certain délai entre le moment où l'utilisateur envoie une transaction avec `send` et le moment où cette transaction prend effet sur la blockchain. C'est parce qu'il faut attendre que la transaction soit incluse dans un bloc, et un bloc est créé toutes les 15 secondes environ avec Ethereum. S'il y a beaucoup de transactions en attente, ou si l'utilisateur paye un montant insuffisant en gas, notre transaction pourrait attendre plusieurs blocs avant d'être incluse, et cela pourrait prendre plusieurs minutes. C'est pour ça que nous avons besoin que notre application gère la nature asynchrone de ce code. @@ -611,14 +611,14 @@ Nous avons ajouté un `div` avec l'ID `txStatus` - de cette manière, nous pouvo 2. Nous allons implémenter une autre fonction : `feedOnKitty`. - La logique pour appeler `feedOnKitty` est pratiquement la même - nous allons envoyer une transaction qui appelle la fonction, si la transaction réussie, un nouveau zombie sera créé, et nous aurons donc besoin de rafraîchir l'interface juste après. + La logique pour appeler `feedOnKitty` est pratiquement la même - nous allons envoyer une transaction qui appelle la fonction ; si la transaction réussie, un nouveau zombie sera créé, et nous aurons donc besoin de rafraîchir l'interface juste après. Faites une copie de `createRandomZombie` juste en dessous, avec les changements suivants : - a) Appelez la 2ème fonction `feedOnKitty`, avec 2 paramètres : `zombieId` et `kittyId` + a) Appelez la 2ème fonction `feedOnKitty`, avec 2 paramètres : `zombieId` et `kittyId`. - b) Le texte de `#txStatus` devra être : `"En train de manger un chaton, cela peut prendre du temps..."` + b) Le texte de `#txStatus` devra être : `"En train de manger un chaton, cela peut prendre du temps..."`. - c) Faites que ça appelle `feedOnKitty` de notre contrat, et passez lui les 2 mêmes paramètres + c) Faites que ça appelle `feedOnKitty` de notre contrat, et passez-lui les 2 mêmes paramètres. - d) Le message de réussite de `#txStatus` devra être : `"A mangé un chaton et a engendré un nouveau Zombie !"` + d) Le message de réussite de `#txStatus` devra être : `"A mangé un chaton et a engendré un nouveau Zombie !"`. diff --git a/fr/6/08.md b/fr/6/08.md index 12ecb4ae6a..1731128071 100644 --- a/fr/6/08.md +++ b/fr/6/08.md @@ -614,7 +614,7 @@ Cela fait beaucoup de zéros à compter - Heureusement, Web3.js a un outil de co web3js.utils.toWei("1", "ether"); ``` -Dans notre DApp, nous avons défini `levelUpFee = 0.001 ether`, ainsi quand nous appelons notre fonction `levelUp`, l'utilisateur devra s'assurer qu'il envoie `0.001` Ether avec le code suivant : +Dans notre DApp, nous avons défini `levelUpFee = 0.001 ether`. Ainsi, quand nous appelons notre fonction `levelUp`, l'utilisateur devra s'assurer qu'il envoie `0.001` Ether avec le code suivant : ``` cryptoZombies.methods.levelUp(zombieId) @@ -625,12 +625,12 @@ cryptoZombies.methods.levelUp(zombieId) Nous allons ajouter une fonction `levelUp` en dessous de `feedOnKitty`. Le code sera vraiment similaire à `feedOnKitty`, mais : -1. La fonction prendra un seul paramètre, `zombieId` +1. La fonction prendra un seul paramètre, `zombieId`. -2. Avant la transaction, le texte de `txStatus` devra être : `"Votre zombie est en train de gagner un niveau..."` +2. Avant la transaction, le texte de `txStatus` devra être : `"Votre zombie est en train de gagner un niveau..."`. -3. Quand `levelUp` est appelé, `"0.001"` ETH converti avec `toWei` devra être envoyé, comme dans l'exemple ci-dessus +3. Quand `levelUp` est appelé, `"0.001"` ETH converti avec `toWei` devra être envoyé, comme dans l'exemple ci-dessus. -4. Si cela réussit, le texte devra afficher `"Quelle puissance écrasante ! Le zombie a bien gagné un niveau"` +4. Si cela réussit, le texte devra afficher `"Quelle puissance écrasante ! Le zombie a bien gagné un niveau"`. -5. Nous **n'avons pas** besoin de rafraîchir l'interface en appelant notre smart contract avec `getZombiesByOwner` — car dans ce cas là, la seule chose qui a changé c'est le niveau du zombie. +5. Nous **n'avons pas** besoin de rafraîchir l'interface en appelant notre smart contract avec `getZombiesByOwner` — car dans ce cas-là, la seule chose qui a changé c'est le niveau du zombie. diff --git a/fr/6/09.md b/fr/6/09.md index a1712baade..a9a284dcdb 100644 --- a/fr/6/09.md +++ b/fr/6/09.md @@ -601,13 +601,13 @@ material: --- -Comme vous pouvez le voir, c'est plutôt simple d'interagir avec votre contrat via Web3.js - une fois que vous avez votre environnement configuré, appeler des fonctions et envoyer des transactions n'est pas vraiment différent d'avec une API web classique. +Comme vous pouvez le voir, c'est plutôt simple d'interagir avec votre contrat via Web3.js - une fois que vous avez votre environnement configuré, appeler des fonctions et envoyer des transactions n'est pas vraiment différent qu'avec une API web classique. Il y a encore un aspect que nous voulons couvrir - s'abonner à des évènements de votre contrat. ## Écouter pour de nouveaux zombies -Si vous vous rapplez de `zombiefactory.sol`, nous avions un évènement appelé `NewZombie` qui était émis chaque fois qu'un nouveau zombie était créé : +Si vous vous rappelez de `zombiefactory.sol`, nous avions un évènement appelé `NewZombie` qui était émis chaque fois qu'un nouveau zombie était créé : ``` event NewZombie(uint zombieId, string name, uint dna); @@ -664,7 +664,7 @@ Puisque vous pouvez utiliser cette méthode pour récupérer tous les évènemen Si vous vous rappelez, enregistrer des données sur la blockchain est une des opérations les plus chères en Solidity. Utiliser des évènements est beaucoup moins cher en terme de gas. -En contrepartie, les évènements ne sont pas lisibles depuis le smart contract. Mais c'est un cas d'utilisation important à retenir si vous voulez stocker de l'information avec un historique sur la blockchain afin de le lire depuis le front-end de votre application. +En contrepartie, les évènements ne sont pas lisibles depuis le smart contract. Mais c'est un cas d'utilisation important à retenir si vous voulez stocker de l'information avec un historique sur la blockchain, afin de le lire depuis le front-end de votre application. Par exemple, nous pourrions l'utiliser pour avoir un historique de nos combats de zombies - nous pourrions créer un évènement à chaque fois qu'un zombie attaque et gagne. Le smart contract n'a pas besoin de cette information pour calculer quoi que ce soit, mais cela pourrait être une information utile pour le front-end de notre application. diff --git a/fr/6/10-wrappingitup.md b/fr/6/10-wrappingitup.md index 2252ceef45..fb22191d29 100644 --- a/fr/6/10-wrappingitup.md +++ b/fr/6/10-wrappingitup.md @@ -19,7 +19,7 @@ Comme récompense, vous obtenez votre propre zombie `The Phantom of Web3` de niv Cette leçon était volontairement basique. Nous voulions vous montrer la logique de base dont vous auriez besoin pour interagir avec votre smart contract, mais nous ne voulions pas prendre trop de temps en faisant une implémentation complète car la portion Web3.js est plutôt répétitive, et nous n'aurions pas introduit de nouveaux concepts en faisant cette leçon plus longue. -L'implémentation est donc minimale. Voici une liste d'idées de choses que l'on voudrait rajouter pour faire de notre front-end une implémentation complète pour notre jeu de zombie, si vous voulez construire votre propre jeu par vous-mêmes : +L'implémentation est donc minimale. Voici une liste d'idées de choses que l'on voudrait rajouter pour faire de notre front-end une implémentation complète pour notre jeu de zombie, si vous voulez construire votre propre jeu par vous-même : 1. Implémenter des fonctions pour `attack`, `changeName`, `changeDna`, et les fonctions ERC721 `transfer`, `ownerOf`, `balanceOf`, etc. L'implémentation de ces fonctions sera identique aux autres transactions `send` que nous avons vu. @@ -27,13 +27,13 @@ L'implémentation est donc minimale. Voici une liste d'idées de choses que l'on 3. Il y a plusieurs vues dans notre application que nous voudrions implémenter : - a. Une page zombie individuelle, où l'on peut voir les infos d'un zombie en particulier avec un lien permanent associé. Cette page devra afficher l'apparence du zombie, son nom, son propriétaire (avec un lien vers le profil de l'utilisateur), son compteur victoires/défaites, son historique de combats, etc. + a. Une page zombie individuelle, où l'on peut voir les infos d'un zombie en particulier avec un lien permanent associé. Cette page devra afficher l'apparence du zombie, son nom, son propriétaire (avec un lien vers le profil de l'utilisateur), son compteur de victoires/défaites, son historique de combats, etc. b. Une page utilisateur, où l'on peut voir l'armée de zombie d'un utilisateur avec un lien permanent. On doit pouvoir cliquer sur un zombie pour voir sa page, et aussi cliquer sur un zombie pour l'attaquer si on est connecté avec MetaMask et qu'on a une armée. c. Une page d'accueil, qui est une variation de la page utilisateur qui montre l'armée de zombie de l'utilisateur actuel. (C'est la page que nous avons commencé avec index.html). -4. Des fonctions dans l'interface, qui permettent à l'utilisateur de se nourrir de CryptoKitties. Il pourrait y avoir un bouton sur chaque zombie de la page d'accueil qui dit "Nourris moi", puis un champ de texte qui demande à l'utilisateur l'ID du chaton (ou l'URL de ce chaton, ex : https://www.cryptokitties.co/kitty/578397). Cela déclencherait la fonction `feedOnKitty`. +4. Des fonctions dans l'interface, qui permettent à l'utilisateur de se nourrir de CryptoKitties. Il pourrait y avoir un bouton sur chaque zombie de la page d'accueil qui dit "Nourris-moi", puis un champ de texte qui demande à l'utilisateur l'ID du chaton (ou l'URL de ce chaton, ex : https://www.cryptokitties.co/kitty/578397). Cela déclencherait la fonction `feedOnKitty`. 5. Une fonction dans l'interface pour que l'utilisateur puisse attaquer le zombie d'un autre utilisateur. @@ -41,7 +41,7 @@ L'implémentation est donc minimale. Voici une liste d'idées de choses que l'on La page d'accueil utilisateur pourrait aussi avoir un bouton pour chaque zombie "Attaquer un autre zombie". Une fois cliqué, cela pourrait afficher une modale avec un champ de recherche pour entrer l'ID d'un zombie. Une option pourrait dire "Attaquer un zombie aléatoire", qui rechercherait un nombre aléatoire. - Il faudrait aussi griser les zombies de l'utilisateur dont la période d'attente n'est pas encore passée, afin que l'interface indique à l'utilisateur qu'il ne peut pas attaquer avec ce zombie, et combien de temps il doit attendre. + Il faudrait aussi griser les zombies de l'utilisateur dont le temps de recharge n'est pas encore écoulé, afin que l'interface indique à l'utilisateur qu'il ne peut pas attaquer avec ce zombie, et combien de temps il doit attendre. 6. La page d'accueil utilisateur pourrait aussi avoir comme options pour chaque zombie de changer son nom, changer son ADN et gagner un niveau (avec un frais). Les options seraient grisées si l'utilisateur n'a pas encore le bon niveau. @@ -55,15 +55,15 @@ L'implémentation est donc minimale. Voici une liste d'idées de choses que l'on C'est juste un début - Je suis sûr que vous avez encore pleins d'idées pour l'améliorer - et c'est déjà une bonne liste. -Puisqu'il y a beaucoup de code front-end dont nous aurions besoin pour créer une interface comme celle-là (HTML, CSS, JavaScript et un framework comme React ou Vue.js), construire tout cela serait sûrement un cours à part avec une dizaine leçons. Nous vous laissons donc le soin de l'implémenter vous-mêmes. +Puisqu'il y a beaucoup de code front-end dont nous aurions besoin pour créer une interface comme celle-là (HTML, CSS, JavaScript et un framework comme React ou Vue.js), construire tout cela serait sûrement un cours à part avec une dizaine de leçons. Nous vous laissons donc le soin de l'implémenter vous-même. > Remarque : Même si notre smart contract est décentralisé, cette interface pour interagir avec notre DApp est complètement centralisée sur un serveur quelque part. > -> Cependant, avec le SDK que nous sommes en train de développer à href="https://medium.com/loom-network/loom-network-is-live-scalable-ethereum-dapps-coming-soon-to-a-dappchain-near-you-29d26da00880" target=_blank>Loom Network, bientôt vous pourrez avoir des front-end comme celui-ci sur leur propre DAppChain au lieu d'un serveur centralisé. De cette manière, entre Ethereum et la DAppChain de Loom, l'ensemble de votre application sera à 100% sur la blockchain. +> Cependant, avec le SDK que nous sommes en train de développer à href="https://medium.com/loom-network/loom-network-is-live-scalable-ethereum-dapps-coming-soon-to-a-dappchain-near-you-29d26da00880" target=_blank>Loom Network, bientôt, vous pourrez avoir des front-end comme celui-ci sur leur propre DAppChain au lieu d'un serveur centralisé. De cette manière, entre Ethereum et la DAppChain de Loom, l'ensemble de votre application sera à 100% sur la blockchain. ## Conclusion -Cela termine la Leçon 6. Vous avez maintenant les compétences nécessaires pour coder un smart contrat et une application front-end pour que vos utilisateurs interagissent avec ! +Cela termine la leçon 6. Vous avez maintenant les compétences nécessaires pour coder un smart contrat et une application front-end pour que vos utilisateurs interagissent avec ! Dans la prochaine leçon, nous allons voir la pièce manquante du puzzle - déployer votre smart contract sur Ethereum.