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
isto inherit. - Parent constructor arguments can be passed inline on the
isline or in the child's constructor. virtualmarks a function as overridable;overridemarks 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
| Library | Inheritance | |
|---|---|---|
| Shares code | yes (linked) | yes (inlined) |
| Has state | no | yes |
| Deployment | separate (linked) or embedded | inlined into contract |
| Call type | DELEGATECALL (deployed) or inlined (internal) | inlined |
using X for Y | yes | no |
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; } }