【问题标题】:How to get ERC-721 tokenID?如何获取 ERC-721 tokenID?
【发布时间】:2021-08-20 11:49:27
【问题描述】:

我创建了一个部署在 ropston 网络上的 ERC-721 合约。 使用合约,我正在创建 NFT,它完全可以正常工作。

现在对于转移部分,我需要获取任何 NFT 的 tokenID 并转移到其他地址,但是每当我从 etherscan 或使用 web3 获取交易详细信息时,我都无法获取 tokenID。

我想将 tokenID 存储在数据库中,以便在转移到其他地址时可以使用它。

我已经圈出了上图中所需的确切 tokenID。

我正在使用以下代码:

            window.ethereum
                .request({
                    method: 'eth_sendTransaction',
                    params: [
                        {
                            from: fromAddress,
                            to: contractAddress,
                            gas: '50000',
                            data: nftContract.methods.transferFrom(fromAddress, toAddress, tokenNumber).encodeABI()
                        },
                    ],
                })

我只想在创建 NFT 时获取 tokenID 并存储到数据库中以供参考和执行业务逻辑。

function mintNFT(address recipient, string memory tokenURI)
        public onlyOwner
        returns (uint256)
    {
        _tokenIds.increment();

        uint256 newItemId = _tokenIds.current();
        _mint(recipient, newItemId);
        _setTokenURI(newItemId, tokenURI);

        return newItemId;
    }

上面是负责创建 NFT 的 solidity 函数。

【问题讨论】:

  • 请编辑您的问题并显示您转移令牌的 sn-p - 如果您这样做,包括发出 Transfer() 事件......另外,只是为了确认,您的问题是 Etherscan 没有t 在交易详情中显示 TokenID?如果这不是您的问题,请澄清。
  • @PetrHejda 请立即查看
  • 感谢您的更新。我的意思是转移的 Solidity 代码 - 抱歉我不清楚。
  • solidity 使用的是标准的传输定义,但我想我的问题更多在于铸币部分,我可以在新创建的 NFT 上获取 tokenID。我也在我的问题中添加了这一点。
  • 现在我需要获取 newItemID 并将其存储到我的数据库中,作为存储对我的 NFT 的引用的一部分,以便稍后将任何点转移到其他地址。

标签: ethereum solidity web3


【解决方案1】:

您的mintNFT() 函数不会发出任何包含newItemId 的事件。

solidity 使用的是标准的 transfer 定义

没有“标准定义”,ERC-721 标准只定义了一个接口和一些其他规则 - (接口的)实际实现由每个开发人员负责。不过,我假设“标准定义”是指OpenZeppelin implementation,它是 ERC-721 标准的广泛使用实现,被许多开始使用 Solidity 编码的人使用。

您可以在链接的实现中看到,OZ _mint() 函数发出 Transfer() 事件,其中第三个参数是铸造的令牌 ID。

因此,执行 mintNFT() 函数会有效地发出 Transfer() 事件,其中包含新铸造的令牌 ID 作为第三个参数的值。


在您从 JS 代码执行 mintNFT() 合约函数后,它会返回一个 PromiEvent 对象,您可以使用该对象来捕获其 receipt 事件。

收据包含发出的日志,您也可以在其中找到Transfer() 日志。

const tx = nftContract.methods.mintNFT(...).send({from: ...});

tx.on('receipt', function(receipt){
    console.log(logs[0].topics[3]); // this prints the hex value of the tokenId
    // you can use `web3.utils.hexToNumber()` to convert it to decimal
});

如果你想从已经存在的交易中获取token ID(使用tx hash),你可以使用这个sn-p:

web3.eth.getTransactionReceipt('0x258a6d35445814d091ae67ec01cf60f87a4a58fa5ac1de25d0746edf8472f189').then(function(data){
    let transaction = data;
    let logs = data.logs;
    console.log(logs);
    console.log(web3.utils.hexToNumber(logs[0].topics[3]));
});

您可以在 send() methodreceipt 的 web3 文档中找到更多详细信息。


【讨论】:

  • 感谢您提供如此详细的信息,请让我知道前进的道路或特别有助于解决此问题的资源。无论您在上面描述什么,我都明白了,但是在应用程序端发出事件并获得价值对我来说是一种灰色区域,没有任何文档参考。
  • @Omar 我已经用从 JS 代码(使用 web3)获取事件日志数据的示例更新了我的答案。
  • 谢谢,我尝试了解决方案,但转换结果总是给出 0,这当然不是我正在寻找的 tokenID:我尝试过的代码:web3.eth.getTransactionReceipt('0x3216a1abc2a955c4323180a0d76a333631e823f39a1ebe82746aed8f9e8f9f7f)然后(函数(数据){ console.log(web3.utils.hexToNumber(data.logs[0].data)); })
  • 您能检查data.logs 变量吗? web3 的某些版本使用的日志结构与文档所涵盖的不同...... tx 也可能发出比这个更多的日志事件(例如,来自您的 _setTokenURI() 和索引 0 是不同的事件日志) .另请注意,事件日志的 data 字段仅包含未索引的参数(没有 indexed 关键字),因此它可能包含多个值。
  • @Volatil3 ERC-721 标准使用 3 个索引参数定义了 Transfer() 事件。 topics[1]address 发件人,topics[2]address 收件人,topics[3]uint256 令牌 ID。 (topics[0] 是事件签名)...请注意,这是 NFT 的 ERC-721。如果你想要一个“常规”的 ERC-20 代币,那么只有 2 个索引主题。
猜你喜欢
  • 2021-11-17
  • 2021-07-07
  • 2021-11-23
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 2022-08-22
  • 2022-07-25
  • 2022-11-11
相关资源
最近更新 更多