Le mapping pour créer une hash table en Solidity

0

Nous allons présenter dans ce tutorial comment mettre en place une hash table avec Solidity, grâce à la fonction mapping qui permet d’associer deux variables entre elles, quelque soit leur type.

Imaginons que nous souhaitons créer un service web dans la blockchain et que celui ci contient plusieurs utilisateurs. Nous souhaitons donc associer à une adresse Ethereum l’adresse email et le nom de l’utilisateur pour pouvoir les afficher et les utiliser dans nos smart contracts. Nous allons créer dans Remix un contrat GestionUtilisateur.

Commençons par déclarer ce contrat :

pragma solidity >=0.4.22 <0.6.0;

contract GestionUtilisateur {
    constructor() public {
    }
}

Nous allons créer une structure utilisateur avec deux chaines de caractères qui permettront de stocker le nom et le mail de nos utilisateurs :

    struct Utilisateur {
        string Mail;
        string Nom;
    }

Enfin, pour que chaque utilisateur soit associé à une adresse Ethereum, il faut créer un mapping qui associera le type de variable ‘address’ au type de variable Utilisateur que nous avons créé précédemment.

Le mapping peut être utilisé avec tous les types de variables, que ce soit int, string, bool, address etc…

Notre contrat permettra donc d’associer le type address au type Utilisateur dans la table de hashage listeUtilisateur grâce à la déclaration suivante :

mapping (address => Utilisateur) listeUtilisateur;

Il reste maintenant à créer une fonction d’ajout d’utilisateur, qui devra tout d’abord initialiser un struct utilisateur, et l’ajouter dans le mapping. Le code sera donc :

    function ajouterUtilisateur (string memory _mail, string memory _nom) public {
        Utilisateur memory nouvelUtilisateur = Utilisateur(_mail, _nom);
        listeUtilisateur[msg.sender] = nouvelUtilisateur;
    }

Enfin, pour que ce smart contract puisse afficher un utilisateur, nous allons créer une fonction voirUtilisateur qui prend en paramètre l’adresse Ethereum d’un utilisateur et envoi en réponse son nom et son mail :

    function voirUtilisateur(address _address) public view returns (string memory, string memory)  {
        return (listeUtilisateur[_address].Nom, listeUtilisateur[_address].Mail);
    }

Le mapping ne permet pas d’itération

C’est une limite importante mais facile à contourner, mais il ne sera pas possible de faire une itération, par exemple avec une boule FOR en Solidity sur un mapping.

Pour résoudre ce problème, parce que nous souhaitons voir par exemple tous les utilisateurs inscrits sur notre contrat, il faudra créer un tableau des adresses des utilisateurs qui sera alimenté à chaque fois que la fonction d’ajout d’un utilisateur est appelée.
Commençons par déclarer en début de contrat ce nouveau tableau :

address[] public ListeDesutilisateurs;

Nous allons alors modifier la fonction d’ajout pour prendre en compte cet inventaire des utilisateurs qui sera alimenté à chaque ajout, la fonction d’ajout devient alors :

    function ajouterUtilisateur (string memory _mail, string memory _nom) public {
        Utilisateur memory nouvelUtilisateur = Utilisateur(_mail, _nom);
        listeUtilisateur[msg.sender] = nouvelUtilisateur;
        ListeDesutilisateurs.push(msg.sender);
    }

C’est terminé ! Le contrat permet maintenant de créer des users et de les afficher, et chacun sera associé à son adresse Ethereum grâce à msg.sender.

Voici le code complet du contrat que vous pouvez tester :

pragma solidity >=0.4.22 <0.6.0;

contract GestionUtilisateur {
    
    constructor() public {
    }
    
    struct Utilisateur {
        string Mail;
        string Nom;
    }
    
    mapping (address => Utilisateur) listeUtilisateur;
    address[] public ListeDesutilisateurs;
    
    function ajouterUtilisateur (string memory _mail, string memory _nom) public {
        Utilisateur memory nouvelUtilisateur = Utilisateur(_mail, _nom);
        listeUtilisateur[msg.sender] = nouvelUtilisateur;
        ListeDesutilisateurs.push(msg.sender);
    }
    
    function voirUtilisateur(address _address) public view returns (string memory, string memory)  {
        return (listeUtilisateur[_address].Nom, listeUtilisateur[_address].Mail);
    }
    
}

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.