解析solidity的event log
阿新 • • 發佈:2018-12-14
參考文件。
例子程式碼如下:
pragma solidity ^0.4.25; contract Assert{ } contract TestReturn { Assert ast; event CreateAssertAll(Assert indexed _sig,uint256 indexed id); event CreateAssertOne(Assert indexed _sig,uint256 id); event Create(Assert _sig,uint256 id); function check() public returns(uint256) { ast = new Assert(); emit CreateAssertAll(ast,uint256(6)); emit CreateAssertOne(ast,uint256(6)); emit Create(ast,uint256(6)); } }
上面的程式碼中,有3個event。他們的index不同。生成的log資料結構不一樣。
- CreateAssertAll全部是index。
- CreateAssertOne有一個是idnex。
- Create全部都不是index。
我在ropsten上呼叫了這個方法。hash如下:
https://ropsten.etherscan.io/tx/0x12e3384bdba97c631bbaa5df27e94e6baeb9ee894ee80c7d9ce0e1b9944b70d7
可以檢視生成的event:
https://ropsten.etherscan.io/address/0x92e22427412dc8705b69c2db1b702d51586018f5#events
使用web3檢視日誌。
const Web3 = require('web3'); const web3 = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io/XXX")); const SolidityCoder = require("web3/lib/solidity/coder.js"); web3.eth.getTransactionReceipt("0x12e3384bdba97c631bbaa5df27e94e6baeb9ee894ee80c7d9ce0e1b9944b70d7",function(error, result){ if(!error){ // console.log("receipt ==== ",result); let logs = result.logs; console.log("logs ==== ",logs); let data = SolidityCoder.decodeParams(["address", "uint256"], logs[2].data.replace("0x", "")); console.log("data ==== ",data); } else console.error(error); });
可以看到列印日下:
logs ==== [ { address: '0x92e22427412dc8705b69c2db1b702d51586018f5',
blockHash: '0x06cf0bd459caa91c9fd13a7b65875d300942648a975bf282813c4e1596258192',
blockNumber: 4381899,
data: '0x',
logIndex: 3,
removed: false,
topics:
[ '0xd39437daf43d90c2fc7f92c178818776f8ae6c1e6bde3215fa60b27756797d17',
'0x00000000000000000000000029f65c9a6f016ad76f5a26896343d3731267cc36',
'0x0000000000000000000000000000000000000000000000000000000000000006' ],
transactionHash: '0x12e3384bdba97c631bbaa5df27e94e6baeb9ee894ee80c7d9ce0e1b9944b70d7',
transactionIndex: 20 },
{ address: '0x92e22427412dc8705b69c2db1b702d51586018f5',
blockHash: '0x06cf0bd459caa91c9fd13a7b65875d300942648a975bf282813c4e1596258192',
blockNumber: 4381899,
data: '0x0000000000000000000000000000000000000000000000000000000000000006',
logIndex: 4,
removed: false,
topics:
[ '0xef0d7493287e1bf143771073deb917ba8ae1b8503a98a3d6d490d058e81d67ea',
'0x00000000000000000000000029f65c9a6f016ad76f5a26896343d3731267cc36' ],
transactionHash: '0x12e3384bdba97c631bbaa5df27e94e6baeb9ee894ee80c7d9ce0e1b9944b70d7',
transactionIndex: 20 },
{ address: '0x92e22427412dc8705b69c2db1b702d51586018f5',
blockHash: '0x06cf0bd459caa91c9fd13a7b65875d300942648a975bf282813c4e1596258192',
blockNumber: 4381899,
data: '0x00000000000000000000000029f65c9a6f016ad76f5a26896343d3731267cc360000000000000000000000000000000000000000000000000000000000000006',
logIndex: 5,
removed: false,
topics:
[ '0xcc9018de05b5f497ee7618d8830568d8ac2d45d0671b73d8f71c67e824122ec7' ],
transactionHash: '0x12e3384bdba97c631bbaa5df27e94e6baeb9ee894ee80c7d9ce0e1b9944b70d7',
transactionIndex: 20 } ]
data ==== [ '0x29f65c9a6f016ad76f5a26896343d3731267cc36',
BigNumber { s: 1, e: 0, c: [ 6 ] } ]
分析日誌可以知道。
- 一共生成了3個日誌。
- topics的第一個值topics[0]是sha3(event名字(引數1型別,引數2型別))
- 引數內容:如果event的引數是index,那就會在topics的值中。如果不是index,那就會在data中。
比較方便的解析方式:
let abi = "";
let SolidityEvent = require("web3/lib/web3/event.js");
let logParser = (logs, abi) => {
// pattern similar to lib/web3/contract.js: addEventsToContract()
let decoders = abi.filter(function (json) {
return json.type === 'event';
}).map(function(json) {
// note first and third params required only by enocde and execute;
// so don't call those!
return new SolidityEvent(null, json, null);
});
return logs.map(function (log) {
return decoders.find(function(decoder) {
return (decoder.signature() == log.topics[0].replace("0x",""));
}).decode(log);
})
};
web3.eth.getTransactionReceipt("0x12e3384bdba97c631bbaa5df27e94e6baeb9ee894ee80c7d9ce0e1b9944b70d7",function(error, result){
if(!error){
// console.log("receipt ==== ",result);
let logs = result.logs;
let events = logParser(logs,JSON.parse(abi));
console.log("logParser === ",events)
}
else
console.error(error);
});