web3.py调用合约transact触发ContractLogicError执行回退问题求解
错误原因
核心问题出在Owner合约的权限初始化逻辑:
- 你定义的
Owned()是普通公共函数,不是合约构造函数,合约部署时不会自动执行,导致fileowner变量的初始值为零地址0x0000000000000000000000000000000000000000 upload函数携带onlyOwner修饰符,会校验交易发起者地址是否等于fileowner,你用Ganache账户调用时,地址和零地址不匹配,require校验失败触发交易回滚,就是你遇到的报错- Remix测试正常是因为你部署后手动调用了
Owned()函数完成了初始化,而Python部署流程中没有这一步
解决方案
两种可选方案,任选一种即可:
方案1:修改合约逻辑,用构造函数自动完成初始化
修改smartcontract.sol的Owner合约代码,把Owned()函数替换为构造函数,部署时会自动执行初始化:
contract Owner { address public fileowner; // 替换原有Owned()函数为构造函数,部署时自动执行 constructor() { fileowner = msg.sender; } // 其余原有代码保持不变 modifier onlyOwner { require(msg.sender == fileowner); _; } function transferOwnership(address newOwner) public onlyOwner { fileowner = newOwner; } function getOwner() public view returns (address) { return fileowner; } }
修改后重新编译部署合约即可,部署时会自动把部署者地址设为fileowner,权限校验可正常通过。
方案2:不修改合约,在Python部署流程中增加初始化调用
在Owner_contract.py的deploy函数末尾,新增对Owned()函数的调用,手动完成初始化:
def deploy(contract_file, contract_name): # 原有部署逻辑保持不变 compiled_sol = compile_files([contract_file]) interface = compiled_sol['{}:{}'.format(contract_file, contract_name)] contract = w3.eth.contract(abi=interface['abi'], bytecode='0x'+interface['bin'], bytecode_runtime=interface['bin-runtime']) tx_hash = contract.constructor(transaction={'from':w3.eth.accounts[0]}).transact() logger.info(f'Owner_tx_hash: {tx_hash}') tx_receipt = w3.eth.getTransactionReceipt(tx_hash) logger.info(f'Owner_tx_receipt: {tx_receipt}') contract_address = tx_receipt['contractAddress'] logger.info(f'Owner_contract_address: {contract_address}') contract_instance = contract(contract_address) logger.info(f'Owner_contract_instance: {contract_instance}') # 新增以下行,手动调用Owned完成权限初始化 contract_instance.functions.Owned().transact() return contract_instance
验证方法
部署完成后先调用getOwner()接口查看返回值,如果返回的是你部署用的Ganache第一个账户地址,说明初始化成功,再调用upload接口就不会触发回滚报错。
内容的提问来源于stack exchange,提问作者user11278217
相关产品推荐
相关产品推荐

