Ruby on Rails区块链项目运行异常:测试余额获取与合约部署验证
环境版本说明
- Geth(控制台访问工具):
1.9.21-stable - Solidity(终端编译工具):
0.4.26+commit.4563c3fc.Darwin.appleclang - Parity(RPC连接工具):
Parity-Ethereum/v2.7.2-stable-d961010f63-20200205/x86_64-apple-darwin/rustc1.41.0 - 浏览器钱包:MetaMask扩展
问题重现
我通过MetaMask创建了测试网账户,并用这条命令导入到本地系统:
geth account import --datadir "account address" --password "password" "pvt key"
但进入geth console --testnet 2>>geth.log控制台后,执行eth.accounts[0]查到余额是0ETH,可MetaMask截图显示账户有4.9962 ETH。
同时,我用以下Solidity合约(greeter.sol):
pragma solidity ^0.4.2; contract mortal { /* Define variable owner of the type address*/ address owner; /* this function is executed at initialization and sets the owner of the contract */ function mortal() { owner = msg.sender; } /* Function to recover the funds on the contract */ function kill() { if (msg.sender == owner) selfdestruct(owner); } } contract greeter is mortal { /* define variable greeting of the type string */ string greeting; /* this runs when the contract is executed */ function greeter(string _greeting) public { greeting = _greeting; } /* main function */ function greet() constant returns (string) { return greeting; } }
搭配Ruby部署代码:
@contract = Ethereum::Contract.create(file: "#{Dir.pwd}/contracts/greeter.sol") @tx = @contract.deploy("Hello") @link = "https://testnet.etherscan.io/tx/#{@tx}"
每次运行都会报错:IOError: "Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 1000000 and got: 0."
下面针对你提出的两个问题给出具体解决方案:
1. 如何获取测试用ETH完成交易与合约创建?
先解决你“MetaMask有余额但geth查不到”的矛盾,再讲如何获取测试ETH:
先排查余额显示不一致的问题
- 检查geth测试网同步状态:进入geth控制台后执行
eth.syncing,如果返回true,说明本地节点还在同步区块,得等同步完成才能查到最新余额。如果同步太慢,建议直接用远程节点代替本地节点,省掉同步的麻烦。 - 确认账户导入是否正确:执行
geth --testnet account list,看看列出的地址和MetaMask里的是否一致。如果不一致,说明你导入时的--datadir路径错了——geth会把账户存在指定目录的keystore文件夹里,建议直接省略--datadir用默认路径重新导入,避免路径配置失误。
获取测试ETH(水龙头)
如果确实账户没余额,就去对应测试网的水龙头申请:
- 如果你用的是Goerli、Ropsten这类常见测试网,都有公开的水龙头,提交你的账户地址就能领到测试ETH。
重点注意:一定要确保MetaMask和geth连接的是同一个测试网,不同测试网的ETH不互通,比如你MetaMask在Goerli,geth连的是Ropsten,那肯定查不到余额。
2. 如何验证交易与合约部署是否成功?
当你成功发送交易后,可以通过这几种方式验证:
方式1:用geth控制台验证
- 查交易是否被打包:拿到交易哈希(Ruby代码里的
@tx),在控制台执行eth.getTransaction("你的交易哈希"),如果返回的对象里blockNumber不是null,说明交易已经上链。 - 获取合约地址:交易打包后,执行
eth.getTransactionReceipt("你的交易哈希"),结果里的contractAddress就是部署好的合约地址(仅限合约部署交易)。 - 调用合约方法测试:加载合约ABI(可以用
solc greeter.sol --abi编译得到),然后调用方法:
var abi = [/* 你的合约ABI数组 */]; var greeter = eth.contract(abi).at("合约地址"); greeter.greet()
如果返回"Hello",说明合约部署成功且能正常工作。
方式2:用Parity RPC验证
你用了Parity的8584端口RPC,可以发POST请求到http://localhost:8584验证:
{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["你的交易哈希"],"id":1}
如果返回结果里的status是"0x1",代表交易执行成功。
方式3:用Ruby代码直接交互验证
部署完成后,在Ruby里调用合约方法:
greeter = @contract.at(@tx.receipt['contractAddress']) puts greeter.greet.call
如果输出Hello,就说明合约已经成功部署并可以正常交互。
内容的提问来源于stack exchange,提问作者Ashish

