Treceți la conținutul principal

Ajutați-ne să actualizăm această pagină

🌏

Există o nouă versiune a acestei pagini, dar este doar în limba engleză pentru moment. Ajutați-ne să traducem versiunea cea mai recentă.

Traduceți pagina
Afișați versiunea în limba engleză

Nici o eroare aici!🐛

Această pagină nu este tradusă. Am lăsat în mod intenționat această pagină în limba engleză deocamdată.

Interacționează cu alte contracte din Solidity

contracte inteligentesolidityremixfabriciimplementarecombinabilitate
Avansat
✍️jdourlens
📚EthereumDev
📆5 aprilie 2020
⏱️4 minute de citit

Sfatul autorului 0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE

Î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, "You're not the owner of the contract");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "You need to use the 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
Afișați tot
📋 Copiați

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
📋 Copiați

Î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
📋 Copiați

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
📋 Copiați

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
📋 Copiați

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, "You're not the owner of the contract");
12 _;
13 }
14
15 modifier onlyFactory() {
16 require(msg.sender == _factory, "You need to use the 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}
59
Afișați tot
📋 Copiați

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 modificare: , Invalid DateTime
Modificați pagina

A fost utilă această pagină?