监听Solidity合约事件
Posted sanqima
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了监听Solidity合约事件相关的知识,希望对你有一定的参考价值。
在ethers.js里,使用contractWithSigner.on()的方式,监听合约的某个事件或者地址上的交易。合约的事件,会通过emit event的方式发出,使用contractWithSigner.on() 注册了该事件,就可以实现监听了。下面以监听EventValue.sol里的ValueChanged事件为例,进行说明。
1、部署合约
a) 参考这篇文章 [用ethers.js部署合约],来部署EventValue.sol合约,得到合约地址为:0x850A0D21Da477Ea95D44d00f2B534CB0DF8eef92
//EventValue.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract EventValue {
event ValueChanged(address indexed author,uint oldValue,uint newValue);
uint _value;
constructor(uint value) public {
uint tmp = _value;
_value = value;
emit ValueChanged(msg.sender, tmp, value);
}
function getValue() view public returns (uint) {
return _value;
}
function setValue(uint value) public {
uint tmp = _value;
_value = value;
emit ValueChanged(msg.sender, tmp, value);
}
}
b) 创建文件夹和文件
mkdir -p test/ethers
cd test/ethers
## 3个脚本
touch 7.er_listenEvent.js
touch 8.any_setValue.js
touch 9.owner_setValue.js
2、编写监听脚本和测试脚本
2.1 监听脚本
监听合约事件的脚本为7.er_listenEvent.js
// 7.er_listenEvent.js
const {ethers} = require("ethers")
const fs = require('fs')
let provider = new ethers.providers.JsonRpcProvider('http://localhost:8545')
function getHexString(prikeyPath) {
const privKeyFile = fs.readFileSync(prikeyPath).toString().trim();
const privKey = new Buffer.from(privKeyFile, 'hex');
return privKey
}
async function listenEvent(){
var privKey = getHexString(".secret")
let wallet = new ethers.Wallet(privKey,provider)
var contractAddr = '0x850A0D21Da477Ea95D44d00f2B534CB0DF8eef92'
//var contractAddr = '0x305Dd19C5FBAd6b24649A030681C7c494b5481e2'
var jsonStr = fs.readFileSync('./build/contracts/EventValue.json')
var jsonInfo = JSON.parse(jsonStr)
var jsonAbi = jsonInfo.abi
let contract = new ethers.Contract(contractAddr,jsonAbi,provider)
let contractSign = contract.connect(wallet)
let curValue = await contractSign.getValue()
console.log('curValue=',ethers.BigNumber.from(curValue).toNumber())
let tx = await contractSign.setValue(300)
console.log('txHash=',tx.hash)
await tx.wait()
//1) 监听ValueChanged事件(不区分合约创建者与普通用户)
contractSign.on("ValueChanged",(author,oldValue,newValue,event) => {
console.log('---- anyUser ---')
console.log('user=',author)
console.log('oldValue=',ethers.BigNumber.from(oldValue).toNumber())
console.log('newValue=',ethers.BigNumber.from(newValue).toNumber())
console.log('eventNumber=',event.blockNumber)
});
//2) 在这些事件中,找出是合约创建者发起的调用交易
let filter = contractSign.filters.ValueChanged(wallet.address)
contractSign.on(filter,(author,oldValue,newValue,event) => {
console.log('--- the Ower ----')
console.log('ower=',author)
console.log('oldValue=',ethers.BigNumber.from(oldValue).toNumber())
console.log('newValue=',ethers.BigNumber.from(newValue).toNumber())
console.log('eventNumber=',event.blockNumber)
})
}
listenEvent()
2.2 普通用户测试脚本
普通用户的测试脚本为8.any_setValue.js
// 8.any_setValue.js
const {ethers} = require("ethers")
const fs = require('fs')
let provider = new ethers.providers.JsonRpcProvider('http://localhost:8545')
function getHexString(prikeyPath) {
const privKeyFile = fs.readFileSync(prikeyPath).toString().trim();
const privKey = new Buffer.from(privKeyFile, 'hex');
return privKey
}
function isNumber(val) {
return !isNaN(val);
}
async function preGetValue(contract) {
let value = await contract.getValue()
let valone = ethers.BigNumber.from(value).toNumber()
console.log("curValue=",valone)
}
async function preSetValue(contract,num) {
let tx = await contract.setValue(num)
console.log('tx=',tx.hash)
await tx.wait()
}
async function doValue(num){
// var privKey = getHexString(".secret")
// other user
let privKey = '0x0272...d322'
let wallet = new ethers.Wallet(privKey,provider)
var contractAddr = '0x850A0D21Da477Ea95D44d00f2B534CB0DF8eef92'
var jsonStr = fs.readFileSync('./build/contracts/EventValue.json')
var jsonInfo = JSON.parse(jsonStr)
var jsonAbi = jsonInfo.abi
let contract = new ethers.Contract(contractAddr,jsonAbi,wallet)
await preSetValue(contract,num)
await preGetValue(contract)
}
var count = process.argv[2]
if (isNumber(count)) {
doValue(count)
} else {
console.log('please input a number')
}
2.3 owner用户测试脚本
合约的部署者,也叫owner用户,其测试脚本如下
// 9.ower_setValue.js
const {ethers} = require("ethers")
const fs = require('fs')
let provider = new ethers.providers.JsonRpcProvider('http://localhost:8545')
function getHexString(prikeyPath) {
const privKeyFile = fs.readFileSync(prikeyPath).toString().trim();
const privKey = new Buffer.from(privKeyFile, 'hex');
return privKey
}
function isNumber(val) {
return !isNaN(val);
}
async function preGetValue(contract) {
let value = await contract.getValue()
let valone = ethers.BigNumber.from(value).toNumber()
console.log("curValue=",valone)
}
async function preSetValue(contract,num) {
let tx = await contract.setValue(num)
console.log('tx=',tx.hash)
await tx.wait()
}
async function doValue(num){
var privKey = getHexString(".secret")
let wallet = new ethers.Wallet(privKey,provider)
var contractAddr = '0x850A0D21Da477Ea95D44d00f2B534CB0DF8eef92'
var jsonStr = fs.readFileSync('./build/contracts/EventValue.json')
var jsonInfo = JSON.parse(jsonStr)
var jsonAbi = jsonInfo.abi
let contract = new ethers.Contract(contractAddr,jsonAbi,wallet)
await preSetValue(contract,num)
await preGetValue(contract)
}
var count = process.argv[2]
if (isNumber(count)) {
doValue(count)
} else {
console.log('please input a number')
}
3、进行测试
3.1 开启事件监听
node test\\ethers\\7.er_listenEvent.js
3.2 普通用户测试
node test\\ethers\\8.any_setValue.js 700
如图(2) 所示:
3.3 owner用户测试
node test\\ethers\\9.owner_setValue.js 702
如图(3) 所示:
由图(2)、图(3)可知普通用户和owner用户,都可以修改value的值,并且7.er_listenEvent.js脚本监听到了这个value值的修改。
参考文献
[1] ethers.js V5 事件监听
[2] ethers.js Provider使用
[3] ethers.js合约详解
[4] hardhat里的合约监听
以上是关于监听Solidity合约事件的主要内容,如果未能解决你的问题,请参考以下文章
详解 Solidity 事件Event - 完全搞懂事件的使用
智能合约实战 solidity 语法学习 13 [ 事件event emit日志logs 异常throw revertrequireassert] 附代码
智能合约实战 solidity 语法学习 13 [ 事件event emit日志logs 异常throw revertrequireassert] 附代码
智能合约实战 solidity 语法学习 13 [ 事件event emit日志logs 异常throw revertrequireassert] 附代码