How to build a Smart contract

In mijn vorige blogs heb ik beschreven wat de voordelen van blockchain zijn en de rol van smart contracts. Met blockchain technologie krijgen we de mogelijkheid de uit te voeren afspraken in contracten vast te leggen in code, waardoor deze te allen tijde wordt uitgevoerd conform de vastgelegde condities. Denk bijvoorbeeld aan een uitkering van een verzekering of de overdracht van vastgoed. Naast transacties kunnen blockchain en smart contracts ook gebruikt worden als truth machine voor bijv. de onderhoudshistorie van gebouwen of voertuigen. In deze blog beschrijf ik hoe een eenvoudig smart contract gemaakt kan worden op de Ethereum blockchain.

Tools
Om een smart contract op Ethereum te kunnen maken zijn een aantal tools (minimaal) nodig. Om te beginnen is een wallet en een Ethereum node nodig. MetaMask is een handige Chrome plugin die zowel een wallet als een bridge naar diverse Ethereum blockchains biedt (waardoor een eigen node niet nodig is). Samen met de online ontwikkelomgeving Remix kunnen we de eerste stappen zetten in het ontwikkelen van een smart contract.

Solidity
Smart contracts worden geschreven in de taal Solidity, dat veel weg heeft van JavaScript. Deze blog behandelt slecht een beperkt deel van Solidity. Zie hier voor een diepgaande uitleg.
Een contract wordt beschreven als een soort class in een Object Oriented taal als Java of C# en kent variabelen en functies. Variabelen worden gebruikt voor het vastleggen van gegevens en functies voor het uitvoeren van handelingen. Verder biedt Solidity overerving (inheritance) en events.

Hieronder een voorbeeld van de code van het contract genaamd Coin, met 2 variabelen:

  • address met de naam minter
  • mapping (hash table) met de naam balances.

Een address is een specifiek blockchain type. Hierin kan een account-adres worden opgeslagen, zoals in dit geval het account dat het contract aanroept. Verder zien we een event Sent en drie functies, waaronder een constructor die alleen wordt aangeroepen wanneer het contract op de blockchain wordt aangemaakt.

How to build a Smart contract – 1@4x

Aanmaken van een contract
Nadat MetaMask is geïnstalleerd zijn er diverse netwerken te kiezen. Het Main-netwerk vergeten we voorlopig, gezien de benodigde ether (geld!) die daar voor nodig is. Voor nu werken we liever met een testnetwerk zoals Ropsten. Om een contract te kunnen aanmaken is test ether nodig. MetaMask biedt op testnetwerken de mogelijkheid deze via de buy knop te krijgen. Via een zogenaamde faucet kan test ethers verkregen worden. Vervolgens kunnen we aan de slag!

How to build a Smart contract – 2@4x

Remix biedt de mogelijkheid smart contracts te schrijven, compileren, deployen, testen en debuggen, direct vanuit de browser. Heel praktisch om mee te starten.

Hoe maken we het Coin contract aan op de testomgeving? We zien onder het tabblad Run de mogelijkheid het contract aan te maken met de knop Create. Voordat we dat kunnen doen hebben we in MetaMask het Ropsten netwerk geselecteerd en in Remix bij Environment gekozen voor Injected Web3. Dit zorgt ervoor dat MetaMask gebruikt wordt als wallet / node. Als account zien we ons account terug uit MetaMask. Soms verschijnt het account niet direct in Remix. Een harde refresh van de pagina in de browser doet wonderen. Nu alles goed staat kunnen we met de knop Create het contract aanmaken.

How to build a Smart contract – 3@4x

Omdat het aanmaken van een contract een transactie start (en een fee nodig is), wordt een bevestiging door MetaMask gevraagd en de transactie wordt vervolgens verstuurd naar de blockchain.

How to build a Smart contract – 4@4x

In MetaMask verschijnt de transactie voor het aanmaken van het contract.

How to build a Smart contract – 5@4x

Nu is het wachten op een miner die het blok toegevoegd. Dit gaat op Ethereum vrij snel (zo’n 20 seconden) Doordat Ropsten net als het Main-netwerk een publiekelijke blockchain is, is alles volledig transparant!

How to build a Smart contract – 6@4x

Wanneer de 3 puntjes veranderd zijn in een document (in dit voorbeeld) is de transactie doorgevoerd. Door op de transactie te klikken opent Etherscan van het Ropsten netwerk. Op deze internetpagina is de transactie volledig in te zien.

How to build a Smart contract – 7@4x

Het contract is nu aangemaakt op het Ropsten netwerk en in de screenshot is te zien wat de werkelijke kosten zijn geweest voor het aanmaken van het contract (361858 gas / 0.007599018 ether). En zoals in het screenshot is te zien, heeft een contract een eigen adres, net als een account (wallet) van een gebruiker. Ook kan een contract ether bezitten (een balans hebben), en zelfs een ander smart contract aanmaken. Een contract account verschilt vrij weinig van een normaal account (zogenaamd externally controlled accounts).

Remix compileert het smart contract dat we hebben geschreven in Solidity automatisch naar byte code. Het contract wordt vervolgens in byte code op de blockchain geplaatst. In Remix kan op het tabblad Compile zowel de byte code als de ABI ingezien worden. De ABI is de Application Binary Interface. De ABI beschrijft de interface van het contract en is nodig om het contract te kunnen aanroepen. Later meer hierover.

How to build a Smart contract – 8@4x

Contract testen
Met Remix kunnen we vervolgens het contract testen. Nadat het contract is aangemaakt verschijnt er een deelvenster waarmee we het contract kunnen aanroepen. Doordat de eerdergenoemde 2 variabelen als public zijn gedefinieerd, zijn automatisch 2 get-functies aangemaakt. Deze zijn te herkennen aan de blauwe knoppen. Door hierop te drukken wordt de huidige waarde getoond. Dergelijke functies raadplegen alleen de blockchain en starten daardoor geen transactie (en kosten dus ook geen ether). Met de functie mint kan een ander account voorzien worden van een aantal ‘coins’, echter alleen door de eigenaar van het contract. Met de functie send kan iedereen die ‘coins’ bezit, een deel hiervan of alles overmaken naar een ander. Let op: Remix verwacht dat parameters (vrijwel altijd) tussen ” … ” worden geplaatst.

How to build a Smart contract – 9@4x

En alle transacties zijn continu te zien in Etherscan en biedt een daarmee een handig hulpmiddel om te controleren wat er gebeurt bij het uitvoeren van transacties.

How to build a Smart contract – 10@4x

Ethers in een contract
In het genoemde voorbeeld wordt een balans bijgehouden van een eigen ‘muntje’. Maar wat nu als je met ethers wilt werken om daarmee echte waarde over te dragen? Allereerst dien je contract ethers te kunnen ontvangen. Dit doe je door simpelweg een of meerdere functies te voorzien van het keyword payable. Deze functies kunnen nu bij een aanroep ethers ontvangen. Zonder een functie payable te maken kan deze functie geen ether ontvangen.

How to build a Smart contract – 11@4x

Door een waarde in te voeren bij Value (aantal ether!) en vervolgens de functie aan te roepen, wordt het ingevoerde aantal ether meegestuurd met de transactie en vervolgens aan de balans van het contract toegevoegd. Hiervoor is verder geen code nodig. Elk smart contract bevat automatisch een balance. Laten we 2 ether meesturen bij de aanroep van de payable functie.

How to build a Smart contract – 12@4x

In MetaMask is te zien dat er 2 ether wordt meegestuurd. Uiteraard dient het account waarmee het contract wordt aangeroepen, wel minimaal 2 ether te bevatten.

How to build a Smart contract – 13@4x

Vervolgens is in Etherscan (door op de transactie in MetaMask te klikken) het contract te bekijken en zien we dat de balans op 2 ether staat.

How to build a Smart contract – 14@4x

In dit voorbeeld hebben we aan de balans van het contract 2 ether toegevoegd. Een contract kan vervolgens net als een externally controlled account ether overmaken naar andere accounts. Dit maakt het mogelijk (tijdelijk) ether op te slaan op een contract en onder vastgelegde voorwaarden over te maken naar andere accounts (rechthebbenden). Denk bijvoorbeeld aan het overmaken van het geld vanuit een contract, als aan de levering (ontvangst) van een goed is voldaan. Overmaken kan met de onderstaande constructie (verdere checks en error handling voor het overzicht weggelaten):

How to build a Smart contract – 15@4x

Met this.balance wordt de huidige balans van het contract bedoeld, of te wel de hoeveelheid ether die het contract bevat. De functie transfer wordt aangeroepen op het adres waarheen de ether wordt overgemaakt. Ether kan alleen worden overgemaakt door het contract zelf. Het is dus uiterst belangrijk functies te hebben ingebouwd waarmee ether kan worden overgemaakt! Indien deze ontbreken is het onmogelijk de ethers uit het contract te halen.

In Etherscan is vervolgens duidelijk zichtbaar dat er vanuit een contract ether wordt overgemaakt naar een ander account.

How to build a Smart contract – 16@4x

Opheffen van een contract
Een eenmaal aangemaakt smart contract is niet meer te wijzigen. Een van de kenmerken van een blockchain is dat het immutable (niet te veranderen) is. Dit geldt ook voor smart contracts. Des te belangrijker vooraf heel goed te na te denken over de werken van het smart contract en te testen. Eenmaal aangemaakt op het Main-netwerk van Ethereum hebben we de controle uit handen gegeven. Aanpassingen zijn dan niet meer mogelijk, met alle mogelijke risico’s van dien.

Wel kunnen we een constructie inbouwen om een smart contract op te heffen, om bij een fout groter leed te voorkomen (of het contract te stoppen wanneer het niet meer gewenst is). Een contract kan worden opgeheven met de functie selfdestruct. Als parameter wordt het adres meegegeven waar alle resterende ether op de balans van het contract naartoe gestuurd moet worden. Vaak is dit de eigenaar van het contract. Belangrijk is dat deze functie niet door iedereen kan worden aangeroepen. Dan zou iedereen het contract kunnen opheffen. In onderstaand voorbeeld wordt daarvoor een modifier ‘onlyowner’ gebruikt. Een gangbare constructie in Solidity.

How to build a Smart contract – 17@4x

Fallback functie
Als laatste sta ik kort stil bij de fallback functie. Dit is een functie in een contract zonder naam, zoals in onderstaand voorbeeld. Deze functie wordt gebruikt voor elke aanroep van het smart contract, waarbij de functienaam en parameters in de aanroep niet overeenkomen met een functie in het smart contract. Hierdoor is het toch mogelijk code in het contract uit te voeren, ondanks de foutieve (of ongewenste) aanroep. Bijv. door het adres van het account dat de aanroep doet te registreren.

How to build a Smart contract – 18@4x

Verified contracts
Omdat smart contracts als byte code (onleesbaar) op Ethereum staan, is niet direct inzichtelijk of het smart contract daadwerkelijk doet wat beloofd wordt dat deze doet. Blockchains zijn immutable en transparant, waardoor alle partijen kunnen vertrouwen op de inhoud. Maar hoe zit dat dan met smart contracts, nu deze in bytecode op Ethereum staan?

Etherscan biedt oplossing. Bij elk contract kan de Solidity code worden toegevoegd. Doordat Etherscan het contract ook compileert kan deze vergeleken worden met de byte code op de blockchain. Indien deze 100% overeenkomst, zijn we er zeker van dat het smart contract gelijk is aan de Solidity code die zichtbaar is in Etherscan.

How to build a Smart contract – 19@4x

DApp met standaard JavaScript
Om een smart contract op Ethereum in een applicatie te kunnen gebruiken is een gebruiksvriendelijke webinterface nodig. We noemen zo’n applicatie een Dapp (distributed application). Maar wat is er nodig om een smart contract te kunnen aanroepen vanaf een webapplicatie? Niet veel meer dan in dit blog beschreven. We hebben een eenvoudige html pagina nodig, een API-interface van Ethereum (genaamd web3.js) en Javascript om met het smart contract te kunnen communiceren.

How to build a Smart contract – 20@4x

Installeer web3.js met een package manager (npm) of download het van github.
Include de web3.js file in de html pagina. Maak een eigen .js bestand waarin onderstaande code wordt opgenomen:

How to build a Smart contract – 21@4x

Via JavaScript kun je vervolgens met de Ethereum node die geselecteerd is in MetaMask communiceren. Hiervoor zijn de eerdergenoemde ABI en het adres van het contract nodig. Via de web3.eth.contract method kun je een instance van het contract aanroepen.

How to build a Smart contract – 22@4x

Vervolgens zijn zowel de variabelen als de functies direct te gebruiken.

How to build a Smart contract – 23@4x
How to build a Smart contract – 24@4x

Bedenk goed dat de functies op het contract een transactie (kunnen) starten waardoor het asynchrone functies zijn. Pas wanneer het block met de transactie is ge-mine-d, is de transactie daadwerkelijk uitgevoerd. Het gaat te ver voor deze blog om dit te bespreken. Meer informatie over web3 zie hier.

Professionele Dapp ontwikkeling
In deze blog heb ik de ontwikkeling van een heel basaal smart contract laten zien. Voor professionelere toepassingen kunnen we gebruikmaken van tools als TestRPC, Geth, Mist en Truffle. Daarover in een volgende blog meer.

 

Meer informatie

victor-van-der-hulst

Victor van der Hulst

Managing Consultant

+31 6 22 98 68 76 Stuur Victor een e-mail

Reacties

Er zijn nog geen reacties op dit bericht.

Plaats een reactie

Dit veld is verplicht.

Vul een geldig e-mailadres in.

Dit veld is verplicht.