How It’s Made: Crowdsale contract
More and more ICO contracts are created on MyWish platform. Therefore, today we want to talk about how the template for the ICO contract has been developed.
The ICO (Crowdsale) template is designed to create contracts for having crowdsales with customizable parameters. The ICO settings are substituted into the contract’s template configuration file. Afterwards, when the preprocessing of the template takes place, a ready Crowdsale contract is generated with tests. Then the contract is compiled and deployed in the local blockchain, before it is automatically tested. The scheme of contract generation from the template:
Customizable contract’s parameters
- start time — start time of ICO;
- end time — end time of ICO;
- soft cap — the amount of ETH the crowdsale must receive to be considered successful;
- hard cap — the maximum amount of ETH that the crowdsale can get;
- rate — a number of tokens produced per 1 ETH;
- name — token name (example, MyWish token);
- symbol — short name of the token (example, WISH);
- decimals — numbers of symbol after the comma;
- cold wallet — an address of the wallet to which the funds raised from crowdsale will be transferred;
- auto finalize — will the crowdsale contract automatically terminate?;
- pause tokens — a suspension of the possibility of transferring tokens before the end of the sale;
- bonus tokens — will the crowdsale contract give bonuses for the period, the purchase amount and the currently collected ETH number;
- premint count — a number of addresses to which bonuses must be credited before starting ICO;
- premint addresses — a list of the addresses;
- premint amounts — a number of tokens to be credited to addresses;
- premint count, addresses, amounts, freezes — the addresses, the number of tokens that will be credited to these addresses and frozen from deployment until the specified time;
- wei raised boundaries, time boundaries, wei raised and time millirates — the limits of the amount of collected funds, time points and bonus courses that operate within the specified limits;
- wei amount boundaries, wei amount millirates — the limits of the amounts of funds that users are willing to spend on the purchase of tokens and bonus courses that operate within specified limits.
Description of the Crowdsale contract
- Buying tokens;
- Suspending the ability to send tokens;
- Completion of ICO after “end time”;
- Transfer of a contract’s ownership to another person;
- Request a refund. If the contract has not collected the amount specified as the minimum amount (soft cap) of which the ICO is considered to be successful, it is possible with a refund for investors.
- Minting of tokens and their freezing until the specified period;
- Bonus accrual.
About freezing funds
There is a possibility of accrual tokens and “freezing” them up until a specified date. The user will not be able to pick them up before the specified time.
More about calculating bonuses
Bonuses (bonus tokens) are additional tokens, accrued to the buyer in excess of those purchased at the current exchange rate. Bonus tokens are generated based on a rate that varies depending on three criteria:
- The period in which the purchase of the tokens was made. For example, there can be one course for the first week of the crowdsale, one for the second week and one for the third week.
- Amount of collected funds. For example, one-third of the necessary funds are collected — one course, more funds collected — another course;
- A number of funds that the buyer is willing to spend. For example:
- ≥10 eth — +20%
- ≥ 5 eth — +10%
- ≥ 1 eth — +5%
The first two criteria are related. Only one bonus acts on two criteria. So, if the conditions for both criteria are met, then the bonus will be the same as if only one condition was satisfied.
Tools used for development
- Solidity as a language for the development of smart contracts;
- Truffle — Ethereum framework. It is used to compile and test contracts.Contains solc-js for compiling contracts, mocha and chai libraries for testing smart contracts;
- ganache-cli –npm-pack. It is a local blockchain where contracts are tested;
- c-preprocessor — npm-pack used to substitute ICO parameter values in a contract template, to connect the selected functions and generate the original contract file from the template;
- zeppelin-solidity — npm-pack. It contains the implementation of ERC20, MintableToken, BurnableToken tokens and Crowdsale contracts by CappedCrowdsale, RefundableCrowdsale, FinalizableCrowdsale.
General structure of the Crowdsale contract
The basis is two contracts. It is a contract for the crowdsale (TemplateCrowdsale) and a token contract (MainToken). These two contracts are inherited from other contracts in which parts of the functionality are implemented. For example, BonusableToken implements accruing bonus tokens when purchasing. The structure of contract inheritance is shown in the diagram.
Blue color marks contracts from the OpenZeppelin library. These contracts realize the bulk of the functionality, starting from the ERC20 standard to the Refundable Crowdsale, which is responsible for keeping funds until the end of the crowdsale and the possibility of a refund if the necessary amount is not completed by the end of the crowdsale.
Green color indicates contracts of additional functionality that you need to implement yourself.
We connect the OpenZeppelin library to ensure compliance with standards and to increase the usability of development. Using inheritance, we collect the contract of the crowdsale and the token with the standard functionality we need from the library contracts.
Let’s start with the contract token:
- First, we inherit the contract from StandardToken, which implements the methods defined by the ERC20 standard;
- Next, we inherit the contract from MintableToken and BurnableToken to provide the possibility of “minting” and “burning” the tokens;
- We inherited from the contract Pausable. This is necessary to provide the possibility of suspending the token contract functions;
Next we inherit the contract crowdsale from:
- FInalizable Crowdsale, which in turn inherits Crowdsale. This ensures the launch and completion of ICO on the dates indicated, the purchase of tokens with the specified rate and the transfer of funds to the cold wallet;
- CappedCrowdsale. This allows you to limit the maximum number of funds that can be obtained as a result of ICO;
- RefundableCrowdsale. This contract adds a property — a minimum amount, under which ICO will be considered successful. Also, this contract does not immediately send funds to the cold wallet (as the standard Crowdsale contract does), it stores them in a special storage. In order to ensure, in the case of an ICO failure, the possibility of the refund on request. This contract is not connected at the preprocessing stage before compilation if the minimum amount mentioned above is zero.
This concludes with the inheritance from the OpenZeppelin library contracts. Next, we will describe the development of functions that are not present in the library.
The following tasks were accomplished in the implementation of the freezing of funds
- storing addresses of frozen funds in a token contract
- adding several release dates to one address
- a release of funds with algorithmic complexity O (1)
Intermediate addresses are created for storing frozen funds, they are based on the user’s address and the release date — address(keccak(userAddress, releaseTimestamp)). It is to this address that tokens are credited without violating the original logic of the token contract.
A list of such addresses at the user’s address is stored in the roots dictionary, where the key is the user’s address, and the value is the release date. Thus, you can get a balance of frozen funds, knowing the address of the user, and free up funds if the date has already come.
To store frozen funds for several dates for one address, another dictionary is used — chains. This collection stores chains from the release dates in the values and the key is the freeze address.
The insertion is done in such a way that the dates go strictly in ascending order. On the one hand, this increases the amount of gas needed to add new freezes, but allows you to release tokens in the amount of gas not depending on the number of funds frozen at the address for different dates.
Calculation of the bonus tokens
To implement this function, we create a contract that will override the standard method of purchasing Crowdsale contract tokens. This contract will be preprocessed if the constant responsible for this function in the preprocessor configuration file is activated. We replace in the method of buying tokens the current rate for a new one, taking into account bonuses. The theoretical part of how bonuses are formed was described earlier. In practice, this is realized due to the arrays of the values of the moments of time, the sums of the ethers and the bonus courses of the aether to the tokens.
Creating contract templates
For the template, as mentioned before, the c-preprocessor from npm is used. It allows you to enable/exclude code blocks and define constants — ICO parameters, depending on the conditions defined in the C-preprocessor-config.json configuration file. The preprocessor processes both contract templates and tests for these contracts.
We use “truffle” to develop contracts. It is also used for tests. Truffle allows you to write tests on solidity and js both, using the chai and mocha test libraries. It was decided to use the second option. As a test environment, the local blockchain provided by ganache-cli is used.
Tests, like the original contract files, are generated by the preprocessor from the template based on the ICO parameters received from the configuration file.
Your comments and feedback are very welcome.