Linguaggi per gli smart contract
Un aspetto fantastico di Ethereum è che gli smart contract possono essere programmati usando linguaggi relativamente facili per gli sviluppatori. Se hai esperienza con Python o con qualsiasi linguaggio a parentesi graffe (opens in a new tab), puoi trovare un linguaggio con una sintassi familiare.
I due linguaggi più attivi e mantenuti sono:
- Solidity
- Vyper
L'IDE Remix fornisce un ambiente di sviluppo completo per creare e testare contratti sia in Solidity che in Vyper. Prova l'IDE Remix nel browser (opens in a new tab) per iniziare a programmare.
Gli sviluppatori più esperti potrebbero anche voler usare Yul, un linguaggio intermedio per la Ethereum Virtual Machine, o Yul+, un'estensione di Yul.
Se sei curioso e ti piace aiutare a testare nuovi linguaggi che sono ancora in forte sviluppo, puoi sperimentare con Fe, un linguaggio emergente per gli smart contract che è attualmente ancora agli inizi.
Prerequisiti
Una conoscenza pregressa dei linguaggi di programmazione, specialmente di JavaScript o Python, può aiutarti a comprendere le differenze nei linguaggi per gli smart contract. Ti consigliamo inoltre di comprendere gli smart contract come concetto prima di addentrarti troppo nei confronti tra i linguaggi. Introduzione agli smart contract.
Solidity
- Linguaggio ad alto livello orientato agli oggetti per l'implementazione di smart contract.
- Linguaggio a parentesi graffe che è stato profondamente influenzato dal C++.
- Tipizzato staticamente (il tipo di una variabile è noto in fase di compilazione).
- Supporta:
- Ereditarietà (puoi estendere altri contratti).
- Librerie (puoi creare codice riutilizzabile che puoi chiamare da contratti diversi, come le funzioni statiche in una classe statica in altri linguaggi di programmazione orientati agli oggetti).
- Tipi complessi definiti dall'utente.
Link importanti
- Documentazione (opens in a new tab)
- Portale del linguaggio Solidity (opens in a new tab)
- Solidity by Example (opens in a new tab)
- GitHub (opens in a new tab)
- Chatroom Gitter di Solidity (opens in a new tab) collegata alla Chatroom Matrix di Solidity (opens in a new tab)
- Cheat Sheet (opens in a new tab)
- Blog di Solidity (opens in a new tab)
- Twitter di Solidity (opens in a new tab)
Contratto di esempio
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.7.0;
contract Coin {
// La parola chiave "public" rende le variabili
// accessibili da altri contratti
address public minter;
mapping (address => uint) public balances;
// Gli eventi permettono ai client di reagire a specifiche
// modifiche del contratto che dichiari
event Sent(address from, address to, uint amount);
// Il codice del costruttore viene eseguito solo quando il contratto
// viene creato
constructor() {
minter = msg.sender;
}
// Invia una quantità di monete appena create a un indirizzo
// Può essere chiamato solo dal creatore del contratto
function mint(address receiver, uint amount) public {
require(msg.sender == minter);
require(amount < 1e60);
balances[receiver] += amount;
}
// Invia una quantità di monete esistenti
// da qualsiasi chiamante a un indirizzo
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Insufficient balance.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}
Questo esempio dovrebbe darti un'idea di come sia la sintassi di un contratto in Solidity. Per una descrizione più dettagliata delle funzioni e delle variabili, consulta la documentazione (opens in a new tab).
Vyper
- Linguaggio di programmazione pythonico
- Tipizzazione forte
- Codice del compilatore ridotto e comprensibile
- Generazione efficiente del bytecode
- Ha deliberatamente meno funzionalità rispetto a Solidity con l'obiettivo di rendere i contratti più sicuri e facili da verificare. Vyper non supporta:
- Modificatori
- Ereditarietà
- Assembly inline
- Overloading delle funzioni
- Overloading degli operatori
- Chiamate ricorsive
- Cicli di lunghezza infinita
- Punti fissi binari
Per maggiori informazioni, leggi la logica di Vyper (opens in a new tab).
Link importanti
- Documentazione (opens in a new tab)
- Vyper by Example (opens in a new tab)
- Altro su Vyper by Example (opens in a new tab)
- GitHub (opens in a new tab)
- Chat Discord della community di Vyper (opens in a new tab)
- Cheat Sheet (opens in a new tab)
- Framework e strumenti di sviluppo di smart contract per Vyper
- VyperPunk: impara a proteggere e hackerare gli smart contract in Vyper (opens in a new tab)
- Vyper Hub per lo sviluppo (opens in a new tab)
- I migliori esempi di smart contract in Vyper (opens in a new tab)
- Risorse curate Awesome Vyper (opens in a new tab)
Esempio
# Asta aperta
# Parametri dell'asta
# Il beneficiario riceve denaro dal miglior offerente
beneficiary: public(address)
auctionStart: public(uint256)
auctionEnd: public(uint256)
# Stato attuale dell'asta
highestBidder: public(address)
highestBid: public(uint256)
# Impostato su true alla fine, non consente alcuna modifica
ended: public(bool)
# Tiene traccia delle offerte rimborsate in modo da poter seguire il pattern di prelievo
pendingReturns: public(HashMap[address, uint256])
# Crea una semplice asta con `_bidding_time`
# secondi di tempo per le offerte per conto dell'
# indirizzo del beneficiario `_beneficiary`.
@external
def __init__(_beneficiary: address, _bidding_time: uint256):
self.beneficiary = _beneficiary
self.auctionStart = block.timestamp
self.auctionEnd = self.auctionStart + _bidding_time
# Fai un'offerta all'asta con il valore inviato
# insieme a questa transazione.
# Il valore verrà rimborsato solo se l'
# asta non viene vinta.
@external
@payable
def bid():
# Controlla se il periodo per le offerte è terminato.
assert block.timestamp < self.auctionEnd
# Controlla se l'offerta è abbastanza alta
assert msg.value > self.highestBid
# Tieni traccia del rimborso per il precedente miglior offerente
self.pendingReturns[self.highestBidder] += self.highestBid
# Tieni traccia della nuova offerta più alta
self.highestBidder = msg.sender
self.highestBid = msg.value
# Preleva un'offerta precedentemente rimborsata. Il pattern di prelievo è
# usato qui per evitare un problema di sicurezza. Se i rimborsi fossero direttamente
# inviati come parte di bid(), un contratto di offerta malevolo potrebbe bloccare
# quei rimborsi e quindi bloccare l'arrivo di nuove offerte più alte.
@external
def withdraw():
pending_amount: uint256 = self.pendingReturns[msg.sender]
self.pendingReturns[msg.sender] = 0
send(msg.sender, pending_amount)
# Termina l'asta e invia l'offerta più alta
# al beneficiario.
@external
def endAuction():
# È una buona linea guida strutturare le funzioni che interagiscono
# con altri contratti (cioè, chiamano funzioni o inviano ether)
# in tre fasi:
# 1. controllo delle condizioni
# 2. esecuzione delle azioni (potenzialmente modificando le condizioni)
# 3. interazione con altri contratti
# Se queste fasi vengono mescolate, l'altro contratto potrebbe richiamare
# il contratto corrente e modificare lo stato o causare
# l'esecuzione multipla di effetti (pagamento di ether).
# Se le funzioni chiamate internamente includono l'interazione con
# contratti esterni, devono anch'esse essere considerate interazioni con
# contratti esterni.
# 1. Condizioni
# Controlla se l'ora di fine dell'asta è stata raggiunta
assert block.timestamp >= self.auctionEnd
# Controlla se questa funzione è già stata chiamata
assert not self.ended
# 2. Effetti
self.ended = True
# 3. Interazione
send(self.beneficiary, self.highestBid)
Questo esempio dovrebbe darti un'idea di come sia la sintassi di un contratto in Vyper. Per una descrizione più dettagliata delle funzioni e delle variabili, consulta la documentazione (opens in a new tab).
Yul e Yul+
Se sei nuovo su Ethereum e non hai ancora programmato con i linguaggi per gli smart contract, ti consigliamo di iniziare con Solidity o Vyper. Esamina Yul o Yul+ solo quando avrai familiarità con le migliori pratiche di sicurezza degli smart contract e con le specifiche del lavoro con la EVM.
Yul
- Linguaggio intermedio per Ethereum.
- Supporta la EVM ed Ewasm (opens in a new tab), un WebAssembly in stile Ethereum, ed è progettato per essere un denominatore comune utilizzabile per entrambe le piattaforme.
- Ottimo target per le fasi di ottimizzazione ad alto livello che possono avvantaggiare equamente sia le piattaforme EVM che Ewasm.
Yul+
- Un'estensione di Yul a basso livello e altamente efficiente.
- Inizialmente progettato per un contratto di rollup ottimistico.
- Yul+ può essere considerato come una proposta di aggiornamento sperimentale per Yul, aggiungendovi nuove funzionalità.
Link importanti
- Documentazione di Yul (opens in a new tab)
- Documentazione di Yul+ (opens in a new tab)
- Post introduttivo su Yul+ (opens in a new tab)
Contratto di esempio
Il seguente semplice esempio implementa una funzione di potenza. Può essere compilato usando solc --strict-assembly --bin input.yul. L'esempio dovrebbe essere salvato nel file input.yul.
{
function power(base, exponent) -> result
{
switch exponent
case 0 { result := 1 }
case 1 { result := base }
default
{
result := power(mul(base, base), div(exponent, 2))
if mod(exponent, 2) { result := mul(base, result) }
}
}
let res := power(calldataload(0), calldataload(32))
mstore(0, res)
return(0, 32)
}
Se hai già molta esperienza con gli smart contract, puoi trovare un'implementazione completa di ERC-20 in Yul qui (opens in a new tab).
Fe
- Linguaggio tipizzato staticamente per la Ethereum Virtual Machine (EVM).
- Ispirato a Python e Rust.
- Mira a essere facile da imparare, anche per gli sviluppatori che sono nuovi nell'ecosistema di Ethereum.
- Lo sviluppo di Fe è ancora nelle sue fasi iniziali, il linguaggio ha avuto la sua versione alpha a gennaio 2021.
Link importanti
- GitHub (opens in a new tab)
- Annuncio di Fe (opens in a new tab)
- Roadmap di Fe del 2021 (opens in a new tab)
- Chat Discord di Fe (opens in a new tab)
- Twitter di Fe (opens in a new tab)
Contratto di esempio
Di seguito è riportato un semplice contratto implementato in Fe.
type BookMsg = bytes[100]
contract GuestBook:
pub guest_book: map<address, BookMsg>
event Signed:
book_msg: BookMsg
pub def sign(book_msg: BookMsg):
self.guest_book[msg.sender] = book_msg
emit Signed(book_msg=book_msg)
pub def get_msg(addr: address) -> BookMsg:
return self.guest_book[addr].to_mem()
Come scegliere
Come per qualsiasi altro linguaggio di programmazione, si tratta principalmente di scegliere lo strumento giusto per il lavoro giusto, oltre che di preferenze personali.
Ecco alcune cose da considerare se non hai ancora provato nessuno dei linguaggi:
Cosa c'è di fantastico in Solidity?
- Se sei un principiante, ci sono molti tutorial e strumenti di apprendimento in circolazione. Scopri di più nella sezione Imparare programmando.
- Sono disponibili ottimi strumenti per gli sviluppatori.
- Solidity ha una grande community di sviluppatori, il che significa che molto probabilmente troverai risposte alle tue domande abbastanza rapidamente.
Cosa c'è di fantastico in Vyper?
- Ottimo modo per iniziare per gli sviluppatori Python che vogliono scrivere smart contract.
- Vyper ha un numero minore di funzionalità, il che lo rende ottimo per la prototipazione rapida di idee.
- Vyper mira a essere facile da verificare e il più leggibile possibile per gli esseri umani.
Cosa c'è di fantastico in Yul e Yul+?
- Linguaggio a basso livello semplicistico e funzionale.
- Permette di avvicinarsi molto di più alla EVM pura, il che può aiutare a ottimizzare l'utilizzo di gas dei tuoi contratti.
Confronti tra i linguaggi
Per confronti sulla sintassi di base, il ciclo di vita del contratto, le interfacce, gli operatori, le strutture dati, le funzioni, il flusso di controllo e altro ancora, dai un'occhiata a questo cheatsheet di Auditless (opens in a new tab)