You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ethers.js解析ERC-721合约ABI时出现数据越界错误排查

问题:ERC-721合约调用queryFilter触发BUFFER_OVERRUN错误

操作过程

我尝试定义标准ERC-721合约的部分可读ABI:

export const ERC721_STANDARD_ABI = [
    "function balanceOf(address owner) view returns (uint)",
    "function transfer(address to, uint amount)",
    "event Transfer(address indexed from, address indexed to, uint amount)",
    "function tokensOfOwner(address _owner) external view returns (uint[] memory)",
    "function tokenURI(uint256 tokenId) public view returns (string memory)",
];

随后初始化合约:

const contract = new ethers.Contract(address!, ERC721_STANDARD_ABI, provider);

(注:address为有效ERC-721合约地址,provider是带API密钥的Alchemy provider)

创建过滤器:

const filter = contract?.filters!.Transfer()!;

调试显示该事件被正确解析为包含3个参数的事件,但调用await contract!.queryFilter(filter)时触发如下错误:

RangeError: data out-of-bounds (buffer=0x, length=0, offset=32, code=BUFFER_OVERRUN, version=6.0.5)
    at makeError ([redacted]/node_modules/ethers/src.ts/utils/errors.ts:660:21)
    at assert ([redacted]/node_modules/ethers/src.ts/utils/errors.ts:680:25)
    at Reader.#peekBytes ([redacted]/node_modules/ethers/src.ts/abi/coders/abstract-coder.ts:419:23)
    at Reader.readBytes ([redacted]/node_modules/ethers/src.ts/abi/coders/abstract-coder.ts:436:36)
    at Reader.readValue ([redacted]/node_modules/ethers/src.ts/abi/coders/abstract-coder.ts:444:30)
    at NumberCoder.decode ([redacted]/node_modules/ethers/src.ts/abi/coders/number.ts:54:33)
    at [redacted]/node_modules/ethers/src.ts/abi/coders/array.ts:108:31
    at Array.forEach (<anonymous>)
    at unpack ([redacted]/node_modules/ethers/src.ts/abi/coders/array.ts:86:12)
    at TupleCoder.decode ([redacted]/node_modules/ethers/src.ts/abi/coders/tuple.ts:66:22) 

错误原因

你的ABI里混用了ERC20和ERC721的定义,导致事件解析逻辑完全错误:

  1. Transfer事件定义错误:ERC721的Transfer事件第三个参数是tokenId(单个NFT的唯一ID),且标准里该参数是indexed类型;你写的uint amount是ERC20的格式,和链上实际的ERC721事件数据不匹配。
  2. 转账函数定义错误:ERC721没有transfer(address to, uint amount)这个函数,这是ERC20的转账接口;ERC721的转账函数是transferFrom或safeTransferFrom,需要指定from、to和tokenId三个参数。

当ethers尝试解析链上的ERC721 Transfer事件时,按照你错误的ABI,会去日志的data字段读取第三个参数(认为是未indexed的amount),但实际ERC721的tokenId是indexed参数,存在于topics里,data字段为空,因此触发了“读取空缓冲区”的越界错误。

修复方案

修正ABI为标准ERC721定义:

export const ERC721_STANDARD_ABI = [
    "function balanceOf(address owner) view returns (uint256)",
    "function transferFrom(address from, address to, uint256 tokenId) external",
    "function safeTransferFrom(address from, address to, uint256 tokenId) external",
    "event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)",
    "function tokensOfOwner(address _owner) external view returns (uint[] memory)",
    "function tokenURI(uint256 tokenId) public view returns (string memory)",
];

重新初始化合约后,queryFilter即可正常解析Transfer事件。

内容的提问来源于stack exchange,提问作者Can Poyrazoğlu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 16:30:44