일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 오블완
- nest.js설명
- ethers typescript
- SBT표준
- 머신러닝기초
- ethers type
- vue기초
- 러스트 기초 학습
- 컨트렉트 동일한 함수이름 호출
- 러스트기초
- 컨트렉트 배포 자동화
- ethers websocket
- 스마트 컨트렉트 함수이름 중복
- 스마트컨트렉트테스트
- multicall
- ethers
- 프록시배포구조
- git rebase
- 스마트컨트렉트프록시
- 스마트컨트렉트 함수이름 중복 호출
- Vue.js
- 체인의정석
- 티스토리챌린지
- 스마트컨트렉트 예약어 함수이름 중복
- 러스트 기초
- chainlink 설명
- Vue
- rust 기초
- ethers v6
- ambiguous function description
Archives
- Today
- Total
체인의정석
Solidityðers 이벤트 로그 parse.log 직접 파싱하기 및 "data out-of-bounds" 오류 해결기 본문
블록체인/Solidity
Solidityðers 이벤트 로그 parse.log 직접 파싱하기 및 "data out-of-bounds" 오류 해결기
체인의정석 2023. 4. 8. 01:30728x90
반응형
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
반응형
'블록체인 > Solidity' 카테고리의 다른 글
Types in storage containing (nested) mappings cannot be assigned to. (0) | 2023.12.29 |
---|---|
VS코드 Solidity 필수 플러그인 모음(작성중) (0) | 2023.10.17 |
Solidity에서 자료형을 에러메세지에 넣는 방법 (0) | 2023.03.28 |
Solidity에서 특정 Contract 타입 사용방법과 Storage를 지정하고 Interface Contract를 작성하는 방법 (0) | 2023.03.27 |
스마트 컨트렉트 "Error: types/values length mismatch" (0) | 2023.02.28 |
Comments