Smart Contract Ethereum con Solidity
Stanno sempre più prendendo piede i contratti intelligenti legati alla blockchain. Vediamo insieme di cosa si tratta.

Negli ultimi anni l’uso di smart contract sta crescendo di pari passo con l’evoluzione della tecnologia blockchain, infatti, lo sviluppo di quest'ultima ha gettato le basi per la creazione di applicazioni personalizzate in svariati settori di mercato.
Naturalmente, di pari passo all'uso, è in costante aggiornamento anche lo sviluppo ed il testing di smart contract, che è vincolato all’utilizzo di Solidity.
Cos’è uno Smart Contract?
Come ogni altro contratto, anche lo smart contract regola i termini e le condizioni di un accordo tra le parti: i termini sono eseguiti sulla base di un codice che è programmato su blockchain, come Ethereum.
Trattandosi quindi di un programma che è archiviato all’interno della blockchain, possiamo quindi definire uno smart contract come un’estensione della blockchain in accordo tra le parti.
Gli smart contract sono utilizzati e utilizzabili in ogni ambito, vengono eseguiti automaticamente, attivano transazioni di stato e richiamano funzioni.
Possono definire:
- regole
- requisiti
- ricompense per i partecipanti
- modalità di trasferimento degli asset tra le parti
Ogni smart contract è identificato, in modo univoco, da un indirizzo di 20 byte. Sono, quindi, ideali per la blockchain in quanto consentono a persone che non si conoscono di svolgere delle attività, secondo le specifiche, in modo sicuro e senza bisogno di intermediari.
Di seguito troviamo alcuni vantaggi che caratterizzano gli smart contract:
- Trasparenza: gli utenti del blockchain possono leggere gli smart contract e accedervi tramite API.
- Immutabilità: l'esecuzione degli smart contract crea log che non possono essere modificati.
- Distribuzione: l'output del contratto viene convalidato e verificato da nodi sulla rete. Gli stati del contratto possono essere resi visibili pubblicamente e in alcuni casi sono visibili anche le variabili "private".
I casi d’uso degli smart contract
Come accennato prima, i campi di applicazione degli smart contract possono essere numerosi.
Vediamone alcuni:
- Assicurazione – In campo assicurativo, all’insorgere di specifici eventi, gli smart contract attivano automaticamente, ad esempio, un reclamo, semplificando e rendendo più agile l'elaborazione dei reclami. Per determinare l'indennizzo che verrà riconosciuto agli utenti, è quindi possibile registrare i dettagli dei reclami nella blockchain. Questa funzionalità può ridurre i tempi di elaborazione e le percentuali di errore umano.
- Operazioni di voto - Gli smart contract possono contribuire a rendere le operazioni di voto automatiche e trasparenti. Ogni contratto rappresenta un unico scrutinio, che corrisponde all'identità di un elettore. Poiché un blockchain è immutabile i voti non possono essere manomessi.
- Catena di montaggio – All’interno di una catena di montaggio, gli smart contract possono registrare la proprietà della merce e verificare in qualsiasi momento il responsabile di un prodotto. Es. se un operaio della catena di montaggio non riesce a consegnare in tempo, tutte le altre parti sanno dove si è verificato il problema.
- Archiviazione di record – Sono molti i settori che possono usufruire degli smart contract per migliorare la velocità e la sicurezza dell'archiviazione dei record. La tecnologia blockchain può essere usata per digitalizzare i record e per crittografarli e archiviarli in modo sicuro, inoltre è possibile rendere l’accesso controllato e concesso solamente a persone autorizzate,
- Titolarità della proprietà - Gli smart contract possono registrare il titolare di una proprietà e contribuiscono anche a facilitare il trasferimento della proprietà in modo tempestivo e sicuro.
Ethereum, Solidity e gli smart contract
Come accennato poco fa, gli smart contract sono comunemente usati con Ethereum. Ma... cos'è ethereum?
Ethereum è una piattaforma basata su tecnologia blockchain open source, per cui, le operazioni realizzate vengono memorizzate in un registro pubblico. Gli utenti della rete possono creare, pubblicare, monetizzare e usare una vasta gamma di applicazioni decentralizzate con supporto per un linguaggio di programmazioneTuring-complete: Solidity.
Per ogni operazione di scrittura effettuata sulla blockchain è necessario pagare ether, ETH (Gas), la "benzina" della piattaforma che consente l'esecuzione degli smart contract.
Come abbiamo introdotto prima, Solidity è il linguaggio di programmazione Turing completo, che consente di scrivere contratti complessi, ma con modalità di definizione e codifica semplici e chiare.
Solidity è ispirato ai linguaggi di programmazione Javascript, C++ e Python, di cui ritroviamo alcune sintassi.
Poiché, come abbiamo detto prima, ogni transizione di stato viene registrata e non è modificabile, sarà necessario testare accuratamente il contratto prima di rilasciarlo in un ambiente di produzione. Le correzioni di bug possono essere costose e causare anche danni critici al sistema.
Vediamo come funziona la scrittura di un contratto.
Scrittura di un contratto
Prerequisiti
Per la realizzazione di un primo prototipo d’esempio ci affideremo ad alcuni tool:
- Visual Studio Code (https://code.visualstudio.com/)
- Kit di sviluppo Blockchain per Ethereum (https://marketplace.visualstudio.com/items?itemName=AzBlockchain.azure-blockchain)
- Truffle (https://trufflesuite.com/truffle/) - Framework di sviluppo per Ethereum
- Ganache (https://trufflesuite.com/ganache/) - Blockchain Ethereum locale
Truffle
Truffle è il framework di sviluppo più diffuso per Ethereum.
Truffle offre i seguenti vantaggi:
- Creazione, compilazione, distribuzione e test di contratti intelligenti
- Gestione della rete per la distribuzione in reti pubbliche e private
- Gestione dei pacchetti per le dipendenze del progetto
- Console interattiva per la comunicazione diretta e la gestione dei contratti
- Pipeline di compilazione configurabile per l'esecuzione automatica dei controlli e la configurazione dei progetti
Creazione nuovo progetto
Una volta installata l’estensione Kit di sviluppo Blockchain per Ethereum sarà possibile tramite il Riquadro comandi… (su mac cmd+shift+p), cercando > Blockchain: New Solidity Project, creare un nuovo progetto Blockchain.
Dopo la creazione, il progetto includerà il boilerplate di Solidity, nella fattispecie:
- contracts: contiene i contratti HelloBlockchain.sol e Migrations.sol
- migrations: contiene una migrazione iniziale e un contratto di distribuzione
- test: contiene un test per il contratto HelloBlockchain scritto in JavaScript
Sono presenti anche alcuni file di configurazione:
- package.json: definisce i dettagli e le dipendenze del progetto
- truffle-config.json: definisce le dipendenze e la configurazione per Truffle
Compilazione contratti
NB. prima di poter compilare, deployare o testare un contratto è necessario avviare il server locale attraverso ganache-cli
Deploy contratti
Una volta che un contratto è stato compilato con successo si può passare al deploy dello stesso localmente.
A fine distribuzione del contratto vengono visualizzate alcune informazioni chiave o metadati:
- Indirizzo del contratto.
- Timestamp del blocco di cui fa parte la transazione di creazione del contratto.
- Indirizzo dell'account che ha distribuito il contratto.
- Saldo (in ether) dopo la transazione. Il saldo è 100 ETH (il valore predefinito iniziale) meno il costo totale.
- Quantità di gas usata e prezzo per gas. Gas indica il corrispettivo necessario per portare a termine una transazione o per eseguire un contratto sulla piattaforma blockchain Ethereum. È paragonabile al carburante necessario per usare la propria auto. Costo totale = prezzo per gas * uso di gas.
Test contratti
Per avviare la suite di test di un contratto basterà lanciare il comando truffle test
Creazione contratto
Proviamo a replicare le transizioni di stato di una spedizione creando
un nuovo contratto.
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.22 <0.8.12;
contract Shipping
{
// Our predefined values for shipping listed as enums
enum ShippingStatus { Pending, Shipped, Delivered }
// Save enum ShippingStatus in variable status
ShippingStatus private status;
// Event to launch when package has arrived
event LogNewAlert(string description);
// This initializes our contract state (sets enum to Pending once the program starts)
constructor() public {
status = ShippingStatus.Pending;
}
// Function to change to Shipped
function Shipped() public {
status = ShippingStatus.Shipped;
emit LogNewAlert("Your package has been shipped");
}
// Function to change to Delivered
function Delivered() public {
status = ShippingStatus.Delivered;
emit LogNewAlert("Your package has arrived");
}
// Function to get the status of the shipping
function getStatus(ShippingStatus _status) internal pure returns (string memory) {
// Check the current status and return the correct name
if (ShippingStatus.Pending == _status) return "Pending";
if (ShippingStatus.Shipped == _status) return "Shipped";
if (ShippingStatus.Delivered == _status) return "Delivered";
}
// Get status of your shipped item
function Status() public view returns (string memory) {
ShippingStatus _status = status;
return getStatus(_status);
}
}
Creazione migration
Una volta buildato il contratto e verificata la sintassi, possiamo procedere con la creazione di una nuova migrazione.
const Shipping = artifacts.require("Shipping");
module.exports = function (deployer) {
deployer.deploy(Shipping);
};
Eseguiamo il deploy tramite la nuova migrazione
Creazione test
Usando truffle scriviamo una suite di test per il contratto Shipping. Lanciando il comando truffle create test Shipping verrà generato un nuovo test che andremo ad estendere così
const ShippingStatus = artifacts.require("Shipping");
const truffleAssert = require('truffle-assertions');
/*
* uncomment accounts to access the test accounts made available by the
* Ethereum client
* See docs: https://www.trufflesuite.com/docs/truffle/testing/writing-tests-in-javascript
*/
contract("Shipping", function (/* accounts */) {
it("should return the status Pending", async ()=> {
// Instance of our deployed contract
const instance = await ShippingStatus.deployed();
// Checking the initial status in our contract
const status = await instance.Status();
// Checking if the status is initially Pending as set in the constructor
assert.equal(status, "Pending");
});
it("should return the status Shipped", async ()=> {
// Instance of our deployed contract
const instance = await ShippingStatus.deployed();
// Calling the Shipped() function
await instance.Shipped();
// Checking the initial status in our contract
const status = await instance.Status();
// Checking if the status is Shipped
assert.equal(status, "Shipped");
});
it("should return the status Delivered", async ()=> {
// Instance of our deployed contract
const instance = await ShippingStatus.deployed();
// Calling the Shipped() function
await instance.Delivered();
// Checking the initial status in our contract
const status = await instance.Status();
// Checking if the status is Delivered
assert.equal(status, "Delivered");
});
});
Se volessimo testare gli eventi
it('should return correct event description', async()=>{
// Instance of our deployed contract
const instance = await ShippingStatus.deployed();
// Calling the Delivered() function
const delivered = await instance.Delivered();
// Check event description is correct
truffleAssert.eventEmitted(delivered, 'LogNewAlert', (event) =>{
return event.description == 'Your package has arrived';
});
});
Realizziamo qualcosa di straordinario insieme!
Siamo consulenti prima che partner, scrivici per sapere quale soluzione si adatta meglio alle tue esigenze. Potremo trovare insieme la soluzione migliore per dare vita ai tuoi progetti.