Solidity Smart Contract Development
Decision Points
Toolchain: Foundry (preferred) for new projects. Hardhat for existing JS/TS ecosystems.
Base contracts: Always start with OpenZeppelin when pattern exists (tokens, access control, upgrades).
Solidity version: Use ^0.8.20 minimum. Named imports: import {ERC20} from "...";
Security-First Mindset
CEI Pattern (Checks-Effects-Interactions):
-
Checks - Validate all conditions and inputs first
-
Effects - Update contract state
-
Interactions - External calls LAST
This order prevents reentrancy. If external call happens before state update, attacker can re-enter and exploit stale state. Use ReentrancyGuard as additional protection.
Access control checklist:
-
Every state-changing function needs explicit access control
-
Never use tx.origin for authorization
-
Prefer Ownable2Step over Ownable for ownership transfers
Common vulnerabilities to check:
-
Reentrancy (external calls before state updates)
-
Unchecked return values on low-level calls
-
Front-running susceptible operations
-
Flash loan attack vectors in DeFi
For comprehensive audit: See references/security-checklist.md
Gas Optimization Principles
Storage is expensive:
-
Pack structs (uint128 + uint128 = 1 slot)
-
Use calldata for read-only external function args
-
Cache storage reads in memory for loops
Computation savings:
-
Custom errors over require strings (saves ~50 gas per revert)
-
unchecked blocks for safe arithmetic (overflow impossible)
-
++i over i++ in loops
For detailed patterns: See references/gas-optimization.md
Token Standards Quick Reference
Standard Use Case Key Consideration
ERC-20 Fungible tokens Check for fee-on-transfer compatibility
ERC-721 Unique NFTs Consider enumerable vs non-enumerable
ERC-1155 Multi-token Batch operations for gas efficiency
ERC-4626 Tokenized vaults Rounding direction matters for security
Upgrade Patterns
UUPS (preferred): Upgrade logic in implementation, smaller proxy footprint.
Transparent: Upgrade logic in proxy, clearer separation but higher gas.
Critical: Always use Initializable , never constructors in upgradeable contracts.
Testing Strategy
Foundry advantages:
-
Fuzz testing: testFuzz_Transfer(uint256 amount) with bound()
-
Cheatcodes: vm.prank() , vm.expectRevert() , vm.warp()
-
Fork testing: Test against mainnet state
Coverage targets:
-
All external/public functions
-
Edge cases: zero amounts, max values, empty arrays
-
Access control: unauthorized callers should revert
-
State transitions: before/after assertions
Deployment Checklist
-
All tests passing with -vvv for trace output
-
Security checklist reviewed
-
Gas optimization reviewed
-
Constructor/initializer args verified
-
Verify source on block explorer post-deploy