Contract "Coin" should be marked as abstract

Viewed 2412

i want to create a token on ERC-20 network.

i want to inheritance from interface in my contract .

when i inheritance form interface it show me this error :

Contract "CpayCoin" should be marked as abstract.

solc version in truffle :

  compilers: {
solc: {
  version: "0.8.10",    // Fetch exact version from solc-bin (default: truffle's version)
  docker: false,        // Use "0.5.1" you've installed locally with docker (default: false)
  settings: {          // See the solidity docs for advice about optimization and evmVersion
    optimizer: {
      enabled: false,
      runs: 200
    },
    evmVersion: "byzantium"
  }
}

},

whats the problem ? how can i solve this problem ???

this is my interface :

    // SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

interface IERC20 {
    function decimals() external view returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount)
        external
        returns (bool);

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}

contract :

// SPDX-License-Identifier: MIT

pragma solidity >=0.4.22 <0.9.0;

import "./IERC-20.sol";

contract CpayCoin is IERC20 {
    //mapping
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;

    //Unit256
    uint256 private _totalSupply;
    uint256 private _tokenPrice;

    // String
    string private _name;
    string private _symbol;

    //Address
    address _minter;

    constructor(
        string memory name_,
        string memory symbol_,
        uint256 totalSupply_
    ) {
        _minter = msg.sender;
        _balances[_minter] = _totalSupply;
        _tokenPrice = 10**15 wei;
        _name = name_;
        _symbol = symbol_;
        _totalSupply = totalSupply_;
    }

    // Modifier
    modifier onlyMinter() {
        require(msg.sender == _minter, "Only Minter can Mint!");
        _;
    }

    modifier enoughBalance(address adr, uint256 amount) {
        require(_balances[adr] >= amount, "Not enough Balance!");
        _;
    }

    modifier enoughValue(uint256 amount) {
        require(msg.value == amount * _tokenPrice, "Not enough Value!");
        _;
    }

    modifier checkZeroAddress(address adr) {
        require(adr != address(0), "ERC20: mint to the zero address");
        _;
    }

    // Functions
    function name() public view virtual returns (string memory) {
        return _name;
    }

    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address adr)
        public
        view
        virtual
        override
        returns (uint256)
    {
        return _balances[adr];
    }

    function _mint(address account, uint256 amount)
        internal
        virtual
        onlyMinter
        checkZeroAddress(account)
    {
        _totalSupply += amount;
        _balances[account] += amount;

        emit Transfer(address(0), account, amount);
    }

    function _burn(address account, uint256 amount)
        internal
        virtual
        onlyMinter
        checkZeroAddress(account)
    {
        uint256 accountBalance = _balances[account];
        unchecked {
            _balances[account] = accountBalance - amount;
        }

        _totalSupply += amount;
        emit Transfer(account, address(0), amount);
    }

    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        uint256 senderBalance = _balances[sender];
        require(
            senderBalance >= amount,
            "ERC20: transfer amount exceeds balance"
        );

        unchecked {
            _balances[sender] = senderBalance - amount;
        }

        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);
    }

    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }
}
2 Answers

Solidity currently (v0.8) doesn't have a way to tell that a class (a contract) implements an interface. Instead, the is keyword is used to mark an inheritance, as "derives from".

So the CpayCoin is IERC20 expression marks the CpayCoin as a child and IERC20 as a parent - not as an interface.

The IERC20 (parent) defines few functions (e.g. decimals() and transfer()) that the CpayCoin (child) doesn't implement, which makes the CpayCoin an abstract class.


Solution:

Implement in CpayCoin all functions defined in the IERC20 interface to not make it an abstract class, and to make it follow the ERC-20 standard. Then you're free to remove the inheritance as it becomes redundant.

Or just remove the inheritance to not have any unimplemented function definitions (but then the contract won't follow the ERC-20 standard).

Mind that in your current code, the _transfer() internal function is unreachable. I'd recommend to implement a transfer() external function that invokes this internal _transfer().

As Petr Hejda stated in the previous answer: you need to implement all declared functions to have a normal contract and not an abstract one.

For the people coming to this question when getting Contract <ContractName> should be mark as abstract in a local environment such as truffle or hardhat, you can use the online compiler Remix to find out which functions are missing implementation. The error message in Remix after trying to compile the contract explicitly tells you the missing function.

Related