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); }
报错原因
- 函数签名不匹配
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),导致编译器无法识别到需要重写的目标函数,抛出“未重写任何内容”的错误。
- 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
相关产品推荐
相关产品推荐

