Solidity Guide
A practical cheatsheet for writing Smart Contracts in Solidity 0.8.x.
This guide is not meant to teach Solidity from scratch.
It is intended for developers who already understand programming fundamentals and want a structured reference.
💡 If you know JavaScript, learning Solidity is significantly easier.
Version Pragma
pragma solidity ^0.8.0;
^0.8.0 compiles with:
= 0.8.0 and < 0.9.0
⚠️ Solidity 0.8.x introduced automatic overflow & underflow protection.
Imports
import "filename.sol";
import * as Math from "./Math.sol";
import {symbol1 as alias, symbol2} from "./file.sol";
Types
Boolean
bool isActive = true;
Operators:
!&&||==!=
Integers
Unsigned:
uint256 value;
uint8 small;
Signed:
int256 number;
Operators:
- Arithmetic:
+ - * / % ** - Comparison:
<= < > >= == != - Bitwise:
& | ^ ~ << >>
✅ In Solidity 0.8+, overflow automatically reverts.
SafeMath is no longer required.
If you intentionally want wrapping behavior:
unchecked {
counter++;
}
Address
address user;
address payable receiver;
Balance
user.balance;
address(this).balance;
Transfer Ether
receiver.transfer(1 ether); // reverts on failure
receiver.send(1 ether); // returns false on failure
Low-Level Call
(bool success, bytes memory data) =
user.call{value: 1 ether}("");
require(success);
delegatecall
(bool success, ) = target.delegatecall(
abi.encodeWithSignature("setValue(uint256)", 10)
);
require(success);
⚠️ delegatecall executes in the caller’s storage context.
Arrays
uint[] dynamicArray;
uint[5] fixedArray;
Bytes
Fixed:
bytes32 data;
Dynamic:
bytes memory raw;
string memory text;
Enum
enum Status { Pending, Approved, Rejected }
Status public current = Status.Pending;
Struct
struct User {
address account;
uint256 balance;
}
Mapping
mapping(address => uint256) public balances;
Mappings behave like hash tables.
Control Structures
Available:
if / elseforwhiledo whilebreakcontinuereturn- ternary
? :
Functions
Structure
function name(uint a)
public
view
returns (uint)
Modifiers:
publicprivateinternalexternalviewpurepayable
Constructor
constructor() {
owner = msg.sender;
}
External Calls (0.8.x Syntax)
contractInstance.functionName{value: 1 ether, gas: 50000}();
View Function
function getBalance() public view returns (uint) {
return address(this).balance;
}
Pure Function
function multiply(uint a) public pure returns (uint) {
return a * 2;
}
Payable
function deposit() public payable {}
Fallback & Receive
receive() external payable {}
fallback() external payable {}
receive()→ triggered when ETH is sent without calldatafallback()→ triggered when function does not exist
Contracts
Creating with new
ContractA a = new ContractA();
Inheritance
contract Owned {
address public owner;
constructor() {
owner = msg.sender;
}
}
contract Child is Owned {}
Interface
interface IToken {
function transfer(address to, uint amount) external returns (bool);
}
Events
event Deposit(address indexed from, uint amount);
function deposit() public payable {
emit Deposit(msg.sender, msg.value);
}
Up to 3 parameters can be indexed.
Library
library Math {
function add(uint a, uint b) internal pure returns (uint) {
return a + b;
}
}
Using For
using Math for uint;
uint result = 5.add(3);
Error Handling
require(condition, "Error message");
assert(condition);
revert("Error message");
Custom Errors (Gas Efficient)
error NotOwner();
if (msg.sender != owner) revert NotOwner();
Global Variables
Block
block.numberblock.timestampblock.coinbaseblock.gaslimitblock.difficulty
Transaction
msg.sendermsg.valuemsg.datamsg.sigtx.origintx.gasprice
Cryptographic Functions
keccak256()sha256()ripemd160()ecrecover()addmod()mulmod()
Contract Related
thisselfdestruct(address payable recipient)
⚠️ selfdestruct is discouraged in modern contract architecture.