From bdf2d6791f7fec821564903d29ea955173d5c099 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Thu, 4 Aug 2022 23:20:03 +0200
Subject: [PATCH 01/26] Update 3-msgsender.md
Translation improvement
---
it/2/3-msgsender.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/it/2/3-msgsender.md b/it/2/3-msgsender.md
index 653e39e5d7..7864523eb6 100644
--- a/it/2/3-msgsender.md
+++ b/it/2/3-msgsender.md
@@ -82,13 +82,13 @@ material:
}
---
-Ora che abbiamo i nostri mapping per tenere traccia di chi possiede uno zombi, vorremmo aggiornare il metodo `_createZombie` per usarli.
+Ora che abbiamo i nostri mapping per tenere traccia di chi possiede uno zombi, possiamo usarli aggiornando il metodo `_createZombie`.
Per fare ciò dobbiamo usare qualcosa chiamato `msg.sender`.
## msg.sender
-In Solidity esistono alcune variabili globali che sono disponibili per tutte le funzioni. Una di queste è "msg.sender", che si riferisce all'`address` della persona (o contratto intelligente) che ha chiamato la funzione corrente.
+In Solidity esistono alcune variabili globali disponibili per tutte le funzioni. Una di queste è "msg.sender", che si riferisce all'`address` della persona (o contratto intelligente) che ha chiamato la funzione corrente.
> Nota: in Solidity l'esecuzione della funzione deve sempre iniziare con un chiamante esterno. Un contratto siederà sulla blockchain senza fare nulla fino a quando qualcuno non chiama una delle sue funzioni. Quindi ci sarà sempre un `msg.sender`.
@@ -110,9 +110,9 @@ function whatIsMyNumber() public view returns (uint) {
}
```
-In questo banale esempio chiunque potrebbe chiamare `setMyNumber` e memorizzare un `uint` nel nostro contratto, che sarebbe legato al loro indirizzo. Quindi quando hanno chiamato `whatIsMyNumber` sono stati restituiti gli `uint` che avevano archiviato.
+In questo banale esempio chiunque potrebbe chiamare `setMyNumber` e memorizzare un `uint` nel nostro contratto, legandolo così al proprio indirizzo. Successivamente, lo stesso utente può ottenere il valore `uint` che ha salvato in precedenza semplicemente chiamando `whatIsMyNumber`.
-L'uso di `msg.sender` ti offre la sicurezza della blockchain di Ethereum - l'unico modo in cui qualcuno può modificare i dati di qualcun altro sarebbe quello di rubare la chiave privata associata al suo indirizzo Ethereum.
+L'uso di `msg.sender` garantisce la sicurezza della blockchain di Ethereum - l'unico modo in cui qualcuno può modificare i dati di qualcun altro è rubare la chiave privata associata al suo indirizzo Ethereum.
# Facciamo una prova
From b2527a6044f6a69da1debe1df68f8fa9d727c8ca Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Thu, 4 Aug 2022 23:35:10 +0200
Subject: [PATCH 02/26] improvement translation
---
it/2/5-inheritance.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/it/2/5-inheritance.md b/it/2/5-inheritance.md
index d1aa0da9ec..2c88c2d83e 100644
--- a/it/2/5-inheritance.md
+++ b/it/2/5-inheritance.md
@@ -93,7 +93,7 @@ material:
---
-Il nostro codice di gioco sta diventando piuttosto lungo. Invece di creare un contratto estremamente lungo, a volte, ha senso dividere la logica del codice su più contratti per organizzare il codice.
+Il codice del nostro gioco sta diventando piuttosto lungo. Invece di creare un contratto estremamente lungo, a volte, ha senso dividere la logica su più contratti per organizzare il codice.
Una caratteristica di Solidity che lo rende più gestibile è il contratto **_eredità_** (**_inheritance_**):
@@ -117,6 +117,6 @@ Questo può essere usato per l'eredità logica (come fosse una sottoclasse, un `
# Facciamo una prova
-Nei prossimi capitoli implementeremo la funzionalità per i nostri zombi di nutrirsi e moltiplicarsi. Mettiamo questa logica nel suo contratto che eredita tutti i metodi da `ZombieFactory`.
+Nei prossimi capitoli implementeremo la funzionalità per i nostri zombi di nutrirsi e moltiplicarsi. Mettiamo questa logica in un nuovo contratto che eredita tutti i metodi da `ZombieFactory`.
-1. Crea un contratto chiamato `ZombieFeeding` sotto `ZombieFactory`. Questo contratto dovrà ereditare dal nostro contratto `ZombieFactory`.
\ No newline at end of file
+1. Crea un contratto chiamato `ZombieFeeding` sotto `ZombieFactory`. Questo contratto dovrà ereditare dal nostro contratto `ZombieFactory`.
From 1aade06a15014805c617d4b664643a7bb9cd88b7 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Thu, 4 Aug 2022 23:41:51 +0200
Subject: [PATCH 03/26] english text removed
---
it/2/6-importfiles.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/it/2/6-importfiles.md b/it/2/6-importfiles.md
index 6d01471245..746597ecb0 100644
--- a/it/2/6-importfiles.md
+++ b/it/2/6-importfiles.md
@@ -77,7 +77,6 @@ contract newContract is SomeOtherContract {
}
```
-So if we had a file named `someothercontract.sol` in the same directory as this contract (that's what the `./` means), it would get imported by the compiler.
Quindi se avessimo un file chiamato `someothercontract.sol` nella stessa directory di questo contratto (ecco cosa significa `./`), esso verrebbe importato dal compilatore.
# Facciamo una prova
From cd28f272b98c7d61ec1b861723bbcd711bb197c4 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Thu, 4 Aug 2022 23:51:14 +0200
Subject: [PATCH 04/26] improvement translation
---
it/2/7-storage.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/it/2/7-storage.md b/it/2/7-storage.md
index 7eefa84170..c27918d702 100644
--- a/it/2/7-storage.md
+++ b/it/2/7-storage.md
@@ -69,7 +69,7 @@ material:
}
---
-In Solidity, there are two places you can store variables — in `storage` and in `memory`.
+In Solidity puoi salvare le variabili all'interno di `storage` o dentro `memory`.
**_Storage_** si riferisce alle variabili memorizzate in modo permanente sulla blockchain. Le variabili **_Memory_** invece sono temporanee e vengono cancellate tra le chiamate di funzioni esterne al contratto. Pensalo come il disco rigido del tuo computer rispetto alla RAM.
From ccbb5454263d626663ce27a5f6739f47a6ee9932 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 09:11:05 +0200
Subject: [PATCH 05/26] fix ita translate
---
it/3/00-overview.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/it/3/00-overview.md b/it/3/00-overview.md
index 6f2230fbb3..fe8c75218e 100644
--- a/it/3/00-overview.md
+++ b/it/3/00-overview.md
@@ -13,4 +13,4 @@ Questa lezione sarà un pò meno appariscente (scusate, nessun colpo di scena!).
Sei stato avvisato: niente gattini e arcobaleni nella Lezione 3!
-Ma qui molta conoscenza di Solidità è densamente raggruppata. Ti consigliamo vivamente di completare la lezione 2 prima di iniziare questa.
+Qui vengono illustrati molti concetti fondamentali di Solidity. Ti consigliamo vivamente di completare la lezione 2 prima di iniziare questo capitolo.
From 0b6d4aa4045345fc5431a13d8264f6dc85b31e00 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 09:34:06 +0200
Subject: [PATCH 06/26] Update 03-onlyowner.md
---
it/3/03-onlyowner.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/it/3/03-onlyowner.md b/it/3/03-onlyowner.md
index 3a5e4316fa..56cf14390a 100644
--- a/it/3/03-onlyowner.md
+++ b/it/3/03-onlyowner.md
@@ -218,7 +218,7 @@ material:
}
---
-Ora che il nostro contratto di base `ZombieFactory` eredita da `Ownable`, possiamo usare il modificatore di funzione `onlyOwner` anche in `ZombieFeeding`.
+Ora che il nostro contratto di base `ZombieFactory` eredita da `Ownable`, possiamo usare il modificatore di funzione `onlyOwner` anche in `ZombieFeeding`.
Ciò è dovuto al modo in cui funziona l'eredità del contratto. Ricorda:
From b04632f1dd478aba61901ac910dbd7c504061a0f Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 09:37:07 +0200
Subject: [PATCH 07/26] Update 04-gas.md
---
it/3/04-gas.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/it/3/04-gas.md b/it/3/04-gas.md
index 8cbb3d7c59..7217fdf83c 100644
--- a/it/3/04-gas.md
+++ b/it/3/04-gas.md
@@ -237,13 +237,13 @@ I creatori di Ethereum volevano assicurarsi che qualcuno non potesse ostruire la
## Struttura ad incastro per risparmiare gas
-Nella Lezione 1 abbiamo menzionato che ci sono altri tipi di `uint`s: `uint8`, `uint16`, `uint32`, ecc.
+Nella Lezione 1 abbiamo menzionato che ci sono altri tipi di `uint`: `uint8`, `uint16`, `uint32`, ecc.
Normalmente non c'è alcun vantaggio nell'utilizzare questi sottotipi perché Solidity riserva 256 bit di memoria indipendentemente dalla dimensione `uint`. Ad esempio, l'uso di `uint8` invece di `uint` (`uint256`) non ti farà risparmiare alcun gas.
-Ma c'è un'eccezione a questo: dentro `struct`s.
+Ma c'è un'eccezione a questo: inserire gli `uint` all'interno di uno `struct`.
-Se hai più `uint`s all'interno di una struttura, l'uso di un `uint` di dimensioni minori, quando possibile, consentirà a Solidity di raggruppare queste variabili per occupare meno spazio di archiviazione. Per esempio:
+Se hai più `uint` all'interno di una struttura, l'uso di un `uint` di dimensioni minori, quando possibile, consentirà a Solidity di raggruppare queste variabili per occupare meno spazio di archiviazione. Per esempio:
```
struct NormalStruct {
From a7cb669fd2c39a361a23ae829778357627afa224 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 09:51:02 +0200
Subject: [PATCH 08/26] Update 06-zombiecooldowns.md
---
it/3/06-zombiecooldowns.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/it/3/06-zombiecooldowns.md b/it/3/06-zombiecooldowns.md
index a06ac955e9..01fcd1c34e 100644
--- a/it/3/06-zombiecooldowns.md
+++ b/it/3/06-zombiecooldowns.md
@@ -243,7 +243,7 @@ Questo farà in modo che gli zombi non potranno nutrirsi illimitatamente di gatt
Innanzitutto definiremo alcune funzioni di aiuto che ci consentono di impostare e controllare il `readyTime` di uno zombi.
-## Passando le strutture come argomenti
+## Passare le strutture come argomenti
È possibile passare un puntatore di archiviazione ad una struttura come argomento di una funzione `private` o `internal`. Ciò è utile, ad esempio, per passare le nostre strutture `Zombie` tra le funzioni.
From 55b628845e8f756c9c8a9a25b94ddf1644d3a288 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 10:07:45 +0200
Subject: [PATCH 09/26] Update 07-zombiecooldowns2.md
---
it/3/07-zombiecooldowns2.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/it/3/07-zombiecooldowns2.md b/it/3/07-zombiecooldowns2.md
index d1d06d0428..117e789acf 100644
--- a/it/3/07-zombiecooldowns2.md
+++ b/it/3/07-zombiecooldowns2.md
@@ -246,7 +246,7 @@ Guardando la storia di questa funzione, puoi vedere che l'abbiamo resa `public`
Riesaminiamo questa particolare funzione, l'utente può chiamare direttamente la funzione e passare qualsiasi `_targetDna` o `_species` che desidera. Così non sembra un gioco: vogliamo che seguano le nostre regole!
-Con un esame più attento, questa funzione dovrà essere chiamata solo da `feedOnKitty()` quindi il modo più semplice per prevenire questi exploit è renderla `internal`.
+Esaminando più attentamente notiamo che questa funzione dovrà essere chiamata solo da `feedOnKitty()` quindi il modo più semplice per prevenire questi exploit è renderla `internal`.
## Facciamo una prova
From f8a7f841b94d941a351d8afebaac1ee588ba46d0 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 10:09:49 +0200
Subject: [PATCH 10/26] Update 09-zombiemodifiers.md
Fixed wrong suggestion inside description in step 2
request -> require
---
it/3/09-zombiemodifiers.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/it/3/09-zombiemodifiers.md b/it/3/09-zombiemodifiers.md
index f17e3d93b3..10f4ec1f83 100644
--- a/it/3/09-zombiemodifiers.md
+++ b/it/3/09-zombiemodifiers.md
@@ -240,7 +240,7 @@ function driveCar(uint _userId) public olderThan(16, _userId) {
1. Creare una funzione chiamata `changeName`. Ci vorranno 2 argomenti: `_zombieId` (un `uint`) e `_newName` (una `string`), inoltre lo renderemo `external`. Dovrebbe avere il modificatore `aboveLevel` e dovrebbe passare `2` per il parametro `_level`. (Non dimenticare di passare anche lo `_zombieId`).
-2. Per prima cosa in questa funzione dobbiamo verificare che `msg.sender` sia uguale a `zombieToOwner[_zombieId]`. Utilizzare un'istruzione `request`.
+2. Per prima cosa in questa funzione dobbiamo verificare che `msg.sender` sia uguale a `zombieToOwner[_zombieId]`. Utilizzare un'istruzione `require`.
3. Quindi la funzione dovrebbe impostare `zombies[_zombieId].name` uguale a `_newName`.
From 269c40d1b2dbd13103b3218b5b509209855617a0 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 11:01:05 +0200
Subject: [PATCH 11/26] Update 12-forloops.md
---
it/3/12-forloops.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/it/3/12-forloops.md b/it/3/12-forloops.md
index 2e2b45958f..84f7fa899f 100644
--- a/it/3/12-forloops.md
+++ b/it/3/12-forloops.md
@@ -262,11 +262,11 @@ Questo approccio è allettante per la sua semplicità. Ma vediamo cosa succede s
Tale funzione di trasferimento dovrebbe:
1. Inserire lo zombi sull'array `ownerToZombies` del nuovo proprietario,
-2. Rimuovi lo zombi dall'array `ownerToZombies` del vecchio proprietario,
-3. Sposta tutti gli zombi nell'array del proprietario più vecchio di un posto per riempire il buco, e poi
-4. Riduci la lunghezza dell'array di 1.
+2. Rimuovere lo zombi dall'array `ownerToZombies` del vecchio proprietario,
+3. Spostare tutti gli zombi nell'array del proprietario più vecchio di un posto per riempire il buco, e poi
+4. Ridurre la lunghezza dell'array di 1.
-Lo step 3 sarebbe estremamente costoso dal punto di vista del gas, dal momento che dovremmo scrivere per ogni zombi di cui abbiamo cambiato la posizione. Se un proprietario ha 20 zombi e scambia il primo, dovremmo fare 19 scritture per mantenere l'ordine dell'array.
+Lo step 3 sarebbe estremamente costoso dal punto di vista del gas, dal momento che dovremmo effettuare un'operazione di scrittura per ogni zombi di cui abbiamo cambiato la posizione. Se un proprietario ha 20 zombi e scambia il primo, dovremmo fare 19 operazioni di scrittura per mantenere l'ordine dell'array.
Poiché la scrittura su memoria è una delle operazioni più costose in Solidity, ogni chiamata a questa funzione di trasferimento sarebbe estremamente costosa dal punto di vista del gas. E peggio ancora, costerebbe una diversa quantità di gas ogni volta che viene chiamata, a seconda di quanti zombi ha l'utente nel proprio esercito e dell'indice dello zombi scambiato. Quindi l'utente non saprebbe quanto gas inviare esattamente.
From 5cfe47323313f13ee4e0319ba98bc8cb6e2f99fc Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 11:12:14 +0200
Subject: [PATCH 12/26] Update payable.md
---
it/4/payable.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/it/4/payable.md b/it/4/payable.md
index a3583ce8e4..4004aaf101 100644
--- a/it/4/payable.md
+++ b/it/4/payable.md
@@ -263,7 +263,7 @@ material:
}
---
-Fino ad ora abbiamo nascosto alcune **_funzioni di modifica_**. Può essere difficile ricordare tutto, quindi passiamo a una breve recensione:
+Fino ad ora abbiamo nascosto alcune **_funzioni di modifica_**. Può essere difficile ricordare tutto, facciamo un breve riassunto di ciò che abbiamo imparato:
1. Abbiamo modificatori di visibilità che controllano da dove e quando la funzione può essere chiamata: `private` significa che è richiamabile solo da altre funzioni all'interno del contratto; `internal` è come `private` ma può anche essere chiamata da contratti che ereditano; `external` può essere chiamata solo al di fuori del contratto; ed infine `public` può essere chiamata ovunque, sia internamente che esternamente.
@@ -277,7 +277,7 @@ Tutti questi modificatori possono essere impilati insieme su una definizione di
function test() external view onlyOwner anotherModifier { /* ... */ }
```
-In questo capitolo introdurremo un altra funzione di modifica: `payable`.
+In questo capitolo introdurremo un'altra funzione di modifica: `payable`.
## Il modificatore `payable`
@@ -285,7 +285,7 @@ Le funzioni `payable` fanno parte di ciò che rendono Solidity ed Ethereum così
Riflettici un minuto. Quando chiami una funzione API su un normale server web, non puoi inviare dollari USA insieme alla tua chiamata di funzione, né puoi inviare Bitcoin.
-Ma in Ethereum poiché sia il denaro (_Ether_), che i dati (*transaction payload*), che il codice del contratto stesso vivono tutti su Ethereum, è possibile chiamare una funzione **e** pagare il contratto al lo stesso tempo.
+Ma in Ethereum poiché sia il denaro (_Ether_), che i dati (*transaction payload*), che il codice del contratto stesso vivono tutti su Ethereum, è possibile chiamare una funzione **e** pagare il contratto allo stesso tempo.
Ciò consente una logica davvero interessante, come richiedere un certo pagamento al contratto per eseguire una funzione.
From b76e1ee0075362485d06fefda2c977160aaba713 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 11:26:59 +0200
Subject: [PATCH 13/26] Update battle-02.md
---
it/4/battle-02.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/it/4/battle-02.md b/it/4/battle-02.md
index 1210257dbc..e81cb36e78 100644
--- a/it/4/battle-02.md
+++ b/it/4/battle-02.md
@@ -287,7 +287,7 @@ In Ethereum, quando si chiama la funzione di un contratto, si trasmette una tran
Quando un nodo ha risolto un PoW, gli altri nodi smettono di tentare di risolverlo, controllano che l'elenco delle transazioni dell'altro nodo sia valido, accettano il blocco e procedono alla risoluzione del blocco successivo.
-**Questo rende utilizzabile la nostra funzione di numero casuale.**
+**Questo renderebbe inutilizzabile la nostra funzione di numeri casuali.**
Immagina di avere un contratto testa o croce, o raddoppi i tuoi soldi o perdi tutto. Usa la funzione di sopra per determinare se è testa o croce. (`random >= 50` è testa, `random < 50` è croce).
From 5391cab18ba283940377f5d04c4b84fd5e2d05c7 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 11:32:27 +0200
Subject: [PATCH 14/26] Update battle-04.md
English text removed
---
it/4/battle-04.md | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/it/4/battle-04.md b/it/4/battle-04.md
index ceeab4b13b..73f9a74630 100644
--- a/it/4/battle-04.md
+++ b/it/4/battle-04.md
@@ -324,15 +324,12 @@ Prenditi un momento... Fai riferimento ad alcune delle nostre lezioni precedenti
La risposta è qua sotto, non continuare fino a quando non ci hai pensato.
## La Risposta
-
-We've done this check multiple times now in previous lessons. In `changeName()`, `changeDna()`, and `feedAndMultiply()`, we used the following check:
-Abbiamo eseguito questo controllo più volte nelle lezioni precedenti. In `changeName()`, `changeDna()` e `feedAndMultiply()`, abbiamo usato il seguente controllo:
+Abbiamo eseguito questo controllo più volte nelle lezioni precedenti. In `changeName()`, `changeDna()` e `feedAndMultiply()`, abbiamo usato:
```
require(msg.sender == zombieToOwner[_zombieId]);
```
-This is the same logic we'll need for our `attack` function. Since we're using the same logic multiple times, let's move this into its own `modifier` to clean up our code and avoid repeating ourselves.
Questa è la stessa logica di cui avremo bisogno per la nostra funzione di attacco. Dato che stiamo usando la stessa logica più volte, spostiamola nel suo `modifier` per ripulire il nostro codice ed evitare di ripeterci.
## Facciamo una prova
From 6e5c9c84105d70bc9a7e2ca4ceacb95bde975814 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 11:49:08 +0200
Subject: [PATCH 15/26] Update 01.md
English text removed
---
it/6/01.md | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/it/6/01.md b/it/6/01.md
index c892f635d1..710ab5b568 100644
--- a/it/6/01.md
+++ b/it/6/01.md
@@ -523,8 +523,6 @@ Oppure puoi semplicemente scaricare il file `.js` minimizzato da Nota: tutti gli esempi di codice che utilizziamo in questa lezione utilizzano la **versione 1.0** di Web3.js, che utilizza promises anziché callbacks. Molti altri tutorial che vedrai online utilizzano una versione precedente di Web3.js. La sintassi è cambiata molto con la versione 1.0, quindi se stai copiando il codice da altri tutorial, assicurati che stiano usando la tua stessa versione!
From b76c7b94f8cd5cf032dae50a0b700cc06a97c8b0 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 18:48:26 +0200
Subject: [PATCH 18/26] Update 07.md
Code specification to solve the quest has been translated, got error while submit them. Removed translation on them.
---
it/6/07.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/it/6/07.md b/it/6/07.md
index c3a33cb5d4..b888c4be07 100644
--- a/it/6/07.md
+++ b/it/6/07.md
@@ -716,8 +716,8 @@ Abbiamo aggiunto un `div` con ID `txStatus` — in questo modo possiamo usare qu
a) Chiama la seconda funzione `feedOnKitty` che accetta 2 argomenti: `zombieId` e `kittyId`
- b) Il testo `#txStatus` dovrebbe aggiornarsi in: `"Mangiando un gattino. Questo potrebbe richiedere del tempo..."`
+ b) Il testo `#txStatus` dovrebbe aggiornarsi in: `"Eating a kitty. This may take a while..."`
c) Chiama `feedOnKitty` sul nostro contratto e passa gli stessi 2 argomenti
- d) Il messaggio di successo su `#txStatus` dovrebbe essere:`"Mangiato un gattino e generato un nuovo Zombi!"`
+ d) Il messaggio di successo su `#txStatus` dovrebbe essere:`"Ate a kitty and spawned a new Zombie!"`
From f9ef898eab4e341458a062ff21d0c01d2d1c6953 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 18:54:16 +0200
Subject: [PATCH 19/26] Update 08.md
Code specification translated and error on submit of the code, removed.
---
it/6/08.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/it/6/08.md b/it/6/08.md
index f85aaa1f4b..e23cb2b1f0 100644
--- a/it/6/08.md
+++ b/it/6/08.md
@@ -684,7 +684,7 @@ material:
La logica di `attack`, `changeName` e `changeDna` sarà estremamente simile, sono banali da implementare e quindi non passeremo il tempo a codificarli in questa lezione.
-> In effetti c'è già molta logica ripetitiva in ognuna di queste chiamate di funzione, quindi probabilmente avrebbe senso rifattorizzare e mettere il codice comune nella propria funzione. (E stiamo usando un sistema di template per i messaggi `txStatus` — vedamo così quanto sarebbero più pulite le cose con un framework come Vue.js!)
+> In effetti c'è già molta logica ripetitiva in ognuna di queste chiamate di funzione, quindi probabilmente avrebbe senso rifattorizzare e mettere il codice comune in un'unica funzione. (E stiamo usando un sistema di template per i messaggi `txStatus` — vediamo così quanto sarebbero più pulite le cose con un framework come Vue.js!)
Diamo un'occhiata ad un altro tipo di funzione che richiede un trattamento speciale in Web3.js — funzioni `payable` (pagabili).
@@ -725,10 +725,10 @@ Aggiungiamo una funzione `levelUp` sotto `feedOnKitty`. Il codice sarà molto si
1. La funzione prenderà 1 parametro, `zombieId`
-2. Pre-transazione dovrebbe visualizzare il testo `txStatus` come `"Il tuo zombie stà salendo di livello..."`
+2. Pre-transazione dovrebbe visualizzare il testo `txStatus` come `"Leveling up your zombie..."`
3. Quando chiama `levelUp` sul contratto, dovrebbe inviare `"0.001"` ETH convertito in `Wei`, come nell'esempio di sopra
-4. In caso di successo, dovrebbe essere visualizzato il messaggio `"Potenza travolgente! Lo zombi è salito di livello con successo"`
+4. In caso di successo, dovrebbe essere visualizzato il messaggio `"Power overwhelming! Zombie successfully leveled up"`
5. **Non** dobbiamo ridisegnare l'interfaccia utente interrogando il nostro contratto intelligente con `getZombiesByOwner` — perché in questo caso sappiamo che l'unica cosa che è cambiata è il livello di uno zombi.
From fdc8736cb95feda5e7f56bbafb610c9383cf0d06 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+lonasozo@users.noreply.github.com>
Date: Sun, 7 Aug 2022 19:12:06 +0200
Subject: [PATCH 20/26] Create 00-overview.md
---
it/11/00-overview.md | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 it/11/00-overview.md
diff --git a/it/11/00-overview.md b/it/11/00-overview.md
new file mode 100644
index 0000000000..6e25d92ca0
--- /dev/null
+++ b/it/11/00-overview.md
@@ -0,0 +1,28 @@
+---
+title: Testare Smart Contracts con Truffle
+header: Testare Smart Contracts con Truffle
+roadmap: roadmap.jpg
+path: solidity_advanced
+position: 1
+publishedOn: Cryptozombies
+---
+
+Benvenuto! Completando le lezioni precedenti hai dimostrato hai le competenze necessarie per proseguite.
+
+Quindi andiamo avanti e rilasciamo il gioco sulla Mainnet. Goditi il successo!
+
+Prenditi un attimo...ci sono _alcune cose_ che potrebbero esserti già venute in mente. Dopo tutto, una volta che i contratti vengono rilasciare sulla mainnet, restanno lì per sempre. Se sono presenti degli errori, resteranno anche loro lì per sempre. Come zombie immortali.
+
+Errori o _**bugs**_ succedono a tutti gli sviluppatori, non importa quante competenze hai. Non vorresti dare il 100% di chance di vittoria ad uno zombie che effettua un attacco, ma può succedere.
+
+Chiaramento dare all'attaccante il 100% di possibilità di vittoria vorrebbe dire che non è più un gioco, o comunque non è più divertente. Un bug come questo distruggerebbe il tuo gioco e non ci sarebbe nulla da fare per i tuoi zombie.
+
+Per impedire che questa cosa terribile accada, è essenziale testare a fondo ogni aspetto del gioco.
+
+Alla fine della lezione sarai in grado di:
+
+- Testare i tuoi smart contracts con `Truffle` contro `Ganache`
+- Usare `Chai` per scrivere affermazioni più espressive
+- Testare `Loom`😉
+
+Iniziamo!
From 7c8474747d03522970069faae001bf4020abeb35 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+viddom@users.noreply.github.com>
Date: Tue, 9 Aug 2022 00:15:39 +0200
Subject: [PATCH 21/26] lesson 11, 01-02 translated (IT)
---
it/11/01.md | 64 ++++++++++++++++++++++++++++++++++++++++++++
it/11/02.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 141 insertions(+)
create mode 100644 it/11/01.md
create mode 100644 it/11/02.md
diff --git a/it/11/01.md b/it/11/01.md
new file mode 100644
index 0000000000..a4494177b6
--- /dev/null
+++ b/it/11/01.md
@@ -0,0 +1,64 @@
+---
+title: Introduzione
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+skipCheckAnswer: false
+material:
+ terminal:
+ help: Probabilmente dovresti lanciare il comando `touch test/CryptoZombies.js`😉
+ commands:
+ 'touch test/CryptoZombies.js':
+ hint: touch test/CryptoZombies.js
+ output: |
+---
+
+In questa lezione, vedremo la teoria dietro il testing degli Smart Contracts di **Etherium**, concentrandoci su **Truffle**, **Mocha**, e **Chai**. Avrai bisogno di un livello intermedio di conoscenza di **Solidity** e **JavaScript** per riuscire a completare la maggior parte delle lezioni.
+
+Se non conosci **Solidity**, o vuoi ripassare alcuni concetti, iniziare a imparare con la nostra prima lezione.
+
+Se non conosci **JavaScript**, considera la possibilità di seguire dei tutorial relativi ad esso prima di iniziare questa lezione.
+
+## Diamo un'occhiata al nostro progetto
+
+Se hai seguito le nostre precedenti lezioni, avresti dovuto costruire un gioco a tema zombi che è in gran parte pronto e la struttura dei tuoi file dovrebbe assomigliare a questa:
+
+```
+├── build
+ ├── contracts
+ ├── Migrations.json
+ ├── CryptoZombies.json
+ ├── erc721.json
+ ├── ownable.json
+ ├── safemath.json
+ ├── zombieattack.json
+ ├── zombiefactory.json
+ ├── zombiefeeding.json
+ ├── zombiehelper.json
+ ├── zombieownership.json
+├── contracts
+ ├── Migrations.sol
+ ├── CryptoZombies.sol
+ ├── erc721.sol
+ ├── ownable.sol
+ ├── safemath.sol
+ ├── zombieattack.sol
+ ├── zombiefactory.sol
+ ├── zombiefeeding.sol
+ ├── zombiehelper.sol
+ ├── zombieownership.sol
+├── migrations
+└── test
+. package-lock.json
+. truffle-config.js
+. truffle.js
+```
+
+Hai notato la cartella `test`? Questa è la cartella dove inseriremo i nostri test.
+
+_Truffle_ offre supporto per test scritti in _JavaScript_ e _Solidity_ ma, per questa lezione, manteremmo le cose semplici e utilizzeremo _JavaScript_.
+
+# Mettiamoci alla prova
+
+È buona norma creare un file di prova separato per ogni contratto e assegnargli il nome del contratto intelligente. Ciò semplifica la gestione dei test a lungo termine, soprattutto quando il progetto cresce e cambia.
+
+1. Nel terminale a destra, lancia il comando `touch test/CryptoZombies.js`.
diff --git a/it/11/02.md b/it/11/02.md
new file mode 100644
index 0000000000..09930c422c
--- /dev/null
+++ b/it/11/02.md
@@ -0,0 +1,77 @@
+---
+title: Introduzione (continua)
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ risposta: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ contract("CryptoZombies", (accounts) => {
+ it("should be able to create a new zombie", () => {
+
+ })
+ })
+---
+
+Andiamo avanti. in questo capitolo continuiamo con le impostazioni per scrivere e lanciare i nostri test.
+
+## Build Artifacts
+
+Ogni volta che si compila uno smart contract, il compilatore _Solidity_ genera un file JSON (denominato **build artefacts**) che contiene la rappresentazione binaria di quel contratto e lo salva nella cartella `build/contracts`.
+
+Successivamente, quando esegui una migrazione, _Truffle_ aggiorna questo file con le informazioni relative a quella rete.
+
+La prima cosa che devi fare ogni volta che inizi a scrivere una nuova suite di test è caricare gli artifacts di build del contratto con cui vuoi interagire. In questo modo, **Truffle** saprà come formattare le nostre chiamate di funzione in un modo comprensibile per il contratto.
+
+Vediamo subito un semplice esempio.
+
+Supponiamo che esistesse un contratto chiamato "MyAwesomeContract". Potremmo fare qualcosa del genere per caricare gli artifacts della build:
+
+```javascript
+const MyAwesomeContract = artifacts.require(“MyAwesomeContract”);
+```
+
+The function returns something called a **_contract abstraction_**. In a nutshell, a _contract abstraction_ hides the complexity of interacting with **Ethereum** and provides a convenient _JavaScript_ interface to our _Solidity_ smart contract. We'll be using it in the next chapters.
+
+La funzione restituisce qualcosa chiamato **_contract abstraction_**. In poche parole, una \__contract abstraction_ nasconde la complessità dell'interazione con **Ethereum** e fornisce una comoda interfaccia _JavaScript_ per il nostro smart contract in _Solidity_. Lo useremo nei prossimi capitoli.
+
+### La funzione contract()
+
+**Truffle** aggiunge un sottile involucro intorno alla **Mocha** per semplificare i test. Poiché il nostro corso si concentra sullo sviluppo di **Ethereum**, non entreremo nel troppo dettaglio su _Mocha_. Se vuoi saperne di più riguardo _Mocha_, vai sul loro sito ufficiale una volta che avrai terminato questa lezione. Per adesso devi solo capire cosa impararemo qui - Come fare:
+
+- **Test di gruppo** utilizzando la funzione `contract()`. Questa funzione estende la funzione `describe()` di **Mocha** fornendo una **lista di account per i test** e mantendo un po' di pulizia.
+
+ `contract()` prende due argomenti. Il primo, una `string`, deve indicare cosa testeremo. Il secondo parametro, un `callback`, è dove scriveremo effettivamente i nostri test.
+
+- **Eseguimaoli**: il modo in cui lo faremo è chiamare una funzione chiamata `it()` che accetta anche due argomenti: una `string` che descrive cosa fa effettivamente il test e un `callback`.
+
+Mettendolo tutto questo insieme, ecco un semplice test:
+
+```javascript
+contract('MyAwesomeContract', (accounts) => {
+ it('should be able to receive Ethers', () => {});
+});
+```
+
+> Nota: un test scritto bene spiega cosa fa effettivamente il codice. Assicurati che la descrizione della suite di test e il test case possano essere letti insieme come una **affermazione coerente**. Pensa come se stessi scrivendo della documentazione relativa al tuo codice.
+
+Ogni test che scriverai dovrà seguire questo schema. Sembra facile, non è vero?😁
+
+# Mettiti alla prova
+
+Ora che abbiamo creato un file `CryptoZombies.js` vuoto, è il momento di riempirlo.
+
+1. La prima riga di codice dovrebbe dichiarare un `const` chiamato `CryptoZombies` e impostarlo uguale al risultato della funzione `artifacts.require` con il nome del contratto che vogliamo testare come argomento.
+
+2. Quindi, vai avanti e copia/incolla il test qui in alto.
+3. Cambia il modo in cui chiamiamo `contract()` in modo tale che il primo parametro sia il nome del nostro smart contract.
+
+ > Nota: non preoccuparti dell'argomento `accounts`. Lo spiegheremo nel prossimo capitolo.
+
+4. Il primo parametro passato alla funzione `it()` (nel nostro esempio, cioè "should be able to receive Ether") dovrebbe essere il nome del nostro test. Dal momento che il nostro scopo è scrivere un test per la creazione di un nuovo zombi, assicurati che il primo parametro sia impostato su "should be able to create a new zombie".
+
+Abbiamo impostato la base. Andiamo al prossimo capitolo!
From 5c012257c9366b0c9653456dee77560e592b3516 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+viddom@users.noreply.github.com>
Date: Tue, 9 Aug 2022 08:47:59 +0200
Subject: [PATCH 22/26] lesson 11, 03-04 translated (IT)
---
it/11/03.md | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
it/11/04.md | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 146 insertions(+)
create mode 100644 it/11/03.md
create mode 100644 it/11/04.md
diff --git a/it/11/03.md b/it/11/03.md
new file mode 100644
index 0000000000..6b4b81b856
--- /dev/null
+++ b/it/11/03.md
@@ -0,0 +1,70 @@
+---
+title: Il primo test - Creazione di uno zombie
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ contract("CryptoZombies", (accounts) => {
+ //1. initialize `alice` and `bob`
+ it("should be able to create a new zombie", () => { //2. Make the callback async
+ })
+ })
+
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ it("should be able to create a new zombie", async () => {
+ })
+ })
+---
+
+Prima di rilasciare il tuo codice su **Ethereum**, è meglio testare i tuoi smart contract in locale.
+
+Puoi farlo utilizzando uno strumento chiamato Ganache, che installa un network **Ethereum** in locale.
+
+Ogni volta che _Ganache_ viene avviato, crea 10 account di prova e fornisce loro 100 Ether per semplificare i test. Poiché _Ganache_ e _Truffle_ sono strettamente integrati, possiamo accedere a questi account attraverso l'array `accounts` che abbiamo menzionato nel capitolo precedente.
+
+Ma usare `accounts[0]` e `accounts[1]` non renderebbe i nostri testi facilmente leggibili, giusto?
+
+Per facilitare la comprensione, utilizzeremo dei placeholder: Alice e Bob. Quindi, all'interno della funzione `contract()`, inizializziamoli in questo modo:
+
+```javascript
+let [alice, bob] = accounts;
+```
+
+> Nota: perdona la scarsa grammatica. In _JavaScript_, la convenzione prevede l'utilizzo di lettere minuscole per i nomi delle variabili.
+
+Perché Alice e Bob? C'è una grande tradizione che rende "Alice e Bob" o più brevemente "A e B" ampiamente utilizzati in crittografia, fisica, programmazione e altro ancora. È una storia breve ma interessante, e vale la pena leggere dopo il completamento di questa lezione.
+
+Ora facciamo il nostro primo test.
+
+## Creazione di un nuovo Zombie
+
+Supponiamo che Alice voglia giocare al nostro fantastico gioco. Se è così, la prima cosa che vorrebbe fare è **creare il proprio zombi 🧟**. Per farlo, il front-end (o _Truffle_ nel nostro caso) dovrebbe chiamare la funzione `createRandomZombie`.
+
+> Nota: per rifrescare la memoria riportiamo il codice _Solidity_ nel nostro contratto:
+
+```sol
+function createRandomZombie(string _name) public {
+ require(ownerZombieCount[msg.sender] == 0);
+ uint randDna = _generateRandomDna(_name);
+ randDna = randDna - randDna % 100;
+ _createZombie(_name, randDna);
+}
+```
+
+Iniziamo testando questa funzione
+
+# Testiamo
+
+1. La prima riga della funzione `contract()` dovrebbe dichiarare due variabili chiamate `alice` e `bob` e inizializzarle come mostrato sopra.
+
+2. Successivamente, vorremmo chiamare correttamente la funzione `it()`. Il secondo parametro (una funzione di `callback`) "parlerà" con la blockchain, per questo doremo renderla asincrona. Basta anteporre la parola chiave `async`. In questo modo, ogni volta che questa funzione viene chiamata con la parola chiave `await`, il nostro test attende una risposta prima di procedere.
+
+> Il funzionamento delle promises non è tra gli scopi di questa lezione. Una volta terminata questa lezione, dai un'occhiata alla documentazione ufficiale per approfondire l'argomento.
diff --git a/it/11/04.md b/it/11/04.md
new file mode 100644
index 0000000000..626025f0bc
--- /dev/null
+++ b/it/11/04.md
@@ -0,0 +1,76 @@
+---
+title: Il primo test - Creazione di uno zombie (continua)
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ it("should be able to create a new zombie", async () => {
+ // start here
+ })
+ })
+
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ it("should be able to create a new zombie", async () => {
+ const contractInstance = await CryptoZombies.new();
+ })
+ })
+---
+
+Ottimo lavoro! Ora che abbiamo una shell per il nostro primo test, lascia che ti spieghi come funziona.
+
+Solitamente, ogni test ha le seguenti fasi:
+
+1. **_set up_**: in cui definiamo lo stato iniziale e inizializziamo gli input.
+
+2. **_act_**: dove testiamo effettivamente il codice. Assicurati sempre di _testare solo una cosa_.
+
+3. **_assert_:** dove controlliamo i risultati.
+
+Diamo un'occhiata a cosa dovrebbe fare il nostro test in modo più dettagliato.
+
+## 1. Impostazione
+
+Nel Capitolo 2, hai imparato a creare una _contract abstraction_. Tuttavia, una \__contract abstraction_, come dice il nome, è solo un'astrazione. Per interagire effettivamente con il smart contract, dobbiamo creare un oggetto _JavaScript_ che fungerà da **istanza** del contratto. Continuando il nostro esempio con `MyAwesomeContract`, possiamo usare la _contract abstraction_ per inizializzare la nostra istanza in questo modo:
+
+```javascript
+const contractInstance = await MyAwesomeContract.new();
+```
+
+Bene, allora come andiamo avanti?
+
+Chiamare `createRandomZombie` richiede di passargli il nome dello zombi come parametro. Quindi, il passo successivo sarebbe dare un nome allo zombi di Alice. Qualcosa come "Alice's Awesome Zombie".
+
+Tuttavia, se lo facciamo per ogni test, il nostro codice non avrà un bell'aspetto. Un approccio migliore consiste nell'inizializzazione di un array globale come segue:
+
+```javascript
+const zombieNames = ['Zombie #1', 'Zombie #2'];
+```
+
+E poi, chiamare i metodi del contratto in questo modo:
+
+```javascript
+contractInstance.createRandomZombie(zombieNames[0]);
+```
+
+> Nota: l'uso di un array per memorizzare i nomi degli zombi è utile se vuoi, ad esempio, scrivere un test che crei 1000 zombi invece di uno o due😉.
+
+# Testiamo
+
+Siamo andati avanti e abbiamo inizializzato l'array `zombieNames` per te.
+
+1. Creiamo un'istanza del nostro contratto. Dichiara un nuovo `const` chiamato `contractInstance` e impostalo uguale al risultato della funzione `CryptoZombies.new()`.
+
+2. `CryptoZombies.new()` comunica con la blockchain. Ciò significa che deve essere una funzione asincrona. Aggiungiamo la parola chiave `await` prima della chiamata di funzione.
From 8569f3a0bc01b78e45b33ad7acb91d0dbe3127f8 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+viddom@users.noreply.github.com>
Date: Fri, 12 Aug 2022 11:21:18 +0200
Subject: [PATCH 23/26] lesson 11, 05-06 translated (IT)
---
it/11/05.md | 94 ++++++++++++++++++++++++++++++++++++
it/11/06.md | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 230 insertions(+)
create mode 100644 it/11/05.md
create mode 100644 it/11/06.md
diff --git a/it/11/05.md b/it/11/05.md
new file mode 100644
index 0000000000..42002d7ee8
--- /dev/null
+++ b/it/11/05.md
@@ -0,0 +1,94 @@
+---
+title: Il primo Test - Creazione di un nuovo zombi (continua)
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ it("should be able to create a new zombie", async () => {
+ const contractInstance = await CryptoZombies.new();
+ // start here
+ })
+ })
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ it("should be able to create a new zombie", async () => {
+ const contractInstance = await CryptoZombies.new();
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name, zombieNames[0]);
+ })
+ })
+---
+
+Ora che abbiamo le nostre papere -ehm zombie-, passiamo alla fase successiva... 🧟🦆🧟🦆🧟🦆🧟🦆🧟🦆🧟🦆
+
+## 2. Act
+
+Abbiamo raggiunto la parte in cui chiameremo la funzione che crea un nuovo zombie per Alice- `createRandomZombie`.
+
+Ma c'è un piccolo problema: come possiamo farlo in modo che il metodo "sa" chi lo chiama? Un altro modo per dirla sarebbe: come possiamo assicurarci che Alice (e non Bob) sarà la proprietaria di questo nuovo zombi?🧐
+
+Bene... il problema è risolto con la '_contract abstraction_'. Una delle caratteristiche di _Truffle_ è che racchiude l'implementazione originale di _Solidity_ e ci consente di specificare l'indirizzo che effettua la chiamata alla funzione passando quell'indirizzo come argomento.
+
+Il seguente chiama `createRandomZombie` e si assicura che `msg.sender` sia impostato sull'indirizzo di Alice:
+
+```javascript
+const result = await contractInstance.createRandomZombie(zombieNames[0], {
+ from: alice,
+});
+```
+
+Ora ho una domanda veloce per te: sai cosa viene memorizzato in `result`?
+
+#### Logs ed Eventi
+
+Una volta specificato il contratto che volevamo testare usando `artifacts.require`, _Truffle_ fornisce automaticamente i log generati dal nostro smart contract. Ciò significa che ora possiamo recuperare il `nome` dello zombi appena creato da Alice usando qualcosa del genere: `result.logs[0].args.name`. In modo simile, possiamo ottenere `id` e `_dna`.
+
+Oltre a queste informazioni, "result" ci fornirà molti altri dettagli utili sulla transazione:
+
+- `result.tx`: hash della transazione
+- `result.receipt`: un oggetto contenente la ricevuta della transazione. Se `result.receipt.status` è uguale a `true` significa che la transazione è andata a buon fine. In caso contrario, significa che la transazione non è riuscita.
+
+> Nota: tieni presente che i registri possono essere utilizzati anche come opzione molto più economica per archiviare i dati. Lo svantaggio è che non è possibile accedervi dall'interno dello smart contract stesso.
+
+## 3. Assertion
+
+In questo capitolo useremo il modulo di asserzione integrato che viene fornito con un insieme di funzioni di asserzione come `equal()` e `deepEqual()`. In poche parole, queste funzioni controllano la condizione e 'generano' un errore se il risultato non è quello previsto. Poiché confronteremo valori semplici, eseguiremo `assert.equal()`.
+
+# Testiamo
+
+Concludiamo il nostro primo test.
+
+1. Dichiara una variabile `const` chiamata `result` e impostala uguale al risultato di `contractInstance.createRandomZombie` con il nome dello zombi e il proprietario come argomenti (alice).
+
+2. Una volta ottenuto il `risultato`, chiama `assert.equal` con due argomenti: `result.receipt.status` e `true`.
+
+Se la condizione del punto 2. è vera, possiamo presumere che il nostro test sia stato superato. Per sicurezza, dato che siamo qui, possiamo aggiungere un altro controllo.
+
+1. Nella riga successiva, controlliamo se `result.logs[0].args.name` è uguale a `zombieNames[0]`. Usa `assert.equal`, proprio come abbiamo fatto sopra.
+
+Ora è il momento di eseguire il nostro primo "test di Truffle" e vedere se va a buon fine. Il modo in cui funziona è che _Truffle_ ispezionerà semplicemente la directory _"test"_ ed eseguirà i file che trova lì.
+
+In realtà, siamo andati avanti e l'abbiamo fatto per te. L'output dovrebbe assomigliare a questo:
+
+```bash
+Contract: CryptoZombies
+ ✓ should be able to create a new zombie (323ms)
+
+
+ 1 passing (768ms)
+```
+
+Questo conclude il tuo primo test: ben fatto! Ce ne sono molti altri in arrivo, quindi andiamo avanti con la prossima lezione...
diff --git a/it/11/06.md b/it/11/06.md
new file mode 100644
index 0000000000..4c7393972f
--- /dev/null
+++ b/it/11/06.md
@@ -0,0 +1,136 @@
+---
+title: Manteniamo il gioco divertente
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+
+ // start here
+
+ it("should be able to create a new zombie", async () => {
+ const contractInstance = await CryptoZombies.new();
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+
+ //define the new it() function
+ })
+
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ })
+ })
+---
+
+Ottimo lavoro! Ora sappiamo per certo che i nostri utenti possono creare nuovi zombi👌🏻.
+
+Tuttavia, se potessero continuare a chiamare questa funzione per creare zombi illimitati nel loro esercito, il gioco non sarebbe molto divertente. Pertanto, nel Capitolo 4 della lezione 2 abbiamo aggiunto un'istruzione `require` al `createZombieFunction()` che assicura che ogni utente non possa possedere più di uno zombi:
+
+```sol
+require(ownerZombieCount[msg.sender] == 0)
+```
+
+Proviamo questa funzione e vediamo se funziona.
+
+## Hooks
+
+In pochi minuti🤞, avremo più di un test e ognuno dovrebbe iniziare in modo pulito. Pertanto, per ogni singolo test dovremo creare una nuova istanza del nostro smart contract nel seguente questo modo:
+
+```javascript
+const contractInstance = await CryptoZombies.new();
+```
+
+Non sarebbe bello se potessi scriverlo solo una volta e fare in modo che _Truffle_ lo esegua automaticamente per ogni test?
+
+Bene... una delle caratteristiche di _Mocha_ (e _Truffle_) è la possibilità di eseguire alcuni frammenti di codice chiamati _hooks_ prima o dopo un test. Per eseguire qualcosa prima che un test venga eseguito, il codice dovrebbe essere inserito in una funzione denominata `beforeEach()`.
+
+Quindi, invece di scrivere `contract.new()` più volte, puoi farlo solo una volta in questo modo:
+
+```javascript
+beforeEach(async () => {
+ // let's put here the code that creates a new contract instance
+});
+```
+
+Poi, `Truffle` si occuperà di tutto. Così è tutto più semplice, vero?
+
+# Testiamo
+
+1. Sotto la riga di codice che inizializza `alice` e `bob`, dichiariamo una variabile denominata `contractInstance`. Per adesso non assegnarlo a nulla.
+
+ > Nota: vogliamo che l'ambito di `contractInstance` sia limitato al blocco in cui è definito. Usa `let` invece di `var`.
+
+2. Quindi, copia/incolla lo snippet dall'alto per definire la funzione `beforeEach()`.
+
+3. Compiliamo il corpo della nostra nuova funzione. Vai avanti e **sposta** la riga di codice che crea una nuova istanza di contratto all'interno della funzione `beforeEach()`. Ora che abbiamo definito `contractInstance` da un'altra parte, rimuovi il qualificatore `const`.
+
+4. Vorremo una nuova funzione `it` vuota per il nostro test. Imposta il nome del test (che è il primo parametro che stiamo passando alla funzione `it`) uguale a "should not allow two zombies".
+
+---
+
+### 🧟♂️Eccoli... zombi di ogni tipo!!!🧟♂️
+
+Se vuoi davvero **_raggiungere la padronanza_**, vai avanti e continua a leggere. Altrimenti... fai clic su Avanti e vai al capitolo successivo.
+
+Sei ancora qui?😁
+
+Stupendo! Dopotutto, perché dovresti negare a te stesso un sacco di meraviglie?
+
+Ora, torniamo indietro a come funziona `contract.new`. Fondamentalmente, ogni volta che chiamiamo questa funzione, _Truffle_ fa in modo che venga distribuito un nuovo contratto.
+
+Da un lato, questo è utile perché ci consente di iniziare ogni test con un ambiente pulito.
+
+D'altra parte, se tutti creassero innumerevoli contratti, la blockchain si riempirebbe inutilmente. Vogliamo che tu rimanga in giro, ma non vogliamo mantenere tutti i tuoi contratti di prova!
+
+Vorremmo evitare che ciò accada, giusto?
+
+Fortunatamente, la soluzione è piuttosto semplice... il nostro contratto dovrebbe "autodistruggersi" una volta che non è più necessario.
+
+Il modo in cui funziona è il seguente:
+
+- **prima**, vorremmo aggiungere una nuova funzione al contratto intelligente `CryptoZombie` in questo modo:
+
+```sol
+function kill() public onlyOwner {
+ selfdestruct(owner());
+}
+```
+
+> Nota: se vuoi saperne di più su `selfdestruct()`, puoi leggere i documenti _Solidity_ qui. La cosa più importante da tenere a mente è che la funzione "selfdestruct" è l'_unico_ modo in cui il codice a un certo indirizzo può essere rimosso dalla blockchain. Questo lo rende una caratteristica piuttosto importante!
+
+- **successivamente**, similmente alla funzione `beforeEach()` spiegata sopra, creeremo una funzione chiamata `afterEach()`:
+
+```javascript
+afterEach(async () => {
+ await contractInstance.kill();
+});
+```
+
+- **Infine**, _Truffle_ si assicurerà che questa funzione venga chiamata dopo l'esecuzione di ogni test.
+
+E voilà, lo smart contract si è distrutto da solo!
+
+Abbiamo ancora molti argomenti da trattare in questa lezione e l'implementazione di questa funzione richiederà probabilmente almeno 2 capitoli aggiuntivi. Confidiamo che lo aggiungerai.💪🏻
From d50c9f0dfa776428c26ff4ff068a416f9f119e94 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+viddom@users.noreply.github.com>
Date: Fri, 12 Aug 2022 16:06:18 +0200
Subject: [PATCH 24/26] Lessons 11 - 07-08 translated (IT)
---
it/11/07.md | 123 ++++++++++++++++++++++++++++++++
it/11/08.md | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 324 insertions(+)
create mode 100644 it/11/07.md
create mode 100644 it/11/08.md
diff --git a/it/11/07.md b/it/11/07.md
new file mode 100644
index 0000000000..75c79415ab
--- /dev/null
+++ b/it/11/07.md
@@ -0,0 +1,123 @@
+---
+title: Manteniamo il gioco divertente (continua)
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ const utils = require("./helpers/utils");
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ // start here
+ })
+ })
+ 'test/helpers/utils.js': |
+ async function shouldThrow(promise) {
+ try {
+ await promise;
+ assert(true);
+ }
+ catch (err) {
+ return;
+ }
+ assert(false, "The contract did not throw.");
+
+ }
+
+ module.exports = {
+ shouldThrow,
+ };
+
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ const utils = require("./helpers/utils");
+
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ })
+---
+
+In questo capitolo andremo a riempire il corpo nel nostro secondo test. Il secondo test dovrebbe eseguire i seguenti passaggi:
+
+- Primo, Alice dovrebbe chiamare `createRandomZombie` e impostare`zombieNames[0]`come nome del primo zombie.
+- Successivamente, Alice dovrebbe provare a creare il suo secondo zombi. L'unica cosa diversa è che questa volta il nome dello zombi dovrebbe essere impostato su `zombieNames[1]`.
+- A questo punto, ci aspettiamo che il contratto 'generi' un errore.
+- Poiché il nostro test dovrebbe essere superato solo se lo smart contract si interrompe, la nostra logica apparirà leggermente diversa. Dovremo racchiudere la seconda chiamata alla funzione `createRandomZombie` all'interno di un blocco `try/catch` come segue:
+
+```javascript
+try {
+ //try to create the second zombie
+ await contractInstance.createRandomZombie(zombieNames[1], { from: alice });
+ assert(true);
+} catch (err) {
+ return;
+}
+assert(false, 'The contract did not throw.');
+```
+
+Ora abbiamo esattamente quello che volevamo, giusto?
+
+Hmmm... siamo abbastanza vicini.
+Per mantenere i nostri test belli e ordinati, abbiamo spostato il codice sopra in `helpers/utils.js` e lo abbiamo importato in "CryptoZombies.js" in questo modo:
+
+```javascript
+const utils = require('./helpers/utils');
+```
+
+Ed ecco come dovrebbe apparire la riga di codice che chiama la funzione:
+
+```javascript
+await utils.shouldThrow(myAwesomeContractInstance.myAwesomeFunction());
+```
+
+# Testiamo
+
+Nel capitolo precedente, abbiamo creato una funzione vuota per il nostro secondo test. Completiamola.
+
+1. Per prima cosa, facciamo in modo che Alice crei il suo primo zombi. Dagli `zombieNames[0]` come nome e non dimenticare di impostare correttamente il proprietario.
+
+2. Dopo che Alice ha creato il suo primo zombie, esegui `shouldThrow` con `createRandomZombie` come parametro. Se non ricordi la sintassi per farlo, controlla l'esempio sopra. Ma prima, prova a farlo senza sbirciare.
+3. Fantastico, hai appena finito di scrivere il tuo secondo test!
+
+Ora, siamo andati avanti e abbiamo eseguito il `test di Truffle` per te. Ecco l'output:
+
+```bash
+Contract: CryptoZombies
+ ✓ should be able to create a new zombie (129ms)
+ ✓ should not allow two zombies (148ms)
+
+
+ 2 passing (1s)
+```
+
+Il test è passato. Hooray!
diff --git a/it/11/08.md b/it/11/08.md
new file mode 100644
index 0000000000..b8270ce6d2
--- /dev/null
+++ b/it/11/08.md
@@ -0,0 +1,201 @@
+---
+title: Trasferire Zombie
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ const utils = require("./helpers/utils");
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+
+ // start here
+ })
+ 'test/helpers/utils.js': |
+ async function shouldThrow(promise) {
+ try {
+ await promise;
+ assert(true);
+ }
+ catch (err) {
+ return;
+ }
+ assert(false, "The contract did not throw.");
+
+ }
+
+ module.exports = {
+ shouldThrow,
+ };
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ const utils = require("./helpers/utils");
+
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ xcontext("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ // TODO: Test the single-step transfer scenario.
+ })
+ })
+ xcontext("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ // TODO: Test the two-step scenario. The approved address calls transferFrom
+ })
+ it("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ // TODO: Test the two-step scenario. The owner calls transferFrom
+ })
+ })
+ })
+---
+
+Domanda- Diciamo che Alice voglia inviare uno dei suoi zombie a Bob. Dovremmo testarlo?
+
+Sicuramente!
+
+Se hai seguito le lezioni precedenti, dovresti sapere che, tra le altre cose, i nostri zombi ereditano da _ERC721_. E la specifica _ERC721_ ha 2 modi diversi per trasferire i token:
+
+**(1)**
+
+```sol
+function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
+```
+
+Il primo modo prevede che _Alice_ (la proprietaria) chiami `transferFrom` con il suo `indirizzo` come parametro `_from`, l'`indirizzo` di Bob come parametro `_to` e lo `zombieId` che vuole trasferire.
+
+**(2)**
+
+```sol
+function approve(address _approved, uint256 _tokenId) external payable;
+```
+
+seguito da
+
+```sol
+function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
+```
+
+Il secondo modo prevede che Alice prima chiami "approve" con l'indirizzo di Bob e "zombieId". Il contratto quindi memorizza che Bob è autorizzato a prendere lo zombi. Successivamente, quando Alice o Bob chiama "transferFrom", il contratto controlla se quel "msg.sender" è uguale all'indirizzo di Alice o Bob. In tal caso, trasferisce lo zombi a Bob.
+
+Chiameremo questi due modi di trasferire gli zombi "scenari". Per testare ogni scenario, creeremo due diversi gruppi di test e forniremo loro delle descrizioni significative.
+
+Perché raggrupparli? Abbiamo solo pochi test...
+
+Sì, in questo momento la nostra logica è piuttosto semplice, ma potrebbe non essere sempre così. Tuttavia, il secondo scenario (che è "approve" seguito da "transferFrom") richiede almeno due test:
+
+- per prima cosa, dobbiamo verificare se Alice stessa è in grado di trasferire lo zombi.
+
+- secondo, dobbiamo controllare se Bob può eseguire `transferFrom`.
+
+Inoltre, in futuro, potresti voler aggiungere altre funzionalità che richiederebbero test diversi. Riteniamo che sia meglio mettere in atto una struttura scalabile fin dall'inizio😉. Rende la comprensione del tuo codice molto più semplice per gli estranei o per te stesso se hai passato del tempo a concentrarti su qualcos'altro per un po' di tempo.
+
+> Nota: se ti trovi in una posizione in cui lavori con altri programmatori, scoprirai che è più probabile che seguano le convenzioni che hai stabilito nel codice iniziale. Essere in grado di collaborare in modo efficace è una delle competenze chiave di cui avrai bisogno se vuoi lavorare su progetti grandi e di successo. Ottenere buone abitudini che ti aiutino a farlo il prima possibile renderà la tua vita di programmatore più facile e di maggior successo.
+
+## La funzione 'context'
+
+Per raggruppare i test, _Truffle_ fornisce una funzione chiamata `context`. Lascia che ti mostri rapidamente come usarlo per strutturare meglio il nostro codice:
+
+```javascript
+context('with the single-step transfer scenario', async () => {
+ it('should transfer a zombie', async () => {
+ // TODO: Test the single-step transfer scenario.
+ });
+});
+
+context('with the two-step transfer scenario', async () => {
+ it('should approve and then transfer a zombie when the approved address calls transferFrom', async () => {
+ // TODO: Test the two-step scenario. The approved address calls transferFrom
+ });
+ it('should approve and then transfer a zombie when the owner calls transferFrom', async () => {
+ // TODO: Test the two-step scenario. The owner calls transferFrom
+ });
+});
+```
+
+Se lo aggiungiamo al nostro file `CryptoZombies.js` e quindi eseguiamo `truffle test` l'output sarà simile a questo:
+
+```bash
+Contract: CryptoZombies
+ ✓ should be able to create a new zombie (100ms)
+ ✓ should not allow two zombies (251ms)
+ with the single-step transfer scenario
+ ✓ should transfer a zombie
+ with the two-step transfer scenario
+ ✓ should approve and then transfer a zombie when the owner calls transferFrom
+ ✓ should approve and then transfer a zombie when the approved address calls transferFrom
+
+
+ 5 passing (2s)
+```
+
+Bene?
+
+Hmm...
+
+Dai un'occhiata di nuovo: c'è un problema con l'output sopra. Sembra che tutti i test siano passati, il che ovviamente è falso dato che non li abbiamo nemmeno scritti!!
+
+Fortunatamente, c'è una soluzione semplice: se mettiamo una `x` davanti alle funzioni `context()` come segue: `xcontext()`, `Truffle` salterà quei test.
+
+> Nota: `x` può essere posizionato anche prima di una funzione `it()`. Non dimenticare di rimuovere tutte le x quando i test sono pronti!
+
+Ora, eseguiamo il `test di Turfle`. L'output dovrebbe assomigliare a questo:
+
+```
+Contract: CryptoZombies
+ ✓ should be able to create a new zombie (199ms)
+ ✓ should not allow two zombies (175ms)
+ with the single-step transfer scenario
+ - should transfer a zombie
+ with the two-step transfer scenario
+ - should approve and then transfer a zombie when the owner calls transferFrom
+ - should approve and then transfer a zombie when the approved address calls transferFrom
+
+
+ 2 passing (827ms)
+ 3 pending
+```
+
+Dove "-" che è stato saltato tramite l'utilizzo della "x" all'inizio del test.
+
+Abbastanza pulito, eh? Ora puoi eseguire i tuoi test mentre procedi e contrassegnare le funzioni vuote in cui sai che dovrai scrivere i test prossimamente.
+
+# Testiamo
+
+1. Vai avanti e copia/incolla il codice in alto.
+
+2. Per adesso, _saltiamo_ le nostre nuove funzioni `context`.
+
+I nostri test sono vuoti e c'è molta logica da scrivere per implementarli. Lo faremo in pezzi più piccoli nei prossimi capitoli.
From 467451f89e8a0016602a9c8b0773ad6c712bb6ba Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+viddom@users.noreply.github.com>
Date: Fri, 12 Aug 2022 16:39:46 +0200
Subject: [PATCH 25/26] lesson 11: 09-10-11 translated (IT)
---
it/11/09.md | 155 +++++++++++++++++++++++++++++++++++++++++++++++++
it/11/10.md | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++
it/11/11.md | 143 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 462 insertions(+)
create mode 100644 it/11/09.md
create mode 100644 it/11/10.md
create mode 100644 it/11/11.md
diff --git a/it/11/09.md b/it/11/09.md
new file mode 100644
index 0000000000..41168946a4
--- /dev/null
+++ b/it/11/09.md
@@ -0,0 +1,155 @@
+---
+title: Trasferimento token ERC721- Scenario a singolo step
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ const utils = require("./helpers/utils");
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ xcontext("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ // start here.
+ })
+ })
+ xcontext("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ // TODO: Test the two-step scenario. The approved address calls transferFrom
+ })
+ it("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ // TODO: Test the two-step scenario. The owner calls transferFrom
+ })
+ })
+ })
+ 'test/helpers/utils.js': |
+ async function shouldThrow(promise) {
+ try {
+ await promise;
+ assert(true);
+ }
+ catch (err) {
+ return;
+ }
+ assert(false, "The contract did not throw.");
+
+ }
+
+ module.exports = {
+ shouldThrow,
+ };
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ const utils = require("./helpers/utils");
+
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ context("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner, bob);
+ })
+ })
+ xcontext("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ // TODO: Test the two-step scenario. The approved address calls transferFrom
+ })
+ it("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ // TODO: Test the two-step scenario. The owner calls transferFrom
+ })
+ })
+ })
+---
+
+Finora ci siamo solo riscaldati...
+
+Ma ora è il momento di mostrare davvero quello che imparato!
+
+Nei prossimi capitoli metteremo insieme ciò che abbiamo imparato e proveremo qualcosa di veramente interessante.
+
+Per cominciare, testeremo lo scenario in cui _Alice_ trasferisce il suo token ERC721 a _Bob_, in un unico passaggio.
+
+Ecco cosa dovrebbe fare il nostro test:
+
+- Creare un nuovo zombi per Alice (ricorda che uno zombi non è altro che un token ERC721).
+
+- Fai in modo che Alice trasferisca il suo token ERC721 a Bob.
+
+- A questo punto, Bob dovrebbe possedere il token ERC721. In tal caso, `ownerOf` restituirà un valore uguale all'indirizzo di Bob.
+
+- Chiudiamo controllando se Bob è il `newOwner`, all'interno di un `assert`.
+
+# Testiamo
+
+1. La prima riga della funzione dovrebbe chiamare `createRandomZombie`. Dagli `zombieNames[0]` come nome e assicurati che Alice sia la proprietaria.
+
+2. La seconda riga dovrebbe dichiarare un `const` chiamato `zombieId` e impostarlo uguale all'id dello zombi. Nel Capitolo 5, hai imparato come recuperare informazioni da log ed eventi nel nostro smart contract. Ripassa il capitolo se necessario. Assicurati di convertire anche `zombieId` in un numero valido utilizzando `toNumber()`.
+
+3. Quindi, usiamo `transferFrom` con `alice` e `bob` come primi parametri. Assicurati che Alice chiami questa funzione e utilizza `await` per aspettare che termini l'esecuzione prima di andare avanti.
+
+4. Dichiara un `const` chiamato `newOwner`. Impostalo uguale a `ownerOf` chiamato con `zombieId`.
+
+5.Infine, controlliamo se Bob possiede questo token ERC721. Per far ciò possiamo utilizzare `assert.equal` passando `newOwner` e `bob` come parametri;
+
+> Nota: `assert.equal(newOwner, bob)` e `assert.equal(bob, newOwner)` sono fondamentalmente la stessa cosa. Ma il nostro interprete della riga di comando non è troppo avanzato, quindi non considererà la tua risposta corretta a meno che tu non digiti la prima opzione.
+
+1. Avevamo detto che il passaggio precedente era l'ultimo! Beh... era una bugia. L'ultima cosa che vogliamo fare è rimuovere il blocco che salta l'esecuzione del primo scenario rimuovendo la `x` dal nome dalla funzione.
+
+Fiuu! È un sacco di codice. Spero che tu riesca a farlo bene. In caso contrario, sentiti libero di fare clic su "mostra risposta".
+
+Adesso lanciamo `truffle test` e vediamo se i nostri test vengono verificati:
+
+```bash
+Contract: CryptoZombies
+ ✓ should be able to create a new zombie (146ms)
+ ✓ should not allow two zombies (235ms)
+ with the single-step transfer scenario
+ ✓ should transfer a zombie (382ms)
+ with the two-step transfer scenario
+ - should approve and then transfer a zombie when the owner calls transferFrom
+ - should approve and then transfer a zombie when the approved address calls transferFrom
+
+
+3 passing (1s)
+2 pending
+```
+
+Ed eccolo! Il nostro codice ha superato il test a pieni voti👏🏻.
+
+Nel prossimo capitolo, passeremo allo scenario in 2 fasi in cui "approve" è seguito da "transferFrom".
diff --git a/it/11/10.md b/it/11/10.md
new file mode 100644
index 0000000000..8c4989957c
--- /dev/null
+++ b/it/11/10.md
@@ -0,0 +1,164 @@
+---
+title: Trasferimento di token ERC721 - Scenario in due fasi
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ const utils = require("./helpers/utils");
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ context("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner, bob);
+ })
+ })
+ xcontext("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ // start here
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner,bob);
+ })
+ it("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ // TODO: Test the two-step scenario. The owner calls transferFrom
+ })
+ })
+ })
+ 'test/helpers/utils.js': |
+ async function shouldThrow(promise) {
+ try {
+ await promise;
+ assert(true);
+ }
+ catch (err) {
+ return;
+ }
+ assert(false, "The contract did not throw.");
+
+ }
+
+ module.exports = {
+ shouldThrow,
+ };
+
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ const utils = require("./helpers/utils");
+
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ context("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner, bob);
+ })
+ })
+ context("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: bob});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner,bob);
+ })
+ xit("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ // TODO: Test the two-step scenario. The owner calls transferFrom
+ })
+ })
+ })
+---
+
+Ora, utilizzare "approve" seguito da "transferFrom" per trasferire i token ERC721 è tutt'altro che una passeggiata, ma siamo qui per imparare.
+
+In poche parole, dobbiamo testare due diversi scenari:
+
+- Alice autorizza Bob a prendere il token ERC721. Quindi, Bob (l'**indirizzo approvato**) chiama "transferFrom".
+
+- Alice autorizza Bob a prendere il token ERC721. Successivamente, Alice trasferisce il token ERC721.
+
+La differenza nei due scenari sta su _**chi**_ chiama il trasferimento effettivo, Alice o Bob.
+
+L'abbiamo fatto sembrare semplice, giusto?
+
+Diamo un'occhiata al primo scenario.
+
+## Bob chiama transferFrom
+
+I passaggi per questo scenario sono i seguenti:
+
+- Alice crea un nuovo token ERC721 e quindi chiama "approve".
+- Successivamente, Bob esegue "transferFrom" che dovrebbe renderlo il proprietario del token EC721.
+- Infine, dobbiamo chiamare `assert.equal` con `newOwner` e `bob` come parametri.
+
+# Testiamo
+
+1. Le prime due righe di codice del nostro test sono simili al test precedente. Siamo andati avanti e li abbiamo copiati e incollati per te.
+
+2. Quindi, per far approvare a Bob il token ERC721, chiama `approve()`. La funzione accetta `bob` e `zombieId` come parametri. Inoltre, assicurati che Alice chiami il metodo (poiché è il suo token ERC721 che verrà trasferito).
+
+3. Le ultime tre righe di codice sono **quasi simili** al test precedente. Ancora una volta, siamo andati avanti e li abbiamo copiati e incollati per te. Aggiorniamo la chiamata alla funzione `transferFrom()` in modo che il mittente sia Bob.
+
+4. Infine, "abilitiamo" questo scenario e "saltamo" l'ultimo test case, quello che dobbiamo ancora codificare.
+
+È ora di eseguire il `test di Truffle` e vedere se è tutto corretto:
+
+```bash
+Contract: CryptoZombies
+ ✓ should be able to create a new zombie (218ms)
+ ✓ should not allow two zombies (175ms)
+ with the single-step transfer scenario
+ ✓ should transfer a zombie (334ms)
+ with the two-step transfer scenario
+ ✓ should approve and then transfer a zombie when the owner calls transferFrom (360ms)
+ - should approve and then transfer a zombie when the approved address calls transferFrom
+
+
+ 4 passing (2s)
+ 1 pending
+```
+
+Fantastico! Adesso andiamo al prossimo test.
diff --git a/it/11/11.md b/it/11/11.md
new file mode 100644
index 0000000000..5ed81b900f
--- /dev/null
+++ b/it/11/11.md
@@ -0,0 +1,143 @@
+---
+title: Trasferimento di token ERC721 - Scenario in due fasi
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ const utils = require("./helpers/utils");
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ context("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner, bob);
+ })
+ })
+ context("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: bob});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner,bob);
+ })
+ xit("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ // TODO: start
+ })
+ })
+ })
+ 'test/helpers/utils.js': |
+ async function shouldThrow(promise) {
+ try {
+ await promise;
+ assert(true);
+ }
+ catch (err) {
+ return;
+ }
+ assert(false, "The contract did not throw.");
+
+ }
+
+ module.exports = {
+ shouldThrow,
+ };
+
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ const utils = require("./helpers/utils");
+
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ context("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner, bob);
+ })
+ })
+ context("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: bob});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner,bob);
+ })
+ it("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner,bob);
+ })
+ })
+ })
+---
+
+Siamo vicini al termine con il test dei trasferimenti! Proviamo ora lo scenario in cui Alice chiama `transferFrom`.
+
+Abbiamo delle buone notizie per te: questo test è semplice. Tutto quello che devi fare è copiare e incollare il codice del capitolo precedente e fare in modo che **Alice** (non Bob) chiami `transferFrom`:
+
+# Testiamo
+
+1. Copia e incolla il codice del test precedente e fai chiamare "transferFrom" ad Alice.
+2. Abilita il test (rimuovendo la 'x').
+
+Eseguendo `truffle test` l'output sarebbe simile a questo:
+
+```bash
+Contract: CryptoZombies
+ ✓ should be able to create a new zombie (201ms)
+ ✓ should not allow two zombies (486ms)
+ ✓ should return the correct owner (382ms)
+ with the single-step transfer scenario
+ ✓ should transfer a zombie (337ms)
+ with the two-step transfer scenario
+ ✓ should approve and then transfer a zombie when the approved address calls transferFrom (266ms)
+ 5 passing (3s)
+```
+
+Non riesco a pensare a nient'altro da testare relativo ai trasferimenti, quindi per ora abbiamo finito.
From 5ffff2026e0cd898802e0729161bd5810ef66a66 Mon Sep 17 00:00:00 2001
From: Lorenz <34058834+viddom@users.noreply.github.com>
Date: Fri, 12 Aug 2022 17:25:31 +0200
Subject: [PATCH 26/26] Lesson 11: translate completed
---
it/11/12.md | 329 ++++++++++++++++++++++++++++++++++++++++
it/11/13.md | 264 ++++++++++++++++++++++++++++++++
it/11/14.md | 187 +++++++++++++++++++++++
it/11/lessoncomplete.md | 17 +++
4 files changed, 797 insertions(+)
create mode 100644 it/11/12.md
create mode 100644 it/11/13.md
create mode 100644 it/11/14.md
create mode 100644 it/11/lessoncomplete.md
diff --git a/it/11/12.md b/it/11/12.md
new file mode 100644
index 0000000000..c3a4209792
--- /dev/null
+++ b/it/11/12.md
@@ -0,0 +1,329 @@
+---
+title: Attacchi Zombie
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ const utils = require("./helpers/utils");
+ const time = require("./helpers/time");
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ context("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner, bob);
+ })
+ })
+ context("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: bob});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner,bob);
+ })
+ it("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner,bob);
+ })
+ })
+ it("zombies should be able to attack another zombie", async () => {
+ let result;
+ result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const firstZombieId = result.logs[0].args.zombieId.toNumber();
+ result = await contractInstance.createRandomZombie(zombieNames[1], {from: bob});
+ const secondZombieId = result.logs[0].args.zombieId.toNumber();
+ //TODO: increase the time
+ await contractInstance.attack(firstZombieId, secondZombieId, {from: alice});
+ assert.equal(result.receipt.status, true);
+ })
+ })
+ 'test/helpers/utils.js': |
+ async function shouldThrow(promise) {
+ try {
+ await promise;
+ assert(true);
+ }
+ catch (err) {
+ return;
+ }
+ assert(false, "The contract did not throw.");
+
+ }
+
+ module.exports = {
+ shouldThrow,
+ };
+
+ 'test/helpers/time.js': |
+ async function increase(duration) {
+
+ //first, let's increase time
+ await web3.currentProvider.sendAsync({
+ jsonrpc: "2.0",
+ method: "evm_increaseTime",
+ params: [duration], // there are 86400 seconds in a day
+ id: new Date().getTime()
+ }, () => {});
+
+ //next, let's mine a new block
+ web3.currentProvider.send({
+ jsonrpc: '2.0',
+ method: 'evm_mine',
+ params: [],
+ id: new Date().getTime()
+ })
+
+ }
+
+ const duration = {
+
+ seconds: function (val) {
+ return val;
+ },
+ minutes: function (val) {
+ return val * this.seconds(60);
+ },
+ hours: function (val) {
+ return val * this.minutes(60);
+ },
+ days: function (val) {
+ return val * this.hours(24);
+ },
+ }
+
+ module.exports = {
+ increase,
+ duration,
+ };
+
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ const utils = require("./helpers/utils");
+
+ const time = require("./helpers/time");
+
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ context("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner, bob);
+ })
+ })
+ context("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: bob});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner,bob);
+ })
+ it("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ assert.equal(newOwner,bob);
+ })
+ })
+ it("zombies should be able to attack another zombie", async () => {
+ let result;
+ result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const firstZombieId = result.logs[0].args.zombieId.toNumber();
+ result = await contractInstance.createRandomZombie(zombieNames[1], {from: bob});
+ const secondZombieId = result.logs[0].args.zombieId.toNumber();
+ await time.increase(time.duration.days(1));
+ await contractInstance.attack(firstZombieId, secondZombieId, {from: alice});
+ assert.equal(result.receipt.status, true);
+ })
+ })
+---
+
+Wow! Con i capitoli precedenti abbiamo ricoperto una vastità di argomenti.
+
+Quindi abbiamo finito ora con tutti gli scenari? No, non ci siamo ancora; abbiamo lasciato le cose migliori per la fine.
+
+Abbiamo creato un gioco di zombi e **la parte migliore** è far combattere gli zombie, giusto?
+
+Questo test è piuttosto semplice e consiste nei seguenti passaggi:
+
+- **Primo**, creeremo due nuovi zombi: uno per Alice e l'altro per Bob.
+- **Secondo**, Alice eseguirà l'azione di attacco "attack" sullo zombie di Bob, specificando lo "zombieId" come parametro
+- **Infine**, affinché il test venga superato con successo, verificheremo se `result.receipt.status` è uguale a `true`
+
+Mentre siamo qui, ho codificato rapidamente tutta questa logica e l'ho inserita in una funzione `it()` ed eseguito `truffle test`.
+
+L'output sarebbe simile a questo:
+
+```bash
+Contract: CryptoZombies
+ ✓ should be able to create a new zombie (102ms)
+ ✓ should not allow two zombies (321ms)
+ ✓ should return the correct owner (333ms)
+ 1) zombies should be able to attack another zombie
+ with the single-step transfer scenario
+ ✓ should transfer a zombie (307ms)
+ with the two-step transfer scenario
+ ✓ should approve and then transfer a zombie when the approved address calls transferFrom (357ms)
+
+
+ 5 passing (7s)
+ 1 failing
+
+ 1) Contract: CryptoZombies
+ zombies should be able to attack another zombie:
+ Error: Returned error: VM Exception while processing transaction: revert
+
+```
+
+Uh oh. Il nostro test è fallito☹️.
+
+Ma perché?
+
+Scopriamolo. Per prima cosa, daremo un'occhiata più da vicino al codice all'interno della funzione `createRandomZombie()`:
+
+```sol
+function createRandomZombie(string _name) public {
+ require(ownerZombieCount[msg.sender] == 0);
+ uint randDna = _generateRandomDna(_name);
+ randDna = randDna - randDna % 100;
+ _createZombie(_name, randDna);
+}
+```
+
+Fin qui tutto bene. Andando avanti, analizziamo `_createZombie()`:
+
+```sol
+function _createZombie(string _name, uint _dna) internal {
+ uint id = zombies.push(Zombie(_name, _dna, 1, uint32(now + cooldownTime), 0, 0)) - 1;
+ zombieToOwner[id] = msg.sender;
+ ownerZombieCount[msg.sender] = ownerZombieCount[msg.sender].add(1);
+ emit NewZombie(id, _name, _dna);
+}
+```
+
+Ohh, hai notato il problema?
+
+Il nostro test è fallito perché abbiamo aggiunto un periodo di **cooldown** al nostro gioco e fatto in modo che gli zombi debbano attendere **1 giorno** dopo aver attaccato (o nutrito) prima di effettuare un'altra azione.
+
+Senza questo, lo zombi potrebbe attaccare e moltiplicarsi innumerevoli volte al giorno, il che renderebbe il gioco troppo facile.
+
+Ora, cosa dobbiamo fare adesso... aspettare un giorno?
+
+## Viaggio nel tempo
+
+Fortunatamente, non dobbiamo aspettare così tanto. In effetti, non c'è bisogno di aspettare affatto. Questo perché _Ganache_ fornisce un modo per andare avanti nel tempo attraverso due funzioni di supporto:
+
+- `evm_increaseTime`: aumenta il tempo per il blocco successivo.
+- `evm_mine`: estrae un nuovo blocco.
+
+Non hai nemmeno bisogno di un Tardis o di una DeLorean per questo tipo di viaggio nel tempo.
+
+Lascia che ti spieghi come funzionano queste funzioni:
+
+- Ogni volta che un nuovo blocco viene estratto, il minatore aggiunge un timestamp. Diciamo che le transazioni che hanno creato i nostri zombi sono state estratte nel blocco 5.
+
+- Successivamente, chiamiamo `evm_increaseTime` ma, poiché la blockchain è immutabile, non c'è modo di modificare un blocco esistente. Quindi, quando il contratto verificherà il tempo, questo non verrà aumentato.
+
+- Se eseguiamo `evm_mine`, il blocco numero 6 viene estratto (e timestamp) il che significa che, quando mettiamo gli zombi a combattere, lo smart contract "vedrà" che è trascorso un giorno.
+- Mettiamo tutto insieme così possiamo risolvere il nostro test viaggiando nel tempo:
+
+```javascript
+await web3.currentProvider.sendAsync(
+ {
+ jsonrpc: '2.0',
+ method: 'evm_increaseTime',
+ params: [86400], // there are 86400 seconds in a day
+ id: new Date().getTime(),
+ },
+ () => {}
+);
+
+web3.currentProvider.send({
+ jsonrpc: '2.0',
+ method: 'evm_mine',
+ params: [],
+ id: new Date().getTime(),
+});
+```
+
+Sì, è un bel pezzo di codice, ma non vorremmo aggiungere questa logica al nostro file `CryptoZombies.js`.
+
+Siamo andati avanti e abbiamo spostato tutto in un nuovo file chiamato `helpers/time.js`. Per aumentare il tempo, dovrai semplicemente chiamare: `time.increaseTime(86400);`
+
+Sì, non è ancora abbastanza. Dopotutto, ci aspettiamo davvero che tu sappia quanti secondi ci sono in un giorno ogni volta che devi chiamare questa funzione?
+
+Ovviamente no. Questo è il motivo per cui abbiamo aggiunto un'altra _helper function_ denominata `days` che richiede il numero di giorni con cui vogliamo aumentare il tempo come argomento. Chiameresti questa funzione in questo modo: `await time.increase(time.duration.days(1))`
+
+> Nota: ovviamente, il viaggio nel tempo non è disponibile sulla rete principale o su nessuna delle catene di test disponibili che sono protette dai minatori. Sarebbe un vero disastro se qualcuno potesse semplicemente scegliere di cambiare il modo in cui il tempo opera nel mondo reale! Per testare i contratti intelligenti, il viaggio nel tempo può essere una parte essenziale ara gli strumenti del programmatore.
+
+# Testiamo
+
+Siamo andati avanti e abbiamo compilato la versione del test che fallisce.
+
+1. Scorri verso il basso fino al commento che abbiamo lasciato per te. Quindi, correggi il test case eseguendo "await time.increase" come mostrato sopra.
+
+E' tutto pronto. Lanciamo il comando `truffle test`:
+
+```
+Contract: CryptoZombies
+ ✓ should be able to create a new zombie (119ms)
+ ✓ should not allow two zombies (112ms)
+ ✓ should return the correct owner (109ms)
+ ✓ zombies should be able to attack another zombie (475ms)
+ with the single-step transfer scenario
+ ✓ should transfer a zombie (235ms)
+ with the two-step transfer scenario
+ ✓ should approve and then transfer a zombie when the owner calls transferFrom (181ms)
+ ✓ should approve and then transfer a zombie when the approved address calls transferFrom (152ms)
+```
+
+Ed ecco qua! Questo è il passaggio finale di questo capitolo.
diff --git a/it/11/13.md b/it/11/13.md
new file mode 100644
index 0000000000..48e95e3881
--- /dev/null
+++ b/it/11/13.md
@@ -0,0 +1,264 @@
+---
+title: Affermazioni più espressive con Chai
+actions: ['checkAnswer', 'hints']
+requireLogin: true
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'test/CryptoZombies.js': |
+ const CryptoZombies = artifacts.require("CryptoZombies");
+ const utils = require("./helpers/utils");
+ const time = require("./helpers/time");
+ //TODO: import expect into our project
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ //TODO: replace with expect
+ assert.equal(result.receipt.status, true);
+ assert.equal(result.logs[0].args.name,zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ context("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ //TODO: replace with expect
+ assert.equal(newOwner, bob);
+ })
+ })
+ context("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: bob});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ //TODO: replace with expect
+ assert.equal(newOwner,bob);
+ })
+ it("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ //TODO: replace with expect
+ assert.equal(newOwner,bob);
+ })
+ })
+ it("zombies should be able to attack another zombie", async () => {
+ let result;
+ result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const firstZombieId = result.logs[0].args.zombieId.toNumber();
+ result = await contractInstance.createRandomZombie(zombieNames[1], {from: bob});
+ const secondZombieId = result.logs[0].args.zombieId.toNumber();
+ await time.increase(time.duration.days(1));
+ await contractInstance.attack(firstZombieId, secondZombieId, {from: alice});
+ //TODO: replace with expect
+ assert.equal(result.receipt.status, true);
+ })
+ })
+
+ 'test/helpers/utils.js': |
+ async function shouldThrow(promise) {
+ try {
+ await promise;
+ assert(true);
+ }
+ catch (err) {
+ return;
+ }
+ assert(false, "The contract did not throw.");
+
+ }
+
+ module.exports = {
+ shouldThrow,
+ };
+ 'test/helpers/time.js': |
+ async function increase(duration) {
+
+ //first, let's increase time
+ await web3.currentProvider.sendAsync({
+ jsonrpc: "2.0",
+ method: "evm_increaseTime",
+ params: [duration], // there are 86400 seconds in a day
+ id: new Date().getTime()
+ }, () => {});
+
+ //next, let's mine a new block
+ web3.currentProvider.send({
+ jsonrpc: '2.0',
+ method: 'evm_mine',
+ params: [],
+ id: new Date().getTime()
+ })
+
+ }
+
+ const duration = {
+
+ seconds: function (val) {
+ return val;
+ },
+ minutes: function (val) {
+ return val * this.seconds(60);
+ },
+ hours: function (val) {
+ return val * this.minutes(60);
+ },
+ days: function (val) {
+ return val * this.hours(24);
+ },
+ }
+
+ module.exports = {
+ increase,
+ duration,
+ };
+
+ answer: >
+ const CryptoZombies = artifacts.require("CryptoZombies");
+
+ const utils = require("./helpers/utils");
+
+ const time = require("./helpers/time");
+
+ var expect = require('chai').expect;
+
+ const zombieNames = ["Zombie 1", "Zombie 2"];
+
+ contract("CryptoZombies", (accounts) => {
+ let [alice, bob] = accounts;
+ let contractInstance;
+ beforeEach(async () => {
+ contractInstance = await CryptoZombies.new();
+ });
+ it("should be able to create a new zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ expect(result.receipt.status).to.equal(true);
+ expect(result.logs[0].args.name).to.equal(zombieNames[0]);
+ })
+ it("should not allow two zombies", async () => {
+ await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
+ })
+ context("with the single-step transfer scenario", async () => {
+ it("should transfer a zombie", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ expect(newOwner).to.equal(bob);
+ })
+ })
+ context("with the two-step transfer scenario", async () => {
+ it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: bob});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ expect(newOwner).to.equal(bob);
+ })
+ it("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
+ const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const zombieId = result.logs[0].args.zombieId.toNumber();
+ await contractInstance.approve(bob, zombieId, {from: alice});
+ await contractInstance.transferFrom(alice, bob, zombieId, {from: alice});
+ const newOwner = await contractInstance.ownerOf(zombieId);
+ expect(newOwner).to.equal(bob);
+ })
+ })
+ it("zombies should be able to attack another zombie", async () => {
+ let result;
+ result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
+ const firstZombieId = result.logs[0].args.zombieId.toNumber();
+ result = await contractInstance.createRandomZombie(zombieNames[1], {from: bob});
+ const secondZombieId = result.logs[0].args.zombieId.toNumber();
+ await time.increase(time.duration.days(1));
+ await contractInstance.attack(firstZombieId, secondZombieId, {from: alice});
+ expect(result.receipt.status).to.equal(true);
+ })
+ })
+---
+
+Finora abbiamo usato il modulo integrato `assert` per scrivere le nostre asserzioni. Sebbene non sia male, il modulo `assert` ha un grosso svantaggio: il codice non è facilmente leggibile. Fortunatamente, là fuori ci sono molti moduli che possono aiutarci e `Chai` è uno dei migliori.
+
+## Libreria per asserzioni Chai
+
+`Chai` è molto potente e, per lo scopo di questa lezione, ci limiteremo a scalfire la superficie. Una volta terminata questa lezione, non esitare a consultare le loro guide per approfondire le tue conoscenze e ottenere maggiori dettagli.
+
+Detto questo, diamo un'occhiata ai tre tipi di stili di asserzione raggruppati in `Chai`:
+
+- _expect_: consente di concatenare asserzioni in linguaggio naturale come segue:
+
+ ```javascript
+ let lessonTitle = 'Testing Smart Contracts with Truffle';
+ expect(lessonTitle).to.be.a('string');
+ ```
+
+- _should_: consente asserzioni simili all'interfaccia `expect`, ma la catena inizia con una proprietà `should`:
+
+ ```javascript
+ let lessonTitle = 'Testing Smart Contracts with Truffle';
+ lessonTitle.should.be.a('string');
+ ```
+
+- _assert_: fornisce una notazione simile a quella confezionata con node.js e include diversi test aggiuntivi, è compatibile con il browser:
+
+```javascript
+let lessonTitle = 'Testing Smart Contracts with Truffle';
+assert.typeOf(lessonTitle, 'string');
+```
+
+In questo capitolo, ti mostreremo come migliorare le tue asserzioni utilizzando `expect`.
+
+> Nota: supponiamo che il pacchetto `chai` sia già installato sul tuo computer. In caso contrario, puoi installarlo facilmente in questo modo: `npm -g install chai`
+
+Per usare lo stile `expect`, la prima cosa che dovremmo fare è importarlo nel nostro progetto come segue:
+
+```javascript
+var expect = require('chai').expect;
+```
+
+## expect().to.equal()
+
+Ora che abbiamo importato `expect` nel nostro progetto, potresti controllare se due stringhe sono nel seguente modo:
+
+```javascript
+let zombieName = 'My Awesome Zombie';
+expect(zombieName).to.equal('My Awesome Zombie');
+```
+
+Basta parlare. Sfruttiamo i poteri di `Chai`!
+
+# Testiamo
+
+1. Importiamo `expect` nel nostro progetto.
+
+2. Continuando l'esempio sopra con `zombieName`, possiamo usare `expect` per testare una transazione riuscita come segue:
+
+```javascript
+expect(result.receipt.status).to.equal(true);
+```
+
+E possiamo verificare se Alice possiede uno zombi con il seguente codice:
+
+```javascript
+expect(zombieOwner).to.equal(alice);
+```
+
+1. Sostituisci tutte le occorrenze di `assert.equal` con `expect`. Abbiamo lasciato un sacco di commenti nel codice per renderli facili da trovare.
diff --git a/it/11/14.md b/it/11/14.md
new file mode 100644
index 0000000000..2e4bcba613
--- /dev/null
+++ b/it/11/14.md
@@ -0,0 +1,187 @@
+---
+title: Test su Loom
+actions: ['checkAnswer', 'hints']
+material:
+ editor:
+ language: javascript
+ startingCode:
+ 'truffle.js': |
+ const HDWalletProvider = require("truffle-hdwallet-provider");
+ const LoomTruffleProvider = require('loom-truffle-provider');
+ const mnemonic = "YOUR MNEMONIC HERE";
+ module.exports = {
+ // Object with configuration for each network
+ networks: {
+ //development
+ development: {
+ host: "127.0.0.1",
+ port: 7545,
+ network_id: "*",
+ gas: 9500000
+ },
+ // Configuration for Ethereum Mainnet
+ mainnet: {
+ provider: function() {
+ return new HDWalletProvider(mnemonic, "https://mainnet.infura.io/v3/")
+ },
+ network_id: "1" // Match any network id
+ },
+ // Configuration for Rinkeby Metwork
+ rinkeby: {
+ provider: function() {
+ // Setting the provider with the Infura Rinkeby address and Token
+ return new HDWalletProvider(mnemonic, "https://rinkeby.infura.io/v3/")
+ },
+ network_id: 4
+ },
+ // Configuration for Loom Testnet
+ loom_testnet: {
+ provider: function() {
+ const privateKey = 'YOUR_PRIVATE_KEY';
+ const chainId = 'extdev-plasma-us1';
+ const writeUrl = 'wss://extdev-basechain-us1.dappchains.com/websocket';
+ const readUrl = 'wss://extdev-basechain-us1.dappchains.com/queryws';
+ // TODO: Replace the line below
+ return new LoomTruffleProvider(chainId, writeUrl, readUrl, privateKey);
+ },
+ network_id: '9545242630824'
+ }
+ },
+ compilers: {
+ solc: {
+ version: "0.4.25"
+ }
+ }
+ };
+
+ answer: |
+ const HDWalletProvider = require("truffle-hdwallet-provider");
+ const LoomTruffleProvider = require('loom-truffle-provider');
+ const mnemonic = "YOUR MNEMONIC HERE";
+ module.exports = {
+ // Object with configuration for each network
+ networks: {
+ //development
+ development: {
+ host: "127.0.0.1",
+ port: 7545,
+ network_id: "*",
+ gas: 9500000
+ },
+ // Configuration for Ethereum Mainnet
+ mainnet: {
+ provider: function() {
+ return new HDWalletProvider(mnemonic, "https://mainnet.infura.io/v3/")
+ },
+ network_id: "1"
+ },
+ // Configuration for Rinkeby Network
+ rinkeby: {
+ provider: function() {
+ return new HDWalletProvider(mnemonic, "https://rinkeby.infura.io/v3/")
+ },
+ network_id: 4
+ },
+ // Configuration for Loom Testnet
+ loom_testnet: {
+ provider: function() {
+ const privateKey = 'YOUR_PRIVATE_KEY';
+ const chainId = 'extdev-plasma-us1';
+ const writeUrl = 'wss://extdev-basechain-us1.dappchains.com/websocket';
+ const readUrl = 'wss://extdev-basechain-us1.dappchains.com/queryws';
+ const loomTruffleProvider = new LoomTruffleProvider(chainId, writeUrl, readUrl, privateKey);
+ loomTruffleProvider.createExtraAccountsFromMnemonic(mnemonic, 10);
+ return loomTruffleProvider;
+ },
+ network_id: '9545242630824'
+ }
+ },
+ compilers: {
+ solc: {
+ version: "0.4.25"
+ }
+ }
+ };
+---
+
+Degno di nota! Devi esserti esercitato.
+
+Ora, questo tutorial non sarebbe completo senza mostrarti come testare la Testnet di **_Loom_**.
+
+Ricordiamo dalle nostre lezioni precedenti che, su **_Loom_**, gli utenti hanno accesso a transazioni molto più veloci e senza gas rispetto a **Ethereum**. Ciò rende DAppChains molto più adatto a qualcosa come un gioco o una DApp rivolta all'utente.
+
+E tu sai cosa? La distribuzione e il test su **Loom** non sono affatto diversi. Siamo andati avanti e abbiamo riassunto ciò che è necessario per fare dei test su **_Loom_**. Diamo una rapida occhiata.
+
+## Configurare Truffle per eseguire test su **Loom**
+
+Cominciando dall'inizio. Diciamo a Truffle come distribuire sulla Testnet di Loom inserendo il seguente snippet all'interno dell'oggetto `networks`.
+
+```javascript
+ loom_testnet: {
+ provider: function() {
+ const privateKey = 'YOUR_PRIVATE_KEY';
+ const chainId = 'extdev-plasma-us1';
+ const writeUrl = 'wss://extdev-basechain-us1.dappchains.com/websocket';
+ const readUrl = 'wss://extdev-basechain-us1.dappchains.com/queryws';
+ return new LoomTruffleProvider(chainId, writeUrl, readUrl, privateKey);
+ },
+ network_id: 'extdev'
+ }
+```
+
+> Nota: non rivelare mai la tua chiave privata! Lo stiamo facendo solo per semplicità. Una soluzione molto più sicura sarebbe salvare la tua chiave privata in un file e leggerne il valore da quel file. Se lo fai, assicurati di evitare di eseguire il push del file in cui hai salvato la tua chiave privata su GitHub, dove chiunque può vederla.
+
+## L'array Accounts
+
+Per fare in modo che _Truffle_ possa comunicare con **Loom** abbiamo sostituito il predefinito "HDWalletProvider" con il nostro Loom Truffle Provider. Di conseguenza, dobbiamo dire al nostro provider di compilare l'array "accounts" in modo da poter testare il nostro gioco. Per fare ciò, siamo tenuti a sostituire la riga di codice `return a new LoomTruffleProvider`:
+
+```javascript
+return new LoomTruffleProvider(chainId, writeUrl, readUrl, privateKey);
+```
+
+con:
+
+```javascript
+const loomTruffleProvider = new LoomTruffleProvider(
+ chainId,
+ writeUrl,
+ readUrl,
+ privateKey
+);
+loomTruffleProvider.createExtraAccountsFromMnemonic(mnemonic, 10);
+return loomTruffleProvider;
+```
+
+# Testiamo
+
+1. Sostituisci la riga di codice che `return a new LoomTruffleProvider` con lo snippet dall'alto.
+
+C'è un'altra cosa di cui dovremmo occuparci. Il viaggio nel tempo è disponibile solo durante il test su _Ganache_, quindi dovremmo saltare questo test. Sai già come _saltare_ un test mettendo una `x` davanti al nome della funzione. Tuttavia, questa volta vogliamo che tu impari qualcosa di nuovo. Per farla breve... puoi _saltare_ un test semplicemente concatenando una chiamata di funzione `skip()` come segue:
+
+```javascript
+it.skip('zombies should be able to attack another zombie', async () => {
+ //We're skipping the body of the function for brevity
+});
+```
+
+Siamo andati avanti e abbiamo saltato il test per te. Quindi, abbiamo eseguito `truffle test --network loom_testnet`.
+
+Se inserisci i comandi dall'alto, l'output dovrebbe essere simile a questo:
+
+```bash
+Contract: CryptoZombies
+ ✓ should be able to create a new zombie (6153ms)
+ ✓ should not allow two zombies (12895ms)
+ ✓ should return the correct owner (6962ms)
+ - zombies should be able to attack another zombie
+ with the single-step transfer scenario
+ ✓ should transfer a zombie (13810ms)
+ with the two-step transfer scenario
+ ✓ should approve and then transfer a zombie when the approved address calls transferFrom (22388ms)
+
+
+ 5 passing (2m)
+ 1 pending
+```
+
+Per ora è tutto, gente! Abbiamo finito di testare il nostro contratto intelligente "CryptoZombie".
diff --git a/it/11/lessoncomplete.md b/it/11/lessoncomplete.md
new file mode 100644
index 0000000000..e1bda7753a
--- /dev/null
+++ b/it/11/lessoncomplete.md
@@ -0,0 +1,17 @@
+---
+title: Lezione completata!
+actions: ['checkAnswer', 'hints']
+material:
+ lessonComplete: 1
+---
+
+Hai finito di testare il gioco. Sei a dir poco straordinario!
+
+Anche se in questo caso il nostro gioco è stato creato come demo, è chiaro che testare uno smart contract Solidity non è un'impresa da poco. Ma sappiamo che ora sei ben attrezzato per testare i tuoi smart contract!
+
+Le cose importanti da ricordare sono:
+
+- Assicurati di creare un test separato per ogni funzione del tuo gioco.
+- Mantieni tutto chiaramente etichettato e organizzato
+- Sfrutta il viaggio nel tempo
+- Prendi in considerazione l'utilizzo di Loom durante lo sviluppo di un gioco o di una DApp rivolta all'utente. Ti consigliamo vivamente di iniziare controllando la nostra documentazione.