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

OpenZeppelin 4.6升4.8后_beforeTokenTransfer重写报错问题

OpenZeppelin 4.6升级至4.8后_beforeTokenTransfer重写编译报错问题

问题场景

将@openzeppelin/contracts从4.6版本升级到4.8版本后,Solidity编译器对重写的_beforeTokenTransfer函数抛出两类错误:

报错信息1

TypeError: Function has override specified but does not override anything.

) internal virtual override (ERC721, ERC721Enumerable, ERC721Pausable) {

报错信息2

TypeError: Invalid contracts specified in override list: "ERC721", "ERC721Enumerable" and "ERC721Pausable".

     ) internal virtual override (ERC721, ERC721Enumerable, ERC721Pausable) {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: This contract: 
  --> @openzeppelin/contracts/token/ERC721/ERC721.sol:19:1:

19 | contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
   | ^ (Relevant source part starts here and spans across multiple lines).
Note: This contract: 
  --> @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol:14:1:
   |
14 | abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
   | ^ (Relevant source part starts here and spans across multiple lines).
Note: This contract: 
  --> @openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol:22:1:
   |
22 | abstract contract ERC721Pausable is ERC721, Pausable {
   | ^ (Relevant source part starts here and spans across multiple lines).

合约继承关系

contract XYZ is
    ERC721,
    ERC721Enumerable,
    ERC721Burnable,
    ERC721Pausable,
    ERC721URIStorage,
    Ownable,
    AccessControlEnumerable
{
}

重写的_beforeTokenTransfer代码

function _beforeTokenTransfer(
    address from,
    address to,
    uint256 amount
) internal virtual override (ERC721, ERC721Enumerable, ERC721Pausable) {
    super._beforeTokenTransfer(from, to, amount);
}

报错原因

  1. 函数签名不匹配
    OpenZeppelin 4.8版本对ERC721的_beforeTokenTransfer函数做了参数调整:
  • 4.6版本签名:_beforeTokenTransfer(address from, address to, uint256 tokenId)
  • 4.8版本签名:_beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize)
    你的代码仍使用旧版的三个参数(还错误用amount代替tokenId),导致编译器无法识别到需要重写的目标函数,抛出“未重写任何内容”的错误。
  1. override目标合约失效
    在4.8版本中,ERC721Enumerable和ERC721Pausable不再单独定义_beforeTokenTransfer函数,相关逻辑改为通过ERC721的新钩子机制或继承链自动触发,因此在override列表中指定这两个合约会被判定为无效。

修复方案

修正_beforeTokenTransfer的函数签名,并调整override列表,只保留ERC721:

function _beforeTokenTransfer(
    address from,
    address to,
    uint256 tokenId,
    uint256 batchSize
) internal virtual override(ERC721) {
    super._beforeTokenTransfer(from, to, tokenId, batchSize);
}

由于你的合约已经继承了ERC721Enumerable和ERC721Pausable,调用super._beforeTokenTransfer会自动执行这两个合约的相关逻辑,无需额外在override列表中指定。


内容的提问来源于stack exchange,提问作者delete

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 02:57:44