最近在用java调用solidity智能合约方法的时候,遇到了方法Log解析的问题。
正常在调用合约后,如果该合约有event时间,那么执行结果会返回对应的log日志,但是返回的log日志是0x开头的16进制字符串,不是我们需要的string、bool等类型的数据。因此我们需要把hex转换成合约对应返回的数据类型。
如下,合约log返回的data信息;
0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001344442d3230323032393330303030303030303100000000000000000000000000
而我们想要的信息是这样的(如下),可以用Hex字符串工具转换成对应的ASCII码(直接转码,有我们想要的结果,但是也会出现大量乱码)。
DD-2020293000000001
而现实中我们得到的数据是这样的
如何得到正确的解析结果呢?下面直接上代码。
解析方法
第一步,需要引入web3j库
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.5.18</version>
</dependency>
第二步,根据合约代码定义Event对象
合约event事件
event LogOnlyCode(string result);
根据event事件构造对应的java对象
Event evet = new Event("LogOnlyCode",Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
将返回结果从合约调用的log中解析出来
TransactionReceipt transaction = hzwqContract.onlyCode(year, type).send();
List<Log> logs = transaction.getLogs();
Log log = logs.get(0);
Event evet = new Event("LogOnlyCode",Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
List<Type> result = FunctionReturnDecoder.decode(log.getData(),evet.getNonIndexedParameters());
onlyCode = String.valueOf(result.get(0));
System.out.println(onlyCode);
最终打印我们想要的结果。
solidity合约对返回的log日志做了特殊的编码处理,所以在解释的时候,需要把Hex的源数据data与event事件对应的参数类型列表,都传入web3j中FunctionReturnDecoder.decode(rawData,List<TypeReference<Type>>),解析器会根据事件参数去解析源数据,并得到预期的结果。