TP Blockchain Ethereum - Partie II

Introduction aux Events

Dans un Smart Contract, une fonction appelée peut émettre un événement (event). Les events en plus d'être inscrit dans la blockchain, peuvent être récupéré par un Listener dans l'application en front-end. Cela permet par exemple de notifier l'utilisateur qu'une opération à bien eu lieu.

Pour les travaux qui suivent nous allons nous appuyer sur la librairie ethers.js (au lieu de web3.js). L'installation se fait à l'aide de la commande npm i ethers (Attention au proxy Lyon 1 : npm config set proxy "http://proxy.univ-lyon1.fr:3128" ).

Programmation asynchrone

Pour pouvoir mieux appréhender la suite des exercices proposés il est important de comprendre la programmation en mode asynchrone de JavaScript (Promise, async/await). Voici un premier exemple qui permet de récupérer le numéro du dernier bloc miné. Ce bout de code peut être exécuté directement dans la console de node ou avec la commande node suivit du nom du fichier javascript.

const ethers = require('ethers');
const provider = ethers.getDefaultProvider(); // homstead (mainnet)

provider.getBlockNumber()
        .then(blockNumber => {
                console.log("Block number : " + blockNumber);
        });

ou avec le support de Infura

const ethers = require('ethers');
const provider = new ethers.providers.InfuraProvider('homestead','64da4byourprojectid.....');

provider.getBlockNumber()
        .then(blockNumber => {
                console.log("Block number : " + blockNumber);
        });

Observons l'évolution de la blockchain

La première étape consiste a observer en "temps réel" la création de nouveaux blocs dans la blockchain homestead (mainnet). L'apparition d'un nouveau bloc est un event en soi. Soit le fichier index.js.

const ethers = require('ethers');
const provider = ethers.getDefaultProvider(); // homstead (mainnet)

provider.on('block', (blockNumber) => {
    console.log('-- New Block: ' + blockNumber);
});

Observons la naissance des chats (CK)

CryptoKitties

Il existe un Smart Contract (ERC-721) à l'addresse 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d qui permet de collectionner des CryptoKitties (chat électronique). L'application frontal (https://www.cryptokitties.co/) permet aux utilisateurs d'en acheter, d'en vendre (spéculation), ou de les faire se reproduire afin de créer de nouvelles générations de "chats". Le code source du Smart Contract qui permet cela est disponible à l'adresse 0x06012c8cf97bead5deae237070f9587f8e7a266d.

Si vous parcourez le code Solidity de ce Smart Contract (lignes 226 et 415) vous observerez qu'un évenement Birth est émis à chaque fois qu'un "chat" naît. Le code source JavaScript suivant permet d'observer la naissance des chats en temps réel.

const ethers = require('ethers');
const provider = ethers.getDefaultProvider(); // homstead (mainnet)

let abi = [
    "event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes)"
];
let contractAddress = "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d";
let contract = new ethers.Contract(contractAddress, abi, provider);

contract.on("Birth", (owner, kittyId, matronId, sireId, genes , event) => {
    console.log("# block # : " + event.blockNumber);
    console.log("# Owner : "   + owner);
    console.log("# kittyId : " + kittyId);
});

Vous devrez peut être patienter quelques longues minutes avant qu'un "heureux événement" ne se produise. Ensuite, avec l'addresse du propriétaire et etherscan.io vous devriez pouvoir observer la transaction sur la blockchain, son coût et surtout à quoi ressemble le "chat" nouveau-né (cf. onglet Inventory).

Travail facultatif :

  1. Écrivez un bout de code qui affiche le numéro de chaque nouveau bloc miné, et
  2. si ce bloc contient la naissance d'un chat, affichez l'adresse Ethereum de son propriétaire et l'Id du chaton.

A vous d'observer ! (ERC-20)

Les contrats ERC-20 définissent un événement Transfer(address indexed _from, address indexed _to, uint _value) appelé par toutes les fonctions de transfert de Token d'un compte à un autre (i.e. transfer(...) et transferFrom(...)).

Choisissez le Token de votre choix (ex: BAT, ZRX, ...) et en vous inspirant des exemples précédents, écrivez un bout de code Javascript qui affiche le nombre de Token transmis (value) entre les comptes en temps réel.

Travail à rendre :

  1. Écrivez un bout de code qui affiche le numéro de chaque nouveau bloc miné
  2. Si ce nouvea bloc contient une transaction du Token que vous avez choisi profitez en pour afficher les adresses de l'émetteur et du récepteur ainsi que la valeur transmise.
  3. Pourquoi pour ce second TP nous n'avons pas eu besoin de récupérer des Ethers au préalable ?

Travail de réflexion :

Comparez le coût en unité de GAS de l'OP_CODE SSTORE et de l'OP_CODE LOG (utilisé par la fonction emit d'un événement) :

  1. Qu'est ce que cela vous inspire ?
  2. Quelle est la limitation ?