以太坊SimpleStorage合约get()函数始终返回零,求技术排查与解决方法
嘿,我之前在开发Go绑定以太坊合约的时候也碰到过一模一样的问题——调用get()始终返回0,折腾了好一会儿才找到原因,给你梳理几个最可能的排查方向:
首先先确认你的合约代码和Go绑定的基础部分是对的:
你的Solidity合约代码:
pragma solidity ^0.4.4; contract SimpleStorage { uint storedData; function set(uint x) public { storedData = x; } function get() public constant returns (uint) { return storedData; } }
Go绑定中Set是付费mutator交易的绑定,这部分是符合预期的,因为set()是修改合约状态的写操作。
接下来逐一排查问题:
务必等set()交易被链上确认后再调用get()
set()是会修改链上状态的交易,不是即时生效的只读调用。你调用完set()后,得等这个交易被矿工打包进区块(至少1个确认)才能读取到更新后的值。如果刚调用完set()就立刻调用get(),读取的还是交易生效前的默认值0。可以通过查询交易哈希的状态,或者等待几秒钟再尝试调用get()。检查Go代码中合约实例的地址是否正确
如果你部署合约后拿到的地址和Go代码中初始化合约实例时用的地址不一致,那你读取的根本不是你调用set()的那个合约实例——新部署的合约storedData默认就是0。一定要对比部署合约时返回的地址和代码里传入的地址完全一致。确保调用get()和set()用的是同一个网络
比如你在测试网部署了合约并调用了set(),但你的Go程序连接的是本地私链或者主网节点,那肯定读不到测试网上的数据。检查你的以太坊节点连接配置,确保网络环境统一。验证Go代码中get()的调用方式是否正确
get()是constant标记的只读方法,在Go绑定中应该用只读调用的方式(CallOpts),而不能像set()那样用交易(TransactOpts)。如果误用了交易方式调用get(),不仅会浪费gas,还不会读取到正确的合约状态。你可以查看bindings/SimpleStorage.go中Get()方法的实现,确保它是用Call而不是Transact来执行的。确认set()交易确实成功执行
有时候调用set()可能因为gas不足、参数格式错误、账号余额不够等原因导致交易失败,这时候storedData还是默认的0。你可以通过查询交易收据的status字段(成功为1),或者查看交易的详细信息,确认set()确实成功修改了合约状态。
内容的提问来源于stack exchange,提问作者quanta

