# Opnet Development

> Build on Bitcoin Layer 1 with OP_NET - Bitcoin L1 consensus layer for trustless smart contracts. Use when building AssemblyScript smart contracts, TypeScript libraries, React frontends, or Node plugins for OPNet. Triggers on Bitcoin smart contract development, OP20 tokens, OP721 NFTs, WebAssembly contracts, verify-dont-custody patterns, epoch mining, and OPNet architecture questions.

- Skill: `btc-vision/opnet-development` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add btc-vision/opnet-development`
- Raw SKILL.md: https://api.skillmd.com/api/skills/btc-vision/opnet-development/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: btc-vision (https://skillmd.com/u/btc-vision)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/btc-vision/opnet-development

---


# OPNet Development Skill

A comprehensive skill for building on OPNet - Bitcoin's L1 consensus layer for trustless smart contracts.

---

# STEP 1: UNDERSTAND WHAT THE USER WANTS FIRST

**BEFORE reading any docs or guidelines, you MUST understand the user's request.**

1. Read the user's message carefully
2. Identify what type of project they need (contract, frontend, backend, plugin, audit, question)
3. Ask clarifying questions if the request is ambiguous
4. ONLY THEN proceed to read the docs listed for that project type

**Do NOT start reading all docs blindly. Understand the task first, then read only the relevant docs.**

---

# STEP 2: MANDATORY READING BEFORE ANY CODE

**IF YOU WRITE CODE WITHOUT READING THE REQUIRED DOCS, YOU WILL CREATE BROKEN, EXPLOITABLE CODE.**

---

## CRITICAL RULES FOR AI AGENTS

### ABSOLUTE RULE - NO RAW JAVASCRIPT

**NEVER write raw JavaScript. ALWAYS use:**
- **Frontend**: TypeScript + Vite + npm packages
- **Backend**: TypeScript + Node.js + npm packages
- **NO EXCEPTIONS. NOT EVEN FOR "QUICK EXAMPLES".**

### DO NOT:
- Read a few files and then say "I have enough context"
- Read random skills or guidelines not listed for your project type
- Start writing code after skimming 2-3 files
- Assume you know OPNet patterns from other frameworks
- Skip files because they "seem similar" to ones you read
- Create zip files or deliverables WITHOUT running `npm run lint` and `npm run typecheck`
- Say "run npm run lint to verify" instead of ACTUALLY running it

### YOU MUST:
- Read **EVERY SINGLE FILE** listed for your project type below
- Read them **IN ORDER** - later files depend on earlier ones
- Read the **COMPLETE FILE**, not just the first few sections
- **ONLY** read files listed in this skill - no random exploration
- Confirm you read all files before writing ANY code
- **ACTUALLY RUN** `npm install`, `npm run lint`, `npm run typecheck`, `npm run build`
- **FIX ALL ERRORS** before creating any deliverable (zip, PR, etc.)

---

## MANDATORY WORKFLOW RULES

### 1. CONTRACTS FIRST, THEN FRONTEND

**When a user asks for a website/dApp that interacts with a smart contract, you MUST build the `.wasm` contract FIRST before building the frontend.**

Workflow order:
1. Build and compile the AssemblyScript smart contract → verify `.wasm` output exists
2. Run contract tests to ensure correctness
3. THEN build the frontend that interacts with that contract

**Never build a frontend that references a contract that doesn't exist yet.**

### 2. WALLET INTEGRATION: ALWAYS USE `@btc-vision/opwallet`

**All OPNet websites MUST use `@btc-vision/opwallet` for OP_WALLET integration.**

OP_WALLET is the official and ONLY wallet that fully supports OPNet features (MLDSA signatures, quantum-resistant keys, full OPNet integration). Every frontend dApp MUST integrate it.

### 3. VITE IS MANDATORY — NO EXCEPTIONS

**All frontend projects MUST use Vite as the build tool.** No webpack, no parcel, no rollup standalone, no esbuild standalone. Vite only.

### 4. IPFS DEPLOYMENT: USE OPNET-CLI ONLY

**When publishing to IPFS:**
1. Build with Vite: `npm run build` (produces `dist/` folder)
2. The output is static HTML + JS + CSS files
3. **Upload using the opnet-cli IPFS upload script:**
   - **IPFS-only upload (no domain):** `bash /root/openclaw/skills/opnet-cli/scripts/ipfs-upload.sh ./dist`
   - **Upload + publish to .btc domain:** `bash /root/openclaw/skills/opnet-cli/scripts/ipfs-upload.sh ./dist mysite`
   - **Dry-run (upload but don't publish on-chain):** `bash /root/openclaw/skills/opnet-cli/scripts/ipfs-upload.sh ./dist mysite --dry-run`
4. The site must work as a fully static site — no server-side rendering, no API routes
5. All contract interactions happen client-side via the OPNet provider

**The `dist/` folder after `vite build` contains everything needed for IPFS deployment.**

**The upload script returns JSON with the CID and gateway URL:**
```json
{
  "cid": "QmXyz...",
  "files": 12,
  "totalSize": 245000,
  "gateway": "https://ipfs.opnet.org/ipfs/QmXyz..."
}
```

**FORBIDDEN IPFS methods — NEVER use any of these:**
- ❌ **Local IPFS daemon (Kubo)** — do NOT run `ipfs add`, `ipfs pin`, or any local Kubo commands
- ❌ **`ipfs-website` skill** — this skill is deprecated and deleted
- ❌ **Direct HTTP calls to IPFS API** — do NOT use `curl`, `fetch`, or any raw HTTP to IPFS endpoints
- ❌ **Uploading files one by one** — the script handles directory uploads with proper chunking
- ❌ **Any IPFS upload method other than the opnet-cli script above**

**ALWAYS use `bash /root/openclaw/skills/opnet-cli/scripts/ipfs-upload.sh` for ALL IPFS uploads. No exceptions.**

---

## COMMON AGENT MISTAKES — DO NOT REPEAT THESE

These are real mistakes observed across multiple AI agents. **If you make any of these, your code is broken.**

| Mistake | Why It's Wrong | Correct Approach |
|---------|---------------|-----------------|
| Using Keccak256 selectors (EVM style) | OPNet uses **SHA256**, not Keccak256. This is Bitcoin, not Ethereum. | Use SHA256 for all hashing and method selectors |
| Calling `approve()` on OP-20 tokens | OP-20 does NOT have `approve()`. It uses `increaseAllowance()` / `decreaseAllowance()` to prevent the well-known approve race condition. | Use `increaseAllowance(spender, amount)` and `decreaseAllowance(spender, amount)` |
| Passing `bc1p...` addresses to `Address.fromString()` | `Address.fromString()` takes TWO hex pubkey parameters, not a Bech32 address string | `Address.fromString(hashedMLDSAKey, tweakedPublicKey)` — both are hex strings |
| Using `bitcoinjs-lib` | OPNet has its own Bitcoin library with critical patches and 709x faster PSBT | Use `@btc-vision/bitcoin` — never `bitcoinjs-lib` |
| Factory-deploys-child-contract pattern | OPNet contracts cannot deploy other contracts. There is no `CREATE` or `CREATE2` opcode. | Deploy each contract separately, then link them via stored addresses |
| Skipping simulation before `sendTransaction()` | Bitcoin transfers are **irreversible**. If the contract reverts, your BTC is gone. | ALWAYS simulate first: `contract.method()` to simulate, then `result.sendTransaction(params)` only after confirming success |
| Using Express/Fastify/Koa for backends | These frameworks are **forbidden**. They are significantly slower. | Use `@btc-vision/hyper-express` and `@btc-vision/uwebsocket.js` only |
| Not running `npm-check-updates` after setup | Package versions drift constantly. Stale versions = build failures. | ALWAYS run `npx npm-check-updates -u && npm i eslint@^9.39.2 @eslint/js@^9.39.2 ...` (see Install Commands section) |
| Giving users `verifyECDSASignature` or `verifySchnorrSignature` without deprecation warning | Both ECDSA and Schnorr are **DEPRECATED**. ECDSA is gated behind `UNSAFE_QUANTUM_SIGNATURES_ALLOWED` and will break when consensus flips the flag. Schnorr is also deprecated but still works through the safe `verifySignature` path. Handing users the direct deprecated methods without warning sets them up for contract failure. | **ALWAYS warn first**: ECDSA and Schnorr are deprecated. Show `Blockchain.verifySignature(address, signature, hash)` as the ONLY correct approach — it is consensus-aware and auto-selects the right algorithm (Schnorr today, ML-DSA when enforced). NEVER point users to `verifyECDSASignature`, `verifyBitcoinECDSASignature`, or `verifySchnorrSignature` directly. Read `guidelines/ethereum-migration-guidelines.md` Section 3. |
| Using `MessageSigner.signMessage()` or `signMLDSAMessage()` instead of Auto methods | The non-Auto methods are environment-specific. `signMessage()` only works with local keypairs (backend), `signMLDSAMessage()` only works with OP_WALLET (browser). Using the wrong one = runtime crash. | **ALWAYS use Auto methods**: `MessageSigner.signMessageAuto()`, `tweakAndSignMessageAuto()`, `signMLDSAMessageAuto()`. These auto-detect whether you're in browser (OP_WALLET) or backend (local keypair) and call the right underlying method. NEVER use the non-Auto variants unless you have an explicit reason and know your environment. |

**If you catch yourself doing any of the above, STOP and fix it immediately.**

---

## WHY THIS MATTERS

OPNet development has:
- **Beta package versions** that change frequently - guessing versions = build failures
- **Strict TypeScript rules** - violations = security vulnerabilities
- **Platform-specific patterns** - wrong patterns = exploits, gas attacks, data loss

**Guidelines are SUMMARIES. The `docs/` folder contains the ACTUAL implementation patterns.**

**Reading 3-4 files is NOT enough. You MUST read ALL files for your project type.**

---

## MANDATORY READING ORDER BY PROJECT TYPE

### For ALL Projects (Read First, Every Time)

| Order | File | Why |
|-------|------|-----|
| 1 | `docs/core-typescript-law-CompleteLaw.md` | **THE LAW** - Type system rules, forbidden constructs, required patterns |
| 2 | `guidelines/setup-guidelines.md` | Package versions, tsconfig, ESLint configs |

---

### For Smart Contracts (AssemblyScript)

**Read ALL of these BEFORE writing contract code:**

| Order | File | Contains |
|-------|------|----------|
| 1 | `docs/core-typescript-law-CompleteLaw.md` | Type rules (applies to AS too) |
| 2 | `guidelines/setup-guidelines.md` | Package versions, asconfig.json |
| 3 | `guidelines/contracts-guidelines.md` | Summary of contract patterns |
| 4 | `docs/contracts-btc-runtime-README.md` | Runtime overview |
| 5 | `docs/contracts-btc-runtime-getting-started-installation.md` | Setup |
| 6 | `docs/contracts-btc-runtime-getting-started-first-contract.md` | Entry point, factory pattern |
| 7 | `docs/contracts-btc-runtime-getting-started-project-structure.md` | Directory layout |
| 8 | `docs/contracts-btc-runtime-core-concepts-storage-system.md` | Storage types, pointers |
| 9 | `docs/contracts-btc-runtime-core-concepts-pointers.md` | Pointer allocation |
| 10 | `docs/contracts-btc-runtime-api-reference-safe-math.md` | SafeMath (MANDATORY for u256) |
| 11 | `docs/contracts-btc-runtime-gas-optimization.md` | Gas patterns, forbidden loops |
| 12 | `docs/contracts-btc-runtime-core-concepts-security.md` | Security checklist |

**For OP20 tokens, also read:**
- `docs/contracts-btc-runtime-api-reference-op20.md`
- `docs/contracts-btc-runtime-contracts-op20-token.md`

**For OP721 NFTs, also read:**
- `docs/contracts-btc-runtime-api-reference-op721.md`
- `docs/contracts-btc-runtime-contracts-op721-nft.md`

---

### For Frontend (React/Vite)

**Read ALL of these BEFORE writing frontend code:**

| Order | File | Contains |
|-------|------|----------|
| 1 | `docs/core-typescript-law-CompleteLaw.md` | Type rules, forbidden constructs |
| 2 | `guidelines/setup-guidelines.md` | Package versions, vite config |
| 3 | `guidelines/frontend-guidelines.md` | Summary of frontend patterns |
| 4 | `docs/core-opnet-README.md` | Client library overview |
| 5 | `docs/core-opnet-getting-started-installation.md` | Installation |
| 6 | `docs/core-opnet-getting-started-quick-start.md` | Quick start |
| 7 | `docs/core-opnet-providers-json-rpc-provider.md` | Provider setup |
| 8 | `docs/core-opnet-providers-internal-caching.md` | Caching (MANDATORY) |
| 9 | `docs/core-opnet-contracts-instantiating-contracts.md` | Contract instances |
| 10 | `docs/core-opnet-contracts-simulating-calls.md` | Read operations |
| 11 | `docs/core-opnet-contracts-sending-transactions.md` | Write operations |
| 12 | `docs/core-opnet-contracts-transaction-configuration.md` | Transaction options |
| 13 | `docs/core-transaction-transaction-factory-interfaces.md` | **Advanced TX params (fees, notes, anchors)** |
| 14 | `docs/clients-walletconnect-README.md` | Wallet connection |
| 15 | `docs/frontend-motoswap-ui-README.md` | **THE STANDARD** - Reference implementation |

---

### For Backend/API (Node.js)

**Read ALL of these BEFORE writing backend code:**

| Order | File | Contains |
|-------|------|----------|
| 1 | `docs/core-typescript-law-CompleteLaw.md` | Type rules, forbidden constructs |
| 2 | `guidelines/setup-guidelines.md` | Package versions |
| 3 | `guidelines/backend-guidelines.md` | Summary of backend patterns |
| 4 | `docs/core-opnet-backend-api.md` | **REQUIRED FRAMEWORKS** - hyper-express, uWebSockets.js |
| 5 | `docs/core-opnet-providers-json-rpc-provider.md` | Provider setup |
| 6 | `docs/core-opnet-providers-threaded-http.md` | Threading (MANDATORY) |
| 7 | `docs/core-opnet-providers-internal-caching.md` | Caching (MANDATORY) |
| 8 | `docs/core-opnet-contracts-instantiating-contracts.md` | Contract instances |
| 9 | `docs/core-opnet-contracts-sending-transactions.md` | Sending transactions |
| 10 | `docs/core-transaction-transaction-factory-interfaces.md` | **Advanced TX params (fees, notes, anchors)** |

**FORBIDDEN FRAMEWORKS:** Express, Fastify, Koa, Hapi, Socket.io - use hyper-express and uWebSockets.js only.

---

### For Plugins (OPNet Node)

**Read ALL of these BEFORE writing plugin code:**

| Order | File | Contains |
|-------|------|----------|
| 1 | `docs/core-typescript-law-CompleteLaw.md` | Type rules, forbidden constructs |
| 2 | `guidelines/setup-guidelines.md` | Package versions |
| 3 | `guidelines/plugin-guidelines.md` | Summary of plugin patterns |
| 4 | `docs/core-OIP-OIP-0003.md` | **PLUGIN SPECIFICATION** - Full spec |
| 5 | `docs/plugins-plugin-sdk-README.md` | SDK reference |
| 6 | `docs/plugins-opnet-node-README.md` | Node integration |

**CRITICAL:** You MUST implement `onReorg()` to handle chain reorganizations or your data will be inconsistent.

---

### For Unit Tests (TypeScript)

**Read ALL of these BEFORE writing test code:**

| Order | File | Contains |
|-------|------|----------|
| 1 | `docs/core-typescript-law-CompleteLaw.md` | Type rules |
| 2 | `guidelines/setup-guidelines.md` | Package versions |
| 3 | `guidelines/unit-testing-guidelines.md` | Summary of test patterns |
| 4 | `docs/testing-unit-test-framework-README.md` | Framework overview |
| 5 | `docs/testing-opnet-unit-test-README.md` | Test setup |
| 6 | `docs/testing-opnet-unit-test-docs-Blockchain.md` | Blockchain mocking |
| 7 | `docs/testing-opnet-unit-test-docs-ContractRuntime.md` | Contract runtime |

**CRITICAL:** Unit tests are TypeScript (NOT AssemblyScript). They have a SEPARATE package.json.

---

### For Generic Questions (Architecture, Concepts, Best Practices)

**Read:** `guidelines/generic-questions-guidelines.md`

For questions like:
- "How does OPNet work?"
- "Can OPNet survive 51% attacks?"
- "How does airdrop work on OPNet?"
- "What's the difference between OPNet and Runes/Ordinals?"
- "Why can't contracts hold BTC?"
- "What is transaction pinning?"
- "How is OPNet different from Ethereum?"
- "How do I port my Solidity contract to OPNet?"
- "What's the equivalent of ecrecover on OPNet?"

**See the full guideline for complete topic mappings and what docs to read for each question type.**

**For Ethereum migration questions:** Read `guidelines/ethereum-migration-guidelines.md` -- covers concept mapping from Ethereum to OPNet (addresses, signatures, tokens, wallets, transactions, DEX patterns).

**CRITICAL -- ecrecover / ECDSA / Schnorr / signature verification questions:**
When a user asks about `ecrecover`, ECDSA, Schnorr, or signature verification, you MUST:
1. **Warn FIRST** that both ECDSA and Schnorr are **DEPRECATED** on OPNet. ECDSA will break when consensus disables `UNSAFE_QUANTUM_SIGNATURES_ALLOWED`. Schnorr is also deprecated but still works through the safe `verifySignature` path.
2. **Show the ONLY correct approach**: `Blockchain.verifySignature(address, signature, hash)` -- this is consensus-aware, auto-selects the right algorithm (Schnorr today, ML-DSA when enforced), and is the ONLY future-proof method.
3. **Show client-side signing with AUTO methods ONLY**: `MessageSigner.signMessageAuto()` / `tweakAndSignMessageAuto()` / `signMLDSAMessageAuto()`. These auto-detect browser (OP_WALLET) vs backend (local keypair) and call the right method. NEVER use the non-Auto variants (`signMessage()`, `signMLDSAMessage()`, `tweakAndSignMessage()`) -- they are environment-specific and will crash in the wrong context.
4. **NEVER point users to** `verifyECDSASignature`, `verifyBitcoinECDSASignature`, or `verifySchnorrSignature` directly. These are deprecated internal methods.
5. **Read** `guidelines/ethereum-migration-guidelines.md` Section 3 BEFORE answering.

Do NOT just hand users deprecated APIs or environment-specific signing methods. Their code WILL break. Show them `verifySignature` for contract-side and `*Auto()` methods for client-side.

**IMPORTANT: For conceptual questions, read the relevant docs/sections BEFORE answering. Do not guess or make assumptions about how OPNet works.**

---

### For Security Auditing

---

# STOP - MANDATORY READING BEFORE ANY AUDIT

**IF YOU AUDIT CODE WITHOUT READING THE REQUIRED DOCS, YOU WILL MISS CRITICAL VULNERABILITIES.**

OPNet audits require understanding:
- **AssemblyScript runtime internals** - serialization, storage, cache coherence
- **Bitcoin-specific attack vectors** - transaction pinning, malleability, reorgs
- **Critical vulnerability patterns** - that standard audits miss completely

**You MUST read `guidelines/audit-guidelines.md` COMPLETELY before auditing ANY code.**

**Skipping the audit guidelines = missing vulnerabilities. There are no shortcuts.**

---

#### DISCLAIMER (MANDATORY IN EVERY REPORT)

```
IMPORTANT DISCLAIMER: This audit is AI-assisted and may contain errors,
false positives, or miss critical vulnerabilities. This is NOT a substitute
for a professional security audit by experienced human auditors.
Do NOT deploy to production based solely on this review.
Always engage professional auditors for contracts handling real value.
```

---

#### Mandatory Reading Order for Audits

**Read ALL of these IN ORDER before starting ANY audit:**

| Order | File | Why Required |
|-------|------|--------------|
| 1 | `docs/core-typescript-law-CompleteLaw.md` | Type rules that define secure code |
| 2 | `guidelines/audit-guidelines.md` | **COMPLETE AUDIT GUIDE** - vulnerability patterns, checklists, detection methods |

**Then read based on code type:**

| Code Type | Additional Required Reading |
|-----------|----------------------------|
| Smart Contracts | `docs/contracts-btc-runtime-core-concepts-security.md`, `docs/contracts-btc-runtime-gas-optimization.md`, `docs/contracts-btc-runtime-api-reference-safe-math.md`, `docs/contracts-btc-runtime-types-bytes-writer-reader.md` |
| DEX/Swap Code | This SKILL.md - CSV, NativeSwap, Slashing sections |
| Frontend | `guidelines/frontend-guidelines.md` |
| Backend | `guidelines/backend-guidelines.md` |
| Plugins | `guidelines/plugin-guidelines.md` - Reorg Handling section |

---

#### AUDIT VERIFICATION CHECKPOINT

**BEFORE writing ANY audit findings, confirm:**

- [ ] I have read `guidelines/audit-guidelines.md` completely
- [ ] I have read `docs/core-typescript-law-CompleteLaw.md` completely
- [ ] I have read ALL additional docs for this code type
- [ ] I understand the Critical Runtime Vulnerability Patterns section
- [ ] I understand serialization/deserialization consistency requirements
- [ ] I understand storage system cache coherence issues
- [ ] I understand Bitcoin-specific attack vectors (CSV, pinning, reorgs)

**If you cannot check ALL boxes, GO BACK AND READ THE DOCS.**

---

#### Smart Contract Audit Checklist (Summary)

**See `guidelines/audit-guidelines.md` for COMPLETE checklists with detection patterns.**

| Category | Check For |
|----------|-----------|
| **Arithmetic** | All u256 operations use SafeMath (no raw `+`, `-`, `*`, `/`) |
| **Overflow/Underflow** | SafeMath.add(), SafeMath.sub(), SafeMath.mul(), SafeMath.div() |
| **Access Control** | onlyOwner checks, authorization on sensitive methods |
| **Reentrancy** | State changes BEFORE external calls (checks-effects-interactions) |
| **Gas/Loops** | No `while` loops, all `for` loops bounded, no unbounded iterations |
| **Storage** | No iterating all map keys, stored aggregates for totals |
| **Input Validation** | All user inputs validated, bounds checked |
| **Integer Handling** | u256 created via fromString() for large values, not arithmetic |
| **Serialization** | Write/read type consistency, sizeof<T>() mapping correct |
| **Cache Coherence** | Setters load from storage before comparison |
| **Deletion Markers** | Storage deletion uses 32-byte EMPTY_BUFFER |
| **Bounds Checking** | `>=` not `>` for max index checks |

#### TypeScript/Frontend/Backend Audit Checklist (Summary)

| Category | Check For |
|----------|-----------|
| **Type Safety** | No `any`, no non-null assertions (the ! operator), no `@ts-ignore` |
| **Null Safety** | Explicit null checks, optional chaining used correctly |
| **BigInt** | All satoshi/token amounts use `bigint`, not `number` |
| **No Floats** | No floating point for financial calculations |
| **Caching** | Provider/contract instances cached, not recreated |
| **Input Validation** | Address validation, amount validation, bounds checking |
| **Error Handling** | Errors caught and handled, no silent failures |
| **Provider Type** | Use JSONRpcProvider (WebSocketProvider is experimental) |

#### Bitcoin-Specific Audit Checklist (Summary)

| Category | Check For |
|----------|-----------|
| **CSV Timelocks** | All swap recipient addresses use CSV (anti-pinning) |
| **UTXO Handling** | Proper UTXO selection, dust outputs avoided |
| **Transaction Malleability** | Signatures not assumed immutable before confirmation |
| **Fee Sniping** | Proper locktime handling |
| **Reorg Handling** | Data deleted/reverted for reorged blocks |
| **P2WPKH** | Only compressed pubkeys (33 bytes), reject uncompressed |
| **Witness Script Size** | Validate against 3,600 byte standard limit |

#### DEX/Swap Audit Checklist (Summary)

| Category | Check For |
|----------|-----------|
| **Reservation System** | Prices locked at reservation, not execution |
| **Slippage Protection** | Maximum slippage enforced |
| **Front-Running** | Reservation system prevents front-running |
| **Queue Manipulation** | Slashing penalties for queue abuse |
| **Partial Fills** | Atomic coordination of multi-provider payments |

#### Critical Runtime Vulnerability Patterns (Summary)

**See `guidelines/audit-guidelines.md` for COMPLETE patterns with code examples.**

| ID | Vulnerability | Impact |
|----|---------------|--------|
| C-07 | Serialization Mismatch (write u16, read u32) | Data corruption |
| C-08 | sizeof<T>() bytes treated as bits | Truncated data |
| C-09 | Signed/unsigned type confusion (i8 → u8) | Sign loss |
| C-10 | Cache coherence (setter compares to unloaded cache) | Silent state corruption |
| C-11 | Wrong deletion marker size | has() returns wrong result |
| C-12 | Generic integer truncation (only reading first byte) | Data loss |
| H-06 | Index out of bounds | Memory corruption |
| H-07 | Off-by-one (`>` instead of `>=`) | Buffer overflow |
| H-08 | Pointer collision (truncate without hash) | Storage overwrites |
| M-05 | Taylor series divergence | Incorrect math |

**ALWAYS end audit reports with the disclaimer. NEVER claim the audit is complete or guarantees security.**

---

## VERIFICATION CHECKPOINT

**BEFORE writing ANY code, you MUST be able to answer:**

1. **What project type am I building?** (Contract / Frontend / Backend / Plugin / Tests)

2. **Did I read EVERY file listed for this project type?**
   - List each file you read
   - If you cannot list them all, GO BACK AND READ

3. **What are the exact package versions?** (from `guidelines/setup-guidelines.md`)
   - If you don't know, GO BACK AND READ

4. **What constructs are FORBIDDEN?**
   - `any`, non-null assertion operator, `while` loops in contracts, `number` for satoshis, etc.
   - If you can't list them, GO BACK AND READ

5. **What patterns are REQUIRED?**
   - Caching, SafeMath, threading, etc.
   - If you can't list them, GO BACK AND READ

---

### STOP - DO NOT PROCEED IF:

- ❌ You read fewer than 5 docs files
- ❌ You skipped any file in the mandatory reading list
- ❌ You read files not listed for your project type
- ❌ You cannot list the exact package versions
- ❌ You're about to write "I have enough context" after reading 2-3 files

**GO BACK AND READ ALL THE REQUIRED FILES. NO SHORTCUTS.**

---

## CODE VERIFICATION ORDER (MANDATORY)

**You MUST actually RUN these commands, not just mention them.**

### Step 1: Install Dependencies

**For Non-Contract Projects:**
```bash
npx npm-check-updates -u && npm i eslint@^9.39.2 @eslint/js@^9.39.2 @btc-vision/bitcoin@rc @btc-vision/transaction@rc opnet@rc @btc-vision/bip32 @btc-vision/ecpair --prefer-online
```

**For Contract Projects:**
```bash
npx npm-check-updates -u && npm i eslint@^9.39.2 @eslint/js@^9.39.2 @btc-vision/opnet-transform@1.1.0 @btc-vision/assemblyscript@^0.29.2 @btc-vision/as-bignum@0.1.2 @btc-vision/btc-runtime@rc --prefer-online
```

- Run the appropriate command FIRST before any other commands
- If package.json was created or modified, this is REQUIRED
- Do NOT skip this step - do NOT just run `npm install` alone

### Step 2: Run Prettier
```bash
npm run format
```
- Formats all code consistently
- Run BEFORE linting to avoid formatting conflicts
- Do NOT skip this step

### Step 3: Run ESLint
```bash
npm run lint
```
- MUST pass with zero errors
- If errors exist, FIX THEM before proceeding
- Do NOT say "you should run lint" - actually RUN IT

### Step 4: Run TypeScript Check
```bash
npm run typecheck
```
- Or `npx tsc --noEmit` if no script exists
- MUST pass with zero errors
- Fix all type errors before proceeding

### Step 5: Build
```bash
npm run build
```
- Only run AFTER format, lint, and typecheck pass
- For contracts: verify .wasm file is generated

### Step 6: Run Tests
```bash
npm run test
```
- Or `npx ts-node --esm tests/*.test.ts` for unit tests
- All tests MUST pass
- If tests fail, FIX THE CODE

---

### STOP - YOU MUST ACTUALLY RUN THESE COMMANDS

- ❌ Do NOT just write "run npm run lint to verify"
- ❌ Do NOT skip steps because "it should work"
- ❌ Do NOT consider code complete without running ALL steps
- ✅ Actually execute each command
- ✅ Verify each command passes
- ✅ Fix any errors before proceeding to next step

**If you wrote code but didn't run these commands, YOUR TASK IS NOT COMPLETE.**

---

## TASK COMPLETION CHECKPOINT

**BEFORE considering ANY task complete, ask yourself these questions:**

1. **Have I performed all the steps required by the task?**
   - Did I address everything the user asked for?
   - Did I miss any requirements?

2. **Did I actually run the verification commands?**
   - Did I run `npm install`? (REQUIRED if package.json exists/changed)
   - Did I run `npm run format`? (REQUIRED - Prettier formatting)
   - Did I run `npm run lint`? (REQUIRED - must pass with zero errors)
   - Did I run `npm run typecheck` or `npx tsc --noEmit`? (REQUIRED)
   - Did I run `npm run build`? (REQUIRED for deployable code)
   - Did I run `npm run test`? (REQUIRED if tests exist)
   - **If ANY command failed, did I fix the errors?**
   - **"I should run lint" is NOT the same as actually running it**

3. **Did I review and reconsider my work?**
   - Re-read what I produced - is it correct?
   - Did I make any assumptions that could be wrong?
   - Are there edge cases I didn't consider?
   - Could my code/answer introduce bugs or vulnerabilities?
   - For smart contracts: SafeMath, bounds checking, access control, serialization
   - For TypeScript: type safety, null handling, caching patterns
   - For answers: Is the information accurate? Did I verify it?

4. **Did I write complete, production-ready code?**
   - **NEVER** add comments like "in a production environment, you would..."
   - **NEVER** add stubs, placeholders, or TODO comments
   - **NEVER** write partial implementations with "add your logic here"
   - If you can't implement something fully, explain why and ask the user
   - All code must be ready to use immediately, not a starting point

5. **Is it appropriate to adjust non-code files?**
   - Did I update documentation if behavior changed?
   - Did I update config files if dependencies changed?

6. **Should new tests be written?**
   - If I added new functionality, are there tests for it?
   - Do the tests cover security patterns from the guidelines?

7. **Is this just exploration/research?**
   - If yes, tests, linting, and auditing are not required
   - Focus on providing accurate information

**This self-reflection prevents incomplete work, missed requirements, and security vulnerabilities.**

---

## PROJECT DELIVERY

---

### STOP - BEFORE CREATING ANY ZIP OR DELIVERABLE

**You MUST run and PASS all verification commands BEFORE packaging:**

```bash
# 1. Install dependencies (use the appropriate command for your project type)
# Non-contract:
npx npm-check-updates -u && npm i eslint@^9.39.2 @eslint/js@^9.39.2 @btc-vision/bitcoin@rc @btc-vision/transaction@rc opnet@rc @btc-vision/bip32 @btc-vision/ecpair --prefer-online
# Contract:
npx npm-check-updates -u && npm i eslint@^9.39.2 @eslint/js@^9.39.2 @btc-vision/opnet-transform@1.1.0 @btc-vision/assemblyscript@^0.29.2 @btc-vision/as-bignum@0.1.2 @btc-vision/btc-runtime@rc --prefer-online

# 2. Format code
npm run format

# 3. Lint (MUST PASS)
npm run lint

# 4. TypeScript check (MUST PASS)
npm run typecheck
# OR: npx tsc --noEmit

# 5. Build (MUST SUCCEED)
npm run build

# 6. Tests (MUST PASS)
npm run test
```

**If ANY command fails, DO NOT create the zip. Fix the errors first.**

❌ **FORBIDDEN:** Creating zip without running verification commands
❌ **FORBIDDEN:** Saying "run npm run lint to verify" instead of actually running it
❌ **FORBIDDEN:** Skipping typecheck because "it should work"

---

**When creating zip files for delivery:**

**NEVER include:**
- `node_modules/` - recipient runs `npm install`
- `build/` or `dist/` - recipient runs `npm run build`
- `.git/` - repository history
- `.env` - contains secrets

**Correct zip command (only AFTER all checks pass):**
```bash
zip -r project.zip . -x "node_modules/*" -x "build/*" -x "dist/*" -x ".git/*" -x "*.wasm" -x ".env"
```

---

## What is OPNet

OPNet is a **Bitcoin L1 consensus layer** enabling smart contracts directly on Bitcoin. It is:

- **NOT a metaprotocol** - It's a full consensus layer
- **Fully trustless** - No centralized components
- **Permissionless** - Anyone can participate
- **Decentralized** - Relies on Bitcoin PoW + OPNet epoch SHA1 mining

### Security Model

After 20 blocks, an epoch is buried deep enough that changing it requires rewriting Bitcoin history at **millions of dollars per hour**, making OPNet state **more final than Bitcoin's 6-confirmation security**.

The **checksum root** for each epoch is a cryptographic fingerprint of the entire state. If even one bit differs, the checksum changes completely and proof fails, making **silent state corruption impossible**.

### Key Principles

1. **Contracts are WebAssembly** (AssemblyScript) - Deterministic execution
2. **NON-CUSTODIAL** - Contracts NEVER hold BTC
3. **Verify-don't-custody** - Contracts verify L1 tx outputs, not hold funds
4. **Partial reverts** - Only consensus layer execution reverts; Bitcoin transfers are ALWAYS valid
5. **No gas token** - Uses Bitcoin directly
6. **CSV timelocks are MANDATORY** - All addresses receiving BTC in swaps MUST use CSV (CheckSequenceVerify) to prevent transaction pinning attacks

### Why OPNet Requires Consensus (Not Just Indexing)

OPNet is fundamentally different from indexer-based protocols like Runes, Ordinals/BRC-20, or Alkanes:

| Protocol | State Consistency | Can Different Nodes Disagree? |
|----------|-------------------|-------------------------------|
| Runes | Indexer-dependent | Yes - no consensus mechanism |
| BRC-20 | Indexer-dependent | Yes - no consensus mechanism |
| Alkanes | Indexer-dependent | Yes - WASM is deterministic but no consensus |
| **OPNet** | **Cryptographic consensus** | **No - proof-of-work + attestations enforce agreement** |

**Why this matters**: For applications requiring binding state consistency (like DEXs, escrows, or any multi-party coordination), indexer disagreement is catastrophic. When NativeSwap locks a reservation at a specific price, EVERY node must agree that reservation exists. OPNet's consensus layer guarantees this through cryptographic proofs.

---

## CSV: The Critical Anti-Pinning Mechanism (MANDATORY)

### What is Transaction Pinning?

Transaction pinning is a **catastrophic attack vector** that most Bitcoin protocols ignore. Here's how it works:

1. When you send Bitcoin to someone, they can immediately create a transaction spending that Bitcoin, **even before the first transaction is confirmed**
2. An attacker creates massive chains of unconfirmed transactions, all dependent on each other
3. This makes it **impossible for miners to include your legitimate transaction** in a block
4. Your transaction is stuck in mempool limbo while the attacker manipulates contract state

### Why Pinning Destroys DEXs Without Protection

**Attack scenario on an unprotected DEX:**

1. Attacker pins your swap transaction, preventing confirmation
2. Your reservation expires, but your BTC is stuck in mempool
3. Attacker cancels their sell orders or manipulates pool state
4. When your transaction finally confirms (if ever), no tokens remain
5. **Result**: Attacker gets free money, you lose everything

This vulnerability exists in **every Bitcoin protocol** that doesn't mandate CSV:
- Multisig bridges can be frozen entirely with one malicious unwrap request
- Ordinals marketplaces are vulnerable
- Runes trading platforms are vulnerable
- BRC-20 exchanges are vulnerable

### The CSV Solution

**CSV (CheckSequenceVerify, BIP 112)** completely eliminates pinning attacks:

```
Without CSV: Maximum unconfirmed chain length = UNLIMITED (attackers can pin forever)
With CSV:    Maximum unconfirmed chain length = ZERO (must wait for confirmation)
```

By requiring all seller addresses to have a **1-block CSV timelock**, once Bitcoin arrives at those addresses, it **cannot be spent again for at least one block**. This is mathematically provable and completely closes the attack vector.

### Implementation Requirement

**ALL addresses receiving BTC in OPNet swaps MUST use CSV timelocks.**

This is enforced at the protocol level in NativeSwap. If you're building any application that coordinates BTC transfers with smart contract state, you MUST implement CSV protection.

---

## The Two Address Systems (CRITICAL for Airdrops)

### Why OPNet Airdrops Work Differently Than Ethereum

On **Ethereum**, there's one address format. You can loop through addresses and call `transfer(to, amount)` because ERC20 contracts just decrement sender balance and increment recipient balance using the same address type.

On **OPNet**, contract balances are keyed by **ML-DSA public key hashes** (32-byte quantum-resistant addresses), but users are typically known externally by their **Bitcoin addresses** (Taproot P2TR, tweaked public keys). These are **completely different cryptographic systems** with no inherent link between them.

| Address System | Format | Used For |
|---------------|--------|----------|
| **Bitcoin Address** | Taproot P2TR (`bc1p...`) | External identity, what you have in your airdrop list |
| **OPNet Address** | ML-DSA public key hash (32 bytes) | Contract balances, internal state |

### WHY YOU CANNOT JUST LOOP AND TRANSFER

If you have a list of Bitcoin addresses from token holders or snapshot participants:

```typescript
// WRONG - THIS DOES NOT WORK
for (const btcAddress of airdropList) {
    await token.transfer(btcAddress, amount);  // IMPOSSIBLE
}
```

**The contract literally cannot credit tokens to a Bitcoin address directly.** The contract storage uses ML-DSA addresses, not Bitcoin addresses. The mapping between them only exists once a user explicitly proves ownership of both keys together.

### THE CORRECT SOLUTION: Claim-Based Airdrop Contract

Airdrops on OPNet are done via a **smart contract** with a claim pattern:

**1. Deploy an airdrop contract** that stores allocations keyed by tweaked public key:
```typescript
// Contract storage
mapping(tweakedPubKey => amount)  // Store: which Bitcoin addresses get how much
mapping(tweakedPubKey => claimed) // Track: has this allocation been claimed
```

**2. Users call `claim()`** providing a signature that proves they control that Bitcoin address:
```typescript
// User's frontend (browser) - OP_WALLET signs automatically
const message = `Claim airdrop for ${contractAddress}`;
const signed = await MessageSigner.tweakAndSignMessageAuto(message);

// Submit to contract with signature in calldata
await airdropContract.claim(signature, messageHash);
```

**3. Contract verifies and transfers:**
```typescript
// Contract logic
public claim(calldata: Calldata): BytesWriter {
    const signature = calldata.readBytes(64);
    const messageHash = calldata.readBytes(32);

    // Verify signature proves caller owns the tweaked public key
    if (!Blockchain.verifySignature(Blockchain.tx.origin, signature, messageHash, false)) {
        throw new Revert('Invalid signature');
    }

    // Get allocation for this tweaked public key
    const tweakedKey = Blockchain.tx.origin.tweakedPublicKey;
    const amount = this.allocations.get(tweakedKey);

    // Transfer to caller's ML-DSA address (now linked!)
    this._mint(Blockchain.tx.sender, amount);
    this.claimed.set(tweakedKey, true);
}
```

**This is the "unlock transaction"** - the moment where the user proves ownership of both identities (Bitcoin address AND ML-DSA address), allowing the contract to link them and credit the tokens.

### The Banana Locker Analogy

- You know 300 monkeys by their **face** (Bitcoin address)
- Lockers open with a **secret handshake** (ML-DSA key)
- You label lockers with faces and put bananas inside
- When a monkey shows up, they show face AND do handshake
- System learns: "this face = this handshake" and gives them their banana
- **The banana was always "theirs" but they couldn't access it until they linked face to handshake**

---

## NativeSwap: How to Build a Real DEX on Bitcoin

NativeSwap answers the biggest unanswered question in BitcoinFi: **How do you build an actual AMM that trades native BTC for tokens, trustlessly, without custody?**

### The Fundamental Problem

Traditional AMMs (like Uniswap) hold both assets in a pool and use math to set prices. **Bitcoin cannot do this** - you literally cannot have a smart contract hold and programmatically transfer BTC.

**Why common "solutions" fail:**
- **Multisig wallets**: Trusted parties can collude or disappear
- **Wrapped BTC**: Bridges become honeypots (billions stolen from bridges)
- **Pure order books**: Terrible liquidity without market makers holding inventory

### Virtual Reserves: The Solution

NativeSwap realizes that an AMM doesn't need to physically hold assets - it just needs to **track the economic effect of trades**. This is similar to:
- Banks updating ledger entries without moving physical cash
- Futures markets trading billions in commodities without touching a barrel of oil
- Clearinghouses settling trillions without holding underlying assets

**How it works:**
1. The contract maintains two numbers: `bitcoinReserve` and `tokenReserve`
2. When someone buys tokens with BTC, the system records that bitcoin reserve increased and token reserve decreased
3. The actual BTC goes **directly to sellers**, not to the contract
4. AMM pricing only depends on the **ratio** between reserves
5. The constant product formula (`bitcoinReserve × tokenReserve = k`) works identically whether reserves are physical or virtual

### Two-Phase Commit: Why Reservations Are Necessary

**Problem**: OPNet can revert smart contract execution, but it **cannot reverse Bitcoin transfers**. Once you send BTC, that transfer is governed by Bit

…(truncated)
