Use when adding new error messages to React, or seeing "unknown error code" warnings.
npx skills add pseudoyu/agent-skills --skill "solidity-gas-optimization"
Install specific skill from multi-skill repository
# Description
Solidity smart contract gas optimization guidelines based on RareSkills. Use when writing, reviewing, or auditing Solidity code. Triggers on tasks involving smart contracts, EVM development, gas optimization, or Solidity best practices.
# SKILL.md
name: solidity-gas-optimization
description: Solidity smart contract gas optimization guidelines based on RareSkills. Use when writing, reviewing, or auditing Solidity code. Triggers on tasks involving smart contracts, EVM development, gas optimization, or Solidity best practices.
Solidity Gas Optimization
Overview
Comprehensive gas optimization guide for Solidity smart contracts, containing 80+ techniques across 8 categories. Based on the RareSkills Book of Gas Optimization. Rules are prioritized by impact and safety.
When to Apply
Reference these guidelines when:
- Writing new Solidity smart contracts
- Reviewing or auditing existing contracts
- Optimizing gas costs for deployment or execution
- Refactoring contract storage layouts
- Implementing cross-contract interactions
- Choosing between design patterns (ERC721 vs ERC1155, etc.)
Priority-Ordered Categories
| Priority | Category | Impact | Risk |
|---|---|---|---|
| 1 | Storage Optimization | CRITICAL | LOW |
| 2 | Deployment Optimization | HIGH | LOW |
| 3 | Calldata Optimization | HIGH | LOW |
| 4 | Design Patterns | HIGH | MEDIUM |
| 5 | Cross-Contract Calls | MEDIUM-HIGH | MEDIUM |
| 6 | Compiler Optimizations | MEDIUM | LOW |
| 7 | Assembly Tricks | MEDIUM | HIGH |
| 8 | Dangerous Techniques | LOW | CRITICAL |
Quick Reference
Critical: Storage Optimization (Apply First)
Zero-to-One Writes:
- Avoid zero-to-one storage writes (costs 22,100 gas)
- Use 1/2 instead of 0/1 for boolean-like values
- Keep minimum balances in ERC20 contracts
Variable Packing:
// Bad: 3 slots
struct Unpacked {
uint64 time; // slot 1
uint256 amount; // slot 2
address user; // slot 3
}
// Good: 2 slots
struct Packed {
uint64 time; // slot 1 (with address)
address user; // slot 1
uint256 amount; // slot 2
}
Caching:
// Bad: reads storage twice
function increment() public {
require(count < 10);
count = count + 1;
}
// Good: reads storage once
function increment() public {
uint256 _count = count;
require(_count < 10);
count = _count + 1;
}
Constants & Immutables:
uint256 constant MAX = 100; // No storage slot
address immutable owner; // Set in constructor, no storage
High: Deployment Optimization
Custom Errors:
// Bad: ~64+ bytes
require(amount <= limit, "Amount exceeds limit");
// Good: ~4 bytes
error ExceedsLimit();
if (amount > limit) revert ExceedsLimit();
Payable Constructors:
// Saves ~200 gas on deployment
constructor() payable {}
Clone Patterns:
- Use EIP-1167 minimal proxies for repeated deployments
- Use UUPS over Transparent Proxy for upgradeable contracts
High: Calldata Optimization
Calldata vs Memory:
// Bad: copies to memory
function process(bytes memory data) external {}
// Good: reads directly from calldata
function process(bytes calldata data) external {}
Avoid Signed Integers:
- Small negative numbers are expensive (e.g., -1 = 0xffff...)
- Use unsigned integers in function parameters
High: Design Patterns
Token Standards:
- Prefer ERC1155 over ERC721 for NFTs (no balanceOf overhead)
- Consider consolidating multiple ERC20s into one ERC1155
Signature vs Merkle:
- Prefer ECDSA signatures over Merkle trees for allowlists
- Implement ERC20Permit for approve + transfer in one tx
Alternative Libraries:
- Consider Solmate/Solady over OpenZeppelin for gas efficiency
Medium-High: Cross-Contract Calls
Reduce Interactions:
- Use ERC1363 transferAndCall instead of approve + transferFrom
- Implement multicall for batching operations
- Cache external call results (e.g., Chainlink oracles)
Access Lists:
- Use ERC2930 access list transactions to pre-warm storage
Medium: Compiler Optimizations
Loop Patterns:
// Good: unchecked increment, cached length
uint256 len = arr.length;
for (uint256 i; i < len; ) {
// logic
unchecked { ++i; }
}
Named Returns:
// More efficient bytecode
function calc(uint256 x) pure returns (uint256 result) {
result = x * 2;
}
Bitshifting:
// Cheaper: 3 gas
x << 1 // x * 2
x >> 2 // x / 4
// Expensive: 5 gas
x * 2
x / 4
Short-Circuit Booleans:
- Place likely-to-fail conditions first in
&& - Place likely-to-succeed conditions first in
||
Medium: Assembly (Use Carefully)
Efficient Checks:
// Check address(0) with assembly
assembly {
if iszero(caller()) { revert(0, 0) }
}
// Even/odd check
x & 1 // instead of x % 2
Memory Reuse:
- Reuse scratch space (0x00-0x40) for small operations
- Avoid memory expansion in loops
Avoid: Dangerous Techniques
These are unsafe for production:
- Making all functions payable
- Ignoring send() return values
- Using gasleft() for branching
- Manipulating block.number in tests
Outdated Patterns
These no longer apply in modern Solidity:
- "external is cheaper than public" - No longer true
- "!= 0 is cheaper than > 0" - Changed around 0.8.12
References
Full documentation with code examples:
references/solidity-gas-guidelines.md- Complete guidereferences/rules/- Individual patterns by category
To look up specific patterns:
grep -l "storage" references/rules/
grep -l "assembly" references/rules/
grep -l "struct" references/rules/
Rule Categories in references/rules/
storage-*- Storage optimization patternsdeploy-*- Deployment gas savingscalldata-*- Calldata optimizationdesign-*- Design pattern choicescrosscall-*- Cross-contract call optimizationcompiler-*- Compiler optimization patternsassembly-*- Low-level assembly tricks
Key Principles
- Always Benchmark - Compiler behavior varies by context and version
- Balance Readability - Not all optimizations are worth code complexity
- Test Both Approaches - Counterintuitive optimizations sometimes increase costs
- Consider
--via-ir- Modern compiler option may obsolete some tricks - Use Alternative Libraries - Solmate/Solady often beat OpenZeppelin on gas
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.