Compilation

TypeError:契約應標記為抽象

  • October 31, 2022

我收到此錯誤:

TypeError: Contract "BaseRegistrarImplementation" should be marked as abstract.
--> Contracts/BaseRegistrarImplementation.sol:7:1:
|
7 | contract BaseRegistrarImplementation is BaseRegistrar, ERC721 {
| ^ (Relevant source part starts here and spans across multiple lines).
Note: Missing implementation:
--> @openzeppelin/contracts/token/ERC721/ERC721.sol:44:5:
|
44 | constructor(string memory name_, string memory symbol_) {
| ^ (Relevant source part starts here and spans across multiple lines).

在嘗試編譯這個合約時(基本上是 ENS BaseRegistrarImplementation,更新到solidity 0.8.0)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './BaseRegistrar.sol';
import '@openzeppelin/contracts/token/ERC721/ERC721.sol';

contract BaseRegistrarImplementation is BaseRegistrar, ERC721 {
   // A map of expiry times
   mapping(uint256=>uint) expiries;

   bytes4 constant private INTERFACE_META_ID = bytes4(keccak256("supportsInterface(bytes4)"));
   bytes4 constant private ERC721_ID = bytes4(
       keccak256("balanceOf(address)") ^
       keccak256("ownerOf(uint256)") ^
       keccak256("approve(address,uint256)") ^
       keccak256("getApproved(uint256)") ^
       keccak256("setApprovalForAll(address,bool)") ^
       keccak256("isApprovedForAll(address,address)") ^
       keccak256("transferFrom(address,address,uint256)") ^
       keccak256("safeTransferFrom(address,address,uint256)") ^
       keccak256("safeTransferFrom(address,address,uint256,bytes)")
   );
   bytes4 constant private RECLAIM_ID = bytes4(keccak256("reclaim(uint256,address)"));

   constructor(ENS _ens, bytes32 _baseNode) {
       ens = _ens;
       baseNode = _baseNode;
   }

   modifier live {
       require(ens.owner(baseNode) == address(this));
       _;
   }

   modifier onlyController {
       require(controllers[msg.sender]);
       _;
   }

   /**
    * @dev Gets the owner of the specified token ID. Names become unowned
    *      when their registration expires.
    * @param tokenId uint256 ID of the token to query the owner of
    * @return address currently marked as the owner of the given token ID
    */
   function ownerOf(uint256 tokenId) public view override returns (address) {
       require(expiries[tokenId] > block.timestamp);
       return super.ownerOf(tokenId);
   }

   // Authorises a controller, who can register and renew domains.
   function addController(address controller) external override onlyOwner {
       controllers[controller] = true;
       emit ControllerAdded(controller);
   }

   // Revoke controller permission for an address.
   function removeController(address controller) external override onlyOwner {
       controllers[controller] = false;
       emit ControllerRemoved(controller);
   }

   // Set the resolver for the TLD this registrar manages.
   function setResolver(address resolver) external override onlyOwner {
       ens.setResolver(baseNode, resolver);
   }

   // Returns the expiration timestamp of the specified id.
   function nameExpires(uint256 id) external view override returns(uint) {
       return expiries[id];
   }

   // Returns true iff the specified name is available for registration.
   function available(uint256 id) public view override returns(bool) {
       // Not available if it's registered here or in its grace period.
       return expiries[id] + GRACE_PERIOD < block.timestamp;
   }

   /**
    * @dev Register a name.
    * @param id The token ID (keccak256 of the label).
    * @param owner The address that should own the registration.
    * @param duration Duration in seconds for the registration.
    */
   function register(uint256 id, address owner, uint duration) external override returns(uint) {
     return _register(id, owner, duration, true);
   }

   /**
    * @dev Register a name, without modifying the registry.
    * @param id The token ID (keccak256 of the label).
    * @param owner The address that should own the registration.
    * @param duration Duration in seconds for the registration.
    */
   function registerOnly(uint256 id, address owner, uint duration) external returns(uint) {
     return _register(id, owner, duration, false);
   }

   function _register(uint256 id, address owner, uint duration, bool updateRegistry) internal live onlyController returns(uint) {
       require(available(id));
       require(block.timestamp + duration + GRACE_PERIOD > block.timestamp + GRACE_PERIOD); // Prevent future overflow

       expiries[id] = block.timestamp + duration;
       if(_exists(id)) {
           // Name was previously owned, and expired
           _burn(id);
       }
       _mint(owner, id);
       if(updateRegistry) {
           ens.setSubnodeOwner(baseNode, bytes32(id), owner);
       }

       emit NameRegistered(id, owner, block.timestamp + duration);

       return block.timestamp + duration;
   }

   function renew(uint256 id, uint duration) external live onlyController override returns(uint) {
       require(expiries[id] + GRACE_PERIOD >= block.timestamp); // Name must be registered here or in grace period
       require(expiries[id] + duration + GRACE_PERIOD > duration + GRACE_PERIOD); // Prevent future overflow

       expiries[id] += duration;
       emit NameRenewed(id, expiries[id]);
       return expiries[id];
   }

   /**
    * @dev Reclaim ownership of a name in ENS, if you own it in the registrar.
    */
   function reclaim(uint256 id, address owner) external live override  {
       require(_isApprovedOrOwner(msg.sender, id));
       ens.setSubnodeOwner(baseNode, bytes32(id), owner);
   }

   function supportsInterface(bytes4 interfaceID) public view override returns (bool) {
       return interfaceID == INTERFACE_META_ID ||
              interfaceID == ERC721_ID ||
              interfaceID == RECLAIM_ID;
   }
}

知道我在做什麼錯嗎?

“缺少的實現”來自您沒有為您的 erc721 創建建構子的事實。

它應該是:

constructor(ENS _ens, bytes32 _baseNode) ERC721("MY_NAME", "MY_SYMBOL"){
       ens = _ens;
       baseNode = _baseNode;
   }

希望這可以幫助!

當您需要從繼承的契約中實現契約中的功能時,會發生此錯誤。如果合約沒有實現所有功能,則必須將其標記為抽象。在您的情況下,錯誤是指@openzeppelin/contracts/token/ERC721/ERC721.sol:44:5,這是建構子呼叫。因此,您需要添加 ERC721 合約的建構子,例如:

constructor() ERC721("MyNFT", "MNFT") { }

看:

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol

契約應標記為摘要

https://docs.openzeppelin.com/contracts/4.x/

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