Blockchain

Jak stworzyć token ERC-20 i contract ICO (cz.2)

Ethereum

Jak już wspominaliśmy w poprzedniej części artykułu, bezpieczeństwo w temacie smart contractów to kluczowa sprawa. Zwłaszcza jeśli w grę wchodzą tokeny o wartości setek tysięcy czy milionów dolarów. Dlatego skupimy się właśnie na zabezpieczeniu contractów.


Michał Dulat. Software engineer w Ragnarson. Inżynier oprogramowania z ponad 8 letnim doświadczeniem zawodowym, specjalizujący się w aplikacjach webowych. Współautor newslettera Blockchain Weekly, raczkujący Blockchain developer oraz miłośnik kryptografii i ostrej kuchni.

 

 

 

Piotr Misiurek. Blockchain Technology Specialist. Programista i startupowiec z ponad 10-cio letnim doświadczeniem i anarchistyczną duszą. Entuzjasta technologii blockchain, w której zakochał się na jesieni 2016 roku. Od tego czasu jest współredaktorem newslettera Blockchain Weekly, współtworzy społeczności entuzjastów blockchaina i kryptowalut w Łodzi (Blockchain Meetup Łódź) oraz pomaga klientom wejść w świat blockchaina, tokenów i ICO w firmie Ragnarson. Lata spędza w Europie, a zimy w Azji.


W naszym smart contractcie ICO zgromadzonych środków nie trzymamy w samym contractcie, a są transferowane na specjalny adres. To powszechnie stosowana praktyka. Zdajemy sobie sprawę z naszych ułomności i chcemy minimalizować potencjalne zagrożenia. Jeśli nie używamy naszego smart contractu do przechowywania środków, to nawet potencjalne błędy w nim nie pozwolą hackerowi na kradzież, bądź zamrożenie naszych środków.

Dlatego transferujemy zgromadzone środki na zewnętrzny portfel. Polecane przez nas rozwiązanie to stworzenie portfela multisig przy wykorzystaniu kluczy prywatnych trzymanych na portfelach sprzętowych.

Portfel multisig to taki portfel, który wymaga podpisów kilku osób przy zlecaniu transferów środków z tego adresu. Dzięki temu zwiększa się nasza odporność, po pierwsze na złą wolę ludzi pracujących w projekcie (nikt nie może samodzielnie podjąć środków) oraz na zewnętrzne ataki (nie wystarczy zaatakować jednej osoby, zdobyć jednego klucza prywatnego, aby mieć dostęp do środków). Tworząc portfel multisig określamy z ilu kluczy prywatnych będzie on stworzony oraz zgoda ilu z nich będzie wymagana do wykonania transakcji. Na przykład portfel 5 z 7 oznacza, że jest on tworzony przez 7 kluczy prywatnych i każda transakcja musi zostać podpisana przez co najmniej 5 z nich.

Sieć Ethereum, w przeciwieństwie do np. Bitcoina, nie obsługuje natywnie adresów multisig. Portfele multisig na Ethereum są więc po prostu smart contractami. Na rynku jest kilka popularnych rozwiązań. My polecamy projekt przygotowany przez zespół GNOSIS. Dostarcza on zarówno smart contract do trzymania środków, jak interfejs webowy i desktopowy do zarządzania zgromadzonymi środkami. Portfel ten jest zdolny zarówno do przechowywania assetów (ETH i tokeny ERC-20), jak i do podejmowania interakcji z innymi smart contractami. Wiele znanych projektów wykorzystuje go. Więcej informacji o portfelu znajdziesz tutaj.

Do przechowywania kluczy prywatnych wykorzystywanych przez portfel multisig oraz podpisywania transakcji dobrze jest wykorzystać portfel sprzętowy. To urządzenia, które na specjalnym bezpiecznym chipie przechowują klucz prywatny, niemożliwy do odczytania z zewnątrz. Na zewnątrz przesyłane są tylko gotowe podpisy do transakcji. Najpopularniejszymi tego typu urządzeniami są Trezor i Ledger Nano S. Ten drugi jest obsługiwany przez GNOSIS multisig wallet.

Sieci Ethereum — mainnet i sieci testowe

Jak zapewne wiesz, każda transakcja wykonana w sieci Ethereum wiąże się z koniecznością uiszczenia opłaty transakcyjnej. Dodatkowo przepustowość sieci jest dość ograniczona (do kilkunastu transakcji na sekundę). Dlatego zarówno dla developerów, jak i dla innych użytkowników sieci, nie jest w interesie, aby rozwój smart contractu dział się bezpośrednio w głównej sieci Ethereum. Aby rozwiązać ten problem powstały różne sieci testowe, o zbliżonym działaniu do sieci głównej, ale gdzie Ether potrzebny do dokonania transakcji można dostać za darmo? Najpopularniejsze sieci testowe Ethereum to:

Testy pierwszych wersji smart contractów powinniśmy więc przeprowadzać na jednej z sieci testowych. Dotyczy to także testów wersji beta, gdzie zapraszamy już zewnętrznych użytkowników. Ma to dla nich dodatkową zaletę, że nie ma kosztów transakcyjnych (testowy Ether jest darmowy) oraz nie ma ryzyka utraty wartości (assety w sieciach testowych nie mają realnej wartości).

Deployment na testnet

Mamy już napisany kod naszego ICO. Teraz czas przetestować go na żywym organizmie. W tym celu umieścimy go na sieci testowej Ropsten, dzięki czemu będzie on publicznie dostępny do przeprowadzania transakcji.

Truffle automatyzuje nie tylko proces developmentu i testowania, ale także deploymentu smart contractów, dzięki migracjom. W dużym uproszczeniu służą one do interakcji z siecią, może nią być testnet, jak i również mainnet. W pierwszej kolejności wygenerujemy sobie migrację do deploymentu naszego contractu tokenu:

$ truffle create migration deploy_token_contract

W pliku migracji zajmiemy się wdrożeniem naszego contractu na Blockchain Ethereum:

const CharityToken = artifacts.require('CharityToken')

module.exports = function (deployer, network) {
 if (network === 'testrpc') return
 deployer.deploy(CharityToken)
}

Funkcja migracji przyjmuje dwa parametry, deployer odpowiedzialny za fizyczne wdrożenie contractów do sieci oraz network, czyli string reprezentujący nazwę sieci, do której wdrażamy nasz contract. W powyższym przykładzie warunkowo uniemożliwiliśmy wykonanie się deploymentu dla sieci o nazwie testrpc. Nie jest to wymagane, ale w naszym przypadku było to potrzebne do automatycznych testów.

Kolejno napiszemy migrację dla contractu ICO:

$ truffle create migration deploy_ico_contract
const CharityToken = artifacts.require('CharityToken')
const CharityTokenICO = artifacts.require('CharityTokenICO')

module.exports = async function (deployer, network) {
 if (network === 'testrpc') return

 const startTime = parseInt(process.env.START_TIME)
 const endTime = parseInt(process.env.END_TIME)
 const rate = parseInt(process.env.RATE)
 const wallet = process.env.WALLET

 await deployer.deploy(CharityTokenICO, startTime, endTime, rate, wallet, CharityToken.address)
 await CharityToken.at(CharityToken.address).transferOwnership(CharityTokenICO.address)
}

Migracja ta inicjuje contract CharityTokenICO wartościami parametrów START_TIME, END_TIME, RATE oraz WALLET, które zostały opisane bardziej szczegółowo w części implementacyjnej contractów. Parametry te musimy umieścić w pliku .env, który wcześniej należy utworzyć w głównym katalogu projektu (zainstaluj wcześniej dotenv zgodnie z instrukcjami na stronie https://www.npmjs.com/package/dotenv). W migracji używamy również contractu CharityToken, który przed chwilą wdrożyliśmy w poprzedniej migracji.

Przed przystąpieniem do uruchomienia deploymentu, musimy jeszcze skonfigurować połączenie z nodem odpowiedzialnym za wdrożenie contractów. W pliku truffle.js:

require('dotenv').config()
require('babel-register')
require('babel-polyfill')
require('babel-node-modules')([
 'zeppelin-solidity'
])

const HDWalletProvider = require('truffle-hdwallet-provider')
const infuraToken = process.env.INFURA_TOKEN
const mnemonic = process.env.DEPLOYMENT_WALLET_MNEMONIC

module.exports = {
 solc: {
   optimizer: {
     enabled: true,
     runs: 200
   }
 },
 networks: {
   ropsten: {
     provider: new HDWalletProvider(mnemonic, `https://ropsten.infura.io/${infuraToken}`),
     network_id: 3,
     gas: 4698717
   }
 }
}

W pliku .env umieszczamy poniższe parametry:

  • INFURA_TOKEN — token służący do komunikacji z nodem Infury, który należy wygenerować na stronie infura.io. Infura to serwis dostarczający usługę deploymentu.
  • DEPLOYMENT_WALLET_MNEMONIC — seed naszego konta, z którego będziemy przeprowadzać deployment i który to adres będzie właścicielem contractu. Jest to lista angielskich słówek, która została wyświetlona podczas zakładania portfela Ethereum. Jeśli jeszcze tego nie zrobiłeś, możesz do tego wykorzystać np. Metamask.

Przed deploymentem musimy jeszcze zdobyć testowe ethery, które będę potrzebne do opłacenia transaction fee. Na szczęście są one darmowe i można je zdobyć na jednym ze źródeł:

Dodatkowo należy zainstalować bibliotekę truffle-hdwallet-provider, która umożliwi nam deployment:

npm install truffle-hdwallet-provider

W następnej kolejności możemy zająć się deploymentem naszego tokenu i ICO:

$ truffle migrate --network ropsten

Deployment na mainnet

Po tym, gdy upewniliśmy się na testnecie, że nasz token i ICO działają jak należy, możemy w końcu umieścić nasze contracty na mainnecie. Sam deployment nie różni się niczym od tego testowego, poza tym, że dodajemy konfiguracje mainnet oraz że za transakcje płacimy prawdziwym Etherem.

Wracamy do pliku truffle.js, gdzie do tablicy networks dodajemy kolejny element:

mainnet: {
     provider: new HDWalletProvider(mnemonic, `https://mainnet.infura.io/${infuraToken}`),
     network_id: 1,
     gas: 4698717,
     gasPrice: 5100000000 // 5.1 GWei
   }

Różnice jakie możemy zauważyć, to:

  • Inny adres API infura, z którego korzystamy, tym razem w subdomenie mainnet,
  • Inny network_id, który dla mainnetu wynosi 1,
  • Nowy parametr gasPrice, w którym wyznaczamy cenę za gaz jaką chcemy płacić. Płacimy realnym Etherem, więc tym razem ma to znaczenie, dlatego chcemy mieć kontrolę nad tym parametrem. Polecam skorzystanie ze strony ethgasstation.info, aby ustawić optymalną na daną chwilę cenę gazu.

Jak już mamy gotowy nasz nowy config, a na adresie którego używamy do przeprowadzenia deploymentu znajduje się Ether, to możemy w końcu wysłać nasz token i ICO na główny blockchain Ethereum:

$ truffle migrate --network mainnet

Jeżeli masz problemy z implementacją to odsyłam Cię do repozytorium, gdzie znajdziesz pełen source code projektu: https://github.com/Ragnarson/charity-token.

Ok, nasz token hula już po mainnecie, a Ty stałeś się prawdziwym blockchain devem 😉 Czekamy na Twój feedback w komentarzach.


baner

Zdjęcie główne artykułu pochodzi z shellypalmer.com.

Podobne artykuły

[wpdevart_facebook_comment curent_url="https://justjoin.it/blog/stworzyc-token-erc-20-contract-ico-cz-2" order_type="social" width="100%" count_of_comments="8" ]