Solidity Cheatsheet
Basics
Use this Solidity reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
How to Use This Solidity Cheatsheet
Use this as a syntax reference while you learn Solidity as a programming language for smart contracts. If you already know JavaScript or TypeScript, the surface syntax may feel familiar, but the important differences are storage, gas, visibility, and security. For a broader software engineering foundation, pair this reference with Hack University's JavaScript or TypeScript language courses before building production smart-contract tooling.
File Structure
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "./MyLibrary.sol"; contract MyContract { // state variables, events, modifiers, functions }
- SPDX comment is mandatory (or you get a compiler warning). Use
UNLICENSEDfor proprietary code. pragma soliditypins the compiler version.^0.8.24means>=0.8.24 <0.9.0.- Import paths: bare specifiers resolve via remappings (
remappings.txt/foundry.toml); relative paths resolve from the file's directory.
Contract Declaration
// Plain contract contract Token { } // Abstract contract (has unimplemented functions) abstract contract Base { function transfer(address to, uint amount) external virtual; } // Interface (all external, no state, no constructor) interface IERC20 { function totalSupply() external view returns (uint256); } // Library (stateless helpers, no ether, no storage) library Math { function max(uint a, uint b) internal pure returns (uint) { return a >= b ? a : b; } }
Pragma Directives
pragma solidity ^0.8.24; // caret range pragma solidity >=0.8.0 <0.9.0; // explicit range pragma solidity 0.8.24; // exact version (rarely used) pragma abicoder v2; // default since 0.8.0; enables complex types in ABI pragma experimental SMTChecker; // static analysis (dev only)
Imports
// Named import (preferred — explicit, avoids namespace pollution) import { ERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; // Alias import import { SafeERC20 as S } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; // Wildcard (avoid — imports everything into scope) import * as OZ from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; // Plain import (imports all top-level symbols — avoid) import "@openzeppelin/contracts/access/Ownable.sol";
Contract Size and Deployment
// EIP-170: max 24 576 bytes of deployed bytecode. // Use libraries, proxies, or split contracts if you exceed the limit. // Check size during tests (Foundry): // assertLt(address(myContract).code.length, 24_576);
Global Constants and Units
// Ether units 1 wei == 1 1 gwei == 1e9 1 ether == 1e18 // Time units 1 seconds == 1 1 minutes == 60 1 hours == 3600 1 days == 86400 1 weeks == 604800 // Usage uint256 public constant LOCK_PERIOD = 30 days; uint256 public fee = 0.01 ether;
ABI Encoding Utilities
bytes memory encoded = abi.encode(address(this), uint256(42)); bytes memory packed = abi.encodePacked(msg.sender, block.timestamp); // no padding bytes4 selector = abi.encodeWithSelector(IERC20.transfer.selector, to, amount); bytes memory callData = abi.encodeWithSignature("transfer(address,uint256)", to, amount); // Decode (address a, uint256 n) = abi.decode(encoded, (address, uint256));
abi.encodePackedis not collision-resistant for dynamic types — do not use it as a hash key with multiple variable-length args. Preferabi.encodeinsidekeccak256.
Version-Specific Features (0.8.x)
| Feature | Added in |
|---|---|
| Built-in overflow/underflow checks | 0.8.0 |
immutable keyword | 0.6.5 |
Custom errors (error Foo()) | 0.8.4 |
try/catch | 0.6.0 |
unchecked { } block | 0.8.0 |
using A for B global | 0.8.13 |
User-defined value types (type Foo is uint256) | 0.8.8 |
bytes.concat / string.concat | 0.8.12 |
push() returns reference | 0.6.0 |
Transient storage (tstore/tload) | 0.8.24 (EIP-1153) |
Comments