📜 ⬆️ ⬇️

Dive into ICO


In the article we will discuss the technical aspects of preparing and conducting an ICO. This is a continuation of my colleague's article “ Technical Features of an ICO. Start ”, and here we will talk more about some technical issues related to Ethereum smart contracts.


Technical project development


Before developing a smart contract, it would be good to make a technical project. This is a schematic diagram of your contract system, which, answering key technical questions, shows the feasibility of the project's economy and your ICO scenario.


What is usually included in the technical project? It does not have to be a thick formal document, four or five pages with key points and a couple of diagrams are enough. And on these pages for a start, consider the mechanics of ownership. The simplest option: one token owner is being implemented, ICO - in a row. Usually they do. A more complicated option is when multi-signature is in progress. It is possible to take a reliable wallet contract as a basis, extract a multi-signature from there and apply it not only to the wallet and to store the broadcast, but also to manage the ICO itself and the token. Here your imagination is not limited, you can mathematically easily implement a variety of scenarios.


It is good when ICO is decomposed, that is, it is not one contract that counts the course, issues tokens and receives the broadcast, but a system of smart contracts when each contract does its own thing. That is, you accept the ether at the ICO stage, which, depending on its logic, understands how many tokens you need to issue. He gives the corresponding command to the token contract, the owner of the token, and at the same time he does not keep the broadcast in himself, but transfers him to a special repository, which is also a contract.



I do not see any crime in storing the broadcast in the contract. On the contrary, it is even more transparent, since it is clear what the contract is doing. You can easily see that the broadcast is stored there until the end of the ICO, and if you don’t raise money, then it is guaranteed to return everything to investors, and even the owners cannot prevent it.


On the other hand, this complication is not free. We can say that this creates additional problems at the deployment stage. And yes, these connections and challenges are an extra opportunity to introduce vulnerabilities. Watch the rights very carefully.


There is a standard for the token, it is called ERC20 , it defines several methods that need to be implemented in the contract. If your token implements this standard, then it can be displayed on many exchanges. In addition, ERC20 support and other wallets besides Ethereum Wallet. Thus, simply having realized the necessary functions, you receive already ready infrastructure for work with your token. Moreover, there are libraries that lay the basis for the token and immediately implement the ERC20. Implementing a standard is not necessary if you have some kind of purely internal resource token and if it is not supposed that users will exchange it with each other. If they come to the amusement park with this token and buy their ticket for the rides, then they probably don’t need a listing on the stock exchange.


In addition, the contract can lay a pause in the event of problems or strange activity. For example, when the air pours, and tokens are not issued. Then you need to suspend the ICO, sort it out and make a decision. It is necessary to lay this state in the technical project. You can also consider issuing a token in a technical project. It is important to think about this before the ICO, because you need to understand how it will be compatible with the token, if you can then do additional emissions.



Be sure to think about this scheme - this is the state graph of your ICO. It is a finite automaton, i.e. the states in which ICO can be. This is the graph, it describes the state and says, under what conditions is the transition from one to another. Your ICO should not just change the state from raising money to “Successfully collected. Let's get them out. ” You need to understand what the state transitions in the ICO are. Investors should also understand this, because they see that everything is fair. And this should be understood and clearly programmed by developers. For this, Solidity has all the means, there are so-called enumerations, with the help of which the state is described. In addition, I recommend making transitions between states controlled by the code, so that there are no invalid transitions.


Any function that is available outside the contract, you can set the state with the help of the so-called Solidity modifiers. So, you can only invest in a state of ICO, but not a pause. Conversely, the owners can only withdraw money if the ICO is successfully completed.


Smart Contract Development


When the technical project is ready, the customer is happy, and the developer understands what needs to be done, we proceed to the development. Ethereum has a virtual machine (Ethereum Virtual Machine, EVM), it performs these very programs of contracts, and the contract is the so-called byte code that is executed by the virtual machine. In this regard, it is possible to develop contracts in several languages. The Solidity language was created specifically for the task of developing smart contracts from scratch, it has a C-like syntax. Besides him, there are other languages: there are similar to JavaScript, there is a language similar to Python.


My intuitive opinion is that it is better to choose Solidity, even for neurophysiological reasons. When a developer uses a language that is similar to Python, he nonetheless writes a Ethereum smart contract. But at the same time, semantics and patterns typical of Python are beginning to emerge in his head, and they are not working clearly when developing under Blockchain.


Talk about Solidity can be a long time, so you need benchmarks. First, it greatly facilitates the development of the Truffle framework. It helps to test the contract, deploy it to the main, test, local blockchains. And even allows you to do this incrementally, i.e., to supplement your contract system with new contracts. In this case, the framework will remember all the old ones and will not re-lay them again.


Why do I urge to reuse libraries? The community is quite young, there is little code, but all the principles obtained in the development of software over the last 30-40 years remain in force in the case of Blockchain. And they tell us that if there is a code that is reasonably well tested, which in itself requires reuse in a wide range of projects, then it is worth taking it and not reinventing the wheel.


First of all, I ’ll note the OpenZeppelin / zeppelin-solidity library . It is on the verge of a de facto standard in developing smart contracts. There are not so many contracts and libraries, they are relatively small. But they cover frequent cases, give you many things out of the box: contract ownership, some tokens, tokens that can be created, burned, some typical ICOs, something related to security, for example, protection against reentrancy attacks.


Another library is SafeMath . I recommend using it, even if you do not want to connect Zeppelin-solidity. It is small, just a few odnostrochnnikov, it can be copied directly into a contract. She insures you against overflows. This is a very relevant and serious problem. For example, when you deal with unsigned numbers in Solidity and if you overlook a five from the three, the contract continues to work, but as a result, a huge number is shown to you. This happened due to overflow. If you use the SafeMath library, an error occurs, that is, the transaction ends with an error, and the state does not change.


There are many recommendations. I mentioned about the state machine, it is desirable to implement it: set the state and modifier. In addition, transitions from one state to another can be realized in time. At the same time, a modifier is added to each function, which says: "I will look at the time, and if now the beginning of the ICO, then I will change the state to ICO."


There are patterns, typical patterns that are beginning to form in the world of Solidity, in the world of smart contracts. For example, you heard that there are many patterns in software development, especially some kind of corporate systems. Here, for example, the well-known template withdrawal pattern can be attributed to this, when the user withdraws the funds owed to him himself, and not when you try to send them to him. For example, if ICO fails, when it is required to return money to investors, if you try to do it yourself, then most likely you will fail for a number of reasons. It is also fraught with security problems. If you issue a refund as a withdrawal by users with appropriate checks, it becomes much easier.


I mentioned pause mode. Infrequently used in the ICO, which we recently see, but it is a very useful mechanism. Understandably, he does not insure against 100% of problem situations (even despite the pause, you can steal the air), but significantly reduces the possibility of attack.


On the replacement of contracts I must say that it is not necessary to go to the end and make a completely dynamic contract, the code of which can be arbitrarily replaced with, for example, calling delegatecall , etc. It is enough that this piece, the ICO stage, which contains a nontrivial twisted logic, could be replaced if a problem is detected. This is possible due to the fact that the tokens and money you have separately, the money remains unchanged. In principle, you can replace this piece and link it with two already existing parts completely transparent. At the same time there are features. If ICO performs initialization, for example a token, then take measures so that when replacing the initialization does not start a second time. Your ICO will have a new address as a result, this is a new contract. The possibility of replacement will be visible in the contract code, and you need to understand that this is a kind of compromise. On the one hand, I want everything to be absolutely unchangeable (this increases the credibility of you), on the other hand, it would be nice to be safe. As a compromise, you can write conditions in the code that are completely unchangeable. For example, to register in the air repository that the minimum threshold for raising funds is unchanged in principle. Then investors will know that it will not happen that they collected 100 thousand, but wanted to collect 100 million, but they still took what they had.


If possible, you should check for reasonableness the parameters that the methods of your contract receive as input. Suppose if your token supports emission and in its parameters you specify the number of tokens that need to be generated, then you can check this number, for example, looking at whether it is more than there are tokens now. This can hedge you when there is a typo in the manually entered parameter. Or, for example, if the emission is initiated by the external infrastructure, when a failure occurs in it - it can emit billions of billions of tokens to you.


Three more links to GitHub:



Here is a set of repositories with some solutions. These are experimental things, try them very carefully, and usually it says there: “This is an alpha version, do not keep more than $ 20 on it”, but it is clear that all good things are born from experiments. It may be better to take something ready as the basis than to write everything yourself from scratch.


What IDE to take for solidity-development? I used to work actively on the command line, I run Truffle from the command line, and in fact there are only three commands required: test , compile , migrate . As for the development environment, I chose PyCharm, there is a free plugin for Solidity, and this is not a bad thing. The development environment helps you a lot, and PyCharm / Idea is a good IDE, I would even say that it is twice as good as its competitors. It will allow you to highlight the variable in the contract, all its use, and it helps a lot when we do an audit, when you literally know the unknown code in a few hours with the help of development environment hints.


A little about the cost of smart contracts. The cost will be only the calculations that change the Blockchain, that is, they participate in the transaction. There are functions with view or pure modifiers, they do not modify the state, they can be used without sending data to Blockchain. If we had developed a function that is called locally, it would not cost anything at all.


Any code that executes really in Blockchain and modifies the state, saves or sends data, is worth the gas. It is easy to put a mental experiment on this topic, can I write code that will, let's say, work for a very long time and save a lot of things. If at the same time members of the Ethereum network have to repeat it, then your code will work on millions of computers around the world. Hence, the developers of Ethereum are preoccupied in any way, so that you pay for it, and quite expensive at current rates. Another thing is that different calculations and lines have different cost. The price of simple arithmetic is 3-5 gas units, and the state modification will cost 20 thousand gas units. Why? Because the blockchain has changed, it has become more by 32 bytes because of you, these bytes have fallen on millions of computers around the world.


Smart Contract Testing


Testing is a must, a 50-year history of software tells us. And it’s strange not to see tests in the repositories of projects that come to the ICO. Maybe they are done, written, but just not laid out. But in any case, if you are doing tests, why not put them? So you show investors that everything is well tested here. This is not a guarantee that there are no errors, but it helps to avoid many problems.


Tests are written directly in Solidity or in JavaScript. In any case, with Truffle, you can run all the tests at once and get a summary report. At the very bottom you should be told: all the tests have passed, there are no failures. You show both to ICO customers, and users, and investors that you have tested the most important aspects of your ICO: token, crowdsale itself, money storage, even bonuses. Bonuses are an important thing. It is very important for investors to know that they will receive their bonuses.



There are unit tests - they check small isolated code fragments, and it is convenient to write such tests to Solidity.


 function testValidationOfDecrease() { Bonuses b = new Bonuses(); b.add(1000000000, 50); b.add(1000000010, 60); b.validate(false); assertInvalid(b, true); b = new Bonuses(); b.add(1000, 60); b.add(1000000000, 50); b.add(1000000010, 60); b.add(1000000020, 0); b.validate(false); assertInvalid(b, true); } 

The code is Solidity, it simply creates a contract, sends data to it and checks that the contract is working as expected. There are tests written in javascript. Usually more complex scenarios are checked here, when several contracts are involved in the interaction. Suppose we create a set of contracts that were mentioned earlier. Then several contracts are involved, there may also be several users. We even call them “investor such and such”, “investor such and such”. There are still owners, there are users without any rights at all. And here you can program the complex interaction and check that tokens are issued correctly during the interactions. Or check that when hard cap is reached, the investor will receive his change. These tests are called integration tests.


Any calls to Blockchain from JavaScript are asynchronous - this adds extra code, all sorts of promises, etc., so I suggest using Babel, a kind of JavaScript compiler that will hide all asynchronous behind the await , async construction.


 it("test max cap", async function() { const role = getRoles(); const [crowdsale, token, funds] = await instantiate(); // +5% await crowdsale.setTime(1511913601, {from: role.owner1}); await crowdsale.sendTransaction({from: role.investor1, value: web3.toWei(20, 'finney')}); await assertBalances(crowdsale, token, funds, web3.toWei(20, 'finney')); const investor3initial = await web3.eth.getBalance(role.investor3); await crowdsale.sendTransaction({from: role.investor3, value: web3.toWei(1000, 'finney'), gasPrice: 0}); const investor3spent = investor3initial.sub(await web3.eth.getBalance(role.investor3)); assertBigNumberEqual(investor3spent, web3.toWei(378, 'finney'), 'change has to be sent'); assert.equal(await crowdsale.m_state(), 4); await assertBalances(crowdsale, token, funds, web3.toWei(398, 'finney')); assertBigNumberEqual(await token.balanceOf(role.investor1), STQ(2100)); assertBigNumberEqual(await token.balanceOf(role.investor3), STQ(39690)); await checkNoTransfers(crowdsale, token, funds); await checkNotInvesting(crowdsale, token, funds); await checkNotWithdrawing(crowdsale, token, funds); await checkNotSendingEther(crowdsale, token, funds); await crowdsale.distributeBonuses(10, {from: role.nobody}); assertBigNumberEqual(await token.balanceOf(role.investor1), STQ(2600)); assertBigNumberEqual(await token.balanceOf(role.investor3), STQ(49140)); await checkNotInvesting(crowdsale, token, funds); await checkNotWithdrawing(crowdsale, token, funds); }); 

Do not forget to test exceptional situations. For example, we verified that owners, after completing a successful ICO, withdraw money. We also have to test that these comrades - investor 2, investor 3, anonymous from the street - cannot withdraw money, i.e., when submitting a request for withdrawal of money, an exceptional situation will occur, the contract will not accept the request.


We summarize: it is worth testing, there are all the means for this. By the way, the programmer should not be a tester. Why? Because the creator badly sees his mistakes. Some model had already formed in his head, and he transferred it to the code. When a programmer tries to check his code, his model inevitably jumps out in his head, and the brain says: “Yes, everything is normal here. We did this method so that ... And stop looking there. Let's go have a drink smoothie. ”


In addition to testing, you also need an audit. Audit involved specially trained people. During the audit, additional tests may be developed, but audit is a completely different situation and completely different skills.


If we are talking about auditing, then first of all you need to understand what vulnerabilities are and how much you will pay for them to auditors. There are several ways to evaluate. For example, a good OWASP methodology, it introduces two dimensions for a vulnerability: importance and probability. The impact of vulnerabilities on a project is the product of these two quantities. This may remind someone a risk assessment matrix.



In practice, in audit reports of a smart contract, it is often necessary to see that the degree of influence of vulnerability and its importance attracts by the ears. I do not know why this is happening. Nonetheless, critical vulnerabilities are not called critical. Therefore, we propose another methodology that links the impact of vulnerability on real life with your project. In the case of smart contracts, there are fairly clear results of exploitation of the vulnerability: you can derive a broadcast or tokens, which is very bad. In some conditions, the contract will hang or its condition will deteriorate to such an extent that it will have to replace the contract. Here the auditors and the audit client may have a minimal amount of disputes. A couple of links to audit reports:



A report is a document that tells you what vulnerabilities have been found and (ideally) what to do next. Someone in Western circles writes big reports: they tell you that you need to call this function differently, but it’s better to move this code somewhere else. But I just do not see the point in doing this if the customer does not engage in the serial development of smart contracts, if he needs to conduct an ICO once and continue to mine his sand in the quarry for which he collected the air.


Security issues of smart contracts


Let us turn to the problems that need attention. This is a topic for a separate article on the security of smart contracts. I will note a few things. To get started, very carefully review the functions and make sure that they are closed with the rights as necessary, with the most stringent restrictions. For example, a function that does not change anything in the blockchain can be declared as view . A function that does not read the blockchain at all is pure . It is necessary to impose these restrictions. Moreover, the administrative functions should be checked by the owner. This seems obvious, but remember Parity.


I repeat once again: all the data in the blockchain is open to everyone, despite the modifiers and access rights to the state. There may be public , it may not be, but in fact everything can be read from the contract. Do not use a transaction parameter such as tx.origin : this opens a vulnerability. Choose msg.sender .


From nontrivial. Probably, many have heard about the so-called reentrancy attack, through which The DAO was hacked. The problem is that when your contract method is still working, it can make an outside call. This only applies to external calls, which, in turn, can go back and forth to the same method or another contract method. And this opens up vulnerabilities: your contract status may not yet be consistent, some invariants may be temporarily broken during the operation of the method and not yet restored.


To combat this there are a number of methods. The most hardcore method - the nonReentrant modifier from the nonReentrant library contract - prohibits reentrancy for contracts. Why not use it? It costs a certain amount of gas, he writes a state, but in some cases, safety is more important than excess gas consumption.


Consider, for example, the front running attack. What if you encrypted something and put it in Blockchain? It is impossible to decipher, because asymmetric cryptography has not been canceled. But as soon as you try to legitimately decrypt it by sending a password transaction, this is what happens. Firstly, the password is obtained as a one-time password, because it flew into the blockchain; everyone sees it. Secondly, when the transaction left you, but has not yet become part of the main branch and has not committed you tokens, at this moment someone can see your password and slip your transaction, which will be earlier than yours, although it occurred later .


Not so long ago there was information about another attack - short address attack. Some exchanges were subject to it. And libraries that send transactions to Ethereum. The main API library Ethereum web3 is not exposed, but software exchanges have been exposed. The attack was that the user used an address shortened by one byte. When parameters were blinded into a transaction, the parameters following this address were shifted by one byte. And when the Ethereum virtual machine accessed these parameters, at the very end, calldata EVM implicitly added a zero. The number was shifted by one byte, and such a shift is multiplication by 256. That is, the user shot 1 unit of air when all security checks on the exchange side had already been passed, and in fact he was transferred 256 units.


Someone says: “Wrongly programmed the exchange”. There is a problem in the Ethereum virtual machine, because, in my opinion, when accessing bytes outside the existing parameters of the transaction, in reality there should not be an implicit zero substitution, but an error, an exceptional situation. So, as it happens in the management of address space in ordinary applications on the computer.


I already mentioned overflow. And once again I will say that there are short data types, for example, numbers that occupy 1 byte. In an unsigned case, this is from 0 to 255 inclusive. It is important to avoid overflowing them. Sometimes it appears implicitly, you may not notice it. For example, if it is a loop parameter to which you substitute a type using the var keyword. That is, the type there will be implicitly selected as single-byte if you initialize the parameter with zero; hence never reaches 256; then you potentially have an infinite loop and a hung contract. It will not hang, it will fall, but if the cycle is somewhere in a key place, then your contract will not go any further.


With different arithmetic, there may be implicit types of expressions. For example, if you raise something to a power, two byte numbers, and assign a result to a large number, then without casting, you will have a byte result and again an overflow will occur.


Bug bounty


Bug bounty - if you translate literally, it is the issuance of rewards for bugs. The same assessment methodology is applicable here as an audit assessment, i.e. an assessment of vulnerabilities. I would single out two types of fundamentally different bug bounty programs. The first is the so-called manual bug bounty. A good link to how this business is made out: Aventus Token Sale Bug Bounty . In fact, this is a kind of offer that suggests: “Let's look for vulnerabilities in such and such code,” many conditions are specified, for example, who first found it, is a good fellow. And in general, go, look, everything is cool there, it describes how much money is due for what vulnerability. Here the mechanics are clear. You write to security experts, hackers that have found this and that. You check, and if so, they are paid a reward.


There is a second type: automatic bug bounty. It is attractive to both hackers and customers. Here it is convenient that there are no negotiations, no disputes about what kind of vulnerability, how much money for it. In the manual version, doubts begin that, they say, it will never be exploited in this form. Here it is not. There may be two scenarios. The first one is convenient for purses, storages of the ether, when the depot is simply depot, the ether is poured onto it, then it says: “Break, guys.” Here the only thing you can add is the comment “This is a bug bounty, everything can and should be broken and taken away on the air.” I'm not sure, but it would seem that by doing this you are shooting potential questions about unauthorized access to information and a criminal article with a hacker who will burglary in your interests. The second scenario of the automatic bug bounty is a violation of the invariant. Contracts usually have explicit or implicit invariants. For example, tokens have a number that says how many tokens are. And this number should be equal to the sum of the balance sheets of tokens holders. Or, for example, the air repository that works during the ICO, it can keep the amount, how much air is collected, and the balance of the storage contract must be greater than or equal to this amount. If this is not the case, then an invariant violation occurs.


How is this bug bounty organized? There is a contract that gives interested parties a new copy of the contract with the invariant, and by their actions they can somehow play with the copy and try to break the invariant. When it is violated, they are automatically flown money, they are paid by the parent contract. This is convenient because this whole story is automatic, and a hacker can get a reward for his work in a couple of hours, and the customer bug bounty will see how his contract has been hacked, he will know for sure, because there were 100 ethers, and it became 0. see it, because in Blockchain everything is public. And both parties do not need to waste time on disputes.


Contract contract


Developed, tested, conducted an audit and bug bounty - now is the time to deploy, that is, to lay out contracts in the blockchain. Truffle , — migrate . , .


— , , - , . , , , 20 20 . . , . . , .


, , , -, . , , , , 1 . , 300 . , , — . , , , , . , Testnet — Ethereum, , . , , , .


, , . , - , . . .


. , : «, , . ». , . : , , . , , , , Truffle . , , . , . . Truffle , geth, , . , . — . , , , .


, , . , . , . . , . . . .


, , , , ICO , .


— . , ABI , , Etherscan. . , , .



- . , , . , , , , .


, . , , , . , , , , , .


, . It's pretty simple. , . , . , .


ICO-, , , , , , , , , . , , .



: , . , . - . , Ethereum, Ethereum, , , , , , Intel AMD. AMD64 , , . RISC-, reduced instruction set. - , . , , , — . , - backdoor, . , , .


. , . : . Etherscan. , , , . , , . . , . , , . user friendly . .


, Etherscan, . : « , , Etherscan — ?» , . , , , , . , . , , white paper.


Conclusion


, . . , . , . 3 . ICO!


')

Source: https://habr.com/ru/post/342534/


All Articles