Entwickeln für die Ethereum-Blockchain: Schritt für Schritt zum ersten Smart Contract

Eigentlich sind Decentralized Apps (Dapps) ein alter Hut. Zumindest dann, wenn man sie mit bekannter Peer-to-Peer-Software (P2P) gleichsetzt wie Tor oder Bittorrent. Neu an den dezentralisierten Anwendungen ist die Blockchain als Backend. Auf ihr basiert bei Dapps sowohl die Logik als auch die Datenspeicherung. Von außen sieht eine Dapp wie eine normale Website aus, da beide Frontends auf den gleichen Programmiersprachen basieren – HTML, CSS und Javascript. Doch während das Frontend einer Website über eine API mit dem Backend auf einem zentralen Server verknüpft ist, steht bei einer Dapp ein sogenannter Smart Contract zwischen Frontend und der Blockchain im Ethereum-Netzwerk.
Leider ist Smart Contract eine etwas irreführende Bezeichnung, denn es handelt sich keineswegs um einen Vertrag. Vielmehr ist ein Smart Contract ein Programmcode, der die Logik der Dapp definiert und in Solidity geschrieben ist. Diese eigenständige Programmiersprache ist inspiriert von C++, Python und Javascript und gezielt für die Ethereum-Blockchain entwickelt worden. Ein Smart Contract läuft auf der Ethereum-Virtual-Machine, also im Ethereum-Netzwerk. Nach dem Deployment kann jeder mit einem Smart Contract interagieren, der einen Account innerhalb des Ethereum-Netzwerks hat – und zwar sowohl Menschen als auch andere Smart Contracts.
Das Besondere an dezentralisierten Anwendungen ist, dass sich mit ihnen komplexe Befehlsketten definieren lassen, die für alle erreichbar in der Blockchain stehen. Wer also etwa eine Spenden-Dapp entwickelt, kann Beiträge automatisiert durch einen Smart Contract sammeln und verwalten. Dapps zeichnen sich dadurch aus, dass ihr Quellcode Open Source ist, die Interaktion mit der Dapp über einen Krypto-Token (etwa Ethereum) verläuft, ihre Daten dezentral und verschlüsselt gespeichert sein müssen und die Interaktion mit dem Smart Contracts zum Mining von Token führt.
In diesem Beispiel soll der bereits erwähnte Spenden-Contract entstehen. Zum Einsatz kommt dabei das browserbasierte Remix-SDK. Einen ausführlichen Überblick gibt es in der dazugehörigen Dokumentation1. Der Vorteil von Remix für dieses Tutorial ist, dass für den Bau des Smart Contracts keine weitere Software notwendig ist.
Zunächst öffnen Entwickler die URL remix.ethereum.org in ihrem Browser. Wer Remix öffnet, findet standardmäßig einen beispielhaften Smart Contract (ballot.sol), der weitere Wahlfunktionen ermöglicht. Um einen eigenen Smart Contract zu erstellen, müssen Entwickler ein neues Dokument anlegen, indem sie auf das Plus-Symbol oben links im Fenster klicken. In diesem Fall soll das Dokument „donation.sol“ heißen. Per Klick auf „ok“ lässt es sich speichern und mit dem folgenden Code der Smart Contract erstellen. Wer sich die Mühe sparen will, kann den Smart Contract aber auch direkt herunterladen2 und in den Solidity-Editor in der Mitte kopieren.
Smart Contracts entwickeln
Zeile für Zeile soll nun der Code des Smart Contract für die Spenden-Dapp entstehen.
pragma solidity ^0.4.19;
Die erste Codezeile definiert die Version des Solidity-Compilers.
contract Donation {
Diese Zeile legt den Name des Smart Contract fest. Mit allem, was danach kommt, bestimmt der Code nun das Verhalten des Smart Contract.
address owner;
address owner legt die Variable fest, in der die Adresse des Ethereum-Accounts vom Besitzer des Contracts steht. Dadurch lassen sich Funktionen durch modifier onlyowner (siehe nächste Seite) so einrichten, dass sie später nur der Besitzer abrufen kann.
event fundMoved(address _to, uint _amount);
Die Anweisung event fundMoved definiert ein Event, das Nutzer später auslösen können. Mit Events können Entwickler die Logging-Funktion der Ethereum Virtual Machine nutzen. Außerdem können sie so auch Javascript-Callbacks auslösen.
modifier onlyowner { if (msg.sender == owner) _; }
Diese Zeile erweitert Funktionen so, dass sie sich nur von dem Konto abrufen lassen, das den Smart Contract veröffentlicht hat.
address[] _giver;
Das Feld address stößt die Ausführung einer Liste an, die alle Accounts aufführt, die Ethereum gespendet haben.
uint[] _values;
Das Feld uint listet hingegen die gespendeten Beträge auf.
event deployed(address _a, address _creator); function Donation() public { owner = msg.sender;
Dieser Code zeigt an, dass der Besitzer derjenige ist, der den Spenden-Smart-Contract veröffentlicht hat.
deployed(this, msg.sender);
}
function donate() payable public {
Diese Funktion stellt sicher, dass auch andere Accounts Ether an den Smart Contract spenden können. Durch das Stichwort
payable kann der Smart Contract die Einzahlungen akzeptieren. Die Angabe public besagt, dass sich diese Funktion sowohl intern als auch durch Nachrichten an den Contract auslösen lässt. Die Public-Funktionen sind Bestandteil des Smart-Contract-
Interfaces.
addGiver(msg.value);
Die Anweisung addGiver dokumentiert die Account-Adressen der Spender.
}
function moveFund(address _to, uint _amount) onlyowner public {
Die Funktion moveFund erlaubt es, Spendenbeträge an andere
Adressen auszuzahlen. Die Modifikation only owner stellt
sicher, dass nur der Besitzer die Funktion auslösen kann. Sie ist aber ebenfalls öffentlich.
if (_amount <= this.balance) {
Diese Anweisung stellt sicher, dass sich nur so viel Geld auszahlen lässt, wie tatsächlich vorhanden ist.
if (_to.send(this.balance)) {
Diese Zeile löst die Transaktion aus. Sollte sie erfolgreich sein, stößt sie das Event fundMoved an.
fundMoved(_to, _amount);
} else {
Sollte die Transaktion aus irgendeinem Grund scheitern, sorgen diese beiden Zeilen dafür, dass der Smart Contract alle Änderungen zurücksetzt.
revert();
} else {
Auch der Versuch, mehr zu überweisen, als auf dem Account eigentlich vorhanden ist, sorgt für eine Zurücksetzung aller Änderungen.
revert();
}
}
function addGiver(uint _amount) internal {
Die Funktion addGiver notiert die Adressen und Beträge der Spender. Wichtig ist dabei die Angabe internal. Sie legt fest, dass sich die Funktion nur aus dem Smart Contract heraus auslösen lässt.
_giver.push(msg.sender);
_values.push(_amount);
Durch diese Zeilen fügen Entwickler noch die Adresse (Account) des Spenders hinzu sowie die Menge der damit verbundenen
Daten (arrays).
(arrays)
}
}
Den Smart Contract compilen
Nun geht es daran, den Smart Contract zu compilen. Rechts oben im Fenster des Solidity Editors zeigt der Reiter „Compile“ an, dass der Compile-Tab offen ist. In der Mitte befindet sich der Solidity Editor und darin der oben genannte Solidity-Code des Smart Contract. Links ist der File-Explorer zu sehen, in dem sich Dokumente so ablegen lassen wie gerade das Dokument „donation.sol“. Entwickler können Remix an dieser Stelle auch mit anderen Dokumenten verknüpfen3. Im unteren Teil des Browsers zeigt ein weiteres graues Terminal die Logs und Transaktionen des Smart Contract an.
Durch das Häckchen bei „Auto Compile“ wandelt Remix den Smart Contract direkt in Ethereum-Virtual-Machine-Byte-Code um und zeigt mögliche Syntax-Fehler an. Zudem ist im Fenster rechts die Static-Analysis zu sehen, durch die Entwickler Fehler im Quellcode aufspüren können, etwa „integer overflows“ oder „reentrancy vulnerabilities“. Wie wichtig diese Static-Analysis- Warnungen sind, sieht man am Fall von The DAO. Das ist eine Dapp, die 2016 durch eine Reentrancy-Schwachstelle Ether im Wert von mehreren Millionen US-Dollar verloren hat. Ein Grund, weshalb sich für dieses Tutorial Spielgeld empfiehlt.
Smart Contract deployen
Nachdem der Smart Contract compiled ist, geht es an das Deployment. Dafür klicken Entwickler auf den Reiter „run tab“ und wählen unter „Environment“ den Eintrag „Javascript VM“ aus. Dabei handelt es sich um eine Ethereum-Node, die nur im Textbrowser existiert und keine Folgen für die Ethereum-Blockchain hat. Mit einem Klick auf „create“ startet das Deployment.
Die Veröffentlichung des Smart Contracts im echten Ethereum-Netzwerk würde einige Sekunden dauern. In diesem Übungs-umfeld geschieht das Deployment umgehend. Der Smart Contract hat nun eine eigene Adresse, die sich unter „Donation at …“ auswählen lässt. In diesem Beispiel lautet die Adresse „Donation at 0x692…77b3a (memory)“. Jedes Deployment eines Smart Contracts erzeugt eine neue Adresse.
Den Smart Contract nutzen
Anstatt den Smart Contract erneut zu veröffentlichen, steht nun die Interaktion mit ihm an. Dafür können Entwickler oben zwischen verschiedenen Accounts wählen. Das Konto, über das ein Entwickler seinen Smart Contract veröffentlicht hat, ist dabei automatisch der Owner-Account – also der Account, der auf die in den Smart Contract gespendeten Token zugreifen kann.
Um den Smart Contract zu testen, müssen Entwickler also ein anderes Konto auswählen. Dann können sie unter „Value“ zum Beispiel den Wert 70 eingeben und als „Einheit“ Ether auswählen. Nach der Bestätigung über den Button „Donate“ zeigt ein Fenster die Testaddresse sowie die 70 Ether, die im Test gerade an die Adresse des Smart Contracts gingen, plus eine kleine Transaktions- und Ausführungsgebühr. Im Echtfall hätte ein Entwickler damit umgerechnet rund 75.000 Euro (Stand Januar 2018) an einen Smart Contract gespendet. Wichtig: Das Konto kann jeder leeren, der das Owner-Wallet besitzt. Das zeigt einmal mehr, wie wichtig es ist, auf seine Wallets und Zugangsdaten aufzupassen.
Doch wie können sich Besitzer nun selbst Geld auszahlen? Dazu wechseln Entwickler wieder zu der Adresse, mit der sie den Smart Contract erstellt haben. Kleiner Tipp: Das ist der Account mit nicht mehr ganz 100 Ether – durch das Deployment und die Interaktion mit der Blockchain ist eine kleine Gebühr entstanden.
Für die Überweisung kopieren Entwickler die Account-Adresse in das Feld neben „movefund“ und geben den gewünschten Betrag in Ether an 0xca35b7d915458ef540ade6068dfe2f44e8fa733c. Wer nun versuchen würde, mehr Ether auszuzahlen, als vorhanden sind, würde nicht weit kommen: Der Smart Contract würde diese Auszahlung aufgrund des Codes nicht ausführen. Ansonsten erscheint mit einem Klick auf „movefund“ oben im Account der neue Kontostand.
Nächste Schritte zur dApp
Wer nun neugierig geworden ist und noch mehr ausprobieren will, kann seinen Smart Contract in einem nächsten Schritt in einem Testnetzwerk deployen. Um das zu tun, benötigen Entwickler einen lokalen Blockchain-Client wie zum Beispiel Geth. Um Geth mit einem Testnetzwerk zu verbinden – etwa mit Rinkeby –, müssen Dapp-Entwickler die Testnet-Flag in der Kommandozeile eingeben (geth –testnet). Nach dem lokalen Compilen des Smart Contracts lässt er sich im Testnetzwerk deployen. Weitere Informationen dazu gibt es im Contract-Tutorial von Ethereum4. Außerdem gibt es mehrere Javascript-Bibliotheken, die den Umgang mit Ethereum erleichtern. Die wichtigste ist web3.js library5. Mit ihrer Hilfe können Entwickler durch ein
Geth-Node mit Ethereum interagieren, also Daten abrufen und darstellen.
Um eine Ethereum-Node zu installieren und so auf ein Testnetzwerk oder das echte Ethereum-Netzwerk zuzugreifen, benötigen Entwickler weitere Werkzeuge wie Geth oder Parity. Als Testnetzwerk können sie entweder Web3-Provider wählen, zum Beispiel Ropsten, Kovan oder Rinkeby. Oder sie nutzen sogenannte Injected-Web3-Provider, die als Browser-Plugin funktionieren. Dazu gehören beispielsweise Mist oder Metamask. All diese Lösungen lassen sich mit Remix oder anderen SDK ansteuern. Beliebte Programme für die Ethereum-Programmierung sind auch Truffle, Embark oder – für Phyton-Fans – Populus. •
LINKS
Remix-Dokumentation: remix.readthedocs.io/en/latest/
Spenden-Smart-Contract:
t3n.me/spenden-smart-contract
Remix mit weiteren Dokumenten verknüpfen:
github.com/ethereum/remix
Deployment im Testnetzwerk:
t3n.me/deployment-testnetzwerk
web3.js library: github.com/ethereum/web3.js
Eugeniu Rusu ist Full-Stack-Developer
für Jolocom. Neben der Entwicklung einer Self-Sovereign-Identity-Lösung und Projekten zu dezentraler Software hat Eugeniu seine Abschlussarbeit 2017 über Wahlen durch Smart Contracts und Blockchain geschrieben.
Yann Levreau ist seit 2014 Entwickler
bei der Ethereum Foundation und dort hauptsächlich an der Entwicklung des Remix-SDK beteiligt. Vorher hat er am C++-Client von Ethereum mitgearbeitet.