Tutorial de solidesa

Solidity és un llenguatge orientat a objectes d’alt nivell per al desenvolupament de dApps (aplicacions descentralitzades) a la cadena de blocs Ethereum.

Una cadena de blocs és una xarxa d’ordinadors d’igual a igual, anomenats nodes, que comparteixen totes les dades i el codi de la xarxa..

Per tant, si sou un dispositiu connectat a la cadena de blocs, sou un node de la xarxa i parleu amb tots els altres nodes d’ordinador de la xarxa (en tutorials posteriors parlarem de com configurar el node Ethereum a la vostra màquina local).

Ara teniu una còpia de totes les dades i el codi de la cadena de blocs. Ja no calen servidors centrals.

Què és Ethereum?

En la seva forma més senzilla, Ethereum és una plataforma de programari obert basada en tecnologia blockchain que permet als desenvolupadors construir i desplegar aplicacions descentralitzades..

Tot i que la cadena de blocs de Bitcoin s’utilitza per fer un seguiment de la propietat de la moneda digital (bitcoins), la cadena de blocs d’Ethereum se centra a executar el codi d’aplicacions descentralitzades.

A la cadena de blocs d’Ethereum, en lloc d’extreure bitcoins, els miners treballen per guanyar Ether, un tipus de fitxa criptogràfica que alimenta la xarxa. Més enllà d’una criptomoneda comercialitzable, Ether també és utilitzat pels desenvolupadors d’aplicacions per pagar comissions i serveis de transacció a la xarxa Ethereum.

Hi ha un segon tipus de testimoni que s’utilitza per pagar comissions als miners per la inclusió de transaccions al seu bloc, s’anomena gas i, per a la realització d’un contracte intel·ligent, s’envia una certa quantitat de gas junt amb ell per atreure els miners a posar-lo la cadena de blocs.

Començant pels conceptes bàsics

El codi de Solidity està encapsulat en contractes.

Ethereum blockchain ens permet executar codi amb la màquina virtual Ethereum (EVM) de la cadena de blocs amb una cosa que s’anomena contracte intel·ligent.

Els contractes intel·ligents són on viu tota la lògica empresarial de la nostra aplicació: totes les variables i funcions pertanyen a un contracte, i aquest serà el punt de partida de tots els vostres projectes..

Els contactes intel·ligents s’escriuen en un llenguatge de programació anomenat Solidity, que sembla una barreja de Javascript i C.

Remix IDE

Remix és una eina en línia que us permet escriure contractes intel·ligents Solidity, desplegar-los i executar-los.

Només cal anar a https://remix.ethereum.org des del vostre navegador i podem començar a codificar.

Com podeu veure, podeu triar entre Solidity i Vyper. Tots dos són idiomes per escriure contractes intel·ligents, Vyper és similar a Python i Solidity és javascript.

Tots dos poden compilar-se al bytecode EVM, com Javascript i Typescript. Estem triant Solidity.

A la part esquerra hi ha l’explorador de fitxers. Per defecte, hi ha dos fitxers .sol, només per demostrar la sintaxi bàsica (ballot.sol és un contracte intel·ligent, ballot_test.sol és un script per provar aquest contracte intel·ligent).

Només cal que feu clic al botó més i ja podem començar a codificar el nostre primer contracte intel·ligent.

Tot el codi font de solidesa hauria de començar amb una “versió pragma”: una declaració de la versió del compilador Solidity que aquest codi hauria d’utilitzar. Això és per evitar problemes amb futures versions del compilador que poden introduir canvis que trenquin el vostre codi.

Es veu així:

solidesa del pragma ^ 0.4.25;

(per a la versió Solidity superior a 0.4.25)

o bé

solidesa del pragma >= 0,5,0 < 0,6,0;

(per a la versió Solidity entre 0.5.0 i 0.6.0)

A continuació, creeu el contracte escrivint la paraula reservada contracte i el nom del vostre fitxer .sol (és important que el nom del contracte coincideixi amb el nom del fitxer; en parlarem per què més endavant). En el nostre cas,

contracte MyFirstContract {

}

Compilem-lo. Només cal que aneu a aquesta pestanya de compilació de l’esquerra i feu clic al botó de compilació gran. Si alguna cosa no funciona amb el codi, veureu errors i advertències aquí (tingueu compassió de Solidity, encara és un “llenguatge jove”).

Amb el nostre contracte actual tot va bé perquè realment no hem fet res.

Ara generaré errors a propòsit només per mostrar-vos alguna cosa. Podeu seleccionar manualment el compilador des d’aquest menú desplegable.

Escollim, per exemple, la versió 0.4.26. Ara, torneu a compilar-lo. Ara veureu un error “Compilador encara no carregat”.

Això es deu al fet que amb pragma hem especificat per treballar amb versions de compilador superiors a 0.5.0. Simplement canvieu de nou la versió del compilador i l’error desapareixerà.

D’acord, codifiquem ara!

Començarem amb un codi senzill “Hello world” i aconseguirem i establirem funcions, només per familiaritzar-nos amb la sintaxi.

Un contracte en el sentit de Solidaritat és una col·lecció de codi (les seves funcions) i dades (el seu estat) que resideix en una adreça específica de la cadena de blocs d’Ethereum.

En primer lloc, definim la variable d’estat anomenada missatge per exemple i el seu tipus serà cadena.

La nostra funció get retornarà el valor del nostre missatge variable i la funció set assignarà un valor nou al missatge variable.

Com escriure funcions?

Primer, paraula reservada funció a continuació, el nom de la funció i els paràmetres particulars i després .

function myFunction () retorna (bool) {

tornar cert;

}

Les funcions poden ser públic o bé privat. Si una funció és pública, es pot trucar fora del contracte. Si una funció és privada, té un abast limitat i només es pot anomenar des del contracte actual (per exemple, des d’alguna altra funció).

Aquí teniu la llista de tots els especificadors de visibilitat de funcions:

  • públic: visible externament i internament (crea una funció getter per a variables d’emmagatzematge / estat)
  • privat: només visible al contracte actual
  • extern: només visible externament (només per a funcions), és a dir, només es pot trucar per missatge (a través de this.func)
  • intern: només visible internament

Les funcions poden ser pur, vista, o bé a pagar. Si una funció no escriu cap dada a blockchain, és molt recomanable que es visualitzi, ja que les funcions de visualització no costen gens.

Aquí teniu la llista de tots els modificadors de funcions (també hi ha modificadors per a variables d’estat, esdeveniments i arguments d’esdeveniments, però en parlarem més endavant):

  • pur: No permet la modificació ni l’accés d’estat.
  • vista: No permet la modificació d’estat.
  • a pagar: Els permet rebre Ether juntament amb una trucada.

Si Function retorna algun valor, cal especificar-ho amb la paraula reservada torna i després entre claudàtors regulars per especificar quin tipus torna la funció. En el nostre cas serà cadena (perquè retornem el nostre missatge variable que és cadena)

Si la funció no retorna cap valor, no és necessari torna declaració.

Per accedir a una variable d’estat, no necessiteu el prefix això. com és habitual en altres idiomes.

Per això, una pràctica habitual és escriure arguments de funció amb sintaxi de subratllat (_messatge). Aquesta convenció prové de Javascript, on els mètodes i variables privades comencen per _.

Per ser clar, el vostre codi funcionarà bé i sense subratllats, però amb ells és més net.

Notareu la paraula reservada memòria al nostre codi. Si escriviu el nostre codi sense memòria i definiu pragma en alguna versió inferior a 0,5. * Funcionarà bé, però quan canvieu el compilador per sobre de 0,5. * EVM genera un error de compilació.

Per què passa això??

Bé, la màquina virtual Ethereum té tres àrees on pot emmagatzemar articles.

  • La primera és emmagatzematge, on resideixen totes les variables d’estat del contracte. Cada contracte té el seu propi emmagatzematge i és persistent entre les trucades de funcions i és bastant car d’utilitzar.
  • El segon és memòria, s’utilitza per mantenir valors temporals. S’esborra entre trucades de funció (externes) i és més barat d’utilitzar.
  • El tercer és el apilar, que s’utilitza per contenir petites variables locals. És gairebé gratuït, però només pot contenir una quantitat limitada de valors.

Per a gairebé tots els tipus, no podeu especificar on s’han d’emmagatzemar, ja que es copien cada vegada que s’utilitzen.

Però quan treballeu amb matrius o estructures, i també a partir de les últimes versions amb cadenes, el compilador us obligarà a especificar l’àrea de magatzem.

Per tant, el nostre codi ara té aquest aspecte:

solidesa del pragma ^ 0,5,0;

contracte MyFirstContract {

missatge de cadena;

la funció get () retorna la vista pública (memòria de cadena) {

missatge de retorn;

}

conjunt de funcions (missatge de memòria de cadena) públic {

missatge = _messatge;

}

}

Tingueu en compte que alguns desenvolupadors de Solidity divideixen aquests especificadors de visibilitat en línies separades per tal de netejar el codi. Per tant, la nostra funció get es pot escriure així:

funció get ()

públic

vista

retorna (cadena)

{

missatge de retorn;

}

Realment depèn de vosaltres com escolliu escriure les vostres funcions.

Compilem ara el nostre contracte i el provem.

Per compilar-lo només cal repetir els passos que es mostren a continuació (Compila .sol botó o cmd / ctrl + S des del teclat i es tornarà a compilar automàticament)

Per veure realment com funciona (si la compilació no genera errors), heu de desplegar el vostre contracte.

Per fer-ho, aneu a la pestanya Desplegament des de l’esquerra, per a l’entorn, seleccioneu JavaScriptVM i premeu el botó Desplega.

Després del desplegament, ara podem veure els mètodes del nostre contracte. Centrem-nos ara només en aquesta part de la pantalla.

Podeu veure que hi ha dos botons (get & set) per a les nostres dues funcions públiques. Si alguna d’aquestes fos privada, no la veuríem aquí.

Si fem clic al botó obtenir EVM executarà la nostra funció get.

Vegem com va funcionar.

Tenim una cadena buida. Ni gran, ni terrible. Però perquè? Bé, perquè no vam inicialitzar la nostra variable de missatge al principi.

Només una pausa ràpida. Vull que introduïu el terminal Remix. Es troba sota l’editor de codi i aquí podeu fer un seguiment de totes les transaccions, per veure si s’executen o no amb èxit, per depurar-les, veure detalls (hash de transaccions, etc.) i molt més.

De moment, tenim dues transaccions reeixides. Un és el desplegament de contractes i ens costa ether (però no us preocupeu, ara som a l’editor, tot és virtual) i el segon és Call of our vista funció.

D’acord, tornem ara. Què passarà si anomenem ara la funció set?

Hem de passar un argument _message (“Hello World” per exemple) i prémer el botó transact per executar la funció. Podeu fer un seguiment de l’èxit de la transacció a Terminal.

Ara tornem a trucar a la funció get. Ara torna el nostre missatge.

Fem algunes millores al nostre codi. No vam inicialitzar el nostre missatge variable. Anem a fer-ho.

contracte MyFirstContract {

missatge de cadena = "Hola món!";

la funció get () retorna la vista pública (memòria de cadena) {

missatge de retorn;

}

conjunt de funcions (missatge de memòria de cadena) públic {

missatge = _messatge;

}

}

Tingueu en compte que ara el missatge és “Hola món!”, I quan cridem la funció get per primera vegada, no tornarà la cadena buida.

Per provar-ho, hem de compilar el nostre contracte (cmd / ctrl + S).

A continuació, torneu a desplegar-lo. Hem de crear una nova instància de contracte (a causa dels canvis que vam fer) i publicar-la a blockchain.

Només cal que suprimiu la versió anterior de l’editor (per descomptat, no de la nostra cadena de blocs virtual) i torneu a prémer el botó Implementa. Truquem ara a la nostra funció get.

Bonic! Anem a trucar a la funció de configuració ara.

I torna-ho.

Guai.

Ara fem que el nostre missatge sigui un constant.

El nostre codi ara:

solidesa del pragma ^ 0,5,0;

contracte MyFirstContract {

missatge constant de cadena = "Hola món!";

la funció get () retorna la vista pública (memòria de cadena) {

missatge de retorn;

}

conjunt de funcions (missatge de memòria de cadena) públic {

missatge = _messatge;

}

}

Quan intentem compilar-lo, obtenim un error en la nostra funció de conjunt. Això es deu al fet que no es pot canviar el valor d’una constant.

Ara ens eliminarem d’aquesta constant.

Inicialitzar variables com aquesta no és un error, però és molt millor si ho fem al constructor. Podeu escriure constructor a Solidity amb:

constructor () públic {

// fer quelcom…

}

Constructor és una altra funció que s’anomena durant el desplegament d’un contracte intel·ligent. El nostre codi té una aparença diferent, però funciona igual.

solidesa del pragma ^ 0,5,0;

contracte MyFirstContract {

missatge de cadena;

constructor () públic {

missatge = "Hola món!";

}

la funció get () retorna la vista pública (memòria de cadena) {

missatge de retorn;

}

conjunt de funcions (missatge de memòria de cadena) públic {

missatge = _messatge;

}

}

Podeu compilar-lo de nou i provar-lo si voleu.

Finalment, es pot canviar la visibilitat de les variables d’estat. Si feu que les vostres variables d’estat públic això vol dir que es poden reclamar els seus valors des de fora del contracte.

La solidesa farà que per a cada variable d’estat pública un mètode amb el mateix nom que es pugui anomenar com a funció normal (com la funció getter).

Això vol dir que podem desfer-nos de la nostra funció get, només hem de declarar com a missatge variable públic, i el nostre codi funcionarà igual, serà molt més net i ens costarà menys desplegar-lo un dia a la xarxa principal.

Com més gran sigui el codi, més gas es necessita per executar-lo i augmenta el cost d’executar la nostra dApp.

Quan desenvolupem contractes intel·ligents hem de ser:

  • eficient – La taxa de gas consumida ha de ser baixa
  • precís – Un cop implementeu el contracte intel·ligent, no es pot canviar i és públic les 24 hores del dia, cada 7 hores, cada línia de codi (imagineu-vos un pirata informàtic que trobi un error i pugui explotar la vostra dApp)

El nostre codi final d’avui té aquest aspecte:

solidesa del pragma ^ 0,5,0;

contracte MyFirstContract {

cadena de missatge públic;

constructor () públic {

missatge = "Hola món!";

}

conjunt de funcions (missatge de memòria de cadena) públic {

missatge = _messatge;

}

}

Desplegem-lo i provem-lo.

Podeu veure aquest botó de missatge. S’està creant perquè el nostre missatge de variable d’estat és públic.

Si anomenem això, ens hauria de retornar un valor que s’està inicialitzant a través del constructor (és a dir, “Hola món!”).

Bonic. Anem a provar la funció de conjunt ara.

Com aprendre la solidesa?

Solidity en si és un llenguatge bastant simple, però per ser un bon desenvolupador de Solidity cal entendre com funciona tot a Ethereum.

  • Solidity és un llenguatge de programació d’alt nivell amb una sintaxi similar a ECMAScript (javascript).
  • Compila a bytecode EVM, cosa que només l’EVM pot entendre.
  • El compilador es diu Solc.

Prenem aquest simple contracte com a exemple:

solidesa del pragma ^ 0,5,0;

Exemple de contracte {

uint a = 10 + 5;

}

Simple com això. Ara anem a compilar-lo. Si anem a Detalls del contracte a Terminal, podem veure molta informació.

En aquest cas, el codi compilat és:

0x6080604052600f600055348015601457600080fd5b5060358060226000396000f3fe6080604052600080fdfea165627a7a72305820bf75c57b7d8745a79baee513ead21a9eb8b075896f8e4c59

Aquests valors llargs són representació hexadecimal del contracte final, també conegut com a bytecode. EVM només entén el bytecode.

Però, si alguna cosa surt malament, ens quedem atrapats amb algun error, per exemple, no es pot depurar un bytecode.

Codis d’opció

L’idioma que apareix a sobre del codi de bytes és l’opcode. Opcode és un llenguatge de programació de baix nivell. Solidity i Opcode són com C i Language Assembly per exemple.

Per tant, quan hem de depurar alguna transacció fallida, depurem el codi opcional.

Una cosa que heu de saber sobre Solidity i depuració: és molt difícil. Però no és impossible, així que ens endinsem en això.

Aquest és l’opcode del nostre contracte d’exemple:

0 PUSH1 60

02 PUSH1 40

04 MSTORE

05 PUSH1 0f

07 PUSH1 00

09 SSTORE

10 CALOR

11 DUP1

12 ISZERO

13 PUSH1 14

15 JUMPI

16 PUSH1 00

18 DUP1

19 REVERTIR

20 JUMPDEST

21 POP

22 PUSH1 35

24 DUP1

25 PUSH1 22

27 PUSH1 00

29 CODECOPPIA

30 PUSH1 00

32 TORNADA

33 INVÀLID

34 PUSH1 80

36 PUSH1 40

38 MSTORE

39 PUSH1 00

41 DUP1

42 REVERTIR

43 INVÀLID

44 LOG1

45 PUSH6 627a7a723058

52 SHA3

53 INVÀLID

54 PUSH22 c57b7d8745a79baee513ead21a9eb8b075896f8e4c59

77 INVÀLID

78 DUP10

79 I

80 JUMPI

81 INVÀLID

82 EQUILIBRI

83 PUSH29 750029

Els codis d’opció són les instruccions legibles del programa de baix nivell. Tots els codis opcionals tenen les seves contraparts hexadecimals, per exemple MSTORE és 0x52.

L’EVM és Stack Machine. Es basa en l’estructura LIFO (Last In First Out). Per simplificar-ho, imagineu-vos apilant llesques de pa al microones, la DARRERA llesca que poseu és la PRIMERA que traieu.

En aritmètica normal, escrivim la nostra equació d’aquesta manera:

10 + 2 * 2

i la resposta és 14, perquè fem multiplicacions abans de la suma.

En una màquina d’apilament, funciona segons el principi LIFO:

2 2 * 10 +

Vol dir, posar 2 a la pila primer, seguit per un altre 2, seguit per una acció de multiplicació. El resultat és 4 asseguts a la part superior de la pila. Ara afegiu un número 10 a sobre de 4 i, finalment, afegiu els 2 números junts. El valor final de la pila esdevé 14.

L’acte de posar dades a la pila s’anomena instrucció PUSH i l’acció d’eliminar dades de la pila s’anomena instrucció POP. És obvi que l’opcode més comú que veiem al nostre exemple anterior és PUSH1, que significa posar 1 byte de dades a la pila.

Per tant, aquesta instrucció:

PUSH1 0x60

significa posar un valor d’1 byte de “0x60” a la pila. Casualment, el valor hexadecimal de PUSH1 també és “0x60”. Eliminant el “0x” no obligatori, podríem escriure aquesta lògica en bytecode com a “6060”.

Anem una mica més enllà.

PUSH1 0x60 PUSH1 0x40 MSTORE

El MSTORE (0x52) té 2 entrades i no produeix cap sortida. Els codis d’opció anteriors signifiquen:

PUSH1 (0x60): posa 0x60 a la pila.

PUSH1 (0x40): posa 0x40 a la pila.

MSTORE (0x52): assigneu 0x60 d’espai de memòria i moveu-vos a la posició 0x40.

El codi byt resultant és:

6060604052

De fet, sempre veiem aquest número màgic “6060604052” al començament de qualsevol codi byt de solidesa perquè és com arrenca el contracte intel·ligent.

Per complicar encara més l’assumpte, 0x40 o 0x60 no es pot interpretar com el nombre real 40 o 60. Com que són hexadecimals, 40 equival a 64 (16¹ x 4) i 60 equival a 96 (16¹ x 6) en decimal.

En resum, el que està fent “PUSH1 0x60 PUSH1 0x40 MSTORE” és assignar 96 bytes de memòria i moure el punter al començament del 64th byte. Ara tenim 64 bytes per a espai de zero i 32 bytes per a emmagatzematge temporal de memòria.

A EVM, hi ha 3 llocs per emmagatzemar dades. En primer lloc, a la pila. Acabem d’utilitzar el codi d’opció PUSH per emmagatzemar-hi dades segons l’exemple anterior.

En segon lloc, a la memòria (RAM) on fem servir el codi d’opció MSTORE i, finalment, a l’emmagatzematge en disc on fem servir SSTORE per emmagatzemar les dades. El gas necessari per emmagatzemar dades és el més car i emmagatzemar dades per apilar és el més barat.

Ara és bon moment per tornar al nostre codi Solidity d’aquest tutorial i recuperar el que hem après sobre la paraula reservada memòria i com el compilador ens obliga a especificar com emmagatzemem les cadenes, per exemple.

Només hem tractat els conceptes bàsics del bytecode i alguns codis d’opció.

No necessitem conèixer codis d’opció per començar a escriure un contracte intel·ligent!

D’altra banda, la gestió d’errors EVM continua sent molt primitiva i és útil examinar els codis d’opció quan les coses van malament..

Conclusió

Aquesta primera lliçó té una mica més de teoria que la codificació real, però és molt important per als principiants saber com funcionen les coses a Ethereum. En els propers tutorials, escriurem un codi més interessant i aprendrem a desplegar el nostre propi testimoni a la cadena de blocs d’Ethereum.

Fins llavors &# 128075;

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