home / skills / raintree-technology / claude-starter / gas-optimization

gas-optimization skill

/skills/aptos/gas-optimization

This skill helps optimize Aptos Move contracts by applying gas-saving techniques, data structure choices, and profiling tips for better throughput.

npx playbooks add skill raintree-technology/claude-starter --skill gas-optimization

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
3.7 KB
---
name: aptos-gas-optimization
description: Aptos gas optimization expert for Move smart contracts. Covers storage costs, execution efficiency, inline functions, aggregators for parallel execution, Table vs SmartTable vs vector tradeoffs, event optimization, struct packing, and gas profiling tools.
allowed-tools: Read, Write, Edit, Grep, Glob, Bash
model: sonnet
license: MIT
metadata:
  author: raintree
  version: "1.0"
---

# Aptos Gas & Performance Optimization Expert

Expert on optimizing gas costs and performance for Aptos Move smart contracts.

## Triggers

- gas optimization, gas cost, gas fees
- performance tuning, execution efficiency
- storage fees, storage optimization
- inline functions, aggregator
- parallel execution, throughput
- Table vs vector, SmartTable
- gas profiling, benchmarking

## Gas Model Overview

```
Total Gas Cost = Execution Gas + Storage Gas + IO Gas

Gas Fee (APT) = Gas Units x Gas Unit Price
1 APT = 100,000,000 octas
```

## Data Structure Costs

| Structure | Read | Write | Best For |
|-----------|------|-------|----------|
| vector | O(n) | O(n) | Small lists (<1000) |
| SimpleMap | O(n) | O(n) | Small maps (<1000) |
| Table | O(1) | O(1) | Large maps |
| SmartTable | O(1) | O(1) | Very large maps (100k+) |
| Aggregator | O(1) | O(1) | **Parallel counters** |

## Key Optimizations

### 1. Use Aggregators for Global Counters

```move
use aptos_framework::aggregator_v2::{Self, Aggregator};

struct Stats has key {
    total_users: Aggregator<u64>  // Concurrent-safe!
}

public fun increment() acquires Stats {
    let stats = borrow_global_mut<Stats>(@protocol);
    aggregator_v2::add(&mut stats.total_users, 1);
    // Multiple txns can do this in parallel!
}
```

### 2. Inline Small Functions

```move
inline fun min(a: u64, b: u64): u64 {
    if (a < b) a else b
}
```

### 3. Cache Loop Lengths

```move
// Bad: calls length() every iteration
while (i < vector::length(v)) { ... }

// Good: cache length
let len = vector::length(v);
while (i < len) { ... }
```

### 4. Use Event V2 (Cheaper)

```move
#[event]
struct TransferEvent has drop, store {
    from: address,
    to: address,
    amount: u64,
}

event::emit(TransferEvent { from, to, amount });
```

### 5. Pack Struct Fields

```move
// Bad: 8 bytes wasted on padding
struct Data { flag1: bool, value1: u64, flag2: bool, value2: u64 }

// Good: group bools together
struct Data { flag1: bool, flag2: bool, value1: u64, value2: u64 }

// Best: pack into bitmap
struct Data { flags: u8, value1: u64, value2: u64 }
```

### 6. Use Table/SmartTable for Large Data

```move
// Bad for large datasets
struct Registry { users: vector<User> }

// Good for large datasets
struct Registry { users: Table<address, User> }

// Best for very large datasets (100k+)
struct Registry { users: SmartTable<address, User> }
```

### 7. Batch Operations

```move
// Single transaction for multiple transfers
public entry fun batch_transfer(
    sender: &signer,
    recipients: vector<address>,
    amounts: vector<u64>
) { ... }
```

### 8. Early Returns

```move
// Check cheapest conditions first
if (amount == 0) return;
if (amount >= MAX) return;
if (!is_valid(user)) return;
// Then do expensive work
```

## Gas Profiling

```bash
# Run tests with gas profiling
aptos move test --gas

# Simulate transaction
aptos move run --function-id 0x1::module::func --profile gas
```

## Checklist Before Mainnet

- [ ] Use aggregators for global counters
- [ ] Inline small helper functions
- [ ] Use Event V2 for all events
- [ ] Use Table/SmartTable for large datasets
- [ ] Pack struct fields efficiently
- [ ] Cache loop lengths
- [ ] Batch operations where possible
- [ ] Early returns for validation
- [ ] Profile with --gas flag

Overview

This skill is an Aptos gas and performance optimization expert for Move smart contracts. It focuses on minimizing gas costs and improving execution throughput by applying practical strategies like data-structure selection, function inlining, struct packing, event optimizations, and parallel-safe aggregators. The guidance is platform-agnostic and aimed at production-ready Move code.

How this skill works

The skill inspects Move smart contract patterns and recommends targeted changes that reduce Execution, Storage, and IO gas. It highlights tradeoffs between vectors, Table, and SmartTable, when to use aggregators for parallel counters, how to emit cheaper Event V2, and where to inline or cache values. It also guides on running gas profiling and interpreting profiles to prioritize optimizations.

When to use it

  • Before mainnet deployment to reduce predictable gas spikes and storage costs.
  • When profiling test transactions shows hotspots or large execution gas.
  • When handling large datasets (thousands to 100k+ entries) where data structure choice matters.
  • When global counters or high-concurrency updates must scale without contention.

Best practices

  • Prefer Table or SmartTable for large maps; use vector/SimpleMap only for small lists (<1000).
  • Use Aggregator for global counters to enable parallel-safe increments and lower contention.
  • Inline trivial helper functions and cache loop lengths to avoid repeated calls in hot loops.
  • Pack struct fields (group booleans or use bitmaps) to reduce storage and IO gas.
  • Emit Event V2 for cheaper events and batch operations to amortize per-transaction overhead.
  • Run gas profiling (aptos move test --gas) and act on the top contributors first.

Example use cases

  • Converting a user registry from vector to Table to avoid O(n) writes on large datasets.
  • Replacing a global u64 counter with Aggregator to allow concurrent increments across txns.
  • Refactoring hot loops to cache vector::length and inline simple helpers to lower execution gas.
  • Packing struct flags into a bitmap to reduce storage bytes and per-write gas.
  • Batching multiple transfers in a single entry function to reduce repeated transaction overhead.

FAQ

When should I use SmartTable instead of Table?

Use SmartTable for very large datasets (100k+ entries) where backend optimizations and storage layout reduce gas and IO compared with Table.

Does using Aggregator always save gas?

Aggregators save contention and enable parallel increments, but evaluate access patterns—if you rarely update a counter, the benefit is smaller than for high-concurrency scenarios.