
Hello! In this article I will tell you how in 5 minutes and a few commands in the terminal to launch a smart contract to collect money for your ICO on Ethereum. This essay will potentially save you tens of thousands of US dollars, since any programmer — and not a programmer too — will be able to run an audited and secure smart contract (instead of paying $ 15,000 - $ 75,000 for development). In short, you can send money to this smart contract and get ERC20 tokens for it. You can say this article is a collection of all the experience I gained by launching an ICO for my project.
On the Internet, these are yours and so full of an article about smart contracts, but as soon as you start to write this, you are faced with the fact that the information is repeated everywhere, and the tutorials on how to run your ERC20 are either not there, or they are outdated and that is utterly impossible. By the way, in order for this article to remain relevant, I will try to indicate potential places where it might become outdated (and how to fix it). Go!
Solidity
This is the name of the main language that the kefir team developed to launch smart contracts. If you are a programmer, then just glance over the
documentation of the language - it is indecently simple. By the way, they made it simple so that it was more difficult to make a mistake in writing a smart contract. So
absolutely any programmer at least at the junior level can figure it out.
Absolutely no sense in paying huge money to developers who know solidity - it will be cheaper to train an existing developer.
Smart contracts
... and everything you need to know about them. Skip this section if you are not a programmer. A smart contract is a piece of code. In principle, this is a class in solidity (OOP, yes), which has two types of functions: state changing and non changing. Well, to launch functions in a smart contract just by sending kefir to it, you need to mark this function
payable
.
The state is a data warehouse, blockchain, epta. Contracts can change the blockchain (state, storage) - but to change the blockchain you need to pay kefir to miners. How they will share kefir will not be analyzed in this article. Paying miners for running a code that changes state is called Gas. If someone from the outside throws kefir on the address of a smart contract with a call to a function marked
payable
but not labeled
Constant
,
View
or
Pure
, then the required amount of kefir will be deducted from the amount sent to pay for miners. Usually in ERC20 tokens are functions that either issue token senders as kefir, or transfer tokens from one token holder to another.
And if you mark a function in the contract with the words
Constant
or
View
(they mean the same thing, they allow only to read the state), or
Pure
(the same, only the state does not read), then even kefir will not have to spend on the execution of this function! I will say even more, these functions do not need to be called up by transactions - after all, any kefir client, theoretically, can execute it at home - and no one else needs to know about it (because nothing is written in the blockchain).
And there are two important things in solidity: multiple inheritance and function modifiers. About them, too, need to know.
The first is that contracts can be inherited simultaneously from several classes such as
TimedCrowdsale
,
CappedCrowdsale
,
MintedCrowdsale
,
Ownable
— while the functions of the constructors are also launched one after the other — but I will explain this later with an example.
The second is the ability to create functions that will then be inserted into other functions. It's like simple encapsulation, just a bit more flexible — it's literally
a function
template . When you create a modifier, you write a special
_
character where you mean the code of the function using this modifier. That is, modifiers are not just an encapsulated functional that returns a value; this is the function template when the code from the modifier is literally inserted into the function using this modifier.
Let's go to practice.
Cooking environment
If you do not know what Terminal is - read
this article here . If you are on the windows, set yourself a terminal through the WLS. If you are already familiar with the Terminal, continue. Also, immediately
put yourself Node.js - it will be necessary for the next steps. It is better to set LTS, but, in fact, absolutely no difference, which of the modern versions of the node to put.
The first thing we will immediately put in and start the block synchronization process is
geth
. In short, this is a utility written in Go, which will allow us to run the ether node on the local computer and connect to the test and real network. You can install
via installers , but I strongly advise you to geth
geth
to the Terminal right away, as described
here . You can check whether your
geth
rules are
geth
running a command in the Terminal:
geth version
If you get the version of geth - everything is in openwork, we continue the tutorial. If not - bad, correct; It seems you will have to deal with love caress with the Terminal and your operating system - but you will not be the first to figure it out. How to install geth, run the following command in the Terminal:
geth --testnet console
This will start the process of synchronization of your node with the test server, the blocks of which can be viewed
here . You can check whether you have synchronized with the network in the
geth
console by
geth
:
eth.blockNumber
The synchronization process took me from 1 to 4 hours - when how. Also, in addition to block synchronization, you will have to wait for state synchronization - this is more often longer than block synchronization. You can also use
geth
with the
--light
flag - then synchronization lasts from a few seconds to a minute and you can still deploy contracts.
All right, we have put the first utility - we put the following. We need to put an analogue of
geth
, only a very local simulation of the blockchain -
testrpc
. Yes, yes, we have
3 blockchains :
testrpc
- local blockchain simulation; fast but unrealistic and stored only on your cargeth --testnet
- geth --testnet
is already a real blockchain, but the test network, where you can get kefir for free and test any lewdness, won't lose moneygeth
- mainnet, main, real blockchain, real kefir; all grown-up, mistakes here - the loss of real kefir
Accordingly, we will begin the test of contracts with
testrpc
, then we will get into
geth --testnet
, and then we will start right in
geth
.
testrpc
by running the following command:
npm install -g ethereumjs-testrpc
Well, or get up immediately with a truffle, as now
testrpc
under the wing of the truffle is called
ganache-cli
. Although the devil knows, I have everything and vanilla
testrpc
worked. And if it works, don't touch it, as they taught me at the intergalactic academy. You can also launch it to check the installation, by registering a
truffle
in the console, but we are already synchronizing the test blockchain - we will not disturb it.
Well, have you dealt with blockchains? Now there is a node and the test is even synchronized? We put a convenient utility for working with smart contracts on kefir -
truffle
, with the following command:
npm install -g truffle truffle version
A truffle is a tool that allows you to keep smart contracts in different files, import other files, and also compiles your smart contract code into one big byte code (unreadable by human), automatically finds your locally running
geth
(test and real ) or
testrpc
, deploy your smart contract to this network. Also, it checks your smart contract code for errors and, more recently, completed transactions
help debug . Mast of, shorter.
At this stage, you should have installed:
testrpc
,
geth
,
truffle
- if one of these things is missing or the version is not spat out to the console upon request, then correct this; otherwise you will not succeed.
Also, I nakidal simple bash-skriptik , which installs everything for you. Called like this:
source <(curl -s https://raw.githubusercontent.com/backmeupplz/eth-installer/master/install.sh)
- but I have never tested it yet, so I'm not sure about its efficiency. However, pull requests will be only happy.
Figa contract
Everything has been thought out and written for you - this is good. A little smut will not care - but I will try to minimize it to you. We will use
ready-made ERC20 contracts from OpenZeppelin - this is now the industry standard, they have been audited, and indeed all their code is used. Thanks to them so much for their contribution to the open-sence.
Make a
cd
in some safe folder and then write:
mkdir contract && cd contract
In this folder we will work. Create a stub here for our smart contract:
truffle init
Be hurt, clearly. We now have two very important folders into which we will climb:
contracts
and
migrations
. The first is the code of our contracts, the second is the code for truffle, so that we know what to do with the total number of contracts in the blockchain.
Next we need to pick up the current smart contract code from npm and, strictly speaking, start the project itself:
npm init -y
Great, the smart contract code from OpenZeppelin is in our pocket in the
node_modules/openzeppelin-solidity/contracts
folder. Now go to the main
contracts
folder, delete all the files there and add the files
MyToken.sol
and
MyCrowdsale.sol
- naturally, you will call your contracts differently. The first will be the contract for our ERC20 Token, and the second - by the contract of our ICO, which will receive kefir and distribute to people
MyToken
. This article may be out of date, but you can always see how OpenZeppelin suggests that you create contracts
in their repository . This is how
MyToken.sol
will look
MyToken.sol
:
pragma solidity ^0.4.23;
Nice - you have a smart contract of your own token (just change the names in the constants)! You can see that there is inheritance from
MintableToken
- but everything is as simple as possible. This is a token that can be released (from the English “Mint” - minted), and only the owner has the right to release it, since the
MintableToken
is also inherited from
Ownable
. Also,
MintableToken
is also inherited from the ERC20 classes of tokens written by OpenZeppelin, in which the ERC20 interface is implemented:
contract ERC20Basic { function totalSupply() public view returns (uint256); function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); }
Yeah, here's the whole ERC20 interface. Complicated? I do not think. It gives an opportunity to see how many tokens were issued, check the address balance and transfer tokens to another address by spitting a translation event for kefir light clients into the network. And all this you get a
MyToken.sol
in your
MyToken.sol
thanks to the work of OpenZeppelin - they are great.
And now let's move on to the main part of our ICO - we need to take yogurt and distribute
MyToken
! This is how your
MyCrowdsale.sol
will look like:
pragma solidity ^0.4.23;
So, so, so, what is here with us? What, guys, smart contracts? Our public sale of tokens inherits three of the most popular properties: it has a hard cap, more than which it will not work; soft cap, without having collected which ethers come back; time to start and end sales of tokens. In fact, what else is needed for happiness?
Programmers notice how the constructors of the classes of multiple inheritance are lined up and get arguments from the main designer of
MyCrowdsale
. Also, we check that our hardkep is higher than softkep - ales gut! Also, do not be intimidated by the parameters cloud in the
MyCrowdsale
constructor - we will pass them on at the stage of contract deployment in truffle.
That's all - you have ready-made contracts of your own ERC20 token and even an ICO smart contract that is customized according to your wishes and distributes your tokens for kefir. Also, it is supported by all ERC20 wallets - lyapota! We turn to the manual tests and Deploy.
Migrations
As I said earlier, we will be testing on three blockchain networks consistently, but the testing process will always be the same. Let's start with
testrpc
, then move on to
geth --testnet
and on to
geth
. Sow, we just wrote the code, let's try to compile it. In the project folder, type:
truffle compile
If everything compiles without problems, then you will have a daddy
build
, which will contain krakozyabra truffle, so that he could put the byte code of your smart contracts into the blockchain. Before deploying smart contracts, we need to tell the truffle what to do. The smart contracts contract in a truffle is called migration - well, well, we will stick to this terminology. Go to
migrations/1_initial_migration.js
and change it in the following way:
const token = artifacts.require("../contracts/MyToken.sol"); const crowdsale = artifacts.require("../contracts/MyCrowdsale.sol"); module.exports = function(deployer, network, accounts) { const openingTime = 1514764800;
This is the file that truffles will use to deploy contracts. So what are we doing with this? First, we requested the compiled
MyToken
and
MyCrowdsale
. After, we set constants with all the arguments of our ICO - set the start and end time; how many tokens people will receive for 1 wei kefir (0.000000000000000001 eth = 1 wei; setting
decimals
indicates how many orders wei need to get 1 of your new token); a purse where kefirs received on sale will come; hard-cap and soft-cap. Note that the
openingTime
should always be after the time of the current block in the blockchain - otherwise your smart contract will not fail due to checking the conditions in
TimedCrowdsale
. I attacked this rake, but failed transactions can not be debugged at all. Change these constants on your own.
The next step is to deploy smart contracts. There is nothing interesting here: we have a
deployer
object that deploit smart contract artifacts and passes arguments there. Notice that MyToken is
MyToken
first, and only then
MyCrowdsale
- and the argument of the first is passed to the second.
Then the most interesting thing is what they do not write about either in the documentation or in books. When you create a
MyToken
from a wallet, this wallet becomes the owner of
MyToken
in the
Ownable
superclass - the same happens with
MyCrowdsale
. If you dig deep into
MintableToken
, you can see that only the
Owner
can mint coins! And who is the owner of
MyToken
? That's right: the address that zadloplo it. And who will send requests for minting coins? That's right:
MyCrowdsale
smart contract. Let me remind you that the address that created
MyToken
and the address for
MyCrowdsale
are two different addresses.
Therefore, we add a non-Orthodox third step of deployment, where the address that has contracted contracts (
web3.eth.accounts[0]
) calls the
transferOwnership
function on the
MyToken
contract
MyToken
that
MyCrowdsale
owns the
MyToken
and can mint coins. And
MyCrowdsale
is still under the control of
web3.eth.accounts[0]
- so everything is a bundle.
A note about web3.eth.accounts[0]
: when deploying a smart contract, make sure that geth or testrpc have the correct wallet in web3.eth.accounts[0]
- do not lose the private key to it, even though it doesn’t hurt you, but suddenly the owner will need to do something later, but the key is gone?
In testrpc
, as a rule, accounts are created immediately upon startup and they are immediately unlocked; However, it’s worth creating an account on personal.newAccount()
on the test and real blockchain of the air through the Faucet on the test blockchain or real kefir on the real blockchain. Do not lose your password and private keys.
Also, you can add an already existing wallet to your accounts by calling web3.personal.importRawKey('pvt_key', 'password')
, but you need to call geth
with the additional parameter --rpcapi="db,eth,net,web3,personal,web3"
. I think you figure it out.
Testing and Deploy
Yes, the contracts are ready, the migrations are written, it remains only to enclose and check. Both
geth
(test and real) and
testrpc
controlled the same way through the
truffle console
- so I’ll describe the test method for
testrpc
and just tell you how to enable
geth
after. And so, we launch a test local kefir blockchain:
testrpc
Um ... that's it. You have a local simulation of the kefir blockchain.
And in order to plug into the test blockchain of ether, you will do geth --testnet --rpc
instead of this command. And in order to block the real blockchain of the ether, you simply geth --rpc
. The --rpc
flag --rpc
needed so that the truffle can connect. The following steps of deployment and test are more or less the same for all three types of blockchain. The only thing is that after you start the test or real blockchain through geth
, it will start synchronizing the blocks - and this can take up to 4-5 hours on a good Internet connection. A remark about this one was at the very beginning of the article. Before deploying smart contracts, I recommend waiting for full synchronization. Also, the blockchain weighs around 60-100 gigabytes, so prepare disk space for this.
Also also, make sure that web3.eth.accounts[0]
unlocked. Usually, you can type in the testrpc
console, which opens immediately, or in a separate Terminal window in the console, which opens via geth console
: eth.unlockAccount(eth.accounts[0], ", ", 24*3600)
- this will unlock your account, which should create a smart contract
Now we open a new Terminal window (
testrpc
not closed - it should work) and write in the project folder:
truffle migrate --reset
This magic command will compile a smart contract (that is, do not need to write
truffle compile
each time) and deposit it on the micro-server of the blockchain found locally open. It should be noted that if
testrpc
does it instantly, then the test and real blockchains will include the transaction in the following blocks much longer. After that, you should spit out something similar in the console:
Using network 'development'. Running migration: 1_initial_migration.js Running step... Replacing MyToken... ... 0x86a7090b0a279f8befc95b38fa8bee6918df30928dda0a3c48416454e2082b65 MyToken: 0x2dc35f255e56f06bd2935f5a49a0033548d85477 Replacing MyCrowdsale... ... 0xf0aab5d550f363478ac426dc2aff570302a576282c6c2c4e91205a7a3dea5d72 MyCrowdsale: 0xaac611907f12d5ebe89648d6459c1c81eca78151 ... 0x459303aa0b79be2dc2c8041dd48493f2d0e109fac19588f50c0ac664f34c7e30 Saving artifacts...
I think you already understood that the console gave you smart contract
MyToken
and
MyCrowdsale
. Everything! The smart contract is secured on the blockchain, whose micro-server is open. It remains only to verify that the tokens are indeed distributed to users who send kefir to the smart contract
MyCrowdsale
. We register the following in the Terminal to enter the truffle console:
truffle console
We register the following in the now truffle (no comment only):
testrpc
, , — , , . ?
MyToken
:
That's all!
testrpc
,
geth --testnet
,
geth
. ICO! . , OpenZeppelin, , .
truffle
— . , , - — . -, , .
Conclusion
, ! , - , . , , ICO — $75,000 -, -, , - 25 .
-! Any questions? — .
Bonus
, , ? ,
rate
OpenZeppelin, - ? -
getTokenAmount
:
function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) { if (block.timestamp < 1533081600) {
, — , . - — !
