编辑合约
您可以基于任何支持solidity的编辑器编写合约。下述将基于remix在线编辑器 为例,进行说明。
为了叙述方便,我们使用如下的简单合约示例:
Copy pragma solidity >=0.4.24 <=0.7.6 ;
contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint) {
return storedData;
}
}
(注意:由于SCDO主网兼容 Istanbul版本的EVM,开发合约时建议使用的solidity版本不大于0.7.6。SCDO 合约虚拟机目前不支持 EVM Berlin 版本的功能。)
下面的图片是 Remix 在线编辑器的首页演示:
编译合约
将合约写好并保存后,可以使用remix的编译功能来编译合约并检查可能的语法错误。如屏幕截图所示,单击“编译”按钮以编译示例合约。如果有错误,编译器将指向可能发生错误的位置。
设置自己的测试环境
成功编译合约后,我们可以部署合约并对其进行测试。我们建议的最佳实践是设置SCDO私有链/专有链节点,然后部署合约在此链上,并进行测试。如果您对测试结果满意,则可以将合约部署到SCDO主网。我们的测试节点是在Ubuntu中设置的。
获取合同bytecode
如 Remix IDE显示的, 在合约成功编译后, 点击 Remix IDE 左边显示栏 的 "Deploy" 图标。见下图:
如果没有错误, 你将会看到下图所示的:
点击绿色查看图标。
您将见到
“input”字段中的值是合约的字节码。单击字节码字符串旁边的复制图标,将其复制到剪贴板。然后将副本保存到安全的地方。字节码如下:
Copy 0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a723058209e18a0a3a2dc0fa6b26ca8a3b915b69344f7a214ce5510d0bc21f948fb0ff0750029
用client tool 部署合约
准备一个SCDO帐户,并确保有足够的余额来部署合约。在这里,我们使用片1的帐户1S010a3fe1668c7cab5923fe0f77cb25ec21f644f1,同时并保存帐户密钥文件。
注意:密钥库文件是由以下命令生成的
Copy ./client savekey --privatekey "the private key paired with 1S010a3fe1668c7cab5923fe0f77cb25ec21f644f1" --file 1S010a3fe1668c7cab5923fe0f77cb25ec21f644f1.keystore --shard 1
启动一个私链节点 node (我们的例子启动的是片1的一个节点)
Copy ./client sendtx --amount 0 --address 0.0.0.0:8027 --payload 0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a723058209e18a0a3a2dc0fa6b26ca8a3b915b69344f7a214ce5510d0bc21f948fb0ff0750029 --from 1S010a3fe1668c7cab5923fe0f77cb25ec21f644f1.keystore
sendtx 参数 address 是启动的node的 ip 地址,这里用的是局部ip 地址; "amount" 是交易token量 (以 Wen为单位), 对部署合约,一般设置为0; from 是前面用savekey 命令生成的密码文件;payload 是合约的bytecode(字节码); gas 是交易需要的最低gas (默认值 20000).
上述命令执行的结果是:
Copy transaction sent successfully
{
"Data": {
"AccountNonce": 12,
"Amount": 0,
"From": "1S010a3fe1668c7cab5923fe0f77cb25ec21f644f1",
"GasLimit": 200000,
"GasPrice": 10,
"Payload": "0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a723058209e18a0a3a2dc0fa6b26ca8a3b915b69344f7a214ce5510d0bc21f948fb0ff0750029",
"Timestamp": 0,
"To": "0S0000000000000000000000000000000000000000",
"Type": 0
},
"Hash": "0x08c45b71dd7c151071f222fb6d1216248425e977255d5923dbade76c32abd1b0",
"Signature": {
"Sig": "9IawOq9cHp6Cmmj7i7YD7oxMNB+Zc28YmJuUzpA7S9INLiGP6ysdYK/AC9jZH3CF+kUJYvBWsIwXEWx2s/s/aQA="
}
}
根据返回结果的Hash查看合约部署结果:
Copy ./client getreceipt --address 0.0.0.0:8027 --hash 0x08c45b71dd7c151071f222fb6d1216248425e977255d5923dbade76c32abd1b0
得到如下结果:
Copy {
"contract": "1S01f671dfc64128d285e178c1f6e7bf640d420002",
"failed": false,
"poststate": "0x3c7e3c77abf149d2d59e2d94d134611314751e22b940a2f22be9b2e2c74fb9b6",
"result": "0x6080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a723058209e18a0a3a2dc0fa6b26ca8a3b915b69344f7a214ce5510d0bc21f948fb0ff0750029",
"totalFee": 802130,
"txhash": "0x08c45b71dd7c151071f222fb6d1216248425e977255d5923dbade76c32abd1b0",
"usedGas": 80213
}
结果中failed为false表明合约部署成功,contract的值为合约地址。
调用合约
通过remix获得调用方法的字节码
使用client sendtx命令调用合约需要提供合约调用方法(包括参数设定)的payload信息(bytecode/字节码)。这个信息可以通过remix获得。在Remix IDE 左边的控制窗口,Deploy 的下面,可以看到本示例合同的set和get方法。在set右侧填入参数值(这里是22),点击set,即可得到调用set方法(包括参数值设定)的字节码了。
在Remix IDE 右下方日志窗口可以看到上面点击结果。点击详情可查看调用详情,其中input的值即为本示例set方法调用的字节码 (参数设置为22)。如下图所示:
调用set方法的字节码是:
Copy 0x60fe47b10000000000000000000000000000000000000000000000000000000000000016
使用 sendtx 调用合约方法
如下的命令调用上述合约中的set方法,参数payload 是我们前面得到的字节码,from为发起交易的账户,to为合约地址
Copy ./client sendtx --amount 0 --payload --address 0.0.0.0:8027 --payload 0x60fe47b10000000000000000000000000000000000000000000000000000000000000016 --from 1S017f6215c30f1505e0d42769c5472b410d6bf961.keystore --to 1S01f671dfc64128d285e178c1f6e7bf640d420002
执行结果如下:
Copy transaction sent successfully
{
"Data": {
"AccountNonce": 13,
"Amount": 0,
"From": "1S010a3fe1668c7cab5923fe0f77cb25ec21f644f1",
"GasLimit": 200000,
"GasPrice": 10,
"Payload": "0x60fe47b10000000000000000000000000000000000000000000000000000000000000016",
"Timestamp": 0,
"To": "1S0126ba0710ad416638a7f0e5a113e9b6be4b0002",
"Type": 0
},
"Hash": "0xb26dae6efc9942c6655a6e5baa372f6d3388b62ac50011466a7b6c105ee6e01e",
"Signature": {
"Sig": "bt/Nh0UyKrCxTxoP/gyeTgE8mHVmVmZHCQHJ14pGePJHblZrS1vI/6aE2d2WXUSqLYGnSqFWoaXkxbOa7hco+wA="
}
}
使用上面结果的hash, 通过查询receipt信息,可以获取set方法的调用结果:
Copy ./client getreceipt --hash 0xb26dae6efc9942c6655a6e5baa372f6d3388b62ac50011466a7b6c105ee6e01e
得到如下结果:
{ "contract": "0x", "failed": false, "poststate": "0x328868cd36c074185bd1ccf4e905728b0f36de9fd06743e93b87483ae3872bd1", "result": "0x", "totalFee": 266690, "txhash": "0xb26dae6efc9942c6655a6e5baa372f6d3388b62ac50011466a7b6c105ee6e01e", "usedGas": 26669 }
注意:调用合约的账户必须是与合约地址同一分片,SCDO目前不支持跨片合约调用
使用call调用合约方法
对于仅获取变量值而不改变合约状态的方法,可以通过call来调用。在我们的示例中,获取get的bytecode (字节码) 和获取set 方法的字节码类似。get的字节码如下:
用call调用get 方法:
Copy client call --payload 0x6d4ce63c --to 0x47a99059219055cf8277d5d7dff933446edb0012
得到如下结果:
Copy {
"contract": "0x",
"failed": false,
"poststate": "0x2673977b8565ad747d1dff04dccaa424afcb1e81c3e07e994eeef538d25a1a06",
"result": "0x0000000000000000000000000000000000000000000000000000000000000016",
"totalFee": 21696,
"txhash": "0x169ac2e722ddfc99a2368aecd4462cbf92a43320c2cf5e18341492bfb00fd4ec",
"usedGas": 21696
}
可以看到,result显示的变量值为之前通过set方法设置的22 (十六进制表示)。
Deploy to SCDO mainnet
如前面几节中所示,对合同进行了充分的测试后,您可以按照与将其部署到专用网络相同的步骤,将其部署到SCDO主网上。