如何通过使用 web3j 的交易获得合同?

How to get a contract by a transaction uising web3j?

我需要检查一笔交易是否是一笔ERC721/ERC1155交易,并获取接收地址、代币地址、价值等信息。如果我理解正确,我必须加载交易合约并检查如果它继承了 ERC165 以确认它是一个 ERC721/ERC1155 交易。

问题:我不明白如何获得具有交易对象的合同。我也没有找到获取令牌地址的方法。

我在 Infura 上有一个以太坊节点,我从那里读取块并迭代交易。我收到一笔交易及其收据。我的代码如下所示:

var tr = web3j.ethGetTransactionByBlockNumberAndIndex(blockIdParam, transactionIndex).sendAsync().get();
var hash = tr.getTransaction().get().getHash();
var receipt = web3.ethGetTransactionReceipt(hash).send().getTransactionReceipt();

现在我正在阅读事务日志,检查它们的主题并验证它们是否包含 Transfer 事件。但是转账事件也是由ERC20交易发出的,所以我在这里有点困惑。

检查 Transfer() 事件日志,您的方向是正确的。即使 ERC20 and ERC721 使用相同的事件签名,ERC721 (NFT) 标准将第 3 个主题(令牌 ID)定义为 indexed,它将其值存储在索引主题集中。虽然 ERC20 将第 3 个主题(数量)定义为 non-indexed,但索引主题的总长度设置为 2.

我随机选择了一个 transaction,其中包含 ERC20 和 ERC721 传输的事件日志。看起来其背后的逻辑是以 ERC20 代币的形式支付以铸造新的 ERC721 代币。

注意:我不是 Java 开发人员,所以我将在我的回答中使用 JS 代码,希望您可以将其用作参考以找到正确的语法和方法在 Web3 库的 Java 实现中。

const Web3 = require("web3");
const web3 = new Web3("<provider_url>");

// keccak256 of string "Transfer(address,address,uint256)"
const TRANSFER_SIGNATURE = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";

async function run() {
    const txHash = "0xfb4dc20b4a8d0b72442a396aced0fc537de757c6aac69609ab3d09d19f9c9aa8";
    const txReceipt = await web3.eth.getTransactionReceipt(txHash);

    for (let log of txReceipt.logs) {
        if (_isERC20Log(log)) {
            // Unindexed topics are concatenated in the `data` field.
            // There's only one unindexed topic in this case,
            // so you don't need to do any parsing and just use the whole value.
            const amount = web3.utils.hexToNumberString(log.data);
            console.log("ERC20 token amount: ", amount);
            console.log("ERC20 token contract: ", log.address);
        } else if (_isERC721Log(log)) {
            // 3rd indexed topic
            // index 0 of the array is the event signature, see `_isERC721Log()`
            const tokenId = web3.utils.hexToNumberString(log.topics[3]);
            console.log("ERC721 token ID: ", tokenId);
            console.log("ERC721 token contract: ", log.address);
        }
    }
}

function _isERC20Log(log) {
    return (
        log.topics[0] == TRANSFER_SIGNATURE
        && log.topics.length == 3 // index 0 is the signature, and then 2 indexed topics
    );
}

function _isERC721Log(log) {
    return (
        log.topics[0] == TRANSFER_SIGNATURE
        && log.topics.length == 4 // index 0 is the signature, and then 3 indexed topics
    );
}

run();

输出:

ERC20 token amount:  40000000000000000000
ERC20 token contract:  0x54a7cee7B02976ACE1bdd4aFad87273251Ed34Cf
ERC721 token ID:  12013
ERC721 token contract:  0x41cB4a771FdD019ADBF4685bd4885fbBeedE1784