Here we illustrate how to run a smart contract on Nexres locally. We provide step-by-step tutorials to set up locally with 4 nodes and use the built-in smart contract service.
Install
Following the instruction install tutorial to initial the environment that runs a Key-Value Service locally. If you are using our cloud, you can ignore the system install section.
Smart Contract Install
It contains three steps if you want to deploy your contract and execute its functions in ResilientDB: Create the contract account, deploy the contract, and execute the functions.
The ‘contract_service_tools’ provides access to the system by providing a JSON file and the service config.
contract_service_tools
bazel-bin/service/tools/kv/api_tools/contract_service_tools -c ServiceConfig –config_file=JSON Path
Parameters:
-c the client configuration path
–config_file the JSON file describing the actions
Create a Owner Account
For creating an account, the JSON file is simply to provide the action:
{
"command":"create_account",
}
Command:
bazel-bin/service/tools/kv/api_tools/contract_service_tools -c service/tools/config/interface/service.config –config_file=service/tools/kv/api_tools/create.js
Response:
Then, you will see the result
create account: address: "0x67c6697351ff4aec29cdbaabf2fbe3467cc254f8"
Deploy Your Contract
Contract
Nexres only handles the JSON description of the contract source code. We use solc, a tool from Solidity, to obtain the JSON file. Currently, we only support solidity version is larger than 0.5.0 (solidity >= 0.5.0)
We provide token.sol as an example below:
solc –evm-version homestead –combined-json bin,hashes –pretty-json –optimize token.sol > token.json
Once get your json contract, you can find the contract name(“token.sol:Token”) and its function hashes under the contract name section in the file.
token.sol:
pragma solidity >= 0.5.0;
// Transfer tokens from the contract owner
contract Token {
mapping (address => uint256) balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
constructor(uint256 s) public {
balances[msg.sender] = s;
}
// Get the account balance of another account with address _owner
function balanceOf(address _owner) public view returns (uint256) {
return balances[_owner];
}
// Send _value amount of tokens to address _to
function transfer(address _to, uint256 _value) public returns (bool) {
if (balances[msg.sender] >= _value) {
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
else
{
return false;
}
}
}
token.json
{
"contracts":
{
"token.sol:Token":
{
"bin": "608060405234801561001057600080fd5b506040516101fe3803806101fe8339818101604052602081101561003357600080fd5b5051336000908152602081905260409020556101aa806100546000396000f3fe608060405234801561001057600080fd5b5060043610610052577c0100000000000000000000000000000000000000000000000000000000600035046370a082318114610057578063a9059cbb1461008f575b600080fd5b61007d6004803603602081101561006d57600080fd5b5035600160a060020a03166100cf565b60408051918252519081900360200190f35b6100bb600480360360408110156100a557600080fd5b50600160a060020a0381351690602001356100ea565b604080519115158252519081900360200190f35b600160a060020a031660009081526020819052604090205490565b33600090815260208190526040812054821161016b573360008181526020818152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600161016f565b5060005b9291505056fea265627a7a72315820600579dee5d66ea3489085c4cb41116045ba977cb4804caac8d5f24e248e337064736f6c63430005100032",
"hashes":
{
"balanceOf(address)": "70a08231",
"transfer(address,uint256)": "a9059cbb"
}
}
},
"version": "0.5.16+commit.9c3226ce.Linux.g++"
}
Deploy JSON file
Now we generate the JSON for the deployment. The JSON file contains the command (“deploy”), the contract location, the contract section in the JSON file, the owner_address address who owns the contract (we have created in the previous step), and the initial parameters, which can be empty.
{
"command":"deploy",
"contract_path": "service/tools/kv/api_tools/example_contract/token.json",
"contract_name": "token.sol:Token",
"init_params": "1000",
"owner_address": "0x67c6697351ff4aec29cdbaabf2fbe3467cc254f8"
}
Command:
bazel-bin/service/tools/kv/api_tools/contract_service_tools -c service/tools/config/interface/service.config –config_file=service/tools/kv/api_tools/deploy.js
Response:
Then you will see the response:
deploy contract:
owner_address: "0x67c6697351ff4aec29cdbaabf2fbe3467cc254f8"
contract_address: "0xfc08e5bfebdcf7bb4cf5aafc29be03c1d53898f1"
contract_name: "token.sol:Token"
Execute Contract
Now we generate the JSON for the execution. The JSON file contains the command (“execute”), the contract address, the caller address who owns the contract, the function name, and the parameters to run the function.
{
"command":"execute",
"contract_address": "0xfc08e5bfebdcf7bb4cf5aafc29be03c1d53898f1",
"caller_address": "0x67c6697351ff4aec29cdbaabf2fbe3467cc254f8",
"func_name":"transfer(address,uint256)",
"params":"0x1be8e78d765a2e63339fc99a66320db73158a35a,100"
}
Command:
bazel-bin/service/tools/kv/api_tools/contract_service_tools -c service/tools/config/interface/service.config –config_file=service/tools/kv/api_tools/execute.js
Response:
Once it is done, you will see the result:
0x0000000000000000000000000000000000000000000000000000000000000001
Using Key-Value Interfaces
The Key-Value interfaces provide the API to access the accounts: get_balance and set_balance.
The JSON files and corresponding commands are shown as below:
{
"command":"get_balance",
"address":"0x1be8e78d765a2e63339fc99a66320db73158a35a"
}
bazel-bin/service/tools/kv/api_tools/contract_service_tools -c service/tools/config/interface/service.config –config_file=service/tools/kv/api_tools/get_balance.js
{
"command":"set_balance",
"address":"0x1be8e78d765a2e63339fc99a66320db73158a35a",
"balance":"2000"
}
bazel-bin/service/tools/kv/api_tools/contract_service_tools -c service/tools/config/interface/service.config –config_file=service/tools/kv/api_tools/set_balance.js
Notice
The accounts do not need to be created using the API before being used. However, if the account is used to deploy the contract, it must first be created by the API to register in the contract database.
Future Work
Apply the authorization for the execution that verifies the owner to execute its contracts, like using the signatures.