Skip to content
Solidity

Inheritance, Abstract & Interfaces

Reuse logic via inheritance; define contracts with abstract and interface.

By EZ4Code Team
inheritanceinterfaceabstractoverride

Code

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

interface IERC20 {
    function transfer(address to, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

abstract contract Ownable {
    address public owner;
    constructor() { owner = msg.sender; }
    modifier onlyOwner() {
        require(msg.sender == owner, "not owner");
        _;
    }
    function transferOwnership(address newOwner) external onlyOwner {
        owner = newOwner;
    }
}

contract Token is Ownable, IERC20 {
    mapping(address => uint256) private _balances;

    function transfer(address to, uint256 amount) external override returns (bool) {
        require(_balances[msg.sender] >= amount, "insufficient");
        _balances[msg.sender] -= amount;
        _balances[to] += amount;
        return true;
    }

    function balanceOf(address account) external view override returns (uint256) {
        return _balances[account];
    }
}

Explanation

Solidity supports multiple linearization inheritance (C3) — most-derived last. Use abstract contracts when some functions lack bodies; use interfaces (no state, no constructors, all functions external) for maximum decoupling (e.g. IERC20). override is required when implementing an interface/parent virtual function. Constructors of parents run in order of inheritance (left to right). Prefer composition over deep inheritance trees to keep upgrade paths clean.

More Solidity Snippets