Hedera-sdk-py智能合约部署与查询相关技术问询
Hedera SDK Python版智能合约开发常见问题解答
1. stateful.json是不是编译后的Solidity合约?
不是直接的合约字节码,它是Solidity合约经过编译器编译后生成的标准JSON输出文件,里面包含了合约的十六进制字节码(object字段)、ABI、调试信息等完整编译产物。示例代码里正是提取了stateful_json['object']字段的内容,编码后用来部署到Hedera链上。
2. 怎么把自己的.sol合约转换成这种JSON格式?
可以用Solidity官方编译器solc或者Hardhat、Truffle这类开发框架生成:
方法一:用solc命令行生成
- 创建编译配置文件(比如
input.json):
{ "language": "Solidity", "sources": { "YourContract.sol": { "urls": ["YourContract.sol"] } }, "settings": { "outputSelection": { "*": { "*": ["*"] } } } }
- 执行编译命令生成标准JSON输出:
solc --standard-json input.json > YourContract.json
生成的YourContract.json就和stateful.json格式一致。
方法二:用Hardhat框架生成
- 初始化Hardhat项目后,将你的.sol合约放到
contracts目录下。 - 执行
npx hardhat compile,编译后的JSON文件会存放在artifacts/contracts/目录下,直接即可使用。
3. 部署后如何在合约中存储数据?
核心是通过合约的写函数修改链上状态,结合Hedera SDK的ContractExecuteTransaction触发交易,用ContractCallQuery读取状态,示例代码已给出完整流程:
前提:合约需包含状态变量和读写函数
对应的Solidity合约示例:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract StatefulContract { string public message; constructor(string memory initialMessage) { message = initialMessage; } function set_message(string memory newMessage) public { message = newMessage; } function get_message() public view returns (string memory) { return message; } }
存储数据的具体步骤
- 修改状态(存数据):用
ContractExecuteTransaction调用合约的写函数(比如set_message),这会向Hedera链发送交易、消耗gas,交易确认后链上状态更新。对应示例代码片段:
resp = (ContractExecuteTransaction() .setGas(200_000) .setContractId(contractId) .setFunction("set_message", ContractFunctionParameters().addString("hello from hedera again!") ) .setMaxTransactionFee(Hbar(2)) .execute(client)) receipt = resp.getReceipt(client)
- 读取状态(取数据):用
ContractCallQuery调用合约的读函数(比如get_message),这是查询操作,不会修改链上状态,仅需支付少量查询费用。对应示例代码片段:
result = (ContractCallQuery() .setGas(50000) .setContractId(contractId) .setFunction("get_message") .setQueryPayment(Hbar(1)) .execute(client)) message = result.getString(0)
完整示例代码
import os import json from hedera import ( Hbar, FileCreateTransaction, ContractCreateTransaction, ContractCallQuery, ContractExecuteTransaction, ContractFunctionParameters, ) from get_client import client, OPERATOR_KEY client.setMaxTransactionFee(Hbar(100)) client.setMaxQueryPayment(Hbar(10)) cur_dir = os.path.abspath(os.path.dirname(__file__)) jsonf = open(os.path.join(cur_dir, "stateful.json")) stateful_json = json.load(jsonf) jsonf.close() byteCode = stateful_json['object'].encode() tran = FileCreateTransaction() resp = tran.setKeys(OPERATOR_KEY ).setContents(byteCode ).execute(client) fileId = resp.getReceipt(client).fileId print("contract bytecode file: ", fileId.toString()) tran = ContractCreateTransaction() resp = tran.setGas(500_000 ).setBytecodeFileId(fileId ).setConstructorParameters( ContractFunctionParameters().addString("hello from hedera!") ).execute(client) contractId = resp.getReceipt(client).contractId print("new contract id: ", contractId.toString()) # 600 < gas fee < 1000 result = (ContractCallQuery() .setGas(50000) .setContractId(contractId) .setFunction("get_message") .setQueryPayment(Hbar(1)) .execute(client)) if result.errorMessage: exit("error calling contract: ", result.errorMessage) message = result.getString(0) print("contract returned message: ", message) resp = (ContractExecuteTransaction() .setGas(200_000) .setContractId(contractId) .setFunction("set_message", ContractFunctionParameters().addString("hello from hedera again!") ) .setMaxTransactionFee(Hbar(2)) .execute(client)) # if this doesn't throw, then we know the contract executed successfully receipt = resp.getReceipt(client) # now query contract result = (ContractCallQuery() .setGas(50000) .setContractId(contractId) .setFunction("get_message") .setQueryPayment(Hbar(1)) .execute(client)) if result.errorMessage: exit("error calling contract: ", result.errorMessage) message = result.getString(0) print("contract returned message: ", message)
内容的提问来源于stack exchange,提问作者mev
相关产品推荐
相关产品推荐

