solidity
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.originfor authorization - Prefer
Ownable2StepoverOwnablefor 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
calldatafor read-only external function args - Cache storage reads in memory for loops
Computation savings:
- Custom errors over require strings (saves ~50 gas per revert)
uncheckedblocks for safe arithmetic (overflow impossible)++ioveri++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)withbound() - 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
-vvvfor trace output - Security checklist reviewed
- Gas optimization reviewed
- Constructor/initializer args verified
- Verify source on block explorer post-deploy