체인의정석

ethers & hardhat에서 이벤트 로그 다루기 (검색부터 필터링과 decode) 본문

블록체인/Ethers & web3

ethers & hardhat에서 이벤트 로그 다루기 (검색부터 필터링과 decode)

체인의정석 2022. 11. 23. 11:19
728x90
반응형

순서대로 다뤄보기

1. 조회하고자 하는 컨트렉트와 연동해준다.

const testContract = await ethers.getContractAt("컨트렉트이름", "컨트렉트주소");

2. 조회를 할 설정값을 넣어서 필터링을 해준다.

   const filter = {
        address: "컨트렉트 주소",
        fromBlock: 0,
        toBlock: 10000000,
        topics: [testContract.filters."이벤트이름"().topics] //Transfer().topics 이런식으로 활용
    };

    const logs = await ethers.provider.getLogs(filter);
    //filter를 적용한 로그 값을 가져온다.

3. logs를 통해 조회가 가능하지만 해당 값들은 디코딩이 되지 않은 값들이다. 디코딩을 해주어야 한다. logs를 통해 transactionhash를 가져올 수 있다.

 

4. transaction hash를 가져와서 변수로 둔다.

        const receipt = await ethers.provider.getTransactionReceipt("");

5. 인터페이스 변수를 선언한다. abi 파일은 하드햇 경로에서 컴파일 된 걸 그대로 써준다.

        let abi = require("../artifacts/contracts/Test.sol/Test.json").abi;
        let iface = new ethers.utils.Interface(abi);

6-1.  이제 하나하나 가져와서 이벤트를 디코딩 해준다.

parseLog를 사용하는 것이 핵심이다.

      receipt.logs.forEach((log: object) => {
            console.log("log >>>", log)
            console.log(iface.parseLog(log));
        });

6-2. decodeEventLog함수도 있다.

const decodedEvent = iface.decodeEventLog("TestEvent", data, '트랜잭션해시');
 console.log("decoded event >>>", decodedEvent)

직면한 오류들

Error: no matching event

이벤트가 없어서 나는 오류이다. 내 경우에서는 컨트렉트 인터페이스만 받아와서 못찾는 거였는데. 오픈제플린 표준같은 다른 컨트렉트를 상속 받는 경우 이벤트 누락이 발생할 수 있다. 이럴땐 컨트렉트 원본 소스를 가져와서 다시 컴파일을 하고 abi를 인터페이스가 아닌 원래 컨트렉트 abi를 가져오면 된다.

코드 작성시 참고한 유용한 예제들

 

1. 여러개의 log나 나올때 순회하면서 조회하는 법 : 깔끔하고 효과적이다.

let abi = [
    "event newConnect (string indexed hashedName, string name, bytes32 connectId, string encrypted, address owner)"
];

let iface = new ethers.utils.Interface(abi)

getLogs.then((logs) => {
    logs.forEach((log) => {
        console.log(iface.parseLog(log));
    });
});

https://github.com/ethers-io/ethers.js/issues/422

 

How to decode log data · Issue #422 · ethers-io/ethers.js

I fetched logs via provider.getLogs. Now I try to decode the data with this: ethers.utils.defaultAbiCoder.decode( [ 'string','string','bytes32','string','address...

github.com

 

 

2. 이벤트의 필터 가져오는 법 - 이런방법도 있다고 한다. 위에서 내가 쓴 방법이 최종적으로 쓰이긴했다.

filter = {
    address: THE_ADDRESS_OF_YOUR_CONTRACT,
    topics: [
        // the name of the event, parnetheses containing the data type of each event, no spaces
        utils.id("Transfer(address,address,uint256)")
    ]
}
provider.on(filter, () => {
    // do whatever you want here
    // I'm pretty sure this returns a promise, so don't forget to resolve it
})

 

 

https://ethereum.stackexchange.com/questions/87643/how-to-listen-to-contract-events-using-ethers-js

 

How to listen to contract events using ethers.js?

I need to listen to the specific contract events and do some task once the event is emitted. I didn't find proper docs on ethers.js documentation. Can anybody tell me how can I keep listening to my

ethereum.stackexchange.com

3. 이벤트 로그 분석하는 예시 : 코드를 만들 때 참고하기 좋았던 예시이다.

const receipt = await ethers.provider.getTransactionReceipt("0x0c8300a14a08fffe209dfe5961b3027b1321428184365751b89c4ac6056c28e4");
let abi = [ "event Donation(address donor, uint256 value, uint256 tokenID)" ];
let iface = new ethers.utils.Interface(abi);
let log = iface.parseLog(receipt.logs[1]); // here you can add your own logic to find the correct log
const {donor, value, tokenID} = log.args;

https://github.com/ethers-io/ethers.js/issues/487

 

How do I parse event logs? · Issue #487 · ethers-io/ethers.js

I have a smart contract that emits events whenever the following line of code in the contract is called: emit Transfer(from, to, value); The script that is used to list these events is shown below:...

github.com

 

4. ethers 공식문서의 예시이다.

 

// Decoding log data and topics (the entries in a receipt)
const data = "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000";
const topics = [
  "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
  "0x0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72",
  "0x000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c"
];

iface.decodeEventLog("Transfer", data, topics);
// [
//   '0x8ba1f109551bD432803012645Ac136ddd64DBA72',
//   '0xaB7C8803962c0f2F5BBBe3FA8bf41cd82AA1923C',
//   { BigNumber: "1000000000000000000" },
//   amount: { BigNumber: "1000000000000000000" },
//   from: '0x8ba1f109551bD432803012645Ac136ddd64DBA72',
//   to: '0xaB7C8803962c0f2F5BBBe3FA8bf41cd82AA1923C'
// ]

https://docs.ethers.io/v5/api/utils/abi/interface/

 

Interface

Documentation for ethers, a complete, tiny and simple Ethereum library.

docs.ethers.io

 

타입스크립트에서 타입 지정해 주는법 예시 코드

https://www.programcreek.com/typescript/?code=naddison36%2Ftx2uml%2Ftx2uml-master%2Fsrc%2Fts%2Ftransaction.ts 

 

typescript source code of transaction

 

www.programcreek.com

 

728x90
반응형
Comments