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 UNLICENSED for proprietary code.
  • pragma solidity pins the compiler version. ^0.8.24 means >=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)

Comments

// Single-line comment

/* Multi-line
   comment */

/// @notice NatSpec single-line (user-facing)
/// @dev    NatSpec developer note
/// @param  amount The amount to transfer
/// @return        The resulting balance
/// @custom:security reviewed 2024-01
function deposit(uint256 amount) external returns (uint256) { }

NatSpec (/// or /** */) generates ABI documentation and is read by Etherscan and IDEs.

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.encodePacked is not collision-resistant for dynamic types — do not use it as a hash key with multiple variable-length args. Prefer abi.encode inside keccak256.

Version-Specific Features (0.8.x)

FeatureAdded in
Built-in overflow/underflow checks0.8.0
immutable keyword0.6.5
Custom errors (error Foo())0.8.4
try/catch0.6.0
unchecked { } block0.8.0
using A for B global0.8.13
User-defined value types (type Foo is uint256)0.8.8
bytes.concat / string.concat0.8.12
push() returns reference0.6.0
Transient storage (tstore/tload)0.8.24 (EIP-1153)