Ajută la actualizarea acestei pagini

🌏

Există o nouă versiune a acestei pagini, dar acum este doar în engleză. Ajută-ne să traducem cea mai recentă versiune.

Interacționează cu alte contracte din Solidity

În tutorialele anterioare ai învățat multe: cum să implementezi primul tău contract inteligent și să adaugi câteva caracteristici la acesta precum controlul accesului cu modificatori sau gestionarea erorilor în Solidity. În acest tutorial vei învăța cum să implementezi un contract inteligent dintr-un contract existent și să interacționezi cu acesta.

Vei crea un contract care permite oricui să aibă propriul contract inteligent Counter, creând o fabrică pentru acesta, numele ei va fi CounterFactory. În primul rând aici este codul contractului inteligent inițial 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, "Nu ești proprietarul contractului");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "Trebuie să folosești fabrica");
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
Afișează tot
📋 Copiere

Reține că am modificat ușor codul contractului pentru a urmări adresa fabricii și adresa proprietarului contractului. Când apelezi un cod de contract dintr-un alt contract, msg.sender va face referire la adresa fabricii noastre de contracte. Acesta este un punct foarte important de înțeles, deoarece utilizarea unui contract pentru a interacționa cu alte contracte este o practică comună. Prin urmare, ar trebui să ai grijă de cine este expeditorul în cazuri complexe.

Pentru aceasta am adăugat și un modificator onlyFactory care se asigură că funcția de modificare a stării poate fi apelată doar de fabrică, care va transmite apelantul inițial ca parametru.

În interiorul noului nostru CounterFactory, care va gestiona toate celelalte contoare, vom adăuga o mapare care va asocia un proprietar la adresa contractului său:

1mapping(address => Counter) _counters;
2
📋 Copiere

În Ethereum, maparea este echivalentă cu obiectele din javascript, acestea permit maparea unei chei de tip A la o valoare de tip B. În acest caz, vom mapa adresa unui proprietar cu instanța Counter-ului său.

Crearea unei instanțe de contor nou pentru cineva, va arăta astfel:

1 function createCounter() public {
2 require (_counters[msg.sender] == Counter(0));
3 _counters[msg.sender] = new Counter(msg.sender);
4 }
5
📋 Copiere

Verificăm mai întâi dacă persoana deține deja un contor. Dacă nu deține un contor, creăm o nouă instanță de contor nou prin trecerea adresei sale la constructorul Counter și atribuim noua instanță creată la mapare.

Pentru a obține numărul unui contor specific, scriem:

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}
9
📋 Copiere

Prima funcție verifică dacă contractul de contor există pentru o anumită adresă, apoi apelează metoda getCount din instanță. A doua funcție: getMyCount este doar un capăt scurt pentru a trece msg.sender direct la funcția getCount.

Funcția increment este destul de asemănătoare, dar transmite expeditorul inițial al tranzacției la contractul Counter:

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

Reține că, dacă este apelat de mai multe ori, contorul nostru ar putea fi victima unui flux excesiv. Trebuie să utilizezi SafeMath Library cât mai mult pentru a te proteja de acest caz posibil.

Pentru a implementa contractul nostru, va trebui să furnizezi atât codul CounterFactory, cât și Counter. Când implementezi, de exemplu, în Remix, va trebui să selectezi CounterFactory.

Aici este codul 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, "Nu ești proprietarul contractului");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "Trebuie să utilizezi fabrica");
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}
59
Afișează tot
📋 Copiere

După compilare, în secțiunea Remix Deploy vei selecta fabrica ce va fi implementată:

Selectarea fabricii care va fi implementată în Remix

După aceea, poți să te joci cu fabrica de contract și să verifici cum se modifică valorile. Dacă dorești să apelezi contractul inteligent de la o adresă diferență va trebui să modifici adresa din „Selectare cont” din Remix.

Ultima editare: , Invalid DateTime
Edit page