블록체인/Solidity
Solidityðers 이벤트 로그 parse.log 직접 파싱하기 및 "data out-of-bounds" 오류 해결기
체인의정석
2023. 4. 8. 01:30
728x90
erc20토큰을 전송 하면 nft가 민팅 되는 구조를 만들고 있었는데 문제가 발생하였다.
평소에는
async function pushETHwithdraw(erc20Token, myAddress, provider, abi) {
clientsETH = []
console.log("pushETHwithdraw")
const resObj = {}
const topic = [erc20Token.filters.WithdrawETH().topics].toString();
const filter = {
address: ERC20,
fromBlock: 28546565,
topics: [topic]
};
const getlogs = await provider.getLogs(filter);
let iface = new ethers.utils.Interface(abi);
for (let logs of getlogs) {
const receipt = await provider.getTransactionReceipt(logs.transactionHash);
receipt.logs.forEach((log) => {
const parsedLog = iface.parseLog(log)
if( parsedLog.topic == topic) {
resObj.amount = parsedLog.args.from.toString();
resObj.buyer = parsedLog.args.to;
resObj.txhash = logs.transactionHash;
clientsETH.push({"amount": (resObj.amount/(10**18)).toString(), "buyer": resObj.buyer, "txhash" : resObj.txhash});
} else {
console.log(`this topic is not Transfer`)
}
});
}
return clientsETH;
}
이런식으로 로그를 파싱했는데
문제는 erc721과 erc20의 표준이 같기 때문에 해당 부분이 같은 트랜잭션 안에 있다면 Parse log가 먹히지 않는 것이다.
이때 data out-of-bounds 오류가 나오는데 이는 일반적으로 abi가 잘못되었을 때 나온다.
그러나 이렇게 동일한 이벤트가 발생할때도 오류가 나온다.
그럼 parseLog없이 이벤트를 파싱하는 방법을 쓸 수 밖에 없다.
async function pushNFTmint(erc721Token, myAddress, provider, abi) {
clientsNFT = []
console.log("pushNFTmint")
const resObj = {}
const topic = [erc721Token.filters.Transfer().topics].toString();
// const topic = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("NFTBuy(address,uint256"));
const filter = {
address: ERC721,
fromBlock: 28727518,
topics: [topic]
};
const getlogs = await provider.getLogs(filter);
console.log("getlogs", getlogs)
let iface = new ethers.utils.Interface(abi);
for (let logs of getlogs) {
const receipt = await provider.getTransactionReceipt(logs.transactionHash);
console.log("receipt", receipt)
receipt.logs.forEach((log) => {
console.log("log.address", log.address);
if( log.topics[0] == topic && log.address == ERC721) {
console.log(`this topic is correct`, topic)
resObj.from = "0x" + log.topics[1].slice(26);
console.log(`resObj.from`, resObj.from)
resObj.to = "0x" + log.topics[2].slice(26);
console.log(`resObj.to`, resObj.to)
resObj.tokenId = parseInt(log.topics[3], 16);
console.log(resObj.tokenId) ;
resObj.txhash = logs.transactionHash;
clientsNFT.push({"from": resObj.from, "to": resObj.to, "tokenId": resObj.tokenId,"txhash" : resObj.txhash});
} else {
console.log(`this topic is not Transfer`,topic)
}
});
}
return clientsNFT;
}
해당 부분은 이런식으로 직접 slice 와 parseInt를 사용하여 해결할 수 있다.
이렇게 모종의 이유로 input값이나 이벤트 등을 파싱해주는 함수가 오류가 날 경우 그냥 16진수에서 데이터를 뽑아내면 된다.
728x90
반응형