You are trying to create a contract factory for the contract, which is abstract and can't be deployed

Solidity 0.8.6 compiler forces the contract to be marked as an abstract contract when trying to use the draft-ERC20Permit feature.

TypeError: Contract "EmberX" should be marked as abstract.

However, hardhat throws an error when trying to deploy the compiled contract on a localhost node

NomicLabsHardhatPluginError: You are trying to create a contract factory for the contract Srinjoy, which is abstract and can't be deployed.
If you want to call a contract using Srinjoy as its interface use the "getContractAt" function instead.
    at getContractFactoryByName (/home/eos/Desktop/Substrate/ethops/node_modules/@nomiclabs/hardhat-ethers/src/internal/helpers.ts:112:11)
    at main (/home/eos/Desktop/Substrate/ethops/scripts/deploy.js:4:18)

:1234: Code to reproduce

pragma solidity 0.8.6;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Snapshot.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

abstract contract Srinjoy is ERC20, ERC20Burnable, ERC20Permit, ERC20Snapshot, AccessControl, Pausable {

    // Create role identifiers for burner, minter, pauser, snapshot
    bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant SNAPSHOT_ROLE = keccak256("SNAPSHOT_ROLE");

    constructor() ERC20("Srinjoy", "SJOY") {
        // Premine 1993 tokens    
        _mint(msg.sender, 1993 * 10 ** decimals());
        // contract deployer plays god as default admin role with ability to grant and revoke any roles
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
        // contract deployer has ercdefault burner, minter, pauser, snapshot role
        _setupRole(BURNER_ROLE, msg.sender);
        _setupRole(MINTER_ROLE, msg.sender);
        _setupRole(PAUSER_ROLE, msg.sender);
        _setupRole(SNAPSHOT_ROLE, msg.sender);
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount) internal whenNotPaused override(ERC20, ERC20Snapshot)
    {
        super._beforeTokenTransfer(from, to, amount);
    }

    // Check that the calling account has the burner role
    function burn(address from, uint256 amount) public onlyRole(BURNER_ROLE) {
        _burn(from, amount);
    }

    // Check that the calling account has the minter role
    function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
        _mint(to, amount);
    }

    function pause() public {
        require(hasRole(PAUSER_ROLE, msg.sender));
        _pause();
    }

    function unpause() public {
        require(hasRole(PAUSER_ROLE, msg.sender));
        _unpause();
    }

    function snapshot() public {
        require(hasRole(SNAPSHOT_ROLE, msg.sender));
        _snapshot();
    }
}

:computer: Environment

hardhat.config.js

require('@nomiclabs/hardhat-ethers');
module.exports = {
  solidity: "0.8.6",
};

package.json

{
  "name": "ethops",
  "version": "0.0.1",
  "description": "ethereum deveops",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "ethops"
  ],
  "author": "srinjoy chakravarty",
  "license": "ISC",
  "devDependencies": {
    "@nomiclabs/hardhat-ethers": "^2.0.2",
    "ethers": "^5.4.0",
    "hardhat": "^2.4.1"
  },
  "dependencies": {
    "@openzeppelin/contracts": "^4.2.0"
  }
} 
1 Like

Did you find any solution? I am facing the same issue.

1 Like

Hello @mansijoshi17

if the compiler forces the contract to be marked as an abstract contract, that is because there are function that are defined and not implemented OR that you inherit from contract that have constructors with arguments, and that are not called by the top level contract.

This will happen is you inherit ERC20Permit and don't call the corresponding constructor.

Abstract contract cannot be deployed. If you want to deploy them, you need to remove the abstract keyword and make sure all constructors are called and all functions are implemented.

2 Likes