Solidity

覆蓋函式不能按預期工作

  • October 21, 2021

我不確定我是否理解重寫函式是如何工作的。我正在研究基於 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

引用自:https://ethereum.stackexchange.com/questions/111939