Zum Hauptinhalt springen

Mit anderen Smart Contracts aus Solidity interagieren

Smart Contracts
Solidity
Remix
Bereitstellung
Zusammensetzbarkeit
Experte
jdourlens
5. April 2020
4 Minuten Lesezeit

In den vorherigen Tutorials haben wir viel darüber gelernt, wie Sie Ihren ersten Smart Contract bereitstellen und ihm einige Funktionen hinzufügen können, wie z. B. Zugriffskontrolle mit Modifikatoren (opens in a new tab) oder Fehlerbehandlung in Solidity (opens in a new tab). In diesem Tutorial werden wir lernen, wie man einen Smart Contract aus einem bestehenden Smart Contract heraus bereitstellt und mit ihm interagiert.

Wir werden einen Smart Contract erstellen, der es jedem ermöglicht, seinen eigenen Counter-Smart-Contract zu haben, indem wir eine Fabrik (Factory) dafür erstellen. Ihr Name wird CounterFactory sein. Hier ist zunächst der Code unseres anfänglichen Counter-Smart-Contracts:

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}
Alle anzeigen

Beachten Sie, dass wir den Code des Smart Contracts leicht modifiziert haben, um die Adresse der Factory und die Adresse des Smart-Contract-Eigentümers nachzuverfolgen. Wenn Sie einen Smart-Contract-Code von einem anderen Smart Contract aus aufrufen, bezieht sich msg.sender auf die Adresse unserer Smart-Contract-Factory. Dies ist ein wirklich wichtiger Punkt, den man verstehen muss, da die Verwendung eines Smart Contracts zur Interaktion mit anderen Smart Contracts eine gängige Praxis ist. Sie sollten daher in komplexen Fällen darauf achten, wer der Absender ist.

Dafür haben wir auch einen onlyFactory-Modifikator hinzugefügt, der sicherstellt, dass die zustandsändernde Funktion nur von der Factory aufgerufen werden kann, die den ursprünglichen Aufrufer als Parameter übergibt.

Innerhalb unserer neuen CounterFactory, die alle anderen Counter verwalten wird, fügen wir ein Mapping hinzu, das einen Eigentümer der Adresse seines Counter-Smart-Contracts zuordnet:

1mapping(address => Counter) _counters;

In Ethereum sind Mappings das Äquivalent zu Objekten in JavaScript. Sie ermöglichen es, einen Schlüssel vom Typ A auf einen Wert vom Typ B abzubilden. In diesem Fall bilden wir die Adresse eines Eigentümers auf die Instanz seines Counters ab.

Die Instanziierung eines neuen Counters für jemanden sieht wie folgt aus:

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

Wir prüfen zunächst, ob die Person bereits einen Counter besitzt. Wenn sie keinen Counter besitzt, instanziieren wir einen neuen Counter, indem wir ihre Adresse an den Counter-Konstruktor übergeben und die neu erstellte Instanz dem Mapping zuweisen.

Um den Zählerstand eines bestimmten Counters abzurufen, sieht das so aus:

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}

Die erste Funktion prüft, ob der Counter-Smart-Contract für eine bestimmte Adresse existiert, und ruft dann die Methode getCount der Instanz auf. Die zweite Funktion: getMyCount ist nur eine Abkürzung, um den msg.sender direkt an die Funktion getCount zu übergeben.

Die Funktion increment ist recht ähnlich, übergibt aber den ursprünglichen Absender der Transaktion an den Counter-Smart-Contract:

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

Beachten Sie, dass unser Counter bei zu vielen Aufrufen möglicherweise Opfer eines Overflows (Überlaufs) werden könnte. Sie sollten die SafeMath-Bibliothek (opens in a new tab) so oft wie möglich verwenden, um sich vor diesem möglichen Fall zu schützen.

Um unseren Smart Contract bereitzustellen, müssen Sie sowohl den Code der CounterFactory als auch den des Counter bereitstellen. Wenn Sie beispielsweise in Remix bereitstellen, müssen Sie CounterFactory auswählen.

Hier ist der vollständige Code:

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}
Alle anzeigen

Nach dem Kompilieren wählen Sie im Bereitstellungsbereich von Remix die Factory aus, die bereitgestellt werden soll:

Auswahl der in Remix bereitzustellenden Factory

Dann können Sie mit Ihrer Smart-Contract-Factory herumspielen und überprüfen, wie sich der Wert ändert. Wenn Sie den Smart Contract von einer anderen Adresse aus aufrufen möchten, müssen Sie die Adresse in der Kontoauswahl von Remix ändern.

Letzte Aktualisierung der Seite: 15. August 2023

War dieses Tutorial hilfreich?