blockchain - web3 - solidity event log
访问量: 713
refer to: https://ethereum.stackexchange.com/questions/16313/how-can-i-view-event-logs-for-an-ethereum-contract
https://medium.com/mycrypto/understanding-event-logs-on-the-ethereum-blockchain-f4ae7ba50378
EventLog 是EVM的重要部分,可以认为是:
1. 传统的log 用来debug
2. (主动通知作用:)作为solidity 函数的return结果(return是返回值给 其他function, event log则是传到链下)
可以使用 get 或者 watch
1. watch: 监听未来要发生的
2. get: 监听之前所有发生过的event log
3. 在某个tx的response中,就可以看出log.
例子: (truffle 项目)
假设我们有下面的这个contract:
$ cat contracts/TestEvent.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract TestEvent { string message; uint256 amount; event HiEvent(string message, uint256 amount); constructor(string memory _message) { message = _message; } function sayHi(uint256 _amount) public { amount = _amount; emit HiEvent(message, amount); } }
然后,调用方法如下:
$ cat callTestEvent.js // contract 地址要有 const CONTRACT_ADDRESS = "0x6FCa9C7EDF4898cF8F0D48E60E1CcB51660505e6" // abi 要有 const contractJson = require('./build/contracts/TestEvent.json') module.exports = async function (callback) { // web3 是Truffle的自动引入的对象 const contract = new web3.eth.Contract( contractJson.abi, CONTRACT_ADDRESS ); // 获得 network , 这个是根据参数传入的 const network = await web3.eth.net.getNetworkType() // TODO 这里最最关键。 // 生成一个tx, 该tx是调用了 mintNFT产生的 //const tx = contract.methods.mint() const tx = contract.methods.sayHi(44) // 发送! const receipt = await tx .send({ from: (await web3.eth.getAccounts())[0],// 使用了HD wallet中的第一个account gas: await tx.estimateGas(), }) .on('transactionHash', (txhash) => { console.log(`Mining transaction ... network: ${network}, tx: ${txhash}`) // console.log(`https://${network}.etherscan.io/tx/${txhash}`) }) .on('error', function(error){ console.error(`An error happened: ${error}`) callback() }) .then(function(receipt){ // Success, you've minted the NFT. The transaction is now on chain! console.log( `Success: The NFT has been minted and mined in block ${receipt.blockNumber}`) callback() }) }
我是在本地使用了ganache网络, 所以运行命令如下:
$ truffle exec callTestEvent.js --network=ganache Using network 'ganache'. Mining transaction ... network: private, tx: 0x6411ad8e0fc691448861eb446a52fe9a30c784376fc9178451fb842aa0fd9bc6 Success: The NFT has been minted and mined in block 65
点击就可以看到详情了:
看一下如何在 js 中监听这个event :
通过 events.HiEvent.returnValues.message 就可以看到了。
// contract 地址要有 const CONTRACT_ADDRESS = "0x6FCa9C7EDF4898cF8F0D48E60E1CcB51660505e6" // abi 要有 const contractJson = require('./build/contracts/TestEvent.json') module.exports = async function (callback) { // web3 是Truffle的自动引入的对象 const contract = new web3.eth.Contract( contractJson.abi, CONTRACT_ADDRESS ); // 获得 network , 这个是根据参数传入的 const network = await web3.eth.net.getNetworkType() // TODO 这里最最关键。 // 生成一个tx, 该tx是调用了 mintNFT产生的 //const tx = contract.methods.mint() const tx = contract.methods.sayHi(77) // 发送! const receipt = await tx .send({ from: (await web3.eth.getAccounts())[0],// 使用了HD wallet中的第一个account gas: await tx.estimateGas(), }) .on('transactionHash', (txhash) => { console.log(`Mining transaction ... network: ${network}, tx: ${txhash}`) // console.log(`https://${network}.etherscan.io/tx/${txhash}`) }) .on('error', function(error){ console.error(`An error happened: ${error}`) callback() }) .then(function(receipt){ console.log('====== total: ') console.log(receipt) console.log('====== events.HiEvent: ', receipt.events.HiEvent) console.log('====== events.HiEvent.returnValues: ', receipt.events.HiEvent.returnValues) console.log('====== events.HiEvent.returnValues.message: ', receipt.events.HiEvent.returnValues.message) console.log('====== events.HiEvent.returnValues.amount: ', receipt.events.HiEvent.returnValues.amount) // Success, you've minted the NFT. The transaction is now on chain! console.log( `Success: The NFT has been minted and mined in block ${receipt.blockNumber}`) callback() })
结果为:
====== events.HiEvent: { logIndex: 0, transactionIndex: 0, transactionHash: '0x17a3f26aa9814465eb8ea5390552ee91e51134217fa4f070d2ff6389e9428918', blockHash: '0x5b4d306a6aa256dda472cf2b7e0c17ee24d49b19cae3f82d2405169bb8ba6c6e', blockNumber: 69, address: '0x6FCa9C7EDF4898cF8F0D48E60E1CcB51660505e6', type: 'mined', id: 'log_ab8dc71c', returnValues: Result { '0': 'I am from construction...', '1': '99', message: 'I am from construction...', amount: '99' }, event: 'HiEvent', signature: '0xc3a44c66585c11d2584403022700a318b8c006ca535e7f155e74d478032edd28', raw: { data: '0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000194920616d2066726f6d20636f6e737472756374696f6e2e2e2e00000000000000', topics: [ '0xc3a44c66585c11d2584403022700a318b8c006ca535e7f155e74d478032edd28' ] } } ====== events.HiEvent.returnValues: Result { '0': 'I am from construction...', '1': '99', message: 'I am from construction...', amount: '99' } ====== events.HiEvent.returnValues.message: I am from construction... ====== events.HiEvent.returnValues.amount: 99
override下的event log:
跟普通方法一样, event log是可以被 override的。 (名称相同,参数不同的函数)
pragma solidity ^0.8.0; contract TestVariable { string message; uint256 amount; event ShowVar(string name, address value); event ShowVar(string name, string value); event ShowVar(string name, uint value); function setMessage(string memory _message) public { message = _message; } function getMessage() public view returns(string memory){ return message; } function setAmount(uint256 _amount) public{ amount = _amount; } function getAmount() public view returns(uint256) { return amount; } function printVariables() public{ emit ShowVar("msg.sender", msg.sender); emit ShowVar("amount", amount); emit ShowVar("message", message); } }
对于上面的函数,设置好 对应的 amount ,message 之后,就可以直接调用 printVariables() 方法了。如下:
// contract 地址要有 const CONTRACT_ADDRESS = "0x5bEa39E27fD77739C6C8877666942D0aa8230961" // abi 要有 const contractJson = require('./build/contracts/TestVariable.json') module.exports = async function (callback) { // web3 是Truffle的自动引入的对象 const contract = new web3.eth.Contract( contractJson.abi, CONTRACT_ADDRESS ); // 获得 network , 这个是根据参数传入的 const network = await web3.eth.net.getNetworkType() // const tx = contract.methods.setMessage("today is 2022-07-06, hot day!") // const tx = contract.methods.setAmount(321) const tx = contract.methods.printVariables() // 发送! const receipt = await tx .send({ from: (await web3.eth.getAccounts())[0],// 使用了HD wallet中的第一个account gas: await tx.estimateGas(), }) .on('transactionHash', (txhash) => { console.log(`Mining transaction ... network: ${network}, tx: ${txhash}`) // console.log(`https://${network}.etherscan.io/tx/${txhash}`) }) .on('error', function(error){ console.error(`An error happened: ${error}`) callback() }) .then(function(receipt){ console.log('====== total: ') console.log(receipt) console.log('====== events.ShowVar: ', receipt.events.ShowVar) // Success, you've minted the NFT. The transaction is now on chain! console.log( `Success: The NFT has been minted and mined in block ${receipt.blockNumber}`) callback() }) }
可以看到,返回的 receipt.events.ShowVar是一个数组(array) , 如下: