合约流程

编辑合约

您可以基于任何支持solidity的编辑器编写合约。下述将基于remix在线编辑器 为例,进行说明。

为了叙述方便,我们使用如下的简单合约示例:

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”字段中的值是合约的字节码。单击字节码字符串旁边的复制图标,将其复制到剪贴板。然后将副本保存到安全的地方。字节码如下:

0x608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a723058209e18a0a3a2dc0fa6b26ca8a3b915b69344f7a214ce5510d0bc21f948fb0ff0750029

用client tool 部署合约

  • 准备一个SCDO帐户,并确保有足够的余额来部署合约。在这里,我们使用片1的帐户1S010a3fe1668c7cab5923fe0f77cb25ec21f644f1,同时并保存帐户密钥文件。

  • 您可以下载 SCDO release Mac/Windows/Linux node 和 client tools.

注意:密钥库文件是由以下命令生成的

./client savekey --privatekey "the private key paired with 1S010a3fe1668c7cab5923fe0f77cb25ec21f644f1" --file 1S010a3fe1668c7cab5923fe0f77cb25ec21f644f1.keystore --shard 1
  • 启动一个私链节点 node (我们的例子启动的是片1的一个节点)

  • 使用sendtx 命令部署合同.

 ./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).

上述命令执行的结果是:

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查看合约部署结果:

./client getreceipt --address 0.0.0.0:8027 --hash 0x08c45b71dd7c151071f222fb6d1216248425e977255d5923dbade76c32abd1b0

得到如下结果:

{
    "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方法的字节码是:

0x60fe47b10000000000000000000000000000000000000000000000000000000000000016

使用 sendtx 调用合约方法

如下的命令调用上述合约中的set方法,参数payload 是我们前面得到的字节码,from为发起交易的账户,to为合约地址

./client sendtx --amount 0   --payload  --address 0.0.0.0:8027 --payload 0x60fe47b10000000000000000000000000000000000000000000000000000000000000016 --from 1S017f6215c30f1505e0d42769c5472b410d6bf961.keystore --to 1S01f671dfc64128d285e178c1f6e7bf640d420002

执行结果如下:

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方法的调用结果:

./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的字节码如下:

 0x6d4ce63c

用call调用get 方法:

client call --payload 0x6d4ce63c --to 0x47a99059219055cf8277d5d7dff933446edb0012

得到如下结果:

{
    "contract": "0x",
    "failed": false,
    "poststate": "0x2673977b8565ad747d1dff04dccaa424afcb1e81c3e07e994eeef538d25a1a06",
    "result": "0x0000000000000000000000000000000000000000000000000000000000000016",
    "totalFee": 21696,
    "txhash": "0x169ac2e722ddfc99a2368aecd4462cbf92a43320c2cf5e18341492bfb00fd4ec",
    "usedGas": 21696
}

可以看到,result显示的变量值为之前通过set方法设置的22 (十六进制表示)。

Deploy to SCDO mainnet

如前面几节中所示,对合同进行了充分的测试后,您可以按照与将其部署到专用网络相同的步骤,将其部署到SCDO主网上。

Last updated