Interagir avec les autres contrats de Solidity
Dans le tutoriel précédent nous avons appris Comment déployer votre premier contrat intelligent et ajouter des fonctionnalité comme le contrôle d'accès avec des modificateurs(opens in a new tab) ou la gestion d'erreur avec Solidity(opens in a new tab). Dans ce tutoriel, nous allons apprendre comment déployer un contrat intelligent à partir d'un contrat existant et interagir avec celui-ci.
Nous allons créer un contrat qui permet à quiconque de disposer de son propre contrat intelligent Counter
en créant une usine. Nous l'appellerons CounterFactory
. Tout d'abord voici le code de notre précèdent contrat intelligent Counter
:
1pragma solidity 0.5.17;23contract Counter {45 uint256 private _count;6 address private _owner;7 address private _factory;8910 modifier onlyOwner(address caller) {11 require(caller == _owner, "Vous le proprietaire du contrat");12 _;13 }1415 modifier onlyFactory() {16 require(msg.sender == _factory, "Vous avez besoin d’un factory");17 _;18 }1920 constructor(address owner) public {21 _owner = owner;22 _factory = msg.sender;23 }2425 function getCount() public view returns (uint256) {26 return _count;27 }2829 function increment(address caller) public onlyFactory onlyOwner(caller) {30 _count++;31 }3233}Afficher toutCopier
Notez que nous avons légèrement modifié le code du contrat pour garder une trace de l'adresse de la Factory et de l'adresse du titulaire du contrat. Lorsque vous appelez un code contrat depuis un autre contrat, msg.render se réfère à l'adresse de notre contrat Factory. C'est un point vraiment important à comprendre car utiliser un contrat pour interagir avec d'autres contrats est une pratique courante. Il convient donc de déterminer qui est l'expéditeur dans des cas complexes.
Pour cela, nous avons également ajouté un modificateur onlyFactory
qui s'assure que la fonction de changement d'état ne peut être appelée que par la Factory qui passera l'appelant original comme paramètre.
À l'intérieur de notre nouvelle CounterFactory
qui gérera tous les autres contre-contrats, nous ajouterons un mapping qui associera un titulaire à l'adresse de son contrat:
1mapping(address => Counter) _counters;Copier
Dans Ethereum, le mapping est équivalent aux objets en javascript, il permet de faire correspondre une clé de type A à une valeur de type B. Dans ce cas, nous cartographions l'adresse d'un propriétaire avec l'instance de son contre-contrat.
Instancier un nouveau contre-contrat pour quelqu'un ressemblera à ceci :
1 function createCounter() public {2 require (_counters[msg.sender] == Counter(0));3 _counters[msg.sender] = new Counter(msg.sender);4 }Copier
Nous vérifions d'abord si la personne est déjà propriétaire d'un contre-contrat. S'il ne possède pas de contre-contrat, nous instancions un nouveau contre-contrat en passant son adresse au constructeur Counter
et assignons l'instance nouvellement créée au mapping.
Pour obtenir le nombre de vues d'un contre-contrat spécifique, il faudra faire comme ceci :
1function getCount(address account) public view returns (uint256) {2 require (_counters[account] != Counter(0));3 return (_counters[account].getCount());4}56function getMyCount() public view returns (uint256) {7 return (getCount(msg.sender));8}Copier
La première fonction vérifie s'il existe un contre-contrat pour une adresse donnée, puis appelle la méthode getCount
de l'instance. La deuxième fonction : getMyCount
est juste une courte opération pour passer le msg.sender directement à la fonction getCount
.
La fonction increment
est assez similaire mais bascule l'émetteur de la transaction originale vers le contrat Counter
:
1function increment() public {2 require (_counters[msg.sender] != Counter(0));3 Counter(_counters[msg.sender]).increment(msg.sender);4 }Copier
Notez que s'il est trop sollicité, notre compteur pourrait être saturé. Il convient d'utiliser la bibliothèque SafeMath(opens in a new tab) autant que possible pour se protéger de cette éventualité.
Pour déployer notre contrat, vous devrez fournir à la fois le code de la CounterFactory
et du Counter
. Lors du déploiement, dans Remix par exemple, vous devrez sélectionner CounterFactory.
Voici le code final :
1pragma solidity 0.5.17;23contract Counter {45 uint256 private _count;6 address private _owner;7 address private _factory;8910 modifier onlyOwner(address caller) {11 require(caller == _owner, "Vous etes le proprietaire du contrat");12 _;13 }1415 modifier onlyFactory() {16 require(msg.sender == _factory, "Vous avez besoin d’un factory");17 _;18 }1920 constructor(address owner) public {21 _owner = owner;22 _factory = msg.sender;23 }2425 function getCount() public view returns (uint256) {26 return _count;27 }2829 function increment(address caller) public onlyFactory onlyOwner(caller) {30 _count++;31 }3233}3435contract CounterFactory {3637 mapping(address => Counter) _counters;3839 function createCounter() public {40 require (_counters[msg.sender] == Counter(0));41 _counters[msg.sender] = new Counter(msg.sender);42 }4344 function increment() public {45 require (_counters[msg.sender] != Counter(0));46 Counter(_counters[msg.sender]).increment(msg.sender);47 }4849 function getCount(address account) public view returns (uint256) {50 require (_counters[account] != Counter(0));51 return (_counters[account].getCount());52 }5354 function getMyCount() public view returns (uint256) {55 return (getCount(msg.sender));56 }5758}Afficher toutCopier
Après avoir compilé, dans la section de déploiement de Remix, vous sélectionnez la Factory à déployer :
Ensuite, vous pouvez jouer avec votre Factory à contrat et suivre l'évolution de la valeur. Si vous souhaitez appeler le contrat intelligent à partir d'une adresse différente, vous devrez changer l'adresse dans la sélection de compte de Remix.
Dernière modification: @nhsz(opens in a new tab), 15 août 2023