gas-optimization
Advanced gas optimization techniques for EVM smart contracts. Covers storage packing, memory vs calldata optimization, assembly/Yul, efficient data structures, batch operations, and benchmark-driven optimization strategies.
Best use case
gas-optimization is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Advanced gas optimization techniques for EVM smart contracts. Covers storage packing, memory vs calldata optimization, assembly/Yul, efficient data structures, batch operations, and benchmark-driven optimization strategies.
Teams using gas-optimization should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/gas-optimization/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How gas-optimization Compares
| Feature / Agent | gas-optimization | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Advanced gas optimization techniques for EVM smart contracts. Covers storage packing, memory vs calldata optimization, assembly/Yul, efficient data structures, batch operations, and benchmark-driven optimization strategies.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Gas Optimization Skill
Advanced gas optimization techniques for EVM smart contracts with benchmark-driven analysis.
## Capabilities
- **Storage Optimization**: Storage packing, slot management, SLOAD/SSTORE minimization
- **Memory Management**: Memory vs calldata optimization, expansion costs
- **Assembly/Yul**: Low-level optimization for critical paths
- **Data Structures**: Gas-efficient mappings, arrays, and structs
- **Batch Operations**: Multi-call patterns, bulk transfers
- **Benchmarking**: Gas profiling, comparison analysis
## MCP/Tool Integration
| Tool | Purpose | Reference |
|------|---------|-----------|
| **Foundry MCP** | Gas reports, testing | [foundry-mcp-server](https://github.com/PraneshASP/foundry-mcp-server) |
| **EVM MCP Tools** | Opcode analysis | [evm-mcp-tools](https://github.com/0xGval/evm-mcp-tools) |
## Storage Optimization
### Storage Layout Packing
```solidity
// BAD: 3 storage slots (96 bytes used, 96 bytes allocated)
contract BadPacking {
uint128 a; // slot 0 (16 bytes)
uint256 b; // slot 1 (32 bytes) - can't pack with a
uint128 c; // slot 2 (16 bytes)
}
// GOOD: 2 storage slots (80 bytes used, 64 bytes allocated)
contract GoodPacking {
uint128 a; // slot 0, bytes 0-15
uint128 c; // slot 0, bytes 16-31
uint256 b; // slot 1
}
// Gas savings: ~20,000 gas per SSTORE avoided
```
### Minimize Storage Writes
```solidity
// BAD: Multiple storage writes
function badUpdate(uint256 newA, uint256 newB) external {
a = newA; // SSTORE: 20,000 gas (cold) or 2,900 gas (warm)
b = newB; // SSTORE: 2,900 gas (warm slot in same tx)
}
// GOOD: Single storage write with packed struct
struct Data {
uint128 a;
uint128 b;
}
Data public data;
function goodUpdate(uint128 newA, uint128 newB) external {
data = Data(newA, newB); // Single SSTORE: 20,000 gas
}
```
### Use Mappings Over Arrays for Lookups
```solidity
// BAD: O(n) lookup, expensive for large arrays
uint256[] public values;
function exists(uint256 value) public view returns (bool) {
for (uint i = 0; i < values.length; i++) {
if (values[i] == value) return true; // SLOAD per iteration
}
return false;
}
// GOOD: O(1) lookup
mapping(uint256 => bool) public valueExists;
function exists(uint256 value) public view returns (bool) {
return valueExists[value]; // Single SLOAD
}
```
## Memory vs Calldata
### Function Parameters
```solidity
// BAD: Copies array to memory
function processArray(uint256[] memory data) external {
// Memory copy cost: 3 gas per word + expansion
}
// GOOD: Read directly from calldata
function processArray(uint256[] calldata data) external {
// No copy, just pointer to calldata
// Savings: ~60 gas per 32 bytes
}
// Note: Use memory if you need to modify the array
```
### String/Bytes Handling
```solidity
// For read-only operations, use calldata
function validate(string calldata input) external pure returns (bool) {
return bytes(input).length > 0;
}
// For modifications, use memory
function transform(string memory input) internal pure returns (string memory) {
bytes memory b = bytes(input);
b[0] = 'X';
return string(b);
}
```
## Unchecked Arithmetic
```solidity
// BAD: Overflow checks on every operation (Solidity 0.8+)
function sumArray(uint256[] calldata arr) external pure returns (uint256) {
uint256 sum = 0;
for (uint256 i = 0; i < arr.length; i++) {
sum += arr[i]; // Overflow check: ~40 gas per operation
}
return sum;
}
// GOOD: Unchecked when overflow is impossible
function sumArray(uint256[] calldata arr) external pure returns (uint256) {
uint256 sum = 0;
uint256 length = arr.length;
for (uint256 i = 0; i < length;) {
unchecked {
sum += arr[i];
++i; // ++i is cheaper than i++
}
}
return sum;
}
// Savings: ~40 gas per iteration
```
## Loop Optimizations
### Cache Array Length
```solidity
// BAD: Length read from storage each iteration
for (uint i = 0; i < array.length; i++) { } // SLOAD per iteration
// GOOD: Cache length
uint256 length = array.length;
for (uint i = 0; i < length; i++) { } // Single SLOAD
```
### Pre-increment
```solidity
// BAD: Post-increment creates temporary
for (uint i = 0; i < length; i++) { }
// GOOD: Pre-increment is cheaper
for (uint i = 0; i < length; ++i) { }
// Savings: ~5 gas per iteration
```
## Custom Errors
```solidity
// BAD: String error messages
require(balance >= amount, "Insufficient balance");
// Cost: ~50 gas per character + memory expansion
// GOOD: Custom errors (Solidity 0.8.4+)
error InsufficientBalance(uint256 available, uint256 required);
if (balance < amount) revert InsufficientBalance(balance, amount);
// Cost: Fixed ~24 gas for error selector
// Savings: ~50+ gas for typical error messages
```
## Assembly/Yul Optimization
### Efficient Balance Check
```solidity
// Solidity
function getBalance(address account) external view returns (uint256) {
return account.balance;
}
// Assembly (slightly cheaper)
function getBalance(address account) external view returns (uint256 bal) {
assembly {
bal := balance(account)
}
}
```
### Efficient Memory Operations
```solidity
// Copy 32 bytes efficiently
function copy32(bytes32 source) internal pure returns (bytes32 dest) {
assembly {
dest := source
}
}
// Efficient keccak256
function efficientHash(bytes32 a, bytes32 b) internal pure returns (bytes32 result) {
assembly {
mstore(0x00, a)
mstore(0x20, b)
result := keccak256(0x00, 0x40)
}
}
```
## Batch Operations
### Batch Transfers
```solidity
// BAD: Individual transfers
function transferToMany(address[] calldata recipients, uint256 amount) external {
for (uint i = 0; i < recipients.length; ++i) {
token.transfer(recipients[i], amount); // 21000 base + transfer cost
}
}
// GOOD: Batch transfer (if supported)
function batchTransfer(
address[] calldata recipients,
uint256[] calldata amounts
) external {
// Single function call overhead
// Reduced SLOAD for token state
}
```
### Multicall Pattern
```solidity
function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
results = new bytes[](data.length);
for (uint256 i = 0; i < data.length; ++i) {
(bool success, bytes memory result) = address(this).delegatecall(data[i]);
require(success);
results[i] = result;
}
}
// Combines multiple operations in single transaction
```
## Benchmarking Workflow
### Using Foundry Gas Reports
```bash
# Run tests with gas report
forge test --gas-report
# Snapshot gas usage
forge snapshot
# Compare against previous snapshot
forge snapshot --check
```
### Gas Snapshot Format
```
| Contract | Function | Min | Avg | Max | # Calls |
|----------|----------|-----|-----|-----|---------|
| Token | transfer | 51234 | 54123 | 65432 | 100 |
| Token | approve | 24356 | 24356 | 24356 | 50 |
```
### Comparison Testing
```solidity
contract GasComparison is Test {
function test_gasComparison_approach1() public {
uint256 gasBefore = gasleft();
// Approach 1
uint256 gasUsed = gasBefore - gasleft();
emit log_named_uint("Approach 1 gas", gasUsed);
}
function test_gasComparison_approach2() public {
uint256 gasBefore = gasleft();
// Approach 2
uint256 gasUsed = gasBefore - gasleft();
emit log_named_uint("Approach 2 gas", gasUsed);
}
}
```
## Common Optimizations Summary
| Technique | Savings | Risk |
|-----------|---------|------|
| Storage packing | 20,000 gas/slot | Low |
| Calldata vs memory | 60 gas/32 bytes | Low |
| Unchecked arithmetic | 40 gas/op | Medium |
| Custom errors | 50+ gas/error | Low |
| Cache storage reads | 100-2100 gas | Low |
| Loop pre-increment | 5 gas/iteration | Low |
| Assembly | Varies | High |
## Process Integration
This skill integrates with:
- `gas-optimization.js` - Full optimization process
- `smart-contract-development-lifecycle.js` - Development best practices
- `amm-pool-development.js` - DeFi-specific optimizations
## Tools Reference
| Tool | Purpose | URL |
|------|---------|-----|
| **Foundry** | Gas reporting | [foundry-rs](https://github.com/foundry-rs/foundry) |
| **Hardhat Gas Reporter** | Gas reports | [hardhat-gas-reporter](https://github.com/cgewecke/hardhat-gas-reporter) |
| **evm.codes** | Opcode costs | [evm.codes](https://www.evm.codes/) |
| **Solidity Optimizer** | Compiler optimization | [Solidity Docs](https://docs.soliditylang.org/en/latest/internals/optimizer.html) |
## See Also
- `skills/evm-analysis/SKILL.md` - Bytecode analysis
- `agents/gas-optimizer/AGENT.md` - Gas optimization agent
- `references.md` - Gas optimization resourcesRelated Skills
image-optimization
Image formats, responsive images, lazy loading, and CDN integration.
bundle-optimization
Bundle analysis, code splitting, tree shaking, and size optimization.
tensorrt-optimization
NVIDIA TensorRT model optimization and deployment. Convert models to TensorRT engines, configure optimization profiles and precision modes, apply INT8 calibration, analyze kernel fusion, generate custom plugins, and profile inference performance.
shader-optimization
Shader performance optimization skill for instruction counting, GPU profiling, and rendering efficiency.
mobile-optimization
Mobile GPU optimization skill for thermal management.
asset-optimization
Asset optimization skill for mesh and texture budgets.
synthesis-optimization
Expertise in RTL optimization for FPGA synthesis tools. Analyzes synthesis reports, applies attributes, and guides resource inference for optimal QoR.
scipy-optimization-toolkit
SciPy scientific computing skill for numerical optimization, integration, and signal processing in physics
nonlinear-optimization-solver
Solve general nonlinear optimization problems
mixed-integer-optimization
Mixed-integer linear and nonlinear programming
derivative-free-optimization
Optimization without gradient information
convex-optimization-solver
Solve convex optimization problems efficiently