Passer au contenu principal

Interagir avec d'autres contrats depuis Solidity

contrats intelligents
Solidity
Remix
déploiement
composabilité
Avancé
jdourlens
5 avril 2020
4 minutes de lecture

Dans les tutoriels précédents, nous avons beaucoup appris sur comment déployer votre premier contrat intelligent, comment y ajouter certaines fonctionnalités comme le contrôle d'accès avec des modificateurs (opens in a new tab) ou la gestion des erreurs dans 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 d'avoir son propre contrat intelligent Counter en créant une fabrique pour celui-ci. Son nom sera CounterFactory. Voici d'abord le code de notre contrat intelligent Counter initial :

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 n'êtes pas le propriétaire du contrat");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "Vous devez utiliser la fabrique");
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

Notez que nous avons légèrement modifié le code du contrat pour garder une trace de l'adresse de la fabrique et de l'adresse du propriétaire du contrat. Lorsque vous appelez un code de contrat depuis un autre contrat, msg.sender fera référence à l'adresse de notre fabrique de contrats. C'est un point vraiment important à comprendre, car l'utilisation d'un contrat pour interagir avec d'autres contrats est une pratique courante. Vous devez donc faire attention à qui est l'expéditeur dans les 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 fabrique qui transmettra l'appelant original en tant que paramètre.

À l'intérieur de notre nouvelle CounterFactory qui gérera tous les autres contrats Compteur, nous ajouterons un mapping qui associera un propriétaire à l'adresse de son contrat Compteur :

1mapping(address => Counter) _counters;

Dans Ethereum, les mappings sont l'équivalent des objets en JavaScript. Ils permettent de mapper une clé de type A à une valeur de type B. Dans ce cas, nous mappons l'adresse d'un propriétaire avec l'instance de son Compteur.

Instancier un nouveau Compteur 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 }

Nous vérifions d'abord si la personne possède déjà un Compteur. S'il ne possède pas de Compteur, nous instancions un nouveau Compteur en passant son adresse au constructeur Counter et nous assignons l'instance nouvellement créée au mapping.

Pour obtenir la valeur d'un Compteur spécifique, cela ressemblera à 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}

La première fonction vérifie si le contrat Compteur existe pour une adresse donnée, puis appelle la méthode getCount depuis l'instance. La deuxième fonction, getMyCount, est juste un raccourci pour passer directement msg.sender à la fonction getCount.

La fonction increment est assez similaire, mais elle transmet l'expéditeur de la transaction originale au contrat Counter :

1function increment() public {
2 require (_counters[msg.sender] != Counter(0));
3 Counter(_counters[msg.sender]).increment(msg.sender);
4 }

Notez que s'il est appelé trop de fois, notre compteur pourrait être victime d'un dépassement de capacité (overflow). Vous devriez utiliser la bibliothèque SafeMath (opens in a new tab) autant que possible pour vous protéger de ce cas de figure.

Pour déployer notre contrat, vous devrez fournir à la fois le code de CounterFactory et de Counter. Lors du déploiement, dans Remix par exemple, vous devrez sélectionner CounterFactory.

Voici le code complet :

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 n'êtes pas le propriétaire du contrat");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "Vous devez utiliser la fabrique");
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

Après compilation, dans la section de déploiement de Remix, vous sélectionnerez la fabrique à déployer :

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

Ensuite, vous pouvez vous amuser avec votre fabrique de contrats et vérifier que la valeur change. 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 mise à jour de la page : 15 août 2023

Ce tutoriel vous a été utile ?