How it’s made: EOS Crowdsale
The Crowdsale EOS contract template is created by analogy with the same contract on Ethereum. As far as possible, of course, taking into account the peculiarities of the different nature of the contracts. The EOS contract was developed using other technologies — another blockchain, another programming language (C++ vs. Solidity in Ethereum).
EOSIO repositories already have source codes for various contracts. Including for a token contract (eosio.token). Such contract fits the needs of a Сrowdsale contract, but requires minor modifications.
It should be noted that the organization of a standard token contract in EOS is very different from that in Ethereum. In Ethereum, 1 contract = 1 token, in EOS 1 contract = ∞ tokens. In EOS, one token contract is created, and then run create action to create a token. The data on the created token is recorded in the contract. Thus, you can create multiple tokens with the same contract (but you cannot create tokens with the same token symbol).
For the needs of MyWish, one token contract is placed on the network and it is used to create new tokens (when you create a token separately, or as part of a crowdsale).
The procedure for creating a contract
Consider what happens when you create a contract for eos.mywish.io, click Launch, and the browser sends a request to the server:
- the server generates a full-fledged contract from the template, substituting the values of the parameters entered by the user into the contract configuration file,
- starts the compilation of the contract with this configuration file, generating a .wasm file containing the WebAssembly contract bytecode to be executed by the EOS virtual machine,
- runs tests that run with the actual parameters specified in the configuration file,
- sends a create action to the token contract to create a new token, which will be owned by the Crowdsale contract,
- creates an account for the Crowdsale contract and sends two actions to the network (setcode and setabi) to create a contract on the account you just created,
- performs init action to initialize the state and pre-mint tokens before the start of the crowdsale.
- transfers “account access rights” of the contract to the user, in order to avoid the possibility of changing the code or withdrawing money until the fundraising is completed.
Standardized contract parameters
To substitute template parameters into a contract, you need to create a config.h file, and add the contract parameters to it via ‘#define PARAM_NAME PARAM_VALUE’ and put the file in the directory with the source code of the crowdsale contract. At the compilation stage, the preprocessor performs parameter substitution in the contract code from the configuration file.
For convenient formation of such a file, a bash script was developed. It must be run by passing the following parameters:
- issuer -the crowdsale contract account’s owner,
- symbol — the symbol of the token being issued,
- decimals — precision of the issued token,
- whitelist — whether whitelist is enabled,
- transferable — whether users are allowed to make transfers of crowdsale-issued tokens before the crowdsale is completed,
- rate and ratedenom is the numerator and denominator of the rate. The value of the rate is divided into two parameters, to enable the setting of fractional values of the rate, for example, 0.5 token per 1 EOS (rate = 1, ratedenom = 2),
- mincontrib is the minimum EOS amount accepted by the Crowdsale contract in a single action. This restriction is necessary so that users do not disrupt a contract or network from transferring small amounts to a crowdsale account,
- maxcontrib is the maximum EOS amount accepted by the Crowdsale contract in a single action,
- softcap — the amount of fees, which is enough to implement the minimum working version of the product (MVP). If the contract was completed on time and did not sell soft cap tokens, then the contract allows you to make a refund — to return the money to investors, since Crowdsale failed,
- hardcap is the maximum number of tokens that Crowdsale can sell. The value must be at least softcap,
- contract — a token contract account whose tokens are distributed in this crowdsale
- mint is a value that determines to which accounts how many tokens to issue before the start of the crowdsale.
Description of the possibilities and the internal structure of the contract
The EOS Crowdsale contract provides the standard Crowdsale features. The first is the purchase of tokens for the “native” currency of the network — EOS. When sending an EOS to the Crowdsale account of the contract, the sender’s account must issue new tokens at a predetermined rate. To do this, the following conditions must also be met: the user is in the whitelist, the crowdsale is not yet over, the hardcap is not built, etc. To do this, you need to override the standard apply function, so that it “catches” not only the crowdsale actions, but also the transfer action, which is directed to the eosio.token contract. In this action, various parameters are validated (user’s presence in the list, hardcap achievement, time frame, etc.), the Crowdsale state records the total number of EOS collected and tokens issued, and an internal token call to issue the new tokens to the investor.
Our EOS Crowdsale contract allows you to issue a predetermined number of tokens to specified accounts before the start of the crowdsale. These tokens will not count for a hardcap in the Crowdsale contract. To implement this feature in the contract there is the init action. The action initializes the contract state, writes the start and end of the crowdsale of the action parameters to the timestamp state and performs the token release cycle. The method is called from the MyWish account once the contract has only been deployed.
When creating a contract, it is possible to enable the whitelist function. In this case, when purchasing tokens, it will be checked whether the user is in the whitelist of the contract. If the user is not in whitelist, the transaction will fail. All such checks are provided by the built-in eosio_assert function, which allows to display an error message and roll back the transaction if the check fails. With the whitelist function, several additional functions are added to add and remove users from whitelist. Whitelist can be useful when using KYC — investors who have undergone this procedure are added to whitelist.
When creating a contract, the future owner of the contract can indicate whether the tokens will be transferable as soon as they are purchased, or become so only after the completion of the crowdsale and the finalize function call. To implement such a function, it was necessary to modify the token contract, which was mentioned above. In the token contract, the createlocked function is added, similar to the create function. It also creates a token, but with blocking of their transfer, until the issuer of the token performs the unlock function. The sequence is as follows: the contract creator passes a transferable value equal to false, the MyWish backend creates a token through the createlocked function instead of create. The token issuer becomes a Crowdsale contract, which means that only it can call the unlock function. It calls it at the moment the finalize function is called.
The EOS Crowdsale contract allows the contract owner to move the start and end dates of the crowdsale if these dates have not yet arrived. This may be necessary if the creator of the crowdsale set the start too late and does not want to wait any longer. Or vice versa, a couple of hours remain before the start of the crowdsale, and nothing is yet ready to hold, except for the contract itself. In this case, the start date can be moved to a later time. In the same way, you can change the time of the end of the collection. For this, the contract has the functions setstart and setfinish.
When the crowdsale is completed in time or the hardcap is reached, any account can call the function finalize (before this the function will be unavailable and the transaction will not be executed). If the softcap is collected and the end time has come, or if hardcap is simply reached, then when calling finalize, the tokens will be unlocked by an internal unlock call to the token contract. If the tokens were not initially blocked, then you do not need to call finalize. In order for the owner to pick up his tokens after the crowdsale is completed, he needs to execute the withdraw action without parameters.
In case the crowdsale failed (did not collect the softcap), investors can return their EOS, which they sent to Crowdsale. To do this, they need to perform a refund action without parameters.
The contract provides two restrictions on the amount of EOS in one action, sent to the Crowdsale contract. This restriction on the minimum investment and maximum. With a minimum investment limit, there is one caveat. Until a hardcap can be reached, the amount may remain less than the minimum investment amount, so that no one will be able to eventually reach the hardcap, and you will have to wait for the crowdsale end date or move the end date. We have implemented such a logic in a contract that a hardcap will be considered as achieved if less than the amount of the minimum investment remains before it is reached. In this case, you can perform all the actions that are supposed to perform after the end of CS — finalize, withdraw / refund.
The reliability of the contract for investors
Unlike Ethereum, EOS blockchain allows you to change the contract code at any time by those who created it (who owns the keys for this account). In addition, any funds lying on the account of the contract can be withdrawn unconditionally. That is, the logic of the contract is not involved in any way. In other words, you can not write code that prohibits the withdrawal of funds for some conditions. The result is that such restrictions as soft cap do not make sense. Yes, and any other restrictions do not make sense if the contract code can be replaced at any time by the organizer of the sale.
To solve this problem, MyWish team offered a solution that will allow you to completely block access to the contract account to everyone who previously had this access (owned keys and their copies). This is done through the EOS privilege system, which allows you to grant access not to a key, but to another account. And if this account is the same as it provides access, then it turns out that access “loops” on itself. This leads to the impossibility of either privilege changes or contract account management. At the same time, all the functionality of the contact is explicitly programmed in the code. For example, you can realize the possibility of transferring funds from a contract to call a particular function (in our case finalize). In the finalize function, it is checked that all the conditions of the contract are fulfilled (for example, a soft cap is reached) and the funds are transferred to the administrator account specified when compiling the code. Code replacement functions are also disabled.
As a result, with such “looping” of privileges, the contract becomes itself, without external control, and is completely analogous to the contracts of the Ethereum network in this sense.
Tokenika is developing an analogue of Truffle for EOS — eosfactory, which we use as a framework for unit-testing smart contracts for EOS, including the Crowdsale contract. The framework provides all the capabilities for managing accounts and contracts on EOS in a private network, which allows you to fully test the contract for various errors and vulnerabilities.
To test the contract unit-tests were written in Python, using eosfactory. Tests fully cover the entire functionality of the contract.
To cover the test code associated with checking the current time, our contract is not suitable and requires little improvement — the ability to specify the current time in the contract, as eosfactory and nodeos rpc do not allow moving the current time of the blockchain (as it is in ganache). To provide this opportunity, the DEBUG flag is added to the contract configuration. When compiling a contract code with this flag, the set time function appears in the contract, setting a new fake “current” time and instead of the real current blockchain time, the information in the contract is taken from the state, from the value that was set by the settime function. There is no this function in the code on the production, nothing to worry about.
In addition, manual testing of the contract was conducted in a “combat” mode — in the test and main EOS networks on all common scenarios, including hacking scripts. Careful testing with autotests and manual testing ensures that the contract is free of errors and vulnerabilities.
The following tools were used to develop the contract:
- C ++ is the programming language in which the contract for the EOS network is written,
- eosiocpp — C ++ code compiler to wasm, readable by the EOS virtual machine,
- cleos is a client for interacting with the EOS network,
- Jungle Testnet — EOS test network to test development results,
- python is the language in which unit-tests for a smart contract are written,
- eosfactory is a framework providing an API for interacting with the EOS private network and the ability to test contracts.
In addition to compiling cpp to wasm, eosiocpp provides the ability to generate abi. But this tool is very weak and not useful in our case — the whole abi for the contract is written manually.
A year ago, if you wanted to create a smart contract, you understood that you need to use Ethereum for these purposes. There was one blockchain supporting smart contracts, people didn’t know others or these didn’t exist.
Now in this regard, technology has stepped further, and new blockchains have appeared, in which it is possible to create smart contracts. The best choice now will be EOS, and there are many reasons for this. their high speed of transactions, its free of charge for users, human-readable addresses and much more. You can add to this the fact that smart contracts are available in EOS more than in Ethereum.
But to create a smart contract, in addition to understanding the logic of the future contract, programming skills and an understanding of the principles of the blockchain work are needed. These are not simple skills, but you can certainly acquire them. And you can save your power and money and use the tool for creating smart contracts on MyWish Platform. It allows you to create the most popular smart contracts (for example, Token or the same Crowdsale) and customize them to your own needs.