跳到主要内容

1. 介绍

本文面向基于Solidity语言进行合约开发的开发人员和使用Solidity合约的普通用户。介绍了在BubiChain上开发Solidity智能合约的方法,包括合约编写、编译、部署、调用等操作流程的说明。

2. 环境准备

本文使用说明提供了HTTP请求示例,您需要将示例中的{url}替换为具体的网站域名或IP地址。

  • 如果您选择使用布比的体验链,请将 {url} 替换为 https://seed1-node.bubi.cn
  • 或者,您也可以参考部署节点自行搭建节点,然后将 {url} 替换为所部署节点的IP地址和webserver模块的端口号。

另外,需准备一个激活的账号。若您尚未拥有账号,请参考激活账号了解账号创建和激活的详细步骤。

3. 合约开发环境

BubiChain对Solidity完全兼容,开发人员可以使用Remix在线IDE进行Solidity合约开发。

进入Remix在线IDE:

  1. 在图形面板选择文件管理模块。
  2. 选择默认工作区,其中提供了示例合约。
  3. 打开Storage.sol合约文件。
  4. 在主面板编辑合约,修改内容如下所示:
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.2 <0.9.0;

/**
* @title Storage
* @dev Store & retrieve value in a variable
* @custom:dev-run-script ./scripts/deploy_with_ethers.ts
*/
contract Storage {

uint256 number;

event Store(uint256 num);

/**
* @dev Store value in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
emit Store(number);
}

/**
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
}

4. 合约语法

Solidity语法和代码编写规则请参考solidity开发文档

在BubiChain上,Solidity在内置接口方面与以太坊略有不同,新增了一些与隐私保护相关的接口。具体信息请参见隐私保护使用说明。

5. 编译合约

编译合约的步骤如下:

  1. 在图形界面选择合约编译模块。
  2. 选择编译器版本0.8.5。
  3. 点击 Compile 1_stoaqe.sol ,若编译成功,图形界面将显示绿色对号。
  4. 复制字节码以备部署合约使用。

6. 部署合约

下面以adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd为源账户进行合约部署。

6.1. 查询账户nonce

使用API getAccountBase 查询源账户 adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd 的 nonce 值。

address 字段替换为自己准备的账号地址。

HTTP请求示例:

curl http://{url}/getAccountBase?address=adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd

请求参数说明:

字段名类型描述
addressString必填,账号地址。

成功的返回JSON数据:

{
"error_code" : 0,
"result" : {
"address" : "adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd",
"assets_hash" : "131bf4753e7c2a556886b07bf9f2b7ff268714399b1a058fa0488fc44c7a1788",
"balance" : 99699954914966002,
"metadatas_hash" : "f66847431c1a4be5be1b85df04dee822c12e5addae64357e0e8a90eb9ac047a5",
"nonce" : 21,
"priv" : {
"master_weight" : 1,
"thresholds" : {
"tx_threshold" : 1
}
}
}
}

响应参数说明:

字段名类型描述
error_codeInt0表示查询成功,4表示账户未激活。
addressString查询的账户地址。
balanceInt账户gas余额。
nonceInt账号当前作为交易源执行过的交易数量。若查询结果没有显示nonce值,说明账号的当前nonce是0。
privJson账户权限。

6.2. 序列化交易

组装交易结构,并通过API getTransactionBlob将交易结构序列化。

address 字段替换为准备好的账号地址,将 nonce 字段替换为该账号当前的 nonce 值加 1。

HTTP请求示例:

curl -d '{
"source_address":"adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd",
"nonce":22,
"fee_limit":10000000000,
"gas_price":1000,
"operations":[
{
"type": 1,
"create_account":{
"dest_address":"",
"contract":{
"type":1,
"payload": "608060405234801561001057600080fd5b50610189806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b6040516100509190610112565b60405180910390f35b610073600480360381019061006e91906100d6565b61007e565b005b60008054905090565b806000819055507f69404ebde4a368ae324ed310becfefc3edfe9e5ebca74464e37ffffd8309a3c16000546040516100b69190610112565b60405180910390a150565b6000813590506100d08161013c565b92915050565b6000602082840312156100ec576100eb610137565b5b60006100fa848285016100c1565b91505092915050565b61010c8161012d565b82525050565b60006020820190506101276000830184610103565b92915050565b6000819050919050565b600080fd5b6101458161012d565b811461015057600080fd5b5056fea26469706673582212205ebe2d0ad55cb1fb362b1357556527347238e3da545b9b14bb083b4fa809d18464736f6c63430008050033"
},
"init_balance": 10000000,
"init_input" : "",
"priv": {
"master_weight": 0,
"thresholds": {
"tx_threshold": 1
}
}
}
}
]
}' http://{url}/getTransactionBlob

请求参数说明:

字段名类型描述
source_addressString必填,源账户地址,即发起交易的账户。
nonceInt必填,必须为源账户当前的nonce值加1。账户当前nonce值为21,因此参数为22。
payloadString必填,将第5节编译合约获得的字节码填入该字段。

其他交易参数按照示例填写即可,更多交易结构信息参考HTTP接口文档

成功的返回JSON数据:

{
"error_code" : 0,
"error_desc" : "",
"result" : {
"hash" : "08eda53c8e1c788bd3e6926df04e4f9e63e35cf407ff1a7ed0d22224185f8fd8",
"transaction_blob" : "0a25616478537031583456376858444452424b484c3655323143706250686b693759716a755564101622ea0608012ae50612d706080112d206363038303630343035323334383031353631303031303537363030303830666435623530363130313839383036313030323036303030333936303030663366653630383036303430353233343830313536313030313035373630303038306664356235303630303433363130363130303336353736303030333536306530316338303633326536346365633131343631303033623537383036333630353733363164313436313030353935373562363030303830666435623631303034333631303037353536356236303430353136313030353039313930363130313132353635623630343035313830393130333930663335623631303037333630303438303336303338313031393036313030366539313930363130306436353635623631303037653536356230303562363030303830353439303530393035363562383036303030383139303535353037663639343034656264653461333638616533323465643331306265636665666333656466653965356562636137343436346533376666666664383330396133633136303030353436303430353136313030623639313930363130313132353635623630343035313830393130333930613135303536356236303030383133353930353036313030643038313631303133633536356239323931353035303536356236303030363032303832383430333132313536313030656335373631303065623631303133373536356235623630303036313030666138343832383530313631303063313536356239313530353039323931353035303536356236313031306338313631303132643536356238323532353035303536356236303030363032303832303139303530363130313237363030303833303138343631303130333536356239323931353035303536356236303030383139303530393139303530353635623630303038306664356236313031343538313631303132643536356238313134363130313530353736303030383066643562353035366665613236343639373036363733353832323132323035656265326430616435356362316662333632623133353735353635323733343732333865336461353435623962313462623038336234666138303964313834363437333666366336333433303030383035303033331a041a0208012880ade2043080c8afa02538e807"
}
}

响应参数说明:

字段名类型描述
error_codeInt0表示成功序列化,2表示交易结构参数错误。
transaction_blobString交易序列化之后的16进制表示。

6.3. 签名交易

通过API getSignaturetransaction_blob进行签名。

注意:这种签名方式不安全,会泄露账号私钥,仅用于测试调试使用。生产环境请使用离线交易签名工具,在本地进行签名。

HTTP请求示例:

curl -d '{
"private_key":"privbtBp152KnunKvCBgFQX96zuASSH6FBY9KVTX1bifPCLUWarq9EaN",
"transaction_blob": "0a25616478537031583456376858444452424b484c3655323143706250686b693759716a755564101622ea0608012ae50612d706080112d206363038303630343035323334383031353631303031303537363030303830666435623530363130313839383036313030323036303030333936303030663366653630383036303430353233343830313536313030313035373630303038306664356235303630303433363130363130303336353736303030333536306530316338303633326536346365633131343631303033623537383036333630353733363164313436313030353935373562363030303830666435623631303034333631303037353536356236303430353136313030353039313930363130313132353635623630343035313830393130333930663335623631303037333630303438303336303338313031393036313030366539313930363130306436353635623631303037653536356230303562363030303830353439303530393035363562383036303030383139303535353037663639343034656264653461333638616533323465643331306265636665666333656466653965356562636137343436346533376666666664383330396133633136303030353436303430353136313030623639313930363130313132353635623630343035313830393130333930613135303536356236303030383133353930353036313030643038313631303133633536356239323931353035303536356236303030363032303832383430333132313536313030656335373631303065623631303133373536356235623630303036313030666138343832383530313631303063313536356239313530353039323931353035303536356236313031306338313631303132643536356238323532353035303536356236303030363032303832303139303530363130313237363030303833303138343631303130333536356239323931353035303536356236303030383139303530393139303530353635623630303038306664356236313031343538313631303132643536356238313134363130313530353736303030383066643562353035366665613236343639373036363733353832323132323035656265326430616435356362316662333632623133353735353635323733343732333865336461353435623962313462623038336234666138303964313834363437333666366336333433303030383035303033331a041a0208012880ade2043080c8afa02538e807"
}' http://{url}/getSignature

请求参数说明:

字段名类型描述
private_keyString必填,源账户的私钥。
transaction_blobString必填,交易序列化的16进制表示。

成功的返回JSON数据:

{
"error_code" : 0,
"result" : {
"data" : "0a25616478537031583456376858444452424b484c3655323143706250686b693759716a755564101622ea0608012ae50612d706080112d206363038303630343035323334383031353631303031303537363030303830666435623530363130313839383036313030323036303030333936303030663366653630383036303430353233343830313536313030313035373630303038306664356235303630303433363130363130303336353736303030333536306530316338303633326536346365633131343631303033623537383036333630353733363164313436313030353935373562363030303830666435623631303034333631303037353536356236303430353136313030353039313930363130313132353635623630343035313830393130333930663335623631303037333630303438303336303338313031393036313030366539313930363130306436353635623631303037653536356230303562363030303830353439303530393035363562383036303030383139303535353037663639343034656264653461333638616533323465643331306265636665666333656466653965356562636137343436346533376666666664383330396133633136303030353436303430353136313030623639313930363130313132353635623630343035313830393130333930613135303536356236303030383133353930353036313030643038313631303133633536356239323931353035303536356236303030363032303832383430333132313536313030656335373631303065623631303133373536356235623630303036313030666138343832383530313631303063313536356239313530353039323931353035303536356236313031306338313631303132643536356238323532353035303536356236303030363032303832303139303530363130313237363030303833303138343631303130333536356239323931353035303536356236303030383139303530393139303530353635623630303038306664356236313031343538313631303132643536356238313134363130313530353736303030383066643562353035366665613236343639373036363733353832323132323035656265326430616435356362316662333632623133353735353635323733343732333865336461353435623962313462623038336234666138303964313834363437333666366336333433303030383035303033331a041a0208012880ade2043080c8afa02538e807",
"public_key" : "b001ac76f97b0fda145c68e2edf6665c247a292260694b5dfcacac8acb658bd3746e7d8a3032",
"sign_data" : "3a06fada16d4fb0752f8661dc6f43cf0784d36501ad2de80095f1887489b2e2530da9fd5630f5b9fd618c27ca576a19b61ed52cee4d447476dba71e71371c006"
}
}
字段名类型描述
dataString交易序列化的16进制表示,即transaction_blob。
public_keyString源账户的公钥。
sign_dataString签名数据。

6.4. 提交交易

通过API submitTransaction将交易提交到链上。

HTTP请求示例:

curl -d '{
"items" : [
{
"transaction_blob" : "0a25616478537031583456376858444452424b484c3655323143706250686b693759716a755564101622ea0608012ae50612d706080112d206363038303630343035323334383031353631303031303537363030303830666435623530363130313839383036313030323036303030333936303030663366653630383036303430353233343830313536313030313035373630303038306664356235303630303433363130363130303336353736303030333536306530316338303633326536346365633131343631303033623537383036333630353733363164313436313030353935373562363030303830666435623631303034333631303037353536356236303430353136313030353039313930363130313132353635623630343035313830393130333930663335623631303037333630303438303336303338313031393036313030366539313930363130306436353635623631303037653536356230303562363030303830353439303530393035363562383036303030383139303535353037663639343034656264653461333638616533323465643331306265636665666333656466653965356562636137343436346533376666666664383330396133633136303030353436303430353136313030623639313930363130313132353635623630343035313830393130333930613135303536356236303030383133353930353036313030643038313631303133633536356239323931353035303536356236303030363032303832383430333132313536313030656335373631303065623631303133373536356235623630303036313030666138343832383530313631303063313536356239313530353039323931353035303536356236313031306338313631303132643536356238323532353035303536356236303030363032303832303139303530363130313237363030303833303138343631303130333536356239323931353035303536356236303030383139303530393139303530353635623630303038306664356236313031343538313631303132643536356238313134363130313530353736303030383066643562353035366665613236343639373036363733353832323132323035656265326430616435356362316662333632623133353735353635323733343732333865336461353435623962313462623038336234666138303964313834363437333666366336333433303030383035303033331a041a0208012880ade2043080c8afa02538e807",
"signatures" : [
{
"sign_data" : "3a06fada16d4fb0752f8661dc6f43cf0784d36501ad2de80095f1887489b2e2530da9fd5630f5b9fd618c27ca576a19b61ed52cee4d447476dba71e71371c006",
"public_key" : "b001ac76f97b0fda145c68e2edf6665c247a292260694b5dfcacac8acb658bd3746e7d8a3032"
}
]
}
]
}' http://{url}/submitTransaction

请求参数说明:

字段名类型描述
transaction_blobString必填,交易序列化的16进制表示。
signatures[].sign_dataString必填,交易签名。
signatures[].public_keyString必填,源账户公钥。

成功的返回JSON数据:

{
"results" : [
{
"error_code" : 0,
"error_desc" : "",
"hash" : "08eda53c8e1c788bd3e6926df04e4f9e63e35cf407ff1a7ed0d22224185f8fd8"
}
],
"success_count" : 1
}

响应参数说明:

字段名类型描述
hashString交易哈希,可通过哈希值查询交易的内容。

6.5. 查询交易

通过API getTransactionHistory查询哈希为6262b3ef5777dfd2602c58f715089b16421dbad3d4b16aee067cc5e202b0cfe0的交易内容。

HTTP请求示例:

curl http://{url}/getTransactionHistory?hash=08eda53c8e1c788bd3e6926df04e4f9e63e35cf407ff1a7ed0d22224185f8fd8

请求参数说明:

字段名类型描述
hashString必填,交易哈希。参数来自提交交易的响应结果。

成功的返回JSON数据:

{
"error_code":0,
"result":{
"total_count":1,
"transactions":[
{
"actual_fee":1001206000,
"close_time":1711590948023360,
"error_code":0,"error_desc":"[{\"contract_address\":\"adxSTDPVrATUUbRT1Chh8rXc672NcjmTdjPZB\",\"contract_evm_address\":\"0x01ea8f369909ec23e1ed23a5e69597a603f0c474\",\"operation_index\":0}]",
"hash":
"08eda53c8e1c788bd3e6926df04e4f9e63e35cf407ff1a7ed0d22224185f8fd8",
"ledger_seq":11707,
"signatures":[
{
"public_key": "b001ac76f97b0fda145c68e2edf6665c247a292260694b5dfcacac8acb658bd3746e7d8a3032",
"sign_data": "3a06fada16d4fb0752f8661dc6f43cf0784d36501ad2de80095f1887489b2e2530da9fd5630f5b9fd618c27ca576a19b61ed52cee4d447476dba71e71371c006"
}
],
"transaction":{
"fee_limit":10000000000,
"gas_price":1000,
"nonce":22,
"operations":[
{
"create_account":{
"contract":{
"payload": "608060405234801561001057600080fd5b50610189806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b6040516100509190610112565b60405180910390f35b610073600480360381019061006e91906100d6565b61007e565b005b60008054905090565b806000819055507f69404ebde4a368ae324ed310becfefc3edfe9e5ebca74464e37ffffd8309a3c16000546040516100b69190610112565b60405180910390a150565b6000813590506100d08161013c565b92915050565b6000602082840312156100ec576100eb610137565b5b60006100fa848285016100c1565b91505092915050565b61010c8161012d565b82525050565b60006020820190506101276000830184610103565b92915050565b6000819050919050565b600080fd5b6101458161012d565b811461015057600080fd5b5056fea26469706673582212205ebe2d0ad55cb1fb362b1357556527347238e3da545b9b14bb083b4fa809d18464736f6c63430008050033",
"type":1
},
"init_balance":10000000,
"priv":{
"thresholds":{
"tx_threshold":1
}
}
},
"type":1
}
],
"source_address":"adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd"
},
"tx_size":1077
}
]
}
}

响应参数说明:

字段名类型描述
transactions[].error_codeInt创建合约账户操作执行结果的错误码,执行成功值为0,执行失败值为对应的错误码。
transactions[].error_descString操作执行成功时,内容包括合约账号的普通地址contract_address和以太坊地址contract_evm_address。操作执行失败时,内容为失败原因的描述。

7. 调用合约

7.1. 查询账户nonce

通过API getAccountBase查询源账号adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd的nonce值。

HTTP请求示例:

curl http://{url}/getAccountBase?address=adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd

请求参数说明:

字段名类型描述
addressString必填,源账户地址。

成功的返回JSON数据:

{
"error_code" : 0,
"result" : {
"address" : "adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd",
"assets_hash" : "ad67d57ae19de8068dbcd47282146bd553fe9f684c57c8c114453863ee41abc3",
"balance" : 98997253847591998,
"metadatas_hash" : "ad67d57ae19de8068dbcd47282146bd553fe9f684c57c8c114453863ee41abc3",
"nonce" : 42,
"priv" : {
"master_weight" : 1,
"thresholds" : {
"tx_threshold" : 1
}
}
}
}

响应参数说明:

参数类型描述
error_codeInt0表示查询成功,4表示账户未激活。
addressString查询的账户地址。
balanceInt账户gas余额。
nonceInt账号当前作为交易源执行过的交易数量。若查询结果没有显示nonce值,说明账号的当前nonce是0。
privJson账户权限。

7.2. 编码合约参数

模拟部署合约:

  1. 在图形面板选择部署模块。
  2. 选择虚拟节点Remix VM。
  3. 选择合约1_Storege.sol
  4. 模拟部署合约。
  5. 模拟部署成功。

模拟调用合约:

  1. 选择已部署的合约。
  2. 选择合约接口store。
  3. 填写参数100。
  4. 发送交易。
  5. 在终端选择交易结果,input字段是合约参数的abi编码,用于调用合约。

7.3. 序列化交易

组装交易结构,并通过API getTransactionBlob将交易结构序列化为。

HTTP请求示例:

curl -d '{
"source_address":"adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd",
"nonce":43,
"fee_limit":10000000000,
"gas_price":1000,
"operations":[
{
"type": 7,
"pay_coin": {
"dest_address": "adxSTD3TB38U6hSXeQiFYtxdmqoYkiJFYioEp",
"amount": 0,
"input": "0x6057361d0000000000000000000000000000000000000000000000000000000000000064"
}
}
]
}' http://{url}/getTransactionBlob

请求参数说明:

字段名类型描述
source_addressString必填,源账户地址,即发起交易的账户。
nonceInt必填,必须为源账户当前的nonce值加1。账户当前nonce值在7.1中获得,根据实际查询的结果填写。
dest_addressString必填,合约地址。
inputString选填,合约接口store调用参数的abi编码。将7.2编码合约参数获得的abi编码填入该字段。

其他交易参数按照示例填写即可,更多交易结构信息参考HTTP接口文档。

成功的返回JSON数据:

{
"error_code" : 0,
"error_desc" : "",
"result" : {
"hash" : "695788504c0365c760dd686862df4f9d8dce7a7e1910e3de35ac968a9f48b75f",
"transaction_blob" : "0a25616478537031583456376858444452424b484c3655323143706250686b693759716a755564102b2277080762730a256164785354443354423338553668535865516946597478646d716f596b694a4659696f45701a4a30783630353733363164303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036343080c8afa02538e807"
}
}

响应参数说明:

字段名类型描述
error_codeInt0表示成功序列化,2表示交易结构参数错误。
transaction_blobString交易序列化之后的16进制表示。

7.4. 签名交易

通过API getSignaturetransaction_blob进行签名。

注意:这种签名方式不安全,会泄露账号私钥,仅用于测试调试使用。生产环境请使用离线交易签名工具,在本地进行签名。

HTTP请求示例:

curl -d '{
"private_key":"privbtBp152KnunKvCBgFQX96zuASSH6FBY9KVTX1bifPCLUWarq9EaN",
"transaction_blob": "0a25616478537031583456376858444452424b484c3655323143706250686b693759716a755564102b2277080762730a256164785354443354423338553668535865516946597478646d716f596b694a4659696f45701a4a30783630353733363164303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036343080c8afa02538e807"
}' http://{url}/getSignature

请求参数说明:

字段名类型描述
private_keyString必填,源账户的私钥。
transaction_blobString必填,交易序列化的16进制表示,3.2节序列化的结果。

成功的返回JSON数据:

{
"error_code" : 0,
"result" : {
"data" : "0a25616478537031583456376858444452424b484c3655323143706250686b693759716a755564102b2277080762730a256164785354443354423338553668535865516946597478646d716f596b694a4659696f45701a4a30783630353733363164303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036343080c8afa02538e807",
"public_key" : "b001ac76f97b0fda145c68e2edf6665c247a292260694b5dfcacac8acb658bd3746e7d8a3032",
"sign_data" : "2fe12a11e1d5b67db204a7a9dc478d335abdd9cae69a51f3d9b95b77610911bef795d8b3feec51fdd42d2dffbcfa3a401bac5ed6ec79ea176aa5f4409a3c1502"
}
}

响应参数说明:

字段名类型描述
dataString交易序列化的16进制表示,即transaction_blob。
public_keyString源账户的公钥。
sign_dataString签名数据。

7.5. 提交交易

通过API submitTransaction将交易提交到链上。

HTTP请求示例:

curl -d '{
"items" : [
{
"transaction_blob" : "0a25616478537031583456376858444452424b484c3655323143706250686b693759716a755564102b2277080762730a256164785354443354423338553668535865516946597478646d716f596b694a4659696f45701a4a30783630353733363164303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303036343080c8afa02538e807",
"signatures" : [
{
"sign_data" : "2fe12a11e1d5b67db204a7a9dc478d335abdd9cae69a51f3d9b95b77610911bef795d8b3feec51fdd42d2dffbcfa3a401bac5ed6ec79ea176aa5f4409a3c1502",
"public_key" : "b001ac76f97b0fda145c68e2edf6665c247a292260694b5dfcacac8acb658bd3746e7d8a3032"
}
]
}
]
}' http://{url}/submitTransaction

请求参数说明:

字段名类型描述
transaction_blobString必填,交易序列化的16进制表示。
sign_dataString必填,交易签名。
public_keyString必填,源账户公钥。

成功的返回JSON数据:

{
"results" : [
{
"error_code" : 0,
"error_desc" : "",
"hash" : "695788504c0365c760dd686862df4f9d8dce7a7e1910e3de35ac968a9f48b75f"
}
],
"success_count" : 1
}

响应参数说明:

字段名类型描述
hashString交易哈希,可通过哈希值查询交易的内容。

7.6. 查询交易

通过API getTransactionHistory查询交易哈希为695788504c0365c760dd686862df4f9d8dce7a7e1910e3de35ac968a9f48b75f的交易内容。

HTTP请求示例:

curl http://{url}/getTransactionHistory?hash=695788504c0365c760dd686862df4f9d8dce7a7e1910e3de35ac968a9f48b75f

请求参数说明:

字段名类型描述
hashString必填,交易哈希。参数取自3.4提交交易的响应结果。

成功的返回JSON数据:

{
"error_code":0,
"result":{
"total_count":1,
"transactions":[
{
"actual_fee":21982000,
"close_time":1710581275771116,
"contract_tx_hashes":[
"95982d22fc062151d59f5855488f8e407297b7af13a3200da0e5227dfc07d98e"
],
"error_code":0,
"error_desc":"[{\"evm_code\":\"0x0\",\"operation_index\":0,\"return\":\"\"}]",
"hash":
"695788504c0365c760dd686862df4f9d8dce7a7e1910e3de35ac968a9f48b75f",
"ledger_seq":32965,
"signatures":[
{
"public_key": "b001ac76f97b0fda145c68e2edf6665c247a292260694b5dfcacac8acb658bd3746e7d8a3032",
"sign_data": "2fe12a11e1d5b67db204a7a9dc478d335abdd9cae69a51f3d9b95b77610911bef795d8b3feec51fdd42d2dffbcfa3a401bac5ed6ec79ea176aa5f4409a3c1502"
}
],
"transaction":{
"fee_limit":10000000000,
"gas_price":1000,
"nonce":43,
"operations":[
{
"pay_coin":{
"dest_address":
"adxSTD3TB38U6hSXeQiFYtxdmqoYkiJFYioEp",
"input": "0x6057361d0000000000000000000000000000000000000000000000000000000000000064"
},
"type":7
}
],
"source_address":"adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd"
},
"tx_size":321
}
]
}
}

7.7. 查询合约事件

在 Solidity 合约中,event 是一种特殊的关键字,用于定义和触发事件。事件是合约中的一种通信机制,用于在合约执行期间发布通知或记录重要的状态变化。事件可以被合约内部的函数调用来触发,并且可以被外部应用程序监听和接收。

  • 事件的定义语法
event EventName(
// 参数列表
// ...
);

本文示例代码中使用了event关键字:

contract Storage {
// 定义事件
event Store(uint256 num);
function store(uint256 num) public {
number = num;
// 触发事件
emit Store(number);
}
}

7.6查询交易响应结果中的contract_tx_hashes字段记录了合约事件的哈希。

通过getTransactionHistory API查询哈希为95982d22fc062151d59f5855488f8e407297b7af13a3200da0e5227dfc07d98e的合约事件

HTTP请求示例:

curl http://{url}/getTransactionHistory?hash=95982d22fc062151d59f5855488f8e407297b7af13a3200da0e5227dfc07d98e

成功的返回JSON数据:

{
"error_code":0,
"result":{
"total_count":1,
"transactions":[
{
"actual_fee":0,
"close_time":1710581275771116,
"error_code":0,
"error_desc":"",
"hash":
"95982d22fc062151d59f5855488f8e407297b7af13a3200da0e5227dfc07d98e",
"ledger_seq":32965,
"transaction":{
"nonce":1,
"operations":[
{
"log":{
"datas":["{\"data\":\"0000000000000000000000000000000000000000000000000000000000000064\",\"topics\":[\"69404ebde4a368ae324ed310becfefc3edfe9e5ebca74464e37ffffd8309a3c1\"]}"
],
"topic": "evmLog_695788504c0365c760dd686862df4f9d8dce7a7e1910e3de35ac968a9f48b75f"
},
"type":8
}
],
"source_address":"adxSTD3TB38U6hSXeQiFYtxdmqoYkiJFYioEp"
},
"trigger":{
"transaction":{
"hash": "695788504c0365c760dd686862df4f9d8dce7a7e1910e3de35ac968a9f48b75f"
}
},
"tx_size":319
}
]
}
}

transactions[0].transaction.operations[0].log记录了事件的内容。data是事件参数的abi编码。

可以通过evmAbiDecode API解码参数,或在Remix IDE中模拟调用接口。

  1. 调用合约store接口。
  2. 交易结果中的logs字段即为事件参数。
[
{
"from": "0x9D7f74d0C41E726EC95884E0e97Fa6129e3b5E99",
"topic": "0x69404ebde4a368ae324ed310becfefc3edfe9e5ebca74464e37ffffd8309a3c1",
"event": "Store",
"args": {
"0": "200",
"num": "200"
}
}
]
字段名类型描述
fromString源账户的以太坊地址。
topicString事件函数的哈希值。
eventString事件名称。
argsJson事件参数。

7.8. 合约返回数据

如果合约函数有返回值,如调用示例合约中的retieve接口:

Remix IDE模拟调用:

  1. 调用retrieve接口。
  2. 执行结果中的decode output即为返回内容。
{
"0": "uint256: 100"
}

8. 地址转换说明

8.1. 地址转换

bubi链上的地址有三种类型:

地址类型描述
原始地址普通账户的地址。如本文中发起部署合约交易的adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd,具有公私钥。
新版地址合约账户地址,前缀adx的编码形式。如本文部署的合约地址adxSTD3TB38U6hSXeQiFYtxdmqoYkiJFYioEp
以太坊地址合约的以太坊地址,在solidity合约中msg.sender返回的是源账户的以太坊地址。合约内通过其他合约的以太坊地址进行合约调用。

通过evmAddressAPI进行地址转换:

参数描述
address原版地址,可以转换到新版地址与以太坊地址
address_v2新版地址,只能转换到以太坊地址,不能转换到原版账号地址,需要通过公钥得到原版账号地址
address_eth以太坊地址,只能转换到新版账号地址,不能转换到原版账号地址,需要通过公钥得到原版账号地址
  • 转换原始地址:

HTTP请求示例:

curl http://{url}/evmAddress?address=adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd

成功的返回JSON数据:

{
"result" : {
"address" : "adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd",
"address_eth" : "0x010685ba7024e96b604d75004f1b845b8f5abe42",
"address_v2" : "adxST8gKZDz4o8QzB5nscv3viaer7D7Tp2nVz"
}
}
  • 转换新版地址

HTTP请求示例:

curl http://{url}/evmAddress?address_v2=adxSTD3TB38U6hSXeQiFYtxdmqoYkiJFYioEp

成功的返回JSON数据:

{
"result" : {
"address" : "",
"address_eth" : "0x01d9d4ec36aea6f402fbb00074939c3a8f133bb0",
"address_v2" : "adxSTD3TB38U6hSXeQiFYtxdmqoYkiJFYioEp"
}
}
  • 转换以太坊地址

HTTP请求示例:

curl http://{url}/evmAddress?address_eth=0x01d9d4ec36aea6f402fbb00074939c3a8f133bb0

成功的返回JSON数据:

{
"result" : {
"address" : "",
"address_eth" : "0x01d9d4ec36aea6f402fbb00074939c3a8f133bb0",
"address_v2" : "adxSTD3TB38U6hSXeQiFYtxdmqoYkiJFYioEp"
}
}

8.2. 合约调用

创建一个合约调用第3节的Storage合约。合约代码如下:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.2 <0.9.0;
// 被调用合约的接口
contract Storage {
function store(uint256 num) public {}
function retrieve() public view returns (uint256){}
}

contract Test {
event Sender(address addr);

function callStore(address _Address, uint num) external {
Storage(_Address).store(num); // 合约名称(合约地址).合约接口(参数);
emit Sender(msg.sender);
}

function callRetrieve(address _Address) external view returns(uint256) {
return Storage(_Address).retrieve();
}
}
  • 按照第6节部署合约的流程进行部署,得到合约账户的地址adxSTbyjgx7NnyMsBCJcUwA8V3DbcrNfMA3No

  • 按照第7节调用合约的流程调用合约的callStore接口将Storage合约中number的值设为123。交易结构如下:

curl -d '{
"source_address":"adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd", // 源账户地址
"nonce":65, // 源账户的nonce加1
"fee_limit":10000000000,
"gas_price":1000,
"operations":[
{
"type": 7,
"pay_coin": {
"dest_address": "adxSTbyjgx7NnyMsBCJcUwA8V3DbcrNfMA3No", // 合约地址
"amount": 0,
"input": "0x462b537c00000000000000000000000001d9d4ec36aea6f402fbb00074939c3a8f133bb0000000000000000000000000000000000000000000000000000000000000007b" // Storage接口参数的abi编码
}
}
]
}' http://{url}/getTransactionBlo

查询交易结果如下:

{
"error_code":0,
"result":{
"total_count":1,
"transactions":[
{
"actual_fee":24414000,
"close_time":1710747118644390,
"contract_tx_hashes":[
"0e93aab8fbdfd4ffc03e3519773e3f13a3c29978a4bd201678800ba768025a43",
"b20d219d1f41187c8440ea85291245d118012b2c1a13be3db62bc7080608a932",
"371c1d2aa74aa6442571c699ed384125229f295dc298b25f661d7ea8bbfdfa9d"
],
"error_code":0,
"error_desc":"[{"evm_code":"0x0","operation_index":0,"return":""}]",
"hash":
"3d9407886607a610e18812a7c4fabb4267c9d8b76a3c8fbda31d145290f05f1a",
"ledger_seq":35738,
"signatures":[
{
"public_key": "b001ac76f97b0fda145c68e2edf6665c247a292260694b5dfcacac8acb658bd3746e7d8a3032",
"sign_data": "b62b740a8c8ed44bda2a1775977141ce47f135f3e31bd5b790c5549ee8ef015c384905dda0309c95931d205b5dff9e35a047a264bbbaaf043e2414011967ae0c"
}
],
"transaction":{
"fee_limit":10000000000,
"gas_price":1000,
"nonce":65,
"operations":[
{
"pay_coin":{
"dest_address":
"adxSTbyjgx7NnyMsBCJcUwA8V3DbcrNfMA3No",
"input": "0x462b537c00000000000000000000000001d9d4ec36aea6f402fbb00074939c3a8f133bb0000000000000000000000000000000000000000000000000000000000000007b"
},
"type":7
}
],
"source_address":"adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd"
},
"tx_size":388
}
]
}
}

contract_tx_hashes第一个哈希是Storage合约中的Store事件的日志。第二个哈希是合约调用的交易记录。第三个哈希是Test合约中的Sender事件的日志,记录的sender为源账户的以太坊地址。

  • 调用Storage合约的retrieve接口查询number的值,交易结果如下:
{
"error_code":0,
"result":{
"total_count":1,
"transactions":[
{
"actual_fee":621000,
"close_time":1710747893794632,
"error_code":0,
"error_desc":"[{\"evm_code\":\"0x000000000000000000000000000000000000000000000000000000000000007b\",\"operation_index\":0,\"return\":\"\"}]",
"hash":
"c2c2928da7477b8582bb0e851bbc7f4587fec962ff37897b778656fcdb8675ea",
"ledger_seq":35752,
"signatures":[
{
"public_key": "b001ac76f97b0fda145c68e2edf6665c247a292260694b5dfcacac8acb658bd3746e7d8a3032",
"sign_data": "075ba53ae24d1c6b921dae9bdfb14b493156181f876d1e912eb4b609450213b687cbccde795249602d0c4a802f4e12e9c5cc39ea212fe60287e14057f1a5830c"
}
],
"transaction":{
"fee_limit":10000000000,
"gas_price":1000,
"nonce":67,
"operations":[
{
"pay_coin":{
"dest_address":
"adxSTD3TB38U6hSXeQiFYtxdmqoYkiJFYioEp",
"input":"0x2e64cec1"
},
"type":7
}
],
"source_address":"adxSp1X4V7hXDDRBKHL6U21CpbPhki7YqjuUd"
},
"tx_size":256
}
]
}
}

根据查询结果可知number的值为123,成功通过Test合约内部调用Storage合约。

8.3. 函数修饰符

在Solidity合约中,函数可以使用以下四种不同的可见性修饰符:external、public、internal和private。

标识符作用
external函数只能被其他合约或外部账户调用,而不能被合约内部其他函数调用,在接收大量数据时更为高效。
public函数既可以被外部账户和其他合约调用,也可以在合约内部的其他函数中调用。
internal函数不能被外部账户或其他合约直接调用,只能在合约内部的其他函数中和继承合约内部调用。
private只能在当前合约内部访问,且不可被继承。