当前位置:   article > 正文

web3j采用call方式查询智能合约执行结果

web3j采用call方式查询智能合约执行结果

 

 

以太坊在调用智能合约中的函数时,即使交易成功发布到区块链上,但是如果合约参数检查出错,交易执行会失败,这个时候调用端仍然能够查询到交易被打包,但是交易执行结果跟期望的会不相符。

假设一个智能合约中有一个transfer函数:

  1. function transfer(address to, uint256 val) public view returns(bool) {
  2. require (msg.sender==owner);//only contract owner can call this function
  3. assert (val>0 && this.balance>=val);
  4. to.transfer(val);
  5. Award(to,val);
  6. return true;
  7. }

transfer函数中用require检查了参数,如果调用者不是合约发布者owner,或者合约的账户余额小于转账额度,都会抛出异常,导致交易区块链上回滚。

现在我这测试链上contract合约是由账户1发布的。如果让账户0来调用该合约给账户2转账10 ether,看一下区块链会发生什么情况:

  1. > contract.transfer.sendTransaction(eth.accounts[2],web3.toWei(10,"ether"),{from:eth.coinbase})
  2. INFO [08-15|17:16:11.230] Submitted transaction fullhash=0x6b87baddbf25edd4bf0d08a47a6f30a7811aba80ec4b1be248369b61983aece4 recipient=0xC14E589990F7e6F7cD4beDdb073716f66bbd254b
  3. "0x6b87baddbf25edd4bf0d08a47a6f30a7811aba80ec4b1be248369b61983aece4"
  4. INFO [08-15|17:16:11.230] evm run error err="invalid opcode 0xfd"
  5. INFO [08-15|17:16:11.230] VM returned with error err="invalid opcode 0xfd"
  6. > miner.start()
  7. INFO [08-15|17:16:21.585] Updated mining threads threads=0
  8. INFO [08-15|17:16:21.585] Transaction pool price threshold updated price=12000000000000
  9. INFO [08-15|17:16:21.585] Starting mining operation
  10. INFO [08-15|17:16:23.732]

查询交易:

  1. > eth.getTransaction("0x6b87baddbf25edd4bf0d08a47a6f30a7811aba80ec4b1be248369b61983aece4")
  2. {
  3. blockHash: "0x6b0b9d2afc7a575d98cd9ba5a6f8573cb63a39dd5213c2b91fc6efb1ce5d42cb",
  4. blockNumber: 8,
  5. from: "0xe0d268886b753fd1778b3698956726c3dbf5d9a4",
  6. gas: 90000,
  7. gasPrice: 100000000000,
  8. hash: "0x6b87baddbf25edd4bf0d08a47a6f30a7811aba80ec4b1be248369b61983aece4",
  9. input: "0xa9059cbb00000000000000000000000041111c21df363759fa47fabf530508369c0463190000000000000000000000000000000000000000000000008ac7230489e80000",
  10. nonce: 4,
  11. r: "0x1c0b64699e19f83af21119c47aa553bfcd74d3bffbf59f6ac8c7bef351efab5f",
  12. s: "0x6b3dffc583e4a33ccf4edd6c0a766d8f0b29c8ee98ff8688e2722924a82569ec",
  13. to: "0xc14e589990f7e6f7cd4beddb073716f66bbd254b",
  14. transactionIndex: 0,
  15. v: "0x10a",
  16. value: 0
  17. }
  18. >

可以看到交易被打包到高度为8的区块中了,但是账户2收到10 ether了没有?查询账户2余额:

  1. > eth.getBalance(eth.accounts[2])
  2. 0

可以看到合约交易虽然被打包,但是合约函数执行结果没效果。这个时候程序端是很难监控到合约执行效果的。由于合约函数调用时参数错误导致合约执行失败,区块链是不会返回错误给调用端的。可以采用call调用的方式来查询合约函数执行结果:

  1. > contract.transfer(eth.accounts[1],web3.toWei(10,"ether"),{from:eth.coinbase})
  2. INFO [08-16|11:06:50.363] evm run error err="invalid opcode 0xfd"
  3. INFO [08-16|11:06:50.363] VM returned with error err="invalid opcode 0xfd"
  4. false
  5. > contract.transfer(eth.accounts[1],web3.toWei(10,"ether"),{from:eth.accounts[1]})
  6. true
  7. >

采用call查询智能合约的transfer函数执行能不能成功,第一次使用eth.coinbase来调用合约,发现返回false。第二次使用合约的发布账户eth.accounts[1]来调用,这回返回true,说明这样能够调用成功。使用call方式只是查询区块链,但是并不会向区块链提交交易。

web3j里面实现call查询方式是:

  1. public boolean querryTransfer(String to, BigInteger val, String from, String contractAddress) throws Exception
  2. {
  3. List<Type> inputParameters = new ArrayList<>();
  4. inputParameters.add(new Address(to));
  5. inputParameters.add(new Uint256(val));
  6. Function function = new Function("transfer",
  7. inputParameters,
  8. Collections.<TypeReference<?>>emptyList());
  9. String encodedFunction = FunctionEncoder.encode(function);
  10. org.web3j.protocol.core.methods.response.EthCall response = ethClient.ethCall(
  11. Transaction.createEthCallTransaction(from, contractAddress, encodedFunction),
  12. DefaultBlockParameterName.LATEST)
  13. .sendAsync().get();
  14. if(response.getValue().equals("0x"))
  15. return false;
  16. return true;
  17. }

当函数返回false,说明合约函数调用会失败,这个时候需要检查相关参数。当函数返回true,则可以调用正式的合约函数调用去向区块链发起合约调用的交易。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/574625
推荐阅读
相关标签
  

闽ICP备14008679号