7 tips about building smart contract on NEO
- Build your own NEO private chain
The operation of NEO smart contracts is inseparable from the NEO blockchain support. In most cases, smart contracts need to access the underlying NEO storage services through the NEO blockchain. At the same time, when the smart contract is invoked, it needs to make a valid judgment on the information of the call initiator when it is invoked, such as verifying the signature and so on. All of these need to be completed in the NEO blockchain to complete the test.
The cost of deploying smart contracts on the NEO blockchain is very expensive. A simple smart contract deployment costs 500 gas. If you need to access NEO storage services and support dynamic calls for smart contracts, the cost of deploying a smart contract is 1000Gas. Although NEO provides a test network, NEO and Gas of the test network are not easily available. Developers can apply to the NEO organization to get some test networks Gas and NEO for testing. But given the deployment of NEO's smart contracts up to 1000Gas (actually, really functional smart contracts such as ICO contracts must access NEO's underlying storage services). Even if NEO issues 20,000 Gases to developers, developers can only complete the deployment of 20 smart contracts.
Therefore, it is very necessary for developers to deploy a NEO private service on their own. This reliance on 100 million NEO coins and 100 million NEO coins derived from Gas. There is no need to worry about the cost of deploying the smart contract when debugging.
Another advantage of building a NEO private chain for development is that it allows developers to more easily query the transactions that have taken place. If the NEO test chain is used for debugging, each block contains not only the developer's own transaction but also the developer's transaction. Because the NEO test chain is open, all transactions that occur in the test chain are mixed together. As a result, developers find their own transaction information in the block, which increases the difficulty invisibly. Will reduce developers' development efficiency to varying degrees. At the same time, it will also expose the developer's own immature code to the public's field of vision prematurely, which will bring security risks.
NEO has provided documentation to teach users how to deploy a NEO private service. Please refer to:
https://docs.neo.org/en-us/network/private-chain.html
After the deployment is completed, it is also necessary to expose a node that supports the RPC interface according to the exchange docking process document to provide services to developers. NEO adapting exchange documents please refer to: https://docs.neo.org/en-us/exchange/v2.7.4.html
- Avoid using floating point data in smart contracts
NEO blockchain natively does not support floating point data. In order to represent a floating-point number, such as NEO's minimum unit of 0.00000001, the actual approach is that NEO will process this data by 10 million times as an integer.
In the NEO virtual machine itself, it does not have a floating point data conversion byte array/byte array conversion floating point data and similar APIs. Therefore, if a floating-point data needs to be saved and read, it is very troublesome to handle it in a smart contract.
The correct approach is to deal with the floating-point data of incoming/outgoing smart contracts, first become an integer to access and calculate, and so on for display, and then back to a floating-point data outside the smart contract.
- Avoid string manipulation in smart contract
Since the virtual machine that runs the NEO smart contract does not have an API for handling strings, even for case conversions, the ToString() method is not supported for some other types. If a developer wants to process a string in a smart contract, he or she must read and verify it byte by byte. Even if the string processing is completed, the consumption of Gas will increase and the volume of the smart contract will also increase.
The correct approach is that data needs to handle string data outside smart contracts. For some flags, you can use integers instead of strings. For some smart contract output results, it should also be replaced with an error code. It is better not to transfer strings directly.
- NEO VM does not support exception handling mechanism
The execution environment of the NEO smart contract, that is, the NEO virtual machine itself does not support the exception handling mechanism. This means that try-catch segments cannot be used when writing smart contract code. The NEON compiler does not allow such code to generate AVM files by compiling.
Therefore, when writing NEO smart contract code, we must pay special attention to the robustness of the code, do a good job of checking the parameters, and check the return value of the function, and avoid using the exception data to perform the next operation to avoid exceptions. Developers of NEO smart contracts should also not expect to determine the execution path of the code by catching exceptions. This does not work.
The developer of the NEO smart contract should make a parameter check inside the function when writing a function and clearly define the meaning of the return value.
In fact, the other two C# keywords ref and out are not supported. So don't expect a function in a smart contract to return multiple values at once.
- Handle byte stream operations carefully
In the NEO virtual machine, the byte[] data is treated as a special data type and is immutable. Once you need to modify the value of a byte in the byte array, you need to regenerate a new byte array object.
In the actual running process, once the code similar to the following is executed, this smart contract call will crash and return directly to "FAULT BREAK".
byte[] byteArray = new byte[]{0x0a, 0x0b, 0x0c, 0x0d};byteArray[2] = 0x01; |
The correct way is to use the Range function to truncate the previously unmodified part of the code. Add the 0x01 to the array through the Concat function, then dock the parts of the original array that do not need to be modified. code show as below:
byte[] byteArray = new byte[]{0x0a, 0x0b, 0x0c, 0x0d};byte[] temp = byteArray.Range(0, 2);temp = temp.Concat(new byte[]{0x01});temp = temp.Concat(byteArray.Range(3, 1)); |
In addition to this, there is no better way to implement changes to the byte[] element.
- Need to push the stack from right to left when calling multi-parameter smart contract function
In the NEO test article (https://docs.neo.org/en-us/sc/quickstart/test.html), examples of how to invoke smart contracts with parameters are given. But that is limited to smart contract functions with a single input parameter. If you need to call smart contract functions with multiple parameters, you need to pay attention to the stacking order of function parameters. For example, the following smart contract function:
bool CallMe(string param1, int param2, bool param3, byte[] param4) |
Then when the code is called, the order in which the functions are stacked should be param4, param3, param2, param1. And before the actual call, pass in the packed instruction sb.Emit(Neo.VM.OpCode.PACK); Package all the parameters. Otherwise, the smart contract function call will fail to return "FAULT BREAK" because of the mismatch of the parameter types.
- Using Map class which is in devpack
NEO provides developers with a generic container object of type Map<TKey, TValue> in the devpack. Developers can use Map-type objects to store a series of complex data in key-value pairs in the NEO store. Advanced packaging of Storage.Get, Storage.Put, and Storage.Delete methods for the Map type. It is easier and more convenient for developers to use Map objects to manipulate NEO underlying storage than three static methods that use Storage directly.