通过 HTTP API 部署与调用智能合约

使用原始 HTTP API 调用部署和调用 TRON 智能合约——这是需要完全控制交易构造时使用的 底层路径。

📘

前置阅读

本文将详细介绍部署与调用 TRON 智能合约的底层原始 HTTP API 接口路径。虽然大多数开发者在日常开发中会使用更高层封装的 SDK 工具(如 TronWeb、TronBox 或 TronIDE),但这些工具在底层最终都会落到下文所列出的这些 API 节点上。当您需要构建自定义的开发工具、从非 JavaScript 环境中集成 TRON 合约,或者需要对交易结构拥有完全的精细控制时,直接调用这些底层 HTTP API 将是最佳选择。

关于高层次的合约部署框架演练,请参阅部署上链快速通道

智能合约部署

部署智能合约的核心逻辑是创建一笔 CreateSmartContract 类型的系统交易。您可以通过调用全节点的 API 接口 wallet/deploycontract 来创建该交易。交易成功构建后,还需要经过私钥签名,方能广播至网络中:

BASE_URL=https://api.shasta.trongrid.io   # 示例——替换为任意 TRON 节点(TronGrid、第三方或自建)
curl --request POST \
     --url ${BASE_URL}/wallet/deploycontract \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '
{
     "owner_address": "41D1E7A6BC354106CB410E65FF8B181C600FF14292",
     "abi": "[{\"constant\":false,\"inputs\":[{\"name\":\"key\",\"type\":\"uint256\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"key\",\"type\":\"uint256\"}],\"name\":\"get\",\"outputs\":[{\"name\":\"value\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]",
     "bytecode": "608060405234801561001057600080fd5b5060de8061001f6000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631ab06ee58114604d5780639507d39a146067575b600080fd5b348015605857600080fd5b506065600435602435608e565b005b348015607257600080fd5b50607c60043560a0565b60408051918252519081900360200190f35b60009182526020829052604090912055565b600090815260208190526040902054905600a165627a7a72305820fdfe832221d60dd582b4526afa20518b98c2e1cb0054653053a844cf265b25040029",
     "fee_limit": 100000000,
     "origin_energy_limit": 100000,
     "name": "SomeContract",
     "call_value": 0,
     "consume_user_resource_percent": 100
}
'

返回的交易构造结果(派生字段已缩写):

{
  "visible": false,
  "txID": "<transaction-id>",
  "contract_address": "<contract-address-hex>",
  "raw_data": {
    "contract": [
      {
        "parameter": {
          "value": {
            "owner_address": "41d1e7a6bc354106cb410e65ff8b181c600ff14292",
            "new_contract": {
              "bytecode": "608060405234801561001057600080fd5b5060de8061001f6000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631ab06ee58114604d5780639507d39a146067575b600080fd5b348015605857600080fd5b506065600435602435608e565b005b348015607257600080fd5b50607c60043560a0565b60408051918252519081900360200190f35b60009182526020829052604090912055565b600090815260208190526040902054905600a165627a7a72305820fdfe832221d60dd582b4526afa20518b98c2e1cb0054653053a844cf265b25040029",
              "consume_user_resource_percent": 100,
              "name": "SomeContract",
              "origin_address": "41d1e7a6bc354106cb410e65ff8b181c600ff14292",
              "abi": {
                "entrys": [
                  {
                    "inputs": [
                      {
                        "name": "key",
                        "type": "uint256"
                      },
                      {
                        "name": "value",
                        "type": "uint256"
                      }
                    ],
                    "name": "set",
                    "stateMutability": "Nonpayable",
                    "type": "Function"
                  },
                  {
                    "outputs": [
                      {
                        "name": "value",
                        "type": "uint256"
                      }
                    ],
                    "constant": true,
                    "inputs": [
                      {
                        "name": "key",
                        "type": "uint256"
                      }
                    ],
                    "name": "get",
                    "stateMutability": "View",
                    "type": "Function"
                  }
                ]
              },
              "origin_energy_limit": 100000
            }
          },
          "type_url": "type.googleapis.com/protocol.CreateSmartContract"
        },
        "type": "CreateSmartContract"
      }
    ],
    "ref_block_bytes": "0a49",
    "ref_block_hash": "975853d6629c8702",
    "expiration": 1652153760000,
    "fee_limit": 100000000,
    "timestamp": 1652153701556
  },
  "raw_data_hex": "<abridged>"
}

示例中的 fee_limit100,000,000 sun(100 TRX),仅作为该测试网示例的费用上限,并不是固定部署成本。部署前应先估算 Energy,通过 wallet/getchainparameters 查询当前 getEnergyFee 完成换算,并确保不超过 getMaxFeeLimit

wallet/deploycontract 只负责构造未签名交易。响应中的 txIDcontract_addressraw_data 不代表合约已经部署成功;客户端仍需签名并调用 wallet/broadcasttransaction。广播后使用 wallet/gettransactioninfobyid 查询 receipt,确认执行成功后,预计算的 contract_address 才是可用的链上合约地址。

虽然 TRON 网络中各类区块链交易的底层交易结构在本质上是完全相同的,但它们的核心区别在于 raw_data 数据体中 contract.parameter.value 字段所携带的具体参数。

在智能合约部署交易中,contract.parameter.value 包含以下核心数据:

  • owner_address —— 交易发起方的账户地址,即该合约的部署方地址。
  • new_contract —— 待部署的智能合约的完整详细配置:
    • origin_address —— 智能合约所有者的账户地址。
    • contract_address —— 系统预分配的智能合约部署地址。
    • abi —— 智能合约的 ABI 接口定义。
    • bytecode —— 编译生成的合约二进制字节码。
    • call_value —— 部署时向合约内充入的原生 TRX 数量。
    • consume_user_resource_percent —— 用户能耗分摊比例,即调用者分摊能量费用的百分比。
    • name —— 智能合约的名称。
    • origin_energy_limit —— 部署者为该合约设定的单次交易代付能量上限,单位为能量(无单位整数,与 fee_limit 的 sun 单位无关)。
  • call_token_value —— 部署时随交易向新合约内注入的 TRC-10 Token数量。
  • token_id —— 注入的 TRC-10 Token对应的唯一数字 ID。

智能合约调用与查询

调用写入方法:triggersmartcontract

调用智能合约中会修改状态的写操作函数,需要创建一笔 TriggerSmartContract 类型的系统交易。您可以通过调用全节点的 API 接口 wallet/triggersmartcontract 来构建此交易。交易创建完成后,同样需要经过本地签名并广播至全网。

BASE_URL=https://api.shasta.trongrid.io   # 示例——替换为任意 TRON 节点(TronGrid、第三方或自建)
curl -X POST ${BASE_URL}/wallet/triggersmartcontract -d '{
"contract_address":"419E62BE7F4F103C36507CB2A753418791B1CDC182",
"function_selector":"transfer(address,uint256)",
"parameter":"00000000000000000000004115208EF33A926919ED270E2FA61367B2DA3753DA0000000000000000000000000000000000000000000000000000000000000032",
"fee_limit":100000000,
"call_value":0,
"owner_address":"41977C20977F412C2A1AA4EF3D49FEE5EC4C31CDFB"
}'

参数详细说明:

  • contract_address —— 目标智能合约的链上地址。
  • owner_address —— 发起此笔调用的账户地址。
  • function_selector —— 合约中待触发的目标函数签名(函数选择器)。
  • parameter —— 经 ABI 编码后的函数入参数据。例如在本例中,该方法需要传入两个编码后的参数(分别对应 addressuint256 类型)。有关如何对参数进行转换,请参阅参数的编码与解码
  • fee_limit —— 调用方该笔交易的能耗预算上限,以 sun 为单位。关于其与实际能量的折算关系,请参阅 FeeLimit 与能量成本管理
  • call_value —— 随该笔调用交易发送给目标智能合约的 TRX 数量。

执行上述命令后,将返回包含待签名交易数据的 JSON 构造结果:

{
	"result": {
		"result": true
	},
	"transaction": {
		"visible": false,
		"txID": "d2ce86097df40287ad45ebc67f0d546ee98c2d7cd7c101e4d4d5b0c8a752d900",
		"raw_data": {
			"contract": [{
				"parameter": {
					"value": {
						"data": "a9059cbb00000000000000000000004115208ef33a926919ed270e2fa61367b2da3753da0000000000000000000000000000000000000000000000000000000000000032",
						"owner_address": "41977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb",
						"contract_address": "419e62be7f4f103c36507cb2a753418791b1cdc182"
					},
					"type_url": "type.googleapis.com/protocol.TriggerSmartContract"
				},
				"type": "TriggerSmartContract"
			}],
			"ref_block_bytes": "1c51",
			"ref_block_hash": "74912b480b7b887c",
			"expiration": 1652169501000,
			"fee_limit": 100000000,
			"timestamp": 1652169442098
		},
		"raw_data_hex": "0a021c51220874912b480b7b887c40c8d2e7e78a305aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a1541977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb1215419e62be7f4f103c36507cb2a753418791b1cdc1822244a9059cbb00000000000000000000004115208ef33a926919ed270e2fa61367b2da3753da000000000000000000000000000000000000000000000000000000000000003270b286e4e78a30900180c2d72f"
	}
}

其中 result.result: true 只表示交易构造和节点预校验成功,不表示合约调用已经执行。必须继续完成本地签名与广播,并通过 wallet/gettransactioninfobyid 检查 receipt,才能判断链上执行是否成功。

合约调用交易中 contract.parameter.value 包含以下内容:

  • owner_address —— 发起调用的账户地址。
  • contract_address —— 目标智能合约的地址。
  • data —— 经过 ABI 规则编码后的完整调用数据:前 4 个字节为函数选择器(由函数签名执行 Keccak-256 哈希后截取前 4 字节所得,用于供虚拟机 TVM 寻址定位对应的方法),后续字节为经填充对齐后的参数列表。有关详细规则,请参阅参数的编码与解码
  • call_value —— 随该交易随附给智能合约的 TRX 数量。
  • token_id —— 随交易附带的 TRC-10 Token ID。
  • call_token_value —— 随交易向目标合约发送的 TRC-10 Token数量。

调用只读方法:triggerconstantcontract

对于智能合约中未修改状态的只读查询方法(即 viewpure 修饰的函数),您可以通过调用全节点的 API 接口 wallet/triggerconstantcontract 进行触发。由于此类调用纯属本地模拟查询,无需在区块链上达成共识,因此无需对其进行交易签名,也不必广播至全网:

BASE_URL=https://api.shasta.trongrid.io   # 示例——替换为任意 TRON 节点(TronGrid、第三方或自建)
curl -X POST ${BASE_URL}/wallet/triggerconstantcontract -d '{
"contract_address":"419E62BE7F4F103C36507CB2A753418791B1CDC182",
"function_selector":"balanceOf(address)",
"parameter":"000000000000000000000041977C20977F412C2A1AA4EF3D49FEE5EC4C31CDFB",
"owner_address":"41977C20977F412C2A1AA4EF3D49FEE5EC4C31CDFB"
}'

参数详细说明:

  • contract_address —— 目标智能合约地址。
  • owner_address —— 发起查询请求的模拟账户地址。
  • function_selector —— 待查询的目标合约函数签名。
  • parameter —— 传入查询函数的 ABI 编码参数。关于如何对参数进行转义,请参阅参数的编码与解码

返回结果:

{
	"result": {
		"result": true
	},
	"constant_result": ["0000000000000000000000000000000000000000000000000000000430e1b700"],
	"transaction": {
		"ret": [{}],
		"visible": false,
		"txID": "7f47212aed2fdab232195feece54fc302bde2ce379e92ffd0d0e95206ce7a3bb",
		"raw_data": {
			"contract": [{
				"parameter": {
					"value": {
						"data": "70a08231000000000000000000000041977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb",
						"owner_address": "41977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb",
						"contract_address": "419e62be7f4f103c36507cb2a753418791b1cdc182"
					},
					"type_url": "type.googleapis.com/protocol.TriggerSmartContract"
				},
				"type": "TriggerSmartContract"
			}],
			"ref_block_bytes": "5ab1",
			"ref_block_hash": "f24f075df912f43e",
			"expiration": 1590382815000,
			"timestamp": 1590382762536
		},
		"raw_data_hex": "0a025ab12208f24f075df912f43e4098cecfd1a42e5a8e01081f1289010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412540a1541977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb1215419e62be7f4f103c36507cb2a753418791b1cdc182222470a08231000000000000000000000041977c20977f412c2a1aa4ef3d49fee5ec4c31cdfb70a8b4ccd1a42e"
	}
}
  • constant_result —— 合约函数的只读查询结果列表。本例中返回的值为原始十六进制格式,代表 uint256 类型的余额。有关如何将此十六进制解码为十进制数值,请参阅参数的编码与解码

使用 data 字段调用

除了直接输入函数选择器和参数外,您还可以严格按照 Solidity 的 ABI 编码规范,将函数选择器与其入参编码拼装为一个完整的十六进制大字符串,并将其直接作为 data 字段传入。

以调用一个标准的 TRC-20 合约中的转账函数 transfer 为例,其标准的函数签名为 transfer(address,uint256)

假设我们需要向接收方地址 TJRabPrwbZy45sbavfcjinPJC18kjpRTv8 转账 100 单位的Token:

  1. 确定函数选择器 —— 对 transfer(address,uint256) 函数签名字符串执行 Keccak-256 哈希计算,取哈希值的前 4 个字节。计算结果为 a9059cbb
  2. 进行参数编码
    • 目标地址 TJRabPrwbZy45sbavfcjinPJC18kjpRTv8:首先转换为底层以 41 开头的 21 字节十六进制格式(415cbdd86a2fa8dc4bddd8a8f69dba48572eec07fb),然后在其高位(左侧)补 11 字节零以对齐至 32 字节。
    • 转账数量 100:转换为十六进制值 64,并在高位补零以对齐至 32 字节。
  3. 拼装数据体 —— 将上述计算所得的函数选择器、补零对齐后的地址参数、补零对齐后的Token数量参数,顺次连接拼接在一起,即可组成最终的 data 属性值:

a9059cbb0000000000000000000000415cbdd86a2fa8dc4bddd8a8f69dba48572eec07fb0000000000000000000000000000000000000000000000000000000000000064

完整调用:

BASE_URL=https://api.shasta.trongrid.io   # 示例——替换为任意 TRON 节点(TronGrid、第三方或自建)
curl --request POST \
     --url ${BASE_URL}/wallet/triggersmartcontract \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "owner_address": "TZ4UXDV5ZhNW7fb2AMSbgfAEZ7hWsnYS2g",
  "contract_address": "TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs",
  "data": "a9059cbb0000000000000000000000415cbdd86a2fa8dc4bddd8a8f69dba48572eec07fb0000000000000000000000000000000000000000000000000000000000000064",
  "fee_limit": 1000000000,
  "call_value": 0,
  "visible": true
}
'

返回结果:

{
	"result": {
		"result": true
	},
	"transaction": {
		"visible": true,
		"txID": "e33c025b615a5125c8a28ec7e012a8b880c5d855f010c07dca45cb2d40609b82",
		"raw_data": {
			"contract": [{
				"parameter": {
					"value": {
						"data": "a9059cbb0000000000000000000000415cbdd86a2fa8dc4bddd8a8f69dba48572eec07fb0000000000000000000000000000000000000000000000000000000000000064",
						"owner_address": "TZ4UXDV5ZhNW7fb2AMSbgfAEZ7hWsnYS2g",
						"contract_address": "TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs"
					},
					"type_url": "type.googleapis.com/protocol.TriggerSmartContract"
				},
				"type": "TriggerSmartContract"
			}],
			"ref_block_bytes": "8e6a",
			"ref_block_hash": "9858ac3fec3262ff",
			"expiration": 1747130115000,
			"fee_limit": 1000000000,
			"timestamp": 1747130056923
		},
		"raw_data_hex": "0a028e6a22089858ac3fec3262ff40b8c7c7c8ec325aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a1541fd49eda0f23ff7ec1d03b52c3a45991c24cd440e12154142a1e39aefa49290f2b3f9ed688d7cecf86cd6e02244a9059cbb0000000000000000000000415cbdd86a2fa8dc4bddd8a8f69dba48572eec07fb000000000000000000000000000000000000000000000000000000000000006470db81c4c8ec3290018094ebdc03"
	}
}

相关资源