NEWS

Come creare la tua criptovaluta su Ethereum

Come creare la tua criptovaluta su Ethereum

Come costruire un sito web di vendita di token e crowdsale di ERC-20

Oggi vedremo come come codificare la tua cripto valuta sulla blockchain di Ethereum e venderla! Mostreremo come creare il tuo token ERC-20 e la vendita passo dopo passo con gli Smart Contract di Ethereum, come testare gli Smart Contract, come distribuire gli Smart Contract nella blockchain di Ethereum e come costruire un Sito Web ICO distribuito sul Web. Spiegherò anche che cos'è un token ERC-20, come funziona un token Ethereum, come funziona una Initial Coin Offering (ICO).

 

Cos'è un token ERC-20?


La blockchain di Ethereum ti consente di creare la tua criptovaluta o token, che può essere acquistata con Ether, la criptovaluta nativa della blockchain di Ethereum. ERC-20 è semplicemente uno standard che specifica come si comportano questi token, in modo che siano compatibili con altre piattaforme come gli exchange di criptovaluta.

 

È possibile creare un token Ethereum con uno Smart Contract. ERC-20 è uno standard che specifica come dovrebbe funzionare questo contratto smart token. Facciamo un esempio per capire come funziona un contratto smart token ERC-20. Diciamo che vogliamo creare un token chiamato "Mio Token" con il simbolo "MTK" e che ci saranno massimo 100.000.000 di questi token esistenti.

 

Innanzitutto, il token Smart Contract tiene traccia di alcuni attributi di base del token. Ad esempio registra il nome "Mio Token", il simbolo che vedi sull'exchange di criptovaluta e quanti token totali esistono.

 

Tiene anche traccia di chi possiede "Mio Token" e quanto.

I token ERC-20 possono essere trasferiti da un account a un altro come pagamento, proprio come qualsiasi altra criptovaluta. Possono anche essere acquistati in una vendita al pubblico, come un ICO, che esamineremo nella prossima sezione. Possono anche essere acquistati e venduti su un exchange di cripto valute.

 

Come funziona la vendita al pubblico (ICO)

 

I token ERC-20 possono essere distribuiti in vari modi. Un metodo popolare è la vendita di massa (Crowdsale) o un' Initial Coin Offering (ICO). Le vendite "Crowdsale" sono un modo per un'azienda di raccogliere capitali per la propria attività creando il proprio token ERC-20 che può essere acquistato dagli investitori con Ether.

 

Ogni volta che avviene una vendita al pubblico (Crowdsale), la compagnia ottiene capitale liquido sotto forma di Ether che è stato pagato dagli investitori, oltre a detenere una quantità riservata dei token ERC-20 venduti nell'offerta iniziale.

 

Per partecipare ad una crowdsale, un investitore deve connettersi alla Blockchain di Etherum con un account. Questo account ha un indirizzo di portafoglio che può memorizzare Ether, così come i token ERC-20 acquistati nel crowdsale.

 

L'investitore deve visitare un sito web del crowdsale dove viene presentato il progetto. Lo Smart Contract governa tutte le regole su come funziona il crowdsale.

 

Ogni volta che un investitore acquista i token sul sito web del crowdsale, invia Ether dal proprio portafoglio al contratto intelligente e il contratto intelligente eroga immediatamente i token acquistati sul loro portafoglio.

Lo Smart Contract stabilisce il prezzo del token nel crowdsale e regola il funzionamento del crowdsale.

 

I crowdsale possono assumere tutti i tipi di forme e dimensioni. Possono avere più livelli o fasi, come la fase pre ICO, ICO e ICO Bonus. Ciascuno di questi livelli può avvenire in diversi momenti e può comportarsi diversamente.

Possono anche esistere white list per limitare gli investitori che possono acquistare token. Possono anche avere una quantità riservata di token che non sono venduti nel crowdsale. Queste riserve sono solitamente riservate ai membri specifici di ciascuna società come fondatori e consulenti. Queste riserve possono essere una quantità fissa di token o una percentuale. Ogni volta che termina il crowdsale, può essere completata da un amministratore. Ogni volta che succede, tutti i token riservati verranno distribuiti agli account appropriati e il crowdsale sarà ufficialmente finito.

 

Come funzionano i token ERC-20


Come ho spiegato in precedenza, i token ERC-20 sono creati con Smart Contract di Ethereum. 

Ethereum consente agli sviluppatori di scrivere applicazioni che funzionano sulla blockchain con Smart Contract, che incapsulano tutte le logiche di business di queste applicazioni. Ci permettono di leggere e scrivere dati sulla blockchain, nonché di eseguire codice. I contatti intelligenti sono scritti in un linguaggio di programmazione chiamato Solidity, che assomiglia molto a Javascript. È un linguaggio di programmazione completo simile Javascript, ma si comporta in modo un pò diverso a causa del suo caso d'uso, come vedremo in questo tutorial.

 

Nel caso di un token ERC-20, lo Smart Contract governa tutto il comportamento su come funziona il token e tiene traccia della proprietà del token e dei saldi dei conti.

ERC-20 è una specifica API su come devono essere costruiti i token Ethereum. È uno standard adottato dalla comunità che consente ai token di essere supportati in una varietà di casi d'uso. Vogliamo costruire un token che sia conforme a questo standard in modo che possa essere ampiamente accettato. Se non avessimo uno standard come questo, potremmo avere infiniti modi per creare token e potrebbero non essere compatibili l'uno con l'altro!

 

L'utilizzo dello standard ERC-20 garantisce che un token sia conforme per i seguenti casi d'uso (e più):

Trasferimenti di portafogli - invio di token da un account a un altro
Acquisto e vendita di scambi di criptovalute
Acquistando i token in una crowd selling (ICO) come dimostreremo in questo tutorial


Le specifiche ERC-20 determinano essenzialmente l'interfaccia a cui il contratto intelligente deve rispondere. Specifica la struttura del contratto intelligente e i tipi di funzioni che il contratto intelligente deve avere. Fornisce anche alcune funzioni suggerite che sono utili da avere, ma in definitiva opzionali. Determina eventi che il nostro token deve gestire, come un evento di trasferimento. Gli Smart Contract possono emettere eventi a cui i consumatori possono iscriversi e, con questo standard, possiamo sottoscrivere eventi che ci dicono quando vengono venduti i token.

Ecco un esempio di implementazione della funzione di trasferimento specificata dallo standard ERC-20. È richiesto dal contratto intelligente e regola il modo in cui qualcuno può inviare un token ERC-20 dal proprio portafoglio a un altro.

 

contract ERC20Token {
   // ...

   function transfer(address _to, uint256 _value) public returns (bool success) {
       require(balanceOf[msg.sender] >= _value);

       balanceOf[msg.sender] -= _value;
       balanceOf[_to] += _value;

       Transfer(msg.sender, _to, _value);

       return true;
   }

   // ...
}

Questa funzione implementa lo standard ERC-20 nei seguenti modi:

La funzione esiste.
Accetta gli argomenti corretti.
Fallisce se l'utente non ha abbastanza token da trasferire, cioè un bilancio insufficiente.
Trasferisce il saldo dal conto del mittente all'account del destinatario.
Attiva un evento di vendita.
Restituisce il valore corretto, ad es. Vero.


Non preoccuparti se tutto ciò non ha ancora perfettamente senso. Spiegherò tutte queste parti in dettaglio mentre costruiamo il token ERC-20 durante l'esercitazione video passo passo.

Puoi leggere ulteriori informazioni sullo standard dei token ERC-20 direttamente sul repository github di Ethereum Improvement Proposal. È qui che si svolge tutta la discussione della community attorno agli standard di Ethereum. Consiglio vivamente di aggiungere ai segnalibri quel repository e di leggere le submission, poiché è qui che puoi vedere la tecnologia Ethereum crescere e cambiare in tempo reale! Raccomando anche questo articolo su Wikipedia.

 

Iniziamo a costruire il nostro Smart Contract

 

Costruiremo un sito web ICO che parlerà con un smart contract di crowdsale sulla blockchain. Questo sito web lato client avrà una form con cui gli utenti possono acquistare token nella crowdsale. Mostrerà i progressi della crowdsale, come quanti token l'utente ha acquistato, quanti token sono stati acquistati da tutti gli utenti e il numero totale di token disponibili nella vendita della folla. Mostrerà anche l'account in cui siamo connessi alla blockchain con "il tuo account".

 

Installazione di dipendenze
Per costruire il nostro token ERC-20 e il relativo crowdsale, abbiamo bisogno prima di alcune dipendenze.

 

Node Package Manager (NPM)
La prima dipendenza di cui abbiamo bisogno è Node Package Manager, o NPM, che viene fornito con Node.js. Puoi vedere se hai già installato il nodo andando al terminal e digitando:

 

$ node -v

 

Truffle Framework

La prossima dipendenza è il Truffle Framework, che ci consente di creare applicazioni decentralizzate sulla blockchain di Ethereum. Fornisce una suite di strumenti che ci consentono di scrivere contatti intelligenti con il linguaggio di programmazione Solidity. Ci consente inoltre di testare i nostri contratti intelligenti e di implementarli nella blockchain. Ci dà anche un posto dove sviluppare la nostra applicazione client-side.

Puoi installare Truffle con NPM nella riga di comando in questo modo:

 

$ npm install -g truffle

Ganache
La prossima dipendenza è Ganache, una blockchain locale in memoria. È possibile installare Ganache scaricandolo dal sito Web di Truffle Framework. Ci fornirà 10 account esterni con indirizzi sulla blockchain locale di Ethereum. Ogni account è precaricato con 100 Ether falsi.

 

Metamask
La prossima dipendenza è l'estensione Metamask per Google Chrome. Per utilizzare la blockchain, dobbiamo collegarci ad essa (ricorda, ho detto che la blockchain è una rete). Dovremo installare un'estensione del browser speciale per utilizzare la blockchain di Ethereum. È qui che entra in gioco la metamask. Saremo in grado di connetterci alla nostra blockchain locale di Ethereum con il nostro account personale e interagire con il nostro contratto intelligente.

Utilizzeremo l'estensione per Chrome di Metamask per questo tutorial, quindi dovrai anche installare il browser Google Chrome se non lo hai già. Per installare Metamask, cerca il plug-in Metamask Chrome nel web store di Google Chrome. Una volta installato, assicurati che sia selezionato nell'elenco delle estensioni. Quando viene installato, vedrai l'icona nell'angolo in alto a destra del browser Chrome.

 

Evidenziazione della sintassi
La dipendenza è facoltativa, ma consigliata. Raccomando di installare l'evidenziazione della sintassi per il linguaggio di programmazione Solidity. La maggior parte degli editor di testo e degli IDE non presentano l'evidenziazione della sintassi per Solidity out of the box, quindi dovrai installare un pacchetto per supportarlo. Sto usando Sublime Text, e ho scaricato il pacchetto "Ethereum" che fornisce una bella evidenziazione della sintassi per Solidity.

 

Smart Contract token ERC-20
Puoi scaricare il codice per questo smart contract da github qui.

Ora che abbiamo installato le nostre dipendenze, iniziamo a costruire il nostro token ERC-20! 

Ecco il codice completo Solidity del contratto token ERC-20 completo.

 

pragma solidity ^0.4.2;

contract DappToken {
   string  public name = "DApp Token";
   string  public symbol = "DAPP";
   string  public standard = "DApp Token v1.0";
   uint256 public totalSupply;

   event Transfer(
       address indexed _from,
       address indexed _to,
       uint256 _value
   );

   event Approval(
       address indexed _owner,
       address indexed _spender,
       uint256 _value
   );

   mapping(address => uint256) public balanceOf;
   mapping(address => mapping(address => uint256)) public allowance;

   function DappToken (uint256 _initialSupply) public {
       balanceOf[msg.sender] = _initialSupply;
       totalSupply = _initialSupply;
   }

   function transfer(address _to, uint256 _value) public returns (bool success) {
       require(balanceOf[msg.sender] >= _value);

       balanceOf[msg.sender] -= _value;
       balanceOf[_to] += _value;

       Transfer(msg.sender, _to, _value);

       return true;
   }

   function approve(address _spender, uint256 _value) public returns (bool success) {
       allowance[msg.sender][_spender] = _value;

       Approval(msg.sender, _spender, _value);

       return true;
   }

   function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
       require(_value <= balanceOf[_from]);
       require(_value <= allowance[_from][msg.sender]);

       balanceOf[_from] -= _value;
       balanceOf[_to] += _value;

       allowance[_from][msg.sender] -= _value;

       Transfer(_from, _to, _value);

       return true;
   }
}

Diamo un'occhiata a ciò che questo smart contract fa e come implementa lo standard ERC-20:

Memorizza il nome del token: string public name = "DApp Token".
Memorizza il simbolo del token per gli scambi di criptovaluta: string public symbol = "DAPP".
Memorizza la quantità totale di token esistenti: uint256 public totalSupply.
Utilizza una mappatura di Solidità per archiviare il saldo di ciascun account proprietario della mappatura dei token: mapping(address => uint256) public balanceOf.
Implementa una funzione di trasferimento (transfer) per consentire agli utenti di inviare token a un altro account.
Implementa una funzione di approvazione (approve) che consente a un altro account di utilizzare token, come in uno scambio di criptovaluta. Questo aggiorna la mappatura delle quote per vedere quanto l'account è autorizzato a spendere (allowance).
Implementa un trasferimento (transferFrom). Ciò consente a un altro account di trasferire i token.

 

Puoi anche leggere i test per questo contratto intelligente per scoprire di più su come funziona. Questi test assicurano che questo contratto intelligente si comporti come ci aspettiamo. Ecco una suite di test completa che controlla tutto il comportamento per il contratto intelligente:

 

var DappToken = artifacts.require("./DappToken.sol");

contract('DappToken', function(accounts) {
 var tokenInstance;

 it('initializes the contract with the correct values', function() {
   return DappToken.deployed().then(function(instance) {
     tokenInstance = instance;
     return tokenInstance.name();
   }).then(function(name) {
     assert.equal(name, 'DApp Token', 'has the correct name');
     return tokenInstance.symbol();
   }).then(function(symbol) {
     assert.equal(symbol, 'DAPP', 'has the correct symbol');
     return tokenInstance.standard();
   }).then(function(standard) {
     assert.equal(standard, 'DApp Token v1.0', 'has the correct standard');
   });
 })

 it('allocates the initial supply upon deployment', function() {
   return DappToken.deployed().then(function(instance) {
     tokenInstance = instance;
     return tokenInstance.totalSupply();
   }).then(function(totalSupply) {
     assert.equal(totalSupply.toNumber(), 1000000, 'sets the total supply to 1,000,000');
     return tokenInstance.balanceOf(accounts[0]);
   }).then(function(adminBalance) {
     assert.equal(adminBalance.toNumber(), 1000000, 'it allocates the initial supply to the admin account');
   });
 });

 it('transfers token ownership', function() {
   return DappToken.deployed().then(function(instance) {
     tokenInstance = instance;
     // Test `require` statement first by transferring something larger than the sender's balance
     return tokenInstance.transfer.call(accounts[1], 99999999999999999999999);
   }).then(assert.fail).catch(function(error) {
     assert(error.message.indexOf('revert') >= 0, 'error message must contain revert');
     return tokenInstance.transfer.call(accounts[1], 250000, { from: accounts[0] });
   }).then(function(success) {
     assert.equal(success, true, 'it returns true');
     return tokenInstance.transfer(accounts[1], 250000, { from: accounts[0] });
   }).then(function(receipt) {
     assert.equal(receipt.logs.length, 1, 'triggers one event');
     assert.equal(receipt.logs[0].event, 'Transfer', 'should be the "Transfer" event');
     assert.equal(receipt.logs[0].args._from, accounts[0], 'logs the account the tokens are transferred from');
     assert.equal(receipt.logs[0].args._to, accounts[1], 'logs the account the tokens are transferred to');
     assert.equal(receipt.logs[0].args._value, 250000, 'logs the transfer amount');
     return tokenInstance.balanceOf(accounts[1]);
   }).then(function(balance) {
     assert.equal(balance.toNumber(), 250000, 'adds the amount to the receiving account');
     return tokenInstance.balanceOf(accounts[0]);
   }).then(function(balance) {
     assert.equal(balance.toNumber(), 750000, 'deducts the amount from the sending account');
   });
 });

 it('approves tokens for delegated transfer', function() {
   return DappToken.deployed().then(function(instance) {
     tokenInstance = instance;
     return tokenInstance.approve.call(accounts[1], 100);
   }).then(function(success) {
     assert.equal(success, true, 'it returns true');
     return tokenInstance.approve(accounts[1], 100, { from: accounts[0] });
   }).then(function(receipt) {
     assert.equal(receipt.logs.length, 1, 'triggers one event');
     assert.equal(receipt.logs[0].event, 'Approval', 'should be the "Approval" event');
     assert.equal(receipt.logs[0].args._owner, accounts[0], 'logs the account the tokens are authorized by');
     assert.equal(receipt.logs[0].args._spender, accounts[1], 'logs the account the tokens are authorized to');
     assert.equal(receipt.logs[0].args._value, 100, 'logs the transfer amount');
     return tokenInstance.allowance(accounts[0], accounts[1]);
   }).then(function(allowance) {
     assert.equal(allowance.toNumber(), 100, 'stores the allowance for delegated trasnfer');
   });
 });

 it('handles delegated token transfers', function() {
   return DappToken.deployed().then(function(instance) {
     tokenInstance = instance;
     fromAccount = accounts[2];
     toAccount = accounts[3];
     spendingAccount = accounts[4];
     // Transfer some tokens to fromAccount
     return tokenInstance.transfer(fromAccount, 100, { from: accounts[0] });
   }).then(function(receipt) {
     // Approve spendingAccount to spend 10 tokens form fromAccount
     return tokenInstance.approve(spendingAccount, 10, { from: fromAccount });
   }).then(function(receipt) {
     // Try transferring something larger than the sender's balance
     return tokenInstance.transferFrom(fromAccount, toAccount, 9999, { from: spendingAccount });
   }).then(assert.fail).catch(function(error) {
     assert(error.message.indexOf('revert') >= 0, 'cannot transfer value larger than balance');
     // Try transferring something larger than the approved amount
     return tokenInstance.transferFrom(fromAccount, toAccount, 20, { from: spendingAccount });
   }).then(assert.fail).catch(function(error) {
     assert(error.message.indexOf('revert') >= 0, 'cannot transfer value larger than approved amount');
     return tokenInstance.transferFrom.call(fromAccount, toAccount, 10, { from: spendingAccount });
   }).then(function(success) {
     assert.equal(success, true);
     return tokenInstance.transferFrom(fromAccount, toAccount, 10, { from: spendingAccount });
   }).then(function(receipt) {
     assert.equal(receipt.logs.length, 1, 'triggers one event');
     assert.equal(receipt.logs[0].event, 'Transfer', 'should be the "Transfer" event');
     assert.equal(receipt.logs[0].args._from, fromAccount, 'logs the account the tokens are transferred from');
     assert.equal(receipt.logs[0].args._to, toAccount, 'logs the account the tokens are transferred to');
     assert.equal(receipt.logs[0].args._value, 10, 'logs the transfer amount');
     return tokenInstance.balanceOf(fromAccount);
   }).then(function(balance) {
     assert.equal(balance.toNumber(), 90, 'deducts the amount from the sending account');
     return tokenInstance.balanceOf(toAccount);
   }).then(function(balance) {
     assert.equal(balance.toNumber(), 10, 'adds the amount from the receiving account');
     return tokenInstance.allowance(fromAccount, spendingAccount);
   }).then(function(allowance) {
     assert.equal(allowance.toNumber(), 0, 'deducts the amount from the allowance');
   });
 });
});

 

Puoi eseguire il test dalla riga di comando con Truffle in questo modo:

 

$ truffle test

Ora possiamo creare un contratto intelligente per il crowdsale che consentirà agli investitori di acquistare token in un'offerta iniziale di monete (ICO). Ecco il codice completo di vendita intelligente del contratto di solidity:

 

pragma solidity ^0.4.2;

import "./DappToken.sol";

contract DappTokenSale {
   address admin;
   DappToken public tokenContract;
   uint256 public tokenPrice;
   uint256 public tokensSold;

   event Sell(address _buyer, uint256 _amount);

   function DappTokenSale(DappToken _tokenContract, uint256 _tokenPrice) public {
       admin = msg.sender;
       tokenContract = _tokenContract;
       tokenPrice = _tokenPrice;
   }

   function multiply(uint x, uint y) internal pure returns (uint z) {
       require(y == 0 || (z = x * y) / y == x);
   }

   function buyTokens(uint256 _numberOfTokens) public payable {
       require(msg.value == multiply(_numberOfTokens, tokenPrice));
       require(tokenContract.balanceOf(this) >= _numberOfTokens);
       require(tokenContract.transfer(msg.sender, _numberOfTokens));

       tokensSold += _numberOfTokens;

       Sell(msg.sender, _numberOfTokens);
   }

   function endSale() public {
       require(msg.sender == admin);
       require(tokenContract.transfer(admin, tokenContract.balanceOf(this)));

       // Just transfer the balance to the admin
       admin.transfer(address(this).balance);
   }
}

Diamo un'occhiata a ciò che questo smart contract fa e come funziona nella crowdsale:

Memorizza un account amministratore per il crowdsale: address admin.
Fa riferimento al contratto intelligente token ERC-20: DappToken public tokenContract.
Memorizza il prezzo del token: uint256 public tokenPrice.
Memorizza il numero di token venduti: uint256 public tokensSold.
Implementa un evento di vendita (sell) in modo che i consumatori possano ricevere notifiche ogni volta che un token è stato venduto.
Implementa una funzione buyTokens che consente agli utenti di acquistare token nella vendita della folla.
Implementa una funzione endSale che consente a un amministratore di terminare la vendita della folla e raccogliere i fondi Ether raccolti durante la vendita.

 

Puoi anche leggere i test per questo contratto intelligente per scoprire di più su come funziona. Questi test assicurano che questo contratto intelligente si comporti come ci aspettiamo. Ecco una suite di test completa che controlla tutto il comportamento per il contratto intelligente:

 

var DappToken = artifacts.require('./DappToken.sol');
 var DappTokenSale = artifacts.require('./DappTokenSale.sol');

 contract('DappTokenSale', function(accounts) {
   var tokenInstance;
   var tokenSaleInstance;
   var admin = accounts[0];
   var buyer = accounts[1];
   var tokenPrice = 1000000000000000; // in wei
   var tokensAvailable = 750000;
   var numberOfTokens;

   it('initializes the contract with the correct values', function() {
     return DappTokenSale.deployed().then(function(instance) {
       tokenSaleInstance = instance;
       return tokenSaleInstance.address
     }).then(function(address) {
       assert.notEqual(address, 0x0, 'has contract address');
       return tokenSaleInstance.tokenContract();
     }).then(function(address) {
       assert.notEqual(address, 0x0, 'has token contract address');
       return tokenSaleInstance.tokenPrice();
     }).then(function(price) {
       assert.equal(price, tokenPrice, 'token price is correct');
     });
   });

   it('facilitates token buying', function() {
     return DappToken.deployed().then(function(instance) {
       // Grab token instance first
       tokenInstance = instance;
       return DappTokenSale.deployed();
     }).then(function(instance) {
       // Then grab token sale instance
       tokenSaleInstance = instance;
       // Provision 75% of all tokens to the token sale
       return tokenInstance.transfer(tokenSaleInstance.address, tokensAvailable, { from: admin })
     }).then(function(receipt) {
       numberOfTokens = 10;
       return tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: numberOfTokens * tokenPrice })
     }).then(function(receipt) {
       assert.equal(receipt.logs.length, 1, 'triggers one event');
       assert.equal(receipt.logs[0].event, 'Sell', 'should be the "Sell" event');
       assert.equal(receipt.logs[0].args._buyer, buyer, 'logs the account that purchased the tokens');
       assert.equal(receipt.logs[0].args._amount, numberOfTokens, 'logs the number of tokens purchased');
       return tokenSaleInstance.tokensSold();
     }).then(function(amount) {
       assert.equal(amount.toNumber(), numberOfTokens, 'increments the number of tokens sold');
       return tokenInstance.balanceOf(buyer);
     }).then(function(balance) {
       assert.equal(balance.toNumber(), numberOfTokens);
       return tokenInstance.balanceOf(tokenSaleInstance.address);
     }).then(function(balance) {
       assert.equal(balance.toNumber(), tokensAvailable - numberOfTokens);
       // Try to buy tokens different from the ether value
       return tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: 1 });
     }).then(assert.fail).catch(function(error) {
       assert(error.message.indexOf('revert') >= 0, 'msg.value must equal number of tokens in wei');
       return tokenSaleInstance.buyTokens(800000, { from: buyer, value: numberOfTokens * tokenPrice })
     }).then(assert.fail).catch(function(error) {
       assert(error.message.indexOf('revert') >= 0, 'cannot purchase more tokens than available');
     });
   });

   it('ends token sale', function() {
     return DappToken.deployed().then(function(instance) {
       // Grab token instance first
       tokenInstance = instance;
       return DappTokenSale.deployed();
     }).then(function(instance) {
       // Then grab token sale instance
       tokenSaleInstance = instance;
       // Try to end sale from account other than the admin
       return tokenSaleInstance.endSale({ from: buyer });
     }).then(assert.fail).catch(function(error) {
       assert(error.message.indexOf('revert' >= 0, 'must be admin to end sale'));
       // End sale as admin
       return tokenSaleInstance.endSale({ from: admin });
     }).then(function(receipt) {
       return tokenInstance.balanceOf(admin);
     }).then(function(balance) {
       assert.equal(balance.toNumber(), 999990, 'returns all unsold dapp tokens to admin');
       // Check that the contract has no balance
       balance = web3.eth.getBalance(tokenSaleInstance.address)
       assert.equal(balance.toNumber(), 0);
     });
   });
 });

Hai creato con successo un contratto ERC-20 e un contratto smart per il crowdsale. 

Puoi anche scaricare il codice sorgente completo di questo tutorial da github qui.

 

Fonte: dappuniversity.com


Ross Evans

Appassionato di criptovalute, blockchain e sistemi di pagamento. 

Donate

12yDuRua58dCr3DySZfKXiDEgjcA7jJe49
0x883643620C5C4056819d98a969d1ad44ea14AF9f
0xcc5D19Cb2CDEC665D395209112a8b8a895f2C429

GUADAGNA CRIPTOVALUTE CON CRYPTOX.IT

Se alla fine dell'articolo trovi "Guadagna cripto condividento questo contenuto" potrai guadagnare criptovalute condividendo il contenuto sui tuoi social o tra i tuoi amici, leggi il regolamento.

RELATED NEWS

Cardano porta le risorse digitali su Shopify e WooCommerce

Annunciata una nuova integrazione
by Linda Carlton Apr 25, 2021

Cardano raggiungerà gli 8 dollari intorno ad Halloween

L'analista di criptovalute Ben Armstron
by Ross Evans Apr 11, 2021

Come funziona il Bitcoin Standard Hashrate Token (BTCST)?

Lanciato su Binance Smart Chain (BSC) il 13 dicembre 2020
by Ross Evans Apr 13, 2021

Cardano introduce il registro per i token nativi

Nuova funzionalità annunciata da Cardano Foundation
by Ross Evans Apr 16, 2021

Il governo etiope con Cardano per aiutare l'istruzione

Parte una nuova partnership con Cardano IOHK
by Linda Carlton Apr 28, 2021

Gary Gensler confermato come nuovo presidente della SEC

Il Senato ha votato per approvare la nomina di Gary Gensler
by Linda Carlton Apr 15, 2021

Teeka Tiwari: Ethereum è ancora sottovalutato

Secondo l'analista può salire ancora di un altro 500%
by James Lombardi Apr 14, 2021

Lanciata oggi cEUR, la stablecoin ancorata all’Euro

Celo, l’ecosistema blockchain mobile-first
by James Lombardi Apr 20, 2021

Litecoin sta formando un setup rialzista

Afferma il principale analista Nicholas Merten
by Ross Evans Apr 09, 2021

Rothschild Investment acquista $ 4,75 milioni di azioni del Grayscale Ethereum Trust

Ora possiede un totale di 38.346 azioni GBTC
by Linda Carlton Apr 20, 2021

AgeUSD verrà lanciato come primo Stablecoin su Cardano Network

Sarà la prima per la rete
by James Lombardi Apr 17, 2021

Il primo ETF Ethereum al mondo approvato dai regolatori canadesi

Lanciato da Purpose Investments
by Linda Carlton Apr 17, 2021

I token della azioni di Microsoft, Apple e MicroStrategy saranno listati su Binance

L'annuncio arriva dalla nota piattaforma di trading
by Linda Carlton Apr 26, 2021

Bitcoin è "troppo trasparente" per essere utilizzato per riciclare denaro

Questa la dichiarazione dell'ex direttore della CIA
by Linda Carlton Apr 14, 2021

Nuovo passo avanti verso la Proof of Stake (PoS) di Ethereum

Il merge della Devnet di Ethereum 2.0 è stata completata con successo
by Linda Carlton May 02, 2021

"Britcoin" in futuro? Il Regno Unito testa la valuta digitale

La Bank of England ha avviato i test provvisori
by Linda Carlton Apr 19, 2021

Cardano Africa Special: IOG collabora con World Mobile per connettere 250.000 persone

Annunciata la partnership con World Mobile
by Linda Carlton Apr 30, 2021

Ethereum raggiunge il nuovo massimo storico

Sfondata la barriera dei 3.000 dollari
by Linda Carlton May 03, 2021

l nuovo brevetto di VeChain potrebbe aiutare a compensare le emissioni di carbonio

VeChain Global Technology ha presentato una petizione
by Linda Carlton May 04, 2021

COMMENTS


PARTNER

CRYPTO RATES

24h 24h Vol Price
BTC +2,52 53.512,24M 48.685,97 EUR
ETH -6,28 31.782,07M 2.939,91 EUR
RPD +15.989.979,42 0,40M 18,45 EUR
BNB -0,41 2.831,96M 518,98 EUR
DOGE +17,25 22.163,52M 0,59 EUR
XRP -4,29 5.890,89M 1,30 EUR
USDT -0,67 129.912,04M 0,82 EUR
ADA -8,01 3.963,00M 1,31 EUR
DOT -5,29 1.874,84M 32,32 EUR
BCH -3,23 6.294,18M 1.135,13 EUR
aggiornato 3 minuti fa da coinmarketcap.com

POPULAR VIDEOS

POPULAR BOOKS

The Bitcoin Standard
The Bitcoin Standard
by Saifedean Ammous Dec 06, 2020
Compra su Amazon
The Mystery Of Banking
The Mystery Of Banking
by Murray N. Rothbard Dec 06, 2019
Compra su Amazon
Mastering Bitcoin
Mastering Bitcoin
by Andreas M. Antonopoulos Nov 12, 2020
Compra su Amazon
Flash Boys
Flash Boys
by Michael Lewis Nov 19, 2019
Compra su Amazon

POPULAR TWEETS

@AndrewNation13 @AndrewNation13 - 21 hours ago Latest Ripple XRP News @Kevin_Cage_ #XRP #cryptocurrency #bestcrypto https://t.co/VAGjl5MGGo

  • 17
  • 2

Agostino Mario Mela @agostinomela - 6 hours ago Si chiamano criptovalute perché per la stragrande maggioranza delle persone sono e saranno sempre un grande mistero.

  • 14
  • 0

FREE MCAFEE - Freedom Club @ostvest - 23 hours ago La mia microazienda, come sapranno i miei affezionatissimi lettori, accantona il 10% delle fatture in ingresso in criptovalute. Ecco il portafoglio ad oggi. NOT FINANCIAL ADVICE - YES LIFE ADVICE https://t.co/iiZU71sNaX

  • 8
  • 0

IOTA - The next generation of Crypto @IotaBullrun2020 - 21 hours ago #IOTA + #INTEL + #DELL = WORKS $iota $miota #miota #altcoins #altcoin #altseason #btc #bitcoin #usdt #binance #bnb https://t.co/p1tutJZfQa

  • 7
  • 2

ハデス @ripple_chan - 22 hours ago AI inside https://t.co/PY166U65br

  • 7
  • 1

CRYPTO NETWORK

Reward Block Difficulty
BTC 6 682449 20.608.845M
ETH 2 12389569 7.470.847.865M
BCH 6 686885 446.535M
UNO 0 1331510 368.211M
XMR 2 2355926 289.099M
DASH 1 1467121 199M
LTC 12 2048442 12M
ZEC 2 1241587 97M
ZEN 3 928985 33M
ETC 3 12697629 403.997.000M
aggiornato 16 ore fa da coinwarz.com

PODCAST


LINKS