Solidity Cheatsheet

Inheritance

Use this Solidity reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Basics

contract Animal {
    string public name;

    constructor(string memory _name) {
        name = _name;
    }

    function speak() public virtual returns (string memory) {
        return "...";
    }
}

contract Dog is Animal {
    constructor(string memory _name) Animal(_name) {}

    function speak() public virtual override returns (string memory) {
        return "Woof";
    }
}
  • Use is to inherit.
  • Parent constructor arguments can be passed inline on the is line or in the child's constructor.
  • virtual marks a function as overridable; override marks it as an override.

Multiple Inheritance (C3 Linearization)

Solidity uses C3 linearization (same as Python). List parents most base-like first.

contract A {
    function who() public virtual returns (string memory) { return "A"; }
}

contract B is A {
    function who() public virtual override returns (string memory) { return "B"; }
}

contract C is A {
    function who() public virtual override returns (string memory) { return "C"; }
}

// Most derived must list all parents that define the function
contract D is B, C {
    // B, C order → linearization: D → C → B → A
    function who() public override(B, C) returns (string memory) {
        return super.who(); // calls C.who() (next in MRO)
    }
}

Ambiguous multiple inheritance is a compile error — you must specify override(A, B) and implement the function.

super

contract Ownable {
    address public owner;
    function transferOwnership(address newOwner) public virtual {
        owner = newOwner;
    }
}

contract Logged is Ownable {
    event OwnerChanged(address newOwner);
    function transferOwnership(address newOwner) public virtual override {
        super.transferOwnership(newOwner); // calls Ownable.transferOwnership
        emit OwnerChanged(newOwner);
    }
}

super follows the MRO (Method Resolution Order), not just the direct parent. In multiple inheritance, super.f() calls the next function in the linearized chain.

Abstract Contracts

abstract contract Shape {
    // Unimplemented — forces child to implement
    function area() public virtual returns (uint256);

    // Concrete function — inherited as-is
    function describe() public pure returns (string memory) {
        return "I am a shape";
    }
}

contract Circle is Shape {
    uint256 public radius;

    constructor(uint256 r) { radius = r; }

    function area() public view override returns (uint256) {
        return 314 * radius * radius / 100; // π ≈ 3.14
    }
}
  • A contract with any unimplemented function is implicitly abstract.
  • Abstract contracts cannot be deployed.

Interfaces

interface IERC20 {
    // All functions must be external
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    // No constructor, no state variables, no implementation
}

// Implementing an interface
contract MyToken is IERC20 {
    // Must implement ALL interface functions
    function totalSupply() external view override returns (uint256) { return _total; }
    // ...
}

// Using an interface to call an external contract
function checkBalance(address token, address user) external view returns (uint256) {
    return IERC20(token).balanceOf(user);
}

Interface rules: - All functions must be external. - No state variables (constants allowed since 0.8.18 — still debated). - No constructors. - No function implementations. - Can inherit from other interfaces. - type(IFoo).interfaceId gives the EIP-165 bytes4 interface ID.

Constructor Inheritance

contract ERC20 {
    string public name;
    string public symbol;

    constructor(string memory _name, string memory _symbol) {
        name   = _name;
        symbol = _symbol;
    }
}

contract Ownable {
    address public owner;
    constructor(address _owner) { owner = _owner; }
}

// Option 1: inline args on `is` line (when args are known at compile time)
contract StaticToken is ERC20("MyToken", "MTK"), Ownable(address(0)) { }

// Option 2: pass args from child constructor (most common)
contract DynamicToken is ERC20, Ownable {
    constructor(string memory name_, string memory sym_, address owner_)
        ERC20(name_, sym_)
        Ownable(owner_)
    { }
}

Calling Parent Functions Directly

contract Child is Parent {
    function foo() public override {
        Parent.foo(); // explicit parent — skips MRO, calls exactly Parent.foo
        super.foo();  // next in MRO chain
    }
}

State Variable Visibility in Inheritance

contract Base {
    uint256 public  a; // inherited getter, accessible in child
    uint256 internal b; // accessible in child
    uint256 private  c; // NOT accessible in child (compile error)
}

contract Child is Base {
    function getB() external view returns (uint256) { return b; } // OK
    // function getC() ... { return c; }  // Error: c is private
}

Shadowing State Variables (Disallowed Since 0.6)

contract Base {
    uint256 public x = 1;
}

// COMPILE ERROR since 0.6:
// contract Child is Base {
//     uint256 public x = 2; // Error: shadowing not allowed
// }

Diamond Problem and MRO Example

//     A
//    / \
//   B   C
//    \ /
//     D

contract A { function f() public virtual returns (string memory) { return "A"; } }
contract B is A { function f() public virtual override returns (string memory) { return "B"; } }
contract C is A { function f() public virtual override returns (string memory) { return "C"; } }

contract D is B, C {
    // MRO: D → C → B → A  (right-to-left of `is` list, then deduplicated)
    function f() public override(B, C) returns (string memory) {
        return super.f(); // "C"
    }
}

Libraries vs Inheritance

LibraryInheritance
Shares codeyes (linked)yes (inlined)
Has statenoyes
Deploymentseparate (linked) or embeddedinlined into contract
Call typeDELEGATECALL (deployed) or inlined (internal)inlined
using X for Yyesno
library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b; // 0.8+ has built-in overflow protection
    }
}

contract MyContract {
    using SafeMath for uint256;
    function foo(uint256 x) external pure returns (uint256) {
        return x.add(1);
    }
}

EIP-165 Interface Detection

interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

contract MyNFT is IERC165 {
    function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC165).interfaceId;
    }
}