Mit anderen Smart Contracts aus Solidity interagieren
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;23contract Counter {45 uint256 private _count;6 address private _owner;7 address private _factory;8910 modifier onlyOwner(address caller) {11 require(caller == _owner, "You're not the owner of the contract");12 _;13 }1415 modifier onlyFactory() {16 require(msg.sender == _factory, "You need to use the factory");17 _;18 }1920 constructor(address owner) public {21 _owner = owner;22 _factory = msg.sender;23 }2425 function getCount() public view returns (uint256) {26 return _count;27 }2829 function increment(address caller) public onlyFactory onlyOwner(caller) {30 _count++;31 }3233}Alle anzeigenBeachten 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}56function 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;23contract Counter {45 uint256 private _count;6 address private _owner;7 address private _factory;8910 modifier onlyOwner(address caller) {11 require(caller == _owner, "You're not the owner of the contract");12 _;13 }1415 modifier onlyFactory() {16 require(msg.sender == _factory, "You need to use the factory");17 _;18 }1920 constructor(address owner) public {21 _owner = owner;22 _factory = msg.sender;23 }2425 function getCount() public view returns (uint256) {26 return _count;27 }2829 function increment(address caller) public onlyFactory onlyOwner(caller) {30 _count++;31 }3233}3435contract CounterFactory {3637 mapping(address => Counter) _counters;3839 function createCounter() public {40 require (_counters[msg.sender] == Counter(0));41 _counters[msg.sender] = new Counter(msg.sender);42 }4344 function increment() public {45 require (_counters[msg.sender] != Counter(0));46 Counter(_counters[msg.sender]).increment(msg.sender);47 }4849 function getCount(address account) public view returns (uint256) {50 require (_counters[account] != Counter(0));51 return (_counters[account].getCount());52 }5354 function getMyCount() public view returns (uint256) {55 return (getCount(msg.sender));56 }5758}Alle anzeigenNach dem Kompilieren wählen Sie im Bereitstellungsbereich von Remix die Factory aus, die bereitgestellt werden soll:
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
