Maintenant que nous avons installé notre environnement de développement, nous allons créer notre premier contrat intelligent, sur des contrats intelligents français.
L’application décentralisée (DAP) que nous réaliserons consistera en un module de gestion des adoptions animales.
Le contexte: une ferme compte 16 refuges pour chiens à adopter. Pour assurer un suivi efficace, nous créons une application qui permet à une personne de l’adopter pour l’associer à chaque animal. (c’est un peu plus intéressant qu’un simple Hello World, et pas plus compliqué)
Nous allons donc créer le contrat intelligent, le compiler, le distribuer sur la blockchain puis créer l’interface web avec laquelle interagir, ce qui nous permet d’avoir un aperçu d’une dApp, de sa création à son utilisation réelle. .
Solicity, le langage de développement de la blockchain Ethereum
Il est possible d’utiliser plusieurs langages pour développer des contrats intelligents, le plus connu et le plus utilisé que nous utiliserons dans ce tutoriel est Solidity, dont la syntaxe est assez proche de javascript. Vous verrez qu’un contrat intelligent ressemble vraiment à une « grande classe », et ce langage est statique.
Une fois créé, le code sera compilé en Bytecode qui sera exécuté par EVM (Ethereum Virtual Machine).
Pour info, mais cela ne se développera pas ici, il est également possible d’utiliser les langages serpent, LLL et Mutan pour développer des contrats intelligents. Enfin, il existe un langage pour Ethereum, qui est très expérimental en ce moment et très similaire à Python appelé Vyper. Il n’est pas recommandé d’essayer de l’utiliser pour le moment ou par curiosité tout en étant conscient qu’il est en phase de recherche.
– Commencez par créer un répertoire qui héberge notre projet, appelez « pet-shop-tutorial », juste à la racine de C:, il sera alors disponible ici: C: pet-shop-tutorial
Ouvrez ensuite une invite de commande (tapez CMD dans le champ de recherche de Windows 10), puis accédez au répertoire que nous venons de créer en tapant:
cd C:pet-shop-tutorial
Nous allons maintenant installer Truffle, qui se veut le couteau de l’armée suisse dans le développement Ethereum, c’est en fait un framework qui fait gagner beaucoup de temps lors de la compilation et de la distribution de notre application, il permet également de créer des tests automatisés pour nos contrats intelligents (nous utiliserons cette fonctionnalité plus tard). De plus, ils ont de bonnes idées chez Truffle pour fournir des «boîtes à truffes», qui contiennent des modules et des bibliothèques pour les contrats intelligents ou pour gérer le frontend. Ce tutoriel est également une adaptation gratuite du (disponible en anglais) disponible ici. Nous aborderons donc l’ensemble du développement Ethereum sous l’angle de l’application Web.
Commençons donc par installer Truffle avec la commande suivante:
npm install -g truffle
Si vous recevez un message d’erreur, vous n’avez probablement pas installé l’environnement de développement illustré ici.
Pour vérifier que tout est installé correctement, vous pouvez taper:
truffle version
Si tout s’est bien passé, vous devriez voir ceci:
Nous allons maintenant installer la boîte à truffes avec tous les outils nécessaires en écrivant ceci:
truffle unbox pet-shop
Et vous verrez alors:
C:pet-shop-tutorial truffle unbox pet-shop Downloading... Unpacking... Setting up... Unbox successful. Sweet! Commands: Compile: truffle compile Migrate: truffle migrate Test contracts: truffle test Run dev server: npm run dev C:pet-shop-tutorial
Nous allons donc commencer à rédiger notre contrat intelligent. Accédez au répertoire « contrat » que vous venez de créer à l’étape précédente. C’est dans ce répertoire que les fichiers .sol, qui sont les fichiers en langage d’équité, doivent être inclus.
Comment créer un nouveau fichier Adoption.sol puis l’ouvrir avec votre éditeur préféré pour inclure ceci:
pragma solidity ^0.4.17; contract Adoption
La première ligne indique au compilateur la plus petite version à utiliser. Ensuite, nous déclarons notre contrat.
Il faut ensuite commencer par déclarer nos variables (rappelez-vous que la solidité est statique), nous commençons par une variable spécifique à ce langage de type ‘adresse’, c’est en fait une adresse Ethereum de 20 octets. Tous les comptes et contrats intelligents ont une adresse dans ce format, qui peut être utilisée pour recevoir et envoyer ETHER (la devise de cette blockchain). Ajoutez cette ligne au contrat:
address[16] public adopters;
Dans la structure d’un contrat, vous devez créer les fonctions spécifiques au fonctionnement du contrat une fois que vous l’avez déclaré et ses variables. Le premier sera d’adopter un chien:
// Adopter un animal function adopt(uint petId) public returns (uint) require(petId >= 0 && petId <= 15); adopters[petId] = msg.sender; return petId;
Dans la solidité, il est toujours important de spécifier le type de variable que la fonction accepte et qu'elle retourne. Ici, notre fonction prend une identification animale. Nous contrôlons grâce à la structure de contrôle "nécessite" que l'animal fasse partie de la liste des identifiants possibles, qui se souviennent ici n'a que 16 valeurs possibles (correspondant aux 16 enclos de notre élevage), soit 0 à 15 (notre site web est responsable de la déclaration des identifiants qui correspond aux animaux).
Enfin, nous déclarons le nouveau propriétaire de l'animal avec msg.sender, qui récupère l'adresse éther de la fonction appelée. L'animal est retourné comme confirmation.
Nous voulons également pouvoir télécharger la liste de tous ceux qui ont adopté un animal, ce que nous ferons avec cette fonctionnalité:
// La liste des propriétaires function getAdopters() public view returns (address[16]) return adopters;
On note ici l'utilisation de 'view' qui signifie que la fonction ne peut pas modifier l'état de la variable, et que rien ne sera changé par cette fonction dans la blockchain.
Maintenant que notre contrat est terminé, il devrait ressembler à ceci:
pragma solidity ^0.4.17; contract Adoption address[16] public adopters; function adopt(uint petId) public returns (uint) require(petId >= 0 && petId <= 15); adopters[petId] = msg.sender; return petId; function getAdopters() public view returns (address[16]) return adopters;
Solidity est un langage compilé, nous devons donc compiler notre contrat afin qu'il puisse être utilisé sur Ethereum Virtual Machine (EVM).
C'est là que les truffes deviennent incroyables car elles transforment des étapes d'assemblage longues et fastidieuses en une ligne de commande à exécuter à partir du répertoire: "C: pet-shop-tutorial".
La commande à exécuter:
truffle.cmd compile
Si vous n'êtes pas dans Windows, utilisez simplement 'truffle' au lieu de 'truffle.cmd'
C:pet-shop-tutorial>truffle.cmd compile Compiling .contractsAdoption.sol... Compiling .contractsMigrations.sol...
Vous pouvez voir certains avertissements sur Migrations.sol que vous pouvez ignorer.
Cette étape a créé 2 fichiers JSON dans le répertoire "build / contract" qui contient les codes d'échange de nos contrats.
Maintenant que nous avons compilé notre premier contrat, il est temps de le distribuer à la blockchain, ce que nous ferons avec un script de migration, qui sont en fait des fichiers javascript pour distribuer le code de solvabilité. (Ici aussi, les truffes sont essentielles pour gagner du temps. Vous pouvez voir dans le répertoire "migration" que notre boîte à truffes a déjà créé le script de migration pour Migrations.sol.
Nous allons donc créer un fichier dans ce répertoire de migration un autre fichier '2_deploy_contracts.js' avec le contenu suivant:
var Adoption = artifacts.require("Adoption"); module.exports = function(deployer) deployer.deploy(Adoption); ;
Nous sommes prêts à distribuer notre contrat, nous devons d'abord lancer notre blockchain locale, appelée Ganache, que nous avons téléchargée à l'étape précédente. Cliquez ensuite sur l'icône de ganache pour voir cette fenêtre:
Ganache nous permet d'avoir des dizaines de comptes Ethereum avec 100 Ether chacun, permettant un test facile, l'avantage est également d'avoir des journaux détaillés de tout ce qui se passe dans la blockchain, donc un outil important dans le développement de toutes les dApps.
truffle.cmd migrate
(comme précédemment, utilisez truffle au lieu de truffle.cmd si vous n'êtes pas sous Windows)
Si tout se passe bien, vous devriez voir ceci:
C:pet-shop-tutorial> truffle.cmd migrate Using network 'development'. Running migration: 1_initial_migration.js Deploying Migrations... ... 0x08a422b62d9bab9af9ffc5e5890dc7ce3fc56f8f3fd036ebfa4755ad21a4ab6a Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0 Saving successful migration to network... ... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956 Saving artifacts... Running migration: 2_deploy_contracts.js Deploying Adoption... ... 0xb34665e299ac7179dd527378f6d44c6cfd6a884dca9fa22bb318a4e42d878951 Adoption: 0x345ca3e014aaf5dca488057592ee47305d9b3e10 Saving successful migration to network... ... 0xf36163615f41ef7ed8f4a8f192149a0bf633fe1a2398ce001bf44c43dc7bdda0 Saving artifacts... C:pet-shop-tutorial>
Nous voyons donc que notre contrat intelligent a été distribué sur notre blockchain locale, cela vient du fichier truffle.js à la racine de notre projet qui contient par défaut l'adresse de la blockchain locale pour l'environnement de développement. La puissance des truffes réside également dans la possibilité de configurer plusieurs environnements dans le même projet, il suffit de les ajouter au fichier truffle.js.
Sur la page Ganache, nous pouvons voir que "le bloc actuel" est passé de 0 à 4, et que le nombre d'ETH pour le premier compte a légèrement diminué. Il ne faut pas trop s'inquiéter pour le moment, Ganache gère le block mining seul (quand il est seulement utile) et l'utilisation d'Ethers.
PROCÉDURE D'ESSAI DE CONTRAT INTELLIGENT
Nous allons maintenant voir comment Truffle nous permet d'interagir et de tester nos contrats intelligents.
Créez d'abord un fichier TestAdoption.sol dans le répertoire "test" de notre application et ajoutez le code suivant:
pragma solidity ^0.4.17; import "truffle/Assert.sol"; import "truffle/DeployedAddresses.sol"; import "../contracts/Adoption.sol"; contract TestAdoption Adoption adoption = Adoption(DeployedAddresses.Adoption());
Actualité importante ici, la commande "import" nous permet d'utiliser d'autres fichiers de solvabilité et donc d'interagir avec d'autres contrats. Truffle nous propose spécialement Assert.sol qui vous permet de tester des équations, des inégalités, si quelque chose est vide etc.
Concernant DeployedAddresses.sol, il crée simplement une nouvelle instance de contrat dans la blockchain pour notre test et récupère l'adresse. Enfin, nous importons le contrat Adoption.sol sur lequel les tests auront lieu.
Test fonctionnel d'adoption
Lorsque nous avons créé notre fonction d'adoption, nous lui avons demandé de nous retourner l'ID pour vérifier qu'elle fonctionnait bien. Nous allons donc tester la fonction et spécifier un ID 'hard' (entre 0 et 15) et vérifier que l'ID retourné est le même avec la méthode 'Assert.equal'.
Créons donc cette nouvelle fonctionnalité:
function testUserCanAdoptPet() public uint returnedId = adoption.adopt(8); uint expected = 8; Assert.equal(returnedId, expected, "L'animal 8 a bien été adopté.");
Test variable d'adopteur
Nous vérifierons également que l'adresse du propriétaire du chien 8 est la même que celle qui a exécuté le contrat en utilisant le mot-clé "this", voici la fonction:
function testGetAdopterAddressByPetId() public // Expected owner is this contract address expected = this; address adopter = adoption.adopters(8); Assert.equal(adopter, expected, "Adresse Ethereum du propriétaire du chien numéro 8.");
Test de la liste des propriétaires
La dernière fonctionnalité que nous avons créée dans notre contrat, la possibilité de récupérer la liste de tous les propriétaires, nous la testerons également:
function testGetAdopterAddressByPetIdInArray() public address expected = this; address[16] memory adopters = adoption.getAdopters(); Assert.equal(adopters[8], expected, "Adresse Ethereum du propriétaire du chien numéro 8.");
Vous pouvez voir ici que nous utilisons un type "mémoire" pour stocker la liste des propriétaires, qui dit à Solidity de la garder en mémoire plutôt que de la stocker dans le contrat.
Pour rappel et vérification, j'ai mis l'intégralité du contenu du fichier TestAdoption.sol:
pragma solidity ^0.4.17; import "truffle/Assert.sol"; import "truffle/DeployedAddresses.sol"; import "../contracts/Adoption.sol"; contract TestAdoption Adoption adoption = Adoption(DeployedAddresses.Adoption()); function testUserCanAdoptPet() public uint returnedId = adoption.adopt(8); uint expected = 8; Assert.equal(returnedId, expected, "Adoption of pet ID 8 should be recorded."); function testGetAdopterAddressByPetId() public // Expected owner is this contract address expected = this; address adopter = adoption.adopters(8); Assert.equal(adopter, expected, "Adresse Ethereum du propriétaire du chien numéro 8."); function testGetAdopterAddressByPetIdInArray() public address expected = this; address[16] memory adopters = adoption.getAdopters(); Assert.equal(adopters[8], expected, "Adresse Ethereum du propriétaire du chien numéro 8.");
Il suffit de commencer notre test:
truffle.cmd test
Si tout s'est bien passé, vous devriez voir ceci:
Si vous avez un message d'erreur, essayez d'abord de redémarrer Ganache, puis redémarrez votre test, vos tests précédents peuvent avoir utilisé un peu trop ETHER.
L'étape 1 prend fin, bien joué ! vous savez désormais créer un contrat, le compiler, le diffuser et le tester, grâce au langage de solvabilité et au cadre truffier.
Ce dont vous devez absolument vous souvenir:
- Un contrat intelligent est, très schématiquement, une classe de variables (qui doivent être déclarées avant utilisation) et de fonctions, écrites dans le langage de solidité
- Chaque fonction doit déclarer le type de variable reçu et retourné
- Truffle nous permet de tester, compiler et distribuer notre contrat de blockchain intelligent sans effort.
- Ganache nous permet de simuler une Blockchain localement.
Nous verrons à l'étape 2 comment développer l'interface web pour interagir avec la blockchain Ethereum et les contrats intelligents, avec Web3, une API Javascript pour communiquer avec une blockchain via une page web. Nous voyons également qu'il est nécessaire d'avoir une extension dans notre navigateur qui nous fournit une adresse Ethereum qui peut être utilisée dans les dApps, pour être sûr qu'elle est vérifiée en tant qu'utilisateur unique.