如何读取以太坊区块交易:包含 bytes[] 字段的数据字段

How to read to read Ethereum block transaction: data field containing bytes[] field

是否可以通过查看以太坊区块交易 data 字段来解码类似 multicall(uint256 deadline, bytes[] data) 的输入数据?

给定的以太坊交易可能包含一个数据字段,例如:

{
    "hash":"0x688c0f7e7ad5c59e4c3e24199e8e56753b95960324e3bb41da210eb0416e581d",
    "nonce":"0x73",
    "blockHash":"0x33fbe975a5a9c6a399c55f1bcb8130cd1d0c560722483dcd72d964020f156f7d",
    "blockNumber":"0xdc0ba9",
    "transactionIndex":"0xde",
    "from":"0xfcf9c19841cd8c6cd7114e638b02e62189a89601",
    "to":"0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45",
    "value":"0x0",
    "gasPrice":"0x4190ab000",
    "gas":"0x6621f",
    "data":"0x5ae401dc000000000000000000000000000000000000000000000000000000006236a988000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e4472b43f3000000000000000000000000000000000000000000001edd40a09ca2037a8ce4000000000000000000000000000000000000000000000000008e6053de0d6216000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000fc09c7cfd9c175dd9423ca02ae1249579ab12f12000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404b7c000000000000000000000000000000000000000000000000008e6053de0d6216000000000000000000000000fcf9c19841cd8c6cd7114e638b02e62189a8960100000000000000000000000000000000000000000000000000000000",
    "input":"0x5ae401dc000000000000000000000000000000000000000000000000000000006236a988000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e4472b43f3000000000000000000000000000000000000000000001edd40a09ca2037a8ce4000000000000000000000000000000000000000000000000008e6053de0d6216000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000fc09c7cfd9c175dd9423ca02ae1249579ab12f12000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404b7c000000000000000000000000000000000000000000000000008e6053de0d6216000000000000000000000000fcf9c19841cd8c6cd7114e638b02e62189a8960100000000000000000000000000000000000000000000000000000000",
    "type":"0x0",
    "v":"0x26",
    "s":"0x3397f6969aec9a7d1c168765985d9ff51d9b1bb4a84126ce561e1793bcc82af7",
    "r":"0xd692324d08b4ed25a2b7a37cc247b4f879d0e3bcb3d851fdc087f3ad40579edb"
}

据此etherscan record, the above block is a transaction sent to Uniswap V3: Router 2. I want to decode the data field. Using the Ethereum ABI Spec,合约的ABI可用于查找智能合约中所有函数的哈希值。将函数 multicall(uint256,bytes[])5ae401dc 的 Keccak-256 散列中的前八个字符与上面 data 字段的开头进行比较,确定函数调用。

但是,此时我无法判断上面的 bytes[] 数组指的是什么,因此无法解码 data 字段的其余部分。似乎真正解码此调用的唯一方法是梳理 uniswap 源代码,将剩余字节映射到更易于阅读的内容。

但不知何故 etherscan.io 设法向我们展示此交易解码为:

我是不是遗漏了什么,或者是通过合同数据到达上述转账列表的唯一方法吗?

此Etherscan代币转账列表来自交易产生的事件日志。不是直接来自 data 字段。

multicall 参数仅指定执行内部交易的地址列表及其数据字段。

您可以在交易收据中看到事件日志列表。例如使用 web3js:

const TRANSFER_EVENT_SIGNATURE = web3.utils.keccak256("Transfer(address,address,uint256)");
const txHash = "0x688c0f7e7ad5c59e4c3e24199e8e56753b95960324e3bb41da210eb0416e581d";
const txReceipt = await web3.eth.getTransactionReceipt(txHash);
for (let log of txReceipt.logs) {
    if (log.topics[0] == TRANSFER_EVENT_SIGNATURE) {
        // This is an event log of the Transfer() event
        console.log(log);
    }
}