Solidity

如何在 ER721 的子合約中更改 _safeMint 方法的邏輯?

  • June 9, 2021

我正在擺弄 OpenZeppelin ERC721 合約,並創建了我自己的繼承自ERC721.sol的合約。我試圖改變_safeMint方法,所以我從父契約中複製了它,這一require行引發了一個錯誤:

function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
   // Some extra logic here while keeping the next line exactly as in the parent contract
   require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}

錯誤:

contracts/nft.sol:98:17: DeclarationError: Undeclared identifier. 
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); ^--------------------^

我相信這是由於在父契約_checkOnERC721Received中定義private的,這使得子契約無法使用。所以我決定把這個_checkOnERC721Received方法複製到我的契約中來解決這個問題。但是它引發了另一個錯誤:

contracts/nft.sol:114:5: TypeError: Overriding function is missing "override" specifier. 
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) ^ (Relevant source part starts here and spans across multiple lines). 
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/token/ERC721/ERC721.sol:435:5: Overridden function is here: 
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) ^ (Relevant source part starts here and spans across multiple lines).

如果我添加override參數,我現在得到:

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/token/ERC721/ERC721.sol:435:5: TypeError: Trying to override non-virtual function.
Did you forget to add "virtual"? function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) ^ (Relevant source part starts here and spans across multiple lines). 

contracts/nft.sol:114:5: Overriding function is here: 
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) ^ (Relevant source part starts here and spans across multiple lines).

所以看來我不能覆蓋那個方法?我如何更改_safeMint子契約中的邏輯,同時保留此行https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/token/ERC721/ERC721.sol#L318?是通過創建整個契約而不繼承的唯一方法嗎?

這些問題是出於學習目的,我不想做任何具體的事情。

你可以做兩件事改變_safeMint行為

  • 覆蓋 _safeMint並呼叫其父級
contract MyToken is ERC721 {
   function _safeMint(address to, uint256 tokenId, bytes memory _data) internal override {
       /* Can do something here and modify input parameters */
       super._safeMint(to, tokenId, _data);
       /* Can do something else here */
   }
}
  • 覆蓋 _mint,在目前實現中_safeMint只呼叫_mint
contract MyToken is ERC721 {
   function _mint(address to, uint256 tokenId) internal override {
       /* Can do something here and modify input parameters */
       super.mint(to, tokenId);
       /* Can do something else here */
   }
}

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