Erc20 erc721 / kip7 kip17 구별하는 법

안녕하세요. 오랜만에 찾아뵙습니다.
특정 EOA가 홀딩하고 있는 토큰 리스트를 수집하고 있습니다.

근데 여기서 발생한게
제가 생각한 방법이 Transfer 이벤트를 이용해서 logs를 까보면서 리스트를 수집하고 있는데
여기서 발생한게 erc20, erc721 모두 Transfer 이벤트가 있다는 것이었습니다.

       fromBlock = 0;
       toBlock = 5000000;

       // signature 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
       const addressTopic = `0x${address.slice(2).padStart(64, "0")}`;
       const drOptions = {
         fromBlock: fromBlock,
         toBlock: toBlock,
         topics: [signature, addressTopic, null], // signature
       };

       let erc20 = [];
       let erc721 = [];
       const drLogs = await web3.eth.getPastLogs(drOptions);
       for (const log of drLogs) {
         const isERC20Dupl = erc20.some((k) => k === log.address);
         const isERC721Dupl = erc721.some((k) => k === log.address);

         if (!isERC20Dupl && !isERC721Dupl) {
           const contract = new web3.eth.Contract(abi, log.address);

           try {
             const owner = await contract.methods.ownerOf(1).call();
             if (owner) {
               isERC20 = false;
               isERC721 = true;
             }
             if (isERC721) {
               erc721.push(log.address);
             }
             isERC721 = false;
           } catch (error) {
             if (error.message.includes("execution revert")) {
               isERC20 = true;
               isERC721 = false;
             }
             if (isERC20) {
               erc20.push(log.address);
             }

             isERC20 = false;
           }
         }

위와 같이 ownerOf 메서드를 call하여 erc20, erc721을 구별하고 있는데

이 방식이 잘못된거 같아서 혹시 더 좋은 방법이 있거나 혹은 제가 이해하고 있는 바가 잘못되었다면 가감없이 지적해주시면 겸허히 배우겠습니다. 감사합니다.

안녕하세요
KIP13 혹은 ERC165 를 참조하시어 supportsinterface 함수를 이용하는 방법이 있습니다

안녕하세요. 답변주신 ERC165 글을 정독하면서 이해한 바로 로직을 추가해봤습니다.

ERC721은 ERC165를 구현했고 ERC20은 구현되지 않은게 맞을까요?

{
      "constant": true,
      "inputs": [
        {
          "name": "interfaceId",
          "type": "bytes4"
        }
      ],
      "name": "supportsInterface",
      "outputs": [
        {
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    }

해당 abi를 통해 web3 인스턴스로

const erc721InterfaceId = "0x80ac58cd";

 const contract = new web3.eth.Contract(abi, contractAddress);

    const interfaceId = await contract.methods
      .supportsInterface(erc721InterfaceId)
      .call();

를 통해 true값을 리턴받았습니다.

ERC20 토큰 컨트랙트들은 Execution reverted 에러가 발생하는게 맞을까요??

네.
해당 표준이 구현되어있지 않은 contract에 대해서는 에러가 발생하는 것이 맞습니다.

또한 첨언드리자면 작성자분이 첨부하신 방법 역시 erc20, erc721을 구분하는 방법으로 틀린 것이 아닙니다.

뿐만 아니라 transfer 이벤트의 로그를 까보는 것도 하나의 방법이 될 수 있습니다.

다만 명시된 모든 방식에 대해 컨트랙트 작성자가 해당 method, event 등에 대해 별도의 오버로딩을 구성했다면 부정확할 수 있습니다

2개의 좋아요

감사합니다 제이 덕분에 해결됐습니다!

1개의 좋아요