
Arbitrum
- 5 installs
- 4 repo stars
- Updated February 25, 2026
- hairyf/blockchain-master
Understand the Arbitrum Nitro L2 stack: architecture, ArbOS, multi-dimensional gas, the BOLD dispute protocol, and repo conventions.
About
A reference for the Arbitrum Nitro node implementation covering Geth execution, ArbOS, WASM fraud proofs, and BOLD disputes. A developer uses it when working on or reasoning about the Nitro L2 stack.
- Nitro architecture (Geth, ArbOS, WASM proofs) and ADR conventions
- Multi-dimensional gas metering and BOLD assertion/edge-tracker dispute system
Arbitrum by the numbers
- 5 all-time installs (skills.sh)
- Ranked #338 of 479 Web3 & Blockchain skills by installs in the Skillselion catalog
- Data as of Jul 13, 2026 (Skillselion catalog sync)
npx skills add https://github.com/hairyf/blockchain-master --skill arbitrumAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 5 |
|---|---|
| repo stars | ★ 4 |
| Last updated | February 25, 2026 |
| Repository | hairyf/blockchain-master ↗ |
What it does
Understand the Arbitrum Nitro L2 stack: architecture, ArbOS, multi-dimensional gas, the BOLD dispute protocol, and repo conventions.
Files
Skill is based on Arbitrum Nitro (OffchainLabs/nitro), generated from source at the listed date. Main docs live at nitro-docs and developer.arbitrum.io.
Nitro is the current Arbitrum L2 stack: Geth for execution, ArbOS for L2 chain services (bridges, batching, compression), and WASM-based interactive fraud proofs. The Nitro repo contains the node implementation, ADRs, and the BOLD dispute protocol integration; run/build and operator docs are in the external documentation.
Core References
| Topic | Description | Reference |
|---|---|---|
| Nitro overview | Stack (Geth, ArbOS, WASM proofs), where docs live, audits | core-about |
| ADRs | MADR format, templates, adding decisions under docs/decisions/ | core-decisions-adr |
Features
| Topic | Description | Reference |
|---|---|---|
| Multi-dimensional gas | ResourceKind categories, L1/L2 calldata, WASM (Stylus) metering | features-multidimensional-gas |
| BOLD protocol | Dispute system, assertion poster/scanner, edge trackers, L2 state provider | features-bold-protocol |
Best Practices
| Topic | Description | Reference |
|---|---|---|
| Changelog fragments | Format, sections (Added/Changed/Configuration/Ignored), one file per PR | best-practices-changelog |
| Constraint types (Go) | Avoid primitive constraint wrappers; keep checks at call sites | best-practices-constraint-types |
Generation Info
- Source:
sources/arbitrum(https://github.com/OffchainLabs/nitro) - Git SHA:
890f0e293fca99c93b6476dc936e84359bb2a68d - Generated: 2026-02-24
Note: Primary Nitro documentation lives in nitro-docs and at developer.arbitrum.io. This skill is generated from the Nitro repo’s in-repo docs (README, docs/, bold/, CONTRIBUTING, changelog).
Changelog Fragments
Nitro uses changelog fragments in the changelog/ directory for release notes. Each PR that is release-note-worthy should add one new markdown file there; format follows Keep a Changelog.
Structure
Use standard section headers. Common ones:
### Added### Changed### Deprecated### Removed### Fixed### Security### Configuration– For new or changed config flags/options.### Ignored– For changes that should not appear in release notes (e.g. CI-only); the fragment is still required but content is not published.
Example (configuration change)
### Changed
- Replace static batch poster compression with backlog-based compression levels
### Deprecated
- Deprecate `--node.batch-poster.compression-level` in favor of `--node.batch-poster.compression-levels`
### Added
- New `--node.batch-poster.compression-levels` flag (JSON array of backlog/threshold configs)
### Configuration
- `--node.batch-poster.compression-levels`: JSON array of objects with `backlog`, `level`, `recompression-level`.
- Example: `[ { "backlog": 0, "level": 3, "recompression-level": 5 }, { "backlog": 10, "level": 5, "recompression-level": 7 } ]`
- Validation: `backlog` strictly ascending; levels non-increasing across entries; `recompression-level >= level`; levels in 0–11.Usage
1. Add a new file under changelog/ (e.g. yourname-brief-description.md). 2. Use the section headers above; one file per logical change. 3. For non–release-note changes, use the ### Ignored section so the fragment exists but is skipped in notes.
Key points
- One fragment per PR; filename and content follow Keep a Changelog.
- Use
### Configurationwhen adding or changing flags/config; include examples and validation rules when relevant. - Use
### Ignoredfor CI or internal-only changes.
<!-- Source references:
- https://github.com/OffchainLabs/nitro (CONTRIBUTING.md, changelog/*.md)
- https://keepachangelog.com/
-->
Constraint Types in Go (Nitro/BoLD)
When a function repeatedly requires a value to satisfy a simple invariant (e.g. “must be positive”), it’s tempting to introduce a constrained type (e.g. Pos64 wrapping uint64) so the invariant is enforced at construction. The Nitro/BoLD decision is to avoid such primitive constraint types and keep checking at call sites (status quo).
Why not constrained wrappers?
Consider a Pos64 type that only allows positive uint64:
- Pro: Single check at construction; functions take
Pos64and don’t re-check. - Con: The type no longer works with operators (
+,*,-,/); you lose expressiveness and must call.Val()or similar everywhere.
The tradeoff was evaluated as:
- New package (e.g. `util/chk`): Expressive and DRY, but operator use is lost.
- Status quo (check in multiple places): Slightly repetitive, but when a function is promoted to public or moved, the invariant still holds at each caller.
- Minimize checks (only at boundary): Fewer checks, but refactors (e.g. making a private function public) can easily introduce bugs.
Decision
Status quo: Keep checking the constraint at each place that needs it (e.g. “virtual must be positive”). Do not introduce a shared constrained wrapper type for primitive values like uint64 where operator support matters.
Usage
- When adding new code that assumes “positive” or similar invariants, validate at the boundary (e.g. at public API or at the start of a function that documents the precondition) and document the precondition.
- Do not add a
Pos64-style type to centralize the check if it would remove use of+/-/*//on the value.
Key points
- Prefer repeated, explicit checks over a constrained wrapper type when the wrapper would break normal operators.
- Keeping checks at each caller avoids subtle bugs when functions are refactored (e.g. private → public).
<!-- Source references:
- https://github.com/OffchainLabs/nitro (docs/decisions/0001-avoid-primitive-constraint-types.md)
-->
Arbitrum Nitro Overview
Nitro is the current Arbitrum L2 stack: a full optimistic rollup with sequencer, fraud proofs, token bridges, and calldata compression. In-repo docs are minimal; the main documentation lives in nitro-docs and the developer portal.
Stack components
- Execution: Geth (EVM) compiled into the L2 engine; no custom EVM emulator.
- Fraud proofs: Interactive fraud proofs over WASM. The Nitro engine is built with standard languages/tooling and compiles to native for normal execution; validators switch to WASM when a fraud proof is needed.
- ArbOS: Go component for L2 chain operations—cross-chain communication, batching, and compression to reduce L1 costs.
So: Nitro runs Geth at L2 on top of Ethereum and can prove fraud over Geth’s core compiled to WASM.
Practical use
- Building/running: Follow docs.arbitrum.io (e.g. run Nitro node, build Nitro). The Nitro repo README and CONTRIBUTING point to these.
- Audits: Audit reports.
- Migration: Arbitrum One moved from Classic to Nitro (see state migration, dapp migration).
Key points
- Nitro = Geth + ArbOS + WASM-based fraud proofs; main docs are in nitro-docs and developer.arbitrum.io.
- For run/build/contributing, use the external docs; the Nitro repo holds code, ADRs, and BOLD-related docs.
<!-- Source references:
- https://github.com/OffchainLabs/nitro (README.md)
- https://github.com/OffchainLabs/nitro/blob/main/docs/notice.md
-->
Architectural Decision Records (ADRs)
Nitro records architectural and code decisions in Markdown Architectural Decision Records under docs/decisions/. Format and templates follow MADR 4.0.0.
Format
Each ADR is a markdown file. Optional frontmatter can set status, date, decision-makers. Core sections:
- Context and Problem Statement – What is being decided and why.
- Considered Options – Bullet list of alternatives.
- Decision Outcome – Chosen option and short justification.
- Consequences (optional) – Good/bad effects.
Templates in docs/decisions/:
adr-template.md– Full sections with explanations.adr-template-minimal.md– Mandatory sections only (with optional Consequences).adr-template-bare.md/adr-template-bare-minimal.md– Same structure, empty (no explanations).
Usage
When adding a new ADR:
1. Copy one of the templates (e.g. adr-template-minimal.md). 2. Replace the placeholder title and fill Context, Options, Decision Outcome (and optionally Consequences). 3. Save under docs/decisions/ with a numeric prefix (e.g. 0003-my-decision.md).
Key points
- MADR 4.0.0 is the chosen format; templates live in
docs/decisions/. - Use ADRs for architecture, code, or process decisions so intent is explicit and reviewable later.
<!-- Source references:
- https://github.com/OffchainLabs/nitro (docs/decisions/README.md, docs/decisions/0000-use-markdown-architectural-decision-records.md)
- https://adr.github.io/madr/
-->
BOLD Protocol (Dispute System)
BOLD (Bounded Liquidity Delay) is the permissionless dispute system for Arbitrum chains. It provides a fixed upper bound on challenge confirmations so that, under deterministic state transitions, an honest participant always wins against invalid assertions.
Components (high level)
- Assertion Poster – Posts validated messages from the L2 validator onchain.
- Assertion Scanner – Watches L1 for new assertions and compares them to the local Nitro node via a L2 State Provider abstraction (
assertions/sync.go). - Challenge Manager – Opens onchain challenges (creates level-zero edges) when the node disagrees with an assertion; tracks edges as goroutines.
- Chain Watcher – Scans for other edges onchain and starts edge tracker goroutines for honest edges not yet tracked.
Edge tracker (per edge)
Each challenge edge is a goroutine (Edge Tracker) that:
- Wakes at a tick interval.
- Uses a finite state machine to choose the next move: bisect, one-step proof, or subchallenge.
- Reaches a Confirmed state when the level-zero edge is confirmed; then the assertion can be confirmed and the honest party wins.
Directory layout (BOLD repo)
api/– Monitoring and visualization.assertions/– Scanning and posting assertions.protocol/– Rollup contract bindings.challenge/– Challenge management and logic.containers/– Data structures, including FSMs.contracts/– Rollup/challenge contracts.state/– L2 backend state and proofs interface.commitment/– Proofs, history commitments, Merkleization.retry/,clock/,log/– Utilities.
Usage
- Integrating BOLD: Depend on the BOLD component; it needs an L2 State Provider (Nitro node) to get state and proofs.
- Understanding disputes: Assertions are posted to L1; if the local node disagrees, it challenges and edge trackers drive the protocol to confirmation.
- Research: See
docs/research-specs/(BOLDChallengeProtocol.pdf, TechnicalDeepDive.pdf, Economics.pdf) and ARCHITECTURE.md for diagrams and FSM.
Key points
- BOLD is a separate repo that plugs into Nitro; it handles assertion posting and permissionless challenges.
- L2 State Provider abstracts the Nitro node; edge trackers implement the challenge FSM per edge.
<!-- Source references:
- https://github.com/OffchainLabs/nitro (bold/README.md, bold/docs/ARCHITECTURE.md)
- https://github.com/OffchainLabs/bold
-->
Multi-Dimensional Gas Metering
Nitro uses a multi-dimensional gas model instead of a single uint64 gas counter. Gas is tracked per resource kind, so consumption can be measured and priced separately (e.g. computation vs state growth vs L1/L2 calldata).
ResourceKind categories
Each opcode’s dynamic gas is mapped to one or more of these kinds:
| Kind | Meaning | Examples |
|---|---|---|
| ResourceKindComputation | CPU-bound, no global state mutation | Opcode execution, memory expansion, call gas (EIP-150), value transfers (except new-account), CREATE/CREATE2, hashing, bloom updates |
| ResourceKindStorageAccess | Read (and write) access to global state | Account lookups (CALL, EXTCODESIZE, BALANCE), storage reads/writes, access list (EIP-2929/2930), Verkle proof traversal, DELEGATECALL/STATICCALL target resolution |
| ResourceKindStorageGrowth | Increase in persistent state size | New account creation, zero→nonzero storage, trie growth (EIP-4762), contract deployment deposit |
| ResourceKindHistoryGrowth | Append-only event log | LOG0–LOG4 |
| ResourceKindL1Calldata | Cost of posting data to L1 | L1 batch calldata |
| ResourceKindL2Calldata | L2 calldata processing | L2 tx calldata, precompile argument data |
| ResourceKindWasmComputation | Stylus WASM execution | WASM/Stylus program and contract execution |
Usage
- Pricing and policy: Adjust cost per resource kind independently (e.g. raise L1 calldata cost without changing pure compute).
- Analysis: Reason about gas in terms of computation vs state vs L1/L2 data.
- Stylus: Stylus contracts are metered under
ResourceKindWasmComputation(and any L2 calldata they use underResourceKindL2Calldata).
Key points
- Gas is multi-dimensional; each resource kind can have its own pricing.
- L1/L2 calldata and WASM computation are separate axes from EVM computation and storage.
<!-- Source references:
- https://github.com/OffchainLabs/nitro (docs/decisions/0002-multi-dimensional-gas-metering.md)
-->