Passer au contenu principal

Interagir avec les autres contrats de Solidity

contrats intelligentssolidityremixdéploiementcomposabilité
Avancé
jdourlens
EthereumDev(opens in a new tab)
5 avril 2020
4 minutes de lecture minute read
comp-tutorial-metadata-tip-author 0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE

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;
2
3contract Counter {
4
5 uint256 private _count;
6 address private _owner;
7 address private _factory;
8
9
10 modifier onlyOwner(address caller) {
11 require(caller == _owner, "Vous le proprietaire du contrat");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "Vous avez besoin d’un factory");
17 _;
18 }
19
20 constructor(address owner) public {
21 _owner = owner;
22 _factory = msg.sender;
23 }
24
25 function getCount() public view returns (uint256) {
26 return _count;
27 }
28
29 function increment(address caller) public onlyFactory onlyOwner(caller) {
30 _count++;
31 }
32
33}
Afficher tout
Copier

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}
5
6function 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;
2
3contract Counter {
4
5 uint256 private _count;
6 address private _owner;
7 address private _factory;
8
9
10 modifier onlyOwner(address caller) {
11 require(caller == _owner, "Vous etes le proprietaire du contrat");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "Vous avez besoin d’un factory");
17 _;
18 }
19
20 constructor(address owner) public {
21 _owner = owner;
22 _factory = msg.sender;
23 }
24
25 function getCount() public view returns (uint256) {
26 return _count;
27 }
28
29 function increment(address caller) public onlyFactory onlyOwner(caller) {
30 _count++;
31 }
32
33}
34
35contract CounterFactory {
36
37 mapping(address => Counter) _counters;
38
39 function createCounter() public {
40 require (_counters[msg.sender] == Counter(0));
41 _counters[msg.sender] = new Counter(msg.sender);
42 }
43
44 function increment() public {
45 require (_counters[msg.sender] != Counter(0));
46 Counter(_counters[msg.sender]).increment(msg.sender);
47 }
48
49 function getCount(address account) public view returns (uint256) {
50 require (_counters[account] != Counter(0));
51 return (_counters[account].getCount());
52 }
53
54 function getMyCount() public view returns (uint256) {
55 return (getCount(msg.sender));
56 }
57
58}
Afficher tout
Copier

Après avoir compilé, dans la section de déploiement de Remix, vous sélectionnez la Factory à déployer :

Sélection de la Factory à déployer dans Remix

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: @Joisir(opens in a new tab), 15 août 2023

Ce tutoriel vous a été utile ?