Inheritance, Abstract & Interfaces
Reuse logic via inheritance; define contracts with abstract and interface.
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
Contract Basics
Define a basic smart contract with state and functions.
Functions and Visibility
Function visibility, payable, and return values.
Modifiers and Access Control
Reuse validation logic with modifiers.
Events and Logs
Emit events for off-chain listeners.
Mappings, Structs & Nested Storage
Group related data with structs and look it up by key with mappings.
Payable, receive & fallback (ETH flows)
Receive ETH via payable functions and the receive/fallback hooks.