multiAI Summary Pending

pitfalls-blockchain

Blockchain RPC error handling, gas estimation, multi-chain config, and transaction management. Use when interacting with smart contracts, estimating gas, or managing transactions. Triggers on: RPC, contract call, gas, multicall, nonce, transaction, revert.

231 stars

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/pitfalls-blockchain/SKILL.md --create-dirs "https://raw.githubusercontent.com/aiskillstore/marketplace/main/skills/barissozen/pitfalls-blockchain/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/pitfalls-blockchain/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How pitfalls-blockchain Compares

Feature / Agentpitfalls-blockchainStandard Approach
Platform SupportmultiLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Blockchain RPC error handling, gas estimation, multi-chain config, and transaction management. Use when interacting with smart contracts, estimating gas, or managing transactions. Triggers on: RPC, contract call, gas, multicall, nonce, transaction, revert.

Which AI agents support this skill?

This skill is compatible with multi.

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

# Blockchain Pitfalls

Common pitfalls and correct patterns for blockchain interactions.

## When to Use

- Making contract calls via RPC
- Estimating gas for transactions
- Handling reverts and errors
- Managing nonces for concurrent txs
- Configuring multi-chain support
- Reviewing blockchain code

## Workflow

### Step 1: Verify Error Handling

Check all contract calls are wrapped in try/catch.

### Step 2: Check Gas Estimation

Ensure gas is estimated with buffer before sending.

### Step 3: Verify Multicall Safety

Confirm multicall uses allowFailure: true.

---

## RPC Error Handling

```typescript
// ✅ Wrap ALL contract calls
async function getQuote(tokenIn: Address, tokenOut: Address) {
  try {
    const quote = await quoter.quoteExactInput(...);
    return quote;
  } catch (error) {
    // Low-liquidity tokens WILL fail - this is expected
    console.warn(`Quote failed for ${tokenIn}->${tokenOut}:`, error.message);
    return null; // Continue processing other tokens
  }
}

// ✅ Validate before calling contracts
if (!isAddress(tokenAddress)) {
  throw new Error('Invalid token address');
}

// ✅ Handle "execution reverted" gracefully
if (error.message.includes('execution reverted')) {
  // Pool doesn't exist or insufficient liquidity
  return null;
}

// ✅ Multicall with individual error handling
const results = await multicall({
  contracts: tokens.map(t => ({ ... })),
  allowFailure: true, // CRITICAL
});
results.forEach((result, i) => {
  if (result.status === 'success') {
    // Use result.result
  } else {
    // Log and skip this token
  }
});
```

## Gas Estimation

```typescript
// ✅ Always estimate gas before sending
const gasEstimate = await contract.estimateGas.swap(...args);

// ✅ Add 10-20% buffer to gas estimates
const gasLimit = gasEstimate.mul(120).div(100);  // 20% buffer

// ✅ EIP-1559 gas pricing
const feeData = await provider.getFeeData();
const tx = {
  maxFeePerGas: feeData.maxFeePerGas,
  maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,
  gasLimit,
};

// ✅ Simulate before execution
try {
  await contract.callStatic.swap(...args);  // Dry run
  const tx = await contract.swap(...args);  // Real execution
} catch (e) {
  // Would revert - don't send
}

// ✅ Handle gas price spikes
if (feeData.maxFeePerGas > MAX_ACCEPTABLE_GAS) {
  throw new Error('Gas too high, waiting...');
}
```

## Multi-Chain Configuration

```typescript
// ✅ Chain-specific configuration
const CHAIN_CONFIG: Record<ChainId, ChainConfig> = {
  ethereum: {
    chainId: 1,
    rpcUrl: process.env.ETHEREUM_RPC_URL,
    blockTime: 12,
    confirmations: 2,
    nativeToken: 'ETH',
  },
  polygon: {
    chainId: 137,
    rpcUrl: process.env.POLYGON_RPC_URL,
    blockTime: 2,
    confirmations: 5,  // More confirmations for faster chains
    nativeToken: 'MATIC',
  },
};
```

## Transaction Management

```typescript
// ✅ Wait for confirmations
const receipt = await tx.wait(2);  // 2 confirmations

// ✅ Nonce management
class NonceManager {
  private pending = new Map<Address, number>();

  async getNextNonce(address: Address, provider: Provider): Promise<number> {
    const onChain = await provider.getTransactionCount(address, 'pending');
    const local = this.pending.get(address) ?? onChain;
    const next = Math.max(onChain, local);
    this.pending.set(address, next + 1);
    return next;
  }
}
```

## Rate Limiting & Retry

```typescript
// ✅ Exponential backoff
async function fetchWithRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (error.status === 429) {  // Rate limited
        const delay = Math.pow(2, attempt) * 1000;
        await sleep(delay);
        continue;
      }
      throw error;
    }
  }
  throw new Error('Max retries exceeded');
}

// ✅ Fallback RPC endpoints
const RPC_ENDPOINTS = [
  'https://eth-mainnet.alchemyapi.io/v2/KEY',
  'https://mainnet.infura.io/v3/KEY',
  'https://rpc.ankr.com/eth',
];
```

## Quick Checklist

- [ ] All contract calls wrapped in try/catch
- [ ] Multicall uses `allowFailure: true`
- [ ] Gas estimation with 20% buffer
- [ ] EIP-1559 gas pricing used
- [ ] Transaction simulation before send
- [ ] Nonce management for concurrent txs
- [ ] Confirmations appropriate per chain