Solidity Tutorial: An Introduction to Solidity Programming for Beginners

Solidity-zelfstudie

Solidity is een objectgeoriënteerde taal op hoog niveau voor het ontwikkelen van dApps (gedecentraliseerde applicaties) op de Ethereum-blockchain.

Een blockchain is een peer-to-peer-netwerk van computers, knooppunten genaamd, die alle gegevens en de code in het netwerk delen.

Dus als je een apparaat bent dat is verbonden met de blockchain, ben je een knooppunt in het netwerk en praat je met alle andere computerknooppunten in het netwerk (we zullen in latere tutorials bespreken hoe je Ethereum-knooppunt op je lokale computer instelt).

Je hebt nu een kopie van alle data en de code op de blockchain. Er zijn geen centrale servers meer nodig.

Wat is Ethereum?

Ethereum is op zijn eenvoudigst een open softwareplatform op basis van blockchain-technologie waarmee ontwikkelaars gedecentraliseerde applicaties kunnen bouwen en implementeren.

Terwijl de Bitcoin-blockchain wordt gebruikt om het eigendom van digitale valuta (bitcoins) te volgen, richt de Ethereum-blockchain zich op het uitvoeren van de code van gedecentraliseerde applicaties.

In de Ethereum-blockchain werken miners in plaats van mijnbouw voor bitcoin om Ether te verdienen, een soort crypto-token dat het netwerk voedt. Naast een verhandelbare cryptocurrency, wordt Ether ook gebruikt door applicatieontwikkelaars om transactiekosten en diensten op het Ethereum-netwerk te betalen..

Er is een tweede type token dat wordt gebruikt om mijnwerkersvergoedingen te betalen voor het opnemen van transacties in hun blok, het wordt gas genoemd, en voor elke slimme contractuitvoering moet een bepaalde hoeveelheid gas worden meegestuurd om mijnwerkers te verleiden om het in te voeren de blockchain.

Beginnend bij de basis

De code van Solidity is ingekapseld in contracten.

Met Ethereum blockchain kunnen we code uitvoeren met de Ethereum Virtual Machine (EVM) op de blockchain met zoiets als een smart contract.

Slimme contracten zijn waar alle bedrijfslogica van onze applicatie leeft – alle variabelen en functies behoren tot een contract, en dit zal het startpunt zijn van al uw projecten.

Slimme contacten zijn geschreven in een programmeertaal genaamd Solidity, die eruitziet als een mix van Javascript en C.

Remix IDE

Remix is ​​een online tool waarmee u slimme Solidity-contracten kunt schrijven, deze vervolgens kunt implementeren en uitvoeren.

Ga gewoon naar https://remix.ethereum.org vanuit uw browser en we kunnen beginnen met coderen.

Zoals je kunt zien, kun je kiezen tussen Solidity en Vyper. Beide zijn talen voor het schrijven van slimme contracten, Vyper is pythonachtig en Solidity is javascript-achtig.

Beide kunnen compileren naar de EVM-bytecode, zoals Javascript en Typescript. We kiezen voor Solidity.

Aan de linkerkant is er een bestandsverkenner. Standaard zijn er twee .sol-bestanden, alleen om de basissyntaxis te demonstreren (ballot.sol is een slim contract, ballot_test.sol is een script voor het testen van dat slimme contract).

U hoeft alleen maar op die plusknop te klikken en we kunnen beginnen met het coderen van ons eerste slimme contract.

Alle solidity-broncode moet beginnen met een “versie pragma” – een verklaring van de versie van de Solidity-compiler die deze code zou moeten gebruiken. Dit is om problemen met toekomstige compilerversies te voorkomen die mogelijk wijzigingen introduceren die uw code zouden breken.

Het ziet er zo uit:

pragma stevigheid ^ 0.4.25;

(voor de Solidity-versie boven 0.4.25)

of

pragma stevigheid >= 0,5,0 < 0.6.0;

(voor de Solidity-versie tussen 0.5.0 en 0.6.0)

Vervolgens maakt u uw contract door het gereserveerde woord te typen contract en de naam van uw .sol-bestand (het is belangrijk dat de contractnaam overeenkomt met de naam van het bestand, we zullen later bespreken waarom). In ons geval,

contract MyFirstContract {

Laten we het compileren. U hoeft alleen maar naar dat compilatietabblad aan de linkerkant te navigeren en op de grote compileerknop te klikken. Als er iets mis is met de code, zie je hier fouten en waarschuwingen (wees medelijdend met Solidity, het is nog steeds “jonge taal”).

Met ons huidige contract is alles in orde want we hebben echt niks gedaan.

Nu zal ik met opzet een fout genereren om u iets te laten zien. U kunt de compiler handmatig selecteren in dat vervolgkeuzemenu.

Laten we bijvoorbeeld kiezen voor versie 0.4.26. Compileer het nu opnieuw. Nu zie je de fout ‘Compiler nog niet geladen’.

Dit komt doordat we met pragma hebben gespecificeerd om te werken met compilerversies hoger dan 0.5.0. Verander gewoon de compilerversie opnieuw en de fout is verdwenen.

Oké, laten we nu gaan programmeren!

We beginnen met eenvoudige ‘Hallo wereld’ -code en krijgen en set-functies, alleen om meer vertrouwd te raken met de syntaxis.

Een contract in de zin van Solidity is een verzameling code (zijn functies) en gegevens (zijn staat) die zich op een specifiek adres op de Ethereum-blockchain bevindt.

Laten we eerst de statusvariabele met de naam message definiëren, en het type zal string zijn.

Onze get-functie retourneert de waarde van ons variabele bericht en de set-functie wijst een nieuwe waarde toe aan ons variabele bericht.

Hoe functies te typen?

Ten eerste, gereserveerd woord functie dan de naam van een bepaalde functie en parameters en daarna .

function myFunction () retourneert (bool) {

terugkeer waar;

Functies kunnen zijn openbaar of privaat. Als een functie openbaar is, kan deze buiten het contract worden aangeroepen. Als een functie privé is, heeft deze een beperkte reikwijdte en kan deze alleen worden aangeroepen vanuit het huidige contract (bijvoorbeeld vanuit een andere functie).

Hier is de lijst met alle functiezichtbaarheidsspecificaties:

  • openbaar: extern en intern zichtbaar (creëert een getter-functie voor opslag- / statusvariabelen)
  • privaat: alleen zichtbaar in het huidige contract
  • extern: alleen extern zichtbaar (alleen voor functies) – d.w.z. alleen oproepbaar (via this.func)
  • intern: alleen intern zichtbaar

Functies kunnen zijn zuiver, visie, of te betalen. Als een functie geen gegevens op blockchain schrijft, is het zeer aan te raden om te bekijken, omdat weergavefuncties geen gas kosten.

Hier is de lijst met alle functiemodificatoren (er zijn ook modificatoren voor toestandsvariabelen, gebeurtenissen en gebeurtenisargumenten, maar daar zal later over worden gesproken):

  • zuiver: Staat wijziging of toegang tot de staat niet toe.
  • visie: Staat wijziging van de staat niet toe.
  • te betalen: Hiermee kunnen ze Ether samen met een oproep ontvangen.

Als Functie een waarde retourneert, moet u dat specificeren met een gereserveerd woord geeft terug en vervolgens tussen normale haakjes om aan te geven welk type de functie retourneert. In ons geval zal het string zijn (omdat we ons variabele bericht retourneren dat string is)

Als de functie geen waarde retourneert, is dat niet nodig geeft terug uitspraak.

Om toegang te krijgen tot een statusvariabele heb je het voorvoegsel niet nodig dit. zoals gebruikelijk is in andere talen.

Daarom is het gebruikelijk om functieargumenten te schrijven met de syntaxis van een onderstrepingsteken (_bericht). Deze conventie is afkomstig van Javascript, waar privémethoden en variabelen beginnen met _.

Voor de duidelijkheid: uw code werkt prima en zonder onderstrepingstekens, maar bij hen is het schoner.

U zult een gereserveerd woord opmerken geheugen in onze code. Als je onze code zonder geheugen schrijft en pragma instelt op een versie onder 0,5. * Het zal prima werken, maar als je je compiler verandert in meer dan 0,5. * EVM genereert compilatiefout.

Waarom gebeurt dit?

Welnu, de Ethereum Virtual Machine heeft drie gebieden waar het items kan opslaan.

  • De eerste is opslag, waar alle contractstatusvariabelen zich bevinden. Elk contract heeft zijn eigen opslag en is persistent tussen functieaanroepen in en vrij duur in gebruik.
  • De tweede is geheugen, dit wordt gebruikt om tijdelijke waarden vast te houden. Het wordt tussen (externe) functieaanroepen gewist en is goedkoper in gebruik.
  • De derde is de stapel, die wordt gebruikt om kleine lokale variabelen vast te houden. Het is bijna gratis te gebruiken, maar kan slechts een beperkt aantal waarden bevatten.

Voor bijna alle typen kunt u niet aangeven waar ze moeten worden opgeslagen, omdat ze bij elk gebruik worden gekopieerd.

Maar als u met arrays of structs werkt, en vanaf de laatste versies ook met strings, zal de compiler u dwingen het winkelgebied op te geven.

Dus onze code ziet er nu als volgt uit:

pragma stevigheid ^ 0,5,0;

contract MyFirstContract {

string bericht;

functie get () public view returns (string memory) {

terug bericht;

functieset (string memory _message) public {

message = _message;

Houd er rekening mee dat sommige Solidity-ontwikkelaars die zichtbaarheidsspecificaties in afzonderlijke regels opsplitsen om de code schoner te maken. Dus onze get-functie kan als volgt worden geschreven:

functie get ()

openbaar

visie

retourneert (string)

terug bericht;

Het is echt aan jou hoe je ervoor kiest om je functies te schrijven.

Laten we nu ons contract samenstellen en testen.

Herhaal de onderstaande stappen om het te compileren (Compileer .sol toets of cmd / ctrl + S van het toetsenbord en het zal het automatisch opnieuw compileren)

Om echt te zien hoe het werkt (als het compileren geen fouten oplevert) moet u uw contract implementeren.

Om dat te doen, navigeert u van links naar dat tabblad Implementatie, selecteert u JavaScriptVM voor de omgeving en drukt u op de knop Implementeren.

Na inzet kunnen we nu methoden uit ons contract zien. Laten we ons nu concentreren op dat deel van het scherm.

Je kunt zien dat er twee knoppen zijn (get & set) voor onze twee openbare functies. Als een van deze privé was, zouden we het hier niet zien.

Als we op de knop ophalen klikken, zal EVM onze ophaalfunctie uitvoeren.

Laten we eens kijken hoe het werkte.

We hebben een lege string. Niet geweldig, niet verschrikkelijk. Maar waarom? Nou, omdat we onze berichtvariabele niet op de eerste plaats hebben geïnitialiseerd.

Slechts een korte pauze. Ik wil dat je kennis maakt met de Remix Terminal. Het staat onder de code-editor en hier kunt u al uw transacties volgen, zien of ze met succes zijn uitgevoerd of niet, fouten opsporen, details bekijken (transactie-hash enz.) En meer.

Voorlopig hebben we twee succesvolle transacties. Een daarvan is contractimplementatie en het kost ons ether (maar maak je geen zorgen, we zijn in de editor nu alles virtueel is) en ten tweede is Call of our visie functie.

Oké, laten we nu teruggaan. Wat gebeurt er als we nu de set-functie aanroepen??

We moeten een argument _message doorgeven (bijvoorbeeld “Hallo wereld”) en op transactieknop drukken om de functie uit te voeren. U kunt het succes van de transactie volgen in Terminal.

Laten we nu de functie Get opnieuw bellen. Nu geeft het onze boodschap terug.

Laten we wat verbeteringen aanbrengen in onze code. We hebben ons variabele bericht niet geïnitialiseerd. Laten we dit doen.

contract MyFirstContract {

string bericht = "Hallo Wereld!"​

functie get () public view returns (string memory) {

terug bericht;

functieset (string memory _message) public {

message = _message;

Merk op dat het bericht nu ‘Hallo wereld!’ Is en dat wanneer we de functie Get voor de eerste keer aanroepen, geen lege tekenreeks wordt geretourneerd.

Om dit te testen, moeten we ons contract samenstellen (cmd / ctrl + S).

Om het vervolgens opnieuw in te zetten. We moeten een nieuw exemplaar van het contract maken (vanwege de wijzigingen die we hebben aangebracht) en dat op blockchain publiceren.

Verwijder gewoon de vorige versie uit de editor (niet uit onze virtuele blockchain natuurlijk) en druk nogmaals op de knop Implementeren. Laten we nu onze ophaalfunctie bellen.

Leuk! Laten we nu de set-functie aanroepen.

En krijg opnieuw.

Stoer.

Laten we onze boodschap nu a maken constante.

Onze code nu:

pragma stevigheid ^ 0,5,0;

contract MyFirstContract {

string constante bericht = "Hallo Wereld!"​

functie get () public view returns (string memory) {

terug bericht;

functieset (string memory _message) public {

message = _message;

Wanneer we het proberen te compileren, krijgen we een fout in onze set-functie. Dat komt omdat men de waarde van een constante niet kan veranderen.

We zullen die constante nu gewoon verwijderen.

Het initialiseren van variabelen zoals deze is geen fout, maar het is veel beter als we dat in constructor doen. Je kunt constructor in Solidity schrijven met:

constructor () openbaar {

// doe iets…

Constructor is gewoon een andere functie die wordt aangeroepen tijdens de implementatie van een slim contract. Onze code ziet er een beetje anders uit, maar het werkt hetzelfde.

pragma stevigheid ^ 0,5,0;

contract MyFirstContract {

string bericht;

constructor () openbaar {

bericht = "Hallo Wereld!"​

functie get () public view returns (string memory) {

terug bericht;

functieset (string memory _message) public {

message = _message;

U kunt het opnieuw compileren en desgewenst testen.

Ten slotte kan men de zichtbaarheid van toestandsvariabelen wijzigen. Als u uw toestandsvariabelen maakt openbaar dat betekent dat men hun waarden van buiten het contract kan claimen.

Solidity zal voor elke publieke statusvariabele een methode maken met dezelfde naam die kan worden aangeroepen als een reguliere functie (een beetje zoals een getter-functie).

Dit betekent dat we onze get-functie kunnen verwijderen, gewoon het variabele bericht declareren als openbaar, en onze code zal hetzelfde werken, het zal veel schoner zijn en het kost ons minder om het op een dag op het hoofdnetwerk te implementeren.

Hoe groter de code, hoe meer gas er nodig is om het uit te voeren en de kosten voor het uitvoeren van onze dApp worden hoger.

Wanneer we slimme contracten ontwikkelen, moeten we:

  • efficiënt – het verbruikte gasdebiet moet laag zijn
  • precies – zodra u een smart contract implementeert, kan het niet worden gewijzigd en is het 24 uur per dag, 7 dagen per week openbaar, elke regel code (stel u een hacker voor die een bug vindt en uw dApp kan exploiteren)

Onze laatste code voor vandaag ziet er als volgt uit:

pragma stevigheid ^ 0,5,0;

contract MyFirstContract {

string openbaar bericht;

constructor () openbaar {

bericht = "Hallo Wereld!"​

functieset (string memory _message) public {

message = _message;

Laten we het implementeren en testen.

Je kunt die berichtknop zien. Het wordt gemaakt omdat ons statusvariabele bericht openbaar is.

Als we dat noemen, zou het ons een waarde moeten retourneren die wordt geïnitialiseerd via constructor (dat is “Hallo wereld!”).

Leuk. Laten we de setfunctie nu testen.

Hoe soliditeit te leren?

Solidity zelf is vrij eenvoudige taal, maar om een ​​goede Solidity-ontwikkelaar te zijn, moet je begrijpen hoe alles werkt op Ethereum.

  • Solidity is een programmeertaal op hoog niveau met syntaxis vergelijkbaar met ECMAScript (javascript).
  • Het compileert naar EVM-bytecode, iets dat alleen de EVM kan begrijpen.
  • De compiler heet Solc.

Laten we dit eenvoudige contract als voorbeeld nemen:

pragma stevigheid ^ 0,5,0;

contract Voorbeeld {

uint a = 10 + 5;

Simpel als dat. Laten we het nu compileren. Als we in Terminal naar Contractdetails gaan, kunnen we veel informatie zien.

In dit geval is de gecompileerde code:

0x6080604052600f600055348015601457600080fd5b5060358060226000396000f3fe6080604052600080fdfea165627a7a72305820bf75c57b7d8745a79baee513ead21a9eb8b075896f8e4c593c17 …

Deze lange waarden zijn een hexadecimale weergave van het uiteindelijke contract, ook wel bytecode genoemd. EVM begrijpt alleen bytecode.

Maar als er iets misgaat, komen we vast te zitten met een fout, bijvoorbeeld, men kan bytecode niet debuggen.

Opcodes

Taal boven bytecode is opcode. Opcode is een programmeertaal op laag niveau. Solidity en Opcode zijn bijvoorbeeld als C en Assembly Language.

Dus als we een mislukte transactie moeten debuggen, debuggen we opcode.

Een ding dat u moet weten over Solidity en foutopsporing – het is erg moeilijk. Maar niet onmogelijk, dus laten we erin duiken.

Dit is de code van ons voorbeeldcontract:

0 PUSH1 60

02 PUSH1 40

04 MEER

05 PUSH1 0f

07 PUSH1 00

09 WINKEL

10 OPROEPWAARDE

11 DUP1

12 ISZERO

13 PUSH1 14

15 JUMPI

16 PUSH1 00

18 DUP1

19 REVERT

20 JUMPDEST

21 POP

22 PUSH1 35

24 DUP1

25 PUSH1 22

27 PUSH1 00

29 CODECOPIE

30 PUSH1 00

32 RETOUR

33 ONGELDIG

34 PUSH1 80

36 PUSH1 40

38 MEER

39 PUSH1 00

41 DUP1

42 REVERT

43 ONGELDIG

44 LOG1

45 PUSH6 627a7a723058

52 SHA3

53 ONGELDIG

54 PUSH22 c57b7d8745a79baee513ead21a9eb8b075896f8e4c59

77 ONGELDIG

78 DUP10

79 EN

80 JUMPI

81 ONGELDIG

82 BALANS

83 PUSH29 750029

Opcodes zijn de door mensen leesbare instructies van het programma op laag niveau. Alle opcodes hebben hun hexadecimale tegenhangers, bijv MEER is 0x52.

De EVM is Stack Machine. Het is gebaseerd op de LIFO-structuur (Last In First Out). Om het eenvoudiger te maken, stel je voor dat je sneetjes brood in een magnetron stapelt, de LAATSTE snee die je erin stopt, is de EERSTE die je eruit haalt.

In normale rekenkunde schrijven we onze vergelijking als volgt:

10 + 2 * 2

en het antwoord is 14, omdat we vermenigvuldigen vóór optellen.

In een stapelmachine werkt het volgens het LIFO-principe:

2 2 * 10 +

Het betekent dat je eerst 2 op de stapel legt, gevolgd door nog eens 2, en dan gevolgd door een vermenigvuldigingsactie. Het resultaat is dat er 4 bovenop de stapel zitten. Voeg nu een getal 10 toe bovenop 4 en tel uiteindelijk de 2 getallen bij elkaar op. De uiteindelijke waarde van de stapel wordt 14.

Het plaatsen van gegevens in de stapel wordt de PUSH-instructie genoemd en het verwijderen van gegevens uit de stapel wordt de POP-instructie genoemd. Het is duidelijk dat de meest voorkomende opcode die we in ons voorbeeld hierboven zien, PUSH1 is, wat betekent dat 1 byte aan gegevens in de stapel moet worden geplaatst.

Dus deze instructie:

PUSH1 0x60

betekent het plaatsen van een 1 byte waarde van “0x60” in de stapel. Toevallig is de hexadecimale waarde voor PUSH1 ook “0x60”. Door de niet-verplichte “0x” te verwijderen, zouden we deze logica in bytecode kunnen schrijven als “6060”.

Laten we nog wat verder gaan.

PUSH1 0x60 PUSH1 0x40 MEERDERE

De MSTORE (0x52) heeft 2 inputs en produceert geen output. De bovenstaande opcodes betekenen:

PUSH1 (0x60): zet 0x60 in de stapel.

PUSH1 (0x40): zet 0x40 in de stapel.

MEERDERE (0x52): wijs 0x60 geheugenruimte toe en ga naar de 0x40-positie.

De resulterende bytecode is:

6060604052

In feite zien we dit magische nummer “6060604052” altijd aan het begin van elke soliditeitsbytecode, omdat zo het slimme contract bootstrap.

Om de zaak nog ingewikkelder te maken, kan 0x40 of 0x60 niet worden geïnterpreteerd als het echte getal 40 of 60. Omdat ze hexadecimaal zijn, is 40 eigenlijk gelijk aan 64 (16 × 4) en 60 gelijk aan 96 (16 × 6) in decimalen.

Kort gezegd, wat “PUSH1 0x60 PUSH1 0x40 MSTORE” doet, is het toewijzen van 96 bytes aan geheugen en het verplaatsen van de pointer naar het begin van de 64e byte. We hebben nu 64 bytes voor werkruimte en 32 bytes voor tijdelijke geheugenopslag.

In de EVM zijn er 3 plaatsen om gegevens op te slaan. Ten eerste in de stapel. We hebben zojuist de PUSH-opcode gebruikt om daar gegevens op te slaan, zoals in het bovenstaande voorbeeld.

Ten tweede in het geheugen (RAM) waar we de MSTORE-opcode gebruiken en ten slotte in de schijfopslag waar we SSTORE gebruiken om de gegevens op te slaan. Het gas dat nodig is om gegevens op te slaan is het duurst en het opslaan van gegevens om te stapelen is het goedkoopst.

Nu is het een goed moment om terug te gaan naar onze Solidity-code uit deze tutorial en om samen te vatten wat we hebben geleerd over gereserveerde woorden geheugen en hoe de compiler ons dwingt om te specificeren hoe we bijvoorbeeld strings opslaan.

We hebben alleen de basisprincipes van bytecode en een paar opcodes behandeld.

We hoeven geen opcodes te kennen om een ​​smart contract te schrijven!

Aan de andere kant is de EVM-foutafhandeling nog steeds erg primitief en het is handig om opcodes te bekijken als er iets misgaat.

Gevolgtrekking

Deze eerste les bevat iets meer theorie dan feitelijke codering, maar het is erg belangrijk voor beginners om te weten hoe de dingen werken op Ethereum. In de volgende tutorials zullen we wat meer interessante code schrijven en leren hoe we ons eigen token op de Ethereum-blockchain kunnen implementeren.

Tot dan &# 128075;

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me