Solidity
覆蓋函式不能按預期工作
我不確定我是否理解重寫函式是如何工作的。我正在研究基於 OpenZeppelin 實現的 ERC721 令牌。OpenZeppelin 的 ERC721.sol 包含以下函式:
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); } function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ERC721.ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: owner query for nonexistent token"); return owner; } }
在我的契約中,我想覆蓋
ownerOf
,所以我有以下程式碼:contract MyNFT is Context, AccessControlEnumerable, Ownable, ERC721Enumerable, ERC721Pausable { function ownerOf(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "DramaLlamas: ownership query for nonexistent token"); address owner = _owners[tokenId]; if (owner == address(0)) { return _creatorAddress; } else { return owner; } } }
當我在
ownerOf
外部呼叫時,這按預期工作。但是,當我呼叫 時transferFrom
,程式碼使用的是原始版本而ownerOf
不是MyNFT
. 這不是我所期望的行為。我希望每次呼叫ownerOf
都使用被覆蓋的函式。有沒有什麼方法可以實現我想要做的事情,而無需在 OpenZeppelin 的實現中創建所有函式的覆蓋?
責任在於
_isApprovedOrOwner
它明確呼叫 ERC721 上的實現,因為ERC721.ownerOf
.function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ERC721.ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); }
如果你覆蓋
ownerOf
它仍然會呼叫ERC721
實現。也許您想改寫
_isApprovedOrOwner
。