Linguaggi degli Smart Contract
Uno degli aspetti positivi di Ethereum è che gli Smart Contract possono essere programmati utilizzando linguaggi relativamente comodi per gli sviluppatori. Se hai esperienza con Python o JavaScript, puoi trovare un linguaggio con una sintassi che conosci.
I due linguaggi più attivi e gestiti sono:
- Solidity
- Vyper
Gli sviluppatori più esperti potrebbero prendere in considerazione anche Yul, un linguaggio intermedio per la macchina virtuale Ethereum, oppure Yul +, un'estensione di Yul.
Prerequisiti
Una conoscenza dei linguaggi di programmazione, in particolare di JavaScript o Python, può aiutarti a capire le differenze nei linguaggi degli Smart Contract. Ti consigliamo inoltre di approfondire la conoscenza del concetto di Smart Contract prima di passare ai confronti tra linguaggi. Introduzione agli Smart Contract.
Solidity
- Influenzato da C++, Python e JavaScript.
- Statico (il tipo di una variabile è noto al momento della compilazione).
- Supporta:
- Ereditarietà (è possibile estendere altri contratti).
- Librerie (è possibile creare codice riutilizzabile che può essere chiamato da contratti diversi, come le funzioni statiche in una classe statica in altri linguaggi di programmazione orientati agli oggetti).
- Tipi di dati complessi definiti dall'utente.
Link importanti
- Documentazione
- Solidity Language Portal
- Solidity by Example
- GitHub
- Solidity Gitter Chatroom
- Cheat Sheet
- Solidity Blog
Esempio di contratto
1// SPDX-License-Identifier: GPL-3.02pragma solidity >= 0.7.0;34contract Coin {5 // La parola chiave "public" rende le variabili6 // accessibili da altri contratti7 address public minter;8 mapping (address => uint) public balances;910 // Gli eventi consentono ai client di reagire a specifiche11 // modifiche ai contratti che vengono dichiarate12 event Sent(address from, address to, uint amount);1314 // Il codice del costruttore viene eseguito solo quando il contratto15 // viene creato16 constructor() {17 minter = msg.sender;18 }1920 // Invia una quantità di monete appena create a un indirizzo21 // Può essere chiamato solo dal creatore del contratto22 function mint(address receiver, uint amount) public {23 require(msg.sender == minter);24 require(amount < 1e60);25 balances[receiver] += amount;26 }2728 // Invia una quantità di monete esistenti29 // da qualsiasi chiamante a un indirizzo30 function send(address receiver, uint amount) public {31 require(amount <= balances[msg.sender], "Insufficient balance.");32 balances[msg.sender] -= amount;33 balances[receiver] += amount;34 emit Sent(msg.sender, receiver, amount);35 }36}37Mostra tuttoCopia
Questo esempio dà un'idea della sintassi di un contratto in Solidity. Per una descrizione più dettagliata di funzioni e variabili, consulta la documentazione.
Vyper
- Linguaggio di programmazione Pythonic
- Tipizzazione forte
- Codice del compilatore contenuto e comprensibile
- Ha volutamente meno funzionalità di Solidity con l'obiettivo di rendere i contratti più sicuri e più facili da controllare. Vyper non supporta:
- Modificatori
- Ereditarietà
- Assembly inline
- Overloading delle funzioni
- Overloading degli operatori
- Chiamate ricorsive
- Cicli di lunghezza infinita
- Punti fissi binari
Per ulteriori informazioni, consulta la logica Vyper.
Link importanti
Esempio
1# Apertura asta23# Parametri d'asta4# Il beneficiario riceve denaro dal miglior offerente5beneficiary: public(address)6auctionStart: public(uint256)7auctionEnd: public(uint256)89# Stato attuale dell'asta10highestBidder: public(address)11highestBid: public(uint256)1213# Imposta a true alla fine per non permettere più modifiche14ended: public(bool)1516# Tiene traccia delle offerte rimborsate in modo da poter seguire il modello di prelievo17pendingReturns: public(HashMap[address, uint256])1819# Crea una semplice asta con `_bidding_time`20# tempo di offerta in secondi per conto21# dell'indirizzo del beneficiario `_beneficiary`.22@external23def __init__(_beneficiary: address, _bidding_time: uint256):24 self.beneficiary = _beneficiary25 self.auctionStart = block.timestamp26 self.auctionEnd = self.auctionStart + _bidding_time2728# Offerta sull'asta con il valore inviato29# insieme a questa transazione.30# Il valore sarà rimborsato solo se l'asta31# non viene vinta.32@external33@payable34def bid():35 # Controlla se il periodo di offerta è finito.36 assert block.timestamp < self.auctionEnd37 # Verifica se l'offerta è abbastanza alta38 assert msg.value > self.highestBid39 # Tiene traccia del rimborso all'offerente più alto precedente40 self.pendingReturns[self.highestBidder] += self.highestBid41 # Tiene traccia della nuova offerta più alta42 self.highestBidder = msg.sender43 self.highestBid = msg.value4445# Preleva un'offerta precedentemente rimborsata. Il modello di prelievo è46# utilizzato qui per evitare un problema di sicurezza. Se i rimborsi venissero inviati direttamente47# come parte di bid(), un contratto di offerta malevolo potrebbe bloccarli48# e quindi bloccare le nuove offerte più alte in arrivo.49@external50def withdraw():51 pending_amount: uint256 = self.pendingReturns[msg.sender]52 self.pendingReturns[msg.sender] = 053 send(msg.sender, pending_amount)5455# Termina l'asta e invia l'offerta più alta56# al beneficiario.57@external58def endAuction():59 # È buona abitudine strutturare le funzioni che interagiscono60 # con altri contratti (cioè chiamano funzioni o inviano Ether)61 # in tre fasi:62 # 1. controllo delle condizioni63 # 2. esecuzione delle azioni (potenzialmente modificando le condizioni)64 # 3. interazione con altri contratti65 # Se queste fasi sono mischiate, l'altro contratto potrebbe eseguire66 # nuove chiamate al contratto corrente e modificare lo stato o causare67 # effetti (pagamento di ether) da eseguire più volte.68 # Se le funzioni chiamate internamente includono l'interazione con contratti esterni69 # devono essere considerate anche interazioni con70 # contratti esterni.7172 # 1. Condizioni73 # Controlla se la fine dell'asta è stata raggiunta74 assert block.timestamp >= self.auctionEnd75 # Verifica se questa funzione è già stata chiamata76 assert not self.ended7778 # 2. Effetti79 self.ended = True8081 # 3. Interazione82 send(self.beneficiary, self.highestBid)83Mostra tuttoCopia
Questo esempio dovrebbe dare un'idea della sintassi di un contratto in Vyper. Per una descrizione più dettagliata di funzioni e variabili, consulta la documentazione.
Yul e Yul+
Se non hai esperienza con Ethereum e non hai ancora usato i linguaggi degli Smart Contract, consigliamo di iniziare con Solidity o Vyper. Prendi in considerazione Yul o Yul+ solo quando hai acquisito familiarità con le best practice di sicurezza per gli Smart Contract e le specifiche per l'utilizzo dell'EVM.
Yul
- Linguaggio di livello intermedio per Ethereum.
- Supporta l'EVM e eWASM, un WebAssembly per Ethereum ed è progettato per essere un denominatore comune utilizzabile per entrambe le piattaforme.
- Buona soluzione per le fasi di ottimizzazione di alto livello che possono essere utili per entrambe le piattaforme, EVM ed eWASM.
Yul+
- Un'estensione a Yul molto efficiente e di basso livello.
- Inizialmente progettata per un contratto optimistic rollup.
- Yul+ può essere considerato come una proposta di upgrade sperimentale a Yul che aggiunge nuove funzionalità.
Link importanti
Esempio di contratto
Il seguente esempio semplice implementa una funzione di alimentazione. Può essere compilato usando solc --strict-assembly --bin input.yul
. L'esempio deve essere incluso nel file input.yul.
1{2 function power(base, exponent) -> result3 {4 switch exponent5 case 0 { result := 1 }6 case 1 { result := base }7 default8 {9 result := power(mul(base, base), div(exponent, 2))10 if mod(exponent, 2) { result := mul(base, result) }11 }12 }13 let res := power(calldataload(0), calldataload(32))14 mstore(0, res)15 return(0, 32)16}17Mostra tutto
Se hai già una buona esperienza con gli Smart Contract, un'implementazione completa di ERC20 in Yul è disponibile qui.
Come scegliere
Come avviene con qualsiasi altro linguaggio di programmazione, si tratta principalmente di scegliere lo strumento giusto per l'operazione da svolgere, in base alle preferenze personali.
Ecco alcuni aspetti da considerare se non hai ancora provato nessun linguaggio:
Quali vantaggi offre Solidity?
- Se non hai esperienza, sono disponibili molti tutorial e strumenti d'apprendimento. Scopri di più nella sezione Impara scrivendo codice.
- Disponibilità di buoni strumenti per gli sviluppatori.
- Solidity ha un'estesa community di sviluppatori, e quindi probabilmente troverai risposte alle tue domande abbastanza rapidamente.
Quali vantaggi offre Vyper?
- Ottimo modo per iniziare per gli sviluppatori di Python che vogliono scrivere Smart Contract.
- Vyper ha un numero minore di funzionalità che lo rendono perfetto per la prototipazione rapida di idee.
- Vyper vuole facilitare l'audit del codice ed essere leggibile il più possibile.
Quali vantaggi offrono Yul e Yul+?
- Linguaggio di basso livello semplicistico e funzionale.
- Consente di avvicinarsi all'EVM grezza, cosa che può aiutare a ottimizzare l'uso del carburante da parte dei contratti.
Confronto tra linguaggi
Per confrontare sintassi di base, ciclo di vita del contratto, interfacce, operatori, strutture di dati, funzioni, flusso di controllo e altro, consulta questo contenuto riassuntivo di Auditless