Automatizzare i pagamenti con uno Smart Contract

In questa pagina trovi...

Attraverso la creazione di un nuovo smart contract esploriamo quali siano le principali funzioni necessarie a disporre dei pagamenti automatizzati in Ether. Analizzeremo il codice solidity e le possibili insidie che si nascondono, terminando con alcune considerazioni giuridiche in merito al contenuto dello smart contract.

Questo contenuto rappresenta un pagina della sezione “Sviluppare uno Smart Contract” ed è fortemente consigliato seguire l’ordine di lettura proposto nella stessa. Il progetto rappresenta un percorso lineare che prevede la conoscenza delle nozioni e delle considerazioni emerse in precedenza.

Un ringraziamento speciale va a Legaltech Italia e a DirittoConsenso, che ospitano una forma sintetica di questo contenuto.  LegaltechItalia.eu non è solo una rivista ma anche una community che ti permetterà di restare aggiornato sulle ultime novità dal mondo Legal Tech. Se sei interessato a tematiche di diritto a tutto tondo in DirittoConsenso.it potrai trovare moltissimi articoli di rilievo. 

Il Pagamento P2P

Il pagamento peer to peer (P2P) rappresenta una delle innovazioni introdotte dalla tecnologia blockchain. Due soggetti possono trasferire denaro in modo diretto tra loro senza la necessità di un terzo intermediario. Non è mia intenzione approfondire il funzionamento tecnico che rende possibile il superamento del problema del double spending, dando vita ad una rete trustless. Ritengo invece opportuno, per ragioni di completezza rispetto a quanto seguirà, descrivere la semplicità con la quale sia possibile compiere un pagamento P2P su blockchain Ethereum. 

É sufficiente essere in possesso di wallet, di una frazione di Ether, e conoscere la chiave pubblica del wallet del destinatario. Come visto in precedenza, nell’articolo dedicato alla notarizzazione, l’estensione per browser “Metamask” è una delle soluzioni più utilizzate per la creazione e gestione del proprio wallet.
Si accede all’account (figura 1)e si seleziona “invia”,  si indica il destinatario, l’importo e si conferma (figura 2).

Figura 1
Clicca per ingrandire - Figura 1
Figura 2
Clicca per ingrandire - Figura 2

Se il trasferimento è un’operazione così semplice perché dovrei utilizzare uno smart contract (SC)?
Le caratteristiche dello SC lo rendono strumento ideale qualora avessi la necessità di vincolare l’esecuzione del trasferimento di valuta all’avverarsi di una specifica condizione.

Obiettivo dell’articolo è analizzare il funzionamento del codice dello SC in merito alla possibilità di ricevere ed inviare denaro, nonché comprendere come una funzione di pagamento possa essere automatizzata e quali siano le principali problematiche.

Il Caso

Riproducendo una possibile esigenza del mondo reale creiamo il nostro caso.
Due sono i soggetti coinvolti nel rapporto, Tizio e Caio. Il primo contatta il secondo richiedendo l’esecuzione di un lavoro di tinteggiatura del proprio immobile. Caio comunica a Tizio che l’esecuzione della prestazione richiederà 90 giorni. I due soggetti si accordano per il corrispettivo di 9 Ether (nel momento in cui si scrive il valore di 1 Ether equivale a circa 1700 euro). Tuttavia Caio, comportando il lavoro l’impiego di una grande quantità di materiali, desidera ottenere il pagamento in anticipo di una parte dell’importo. Dopo una fase di trattativa le due parti stabiliscono la seguente modalità di erogazione del corrispettivo: la somma di 9 Ether sarà erogata da Tizio in 3 diverse rate di pari importo a distanza di 30 giorni l’una dall’altra; la prima dopo 10 giorni dall’inizio dei lavori, la seconda dopo 40 giorni e la terza dopo 70 giorni. L’accordo prevede inoltre dettagliate condizioni di esecuzione della prestazione di tinteggiatura, qualora queste non siano rispettate da Caio, Tizio potrà interrompere il pagamento della prestazione senza dover corrispondere le rate residue.

Le parti decidono quindi di utilizzare lo smart contract come soluzione per l’erogazione automatica del pagamento. 
Può uno smart contract essere idoneo a svolgere questa attività? Quali sono le functions necessarie e quanto è complesso l’utilizzo?

Il Codice dello Smart Contract

Quale tipologia di meccanismo dovrà integrare lo smart contract (SC)? 
Per raggiungere il risultato prefissato dovrebbe essere possibile compiere queste operazioni:
– Tizio deve inviare 9 Ether allo SC;
– lo SC deve conservare l’importo fino al momento stabilito;
– lo SC dovrà disporre in modo automatico il trasferimento di ciascuna singola rata da 3 Ether verso l’account di Caio, al raggiungimento della data specifica;
– Tizio deve avere la possibilità di interrompere il pagamento automatico qualora si verificassero le condizioni stabilite in fase di trattativa. 

Basandosi su questa premessa è facile comprendere perché spesso l’attributo trustless viene associato allo smart contract; sia Tizio che Caio ne beneficiano in termini di rischio. Il primo sarà contento di non dover versare immediatamente l’intera cifra e di poter interrompere il pagamento qualora risultasse necessario; il secondo potrà verificare che Tizio dispone effettivamente delle risorse per retribuire la prestazione e non temere il ritardo nel pagamento. 

Ma funziona realmente così uno smart contract? 
Prima di tutto, perché è necessario che Tizio trasmetta immediatamente l’intero importo alla creazione dello smart contract? É bene precisare che l’operazione iniziale si configura sempre come necessaria in quanto uno SC non può mai compiere un prelievo forzoso verso un wallet. L’unico modo per assicurare il compimento della prestazione sarà quindi depositare la valuta all’interno dello SC così che sia esso a gestirne il trasferimento.

Mi preme evidenziare fin da subito che il codice proposto non rappresenta sicuramente la miglior soluzione in termini di efficienza ed eleganza informatica, ma rappresenta a mio avviso uno dei migliori compromessi a favore della comprensibilità. Qualora volessi sperimentare alternative ti ricordo l’esistenza di due validi strumenti: la Guida Ufficiale di Solidity e Stack Overflow.

Procediamo quindi come fatto nei precedenti articoli per la predisposizione del codice:
apri Remix, crea un nuovo file “.sol” e definisci il nome, nel mio caso “TrasferimentoEth.sol” (figura 3).

Figura 3
Clicca per ingrandire - Figura 3

Le Variabili

Iniziamo definendo la licenza, la versione del compilatore, e assegniamo l’identificatore al contratto (figura 4). 
Quali variabile sono necessarie per il nostro scopo?
Dividendole in gruppi possiamo individuare le variabili:
– per indicare Tizio e Caio;
– per stabilire gli elementi temporali, ossia le condizioni che innescheranno la funzione di pagamento;
– per memorizzare l’avvenuto pagamento della rata;
– infine una variabile che possa contenere la motivazione dell’interruzione del pagamento, qualora Tizio eserciti l’apposita funzione. 

Figura 4
Clicca per ingrandire - Figura 4

Possiamo ora creare le singole variabili.
Ricorda che in questo momento stiamo semplicemente assegnando gli identificatori, ossia stiamo dando un nome alle variabili intese come contenitore, senza definire quale sia il loro contenuto. 

Crea quindi le variabili Tizio e Caio, i quali saranno rappresentati dal loro address, ossia la chiave pubblica del wallet. Indica inoltre, attraverso un commento single line, la qualità della parte ossia Tizio “committente” e Caio “prestatore d’opera” (come in figura 5).
Ti ricordo che i commenti non vengono eseguiti dalla EVM, hanno semplicemente funzione esplicativa, e per tale ragione giocano un ruolo importante in termini di intellegibilità del contenuto. 

Procediamo con l’inserimento delle variabili tempo che necessariamente indicheremo con il tipo di dato uint, questo perché il dato temporale viene espresso in forma numerica. Il tempo viene gestito da Solidity secondo lo standard Unix Epoch Time. Nel momento in cui si scrive l’ Unix Epoch Clock segna le ore “1618003660”. Il numero non è altro che la somma dei secondi calcolati a partire dal 1° gennaio 1970. Se vuoi scoprire che ore sono in questo momento o hai bisogno di fare dei calcoli? Clicca qui – EpochConverter. In ogni caso non spaventarti, come vedremo successivamente, il compilatore ci aiuterà nel calcolo delle date.

Continuiamo inserendo due mapping: il primo ad indicazione dell’avvenuta riscossione della rata, il secondo come indicatore di avvenuta interruzione della prestazione di pagamento. Per ora non ci soffermiamo sul funzionamento del mapping, ne analizzeremo il contenuto al momento della creazione delle functions.

Per ultimo creiamo una variabile string come contenitore della motivazione che Tizio dovrà inserire qualora volesse interrompere il pagamento.

Figura 5
Clicca per ingrandire - Figura 5

Ora creiamo il costruttore
Ad esso è necessario aggiungere l’attributo “payable“, questo ci garantirà l’idoneità dello SC a ricevere Ether. All’interno del constructor definiamo il contenuto delle variabili di stato create in precedenza (figura 6). 

Per le variabili address Tizio e Caio indichiamo le relative chiavi pubbliche.
Definiamo ora le variabili uint. Come visto poco fa, l’elemento temporale viene rappresentato in forma numerica a 10 cifre. Fortunatamente a noi non viene richiesto di effettuare alcun calcolo. Volendo far coincidere la data di pubblicazione del contratto con quella dell’inizio dell’esecuzione della prestazione di Caio, assegniamo alla variabile denominata “DataDeploy” il valore temporale del deploy attraverso il comando “block.timestamp“.
Per determinare la scadenza delle tre rate ci baseremo quindi sul timestamp del deploy dello SC. Anche qui il compilatore ci viene in aiuto supportando in modo nativo la sintassi “days” per indicare la misura dei giorni (così come seconds, minutes, hours, ecc…clicca qui per conoscere l’elenco completo della sintassi cronologica supportata). La definizione delle variabili uint che indicano le rate saranno quindi definite come “DataDeploy + … days“.

Clicca per ingrandire - Figura 6

Le Functions

Definiamo ora quali siano le funzioni che vogliamo inserire nello smart contract e riportiamo il tutto in forma di commento multiriga (figura 7). 
Per rendere il codice maggiormente comprensibile si decide di creare:

– una funzione per inviare Ether allo smart contract;
– una funzione per conoscere l’importo di Ether contenuti all’interno dello SC;
– tre funzioni di riscossione, una per ogni rata;
– una funzione di interruzione del pagamento.

Figura 7
Clicca per ingrandire - Figura 7

Trasferimento Ether e Bilancio SC

La funzione per trasferire Ether allo Smart contract è molto semplice:

(figura 8)        function TraferisciEtherAlloSC() external payable { }  

All’identificatore seguono: le parentesi tonde, l’attributo di visibilità e l’attributo payable. Quest’ultimo indica l’idoneità a ricevere valuta e senza di esso un eventuale tentativo di invio provocherebbe il revert della function. 
L’attributo external lo incontriamo per la prima volta, in quanto fino ad ora abbiamo utilizzato solo public. A differenza di quest’ultimo, che indica una funzione esercitabile da qualsiasi address e anche dallo stesso SC, external indica una funzione esercitabile solo dall’esterno dello smart contract. Seppur nel caso specifico l’inserimento di public non causerebbe malfunzionamenti, external è da preferirsi in quanto comporta una minor spesa in termini di gas per il deploy dello SC. 

Figura 8
Clicca per ingrandire - Figura 8

Per quanto concerne la funzione per leggere il bilancio (totale della valuta contenuta nell’account) dello smart contract anch’essa presenta pochi elementi di novità:

(figura 9)      function BilancioSC() external view returns(uint){return address(this).balance;}

A function seguono:
– l’identificatore;
– le partesi tonde vuote (in quanto non è necessario alcun valore in input);
– visibilità external per la medesima ragione espressa poc’anzi;
view (da specificare in quanto funzione di sola lettura non comporta un costo di esercizio);
returns(uint) in quanto la funzione dovrà restituire un numero.

Passiamo ora al vero e proprio comando impartito, potendolo così tradurre:
restituisci (return) in merito a questo address (address(this)) il bilancio (.balance).
In altri termini, balance costituisce l’indicazione del totale degli ether contenuti in un wallet, facendo precede tale termine dall’espressione address + (la chiave pubblica di un address specifico) otteniamo il totale degli ether contenuti in esso.
Perchè inseriamo il termine “this“? Allo smart contract non è assegnata alcuna chiave pubblica fino al momento del deploy; indicando this lo SC sarà in grado di recuperare in autonomia il proprio indirizzo durante l’esercizio della function.

Figura 9
Clicca per ingrandire - Figura 9
(Test) - Trasferimento Ether e Bilancio SC

Verifichiamo ora il corretto funzionamento delle due functions.
Con la prima funzione invieremo 9 Ether allo SC, con la seconda verificheremo la presenza in esso di tale ammontare.
Prima di procede è doverosa un piccola premessa in merito all’unita di misura della valuta. Se sei stato particolarmente attento avrai notato che la funzione restituisce un numero intero(uint) e non un valore con virgola (float). La ragione è semplice, in Solidity i calcoli non vengono effettuati con l’unità di misura Ether (Eth), ma con il fratello minore Wei.
1 Wei equivale a  10^(-18) Ether, in altri termini 1 Ether = 1,000,000,000,000,000,000 wei.

Procediamo con il test di funzionamento. 
Effettuiamo il compile (nel caso non avessimo spuntato l’opzione “auto compile”), selezioniamo l’account di Tizio, procediamo con il deploy (in ambiente JavaScript VM) ed infine alla voce deployed contracts visualizziamo le funzioni disponibili (figura 10).

Tramite la funzione BilancioSC verifichiamo che l’importo iniziale contenuto all’interno dello smart contract sia 0 (figura 11).

Come illustrato in figura 12, per trasferire 9 Ether è necessario inserire alla voce “value” il valore 9, cambiare l’unità di misura da wei ad Ether, ed esercitare la funzione tramite il tasto rosso “TrasferisciEtherAlloSC” .

A questo punto vedrai immediatamente modificarsi l’importo residuo di Ether presenti nel wallet di Tizio. Per verificare l’effettivo trasferimento di valuta, oltre a visualizzare nel report della funzione il valore di 9000000000000000000 wei, possiamo esercitare la funzione BilancioSC per controllare l’ammontare di Eth nello smart contract (figura 13).

Figura 10
Clicca per ingrandire - Figura 10
Clicca per ingrandire - Figura 11
Clicca per ingrandire - Figura 12
Figura 13
Clicca per ingrandire - Figura 13

Funzioni di Pagamento Rate

Abbiamo deciso che il pagamento sarà disposto attraverso tre distinte functions, una per ogni rata. 
Come specificato in precedenza, la scelta di utilizzare 3 funzioni, e non una singola, sfugge alle logiche minimaliste della programmazione ma è giustificata dall’obiettivo di creare un codice il più auto-esplicativo possibile.

Le tre funzioni sono quindi molto similari tra loro (figura 14) e hanno il compito principale di trasferire 3 Eth al bilancio di Caio. Come vedremo in seguito, oltre alla verifica del raggiungimento della data di esigibilità del pagamento, sarà necessario prevedere ulteriori meccanismi di tutela, ad esempio quello che impedisce il riutilizzo della funzione con la finalità di ottenere più volte il pagamento della medesima rata.

Clicca per ingrandire - Figura 14

Per comprendere tali meccanismi è necessario fare un passo indietro e analizzare le due variabili di stato mapping definite alla voce “Database delle operazioni” (figura 15):

mapping(uint=>bool) Riscosso; 
mapping(uint=>bool) PagamentoBloccato; 

Il mapping lo incontriamo ora per la prima volta ma è molto utilizzato nella programmazione.
Analizziamo quindi la struttura: il termine mapping è seguito da parentesi tonde, le quali contengono al loro interno due tipi di dati separati da una freccia, segue poi l’identificatore del mapping ossia “Riscosso” e “PagamentoBloccato”.
Se vuoi approfondire il funzionamento di questo data type ti invito a cliccare qui per leggere l’apposita spiegazione nella guida ufficiale Solidity.
Limitandosi ad una spiegazione semplicistica si può immaginare il mapping come una tabella a due colonne: nella prima colonna viene inserito il valore indicato prima della freccia (nel nostro caso uint), nella seconda colonna il valore che segue la freccia (nel nostro caso bool).
Prendiamo in esame il mapping “Riscosso”, che è stato creato con la finalità di tenere traccia dell’avvenuto pagamento delle rate: nella prima colonna verrà inserito il valore che indica la rata (ad esempio uint MeseUno) nella seconda il valore booleano (true/false) che indica se il pagamento è avvenuto. Ricorda che il valore di default di bool è sempre false.
Attraverso appositi comandi sarà poi possibile leggere e modificare i valori memorizzati all’interno del mapping.

Clicca per ingrandire - Figura 15

Procediamo con l’analisi di PagamentoPrimaRata (figura 16).
La funzione non prevede alcun parametro in input e l’attributo di visibilità è external.
Alle righe 58-60 sono previsti 3 require. Come visto in passato, il require ha lo scopo di accertare l’esistenza di presupposti essenziali per il proseguimento dell’esecuzione della funzione, in assenza dei quali provoca il revert.
La struttura è assai semplice: require(condizione da rispettare, “messaggio di errore”).
Vediamo quindi cosa prevedono i require, seguendo la denominazione presente in figura 16:

(lettera A)       require(Riscosso[MeseUno]==false, “Mensilita’ gia’ riscossa”);
Verifica che all’interno del mapping “Riscosso” al valore MeseUno corrisponda il booleano false. Qualora il booleano dovesse essere true, la funzione provoca il revert e segnala che la mensilità è già stata riscossa.

(lettera B)      require(PagamentoBloccato[MeseUno]==false, “il pagamento e’ stato bloccato da Tizio”);
Verifica che all’interno del mapping “PagamentoBloccato” il valore di riferimento per MeseUno sia false. Se il requisito non è soddisfatto restituisce in errore “il pagamento e’ stato bloccato da Tizio” e provoca il revert

(lettera C)      require(block.timestamp >= MeseUno, “troppo presto per riscuotere”);
Confronta il valore uint che indica il momento in cui viene esercitata la funzione (block.timestamp) con il valore uint MeseUno, e verifica che il primo sia maggiore di quest’ultimo. In caso contrario verrà riportato il messaggio di errore “troppo presto per riscuotere”. 
Non confondere block.timestamp con la variabile DataDeploy, quest’ultima memorizzerà al suo interno il valore di block.timestamp al momento del deploy e rimarrà invariata durante tutta l’esecuzione del contratto.

Nel caso tutti i require siano soddisfatti si verificherà quanto stabilito alla lettera D ed E della figura 16:

(lettera D)       payable(Caio).transfer(3000000000000000000);  

Come suggerisce il commento al codice, la funzione trasferisce 3 Ether a Caio. Transfer è preceduto dall’indirizzo del destinatario (per il quale è sempre necessario specificare payable) e seguito dall’importo che si desidera trasferire.

(lettera E)      Riscosso[MeseUno]=true;

Infine riceve esecuzione il comando che modifica all’interno del mapping Riscosso il booleano corrispondente a MeseUno. Questa indicazione è di fondamentale importanza in quanto nel caso la funzione dovesse essere eseguita nuovamente verrà subito interrotta in quanto il require alla lettera [A] non troverà soddisfazione.
Ti ricordo che il singolo “=” indica l’assegnazione di un valore mente il “==” indica una valutazione comparativa tra parametri.

Figura 16
Clicca per ingrandire - Figura 16

Vediamo brevemente in cosa si differenziano le funzioni PagamentoSeconda/TerzaRata, per testarne subito dopo il corretto funzionamento.

Come evidenziato in figura 17, mutano i valori relativi ai controlli iniziali circa l’avvenuta riscossione e il tempo di esercizio della funzione. Al valore MeseUno è infatti sostituito MeseDue. Per quanto concerne la verifica del blocco del pagamento oltre al valore MeseUno avverrà il controllo anche per MeseDue. La ragione è semplice, la funzione di PagamentoRata non può proseguire se è stato interrotto il pagamento della rata che la precede.
Quanto appena considerato trova riscontro anche in merito alla funzione PagamentoTerzaRata (figura 18).

Figura 17
Clicca per ingrandire - Figura 17
Figura 18
Clicca per ingrandire - Figura 18
(Test) - Pagamento rate

Si procede quindi con la verifica della corretta esecuzione delle 3 funzioni analizzate.
Prima di effettuare il deploy è essenziale  modificare le variabili uint relative agli indicatori di tempo, altrimenti si renderebbe necessario attendere 30 giorni tra un test e quello successivo. Sostituire “seconds” al posto di “days” nelle variabili MeseUno, MeseDue e MeseTre, consentirà di ridurre l’attesa ad un massimo di 30 secondi (figura 19). 

Figura 19
Clicca per ingrandire - Figura 19

Si può ora procedere con le seguenti operazioni:

– compile e deploy del contratto;
– esercizio della funzione TraferisciEtherAlloSC con l’account di Tizio per l’importo di 9 Ether;
– esercizio della funzione BilancioSC per controllare l’ammontare di Ether nello SC;
– trascorsi almeno 10 secondi dal deploy, esercitare la funzione PagamentoPrimaRata;
– verificare il corretto esito della funzione controllando gli importi residui all’interno dello SC;
– esercitare la funzione PagamentoSecondaRata prima che sia trascorso il tempo necessario (30 sec);
– ottenere dal terminale l’errore “troppo presto per riscuotere”;
– trascorso il tempo necessario esercitare nuovamente la funzione  e verificare il corretto trasferimento di Ether;
– controllare che al tentativo di riutilizzo di una funzione di pagamento il terminale restituisca l’errore “Mensilita’ gia’ riscossa”. 

Qui a lato troverai alcune immagini esplicative dei punti appena elencati (figure 20-24).

Osservazioni - Pagamento rate

Prima di analizzare l’ultima function dello SC soffermiamoci per alcune considerazioni in merito al test appena effettuato. 

Una prima riflessione penso sia doverosa per quanto concerne l’automaticità della prestazione.
Il pagamento è davvero automatico?
Questa automaticità dipende unicamente dello smart contract?
Come è stato possibile osservare in fase di test, è sempre necessario che vi sia un input che determini l’esercizio della funzione. Lo smart contract può concretamente controllare la data e trasferire l’importo al destinatario ma solo qualora vi fosse “qualcuno” che gli richiede di controllare se ricorrano le condizioni prestabilite.
Ma chi è questo “qualcuno”? Nel nostro caso eravamo noi, una persona fisica che esercitava la funzione (richiedendo allo smart contract se vi fossero le condizioni per effettuare il pagamento) e attendendo l’esito. 
É sempre necessaria una persona fisica? Assolutamente no, in quanto l’operazione può essere automatizzata con un software esterno alla blockchain al quale si richiede di compiere l’esercizio della funzione al posto nostro. Inoltre, è bene precisare che l’input potrebbe anche provenire da un differente smart contract o addirittura dallo stesso smart contract che preveda al suo interno l’esercizio di una funzione come esito di un’altra funzione. Tuttavia l’osservazione resta la medesima ossia, affinché ciò avvenga, deve esistere un input off-chain che attivi il diverso smart contract o la diversa funzione del medesimo smart contract.
Ma perché lo smart contract non può attivarsi da solo?
Gli smart contract sono codici decisamente limitati rispetto ai programmi che normalmente siamo abituati ad utilizzare su computer o smartphone; le ragioni di tale limitazioni risiedono nella struttura che ne ospita l’esecuzione, ossia la blockchain. Se sei appassionato della tematica sicuramente saprai che gli organi deputati all’esecuzione degli smart contracts sono le EVMs (Ethereum Virtual Machines), queste hanno una limitata dimensione e capacità computazionale.
Vi è inoltre un ulteriore aspetto rilevante, ogni operazione in blockchain richiede una validazione (da parte dei miners) con un conseguente costo di esercizio (fees per i miners). Se lo smart contract dovesse sostenere un processo attivo al suo interno adibito a controllare il trascorrere del tempo rischierebbe di esaurire gli Eth presenti nel bilancio.

Questo ci porta ad affrontare una seconda questione. 
Chi sopporta il costo della funzione?
Il costo è supportato da colui che la esercita. Il fatto che ad esercitarla sia un soggetto diverso dallo smart contract consente al bilancio interno di non essere diminuito nel suo ammontare di 9 Ether.
Seppur le fees sono una cifra quasi ininfluente per un importo così elevato, l’ultimo periodo (2020- 2021) ha registrato una crescita vertiginosa di questi valori, tale da rendere più che lecito il quesito. Il costo da sostenere potrebbe essere oggetto di accordo tra le parti? E di chi è la responsabilità dell’esercizio delle funzioni? Ci occuperemo di queste questioni nella parte finale dell’articolo trattandosi di problematiche giuridiche.

Funzione di Interruzione della Prestazione di Pagamento

Analizziamo ora l’ultima function dello smart contract denominata BloccaPagamentoRata.
Qual è il compito di questa funzione? Deve consentire a Tizio di bloccare il pagamento della rata esprimendo la motivazione.
Gli elementi contenuti in essa sono tutte strutture già incontrate in precedenza.
Si tratta di una funzione in scrittura che prende in input un valore string con identificatore locale _motivazione. La funzione è esercitabile solo dall’esterno (external) e restituisce un dato stringa (string memory). Come stabilisce il primo require, la funzione di interruzione può solamente essere utilizzata da Tizio. 
Dalle righe 87 a 95 vengono definiti i requisiti temporali, dalle righe 98 a 100 il comando da eseguire (figura 25). 

In base al momento di esercizio della function è possibile ricadere in 4 diverse ipotesi:
1 – [if]         →  se avviene entro 10 giorni dal deploy
2 – [else if] → se avviene tra il giorno 11 e 39
3 – [else if] → se avviene tra il giorno 41 e 69
4 – [else]    → se avviene in una qualsiasi altra ipotesi.

Qualora si ricadesse nelle ipotesi 1, 2, 3 avverrà la contestuale modifica dei valori del mapping PagamentoBloccato; 4 invece condurrà al revert.

Figura 25
Clicca per ingrandire - Figura 25

Nelle ipotesi 1, 2, 3, si producono ulteriori effetti (righe 98-100, figura 26). 

(riga 98)      payable(Tizio).transfer(address(this).balance);

Il comando si presenta molto simile a quello utilizzato per trasferire Ether a Caio, in esso viene modificato il destinatario (Tizio) e l’importo (l’intero ammontare degli Eth residui all’interno dello SC).
Dimenticarsi di inserire questo comando significa commettere un grave errore, compromettendo la possibilità per Tizio di riottenere quanto versato allo smart contract. Infatti il creatore dello SC, salvo aver previsto un’apposita funzione, non dispone di alcun potere di accesso al bilancio. 

Infine sono necessarie le righe 99 e 100 per restituire in output la motivazione.
L’accordo raggiunto dalle parti prevede che Tizio possa interrompere l’esecuzione della prestazione di pagamento qualora Caio non rispetti le condizioni stabilite per l’esecuzione della prestazione d’opera (per non appesantire ulteriormente la lettura si è deciso di non definire quali siano le motivazioni che giustificano l’esercizio). É quindi necessario che Tizio indichi la ragione affinché la medesima sia notarizzata dallo SC.

(riga 99)        Motivazione = _motivazione;
(riga 100)      return Motivazione;

Attraverso queste istruzioni disponiamo che il valore string dato in input da Tizio (_motivazione) sia memorizzato all’interno della variabile di stato Motivazione, ed in seguito visualizzato (return).

Figura 26
Clicca per ingrandire - Figura 26
(Test) - Interruzione della Prestazione di Pagamento

Non resta che verificare il corretto funzionamento della function di interruzione.
Per celerità ci limiteremo a testare una singola ipotesi, procedendo in questo modo:

– compile e deploy di un nuovo contratto (ricarica la pagina per ottenere nuovamente accounts con 100 Eth);
– esercizio della funzione TraferisciEtherAlloSC con l’account di Tizio per l’importo di 9 Ether;
– trascorsi almeno 10 secondi dal deploy, esercitiamo la funzione PagamentoPrimaRata;
– trascorsi ulteriori 30 secondi esercitiamo la funzione per il pagamento della seconda rata;
– controllo visivo nella sezione account che gli importi siano stati trasferiti ed esercizio della funzione BilancioSC per verificare l’ammontare di Ether nello SC;
– con l’account di Tizio esercitiamo la funzione BloccaPagamentoRata con inserimento della motivazione;
– esercizio della funzione di riscossione della terza rata, che deve restituire errore;
– controllo finale che sia avvenuta la restituzione degli Eth residui a Tizio.

Il carosello qui a lato illustra alcuni dei passaggi appena descritti (figure 27-30). 
Chiaramente non è sufficiente compiere un singolo test; il debugging è un’importante attività a carico dello sviluppatore ma assume sempre più rilevanza, a causa delle implicazioni legali, la necessità di un confronto con il giurista .

Durante l’attività di test ho ipotizzato una pluralità di situazioni concrete e verificato il corretto funzionamento dello SC. Una di queste ipotesi ha portato in evidenza un potenziale disagio. Vista la finalità esplorativa dei contenuti proposti, ho ritenuto essere di maggior stimolo mantenere quella fragilità all’interno del codice e lasciare la libertà al lettore di ripercorre i ragionamenti che mi hanno condotto alla scoperta.
Chiaramente sarebbe incompleta una trattazione priva della disamina del problema, per tale ragione al termine dell’articolo troverai la sezione “Extra – Debugging” nella quale illustro il difetto e propongo quella che a mio avviso è la soluzione più appropriata.

Osservazioni Giuridiche

Lo smart contract così realizzato si è dimostrato un utile strumento per rendere automatica una delle prestazioni delle parti.
Nonostante il caso creato sia di pura fantasia e (per mantenere un approccio semplificato al codice informatico) ci si sia limitati ad una parziale definizione delle regole che disciplinano il rapporto contrattuale, emergono molteplici elementi di spunto per interessanti considerazioni giuridiche.

Ad oggi non è ancora presente una normativa che permetta di inquadrare in modo completo e nel dettaglio l’utilizzo degli strumenti di blockchain e smart contract, lasciando purtroppo spazio a diverse incertezze.
Per tale ragione e per i motivi che emergeranno in seguito in questa sede dobbiamo limitarci a delle semplici osservazioni e alla formulazione di interrogativi. 
Ricordo come sempre che l’articolo è rivolto sia a giuristi che informatici, per tale ragione si presta maggior attenzione alla comprensibilità piuttosto che al rigore terminologico.

Prima di procedere con i quesiti cerchiamo di capire se il rapporto che lega le parti possa essere ricondotto ad un contratto tipico (ossia uno schema contrattuale che trova espressa disciplina all’interno dell’ordinamento).

Tizio richiede a Caio di effettuare la tinteggiatura dell’immobile verso corrispettivo in Ether, la cui erogazione è scandita da una precisa tabella temporale.
Assumiamo che Caio sia un imbianchino e che possa essere inquadrato come piccolo imprenditore (ex articolo 2083 c.c.). L’accordo che lega Tizio e Caio potrà essere ricondotto al contratto d’opera, come definito dall’articolo 2222 del Codice civile:

“Quando una persona si obbliga a compiere verso un corrispettivo un’opera o un servizio, con lavoro prevalentemente proprio e senza vincolo di subordinazione nei confronti del committente, si applicano le norme di questo capo, salvo che il rapporto abbia una disciplina particolare nel libro IV [1655].“

Verifichiamo che quanto indicato dall’articolo sia conciliabile con la fattispecie ipotizzata. Gli elementi richiesti dall’articolo sono:

– obbligazione a compiere opera o servizio → tinteggiatura immobile
– verso corrispettivo → 9 Ether
– lavoro proprio e assenza di subordinazione → Caio è infatti un imprenditore
– la fattispecie non deve trovare disciplina particolare nel libro IV → avendo definito Caio piccolo imprenditore escludiamo l’applicabilità della disciplina dell’appalto (riservata all’imprenditore medio-grande).

Occupiamoci quindi della prima questione da dirimere: siamo in presenza di uno Smart legal contract o di un semplice smart contract informatico?

Quali requisiti debba possedere il codice informatico per poter essere considerato un contratto legalmente vincolante lo stabilisce l’articolo 8 ter della L.12/2019 combinato con le disposizioni del Codice civile in materia di contratti. Nel precedente articolo “Smart Legal Contract – Conversione di una scrittura privata” è stata fatta una ricognizione di quali siano gli elementi essenziali del contratto che devono essere necessariamente presenti all’interno dello SC.

Non vi sono dubbi in merito al fatto che il codice in questione sia un programma per elaboratore che opera su tecnologie basate su registri distribuiti e che su tale tecnologia riceva esecuzione; tuttavia non si tratta di uno smart legal contract in quanto non presenta i requisiti essenziali del contratto previsti dal Codice civile. In altri termini, siamo di fronte ad un semplice smart contract informatico che si limita ad essere mezzo di esecuzione di una delle prestazioni, e non di certo un contratto. 

Per meglio motivare questa affermazione si procede con l’analisi dei seguenti punti:
– individuazione degli elementi presenti nel codice;
– definizione degli elementi non presenti invece necessari a conferire valore legale;
– formulazione di una possibile integrazione degli elementi necessari.

Elementi presenti.
All’interno del codice è possibile individuare la presenza di due address ai quale viene associato il nome delle parti e la qualifica del rispettivo ruolo (“committente” e “prestatore d’opera”); si comprende che vi è uno spostamento di valuta a favore di Caio al corrispondere di intervalli di tempo definiti come “data di esigibilità”; infine è possibile individuare il potere di Tizio di interrompere il pagamento esprimendo una motivazione.
Questi elementi sono sufficienti a racchiudere l’effettivo contenuto del contratto? No.

Elementi assenti.
L’articolo 1321 del Codice civile stabilisce che:

“Il contratto è l’accordo di due o più parti per costituire, regolare o estinguere tra loro un rapporto giuridico patrimoniale.”

Risulta subito evidente che il codice informatico non contenga gli elementi sufficienti per raggiungere questo risultato. Non è possibile individuare all’interno dello smart contract: accordo, causa e oggetto del contratto; non vi è indicazione di quale sia la prestazione che deve compiere Caio e nemmeno che questa debba concludersi in 90 giorni.
Non è inoltre possibile dare prova del fatto che vi sia un accordo e nemmeno che Caio sia a conoscenza dell’esistenza dello SC, in quanto tutte le functions presenti nel codice possono essere esercitate anche dal solo address di Tizio.
Se non fosse per la debole presenza dei commenti “prestatore d’opera” e “data di esigibilità” si potrebbe addirittura pensare che si tratti di un atto di liberalità.

Seppur molte di queste informazioni possano essere integrate, la problematica maggiore riguarda l’identificazione dei soggetti e l’apposizione della firma delle parti. Il primo problema si presenta come una diretta conseguenza dell’assenza di formalità nel processo per la creazione di un wallet Etherum, non comportando questo alcun accertamento dell’identità del proprietario; in merito alla firma solo l’emanazione delle linee guida dell’AgID potrà porre termine alla situazione di incertezza e a nulla vale che la tecnologia utilizzata nel protocollo blockchain sia similare a quella utilizzata per la firma digitale (basandosi anch’essa sull’utilizzo delle chiavi asimmetriche).

Possibili integrazioni.
La maggior parte degli elementi mancanti possono essere integrati nel contatto sotto forma di string, e contestualmente possono essere previste delle functions che consentano alle stesse parti di visualizzare e approvare il contenuto. Come visto in precedenza la variabile string permette sostanzialmente di riprodurre quanto contenuto in un qualsiasi documento di testo, tuttavia è necessario considerare che ogni informazione aggiuntiva aumenterà il costo del deploy dello smart contract. Sarà quindi possibile prevedere delle variabili che contengano le generalità delle parti, l’oggetto e la causa del contratto senza difficoltà. Per quanto concerne la sottoscrizione, ferme restando le considerazioni espresse poc’anzi, le parti potrebbero integrare un ulteriore sistema di autenticazione attraverso una OTP (one time password) per aumentare il livello di sicurezza.

Constatato che non si tratti di uno smart legal contract emergono ulteriori quesiti di rilievo.

Sostenendo che il vero contratto abbia preceduto in forma scritta o orale lo smart contract, quale valore possiamo attribuire a quest’ultimo? È corretto limitarsi a ritenere che si tratti semplicemente della prestazione dovuta da Tizio?
Sicuramente la fattispecie non può trovare una semplice definizione, e ad un quesito spesso ne segue un altro.

Volendo sostenere che non si tratti di un negozio giuridico ma della prestazione che grava su Tizio, potremo affermare probabilmente che la manifestazione della conoscenza del codice informatico da parte di Caio non sia necessaria. Tuttavia sostenere che Tizio sia obbligato alla prestazione del versamento di 9 Eth (suddivisi in rate) e che il mancato trasferimento comporti l’inadempimento, porta a chiedersi perché mai Tizio invece di trasferire P2P gli Ether nei giorni prestabiliti dovrebbe farsi carico dello sviluppo dello smart contract dovendo sopportare anche il rischio di malfunzionamento dello stesso. In assenza dello smart contract Caio dovrebbe invece rinunciare ai benefici derivanti da questo e sopportare il rischio di non ricevere puntualmente la prestazione.

Sarebbe probabilmente più appropriato ritenere che le parti debbano concordare il contenuto del codice e integrare all’interno della documentazione contrattuale un insieme di informazioni a definizione dell’iter di sviluppo, in modo da rendere maggiormente agevole individuare la responsabilità di un eventuale malfunzionamento (ad esempio, il malfunzionamento dello script off-chain).

Come sottolineato più volte, per mantenere la scrittura del codice più agevole si è deciso di non definire in modo dettagliato il rapporto contrattuale che lega le parti. Questa scelta comporta l’emergere di ulteriori interrogativi. Si è stabilito che le rate dovute siano “esigibili” in specifiche date. Il funzionamento stesso del codice informatico, anche in ragione dell’effettivo meccanismo di automatica esecuzione, prevede che il pagamento sia esercitabile da un determinato momento in poi, è necessario comprendere come questa scelta rilevi sul piano giuridico.

L’articolo 1184 del Codice civile stabilisce:

“Se per l’adempimento è fissato un termine,  questo  si  presume  a favore del debitore, qualora  non  risulti  stabilito  a  favore  del creditore o di entrambi.”

Questa disposizione implica che se nulla è stabilito Tizio potrebbe adempiere anche prima del termine; tuttavia il codice informatico così come creato impedisce questa operazione; è quindi questa un’indicazione della specifica volontà delle parti? Quale valore deve essere attribuito?

Un ulteriore quesito riguarda il ritardo nella prestazione (come visto in sede di analisi deve essere presente uno script off-chain). Ogni giorno che trascorre dalla data di esigibilità cosa comporta? Tizio è forse debitore degli interessi per ogni giorno di ritardo?
Si ritiene che la prestazione di trasferimento Eth non possa (vista la natura di criptovaluta e non di moneta avente corso legale) essere considerata come una prestazione pecuniaria e non sia quindi ritenibile un debito portabile. Questo porta a considerare che all’inadempimento di Tizio sarebbe necessaria un’attivazione di Caio per provocarne la costituzione in mora (articolo 1219 c.c.). In tale eventualità, secondo l’articolo 1223 c.c., Tizio sarebbe anche tenuto al risarcimento del danno e responsabile per l’eventuale oscillazione di valore degli Eth.
In considerazione di quanto appena detto, avrebbero vantaggio entrambe le parti a sfruttare lo strumento dello smart contract stabilendo nel codice l’applicazione di un aumento specifico per ogni giorno di ritardo. Una via alternativa potrebbe essere stabilire che le funzioni di pagamento vengano esercitate direttamente da Caio, in questo modo però sarebbe costretto a sostenere il costo delle fees. Ma su chi grava il costo di esercizio della funzione? La risposta più scontata non è necessariamente corretta. Essendo Tizio il soggetto debitore della prestazione verrebbe da pensare che sia anche il soggetto onerato dalle fees, al pari del costo che sosterrebbe per effettuare il bonifico bancario. Tuttavia non si tratta di una prestazione pecuniaria e la scelta di utilizzare lo smart contract non è frutto dell’autonoma decisione di Tizio. Come visto sono molte le conseguenze in termini di rischio derivante dalla scrittura di uno smart contract difettoso e devono necessariamente essere tenute in considerazione.

Differente è il caso nel quale le parti non abbiano stabilito assieme l’uso dello smart contract ma sia un’autonoma decisione di Tizio. Sarà quindi quest’ultimo a sopportare il costo del deploy del contratto, delle funzioni e anche il rischio di perdere l’intero ammontare di Eth, in conseguenza del quale non potrà comunque essere liberato dall’obbligazione originaria. Quale valore attribuire allo sviluppo dello smart contract da parte di Tizio in autonomia? Ammettiamo per esempio che il contratto originale (in forma orale) non preveda l’uso dello smart contract ma che sia una scelta autonoma di Tizio, il quale ad un certo punto ne interrompe il funzionamento e si rifiuta di eseguire la prestazione dovuta. In tale ipotesi non si esclude che Caio possa cercare di utilizzare lo smart contract ai fini dell’articolo 1988 c.c., ossia sostenendo che il codice informatico costituisca il riconoscimento del debito da parte di Tizio.

Quanto fino ad ora emerso evidenzia che molteplici sono le implicazioni soprattutto in merito ai profili di responsabilità. Difficilmente il debitore si assumerà tutto il rischio della creazione dello smart contract, ed è evidente quindi che le parti, in assenza di una rigorosa definizione delle regole e conoscenza dello strumento, preferiranno affidarsi ad un soggetto terzo il quale garantisca il corretto funzionamento dello smart contract e, in cambio di un corrispettivo, sopporti il rischio di malfunzionamento.

Considerazioni Conclusive

L’esperimento condotto ha permesso di verificare quali siano le funzioni di base che permettano l’interazione con uno smart contract ai fini del trasferimento di valuta. Invio e ricezione sono facilmente integrabili, come anche la predisposizione di azioni automatizzate innescate da ricorrere di condizioni prestabilite.
Alle parti è rimessa la scelta della modalità che meglio risponde alle esigenze concrete: una prima possibilità prevede di sviluppare uno smart contract informatico con relativa regolamentazione all’interno del contratto tradizionale; un’alternativa è prevedere l’integrazione dell’accordo all’interno del codice informatico così realizzando uno smart legal contract (ferma restando la situazione di incertezza normativa segnalata).
È pur vera la necessità di mantenere un certo realismo e considerare che, seppur le conoscenze basilari per svolgere l’operazione di pagamento siano facilmente accessibili, la capacità di sviluppare un codice privo di malfunzionamenti richiede necessariamente professionalità ed esperienza. Lo sviluppo di una soluzione artigianale potrebbe non solo non condurre al risultato sperato ma anche esporre le parti a profili di responsabilità non previsti.
Si procede in modo sintetico a riassumere quali siano i principali vantaggi e svantaggi emersi dalla disamina dello strumento.

Vantaggi.
Attraverso il codice è possibile creare condizioni molto ben definite con un alto livello di personalizzazione in base alle esigenze specifiche. È possibile non solo prevedere un pagamento automatico ma anche stabilire la variazione dell’importo in base ad ulteriori condizioni, aggiungendo ad esempio gli interessi di mora per ogni giorno di ritardo nell’adempimento alla prestazione.
Ogni operazione on-chain compiuta dalle parti potrà godere della c.d. notarizzazione, lasciando traccia di colui che ha interagito con il contratto e della data dell’evento.
Lo strumento conferma le aspettative generate dal famoso appellativo trustless. Lo smart contract potrà infatti prevedere che il creditore si sostituisca al debitore nell’esercizio della funzione che produce l’adempimento. Questo permette di avere la certezza di ricevere la prestazione senza dover intraprendere un procedimento giudiziale per veder riconosciuto il proprio diritto, attraverso una soluzione immediata e senza dover sostenere i costi del procedimento.

Svantaggi.
Lo svantaggio principale è dettato dalla profonda conoscenza tecnica e giuridica necessaria alla creazione dello strumento. Colui che svilupperà lo smart contract dovrà essere in grado di riconoscere quale blockchain, criptovaluta e linguaggio di programmazione possa essere maggiormente adatto alle esigenze. Oltre alla creazione dello smart contract sarà necessario predisporre un idoneo software off-chain volto ad interagire con le funzioni in esso presenti e garantire gli automatismi previsti. Quanto descritto comporta necessariamente un costo che le parti dovranno sostenere. Bisogna inoltre considerare che maggiore è il numero di condizioni che dipendono da elementi esterni alla blockchain, minore sarà il vantaggio nell’adottare questo tipo di soluzione tecnica.  

In conseguenza a quanto emerso sarà proprio l’analisi del caso concreto a stabilire l’utilità e la convenienza nell’adottare uno smart contract. Seppur lo strumento possa vantare molteplici applicazioni per la regolazione di eventi totalmente on-chain presenta numerosi elementi di criticità qualora si decida di adottarlo per disciplinare operazioni off-chain. Si riducono ulteriormente i benefici qualora lo strumento sia destinato a regolare una situazione unica, che non si ripete nel tempo, al contrario potrebbe comportare significativi vantaggi in situazioni reiterate nel tempo e con una pluralità indefinita di soggetti partecipanti.
Se è vero che i profili di incertezza siamo molteplici la situazione è in continua evoluzione e le caratteristiche tecniche innovative comportano evidenti vantaggi se correttamente sfruttate. In attesa di una più profonda definizione della questione giuridica non possiamo che sperimentare e mettere alla prova questo strumento.

Ultimo aggiornamento: 15/05/2021

Torna all’indice dei contenuti della pagina

Contenuto Extra - Debugging

Questo paragrafo rappresenta un proseguimento di (Test) – Interruzione della Prestazione di Pagamento, viste le implicazioni giuridiche ti suggerisco la lettura dopo aver visionato il resto dell’articolo.
Nelle righe che seguiranno ti spiegherò quale fragilità contiene il codice fino ad ora analizzato e quali modifiche ho ritenuto opportuno effettuare.

Riassumendo velocemente il funzionamento del contratto:
– Tizio effettua il deploy dello smart contract il giorno in cui Caio inizia la prestazione.
– Tizio trasferisce in esso l’ammontare di 9 Eth ed esercita la funzione di pagamento delle rate
      – la prima a partire dal 10° giorno,
      – la seconda a partire dal 40° giorno
      – la terza a partire dal 70° giorno.

L’esercizio di queste funzioni è a carico di Tizio (per le ragioni emerse in “Osservazioni Giuridiche“), il quale dovrebbe occuparsi di automatizzarne l’esecuzione off-chain o provvedere ad eseguirle personalmente.
Ipotizziamo il seguente scenario: Caio inizia la prestazione di tinteggiatura, Tizio pubblica lo SC e automatizza l’esercizio delle funzioni di pagamento con uno script;  il giorno 10 Caio riceve il pagamento di 3 Ether ma subito dopo lo script off-chain creato da Tizio cessa di funzionare. Quest’ultimo non si accorge dell’accaduto e il pagamento dovuto a Caio il 40° giorno non viene effettuato. Il 75° giorno Tizio, resosi conto che la prestazione di tinteggiatura non è conforme a quanto stabilito, esercita la funzione “BloccaPagamentoRata” per bloccare il pagamento della terza rata e lo comunica a Caio. Quest’ultimo, per nulla contento, scopre di non aver ancora ricevuto l’accredito della seconda rata. 

Caio potrà sollecitare Tizio a compiere il pagamento dovuto oppure potrà egli stesso esercitare la function PagamentoSecondaRata per ottenere il trasferimento degli Eth che gli spettano.
Se è vero che scegliendo quest’ultima modalità Caio sarà costretto a sostenere il costo delle fees per l’esercizio della funzione, è anche vero che otterrebbe un pagamento immediato senza dover attendere gli effetti delle sollecitazioni nei confronti di Tizio o peggio ancora il tempo necessario per un decreto ingiuntivo. 
Certamente, Caio ci ha messo abbastanza ad accorgersi che non era stato ancora pagato, ma a noi interessa verificare l’idoneità dello smart contract ad ottenere immediata soddisfazione.
Tuttavia il terminale non restituisce il risultato voluto ed emerge che l’effetto indesiderato sia causato dalla funzione BloccaPagamentoRata.

Come puoi vedere nella figura 31 la causa è da imputarsi al contenuto della riga 104. In essa è stabilito che a Tizio viene riconsegnato quanto rimanente all’interno dello smart contract, senza considerare però l’ipotesi sopra esposta e quindi che residui all’interno dello smart contract un ammontare che sia già di diritto spettante a Caio. Si propone quindi la rimozione di questa singola riga e l’introduzione di quanto previsto alle righe 90, 95, 100. Questo semplice accorgimento permetterà sia di restituire il giusto ammontare a Tizio (ossia 9, 6, o 3 Ether in base al momento in cui la funzione viene esercitata) che tutelare Caio nell’ipotesi analizzata.

È chiaro che anche nel caso in cui lo smart contract presentasse questo difetto, Caio resterebbe creditore della cifra residua che potrebbe ottenere rivolgendosi ad un giudice, tuttavia l’obiettivo che giustifica la scelta di adottare lo strumento dello smart contract è quello di porre al riparo da possibili inadempimenti senza la necessità di rivolgersi all’autorità.

Ti ringrazio per aver letto anche questo contenuto aggiuntivo, qualora volessi presentarmi la tua soluzione o avessi ulteriori domande trovi i miei contatti alla sezione About.

Figura 31
Clicca per ingrandire - Figura 31
Figura 32
Clicca per ingrandire – Figura 32

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.2;

contract TrasferimentoEth {

//Variabili di stato

//parti
address Tizio; //committente
address Caio; //prestatore d’opera

//Indicatori di tempo
uint DataDeploy; //Data deploy dello smart contract
uint MeseUno; //esigibilità primo pagamento
uint MeseDue; //esigibilità secondo pagamento
uint MeseTre; //esigibilità terzo pagamento

//Database delle operazioni
mapping(uint=>bool) Riscosso; // “true” indica che la rata è già stata riscossa
mapping(uint=>bool) PagamentoBloccato; //”true” quando il committente blocca l’esecuzione della prestazione di pagamento

//Dati
string Motivazione; //motivazione fornita da Tizio all’interruzione del pagamento

constructor() payable{ //payable= il contratto puo’ ricevere Ether

//definiamo le parti
Tizio = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
Caio = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2;

//definiamo le variabili cronologiche
DataDeploy = block.timestamp; //la variabile assumerà il timestamp del momento in cui avviene il DataDeploy
MeseUno= DataDeploy + 10 days; //data esigibilità primo pagamento, 10 giorni dal deploy;
MeseDue= MeseUno + 30 days; //data esigibilità secondo pagamento, 40 giorni dal deploy;
MeseTre= MeseDue + 30 days; //data esigibilità terzo pagamento, 70 giorni dal deploy;
}

/*Definizione delle funzioni, in ordine di scrittura:
– Una funzione per inviare Ether al contratto;
– Una funzione per leggere il bilancio dello SC.
– Tre funzioni per la riscossione delle rate a favore di Caio;
– Una funzione ad uso esclusivo di Tizio, per interrompere l’esecuzione del pagamento
e ottenere la restituzione dell’importo restante all’interno dello SC;
*/

//function per inviare Ether allo SC
function TraferisciEtherAlloSC() external payable { //1 wei = 10^(-18) ether.
}

//function per conoscere il bilancio dello SC.
function BilancioSC() external view returns(uint){
return address(this).balance;
}

function PagamentoPrimaRata () external { //funzione per riscuotere il pagamento relativo alla prima rata.
require(Riscosso[MeseUno]==false, “Mensilita’ gia’ riscossa”);
require(PagamentoBloccato[MeseUno]==false, “il pagamento e’ stato bloccato da Tizio”);
require(block.timestamp >= MeseUno, “troppo presto per riscuotere”);

payable(Caio).transfer(address(this).balance/3); //traferisci a Caio 1/3 Ether del contratto
Riscosso[MeseUno]=true; //aggiorna database
}

function PagamentoSecondaRata() external { //funzione per riscuotere il pagamento relativo alla seconda rata.
require(Riscosso[MeseDue]==false, “Mensilita’ gia’ riscossa”);
require(PagamentoBloccato[MeseUno]==false && PagamentoBloccato[MeseDue]==false, “il pagamento e’ stato bloccato da Tizio”);
require(block.timestamp >= MeseDue, “troppo presto per riscuotere”);

payable(Caio).transfer(address(this).balance/3); // Pagamento 1/3 Ether
Riscosso[MeseDue]=true;
}

function PagamentoTerzaRata () external { //funzione per riscuotere il pagamento relativo alla terza rata.
require(Riscosso[MeseTre]==false, “Mensilita’ gia’ riscossa”);
require(PagamentoBloccato[MeseUno]==false && PagamentoBloccato[MeseDue]==false
&& PagamentoBloccato[MeseTre]==false, “il pagamento e’ stato bloccato da Tizio”);
require(block.timestamp >= MeseTre, “troppo presto per riscoutere”);

payable(Caio).transfer(address(this).balance/3); // Pagamento 1/3 Ether
Riscosso[MeseTre]=true;
}

//una function ad uso esclusivo di Tizio che permette l’interruzione della prestazione di pagamento.
function BloccaPagamentoRata(string memory _motivazione) external returns(string memory){
require(msg.sender==Tizio, “Non sei Tizio”);
if (PagamentoBloccato[MeseUno]==false && block.timestamp < MeseUno)
PagamentoBloccato[MeseUno]=true;
else if (PagamentoBloccato[MeseDue]==false && block.timestamp > MeseUno
&& block.timestamp < MeseDue)
PagamentoBloccato[MeseDue]=true;
else if (PagamentoBloccato[MeseTre]==false && block.timestamp > MeseDue
&& block.timestamp < MeseTre)
PagamentoBloccato[MeseTre]=true;
else revert(“il pagamento e’ gia’ stato bloccato o non ci sono le condizioni per bloccare il pagamento”);

payable(Tizio).transfer(address(this).balance); //restituisce gli Ether rimanenti ad Tizio, N.B. altrimenti imprigionati.
Motivazione = _motivazione;
return Motivazione; //restituisci la motivazione fornita da Tizio
}

}

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.2;

contract TrasferimentoEth {

//Variabili di stato

//parti
address Tizio; //committente
address Caio; //prestatore d’opera

//Indicatori di tempo
uint DataDeploy; //Data deploy dello smart contract
uint MeseUno; //esigibilità primo pagamento
uint MeseDue; //esigibilità secondo pagamento
uint MeseTre; //esigibilità terzo pagamento

//Database delle operazioni
mapping(uint=>bool) Riscosso; // “true” indica che la rata è già stata riscossa
mapping(uint=>bool) PagamentoBloccato; //”true” quando il committente blocca l’esecuzione della prestazione di pagamento

//Dati
string Motivazione; //motivazione fornita da Tizio all’interruzione del pagamento


constructor() payable{ //payable= il contratto puo’ ricevere Ether

//definiamo le parti
Tizio = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
Caio = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2;

//definiamo le variabili cronologiche
DataDeploy = block.timestamp; //la variabile assumerà il timestamp del momento in cui avviene il DataDeploy
MeseUno= DataDeploy + 10 seconds; //data esigibilità primo pagamento, 10 giorni dal deploy;
MeseDue= MeseUno + 30 seconds; //data esigibilità secondo pagamento, 40 giorni dal deploy;
MeseTre= MeseDue + 30 seconds; //data esigibilità terzo pagamento, 70 giorni dal deploy;
}

/*Definizione delle funzioni, in ordine di scrittura:
– Una funzione per inviare Ether al contratto;
– Una funzione per leggere il bilancio dello SC.
– Tre funzioni per la riscossione delle rate a favore di Caio;
– Una funzione ad uso esclusivo di Tizio, per interrompere l’esecuzione del pagamento
e ottenere la restituzione dell’importo restante all’interno dello SC;
*/

//function per inviare Ether allo SC
function TraferisciEtherAlloSC() external payable { //1 wei = 10^(-18) ether.
}

//function per conoscere il bilancio dello SC.
function BilancioSC() external view returns(uint){
return address(this).balance;
}

function PagamentoPrimaRata () external { //funzione per riscuotere il pagamento relativo alla prima rata.
require(Riscosso[MeseUno]==false, “Mensilita’ gia’ riscossa”);
require(PagamentoBloccato[MeseUno]==false, “il pagamento e’ stato bloccato da Tizio”);
require(block.timestamp >= MeseUno, “troppo presto per riscuotere”);

payable(Caio).transfer(3000000000000000000); //traferisci a Caio 3 Ether
Riscosso[MeseUno]=true; //aggiorna database
}

function PagamentoSecondaRata() external { //funzione per riscuotere il pagamento relativo alla seconda rata.
require(Riscosso[MeseDue]==false, “Mensilita’ gia’ riscossa”);
require(PagamentoBloccato[MeseUno]==false && PagamentoBloccato[MeseDue]==false, “il pagamento e’ stato bloccato da Tizio”);
require(block.timestamp >= MeseDue, “troppo presto per riscuotere”);

payable(Caio).transfer(3000000000000000000); // Pagamento 3 Ether
Riscosso[MeseDue]=true;
}

function PagamentoTerzaRata () external { //funzione per riscuotere il pagamento relativo alla terza rata.
require(Riscosso[MeseTre]==false, “Mensilita’ gia’ riscossa”);
require(PagamentoBloccato[MeseUno]==false && PagamentoBloccato[MeseDue]==false
&& PagamentoBloccato[MeseTre]==false, “il pagamento e’ stato bloccato da Tizio”);
require(block.timestamp >= MeseTre, “troppo presto per riscoutere”);

payable(Caio).transfer(3000000000000000000); // Pagamento 3 Ether
Riscosso[MeseTre]=true;
}

//una function ad uso esclusivo di Tizio che permette l’interruzione della prestazione di pagamento.
function BloccaPagamentoRata(string memory _motivazione) external returns(string memory){
require(msg.sender==Tizio, “Non sei Tizio”);
if (PagamentoBloccato[MeseUno]==false && block.timestamp < MeseUno)
{PagamentoBloccato[MeseUno]=true;
payable(Tizio).transfer(9000000000000000000);}

else if (PagamentoBloccato[MeseDue]==false && block.timestamp > MeseUno
&& block.timestamp < MeseDue)
{PagamentoBloccato[MeseDue]=true;
payable(Tizio).transfer(6000000000000000000); }

else if (PagamentoBloccato[MeseTre]==false && block.timestamp > MeseDue
&& block.timestamp < MeseTre)
{PagamentoBloccato[MeseTre]=true;
payable(Tizio).transfer(3000000000000000000);}

else revert(“il pagamento e’ gia’ stato bloccato o non ci sono le condizioni per bloccare il pagamento”);

//RIMUOVI payable(Tizio).transfer(address(this).balance); //restituisce gli Ether rimanenti ad Tizio, N.B. altrimenti imprigionati.
Motivazione = _motivazione;
return Motivazione; //restituisci la motivazione fornita da Tizio
}

}