Solidity Patterns
Quick start
- •Default to Solidity 0.8.x.
- •Use custom errors and events for clarity and gas efficiency.
- •Follow checks-effects-interactions and prefer pull payments.
- •Keep state variables private and expose explicit getters.
- •Return file paths plus minimal templates.
Templates
Basic contract
solidity
pragma solidity ^0.8.20;
contract Counter {
uint256 private value;
event ValueChanged(uint256 value);
function get() external view returns (uint256) {
return value;
}
function increment() external {
value += 1;
emit ValueChanged(value);
}
}
Ownership modifier (no external deps)
solidity
pragma solidity ^0.8.20;
error NotOwner();
contract OwnableSimple {
address private owner;
modifier onlyOwner() {
if (msg.sender != owner) revert NotOwner();
_;
}
constructor() {
owner = msg.sender;
}
}
Pull payment pattern
solidity
pragma solidity ^0.8.20;
error NotEnoughBalance();
error TransferFailed();
contract PullPayments {
mapping(address => uint256) private balances;
function deposit() external payable {
balances[msg.sender] += msg.value;
}
function withdraw(uint256 amount) external {
uint256 bal = balances[msg.sender];
if (bal < amount) revert NotEnoughBalance();
// effects
balances[msg.sender] = bal - amount;
// interactions
(bool ok, ) = msg.sender.call{ value: amount }("");
if (!ok) revert TransferFailed();
}
}
Reentrancy guard (simple)
solidity
pragma solidity ^0.8.20;
error Reentrancy();
abstract contract ReentrancyGuard {
uint256 private locked = 1;
modifier nonReentrant() {
if (locked != 1) revert Reentrancy();
locked = 2;
_;
locked = 1;
}
}
Notes
- •Prefer OpenZeppelin for standard tokens and access control in production.
- •Emit events for state changes that external systems must observe.