# Getting started

Citrea is the first rollup that enhances the capabilities of Bitcoin blockspace with zero knowledge technology. Citrea is the only scalability solution that uses Bitcoin both as a data availability and a settlement layer, via its BitVM-based trust-minimized two-way peg program - [Clementine](/essentials/clementine-trust-minimized-bitcoin-bridge). Citrea is fully EVM compatible, enabling all EVM developers to easily build on Bitcoin.

This documentation serves as a knowledge base for both developers and users. If you're a developer, you can check our [developer documentation](/developer-documentation/developer-documentation), and if you're a user, you can start using the Citrea Mainnet by [bridging to Citrea](https://citrea.xyz/bridge). Along with that, you can check our architecture and security properties from the links in the sidebar.

You can also join our community or follow us from the links below:

* [Join our Discord](https://discord.gg/citrea)
* [Follow us on Twitter | X](https://x.com/citrea_xyz)
* [Website](https://citrea.xyz)


# Chain Information - Quickstart

## Core Parameters

<table data-header-hidden><thead><tr><th valign="middle">Config</th><th></th></tr></thead><tbody><tr><td valign="middle"><strong>Network Name</strong></td><td>Citrea Mainnet</td></tr><tr><td valign="middle"><strong>Chain ID</strong></td><td>4114</td></tr><tr><td valign="middle"><strong>Currency Symbol*</strong></td><td>cBTC</td></tr><tr><td valign="middle"><strong>Currency Decimals</strong></td><td>18</td></tr><tr><td valign="middle"><strong>Currency Name</strong></td><td>Citrea Bitcoin</td></tr><tr><td valign="middle"><strong>HTTP RPC URL</strong></td><td><a href="https://rpc.mainnet.citrea.xyz/">https://rpc.mainnet.citrea.xyz</a></td></tr><tr><td valign="middle"><strong>Block Explorer</strong></td><td><a href="https://explorer.mainnet.citrea.xyz/">https://explorer.mainnet.citrea.xyz</a></td></tr><tr><td valign="middle"><strong>Network Type</strong></td><td>EVM-compatible ZK Rollup (Type II zkEVM)</td></tr><tr><td valign="middle"><strong>Block Time</strong></td><td>2 seconds</td></tr><tr><td valign="middle"><strong>Block Gas Limit</strong></td><td>10,000,000</td></tr><tr><td valign="middle"><strong>Latest Supported EVM Version</strong></td><td>Pectra**</td></tr><tr><td valign="middle"><strong>Settlement &#x26; Data Availability Layer</strong></td><td>Bitcoin</td></tr><tr><td valign="middle"><strong>Genesis Specs</strong></td><td><a href="https://github.com/chainwayxyz/citrea/blob/nightly/resources/genesis/mainnet/evm.json">evm.json</a></td></tr><tr><td valign="middle"><strong>Currency Logo</strong></td><td><a href="https://drive.google.com/drive/folders/1e9VFs4v3_mBs-WAW-FzVgTnPvYyJ8pvF?usp=sharing">cBTC Logo</a></td></tr><tr><td valign="middle"><strong>Chain Logo</strong></td><td><a href="https://drive.google.com/drive/folders/1PyBMVom9sN5Qe529vCT8jBq3Q8fcHoS5?usp=sharing">Citrea Brand Kit</a></td></tr></tbody></table>

<sup>\*native currency, not ERC-20</sup>\ <sup>\*\*differences explained in the</sup> [<sup>Execution Environment</sup>](https://docs.citrea.xyz/essentials/execution-environment) <sup>page</sup>

***

## Kickstart Development

### Add Citrea to your Wallet / Code

For wallets, you can either use the information above, click & add using [**Chainlist**](https://chainlist.org/chain/4114)**,** or the following JSON as the baseline:

```json
{
  "chainId": "0x1012",
  "chainName": "Citrea Mainnet",
  "nativeCurrency": { "name": "cBTC", "symbol": "cBTC", "decimals": 18 },
  "rpcUrls": ["https://rpc.mainnet.citrea.xyz"],
  "blockExplorerUrls": ["https://explorer.mainnet.citrea.xyz"]
}
```

| Network Name       | Citrea Mainnet                                                                                       |
| ------------------ | ---------------------------------------------------------------------------------------------------- |
| Default RPC URL    | [https://rpc.mainnet.citrea.xyz](https://rpc.mainnet.citrea.xyz/)                                    |
| ChainID            | 4114                                                                                                 |
| Currency Symbol    | cBTC                                                                                                 |
| Block Explorer URL | <p><a href="https://explorer.mainnet.citrea.xyz/"><https://explorer.mainnet.citrea.xyz/></a><br></p> |

### Get cBTC

cBTC is used as the native currency to cover gas, which is necessary to deploy smart contracts & use the network.

Head over to [Bridge Hub](https://citrea.xyz/bridge) to Bridge BTC from Bitcoin; USDC, USDT or WBTC from Ethereum.

***

## Where to go from here?

Here are quick links you might be looking for:

* [RPC Endpoints](https://docs.citrea.xyz/developer-documentation/rpc-documentation)
  * includes support for `eth_` endpoints, along with useful Bitcoin & finality related endpoints of Citrea
* [Ecosystem Tooling](https://docs.citrea.xyz/developer-documentation/ecosystem-tooling)
  * partners to check out for Interop, Oracles, Indexers, Wallets, Account Abstraction...
* [Citrea Execution Environment](https://docs.citrea.xyz/essentials/execution-environment)
  * explainers on subtle differences of Citrea compared to Ethereum and other EVM environments
* [System Contracts](https://docs.citrea.xyz/developer-documentation/system-contracts)
  * a set of pre-deployed smart contracts on Citrea that can be used to verify Bitcoin transactions, execute bridge logic, and more


# Bridge to Citrea

This guide explains how to bridge assets to Citrea from Bitcoin and Ethereum.

## Bridge from Bitcoin

Citrea offers two bridging options depending on your deposit amount.

### Option 1: Clementine (10 BTC or multiples, Web App or CLI)

For deposits of 10 BTC, use [Clementine](/essentials/clementine-trust-minimized-bitcoin-bridge)—Citrea's canonical, trust-minimized Bitcoin bridge. To use it, follow the [Using Clementine](/essentials/using-clementine) guide (Clementine Web App or command-line tool).

{% hint style="info" %}
Clementine is the **canonical bridge** of Citrea. It provides the highest security guarantees by leveraging BitVM-based verification on Bitcoin.
{% endhint %}

{% hint style="warning" %}
Clementine only supports **10 BTC per transaction**. To bridge larger amounts (e.g., 40 BTC), you must perform multiple separate deposits of 10 BTC each.
{% endhint %}

**Steps:**

1. Open the [Clementine Web App](https://clementine.citrea.xyz) or install the [Clementine CLI](https://github.com/chainwayxyz/clementine-cli); see the [Using Clementine](/essentials/using-clementine) guide for details
2. Follow the deposit instructions in the app or in the [CLI documentation](/essentials/using-clementine/clementine-cli)
3. Repeat the process for each additional 10 BTC you wish to bridge

### Option 2: Symbiosis (Best for Smaller Transactions)

For deposits less than 10 BTC, use [Symbiosis](https://symbiosis.finance/).

**Steps:**

1. Go to [Symbiosis Swap page](https://app.symbiosis.finance/swap?amountIn=0.001\&chainIn=Bitcoin\&chainOut=Citrea\&tokenIn=BTC\&tokenOut=CBTC)
2. Set **Bitcoin** as the source chain and **Citrea** as the destination
3. Select **cBTC** as token
4. Enter the amount you want to bridge
5. Enter a BTC refund address
6. Enter your Citrea address or connect your wallet

{% hint style="warning" %}
Symbiosis functions as a cross-chain swap. The amount of BTC received is subject to swapping quotes, which depend on the cBTC-syBTC liquidity pool.
{% endhint %}

|                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                                                      |
| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-d63856434a5b69f5764adddd0e66ec796c5f7d4c%2Fsymbiosis-cbtc.png?alt=media" alt="Select cBTC" data-size="original"> | <img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-765d61216f8ae500d72ac8141c212836923ea248%2Fsymbiosis.png?alt=media" alt="Symbiosis" data-size="original"> |

### Option 3: [Atomiq Exchange](https://app.atomiq.exchange/) (Supports Bitcoin and Lightning routes)

For deposits less than 10 BTC or deposits via the Bitcoin Lightning network use atomiq.exchange

**Steps:**

1. Go to [app.atomiq.exchange](https://app.atomiq.exchange/)
2. Bitcoin on-chain is pre-selected as the source, if you wish to swap from Bitcoin Lightning Network, select the Bitcoin (lightning L2) asset in the "You pay" section
3. Enter the amount you want to bridge (you can specify either input or output amounts)
4. Connect your Citrea wallet or type in the destination Citrea address
5. Connect your Bitcoin wallet (e.g. UniSat, Xverse or Magic Eden), not required for swap from Bitcoin Lightning Network
6. Click Initiate swap and confirm the transaction in your Bitcoin wallet, or send over the funds to the presented lightning network invoice (in case of Bitcoin Lightning Network)
7. The swap settles automatically after the bitcoin transaction gets confirmed (2 confirmations take on average 20 minutes), this is instant for Bitcoin Lightning Network

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-f383c880f6ee76640134f1286b6676c24a75bfa1%2Fatomiq.png?alt=media" alt="" width="375"><figcaption><p>Atomiq</p></figcaption></figure>

## Bridge from Ethereum and other chains

Citrea supports multiple bridging options from Ethereum and other chains. LayerZero and Hyperlane are integrated directly into [Bridge Hub](https://mainnet.citrea.xyz/bridge), you can complete the entire bridging process without leaving the site.

### [LayerZero](https://layerzero.network/) Bridge (via Bridge Hub)

Bridge **USDT**, **USDC**, or **WBTC** from Ethereum, powered by LayerZero.

| Destination Asset                                                                                |
| ------------------------------------------------------------------------------------------------ |
| [USDT.e](https://explorer.mainnet.citrea.xyz/address/0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4) |
| [USDC.e](https://explorer.mainnet.citrea.xyz/address/0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839) |
| [WBTC.e](https://explorer.mainnet.citrea.xyz/address/0xDF240DC08B0FdaD1d93b74d5048871232f6BEA3d) |

Assets are bridged at a 1:1 ratio.

**Steps:**

1. Go to [Bridge Hub](https://mainnet.citrea.xyz/bridge) and select **Ethereum**
2. Choose your source asset
3. Connect your wallet
4. **Optionally** enable `Refuel Gas` for *gas drop* on Citrea
5. Complete the transaction

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-0fccdcd6753ba702bf02f21445812f6d73219af9%2Fethereum-birdgehub-layerzero.png?alt=media" alt="" width="375"><figcaption><p>Bridge via Bridge Hub with LayerZero</p></figcaption></figure>

{% hint style="success" %}
This route supports gas refuel which allows you to send native gas (cBTC) to the Citrea to cover transaction fees. The equivalent amount is deducted from your source chain balance. Note that this is only available for LayerZero-supported routes where the input and output assets are the same (e.g., USDC → USDC.e, USDT → USDT.e, WBTC → WBTC.e).
{% endhint %}

### [Hyperlane](https://www.hyperlane.xyz/) and [Swaps](https://www.swaps.xyz/) (via Bridge Hub)

Bridge **USDC** or **USDT** from Ethereum to **ctUSD**, powered by Hyperlane and Swaps.

**Steps:**

1. Go to [Bridge Hub](https://mainnet.citrea.xyz/bridge) and select **Ethereum**
2. Choose USDC or USDT as the source
3. Choose ctUSD as destination
4. Connect your wallet
5. Complete the transaction

{% hint style="warning" %}
This route does not support gas refuel at this time.
{% endhint %}

### [Squid Router](https://www.squidrouter.com/)

You can also use Squid Router to bridge between Ethereum and Citrea.

**Steps:**

1. Go to [Squid’s app](https://tokka.app.squidrouter.com/?chains=42161%2C4114\&tokens=0xaf88d065e77c8cc2239327c5edb3a432268e5831%2C0xe045e6c36cf77faa2cfb54466d71a3aef7bbe839)
2. Connect your wallet
3. Choose the token you want to pay with
4. Choose the token on Citrea you want to receive.
5. Submit and sign with your wallet
6. All bridges should take less than 20 seconds

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-203594c249f0dfaf905818b375b894813d710b06%2Fsquid-router-bridge.png?alt=media" alt="" width="375"><figcaption><p>Squid Router Bridge</p></figcaption></figure>

### Citrea Fast Bridge by [Avail](https://availproject.org)

Bridge your unified USDC or USDT, across several chains, to USDC.e or USDT.e on Citrea, in one click.

**Steps:**

1. Go to the [Citrea Fast Bridge](https://fastbridge.availproject.org/citrea)
2. Connect your wallet.
3. Select the asset on Citrea you want to bridge to (USDC or USDT)
4. Check your unified balance and break up across chains
5. Enter the amount and click `Bridge`
6. Verify and Confirm the route (sources to be used and fees)

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-19b7780e1589fa08ac94cb9148e5f02e96951ec7%2Favail-bridge.png?alt=media" alt="" width="375"><figcaption><p>Avail Citrea Bridge</p></figcaption></figure>

{% hint style="warning" %}
Citrea only maintains Clementine and USDT.e, USDC.e, WBTC.e bridges natively.
{% endhint %}

### Stargate Bridge by [LayerZero](https://layerzero.network/)

You can also use LayerZero's [Stargate Bridge](https://stargate.finance/).

**Steps:**

1. Connect Wallet
2. Select source chain and token
3. Select Citrea as the destination chain and select token
4. Enter amounts
5. **Optionally** Click advanced settings on the top right corner, select `Medium` for `Gas on Destination` to get your 2.5$ worth of gas drop
6. Click transfer to bridge

|                                                                                                                                                                                                                                                           |                                                                                                                                                                                                                                                                     |
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-300224038676a95e91b983933978e5fcc5a533b9%2Fstargate.png?alt=media" alt="Stargate Bridge" data-size="original"> | <img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-cb6c21154da9caaf59e87977e5d126e213c93f4a%2Fstargate-advanced.png?alt=media" alt="Gas drop options" data-size="original"> |

{% hint style="success" %}
This route supports gas refuel which allows you to send native gas (cBTC) to the Citrea to cover transaction fees. The equivalent amount is deducted from your source chain balance. Note that this is only available for LayerZero-supported routes where the input and output assets are the same (e.g., USDC → USDC.e, USDT → USDT.e, WBTC → WBTC.e).
{% endhint %}


# TL;DR

Citrea is the first rollup that enhances the capabilities of Bitcoin blockspace with zero-knowledge technology, making it possible to **build everything on Bitcoin**.

{% hint style="success" %}
**Citrea requires no changes to the network's consensus rules. Citrea and Clementine have been live on Bitcoin since January 2026.**
{% endhint %}

### Citrea is a **rollup on Bitcoin**

**Citrea is a rollup**. It regularly submits **batch proofs** to Bitcoin - which also include the **state differences** for each batch, meaning that any changes from the start to the end of a batch are also available for anyone reading Bitcoin.

A Citrea full node can read the state differences and reconstruct the state directly from Bitcoin - unlike sidechains, in which only small cryptographic commitments are posted and it is impossible to reconstruct the state using that data.

Citrea uses **Bitcoin as a Data Availability layer**, and it's the only source of truth for the system. As long as Bitcoin is secure, the state of Citrea will be accessible and reconstructable.

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FbhAqhd1iRL2kcYTwrOYJ%2Fimage.png?alt=media&#x26;token=483a4181-657a-4bec-888d-c5be8bbed419" alt=""><figcaption></figcaption></figure>

### Citrea is a [Type 2 zkEVM](https://docs.citrea.xyz/essentials/execution-environment)

Citrea is **EVM-compatible**. As a developer, you can write & deploy your smart contracts in Solidity using the standard EVM tooling.

Citrea processes a large number of zkEVM transactions off-chain. In **batches,** using these transactions, it generates succinct **STARK** proofs (later wrapped into succinct **SNARK** proofs). These proofs are then published to Bitcoin directly. This allows for easy client side verification of the batch validity in an inscription-like envelope.

### Citrea's currency is Bitcoin

Citrea uses **Bitcoin** as its native currency. To avoid confusion and improve on/off-ramp UX, Citrea’s native Bitcoin is referred to as Citrea Bitcoin, **$cBTC** in short.

### Citrea is designed to scale Bitcoin

As a separate execution layer, Citrea has different properties compared to Bitcoin and Ethereum. As an **independent execution layer**, it offers higher throughput, richer smart‑contract functionality, and lower fees than Bitcoin’s base layer, while still anchoring finality to Bitcoin.

| Dimension         | Citrea                  | Ethereum | Bitcoin        |
| ----------------- | ----------------------- | -------- | -------------- |
| Execution         | zkEVM                   | EVM      | Bitcoin Script |
| Settlement        | Bitcoin                 | Ethereum | Bitcoin        |
| Data availability | Bitcoin via State Diffs | Ethereum | Bitcoin        |
| Fees & Currency   | BTC (cBTC)              | ETH      | BTC            |

### Citrea has a native trust-minimized two-way peg: Clementine

Clementine is the BitVM-based trust-minimized two-way peg mechanism of Citrea. It uses **Light Client Proofs** that include recursively proven Citrea batch proofs, which enables **optimistic ZK Proof verification** **on Bitcoin** using BitVM.

Clementine is **trust-minimized** as it has a **1-of-N trust assumption**, which means that as long as one single entity in the bridge verifier set is honest, no party can steal the pegged BTC from the bridge.

Clementine is deployed on Citrea mainnet. You can read more about Clementine [here](https://docs.citrea.xyz/essentials/clementine-trust-minimized-bitcoin-bridge).

### Citrea is audited & fully open-source

Citrea & Clementine are built in public.

Both Citrea and Clementine codebases are open-source:

* <https://github.com/chainwayxyz/citrea>
* <https://github.com/chainwayxyz/clementine>

Both Citrea and Clementine codebases are [audited](https://docs.citrea.xyz/security/audits-inquiries) as of October 2025.


# Architecture and Transaction Lifecycle

## System Architecture Overview

***

Citrea’s architecture consists of several core components that work together. Mainly, these include:

* a private Mempool for transaction staging
* a Sequencer node for block production
* a Batch Prover node and a Light Client Prover node for zero-knowledge proof generation
* permissionless Full Nodes for verification
* a BitVM-based trust-minimized bridge, Clementine

Each component has a distinct role, yet they complement each other to ensure that transactions are executed correctly and finality is achieved by the finalization of published proofs in Bitcoin.

Below, let's introduce each major component and its function in the system first:

### Mempool

Citrea has a private **mempool** (memory pool) as a temporary staging area for pending transactions before they are included in a block. The mempool enforces some basic validity and resource checks first. If the transaction passes these checks, it is added to the mempool.

<details>

<summary>Basic Mempool Checks</summary>

* Does the address have enough balance?
* Does the transaction have a valid nonce that is greater than or equal to the current nonce?
* Is there enough space in the mempool?
* Does it fit into account limits?

</details>

Citrea mempool has custom [SubPools](https://reth.rs/docs/reth_transaction_pool/enum.SubPool.html#variants) that use `reth-transaction-pool` architecture. For **Queued**, **BaseFee**, and **Pending** pools, Citrea has the 10x configuration limits compared to default values of Ethereum: **100,000** transactions per subpool with **200 MB** limit.

Another custom mempool configuration is the number of transaction slots per account, `max_account_slots`. Citrea has a maximum of **64 slots per account** in the mempool to prevent spamming.

{% hint style="info" %}
Citrea does not have a Blob pool as it does not support blob transactions at the moment (no EIP-4844)
{% endhint %}

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FYApH3KQmTcYO2LdJ2IBT%2Fimage.png?alt=media&#x26;token=056662c9-6dc0-45d4-8e01-333a80f1a0c4" alt=""><figcaption></figcaption></figure>

### Sequencer

The Citrea sequencer is a specialized full node responsible for ordering user transactions and constructing rollup blocks. It continuously monitors the mempool and, every two seconds, selects a batch of valid transactions (prioritized by fees) to form the next block. Along with these user transactions, the sequencer also injects [system transactions](https://docs.citrea.xyz/developer-documentation/system-contracts#system-transactions) at the beginning of the block, covering important operations such as updating the latest Bitcoin block headers or handling bridge events. The sequencer executes all these transactions against the current state of the rollup, updates balances and contract storage, and computes a new state root. Gas usage and state changes are also stored in transaction receipts.

Upon assembling and executing a block, the sequencer generates, signs, and broadcasts a **soft confirmation** that attests to the block's content and the state root. This provides a fast & provisional confirmation of transactions/blocks for full nodes (i.e., soft-finality).

Lastly, the sequencer is also responsible for generating sequencer commitments, which provide finality for transactions and blocks once settled on Bitcoin.

{% hint style="success" %}
Regarding trust assumptions, the sequencer has the authority over choosing and ordering transactions and may cause liveness failures (delays), but it **cannot violate** correctness, steal funds, or freeze them arbitrarily.

Validity proofs and on-chain data availability on Bitcoin guarantee the integrity of state transitions and the validity of each block.
{% endhint %}

### Batch Prover

The Batch Prover is a dedicated node that generates ZK Proofs that attest to the correctness of Citrea blocks in **batches**. As mentioned above, sequencer posts commitments to Bitcoin. Once these commitments are finalized on Bitcoin, the prover fetches the corresponding batch of Citrea blocks and replays their execution inside a zkVM, and produces a succinct proof for the entire state transition. This proof is equivalent to the following statement: “***if you start from the last proven state and execute all Citrea blocks in order, you will arrive at the state root claimed by the sequencer***” – using this, anyone (e.g. full nodes) can verify without replaying the transactions themselves.

Citrea’s batch prover uses a Groth16 circuit (running in the [RISCZero](https://risczero.com/) zkVM environment, with [Boundless](https://beboundless.xyz/)). Once the proof for a given batch of blocks is generated, the batch prover packages the proof (and any needed public inputs such as the old and new state root, and the range of block indices covered) into a transaction that is posted on the Bitcoin network.

{% hint style="success" %}
Posting the proof to Bitcoin serves a similar purpose as posting sequencer commitments: it timestamps and makes public the evidence that the Citrea blocks are valid. Full nodes and other verifiers will pick up the proof from Bitcoin and check its validity. If valid, this proof guarantees the finality of the batch of L2 blocks in question, since we now have a cryptographic guarantee of their correctness that is recorded on Bitcoin.
{% endhint %}

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FHVYinR2zsDgR8xab3oB3%2Fimage.png?alt=media&#x26;token=df0f0496-0967-47d6-8f34-63d2297d803d" alt=""><figcaption></figcaption></figure>

### Light Client Prover

The Light Client Prover (LCP) is a specialized node that produces a recursive proof of the entire Citrea rollup state.

The mission of the LCP is to enable light clients (and other external verifiers like smart contracts on other chains) to easily verify the latest state of the rollup with minimal data, by checking a single proof that encapsulates all necessary history. To accomplish this, the LCP runs a light client circuit continuously. The circuit processes each new Bitcoin block along with the previous light client proof, producing a new proof that verifies the correct Citrea state root for that block.

Essentially, each light client proof builds on the prior one, forming *an unbroken chain of proofs* (a recursive proof sequence) from the start of the rollup up to the current state. By verifying just the latest proof, a light client can be confident that all the Citrea blocks and all the batch proofs in the rollup’s history (up to that point) were valid and consistent with what was posted on Bitcoin.

{% hint style="success" %}
The primary use case for the LCP’s output in Citrea’s design is to feed into [Clementine](https://citrea.xyz/clementine_whitepaper): the Bitcoin bridge requires a valid LCP to resolve any disputes about the rollup state in BitVM. This way, it inherits the security from the ZK proof if an operator tries to cheat. The LCP combines the security of both Bitcoin and the batch proofs into one succinct artifact.
{% endhint %}

### Full Nodes

A full node is a permissionless participant that anyone can run to fully verify the rollup’s state and serve data to others. A full node keeps a complete copy of Citrea’s state (all accounts, contracts, etc.) and the history of transactions. Its responsibilities include:

* **Syncing Citrea Blocks:** It connects to the Sequencer and receives every new block (and soft-confirmation). The full node replays the transactions in each block, applying the **state transition function** to update its copy of the state (and recompute the new state root).
* **Monitoring Bitcoin:** The full node follows Bitcoin’s blocks to detect Citrea data posted on Bitcoin. For every finalized Bitcoin block, it fetches and verifies **sequencer commitments** and **batch proofs** from Bitcoin. Essentially, full nodes use Bitcoin as the source of truth to cross-verify the sequencer’s output.
* **Serving Data & RPC:** Full nodes expose a standard **JSON-RPC API** (compatible with Ethereum’s EVM interface) to allow wallets, dApps, explorers, and users to interact with the Citrea network. Through a full node, one can query contract states, submit transactions, retrieve receipts and proofs, etc., without relying on any centralized service.

In essence, full nodes **ensure trustlessness**: users don’t have to trust the sequencer or any single party, because they can run a full node to independently validate every block and proof. Unlike miners in Bitcoin, Citrea’s full nodes do **not** compete to produce blocks – their role is purely to verify and relay information.

### Clementine

**Clementine** is Citrea’s BitVM-based trust-minimized two-way peg for **BTC ↔ cBTC** - a new breakthrough that enables optimistic verification of ZK Proofs directly on Bitcoin without any changes / soft-forks.

For full protocol details and diagrams, see: <https://docs.citrea.xyz/technical-specs/characteristics/clementine-trust-minimized-bitcoin-bridge>

## Transaction Lifecycle on Citrea

***

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FVNtMZiDIyR4DjUkiRRbp%2Fimage.png?alt=media&#x26;token=b6ed57e5-5640-49bc-ab6d-7f18232820fc" alt=""><figcaption><p>The transaction lifecycle with numbers indicating the chronological order.</p></figcaption></figure>

Having introduced the components, let's now walk through the lifecycle of a user-submitted transaction from the moment a transaction is sent, to its inclusion in a Citrea block, and ultimately to its cryptographic finalization on Bitcoin.

### **1) Submission to Mempool**

A user initiates a transaction (for example, transferring cBTC or calling a smart contract on Citrea) and broadcasts it to the Citrea network, typically via a full node’s RPC interface. The full node relays the transaction to the [Sequencer](#sequencer), where it enters [**mempool**](#mempool) **if it is valid**.

### **2) Sequencing and Block Production**

As discussed, the sequencer constantly watches the mempool for new transactions. At regular intervals (every \~2 seconds in the current design), the Sequencer selects a set of the highest-priority pending transactions to include in the next block. It then executes these transactions one by one against the current state. During execution, smart contract code is run in Citrea’s EVM environment, state variables are updated, and gas is consumed as in other EVMs.

The Sequencer packages the transactions into a **rollup block**. Along with user transactions, the Sequencer also includes system transactions in this block – for example, a transaction to update the BitcoinLightClient with a new Bitcoin block hash, or to process a bridge deposit that became final.

### **3) Soft Confirmation Broadcast**

After producing a block, the Sequencer immediately generates a **soft confirmation** for it. A soft confirmation is essentially a signed statement containing the new block’s hash, the previous block’s hash, the new state root, and a reference to the latest Bitcoin block (among other metadata). By issuing a soft confirmation, the sequencer itself guarantees that the signed confirmation is the next in the canonical Citrea chain.

The Sequencer then broadcasts the soft-confirmation (with the block data) to all **Full Nodes** in the network. Full nodes receive the new block and, using the soft confirmation, they update their local view of the chain to include it. They execute the block’s transactions themselves to update their state, verifying that they get the same post-state root. At this point, the transaction is considered *soft-confirmed* on Citrea – users and applications see it as included in a block with an assigned order and can start using it immediately, but this inclusion is still conditional on later being committed on Bitcoin.

### **4) Sequencer Commitments on Bitcoin**

To secure the ordering of transactions and blocks, the Sequencer periodically publishes **Sequencer Commitments** to the Bitcoin blockchain. This typically happens after accumulating a batch of Citrea blocks or after a time interval. These commitments include

* a Merkle root of recent soft-confirmation hashes (covering a sequence of Citrea blocks)
* and the start and end block indices of that batch.

By inscribing this data in a Bitcoin transaction, the Sequencer creates a permanent, tamper-resistant record of the Citrea blocks up to that point. Once this Bitcoin transaction gets enough confirmations, those Citrea blocks are considered *finalized in order*: neither the Sequencer nor anyone else can reorder or discard them without contradicting data that is now settled on Bitcoin.

Full nodes watch for sequencer commitments on Bitcoin and, when found, mark the corresponding Citrea blocks as finalized. At this stage, the user’s transaction has an immutable position in the history, anchored by Bitcoin’s proof-of-work. However, one must still ensure that the contents of those blocks are valid – this is where the prover comes in next.

### **5) Batch Proof Generation & Submission**

After the Sequencer’s commitment is finalized on Bitcoin, the **Batch Prover** takes over to prove the correctness of that batch of blocks. The prover node fetches the commitment reference(s) from Bitcoin. It then executes a zkSNARK circuit (Batch Proof Circuit) that simulates applying all those transactions in order, from the known previous state root to the new state root claimed by the Sequencer. If the batch of transactions is valid (no fraudulent state transitions), the circuit produces a succinct **batch proof** attesting to that fact.

The proving step may take some time (minutes, hours, depending on batch size and proving hardware), but it’s done asynchronously. Once the proof is ready, the Batch Prover embeds the proof along with the batch’s index and state roots into a Bitcoin transaction and publishes it. This action puts the validity proof on Bitcoin for anyone to retrieve. It also timestamps the proof so that it corresponds to a specific Bitcoin block (and by extension, a specific Citrea batch proof submission).

{% hint style="success" %}
Batch Proofs include the state differences of Citrea blocks. That means, anyone running a Bitcoin node can trustlessly reach and sync with Citrea's canonical chain.

The proof size depends on the number and type of transactions on Citrea. To prevent non-standard batch proof transactions on Bitcoin and to enable faster finalization of blocks, Citrea uses a chunking mechanism to keep each proof size under 400 kilobytes per transaction.

There can be multiple batch proofs posted for any Bitcoin block.
{% endhint %}

### **6) Proof Verification and Finality**

Finally, Citrea full nodes (as well as any external observers) fetch the newly posted batch proofs directly from Bitcoin and verify them against the claimed state transition. Upon sufficient confirmations, full nodes:

* verify the succinct proof for a batch of blocks,
* check whether they match the commitment’s root and `[start, end]`
* update the last finalized/proven block and transaction information in its database.

The node advances its proven tip to the batch’s end height; all transactions in that window are now **proven** on Citrea (reversal would require a deep Bitcoin reorg).

In parallel, the **Light Client Prover** maintains a **recursive** proof of the entire rollup: it ingests the previous LCP proof and the latest Bitcoin block (plus recent batch proofs) to output a single, updated proof that *the Citrea state is correct up to this Bitcoin block*. External verifiers (including the **Clementine** bridge via BitVM) can check **one** proof to learn the latest valid state, without processing whole chain history.

***

Throughout the lifecycle of a transaction, Bitcoin is used at two critical points: first to **commit** to block order (preventing censorship or reordering attacks), and second to **attest** to execution validity (preventing invalid state transitions).


# Clementine: trust-minimized Bitcoin Bridge

Clementine is Citrea’s native two‑way peg that moves BTC ↔ cBTC in a trust-minimized way.

{% hint style="success" %}

### Why Clementine?

Existing Bitcoin bridges usually depend on trusted multisigs or on separate chains/consensus, pushing users to accept an **honest‑majority** assumption and moving economic activity away from Bitcoin.

Clementine is a trust-minimized solution based on [BitVM2](https://bitvm.org/bitvm_bridge.pdf) - a new breakthrough that enables optimistic verification of ZK Proofs directly on Bitcoin without any changes / soft-forks.

Using BitVM2, one can:

* verify the correctness of a ZK Proof **on Bitcoin**
* and, in case a provided proof is not correct, can determine and take action against it **on Bitcoin.**

With the help of BitVM2 Clementine keeps the safety of funds *on Bitcoin,* reduces the peg-out trust to **“1‑of‑N honesty”,** and achieves trust-minimization:

* One honest **Signer** ensures funds can only follow pre‑approved spend paths.
* One honest **Watchtower** can block a claim anchored to the wrong Bitcoin chain.
* One rational **Challenger** can prove an invalid computation and seize a malicious Operator’s collateral.

As long as 1-of-N honest assumption holds, funds are **protected** against **both** liveness failures and theft.
{% endhint %}

Clementine is formally described and explained in its [whitepaper](https://citrea.xyz/clementine_whitepaper.pdf). Clementine is also open-source, you can read the codebase [here](https://github.com/chainwayxyz/clementine).

In this page, we provide a detailed high-level overview of the protocol. For a formal definition with more explanations, please refer to the whitepaper.

Let's continue with the roles in the Clementine bridge.

***

## Roles and Responsibilities

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2F2ZZ8CwoiXZXg3E2XhGnm%2Fimage.png?alt=media&#x26;token=7840727f-e354-4168-ba37-d750438f6272" alt=""><figcaption></figcaption></figure>

There are **five** major roles on a functional Clementine bridge. In this section we provide the major definition of these roles, and in the following sections you may understand their exact functions under different conditions.

* **Users** - start peg‑ins (deposits BTC to mint **cBTC**, Citrea's native asset) and peg‑outs (burn **cBTC** to a system contract to withdraw BTC to Bitcoin).
* **Signers** - a committee of n signers that **pre‑signs the allowed spend rules**. These signers emulate [covenant](http://covenants.info)‑like restrictions: funds can only move along Clementine’s approved paths, or they are returned to the user if user deposit is not moved to vault by signers in time.\ <sub>*A third option is the optimistic payouts, which we discuss in the following sections*</sub><sub>.</sub>
* **Operators** - entities who **facilitate fast withdrawals to Bitcoin by fronting BTC** payments to the user and **later claim reimbursement from the bridge vault** if nobody can prove malicious or fraudulent intent. In the case of malicious Operator intent, Clementine initiates a challenge response game described in the sections below.\ <sub>*to make sure economics are safe, Operators put a slashable bond to the protocol (\~ 2 BTC). This is discussed under section 5.*</sub>
* **Watchtowers** - entities who monitor both Citrea and Bitcoin. In the case of an initiated challenge transaction where malicious intent by an operator is detected, watchtowers are responsible for publishing the compact **Bitcoin header-chain proof** with total work.
* **Challengers** - entities who **force** an operator to prove their intent by initiating a Challenge transaction and using the header-chain proof published by the watchtower.

{% hint style="info" %}
These entities are not mutually exclusive. For example, in mainnet, a signer in Clementine will also function as a watchtower and a challenger. Thus, roughly, the following relation will hold:

<mark style="background-color:$success;">**Operators ⊆ Signers ⊆ Watchtowers ⊆ Challenger ⊆ Users (permissionless)**</mark>
{% endhint %}

***

## How funds move around

In this section we go over the flow of the funds based on the protocol's rules, for both peg-in(s) and peg-out(s).

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2F9KQF6JzcRMMOiy9h6DNr%2Fimage.png?alt=media&#x26;token=0eca420d-47d5-434e-9713-d16f10a4457e" alt=""><figcaption></figcaption></figure>

### A) Peg-in (BTC → cBTC)

***

Peg-in flow to Citrea is fairly simple:

1. **User deposit:** user sends **10 BTC** to a [Taproot](https://bitcoinops.org/en/topics/taproot/) address that encodes two paths:
   * *Bridge path:* spendable only with all Signers' signatures and inscribing the user's EVM address in the witness script.
   * *Refund path:* the user can take funds back after a timelock (`OP_CSV`) if the bridge doesn’t act as described below in 200 Bitcoin blocks. This timeout prevents funds from getting stuck if Step 2 does not happen.
2. **Move BTC to vault:** Signers sign the transaction that moves the deposit into a "vault" UTXO that is only spendable by the bridge’s allowed exits.
   * This `MovetoVault` transaction *emulates* covenants with pre‑signed transactions and MuSig‑style aggregation. Funds **must** follow the pre‑signed paths if at least one signer is honest.
3. **Mint on Citrea:** Once the `MovetoVault` transaction is successfully finalized (6+ blocks), the `Bridge` system smart contract on Citrea checks its validity using the `BitcoinLightClient` smart contract. The contract then mints **10 cBTC** to the user’s Citrea address (the address is bound in the deposit).

### B) Peg‑out (cBTC → BTC)

***

Bridging from Citrea to Bitcoin (converting cBTC on Citrea to BTC on Bitcoin) is handled in a couple steps.

First, a user should ***burn*** their cBTC on Citrea using the [Bridge](https://docs.citrea.xyz/developer-documentation/system-contracts/bridge) system contract using the `safeWithdraw` function. Then, they need to submit their request to exit to the Operators of the bridge using a *Payout* transaction template that includes their BTC address and the amount. As a special template, this is a presigned transaction that requires an additional UTXO input from an operator.

After user's burn, there are two scenarios

* **Optimistic Case**: This is the case where there's no one malicious.
* **Dispute & Challenge Case**: This is the case where there's an operator with malicious intent.

Let's cover these cases in separate sections, in detail.

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FnBSIKG8kmnKDaioD47eT%2Fimage.png?alt=media&#x26;token=23a1e587-6399-486c-9d26-a1c6ab967e23" alt=""><figcaption></figcaption></figure>

#### Peg-out Scenario 1: Happy Case

If there is no malicious intent from the operators, the payout can be completed in two ways:

1. **Optimistic Payout with n Signers:** If all signers are online, they can give signatures and directly transfer the BTC to the user address without the need of Operator. We call this an **optimistic payout** - just like a regular transfer from an n-of-n multisig.
2. **Operator Payout:** If a signer is not online for *12 hours*, the optimistic payout above cannot be completed. Thus, the user still needs to be paid. In this case, an operator from the operator set steps in and fetches the Payout template from the user. The operator then attaches their own inputs to the template and broadcasts the *Payout* transaction. This template uses [**`SIGHASH_SINGLE|ANYONECANPAY`**](https://wiki.bitcoinsv.io/index.php/SIGHASH_flags) , so the user’s output is locked while any Operator can fund it.

<mark style="background-color:$success;">From the user’s perspective, once either of these transactions is finalized, the withdrawal is complete.</mark>

If the payout is completed through an Operator Payout (step 2), then the operator needs to be **reimbursed** from the bridge vault on Bitcoin. It is completed as follows:

1. The operator asks for reimbursement by posting a claim transaction (called `KickOff`) on Bitcoin.
2. This starts a challenge window. If nobody disputes in a predetermined time period (i.e. 1.5 days where everything is fine), the Operator is able to post another transaction called `NoChallenge`, that gets unlocked only upon timelock expiry. Using this `NoChallenge` transaction, Operator can reimburse itself.

For the cases above so far, we assumed that operators are honest. However... what if an Operator claims a payment that did not happen? What if they are malicious?

This leads us to the **`Dispute`** scenario. Let's go over it.

#### Peg-out Scenario 2: Dispute & Challenge Case

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FVYWyAP8AZJxNpgqWez7x%2Ffinal_diagram.png?alt=media&#x26;token=ec6330a0-0e1a-4740-b872-449998d0bb77" alt="Green Boxes indicate Operator reimbursement, whereas grey boxes indicate cases that Operator is slashed &#x26; kicked out from the vault."><figcaption><p>Green Boxes indicate Operator reimbursement, whereas grey boxes indicate cases that Operator is slashed &#x26; kicked out from the vault.</p></figcaption></figure>

If an Operator makes a fraudulent reimbursement claim (e.g., for a non-existent withdrawal), the protocol enters a dispute resolution phase enforced by Watchtowers and Challengers with the following steps:

1. **Challenge Initiation:** A Challenger detects the fraudulent `KickOff` transaction by the operator and posts a `Challenge` transaction on Bitcoin, which signals the beginning of a dispute.
2. **Watchtower Challenge Transaction:** After waiting enough time to make sure that an Operator is not trying to maliciously make a private Bitcoin fork with exceeding proof-of-work, a Watchtower posts the current finalized canonical Bitcoin header-chain proof with Work.
3. **Challenge-Response Game:** The Operator is now forced to defend their reimbursement claim by providing a zkSNARK Light Client Proof of Bitcoin which shows their committed chain has more proof-of-work (than the Watchtower's claim) and includes the payout transaction in which the operator paid the user that withdrew funds from Citrea.
   1. **If the operator is not malicious**, by waiting some time and posting the correct Light Client Proof, it can win the challenge against the Challenger and get reimbursed. The only requirement for the Operator's Light Client Proof is to carry more Work compared to Watchtower's proof.
   2. **If the operator is malicious**, it cannot post a valid Light Client Proof with more work included due to hash rate. Whether it posts an invalid proof (or cannot prove that a valid payout exists), it will lose the challenge.
      * This phase uses BitVM - the complex computation is executed off-chain, but any step in the execution can be disputed and verified on-chain.

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FwzdO5HYQkIyiKD2PLZGW%2Fimage.png?alt=media&#x26;token=ea03944f-537a-490c-b013-2bd00dbfda30" alt=""><figcaption></figcaption></figure>

To summarize, after all the steps above, if the on-chain step confirms the Operator is dishonest, or if the Operator fails to provide a valid proof, their entire collateral bond is **slashed**.

Once an operator is slashed, they are also effectively **kicked out** of the Signer & Operator set to prevent any other malicious activity.

{% hint style="success" %}
The disputes and challenges can occur for an honest operator as well. However, operator will win the challenge if it is honest and did not take any malicious actions, and the challenger will pay for the whole transaction fees.
{% endhint %}

***

## Economics, Security, and Liveness

### a) Operator's Bond

In Clementine, each operator locks **their own BTC** as a **bond**. That single bond backs a round of many user withdrawals and continues to persist as long as the operator is honest for consecutive rounds. If **any** paid withdrawal claim by an operator in the round is proven fraudulent (or the operator misses required steps during dispute), the bond is **slashed** and **none** of the reimbursements in that round are paid. This helps keep the bridge safe, as the operator is discouraged from making any malicious attempts, while the stake can be relatively low because one bond works for all claims.

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FYZYHnQj67HK185VT7GuF%2Fimage.png?alt=media&#x26;token=1a4e9754-3a36-4a8f-acc8-038da42208ea" alt=""><figcaption></figcaption></figure>

### b) Payoff Rounds & Capital Efficiency

Unlike BitVM2, Clementine requires only one successful challenge to slash an Operator's entire bond for a malicious case, preventing them from claiming *any* of their reimbursements for that payoff round. Also, upon the finalization of a round, the same collateral is reused for the next round as well. This drastically reduces the on-chain load and provides a strong economic deterrent against misbehavior.

### **c) Security & Liveness Guarantees**

Let's go over a summary of Clementine's trust assumptions, as stated in the whitepaper too:

* Clementine is trust-minimized as **1-of-N** - the bridge’s safety does not depend on a majority of honest actors, as explained in the sections above. It only requires **one honest participant** for each key role, out of N.
* Clementine is **secure** as long as an attacker does not control more than 45% of Bitcoin's hash rate for 2 weeks.
* Assuming the two conditions above hold, **incorrect peg-outs cannot succeed**, as they will be challenged and stopped. In that case, the user can be paid later by another operator.
* Also in a case where a watchtower and challenger duo is malicious, the operator can provide their valid proofs and win the challenge, which prevents any potential DOS attacks.
* During a peg-out, the same *Payout* template cannot be used twice. Therefore, **a withdrawal request cannot be paid twice**.

***

## Implementation Notes

The deployed version of Clementine incorporates two design decisions that differ from the whitepaper. These are deliberate engineering choices made for the initial release, with no impact on the core security guarantees of the protocol.

### Watchtower Circuit Simplification

In the whitepaper (Section 8), the Watchtower Circuit includes a verification step that checks whether the watchtower's submitted chain contains the block with the `payout_tx_blockhash`. In the deployed implementation, this step is omitted.

This simplification does not weaken Clementine's security model. Even without this additional check, a malicious watchtower would still need to control more than 50% of Bitcoin's total hash rate to affect the outcome of a dispute — the same fundamental security bound that protects the protocol overall.

### Challenge Reimbursement

The whitepaper (Section 6.1) describes a mechanism where a Challenger includes an output with their Citrea address in the Challenge transaction, enabling cross-chain reimbursement of the challenge cost (*c* coins) via a light client proof if the challenge is successful.

This reimbursement mechanism is not included in the current deployment. In practice, this means the protocol's "existential honesty" assumption for Challengers is narrowed to Challengers who have sufficient capital to cover the upfront cost of issuing a challenge.

This is an acceptable trade-off for the initial version of Clementine. Ongoing research into [Clementine v2 with Garbled Circuits](https://www.blog.citrea.xyz/clementine-v2-with-garbled-circuits-and-toop/) is expected to substantially reduce the on-chain cost of challenges, making the financial barrier to challenging negligible in future versions and removing the need for a cross-chain reimbursement mechanism altogether.


# Using Clementine

Clementine is Citrea’s trust-minimized Bitcoin bridge. You can use it only at **fixed size**: each deposit moves **10 BTC** from Bitcoin to Citrea (minting **10 cBTC**), and each withdrawal moves **10 cBTC** from Citrea to Bitcoin (paying out approximately **10 BTC**, subject to fees). There are no partial or custom amounts for a single Clementine operation; larger totals require separate 10 BTC (or 10 cBTC) operations.

To learn how the bridge works and read about its security properties, see [Clementine: trust-minimized Bitcoin Bridge](/essentials/clementine-trust-minimized-bitcoin-bridge).

If you need to bridge **less than 10 BTC**, use third-party bridges. See [Bridge to Citrea](/welcome/bridge-to-citrea) and [citrea.xyz/bridge](https://citrea.xyz/bridge) for options.

If you run into issues with Clementine tooling, email <clementine-cli@citrea.xyz>.

## Clementine Web App

The [Clementine Web App](/essentials/using-clementine/clementine-web-app) runs in your browser and walks you through Clementine deposit and withdrawal operations with on-screen steps and status. Use [clementine.citrea.xyz](https://clementine.citrea.xyz) on mainnet and [clementine.testnet.citrea.xyz](https://clementine.testnet.citrea.xyz) on testnet.

## Clementine CLI

The [Clementine CLI](/essentials/using-clementine/clementine-cli) is a wallet-agnostic command-line tool for the same 10 BTC / 10 cBTC operations. It suits advanced setups (for example, air-gapped signing and scripting). The CLI docs cover installation, wallet usage, deposit and withdrawal guides, and reproducible builds.


# Clementine Web App

## Clementine Web App

The Clementine Web App lets you bridge between Bitcoin and Citrea from your browser.

You can use it to:

* Deposit **10 BTC** and receive **10 cBTC** on Citrea.
* Withdraw **10 cBTC** and receive **BTC** on Bitcoin.

### URLs

* Mainnet: [clementine.citrea.xyz](https://clementine.citrea.xyz)
* Testnet: [clementine.testnet.citrea.xyz](https://clementine.testnet.citrea.xyz)

### Before you start

You will need:

* An **EVM wallet** connected to Citrea.
* A **Bitcoin wallet** that can send exact BTC amounts.
* For deposits: exactly **10 BTC**.
* For withdrawals: **10 cBTC** on Citrea and a Bitcoin dust UTXO.

The same EVM wallet is used throughout each flow. The app may ask your wallet to sign messages so it can generate the Bitcoin keys needed for the bridge process.

These keys are generated locally in your browser and are kept only for your current session. If you refresh the page, they are cleared. You can regenerate them by signing the same message again with the same EVM wallet.

Each page also has a **Restart Flow** button in the top right. This clears the current flow and lets you start over.

For advanced users who want stronger key isolation, such as signing from an offline machine, use the [Clementine CLI](/essentials/using-clementine/clementine-cli).

For more background, see:

* [Clementine: trust-minimized Bitcoin Bridge](/essentials/clementine-trust-minimized-bitcoin-bridge)
* [Using Clementine](/essentials/using-clementine)

***

## Deposit BTC to Citrea

Use the **Deposit** page to bridge **10 BTC** into **10 cBTC**.

### Step 1: Choose your Citrea destination

Connect the Citrea wallet where the minted cBTC should be sent.

By default, the connected wallet address is used as the destination address on Citrea.

### Step 2: Generate your recovery key

Click **Generate Recovery Signer Key**.

Your wallet will ask you to sign a message. This signature is used locally in your browser to generate a Bitcoin recovery key.

This recovery key is required to recover your BTC if something goes wrong with the deposit, such as sending the wrong amount.

The first time you generate this key, the app may ask you to run a **Determinism Check**. This confirms that your wallet can reliably regenerate the same key later.

If the result is **Match**, you can continue.

### Step 3: Send exactly 10 BTC

The app will generate a Bitcoin deposit address.

Send **exactly 10 BTC** to the address shown in the app.

Do not send more or less than 10 BTC. Deposits with any other amount will not complete normally and must be recovered.

You can optionally open the mempool.space link shown in the app to verify the deposit address details.

After sending the BTC, click **Continue**.

### Step 4: Track your deposit

The app will show the status of your deposit.

Common statuses are:

| Status                         | Meaning                                                                   |
| ------------------------------ | ------------------------------------------------------------------------- |
| In Mempool                     | Your Bitcoin transaction has been seen but is not confirmed yet.          |
| New                            | Your transaction is confirmed on Bitcoin and is waiting for finalization. |
| In Progress                    | The bridge is processing your deposit.                                    |
| Move To Vault Transaction Sent | The bridge has moved your deposit into the vault.                         |
| Completed                      | Your 10 cBTC has been minted on Citrea.                                   |

When the deposit is complete, the app shows the Citrea transaction hash.

### Recovering a deposit

If you sent the wrong amount, the app will show the deposit under **Incorrect amount deposits**.

To recover it:

1. Wait for the **200-block recovery delay** to pass.
2. Derive the recovery key using the **Sign to derive key** button.
3. Click **Generate recovery tx**.
4. Enter the Bitcoin address where you want the funds returned.
5. Choose a fee rate.
6. Preview or broadcast the recovery transaction.

For valid 10 BTC deposits, you can also create and download a recovery transaction as a safety backup. This transaction can only be used if the bridge does not process your deposit in time.

***

## Withdraw cBTC to Bitcoin

Use the **Withdraw** page to bridge **10 cBTC** back to BTC.

You burn **10 cBTC** on Citrea, and the amount of BTC you receive depends on which payout path completes the withdrawal:

* **Optimistic payout:** **9.9999976 BTC** This is the default path and completes within 12 hours in the normal case.
* **Operator payout:** **9.97 BTC** This fallback runs if no optimistic payout arrives within 12 hours, and pays a higher fee to the operator that completes the withdrawal.

### Step 1: Connect your Citrea wallet

Connect the EVM wallet that holds the **10 cBTC** you want to withdraw.

The app will show your current cBTC balance.

### Step 2: Enter your Bitcoin address

Enter the Bitcoin address where you want to receive BTC.

The app checks that the address matches the current network.

### Step 3: Generate your withdrawal key

Click **Generate Withdrawal Signer Key**.

Your wallet will ask you to sign a message. This signature is used locally to generate a Bitcoin key for the withdrawal.

This key is used to sign the withdrawal payout bound to your selected Bitcoin address.

As with deposits, the app may ask you to run a **Determinism Check**. If the result is **Match**, you can continue.

### Step 4: Send the dust transaction

The app will show a Bitcoin signer address and a small dust amount. The default is **0.0000033 BTC**; if your wallet doesn't support that amount, you can change the dust value in **Settings**.

Send the indicated dust amount from your Bitcoin wallet to the signer address.

This small Bitcoin transaction is used as part of the withdrawal process.

Once the dust transaction appears on Bitcoin:

1. Click **Scan for UTXOs**.
2. Select the UTXO you just sent.
3. Click **Continue**.

### Step 5: Sign and send the withdrawal transaction

The app will prepare your withdrawal transaction on Citrea.

Before sending, click **Simulate Transaction**. This checks that the transaction can be submitted successfully.

Once the simulation passes, click **Send Transaction**.

Your EVM wallet will ask you to confirm the transaction. This sends **10 cBTC** to the bridge contract on Citrea.

After the transaction is submitted, the app shows the Citrea transaction hash.

If the selected Bitcoin UTXO needs more confirmations, the send button will stay disabled and the app will show how many blocks are left.

### Step 6: Track your withdrawal

The app will show the withdrawal status.

Common statuses are:

| Status                                     | Meaning                                                                  |
| ------------------------------------------ | ------------------------------------------------------------------------ |
| Waiting for Citrea finalization on Bitcoin | The withdrawal request is waiting for Citrea finalization before payout. |
| completed                                  | The withdrawal is complete.                                              |

### Step 7: Submit operator signatures, if needed

Most withdrawals complete through the optimistic payout path.

If no optimistic payout arrives within **12 hours**, the withdrawal falls back to **operator payout**: you can move on by submitting signatures so an operator can complete your payout instead.

Click **Submit Operator Signatures**.

After the signature is submitted, Step 7 is marked as **Submitted**. This means the operator signature was sent successfully; continue using **Monitor Status** to track payout completion.


# Clementine CLI

A wallet-agnostic command-line tool for depositing 10 BTC from Bitcoin to Citrea and withdrawing 10 cBTC from Citrea to Bitcoin.

For more information about the Clementine bridge, visit [Clementine: trust-minimized Bitcoin Bridge](/essentials/clementine-trust-minimized-bitcoin-bridge).

Clementine can also be used through the [Clementine Web App](/essentials/using-clementine/clementine-web-app): [clementine.citrea.xyz](https://clementine.citrea.xyz) for mainnet and [clementine.testnet.citrea.xyz](https://clementine.testnet.citrea.xyz) for testnet.

If you are looking for bridging smaller amounts, you can use third party bridges. Visit <https://citrea.xyz/bridge> for more information.

If you encounter any issues, email us at <clementine-cli@citrea.xyz>.

## Installation

Choose one of the following installation paths.

### Option A: Build from source

Install Rust:

```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

Install Clementine CLI:

```sh
cargo install --git https://github.com/chainwayxyz/clementine-cli --tag v0.1.0 --locked --force
```

### Option B: Download a pre-built binary and verify it

See [Download & Verify](/essentials/using-clementine/clementine-cli/download-verify) for instructions on downloading pre-built binaries and verifying signatures.

### Initialize and configure

Install the default configuration by running the CLI init command which creates the `~/.clementine/bridge_cli_config.toml` file for you:

```sh
clementine-cli init
```

Show configuration:

```sh
clementine-cli show-config
```

Show help:

```sh
clementine-cli --help
```

## Quick Usage

By default, `clementine-cli` uses `bitcoin` (mainnet) network. If you wish to make deposits and withdrawals on testnet, please provide `--network testnet` flag every time you invoke `clementine-cli`. Throughout the docs, network aliases are used interchangeably: `bitcoin`/`mainnet`, `testnet4`/`testnet`, `signet`/`devnet`, and `regtest`.

### Deposit

```sh
# Create wallet for deposit (Recovery Taproot Address)
clementine-cli wallet create my-deposit-wallet deposit

# Start deposit (generate deposit address)
clementine-cli deposit start <RECOVERY_TAPROOT_ADDRESS> <CITREA_ADDRESS>

# Send 10 BTC to the shown address as prompted by the start command

# Monitor deposits
clementine-cli deposit status <DEPOSIT_ADDRESS>
```

### Withdrawal

```sh
# Create wallet for withdrawal (Withdrawal Signer Address)
clementine-cli wallet create my-withdrawal-wallet withdrawal

# Start withdrawal (Generate Withdrawal Address)
clementine-cli withdraw start <WITHDRAWAL_TAPROOT_ADDRESS> <DESTINATION_ADDRESS>

# Send 330 sats to the shown address as prompted by the start command
# Then run withdrawal scan command to find available withdrawal UTXOs
clementine-cli withdraw scan <WITHDRAWAL_TAPROOT_ADDRESS> <DESTINATION_ADDRESS>

# Run the prompted commands to generate withdrawal signatures and send withdrawal request to Citrea for optimistic withdrawal

# Monitor withdrawals
clementine-cli withdraw status <WITHDRAWAL_ADDRESS>
```

## Two-Device Security

We suggest using Clementine CLI with two devices for maximum security:

* **Airgapped device:**\
  All wallet creation, key generation, and signing operations\
  `clementine-cli wallet create`\
  `clementine-cli deposit create-signed-recovery-tx`\
  `clementine-cli withdraw generate-withdrawal-signatures`
* **Online device:**\
  Status monitoring, address generation, broadcasting

## Documentation

* [Download & Verify](/essentials/using-clementine/clementine-cli/download-verify) - Download pre-built binaries and verify signatures
* [Wallet Guide](/essentials/using-clementine/clementine-cli/wallet) - Wallet operations
* [Deposit Guide](/essentials/using-clementine/clementine-cli/deposit) - Deposit Bitcoin to Citrea
* [Withdrawal Guide](/essentials/using-clementine/clementine-cli/withdraw) - Withdrawal from Citrea to Bitcoin
* [Advanced Usage](/essentials/using-clementine/clementine-cli/advanced) - Advanced users only: signet/regtest config, API/RPC selection, hidden CLI commands
* [Reproducible Builds](/essentials/using-clementine/clementine-cli/reproducible-builds) - Build and verify binaries reproducibly


# Download & Verify

This guide explains how to download pre-built binaries and verify their integrity using SHA256 checksums and PGP signatures.

## Release Artifacts

Each GitHub release includes these assets:

* Platform-specific binaries named by release tag and OS/arch, for example `clementine-cli-<RELEASE_TAG>-<OS>-<ARCH>` or `clementine-cli-<RELEASE_TAG>-<OS>-<ARCH>.exe`.
* `SHA256SUMS` file with checksums for all release binaries.
* `SHA256SUMS.asc` which is the PGP-signed checksum file.

Download the latest release binary for your platform from the [Releases](https://github.com/chainwayxyz/clementine-cli/releases) page.

Whenever you see placeholders like `<RELEASE_TAG>-<OS>-<ARCH>` in the commands below, replace them with the values for your download. Example values:

* `<RELEASE_TAG>`: `v0.1.0-rc.1`
* `<OS>`: `darwin`, `linux`, or `windows`
* `<ARCH>`: `aarch64` or `x86_64`

Example filename: `clementine-cli-v0.1.0-rc.1-darwin-aarch64`

## Download

* Download the release binary for your platform.

Download verification is optional but strongly recommended. These steps ensure the binaries and checksum files you downloaded are authentic and unmodified.

* Download `SHA256SUMS`.
* Download `SHA256SUMS.asc`.
* Keep all three files together in the folder where the release artifacts were downloaded.

## Import the Release Signing Key

Only trust a key after validating the **full fingerprint** out-of-band.

If GPG is not installed, install it before proceeding:

* macOS: [GPGTools](https://gpgtools.org)
* Linux: your package manager
* Windows: [Gpg4win](https://gpg4win.org/download.html)

{% hint style="info" %}
Windows users: the GPG executable path shown in this guide assumes Gpg4win is installed under `C:\Program Files\GnuPG\bin\gpg.exe`. If your installation uses a different path, update the commands to match your actual location.
{% endhint %}

References:

* Keyserver: `hkps://keyserver.ubuntu.com`
* Public key repository: [chainwayxyz/pgp-keys](https://github.com/chainwayxyz/pgp-keys)
* Full fingerprints: [FINGERPRINTS.md](https://github.com/chainwayxyz/pgp-keys/blob/main/FINGERPRINTS.md)
* Signer keys: [clementine-cli-builder](https://github.com/chainwayxyz/pgp-keys/tree/main/clementine-cli-builder)

### macOS/Linux

#### From a keyserver

```sh
gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys <KEY_FINGERPRINT>
gpg --fingerprint <KEY_FINGERPRINT>
```

Use the fingerprint or key ID with no spaces in the `recv-keys` command.

Expected output:

* `gpg` reports the key was retrieved/imported.
* The `gpg --fingerprint` line shows the full fingerprint and matches `FINGERPRINTS.md`.

#### From the public key repository

Select a trusted signer from the `clementine-cli-builder` directory and use that filename as `<KEY_FILENAME>`. For stronger assurance, verify against multiple trusted signers and compare fingerprints before trusting a key.

```sh
curl -fsSL https://raw.githubusercontent.com/chainwayxyz/pgp-keys/main/clementine-cli-builder/<KEY_FILENAME> -o clementine-cli-release.pgp
gpg --import clementine-cli-release.pgp
gpg --fingerprint <KEY_FINGERPRINT>
```

Expected output:

* `gpg` reports the key was imported.
* The `gpg --fingerprint` line shows the full fingerprint and matches `FINGERPRINTS.md`.

#### Import all signer keys (optional)

```sh
git clone https://github.com/chainwayxyz/pgp-keys.git
gpg --import pgp-keys/clementine-cli-builder/*.pgp
```

Expected output:

* `gpg` reports each key import.
* The fingerprints you intend to trust match `FINGERPRINTS.md`.

### Windows (PowerShell)

#### From a keyserver

```powershell
& "C:\Program Files\GnuPG\bin\gpg.exe" --keyserver hkps://keyserver.ubuntu.com --recv-keys <KEY_FINGERPRINT>
& "C:\Program Files\GnuPG\bin\gpg.exe" --fingerprint <KEY_FINGERPRINT>
```

Command Prompt:

```cmd
"C:\Program Files\GnuPG\bin\gpg.exe" --keyserver hkps://keyserver.ubuntu.com --recv-keys <KEY_FINGERPRINT>
"C:\Program Files\GnuPG\bin\gpg.exe" --fingerprint <KEY_FINGERPRINT>
```

Use the fingerprint or key ID with no spaces in the `recv-keys` command.

Expected output:

* `gpg` reports the key was retrieved/imported.
* The `gpg --fingerprint` line shows the full fingerprint and matches `FINGERPRINTS.md`.

#### From the public key repository

Select a trusted signer from the `clementine-cli-builder` directory and use that filename as `<KEY_FILENAME>`. For stronger assurance, verify against multiple trusted signers and compare fingerprints before trusting a key.

```powershell
curl.exe -fsSL https://raw.githubusercontent.com/chainwayxyz/pgp-keys/main/clementine-cli-builder/<KEY_FILENAME> -o clementine-cli-release.pgp
& "C:\Program Files\GnuPG\bin\gpg.exe" --import clementine-cli-release.pgp
& "C:\Program Files\GnuPG\bin\gpg.exe" --fingerprint <KEY_FINGERPRINT>
```

Command Prompt:

```cmd
curl -fsSL https://raw.githubusercontent.com/chainwayxyz/pgp-keys/main/clementine-cli-builder/<KEY_FILENAME> -o clementine-cli-release.pgp
"C:\Program Files\GnuPG\bin\gpg.exe" --import clementine-cli-release.pgp
"C:\Program Files\GnuPG\bin\gpg.exe" --fingerprint <KEY_FINGERPRINT>
```

Expected output:

* `gpg` reports the key was imported.
* The `gpg --fingerprint` line shows the full fingerprint and matches `FINGERPRINTS.md`.

Replace `<KEY_FILENAME>` with the specific signer key file (for example, `ahmet-oguz-engin.pgp`) to avoid ambiguity.

#### Import all signer keys (optional)

```powershell
git clone https://github.com/chainwayxyz/pgp-keys.git
& "C:\Program Files\GnuPG\bin\gpg.exe" --import pgp-keys\clementine-cli-builder\*.pgp
```

Command Prompt:

```cmd
git clone https://github.com/chainwayxyz/pgp-keys.git
"C:\Program Files\GnuPG\bin\gpg.exe" --import pgp-keys\clementine-cli-builder\*.pgp
```

Expected output:

* `gpg` reports each key import.
* The fingerprints you intend to trust match `FINGERPRINTS.md`.

The public key repository should contain:

* Individual `.pgp` key files under `clementine-cli-builder/`
* `FINGERPRINTS.md` to cross-check expected fingerprints

## Verify the Checksum Signature

### macOS/Linux

* Run these commands from the folder where the release artifacts were downloaded.
* Ensure the trusted signer keys are imported and the fingerprints match `FINGERPRINTS.md`.
* Verify the checksum signature:

```sh
gpg --verify SHA256SUMS.asc SHA256SUMS
```

### Windows (PowerShell)

* Run these commands from the folder where the release artifacts were downloaded:
  * PowerShell: `cd $env:USERPROFILE\Downloads`
  * Command Prompt: `cd %UserProfile%\Downloads`
* Ensure the trusted signer keys are imported and the fingerprints match `FINGERPRINTS.md`.
* Verify the checksum signature:

```powershell
& "C:\Program Files\GnuPG\bin\gpg.exe" --verify SHA256SUMS.asc SHA256SUMS
```

Command Prompt:

```cmd
"C:\Program Files\GnuPG\bin\gpg.exe" --verify SHA256SUMS.asc SHA256SUMS
```

Expected output:

* A line that starts with: `gpg: Good signature`
* A fingerprint line that matches one of the trusted fingerprints in `FINGERPRINTS.md`

{% hint style="info" %}
Depending on your OS and GPG version, you might not see a `Primary key fingerprint:` line. Some builds print the fingerprint without a label.
{% endhint %}

The fingerprint shown by GPG must match one of the trusted fingerprints you validated from [FINGERPRINTS.md](https://github.com/chainwayxyz/pgp-keys/blob/main/FINGERPRINTS.md). If the signer differs from your trusted set, treat it as untrusted and stop.

You may also see warnings:

* `gpg: Can't check signature: No public key` means GPG could not verify that signer's signature. If this appears for a signer you already imported, stop and fix the key import. Your download is only verified when you see at least one `gpg: Good signature` from a trusted signer whose fingerprint matches [FINGERPRINTS.md](https://github.com/chainwayxyz/pgp-keys/blob/main/FINGERPRINTS.md).
* `gpg: WARNING: This key is not certified with a trusted signature!` or `WARNING: The key's User ID is not certified with a trusted signature!` means GPG cannot establish trust. Confirm the fingerprint matches a trusted signer before proceeding.

Proceed only if the signature is valid and the fingerprint matches your trusted key record.

## Verify the Binary Checksum

Use the checksum file to verify the binary you downloaded. Follow the section for your OS.

### macOS/Linux

From the folder where the release artifacts were downloaded, run:

```sh
sha256sum --check --ignore-missing --strict SHA256SUMS
```

Expected output:

* The line for your downloaded file ends with `OK` (for example: `clementine-cli-v0.1.0-rc.1-darwin-aarch64: OK`).

To compute a hash directly for auditing or tooling and compare it to the matching line in `SHA256SUMS`:

```sh
sha256sum clementine-cli-<RELEASE_TAG>-<OS>-<ARCH>
```

Expected output:

* A single SHA256 hash and filename; it must match the corresponding line in `SHA256SUMS`.

### Windows (PowerShell)

From the folder where the release artifacts were downloaded, run:

```powershell
$file = "clementine-cli-<RELEASE_TAG>-<OS>-<ARCH>.exe"
$expected = (Select-String -Path SHA256SUMS -SimpleMatch $file).Line.Split()[0]
$actual = (Get-FileHash $file -Algorithm SHA256).Hash
$expected -eq $actual
```

Expected output:

* `True` when the checksum matches.

### Windows (Command Prompt)

From the folder where the release artifacts were downloaded, run:

```cmd
certutil -hashfile clementine-cli-<RELEASE_TAG>-windows-x86_64.exe SHA256
type SHA256SUMS
```

Expected output:

* The SHA256 value from `certutil` matches the corresponding line in `SHA256SUMS` (compare every character).

### Windows (PowerShell) - Direct Hash

To compute a hash directly for auditing or tooling and compare it to the matching line in `SHA256SUMS`:

```powershell
Get-FileHash .\clementine-cli-<RELEASE_TAG>-<OS>-<ARCH>.exe -Algorithm SHA256
```

Expected output:

* The `Hash` value matches the corresponding line in `SHA256SUMS`.

## Rename and Run

For easier usage, rename the binary to `clementine-cli` and ensure it is executable. On macOS/Linux, use `./` because the current directory is not in PATH by default, or add the directory containing the binary to your PATH for global access.

### macOS/Linux

```sh
mv clementine-cli-<RELEASE_TAG>-<OS>-<ARCH> clementine-cli
chmod +x clementine-cli
./clementine-cli --help
```

### Windows (PowerShell)

```powershell
Rename-Item clementine-cli-<RELEASE_TAG>-<OS>-<ARCH>.exe clementine-cli.exe
.\clementine-cli.exe --help
```

### Windows (Command Prompt)

```cmd
rename clementine-cli-<RELEASE_TAG>-<OS>-<ARCH>.exe clementine-cli.exe
clementine-cli.exe --help
```


# Wallet Operations

Clementine CLI wallet doesn't provide typical Bitcoin wallet functionality. It is a specialized tool for signing transactions for Clementine deposits and withdrawals.

{% hint style="danger" %}
Don't forget to specify the `--network` flag if you plan to use a different Bitcoin network other than mainnet. Mainnet is selected implicitly for every command. Network aliases are used interchangeably throughout the docs: `bitcoin`/`mainnet`, `testnet4`/`testnet`, `signet`/`devnet`, and `regtest`.
{% endhint %}

## About Clementine Wallets

Clementine CLI wallets are specialized Bitcoin key managers designed for secure bridge operations with Citrea. Unlike Bitcoin Core wallets that manage multiple addresses, each Clementine CLI wallet corresponds to a single Bitcoin address with its associated private key. Clementine CLI wallets generate addresses with specific prefixes that indicate their intended bridge use case and prevent accidental misuse of funds.

### Address Prefixes and Purpose Field

**Safety Feature:** Clementine uses address prefixes to create specialized bridge addresses that prevent fund loss through accidental misuse:

* **"dep" prefix**: Used for deposit operations (e.g., `depbc1p...`)
* **"wit" prefix**: Used for withdrawal operations (e.g., `witbc1p...`)
* **Standard addresses**: Used for regular wallet operations (e.g., `bc1p...`)

**Purpose Field:** When creating a wallet, the `<PURPOSE>` parameter determines the address prefix and cryptographic properties:

* `deposit` → generates addresses with "dep" prefix for deposit operations
* `withdrawal` → generates addresses with "wit" prefix for withdrawal operations

**These are not ordinary Bitcoin addresses** - they are specialized bridge addresses with different spending conditions specifically generated for Clementine bridge operations.

**Why prefixes matter:**

* **Prevent accidental copy-paste errors** that could result in permanent fund loss
* **Ensure proper address derivation** with bridge-specific cryptographic schemes
* **Distinguish between different signature algorithms** required by deposit vs withdrawal operations
* **Provide validation layer** to catch user errors before interacting with Clementine protocol
* **Enable operation-specific security** tailored to each bridge function

{% hint style="danger" %}
Never manually remove or modify address prefixes, as this can lead to:

* Failed Clementine interactions
* Permanent loss of funds due to misinterpretation or confusion
* Inability to recover funds from bridge operations
  {% endhint %}

View all wallet commands: `clementine-cli wallet --help`

{% hint style="warning" %}
It is advised to perform all wallet-related operations on an air-gapped device.
{% endhint %}

## Create Wallet for Deposits

Create a wallet for deposits:

This command will create a wallet for deposits and will prompt you to enter a passphrase. The generated `dep` prefixed address will be used as the `recovery taproot address` for the deposit operation. Don't send any funds to your Clementine wallet addresses unless otherwise specified.

```sh
clementine-cli wallet create <WALLET-LABEL> deposit
```

## Create Wallet for Withdrawals

Create a wallet for withdrawals:

This command will create a wallet for withdrawals and will prompt you to enter a passphrase. The generated `wit` prefixed address will be used as the `signer address` for the withdrawal operation. Don't send any funds to your Clementine wallet addresses unless otherwise specified.

```sh
clementine-cli wallet create <WALLET-LABEL> withdrawal
```

{% hint style="warning" %}
Do not send any funds to your Clementine wallet addresses unless otherwise specified.
{% endhint %}

## Backup and Importing a Wallet

### Export/Backup a Wallet

A wallet can be backed up using:

```sh
clementine-cli wallet backup <BACKUP-DIRECTORY> <WALLET-ADDRESS>

# Example of backing up a wallet with address `tb1pd...` with `deposit` purpose to the current directory
clementine-cli wallet backup . deptb1pd...
```

After that, a `wallet_<address>.json` file will be available as a backup.

### Import Wallet Using File

Wallet files that are generated elsewhere or previously exported can be imported using `import-file` command:

```sh
clementine-cli wallet import-file <FILE-NAME> [WALLET-LABEL]

# Example of importing a wallet in the current directory:
clementine-cli wallet import-file wallet_<address>.json
# Example with label:
clementine-cli wallet import-file wallet_<address>.json wallet1
```

* `<WALLET-LABEL>` is optional. If omitted, the label will be inferred from the file.

### Import Private Key

If you already have a recovery taproot address, you can import it as a wallet using the import utility with your secret key. It will be marked as imported via private key when you list wallets using `clementine-cli wallet list`.

{% hint style="info" %}
This is especially useful if you generated your recovery taproot address using the [website](https://citrea.xyz/bridge); however, this is not recommended. We suggest using those keys only for testing purposes.
{% endhint %}

```sh
clementine-cli wallet import-private-key [--network <BITCOIN_NETWORK>] <WALLET-LABEL> <PURPOSE>
```

### Import Using Mnemonic

You can also import a wallet using the 12 word mnemonic:

```sh
clementine-cli wallet import-mnemonic [--network <BITCOIN_NETWORK>] <WALLET-LABEL> <PURPOSE>
```

This command will prompt you to enter all the mnemonic words step by step.

## Wallet Management

### List All Wallets

View all wallets with their addresses, networks and import status:

```sh
clementine-cli wallet list
```

### Show Mnemonic

Securely display the mnemonic for an existing wallet (use with extreme caution):

```sh
clementine-cli wallet show-mnemonic <WALLET_ADDRESS>
```

### Show Private Key

Display the private key for a wallet (use with extreme caution):

```sh
clementine-cli wallet show-private-key <WALLET_ADDRESS>
```

## Security Best Practices

### Critical Security Requirements

* **Airgapped Environment**: Perform all wallet creation and key operations offline
* **Secure Storage**: Store mnemonic phrases and private keys in encrypted, offline storage
* **Multiple Backups**: Keep wallet backups in multiple secure, geographically distributed locations
* **Access Control**: Limit access to wallet files and ensure proper file system permissions

## Troubleshooting

### Common Issues

**Wallet not found:**

* Verify wallet exists with `wallet list`
* Ensure correct network parameter

**Import failures:**

* Verify mnemonic phrase accuracy (12 words, correct spelling)
* Check private key format
* Ensure backup file is not corrupted

**Permission errors:**

* Check file system permissions on wallet directory
* Ensure sufficient disk space for wallet operations

### Recovery Procedures

If wallet files are corrupted or lost:

1. Use `import-mnemonic` with your backed-up mnemonic phrase
2. Use `import-private-key` if you have the private key backup
3. Use `import-file` with your wallet backup file


# Deposit Guide

This guide covers the complete process for depositing 10 BTC to Citrea using Clementine CLI. The deposit process involves creating a wallet, generating a deposit address, sending 10 BTC, and monitoring the bridging process.

View all deposit commands:

```sh
clementine-cli deposit --help
```

{% hint style="danger" %}
Don't forget to specify the `--network` flag if you plan to use a different Bitcoin network other than mainnet. Mainnet is selected implicitly for every command. Network aliases are used interchangeably throughout the docs: `bitcoin`/`mainnet`, `testnet4`/`testnet`, `signet`/`devnet`, and `regtest`.
{% endhint %}

## Prerequisites

Before starting a deposit, ensure you have:

* A Citrea address
* A Clementine CLI wallet with `deposit` purpose ("dep" prefix address) which will be used as the `recovery taproot address`
* Access to a Bitcoin wallet for sending 10 BTC to the deposit address

## Deposit Process Overview

The deposit process consists of several stages:

1. [**Create a Wallet for Deposits**](#step-1-create-a-wallet-for-deposits) - Create a recovery taproot address
2. [**Start Deposit**](#step-2-start-deposit-generate-deposit-address) - Create a unique deposit address using your Citrea (EVM) address and recovery taproot address
3. [**Send 10 BTC to the Deposit Address**](#step-3-send-10-btc-to-the-deposit-address) - Transfer 10 BTC to the deposit address and rest will be automatically handled by the Clementine, and you will receive your 10 cBTC on your Citrea address.
4. [**Monitor Deposit Status**](#step-4-monitor-deposit-status) - Track the bridging process
5. [**Fund Recovery (If Needed)**](#step-5-fund-recovery-if-needed) - Recover funds if bridging fails

{% hint style="warning" %}
The `RECOVERY_TAPROOT_ADDRESS` and the `DEPOSIT_ADDRESS` are different. The `RECOVERY_TAPROOT_ADDRESS` will belong to your Clementine CLI wallet to be able to sign the recovery transaction in case the deposit fails, whereas the `DEPOSIT_ADDRESS` is the address you send Bitcoin to in order to perform the deposit operation. Your `RECOVERY_TAPROOT_ADDRESS` is used alongside the `N_of_N_ADDRESS` when creating the `DEPOSIT_ADDRESS` to make sure if the deposit fails, you can recover your funds back to your `DESTINATION_ADDRESS`.
{% endhint %}

## Step 1: Create a Wallet for Deposits

Create a deposit-purpose wallet to get your recovery taproot address:

```sh
clementine-cli wallet create <WALLET-LABEL> deposit
```

The `dep`-prefixed address output is your `RECOVERY_TAPROOT_ADDRESS`. See [Wallet Operations](/essentials/using-clementine/clementine-cli/wallet#create-wallet-for-deposits) for details.

## Step 2: Start Deposit (Generate Deposit Address)

### Start Deposit

Create a deposit address using your Citrea (EVM) address and recovery taproot address:

```sh
clementine-cli deposit start [--network <BITCOIN_NETWORK>] <RECOVERY_TAPROOT_ADDRESS> <CITREA_ADDRESS>
```

**Example:**

```sh
clementine-cli deposit start depbc1p... 0x742d35...e4C837Be
# For testnet4
clementine-cli deposit start --network testnet depbc1p... 0x742d35...e4C837Be
```

{% hint style="warning" %}
**About the "dep" prefix:** The recovery taproot address should belong to Clementine wallet with `deposit` purpose and should be prefixed with "dep" to indicate it's being used for deposit operations. This prefix helps distinguish deposit-specific addresses from regular wallet addresses and ensures proper address derivation in the Clementine bridge system.
{% endhint %}

## Step 3: Send 10 BTC to the Deposit Address

Send your Bitcoin to the generated deposit address. You can use any Bitcoin wallet or client. The deposit amount is fixed to `10 BTC`. After sending the funds, rest will be automatically handled by the Clementine, and you will receive your 10 cBTC on your Citrea address.

{% hint style="danger" %}
Save your deposit transaction ID immediately. This is required for recovery if the Move to Vault transaction fails after 200 blocks.
{% endhint %}

## Step 4: Monitor Deposit Status

Track the progress of your deposit throughout the bridging process:

```sh
clementine-cli deposit status [--network <BITCOIN_NETWORK>] <DEPOSIT_ADDRESS>
```

**Example:**

```sh
clementine-cli deposit status tb1pd...
# For testnet4
clementine-cli deposit status --network testnet tb1pd...
```

## Step 5: Fund Recovery (If Needed)

If 200 blocks have passed and the deposit status shows the Move to Vault transaction has not been broadcasted, you can recover your funds using the recovery mechanism. Recovery is done by signing a recovery transaction with your Clementine CLI wallet and broadcasting it to the Bitcoin network.

### Prepare Recovery Data

Gather all necessary information:

* `RECOVERY_TAPROOT_ADDRESS`: Your wallet's recovery address (`depbc1p...`)
* `CITREA_ADDRESS`: Your Citrea address used for the deposit (`0x...`)
* `DEPOSIT_UTXO_OUTPOINT`: Your deposit Outpoint (`txid:vout`)
* `DESTINATION_ADDRESS`: Bitcoin address where recovered funds will be sent
* `CLEMENTINE_AGGREGATED_KEY`: MuSig2 aggregated x-only public key for the bridge signers

You can check `CLEMENTINE_AGGREGATED_KEY` with: `clementine-cli show-config --network <BITCOIN_NETWORK>` or `clementine-cli deposit get-deposit-address-details <DEPOSIT_ADDRESS>`.

Use MuSig2 key aggregation if you need to compute `CLEMENTINE_AGGREGATED_KEY` from signer pubkeys. Signer pubkeys are listed in [Clementine signers](/advanced/clementine-signers). Check the aggregated key with the command below:

```sh
clementine-cli musig2-key-aggregation <PUBKEYS>
```

`PUBKEYS` is a comma-separated list of hex-encoded public keys.

Example:

```sh
clementine-cli musig2-key-aggregation 02abc...123,03def...456
```

### Create Recovery Transaction

Generate signed recovery transaction:

```sh
clementine-cli deposit create-signed-recovery-tx [--network <BITCOIN_NETWORK>] <RECOVERY_TAPROOT_ADDRESS> <CITREA_ADDRESS> <DEPOSIT_UTXO_OUTPOINT> <DESTINATION_ADDRESS> <FEE_RATE> <AMOUNT> <CLEMENTINE_AGGREGATED_KEY>
```

**Example:**

```sh
clementine-cli deposit create-signed-recovery-tx deptb1pd... 0x742d35... abc123def456...:0 tb1qe... 1 10 1e0f48f81dfa14...6bf7
# For testnet4
clementine-cli deposit create-signed-recovery-tx --network testnet deptb1pd... 0x742d35... abc123def456...:0 tb1qe... 1 10 1e0f48f81dfa14...6bf7
```

{% hint style="warning" %}
Please make sure that `AMOUNT` you enter is the exact amount of BTC you sent to the deposit address. This is necessary to recover your funds if you accidentally send any amount other than `10 BTC`.
{% endhint %}

### Verify Recovery Transaction (Optional)

Verify the recovery transaction details before broadcasting:

```sh
clementine-cli deposit verify-recovery-tx [--network <BITCOIN_NETWORK>] <RECOVERY_TX> <RECOVERY_TAPROOT_ADDRESS> <CITREA_ADDRESS> [AMOUNT] <CLEMENTINE_AGGREGATED_KEY>
```

### Broadcast Recovery Transaction

Send the recovery transaction to the Bitcoin network:

```sh
clementine-cli deposit broadcast-recovery-tx <RECOVERY_TX>
```

## Troubleshooting

### Common Issues

**Deposit address generation fails:**

* Verify Citrea (EVM) address format (`0x...`)
* Check recovery taproot address format (`depbc1p...`)
* Ensure network parameter matches your Bitcoin network

**Status check returns no results:**

* Confirm deposit address is correct
* Wait for Bitcoin network confirmation (usually 1-6 blocks)
* Check if deposit transaction was actually broadcasted

**Recovery transaction creation fails:**

* Verify all parameters match original deposit exactly
* Check that 200 blocks have actually passed
* Ensure recovery taproot address is from the correct wallet


# Withdrawal Guide

This guide covers the withdrawal process from Citrea back to Bitcoin using Clementine CLI. Withdrawals follow a specific sequential process.

All available withdrawal commands can be viewed using `clementine-cli withdraw --help` command and `clementine-cli withdraw <subcommand> --help`.

{% hint style="danger" %}
Don't forget to specify the `--network` flag if you plan to use a different Bitcoin network other than mainnet. Mainnet is selected implicitly for every command. Network aliases are used interchangeably throughout the docs: `bitcoin`/`mainnet`, `testnet4`/`testnet`, `signet`/`devnet`, and `regtest`.
{% endhint %}

## Prerequisites

Before starting a withdrawal, ensure you have:

* A Clementine CLI wallet with `withdrawal` purpose ("wit" prefix address) which will be used as the `signer address`
* A Bitcoin address where funds will be sent (destination address)
* Access to Citrea wallet with 10 cBTC to withdraw. This can be on a MultiSig or an EOA wallet.

## Withdrawal Process Overview

The withdrawal process follows these sequential steps:

1. [**Create Withdrawal Wallet**](#step-1-create-a-wallet-for-withdrawal) - Create a withdrawal wallet for the signer address
2. [**Start Withdrawal**](#step-2-start-withdrawal) - Initiate withdrawal process (prompts for Bitcoin transaction)
3. [**Send Bitcoin Transaction**](#step-3-send-required-bitcoin-transaction) - Send 330 sats to the signer address to create withdrawal UTXO
4. [**Scan for Withdrawals**](#step-4-scan-for-withdrawals) - Find available withdrawal UTXOs
5. [**Generate Withdrawal Signatures**](#step-5-generate-withdrawal-signatures) - Create signatures for optimistic and operator-paid withdrawals
6. [**Send**](#step-6-send-10-cbtc-to-the-bridge-contract) - Send withdrawal request with signature to Citrea for optimistic withdrawal along with sending 10 cBTC to the bridge contract for registration of the withdrawal operation. After successful optimistic withdrawal, you will receive your \~10 BTC on your Bitcoin address.
7. [**Check Status**](#step-7-check-withdrawal-status) - Monitor withdrawal progress for optimistic withdrawal for 12 hours
8. [**Send Signature to Operators**](#step-8-send-the-signature-to-the-operators) - If Step 6 fails, submit signature to Clementine operators for operator-paid withdrawal
9. [**Check Status**](#step-7-check-withdrawal-status) - Monitor withdrawal progress for operator-paid withdrawal

{% hint style="warning" %}
The `SIGNER_ADDRESS` and the `DESTINATION_ADDRESS` are different. The `SIGNER_ADDRESS` will belong to your Clementine wallet to be able to perform withdrawal specific signing operations, whereas `DESTINATION_ADDRESS` is the address that the withdrawn BTC funds will be sent to.
{% endhint %}

## Step 1: Create a Wallet for Withdrawal

A new address for withdrawal is required:

```sh
clementine-cli wallet create --network <BITCOIN_NETWORK> <WALLET_NAME> withdrawal
```

**Example:**

```sh
clementine-cli wallet create --network testnet my_withdrawal_wallet withdrawal
```

For more detailed wallet usage, please check the [wallet documentation](/essentials/using-clementine/clementine-cli/wallet).

## Step 2: Start Withdrawal

Start the withdrawal process:

```sh
clementine-cli withdraw start [--network <BITCOIN_NETWORK>] <SIGNER_ADDRESS> <DESTINATION_ADDRESS>
```

**Parameters:**

* `SIGNER_ADDRESS`: Withdrawal wallet address with "wit" prefix
* `DESTINATION_ADDRESS`: Bitcoin address where funds will be sent

**Example:**

```sh
clementine-cli withdraw start wittb1pf... tb1qg...
# For testnet4
clementine-cli withdraw start --network testnet wittb1pf... tb1qg...
```

This command will prompt the user to send 330 sats to the signer address to create the dust UTXO needed for the withdrawal operation.

{% hint style="warning" %}
**About the "wit" prefix:** The signer address must belong to a Clementine wallet with `withdrawal` purpose and should be prefixed with "wit" to indicate it's being used for withdrawal operations. This ensures proper cryptographic derivation for withdrawal bridge operations.
{% endhint %}

**Important:** After running this command, you'll need to send the prompted Bitcoin transaction to the signer address before proceeding.

## Step 3: Send Required Bitcoin Transaction

Send 0.00000330 BTC to the prompted address given by the start command to create your withdrawal UTXO.

{% hint style="info" %}
You'll notice the address used in the command above matches your signer address but lacks the `wit` prefix. This is intentional—the prefix is only needed for Clementine-specific operations, whereas regular transactions use the address in its standard form.
{% endhint %}

{% hint style="warning" %}
If your wallet cannot send exactly 0.00000330 BTC, you may want to send a slightly higher amount. Be sure to update the config to match the amount you actually sent before proceeding. Run `clementine-cli update-config` to update the `dust_utxo_amount` to the amount you actually sent.
{% endhint %}

This creates the small UTXO needed for the withdrawal operation.

## Step 4: Scan for Withdrawals

Scan for available withdrawal UTXOs:

```sh
clementine-cli withdraw scan [--network <BITCOIN_NETWORK>] <SIGNER_ADDRESS> <DESTINATION_ADDRESS>
```

**Example:**

```sh
clementine-cli withdraw scan wittb1pf... tb1qg...
# For testnet4
clementine-cli withdraw scan --network testnet wittb1pf... tb1qg...
```

**What this command does:**

The scan command provides detailed information about your withdrawal:

* **Why**: Explains that it's locating UTXOs to withdraw funds from Citrea back to Bitcoin
* **Where**: Displays the Bitcoin network, signer address, destination address, and expected UTXO amount
* **When**: Shows block height and confirmation status of each found UTXO, indicating whether they're ready for withdrawal or still pending confirmation

The command will:

1. Scan the Bitcoin network for UTXOs at your signer address
2. Display detailed information about each UTXO including:
   * OutPoint (transaction ID and output index)
   * Amount in BTC and satoshis
   * Block height (if confirmed) or mempool status (if unconfirmed)
   * Current status (ready for withdrawal or waiting for confirmation)
3. Filter and identify UTXOs that match the expected dust amount
4. Filter UTXOs that are already used in a withdrawal operation, and warn user not to reuse their signer address
5. Provide the exact command to generate withdrawal signatures for each valid UTXO

{% hint style="success" %}
If a UTXO is unconfirmed, you'll need to wait for Bitcoin network confirmation before proceeding with signature generation.
{% endhint %}

## Step 5: Generate Withdrawal Signatures

Generate the signatures for optimistic withdrawal and operator-paid withdrawal using your Clementine CLI wallet.

This command will generate two signatures: one for `optimistic` withdrawal (which has an exact amount of 999999760 satoshis, or 9.9999976 BTC), and one for `operator-paid` withdrawal (which has an exact amount of 997000000 satoshis, or 9.97 BTC).

```sh
clementine-cli withdraw generate-withdrawal-signatures [--network <BITCOIN_NETWORK>] <SIGNER_ADDRESS> <DESTINATION_ADDRESS> <WITHDRAWAL_UTXO>
```

**Example:**

```sh
clementine-cli withdraw generate-withdrawal-signatures wittb1pf... tb1qg... abc123def456...:0
# For testnet4
clementine-cli withdraw generate-withdrawal-signatures --network testnet wittb1pf... tb1qg... abc123def456...:0
```

{% hint style="danger" %}
Save the generated signatures since they will be used to authorize the withdrawal operations that will be done later.
{% endhint %}

## Step 6: Send 10 cBTC to the Bridge Contract

Send 10 cBTC to the bridge contract for registration of the withdrawal operation. After successful optimistic withdrawal, you will receive your \~10 BTC on your Bitcoin address.

Run the following command to open the webpage where you can send the 10 cBTC to the bridge contract along with the generated withdrawal signature that will be used for optimistic withdrawal.

```sh
clementine-cli withdraw send [--network <BITCOIN_NETWORK>] <SIGNER_ADDRESS> <DESTINATION_ADDRESS> <WITHDRAWAL_UTXO> <OPTIMISTIC_SIGNATURE>
```

**Example:**

```sh
clementine-cli withdraw send wittb1pf... tb1qg... abc123def456:0 807c42770...
# For testnet4
clementine-cli withdraw send --network testnet wittb1pf... tb1qg... abc123def456:0 807c42770...
```

## Step 7: Check Withdrawal Status

Monitor the status of your withdrawal:

```sh
clementine-cli withdraw status [--network <BITCOIN_NETWORK>] <WITHDRAWAL_UTXO>
```

**Parameters:**

* `WITHDRAWAL_UTXO`: Withdrawal UTXO in `txid:vout` format

**Example:**

```sh
clementine-cli withdraw status 4f38192dba8b52fd4327d5c67a3fc2c61fc407a556ee19258026f83dde84798a:0
# For testnet4
clementine-cli withdraw status --network testnet 4f38192dba8b52fd4327d5c67a3fc2c61fc407a556ee19258026f83dde84798a:0
```

The status will show the response from the backend.

## Step 8: Send the Signature to the Operators

If the optimistic withdrawal does not complete within 12 hours, submit the generated `operator-paid` withdrawal signature to bridge operators for `operator-paid` withdrawal processing:

```sh
clementine-cli withdraw send-withdrawal-signature-to-operators [--network <BITCOIN_NETWORK>] <SIGNER_ADDRESS> <DESTINATION_ADDRESS> <WITHDRAWAL_UTXO> <OPERATOR_PAID_SIGNATURE>
```

**Example:**

```sh
clementine-cli withdraw send-withdrawal-signature-to-operators  wittb1pf... tb1qg... abc123def456:0 807c42770...
# For testnet4
clementine-cli withdraw send-withdrawal-signature-to-operators --network testnet wittb1pf... tb1qg... abc123def456:0 807c42770...
```

{% hint style="info" %}
After sending the `operator-paid` signature, Clementine Operators will validate and process the withdrawal. Use Step 7 to monitor the status.
{% endhint %}

## Troubleshooting

* **Address rejected**: `DESTINATION_ADDRESS` must be a normal Bitcoin address without the `wit`/`dep` prefix and not one of your Clementine wallet addresses.
* **No valid UTXOs found in `withdraw scan`**: the dust UTXO must be confirmed and match `dust_utxo_amount`.
* **Signature rejected**: regenerate signatures with the exact `WITHDRAWAL_UTXO` from scan and use the optimistic signature for `withdraw send` or the operator-paid signature for `send-withdrawal-signature-to-operators`.


# Advanced Usage

This guide covers non-default networks, API/RPC configuration, and hidden CLI commands that are available but not shown in `--help`.

## Enable Signet And Regtest

`clementine-cli init` creates the bridge config at `~/.clementine/bridge_cli_config.toml`. The file is a TOML document with a top-level table per network.

By default, only `[bitcoin]` and `[testnet4]` are created. To use signet or regtest, add `[signet]` and/or `[regtest]` sections to the same file.

Copy existing network sections. Update all parameters in the new network section to match the target network you are adding. Adjust endpoints and RPC settings for your environment. Exactly one of `esplora_rest_api` or `bitcoin_config` must be set per network.

After saving the file, you can verify with:

```sh
clementine-cli show-config --network signet
clementine-cli show-config --network regtest
```

## Bitcoin RPC (Manual)

RPC settings are not added by default. If you want to use Bitcoin Core RPC instead of Esplora, you must edit the config file manually to add a `bitcoin_config` section and remove `esplora_rest_api` for that network.

Bitcoin API selection order:

1. `esplora_rest_api` if set (even if `bitcoin_config` is also set)
2. `bitcoin_config` if set
3. Error if neither is set (`No Bitcoin API configured`)

Example (regtest):

```toml
[regtest]
network = "regtest"
aggregated_public_key = "30ff95ec2726938072a2009f3276cd8fba2363d9284a7eb01217b2f302eb8577"
citrea_chain_id = 5655
citrea_backend_endpoint = "https://127.0.0.1/"
user_takes_after = 200
bridge_amount = 1000000000
optimistic_withdrawal_amount = 999999760
operator_withdrawal_amount = 997000000
dust_utxo_amount = 330
bridge_contract_address = "0x3100000000000000000000000000000000000002"
move_tx_finalization_blocks = 5

[regtest.bitcoin_config]
url = "http://127.0.0.1:18443/" # Add `/wallet/name` if necessary
user = "admin"
password = "admin"
```

## Hidden Commands

The CLI includes a few subcommands marked hidden in the help output. They are supported, but intended for advanced workflows.

### Update Config

```sh
clementine-cli update-config --network <network> key=value ...
```

Updates existing keys in `~/.clementine/bridge_cli_config.toml`. It refuses to create new keys, so add `[signet]` or `[regtest]` tables first if needed.

### Deposit Params

```sh
clementine-cli deposit get-deposit-params --network <network> <MOVE_TO_VAULT_TXID>
```

Outputs hex-encoded deposit parameters for a move-to-vault transaction, useful for manual deposit submission.

### Safe Withdraw

```sh
clementine-cli withdraw send-safe-withdraw --network <network> <SIGNER_ADDRESS> <DESTINATION_ADDRESS> <WITHDRAWAL_UTXO> <OPTIMISTIC_SIGNATURE>
```

Sends a safe withdrawal transaction directly to the bridge contract if the normal browser flow fails. Requires `citrea_rpc_url` to be set in `~/.clementine/bridge_cli_config.toml` under the selected network section, and it is not included by default, so add it manually. See [Withdrawal Guide](/essentials/using-clementine/clementine-cli/withdraw) for the primary withdrawal flow.


# Reproducible Builds

This guide shows how to build Clementine CLI reproducibly using [Nix](https://nixos.org/) and verify your build matches the official release.

Reproducible builds ensure bit-for-bit identical binaries, allowing you to verify that published binaries match the source code exactly.

## Platform Support

**4 platforms** are fully supported and reproducible:

| Platform | Architecture   |
| -------- | -------------- |
| Linux    | x86\_64, ARM64 |
| Windows  | x86\_64        |
| macOS    | Apple Silicon  |

### What You Can Build

| Your System               | Can Build For          |
| ------------------------- | ---------------------- |
| **Linux (x86\_64)**       | Linux x86\_64, Windows |
| **Linux (ARM64)**         | Linux ARM64            |
| **macOS (Apple Silicon)** | macOS Apple Silicon    |

{% hint style="info" %}
Cross-compilation is supported for Windows from Linux x86\_64. For reproducibility, Linux ARM64 and macOS Apple Silicon must be built on their native architecture; cross-compilation is not supported for these.
{% endhint %}

## Install Nix

```bash
sh <(curl -L https://nixos.org/nix/install) --daemon
```

Enable flakes (required):

```bash
mkdir -p ~/.config/nix
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf

# Restart Nix daemon
# Linux:
sudo systemctl restart nix-daemon

# macOS:
sudo launchctl unload /Library/LaunchDaemons/org.nixos.nix-daemon.plist
sudo launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist
```

## Build

```bash
# Build for your platform
nix build

# Or specify a platform:
nix build .#linux-x86_64          # Linux x86_64
nix build .#linux-aarch64         # Linux ARM64
nix build .#windows-x86_64        # Windows 64-bit
nix build .#darwin-aarch64        # macOS Apple Silicon

# Binary location:
ls -la ./result/bin/
```

{% hint style="info" %}
First build? Expect 10-20 minutes as Nix builds \~500 dependencies. Subsequent builds take 1-2 minutes.
{% endhint %}

## Supported Platforms

### Working Platforms

Build commands for all working platforms:

```bash
# Linux
nix build .#linux-x86_64            # Intel/AMD 64-bit
nix build .#linux-aarch64           # ARM 64-bit

# macOS (Apple Silicon)
nix build .#darwin-aarch64          # Apple Silicon

# Windows (cross-compile from Linux)
nix build .#windows-x86_64          # 64-bit

# Default (current platform)
nix build
```

**Binary location:** `./result/bin/clementine-cli` (or `.exe` for Windows)

## Platform-Specific Build Instructions

### From Linux

Linux can build for its native architecture and Windows (from x86\_64):

```bash
# Linux builds (on x86_64)
nix build .#linux-x86_64            # Intel/AMD 64-bit

# Cross-compile to Windows (from x86_64 Linux)
nix build .#windows-x86_64          # 64-bit

# Linux ARM64 (on ARM64 system)
nix build .#linux-aarch64           # ARM 64-bit
```

### From macOS

Apple Silicon Macs can build for their native platform. macOS Intel builds are not supported by the current flake targets.

```bash
# Check your Mac architecture
uname -m  # "x86_64" = Intel, "arm64" = Apple Silicon

# Build for your current Mac architecture
nix build                           # Automatically selects your architecture

# Apple Silicon Macs can build:
nix build .#darwin-aarch64          # macOS Apple Silicon
```

{% hint style="info" %}
macOS Intel builds are not supported by the current Nix flake targets.
{% endhint %}

{% hint style="info" %}
We assume that `/usr/lib/libiconv.2.dylib` is present on target macOS systems; if it is not available or you experience issues related to this adjustment, please open an issue on this repository so the maintainers can assist.
{% endhint %}

{% hint style="info" %}
For Linux and Windows builds, use a Linux system.
{% endhint %}

## Development Environment

Enter a development shell with all dependencies:

```bash
nix develop
```

This provides a shell with Rust 1.89.0 and all required build dependencies.

## Verifying Reproducibility

### Quick Test

```bash
# Build twice and compare hashes
nix build .#linux-x86_64
HASH1=$(nix hash path ./result)

# Force rebuild (useful for debugging)
nix build .#linux-x86_64 --rebuild
HASH2=$(nix hash path ./result)

# Should match
echo "Build 1: $HASH1"
echo "Build 2: $HASH2"
```

{% hint style="success" %}
Use `--rebuild` flag to force a rebuild even if the output already exists in the store. This is helpful for debugging and testing reproducibility without clearing the result directory.
{% endhint %}

### Full Verification (recommended for release verification)

Test with a completely clean Nix store to ensure no cached artifacts affect the build:

```bash
# First clean build
nix build .#linux-x86_64
HASH1=$(nix hash path ./result)

# Clean everything and rebuild
rm -rf result
nix store gc --max 0  # Removes all cached dependencies (~36GB)
nix build .#linux-x86_64  # Takes 10-20 minutes
HASH2=$(nix hash path ./result)

# Verify reproducibility
[ "$HASH1" = "$HASH2" ] && echo "Reproducible!" || echo "Not reproducible"
```

### Cross-Machine Verification

To verify your build matches another developer's:

1. **Ensure identical source**: Both machines must be on the same git commit/tag
2. **Build the binary**: Run `nix build .#<platform>`
3. **Compare hashes**: Both should produce identical `nix hash path ./result` and `sha256sum ./result/bin/clementine-cli` output.

If hashes don't match, verify:

* Same git commit/tag: `git rev-parse HEAD`
* Same Nix version: `nix --version` (recommended: 2.32.1)
* Clean build if needed: `nix store gc --max 0` before rebuilding

{% hint style="info" %}
Hashes change when source code, dependencies (Cargo.lock), or build configuration (flake.nix) are modified. Always compare builds from the exact same commit.
{% endhint %}

## Verifying Downloaded Binaries

If you downloaded a pre-built binary from GitHub Releases, you can verify it matches the source code by building it yourself and comparing hashes.

### Step 1: Check the Release Tag

```bash
# Find the release version from the binary filename
# Example: clementine-cli-v0.1.0-linux-x86_64
# The tag is: v0.1.0

# Clone the repository and checkout the release tag
git clone https://github.com/chainwayxyz/clementine-cli.git
cd clementine-cli
git checkout v0.1.0  # Use the version from your downloaded binary
```

### Step 2: Build the Binary

```bash
# Build for the same platform as your downloaded binary
nix build .#linux-x86_64          # For Linux x86_64
nix build .#linux-aarch64         # For Linux ARM64
nix build .#windows-x86_64        # For Windows
nix build .#darwin-aarch64        # For macOS Apple Silicon

# Add --rebuild to force a fresh build (useful for debugging)
nix build .#linux-x86_64 --rebuild
```

### Step 3: Compare Binaries

```bash
# Compare your downloaded binary with the one you just built
sha256sum /path/to/downloaded/clementine-cli
sha256sum ./result/bin/clementine-cli

# Or compare them directly
diff <(sha256sum /path/to/downloaded/clementine-cli) \
     <(sha256sum ./result/bin/clementine-cli)
```

If the SHA256 hashes match, your downloaded binary is bit-for-bit identical to what the source code produces. This proves:

* The binary matches the published source code exactly
* No modifications were made between building and distribution
* The build process is reproducible

{% hint style="success" %}
If hashes don't match, ensure you're using the exact same release tag and building for the correct platform.
{% endhint %}

## Troubleshooting

### Hash Doesn't Match

If your hash doesn't match the expected value:

* Ensure you're on the same git commit/tag
* Check your Nix version: `nix --version`
* Force a rebuild: `nix build .#<platform> --rebuild`
* Try a clean build: `nix store gc --max 0` then rebuild (takes 10-20 min)

### Common Issues

| Issue                                   | Solution                                                                                            |
| --------------------------------------- | --------------------------------------------------------------------------------------------------- |
| **"experimental-features not enabled"** | Add `experimental-features = nix-command flakes` to `~/.config/nix/nix.conf` and restart Nix daemon |
| **Slow first build**                    | Normal - \~500 packages built (10-20 min). Subsequent builds are cached (1-2 min)                   |
| **Out of disk space**                   | Run `nix store gc` for cleanup or `nix store gc --max 0` for full cleanup (\~36GB freed)            |
| **Windows build fails from macOS**      | Not supported - use Linux x86\_64 to build Windows binaries                                         |
| **Linux ARM64 build fails from macOS**  | Not supported - use Linux ARM64 to build Linux ARM64 binaries                                       |

### Cleaning Build Cache

```bash
# Light cleanup (removes unreferenced packages)
nix store gc

# Full cleanup (removes everything, frees ~36GB)
nix store gc --max 0
```

{% hint style="warning" %}
Next build after full cleanup will take 10-20 minutes.
{% endhint %}

Use full cleanup when:

* Testing reproducibility with a clean slate
* Freeing disk space
* Resolving cache issues

## Additional Resources

* [Reproducible Builds Project](https://reproducible-builds.org/)
* [Nix Documentation](https://nixos.org/manual/nix/stable/)


# Execution Environment

The Citrea VM is an EVM-equivalent virtual machine running on Bitcoin and using **$cBTC** as its native token. EVM, as a concept, is arguably the most battle-tested and mature VM in the cryptocurrency ecosystem. It is a deterministic, stack-based virtual machine, renowned for its ability to efficiently execute smart contracts in a secure and isolated environment.

Citrea implements its own EVM, referred to as a "**zkEVM**". A zkEVM is a special EVM implementation that makes the full VM implementation provable. Citrea zkEVM is classified as **Type 2**, which means full equivalency and a scalable and trustless proof system as it is based on zk-STARKs. Citrea zkEVM is built using RISCZero.

#### Different characteristics of Citrea

Being a Type 2 zkEVM, Citrea has some different characteristics compared to Ethereum and other EVM blockchains:

* **Native currency is Bitcoin**: Citrea uses $cBTC for gas fees and transfers in the network, which is the trust-minimized 1:1-backed Bitcoin asset. It is **not** an ERC-20 - it is the native asset with 18 decimals (not 8!).
* **Block time & gas limit**: Citrea has a block time of **2 seconds** with a block gas limit of **10 million**.
* **L1 Fee**: As Citrea posts state diffs to Bitcoin, there is a fundamental DA cost - this is reflected as **L1 Fee** to the users. L1 Fee is deducted from the address's balance at the end of a transaction, and it is calculated with the formula of `l1FeeRate * diffSize`. If there is not enough balance to pay the L1 Fee, the transaction will fail. See the [Fee Model](/advanced/fee-model) for detailed calculations and typical costs.
  * **L1 Fee Rate**: Wei per Byte cost of the state diff, derived from Bitcoin's current fee market.
  * **Diff Size**: The size of the compressed state diff in bytes.
* **EVM Version & Tweaks**: Citrea supports **Pectra** version of EVM with some tweaks:
  * **EIP-4844**: EIP-4844 is not supported on Citrea, along with KZG precompile. If the address `0x0A` is called, it will behave like an EOA.
  * **EIP-2935**: EIP-2935 is not supported on Citrea.
* **Additional Precompiles**: Compared to Pectra version, Citrea offers two additional precompiles: **secp256r1** and **Schnorr**. You can read more about them [here](https://docs.citrea.xyz/developer-documentation/schnorr-secp256r1).
* **Merkle Tree**: Citrea uses Jellyfish Merkle Tree for its state instead of Patricia Merkle Tree.
* **System Smart Contracts**: There are special system smart contracts of Citrea that are optimized for system level operations: `BitcoinLightClient`, `Bridge`, and `FeeVault`. You can read more about them [here](https://docs.citrea.xyz/developer-documentation/system-contracts).


# Security Properties

In terms of security properties, Citrea enables improvements in several areas compared to current Bitcoin scaling solutions.

### Validity

*Only correct state updates are accepted, and there's a way to validate on Bitcoin.*

Citrea executes transactions off-chain in an EVM-compatible environment using RISCZero zkVM, and then for every batch it posts a commitment and a ZK proof to Bitcoin. This proof attests to thousands of Citrea blocks at a time and includes the initial state root, the latest state root, and the compact state diff of the corresponding batch. Therefore, anyone with a Citrea node and a Bitcoin node can independently verify the batch result.

The ZK circuits of Citrea also include blockspace proving - it scans Bitcoin for on-chain commitments as well. Ordering is preserved inside the proof, and the proof itself shows the prover generated the valid proof for a valid state transition, as it cannot do so with an invalid state transition.

As for the verification on Bitcoin L1 itself, Bitcoin Script cannot natively verify ZK Proofs. Citrea uses BitVM to *optimistically verify* ZK proofs for the Clementine bridge. For more details, please refer to the [Clementine](https://docs.citrea.xyz/essentials/clementine-trust-minimized-bitcoin-bridge) page.

### Data Availability

*Anyone can construct the Citrea state using Bitcoin only.*

Citrea uses **Bitcoin as its DA (Data Availability) layer**. Instead of posting full transactions, it publishes **state differences (state diffs)** plus the latest state root to Bitcoin. A full node can rebuild the entire rollup by scanning Bitcoin blocks, extracting valid batches, and applying the posted state diffs - so the rollup remains reconstructible “as long as Bitcoin lives.”

Posting state diffs is a different mechanism compared to traditional sidechains, as sidechains post a very small cryptographic commitment only, which does not let anyone recover the current state of the sidechains.

The trade-off is Bitcoin’s limited bandwidth and fees. Using Bitcoin as the DA inherits strong liveness, recoverability, and auditability (no DA committees to trust), but it also inherits Bitcoin’s blockspace & fee constraints.

### Re-Org Resistance

*You cannot reorder or rewrite Citrea history without re-orging Bitcoin.*

Every Citrea block header is baked into the state transition function. Once a batch containing those headers is **pushed to Bitcoin and confirmed**, **re-orging Citrea would require re-orging Bitcoin**; practically, after \~6 BTC confirmations, such a re-org is considered highly unlikely.

Block producers and nodes operate with **direct access to the Bitcoin network**, and nodes validate Citrea blocks against the referenced Bitcoin blockhash. This tight coupling means Citrea can’t fork independently for already-anchored history - the L2’s practical finality horizon tracks Bitcoin’s, while pre-anchor head movement is bounded by the usual challenge/anchoring cadence.

### Force Transactions

After mainnet launch, Citrea will implement a force-inclusion mechanism from its Bitcoin anchoring and blockspace-proving design: a user can post a minimal L1 commitment on Bitcoin, and Citrea nodes will be required to scan Bitcoin and treat such commitments as must-include inputs. Ordering will be preserved inside the ZK proof - any batch that skips or reorders a valid force transaction observed before the cutoff cannot generate a valid proof and will be rejected during verification on Bitcoin.

If block producers fail or refuse service beyond that window, users will be able to unilaterally progress or exit. Because Citrea uses Bitcoin for data availability and publishes state diffs plus the latest state root, any full node can reconstruct the state and produce Merkle witnesses for balances/state in that scenario. This will enable users to finalize withdrawals or enforce effects without sequencer cooperation, preserving liveness and fund recoverability while inheriting Bitcoin’s auditability and constraints.

{% hint style="warning" %}
The force transaction feature will be implemented post-mainnet.
{% endhint %}


# Transaction Finality

As a rollup on Bitcoin, Citrea has three layers of finality:

* `Confirmed`
* `Finalized`
* `Proven`

The degree of finality begins when a block is *soft-confirmed* by the sequencer, then *finalizes* when the batch window that contains it is finalized on Bitcoin, and reaches its highest level when that window’s execution is *proven* and reconstructable from Bitcoin L1 itself.

When BTC <-> cBTC moves across the bridge, Bitcoin settlement and a short challenge window complete the full process.

### Soft Confirmations

A transaction on Citrea first appears inside a **sequencer-signed soft confirmation (L2 Blocks)** with a block. At this point, the block has been executed in the zkEVM, a new state root has been produced, and full nodes can update their local view immediately. Soft-confirmations enable responsive interfaces and optimistic flows. On the other hand, though, they are not anchored to Bitcoin yet and remain mutable.

The sequencer's signature provides a soft-finality for full nodes. However, as mentioned, the sequencer could still reorder transactions in this range - therefore soft confirmations are great for the UX as a direct confirmation from the sequencer itself but the transactions are not finalized at this stage.

<details>

<summary><strong>Soft Confirmation Fields</strong></summary>

Each soft confirmation encapsulates essential information about a block:

* **Header:**
  * **Height:** The block height/header
  * **Previous Hash**: The hash of the preceding soft confirmation, forming a chain of blocks that prevents replay attacks and ensures correct ordering.
  * **State Root**: The root hash of the rollup state after applying the transactions in this soft confirmation.
  * **Transactions Merkle Root:** A 32-byte Merkle root of all transactions included in the block
  * **L1 Fee Rate**: The fee rate on Bitcoin L1, relevant for calculating transaction costs.
  * **Timestamp**: The timestamp of the block, recording when it was produced by the sequencer.
* **Header Hash:** Rollup block header hash
* **Signature**: The sequencer's signature on the soft confirmation data.
* **Transactions**: List of transactions included in the block.

The structure above is signed and distributed to the network. Soft confirmations form the basis for *sequencer commitments*, which are published to the DA layer for finalization.

</details>

### Finalized

A batch window of Citrea becomes finalized when the sequencer ***inscribes*** a commitment to Bitcoin and that inscription reaches the required confirmation depth. These commitments are called **Sequencer Commitments** and contain the following info:

* a Merkle root over the soft-confirmation hashes
* the batch window’s start and end heights on Citrea

Once a sequencer commitment is finalized on Bitcoin, the ordering of blocks in that window is pinned and the exact set of soft-confirmed blocks that will be proven next is canonical. Therefore, the sequencer commitments provide a great degree of finalization as the order of transactions and blocks are now certain. The finalization here does not prove the execution itself. Yet, it defines the canonical sequence to be proved next.

Sequencer commitments are also used in the **Batch Proof Circuits** to make sure proofs are generated for the canonical batch used in sequencer commitments, too. **Light Client Proofs** that are used in BitVM based [Clementine](https://docs.citrea.xyz/essentials/clementine-trust-minimized-bitcoin-bridge) bridge benefit from the sequencer commitments indirectly, too.

<details>

<summary>Querying Sequencer Commitments</summary>

Sequencer commitments can be queried by using the **Citrea Batch Explorer**, along with the [RPC endpoints](https://docs.citrea.xyz/developer-documentation/rpc-documentation/citrea-rpc-documentation). You can find the explorer [here](https://citrea.xyz/batch-explorer).

</details>

### Proven

The highest level of finality is reached when a batch’s **execution is proven** and posted on Bitcoin. A batch enters **proven finality** once a succinct ZK proof attesting to the correct execution of that batch (called a *batch proof*), along with the minimal state data needed (state diffs), is inscribed on Bitcoin and gains sufficient confirmations. At this point, the entire state transition of that batch is *cryptographically validated* end-to-end, and the necessary data to reconstruct the new state is available on the Bitcoin L1. In other words, any node can *independently rebuild Citrea’s state from Bitcoin alone* by applying each batch’s state diff in order, starting from genesis.

Proven finality provides an **irrefutable guarantee** of correctness. Full nodes will retrieve the batch proof transaction from Bitcoin, verify the zkSNARK, and if the proof is valid, the batch of L2 blocks is conclusively final. Even if the sequencer (or any actor) was malicious, they *cannot* fake a valid proof for an incorrect state transition - thus proven finality is the ultimate safeguard for Citrea’s security.

The rollup blocks are as secure as the Bitcoin proof-of-work that cemented its data and the cryptographic soundness of the zk-proof. Except for an extreme Bitcoin reorganization beyond the finality depth (e.g. >6 blocks), a proven batch cannot be reversed or disputed – the L2 block is effectively as final as an L1 Bitcoin transaction.

<details>

<summary>Batch Proof Inscription Contents</summary>

Each batch proof inscription contains the necessary components for verifiers to validate and apply the batch:

* **Succinct ZK Proof:** A zkSNARK (generated by Citrea’s batch prover) proving that if one starts from the previous proven state and executes all transactions in the batch, the resulting state matches the sequencer’s claims. This proof attests to the validity of the batch’s state transition.
* **State Difference:** A compressed representation of the state changes introduced by the batch (often called the *state diff*). This is the minimal data needed to update the prior state to the new state. Instead of posting full transaction data, Citrea posts the state diff between pre- and post-state, which is constrained by the zk-circuit (any alteration would break the proof).
* **Initial & Final State Roots:** The state root before the batch and the state root after the batch, proving the state was correctly updated. These are used as public inputs to the circuit and help nodes quickly verify they apply the correct batch in sequence.
* **Batch Block Range:** The index range of Citrea blocks covered by this batch (e.g. “L2 blocks 1000–1050”). This links the proof to a specific sequence of soft-confirmed blocks.
* **Referenced Bitcoin Block:** The hash (identifier) of the Bitcoin block containing the sequencer commitment for this batch. This ties the proof to the exact L1 commitment it is proving, ensuring the proof’s batch corresponds to an anchored commitment in a particular Bitcoin block.

When a batch proof is published, full nodes use these components to validate the proof and apply the state diff to their local state. Once verified, the batch’s blocks are considered fully final — the proof serves as a permanent, Bitcoin-backed *certificate of correctness* for those transactions.

</details>


# Overview

CTR is the coordination asset for the Bitcoin economy, handing control of the Citrea ecosystem to its users.

## Overview

CTR has no voting power on its own. Users stake CTR to receive xCTR — a non-transferable token that grants voting power over the Citrea Governance Treasury and the Citrea Network.

## Key Features

* **Staking**: Stake CTR to receive xCTR with a 14-day unstaking window
* **Governance**: xCTR holders vote on treasury allocations, council selection, and network operations
* **Dual Treasury**: Governance Treasury (controlled by xCTR holders) and Foundation Treasury (R\&D, grants, operations)
* **Fixed Supply**: 10 billion CTR, no inflation

## Token Details

| Property     | Value          |
| ------------ | -------------- |
| Name         | Citrea         |
| Symbol       | CTR            |
| Decimals     | 18             |
| Type         | ERC-20         |
| Total Supply | 10,000,000,000 |
| Native Chain | Citrea Network |

## Contract Addresses

| Network | Contract      | Address                                                                                                                                |
| ------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| Citrea  | CTR           | [`0x547AfD93B9c47D552059FEb556909e017f8a9b25`](https://explorer.mainnet.citrea.xyz/token/0x547AfD93B9c47D552059FEb556909e017f8a9b25)   |
| Citrea  | xCTR          | [`0x2015F35030A8Ff2C0CA161a865414996F8E80AA4`](https://explorer.mainnet.citrea.xyz/address/0x2015F35030A8Ff2C0CA161a865414996F8E80AA4) |
| Base    | CTR (bridged) | [`0x11030f79109269d796fd0fb956d6244e502757f7`](https://basescan.org/token/0x11030f79109269d796fd0fb956d6244e502757f7)                  |

## Sections

* [Staking & Governance](/ctr-token/staking-and-governance) — Stake CTR, earn rewards, participate in governance
* [Supply & Allocations](/ctr-token/supply-and-allocations) — Token distribution and circulating supply


# Staking & Governance

Stake CTR to receive xCTR — a non-transferable token that grants voting power over the Citrea Governance Treasury and the Citrea Network.

## How Staking Works

Users stake CTR to receive xCTR, a modified ERC-4626 vault receipt token. xCTR is **non-transferable**. Stakers receive xCTR based on their share of the contract, starting at 1:1 and adjusting as rewards flow in.

| Token    | Description                                          |
| -------- | ---------------------------------------------------- |
| **CTR**  | Base token — transferable, no voting power           |
| **xCTR** | Staked token — non-transferable, grants voting power |

See [Canonical Contract Addresses](/developer-documentation/canonical-contract-addresses) for the CTR, xCTR, and Citrea DAO contract addresses.

## Unstaking

To convert xCTR back to CTR, you go through an exit process with a **14-day unstaking window** and a variable penalty:

* **Instant exit**: 50% flat penalty
* **Days 3–14**: Penalty decays linearly from 50% down to 0%

| Day     | Penalty | You Receive      |
| ------- | ------- | ---------------- |
| Instant | 50%     | 50% of CTR value |
| 3       | 50%     | 50%              |
| 5       | \~41%   | \~59%            |
| 7       | \~32%   | \~68%            |
| 9       | \~23%   | \~77%            |
| 11      | \~14%   | \~86%            |
| 14+     | 0%      | 100%             |

Penalties paid by early exiters are distributed pro-rata to remaining stakers. Both the penalty rates and the unstaking period length are governed by xCTR holders and can be changed by governance.

## Governance

### Dual Treasury Model

Citrea separates treasury responsibilities between two entities:

**Citrea Governance Treasury** (controlled by xCTR holders):

* Liquidity incentives
* Council selection and payments
* Infrastructure provider selection and payments

**Citrea Foundation Treasury**:

* R\&D and ecosystem grants
* Operations and strategic initiatives
* Cannot use its treasury for liquidity emissions without Governance approval (with clear goals and KPIs)

### Voting Power

Your voting power equals your xCTR balance. To activate voting, delegate to yourself or another address. Undelegated xCTR has no voting power.

You can delegate your voting power to a trusted address who will vote on your behalf while retaining your xCTR. Delegation can be changed or revoked at any time.


# Supply & Allocations

## Total Supply

CTR has a fixed supply of **10 billion tokens**.

| Property                           | Value              |
| ---------------------------------- | ------------------ |
| Total Supply                       | 10,000,000,000 CTR |
| Unlocked Supply at Launch          | 34.83%             |
| Circulating Supply (June 25, 2026) | 15%                |

The difference between unlocked supply and circulating supply reflects tokens that are unlocked but not entering the market. The Incentives and Treasury allocation (25.16%) is locked in a smart contract and can only be released through governance via xCTR holders. The Ecosystem Growth and R\&D allocation (22.83%) is held by the Foundation and primarily used for staking and delegation to support governance decentralization at launch.

This page will be updated monthly to reflect actual numbers as tokens are released from the Incentives and Treasury allocation by xCTR holders or deployed through the ecosystem growth strategy from the Foundation.

## Distribution

| Category                  | Allocation | Lockup                                                                                                                                        |
| ------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Initial Claims            | 12%        | Distributed via the Genesis Airdrop and other TGE-related activities, including prior community sale activities                               |
| Incentives and Treasury   | 25.16%     | Governed by xCTR holders to fund the gauge system, ecosystem incentives, and payments to councils or service providers                        |
| Ecosystem Growth and R\&D | 22.83%     | Unlocked at genesis for delegations, strategic multi-year deployment toward research, developer support, ecosystem development and operations |
| Investors                 | 19.35%     | Unlocked over 4 years with a 1 year cliff                                                                                                     |
| Early Contributors        | 20.66%     | Unlocked over 4 years with a 1 year cliff                                                                                                     |

## Availability

CTR is natively issued on the Citrea Network as an ERC-20 token and is also available on the Base Network in bridged form.

| Network | Address                                                                                                                              |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Citrea  | [`0x547AfD93B9c47D552059FEb556909e017f8a9b25`](https://explorer.mainnet.citrea.xyz/token/0x547AfD93B9c47D552059FEb556909e017f8a9b25) |
| Base    | [`0x11030f79109269d796fd0fb956d6244e502757f7`](https://basescan.org/token/0x11030f79109269d796fd0fb956d6244e502757f7)                |

See [Canonical Contract Addresses](/developer-documentation/canonical-contract-addresses) for the full list of canonical contracts on Citrea.


# Kickstart

Welcome to Developer Documentation! In this section, we provide

* some [tools](https://docs.citrea.xyz/developer-documentation/deployment-guide) to start developing quickly
* the ways to run a [Citrea Full Node](https://docs.citrea.xyz/developer-documentation/run-a-node)
* insights to our [System Contracts](https://docs.citrea.xyz/developer-documentation/system-contracts)
* a [comprehensive guide](https://docs.citrea.xyz/developer-documentation/rpc-documentation/citrea-rpc-documentation) to our RPC endpoints (including Citrea-specific endpoints in addition to common eth\_ endpoints)
* and available [ecosystem tooling](https://docs.citrea.xyz/developer-documentation/ecosystem-tooling) for developers


# Chain Information

## Citrea Mainnet

Here are the configs that you can use to connect to the Citrea Mainnet:

| Config          | Value                                 |
| --------------- | ------------------------------------- |
| Chain ID        | 4114                                  |
| Endpoint        | <https://rpc.mainnet.citrea.xyz>      |
| Explorer        | <https://explorer.mainnet.citrea.xyz> |
| Chain Name      | Citrea Mainnet                        |
| Currency Symbol | cBTC                                  |

## Citrea Testnet

Here are the configs that you can use to connect to the Citrea Testnet:

| Config          | Value                                 |
| --------------- | ------------------------------------- |
| Chain ID        | 5115                                  |
| Endpoint        | <https://rpc.testnet.citrea.xyz>      |
| Explorer        | <https://explorer.testnet.citrea.xyz> |
| Chain Name      | Citrea Testnet                        |
| Currency Symbol | cBTC                                  |


# Citrea USD: ctUSD

Citrea USD (ctUSD) is Citrea's fiat-backed, regulatory-compliant stablecoin. Issued by MoonPay, it serves as the default stablecoin on the Citrea network.

### How to Acquire ctUSD

ctUSD is fully ready and available on Citrea Mainnet. Initially, users and developers can acquire ctUSD via four primary channels:

* Bridging from Ethereum: Users can acquire ctUSD using other stablecoins on Ethereum (e.g., USDC, USDT) via bridges integrated to Citrea (e.g. Bridge Hub).
* DEX Pools: Liquid markets are available on Citrea-native Decentralized Exchanges (DEXs).
* MoonPay: Direct fiat-to-crypto purchase using the MoonPay on-ramp widget. See [MoonPay ctUSD Country Availability](/developer-documentation/citrea-usd-ctusd/moonpay-ctusd-country-availability).
* Direct Minting (OTC): Direct minting support is available for large institutional orders.

> ℹ️ Institutional Inquiries: If you are interested in large volume minting, please reach out to us directly at <info@citrea.xyz>.

***

## Developer Guide

ctUSD adheres to the ERC-20 standard, making it compatible with all standard EVM tooling.

### 1. Contract Details

| Network        | Contract Address                                                                                                                     | Decimals |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------- |
| Citrea Mainnet | [0x8D82c4E3c936C7B5724A382a9c5a4E6Eb7aB6d5D](https://explorer.mainnet.citrea.xyz/address/0x8D82c4E3c936C7B5724A382a9c5a4E6Eb7aB6d5D) | `6`      |

> ⚠️ Important: ctUSD uses 6 decimals (not 18). Ensure your app's arithmetic and UI formatting handle this correctly to avoid precision errors.

### 2. Integration Guide

#### Smart Contract (Solidity)

To interact with ctUSD in your contracts, you can use the standard `IERC20` interface from OpenZeppelin.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract MyDeFiProtocol {
    IERC20 public immutable ctUSD;

    // Initialize with the ctUSD address on Citrea Mainnet
    constructor(address _ctUSD) {
        ctUSD = IERC20(_ctUSD);
    }

    function deposit(uint256 amount) external {
        // Transfer ctUSD from the user to this contract
        // Note: The user must approve this contract first
        bool success = ctUSD.transferFrom(msg.sender, address(this), amount);
        require(success, "Transfer failed");

        // Your logic here...
    }
}
```

#### Frontend (Adding to Wallet)

```javascript
import { createWalletClient, custom } from 'viem';
import { citrea } from 'viem/chains';

const client = createWalletClient({
  chain: citrea,
  transport: custom(window.ethereum)
});

const addCtUSD = async () => {
  try {
    const success = await client.watchAsset({
      type: 'ERC20',
      options: {
        address: '0x8D82c4E3c936C7B5724A382a9c5a4E6Eb7aB6d5D', // ctUSD Contract Address
        symbol: 'ctUSD',
        decimals: 6,
        image: 'https://citrea.xyz/assets/ctusd-logo.png',
      },
    });

    if (success) console.log('ctUSD added!');
  } catch (error) {
    console.error('Error adding token:', error);
  }
};
```

***

### 3. Ecosystem Infrastructure (SDKs & Tools)

ctUSD is supported by a full suite of financial infrastructure providers. Use the official documentation below to integrate banking rails, on-ramps, and commerce tools into your application.

| Capability                                      | Provider  | Documentation Link                                      |
| ----------------------------------------------- | --------- | ------------------------------------------------------- |
| Fiat On/Off-Ramps                               | MoonPay   | [View MoonPay Developer Docs](https://dev.moonpay.com/) |
| Autoramp (Virtual Bank Accounts (vIBAN), Swaps) | Iron      | [View Iron API Docs](https://docs.iron.xyz/)            |
| Cross-Chain Swaps & Bridging                    | Swaps.xyz | [View Swaps Protocol Docs](https://docs.swaps.xyz/)     |
| Merchant Payments & Checkout                    | Helio     | [View Helio/Commerce Docs](https://docs.hel.io/)        |

***

### 4. Verification & Transparency (M0 Network)

Because ctUSD is minted via the M0 Protocol, developers and auditors can query the underlying network data to verify reserves, total supply, and minter status in real time.

| Resource                | Description                                                                                        | Link                                                                     |
| ----------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| Transparency Dashboard  | View real-time attestations, reserve breakdowns (Cash vs T-Bills), and audit reports.              | [View M0 Reserves Dashboard](https://dashboard.m0.org/stablecoins/ctusd) |
| Protocol API (GraphQL)  | Programmatically query minter data, supply caps, and collateral health for your UI/Analytics page. | [View M0 GraphQL Docs](https://docs.m0.org/api/overview/)                |
| Contract Specifications | Deep dive into the M0 smart contract architecture used by ctUSD.                                   | [View M0 Protocol Docs](https://docs.m0.org/)                            |

***

### Appendix: Reserves & Regulatory Framework

ctUSD is issued by MoonPay. This legal structure ensures that:

1. Bankruptcy-remote: All reserves are held in segregated accounts, legally distinct from MoonPay's corporate funds, for the benefit of ctUSD holders.
2. 1:1 collateralization: Every token is backed 100% by cash and short-term U.S. Treasury bills.
3. Attestations: Reserves are periodically published on-chain by independent oracles.


# MoonPay ctUSD Country Availability

This page lists country availability for buying ctUSD through MoonPay.

{% hint style="info" %}
MoonPay availability can change based on regional, compliance, and asset-specific requirements. The list below reflects ctUSD buy/on-ramp availability checked against MoonPay's live API on August 18, 2026.
{% endhint %}

| Total countries checked | Supported countries | Not supported countries |
| ----------------------- | ------------------- | ----------------------- |
| 214                     | 124                 | 90                      |

## Supported Countries

Algeria, Angola, Anguilla, Antigua and Barbuda, Argentina, Australia, Bahamas, Bahrain, Belize, Benin, Bermuda, Bhutan, Bolivia, Botswana, Brazil, British Indian Ocean Territory, British Virgin Islands, Brunei, Burundi, Cabo Verde, Cambodia, Cameroon, Cayman Islands, Central African Republic, Chad, Chile, Colombia, Comoros, Costa Rica, Djibouti, Dominica, Dominican Republic, Ecuador, Egypt, El Salvador, Equatorial Guinea, Eritrea, Eswatini, Ethiopia, Falkland Islands, Fiji, Gabon, Gambia, Ghana, Gibraltar, Grenada, Guatemala, Guernsey, Guinea, Guyana, Honduras, Hong Kong, Indonesia, Isle of Man, Israel, Jersey, Jordan, Kenya, Kiribati, Kuwait, Kyrgyzstan, Laos, Lesotho, Malawi, Maldives, Mali, Marshall Islands, Mauritania, Mauritius, Mexico, Micronesia, Montserrat, Mozambique, Namibia, Nauru, Nepal, New Zealand, Niger, Oman, Palau, Panama, Papua New Guinea, Paraguay, Peru, Philippines, Pitcairn, Qatar, Republic of the Congo, Rwanda, Saint Helena, Ascension and Tristan da Cunha, Saint Kitts and Nevis, Saint Lucia, Saint Vincent and the Grenadines, Samoa, São Tomé and Príncipe, Saudi Arabia, Seychelles, Sierra Leone, Singapore, Solomon Islands, South Africa, South Georgia and the South Sandwich Islands, South Korea, Sri Lanka, Suriname, Taiwan, Tajikistan, Tanzania, Thailand, Timor-Leste, Togo, Tonga, Trinidad and Tobago, Tunisia, Turkmenistan, Turks and Caicos Islands, Tuvalu, United Arab Emirates, United States (excluding New York, Colorado, and U.S. Virgin Islands), Uruguay, Uzbekistan, Vanuatu, Vietnam, Zambia.

## Not Supported Countries

Afghanistan, Albania, Andorra, Armenia, Austria, Azerbaijan, Bangladesh, Barbados, Belarus, Belgium, Bosnia and Herzegovina, Bulgaria, Burkina Faso, Canada, China, Côte d'Ivoire, Croatia, Cuba, Cyprus, Czechia, Democratic Republic of the Congo, Denmark, Estonia, Finland, France, Georgia, Germany, Greece, Guinea-Bissau, Haiti, Hungary, Iceland, India, Iran, Iraq, Ireland, Italy, Jamaica, Japan, Kazakhstan, Kosovo, Latvia, Lebanon, Liberia, Libya, Liechtenstein, Lithuania, Luxembourg, Madagascar, Malaysia, Malta, Moldova, Monaco, Mongolia, Montenegro, Morocco, Myanmar, Netherlands, Nicaragua, Nigeria, North Korea, North Macedonia, Norway, Pakistan, Palestine, Poland, Portugal, Romania, Russia, San Marino, Senegal, Serbia, Slovakia, Slovenia, Somalia, South Sudan, Spain, Sudan, Sweden, Switzerland, Syria, Turkey, Uganda, Ukraine, United Kingdom, Vatican City, Venezuela, Western Sahara, Yemen, Zimbabwe.


# CTR & xCTR

Technical reference for integrating with the CTR and xCTR contracts.

* [CTR Token](/developer-documentation/ctr-token/ctr-token) — ERC-20 token with mint/burn and permit
* [xCTR Staking](/developer-documentation/ctr-token/staking) — ERC-4626 staking vault with exit mechanics


# CTR Token

CTR is a standard ERC-20 token with minting capabilities and gasless approvals.

## Specifications

| Property | Value                                 |
| -------- | ------------------------------------- |
| Name     | CTR                                   |
| Symbol   | CTR                                   |
| Decimals | 18                                    |
| Standard | ERC-20 + ERC-2612 (Permit) + Burnable |
| Solidity | 0.8.33                                |

## Features

### Permit (EIP-2612)

Gasless approvals via off-chain signatures:

```solidity
function permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v, bytes32 r, bytes32 s
) external;
```

### Minting

Only addresses with `MINTER_ROLE` can mint:

```solidity
function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE);
```

### Burning

Any holder can burn their own tokens:

```solidity
function burn(uint256 amount) external;
function burnFrom(address account, uint256 amount) external;
```

### Access Control

Uses OpenZeppelin `AccessControlDefaultAdminRules`:

| Role                 | Description             |
| -------------------- | ----------------------- |
| `DEFAULT_ADMIN_ROLE` | Can grant/revoke roles  |
| `MINTER_ROLE`        | Can mint new CTR tokens |


# xCTR Staking

xCTR is an upgradeable ERC-4626 vault with voting power (ERC20Votes). It is **non-transferable** — `transfer()` and `transferFrom()` revert. Standard ERC-4626 `withdraw()` and `redeem()` also revert; use the exit system instead.

## Specifications

| Property     | Value                               |
| ------------ | ----------------------------------- |
| Name         | Staked CTR                          |
| Symbol       | xCTR                                |
| Decimals     | 18                                  |
| Standard     | ERC-4626 + ERC20Votes (upgradeable) |
| Transferable | No                                  |
| Clock Mode   | Timestamp                           |

## Configuration

| Parameter               | Default    | Description                         |
| ----------------------- | ---------- | ----------------------------------- |
| `epochPeriod`           | 7 days     | Reward streaming period             |
| `minExitDuration`       | 3 days     | Minimum wait before exit completion |
| `maxExitDuration`       | 14 days    | Wait time for zero penalty          |
| `minExitPenaltyBps`     | 0 (0%)     | Penalty at max duration             |
| `maxExitPenaltyBps`     | 5000 (50%) | Penalty at min duration             |
| `instantExitPenaltyBps` | 5000 (50%) | Fixed instant exit penalty          |

All parameters are updatable by the contract owner.

## Staking

Deposit CTR to receive xCTR shares:

```solidity
// Approve first
ctr.approve(xCTR_ADDRESS, amount);

// Deposit CTR, receive xCTR
uint256 shares = xCTR.deposit(amount, receiver);

// Or specify shares
uint256 assets = xCTR.mint(shares, receiver);
```

Shares are calculated at the current exchange rate (`totalAssets / totalSupply`). As rewards accrue, each xCTR becomes redeemable for more CTR.

## Rewards

Rewards are streamed linearly over weekly epochs:

1. Rewards added via `addRewards(amount)` are queued for the **next** epoch
2. When a new epoch starts, queued rewards stream linearly over 7 days
3. Exit penalties are also added as rewards for remaining stakers

```solidity
// Add external rewards (requires approval)
ctr.approve(xCTR_ADDRESS, rewardAmount);
xCTR.addRewards(rewardAmount);
```

## Exit System

### Start Exit

Burns xCTR shares and locks the CTR value at the current exchange rate:

```solidity
uint256 exitId = xCTR.startExit(shares);
```

Each user can have multiple pending exits, each with its own ID and timeline. Exit parameters (penalty rates, durations) are **snapshotted** at start time — subsequent parameter changes don't affect existing exits.

### Complete Exit (after day 3)

Penalty decreases linearly from 50% → 0% over the exit window:

```solidity
xCTR.completeExit(exitId);
```

Penalty formula:

```
penaltyBps = minPenalty + (maxPenalty - minPenalty) × (maxDuration - elapsed) / (maxDuration - minDuration)
```

### Cancel Exit (before day 3)

Returns xCTR at the current exchange rate (may differ from original amount):

```solidity
xCTR.cancelExit(exitId);
```

### Instant Exit

Immediate withdrawal with a fixed 50% penalty:

```solidity
xCTR.instantExit(shares);
```

## Read Functions

```solidity
// xCTR balance
uint256 shares = xCTR.balanceOf(user);

// CTR value of shares
uint256 ctrValue = xCTR.convertToAssets(shares);

// Shares needed for a CTR amount
uint256 sharesNeeded = xCTR.convertToShares(ctrAmount);

// Total assets backing all xCTR
uint256 total = xCTR.totalAssets();

// Preview exit outcome
(uint256 assets, uint256 minDur, uint256 maxDur, uint256 minPen, uint256 maxPen) = xCTR.previewStartExit(shares);

// Preview completion at a given timestamp
(uint256 netAssets, uint256 penalty) = xCTR.previewCompleteExit(user, exitId, timestamp);

// Preview cancellation
(uint256 assets, uint256 sharesRestored) = xCTR.previewCancelExit(user, exitId);

// Penalty calculations
uint256 penalty = xCTR.getExitPenalty(assets, duration);
uint256 instantPenalty = xCTR.getInstantExitPenalty(assets);
```

## Voting

xCTR integrates ERC20Votes for governance. Voting power equals xCTR balance but must be delegated to activate:

```solidity
// Delegate to self
xCTR.delegate(msg.sender);

// Delegate to another address
xCTR.delegate(delegatee);

// Check voting power
uint256 votes = xCTR.getVotes(account);

// Historical voting power
uint256 pastVotes = xCTR.getPastVotes(account, timestamp);
```

## Events

| Event                                                    | Description                   |
| -------------------------------------------------------- | ----------------------------- |
| `RewardsAdded(sender, amount, isPenalty)`                | Rewards queued for next epoch |
| `ExitStarted(user, exitId, shares, assets)`              | Exit initiated                |
| `ExitCompleted(user, exitId, amount, penalty, duration)` | Exit finalized                |
| `ExitCancelled(user, exitId, assets, sharesRestored)`    | Exit cancelled, xCTR restored |
| `InstantExited(user, shares, amount, penalty)`           | Instant exit executed         |


# Canonical Contract Addresses

## Assets

| Asset  | Contract Address                                                                                                                     |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| CTR    | [0x547AfD93B9c47D552059FEb556909e017f8a9b25](https://explorer.mainnet.citrea.xyz/token/0x547AfD93B9c47D552059FEb556909e017f8a9b25)   |
| xCTR   | [0x2015F35030A8Ff2C0CA161a865414996F8E80AA4](https://explorer.mainnet.citrea.xyz/address/0x2015F35030A8Ff2C0CA161a865414996F8E80AA4) |
| ctUSD  | [0x8D82c4E3c936C7B5724A382a9c5a4E6Eb7aB6d5D](https://explorer.mainnet.citrea.xyz/address/0x8D82c4E3c936C7B5724A382a9c5a4E6Eb7aB6d5D) |
| wcBTC  | [0x3100000000000000000000000000000000000006](https://explorer.mainnet.citrea.xyz/token/0x3100000000000000000000000000000000000006)   |
| USDC.e | [0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839](https://explorer.mainnet.citrea.xyz/address/0xE045e6c36cF77FAA2CfB54466D71A3aEF7bbE839) |
| USDT.e | [0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4](https://explorer.mainnet.citrea.xyz/address/0x9f3096Bac87e7F03DC09b0B416eB0DF837304dc4) |
| WBTC.e | [0xDF240DC08B0FdaD1d93b74d5048871232f6BEA3d](https://explorer.mainnet.citrea.xyz/address/0xDF240DC08B0FdaD1d93b74d5048871232f6BEA3d) |

## Governance

| Contract   | Address                                                                                                                              |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Citrea DAO | [0xA941b1C1D9aDC88C9241aA3ACA59E8B8f0386419](https://explorer.mainnet.citrea.xyz/address/0xA941b1C1D9aDC88C9241aA3ACA59E8B8f0386419) |

## Bridges

| Bridge                    | Contract Address                                                                                                                     | Network  |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------- |
| Destination USDC.e Bridge | [0x41710804caB0974638E1504DB723D7bddec22e30](https://explorer.mainnet.citrea.xyz/address/0x41710804caB0974638E1504DB723D7bddec22e30) | Citrea   |
| Destination USDT.e Bridge | [0xF8b5983BFa11dc763184c96065D508AE1502C030](https://explorer.mainnet.citrea.xyz/address/0xF8b5983BFa11dc763184c96065D508AE1502C030) | Citrea   |
| Destination WBTC.e Bridge | [0xDF240DC08B0FdaD1d93b74d5048871232f6BEA3d](https://explorer.mainnet.citrea.xyz/address/0xDF240DC08B0FdaD1d93b74d5048871232f6BEA3d) | Citrea   |
| Source USDC Bridge        | [0xdaa289CC487Cf95Ba99Db62f791c7E2d2a4b868E](https://etherscan.io/address/0xdaa289CC487Cf95Ba99Db62f791c7E2d2a4b868E)                | Ethereum |
| Source USDT Bridge        | [0x6925ccD29e3993c82a574CED4372d8737C6dbba6](https://etherscan.io/address/0x6925ccD29e3993c82a574CED4372d8737C6dbba6)                | Ethereum |
| Source WBTC Bridge        | [0x2c01390E10e44C968B73A7BcFF7E4b4F50ba76Ed](https://etherscan.io/address/0x2c01390E10e44C968B73A7BcFF7E4b4F50ba76Ed)                | Ethereum |

## Utility Contracts

| Utility Contract           | Address                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Create2 Factory (Arachnid) | [0x4e59b44847b379578588920ca78fbf26c0b4956c](https://explorer.mainnet.citrea.xyz/address/0x4e59b44847b379578588920ca78fbf26c0b4956c)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| CreateX                    | [0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed](https://explorer.mainnet.citrea.xyz/address/0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| Safe 1.3.0 (EIP-155)       | [Contract addresses list](https://contractscan.xyz/bundle?name=Safe+1.3.0+EIP-155\&addresses=0x017062a1de2fe6b99be3d9d37841fed19f573804,0xb19d6ffc2182150f8eb585b79d4abcd7c5640a9d,0x69f4d1788e39c87893c980c06edf4b7f686e2938,0xfb1bffc9d739b8d520daf37df666da4c687191ea,0x998739bfdaadde7c933b942a68053933098f9eda,0xa1dabef33b3b82c7814b6d82a79e50f4ac44102b,0xc22834581ebc8527d974f8a1c97e1bea4ef910bc,0x98ffbbf51bb33a056b08ddf711f289936aaff717,0x727a77a074d1e6c4530e814f89e618a3298fc044)                                                                                                                          |
| Safe 1.4.1                 | [Contract addresses list](https://contractscan.xyz/bundle?name=Safe+1.4.1\&addresses=0xfd0732dc9e303f09fcef3a7388ad10a83459ec99,0x9b35af71d77eaf8d7e40252370304687390a1a52,0x38869bf66a61cf6bdb996a6ae40d5853fd43b526,0x9641d764fc13c8b624c04430c7356c1c7c8102e2,0x41675c099f32341bf84bfc5382af534df5c7461a,0x29fcb43b46531bca003ddc8fcb67ffe91900c762,0x4e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67,0xd53cd0ab83d845ac265be939c57f53ad838012c9,0x3d4ba2e0884aa488718476ca2fb8efc291a46199,0x526643F69b81B008F46d95CD5ced5eC0edFFDaC6,0xfF83F6335d8930cBad1c0D439A841f01888D9f69,0xBD89A1CE4DDe368FFAB0eC35506eEcE0b1fFdc54) |


# Canonical Bitcoin Addresses

## Mainnet

| Address Type     | Bitcoin Address                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Sequencer        | [bc1pqqjrzkc79qkgys40yfu48s8y04d4zud26cnt48qd98mywl9l70zsadyvz5](https://mempool.space/address/bc1pqqjrzkc79qkgys40yfu48s8y04d4zud26cnt48qd98mywl9l70zsadyvz5)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Batch Prover     | [bc1ppuj4hke08g3qjqlspdud8mkymgfq6y9l4ud4vaglj7fc5k3rrudqm5947j](https://mempool.space/address/bc1ppuj4hke08g3qjqlspdud8mkymgfq6y9l4ud4vaglj7fc5k3rrudqm5947j)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Clementine Vault | [bc1pl7grnght2uhp75wm03djde5a56syp06ssdjf7ucm4wkq0tetpqas5e20e9](https://mempool.space/address/bc1pl7grnght2uhp75wm03djde5a56syp06ssdjf7ucm4wkq0tetpqas5e20e9#taptree=01c0222070458db6f75b129ad93878e7781eeb9ba24bf4bbd498d6a9d3f27827b25c8f81ac01c0ac207ccb7989666c483bf47b87febc5b8bcaeadff718eeaea14fe9e5682cc7195601ac2010075f199d462be0b15a0518c29474e3faf670240ba2cb9b5a209aeee77e0e12ba20f39002e4ec68164dd958903bdea5da936ff3abc92cb4f8a96c92930a0402137cba20fe041cdb5e1912a259b982122294144a986f9cf9ca5a3998c4696d739105d59eba2044bded55bf7d7ccd08e93f5ce6598b1bcf54e1704bd5cff5f3b7be51820c035aba539c\&ikey=50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0) |

> The Clementine Vault is the address that stores all Clementine bridge deposits. Click the link above to view all spending paths in the taproot tree:
>
> * **N-of-N spending path**: Controlled by the [Clementine Signers](/advanced/clementine-signers) enforcing covenants through presigned transactions for normal bridge operations. To verify the N-of-N aggregated public key, see [Clementine Signers](/advanced/clementine-signers#verify-the-musig2-aggregated-key).
> * **Multisig spending path**: Controlled by the [Security Council](/advanced/security-council) for emergency operations & planned upgrades.

## Testnet4

| Address Type     | Bitcoin Address                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Sequencer        | [tb1pgtvrhhny4jd4fe0e0ryv7jzv6udvaa5t2a9dalkk26v9x9upchcsven74z](https://mempool.space/testnet4/address/tb1pgtvrhhny4jd4fe0e0ryv7jzv6udvaa5t2a9dalkk26v9x9upchcsven74z)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Batch Prover     | [tb1pd4mqgarm0gmw4x89pfdxajfwcrvtgmkt7dttet2f5wgyqh4xnxdsxvptxp](https://mempool.space/testnet4/address/tb1pd4mqgarm0gmw4x89pfdxajfwcrvtgmkt7dttet2f5wgyqh4xnxdsxvptxp)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Clementine Vault | [tb1p79fytrmspusruc6s4k74aq89eum0kt5kjsc2ejukjqa67kkp8s7scnm9up](https://mempool.space/testnet4/address/tb1p79fytrmspusruc6s4k74aq89eum0kt5kjsc2ejukjqa67kkp8s7scnm9up#taptree=01c022201e0f48f81dfa14d114f5d942f1e2d50771a4b019fa942606bb1f258b4b326bf7ac01c0ac20b496bfbae14987817c53d592be0aa66c45c7b94443c1f74551373f9ce34d2346ac209c00b80d739933388f136f4519fed20cbaee4153899810703ca216d2320e20c4ba20994283e4c648fbeded4ecf579490622dd4469152e3b4bc8290607ed365fd29beba20850575c6980086279f2b12caf3253a140a815338e22268759d1f3943fa99c44eba20a3b16cb02ee9f4cdf23752b0e99adf96847ec27fd3bceca5830103d349e41369ba539c\&ikey=50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0) |


# Run Citrea Full Node

Running a Citrea node is permissionless - anyone can run a full node for development & security purposes.

{% hint style="warning" %}
**A Citrea Full Node requires a Bitcoin node.** Citrea uses Bitcoin as its DA layer, so before running a Citrea node you need a fully synced Bitcoin Mainnet node running with `-txindex=1`. Set one up first by following [Bitcoin Mainnet](https://docs.citrea.xyz/developer-documentation/run-a-node/bitcoin-mainnet), then use its RPC URL, username, and password in the steps below.
{% endhint %}

The easiest way to get started is to use the Citrea full node Docker image.

### Step 1: Install Docker

Follow instructions to install Docker [here](https://docs.docker.com/engine/install/).

### Step 2: Run Citrea Full Node (mainnet)

```sh
docker run -d \
  -e NETWORK=mainnet \
  -e NODE_URL=<your_bitcoin_node_rpc_url> \
  -e NODE_USERNAME=<your_bitcoin_rpc_username> \
  -e NODE_PASSWORD=<your_bitcoin_rpc_password> \
  -v citrea-data:/mnt/task/citrea-db \
  -p 8080:8080 \
  chainwayxyz/citrea-full-node:latest
```

This starts a Citrea mainnet full node. You must provide a fully synced Bitcoin mainnet node running with `-txindex=1` for `NODE_URL`

{% hint style="info" %}
**Running on Testnet?** Set `NETWORK=testnet` and point `NODE_URL` at a Bitcoin **Testnet4** node (see [Bitcoin Mainnet](https://docs.citrea.xyz/developer-documentation/run-a-node/bitcoin-mainnet) — each guide has a Testnet4 info box). Everything else stays the same:

```sh
docker run -d \
  -e NETWORK=testnet \
  -e NODE_URL=<your_bitcoin_testnet4_node_rpc_url> \
  -e NODE_USERNAME=<your_bitcoin_rpc_username> \
  -e NODE_PASSWORD=<your_bitcoin_rpc_password> \
  -v citrea-data:/mnt/task/citrea-db \
  -p 8080:8080 \
  chainwayxyz/citrea-full-node:latest
```

{% endhint %}

{% hint style="info" %}
Please note that **there are no financial incentives** to run a Citrea Full Node. It's for your own development setup and security practices.
{% endhint %}

***

## Mainnet manual setup (binary or source)

If you prefer to avoid Docker or need to customize your setup, use one of the options below.

### Option 1: Pre-built binary

1. Download the latest binary for your OS from the Citrea releases page.
2. Download mainnet config and genesis files:

```sh
curl https://raw.githubusercontent.com/chainwayxyz/citrea/nightly/resources/configs/mainnet/rollup_config.toml --output rollup_config.toml
mkdir -p genesis
curl https://raw.githubusercontent.com/chainwayxyz/citrea/nightly/resources/genesis/mainnet/evm.json --output genesis/evm.json
curl https://raw.githubusercontent.com/chainwayxyz/citrea/nightly/resources/genesis/mainnet/accounts.json --output genesis/accounts.json
curl https://raw.githubusercontent.com/chainwayxyz/citrea/nightly/resources/genesis/mainnet/l2_block_rule_enforcer.json --output genesis/l2_block_rule_enforcer.json
```

3. Run the node (example for macOS):

```sh
./citrea-v2.4.0-osx-arm64 --network mainnet --da-layer bitcoin --rollup-config-path ./rollup_config.toml --genesis-paths ./genesis
```

{% hint style="info" %}
**Testnet config & genesis:** To run on testnet, download the `testnet` config and genesis instead and run with `--network testnet`:

```sh
curl https://raw.githubusercontent.com/chainwayxyz/citrea/nightly/resources/configs/testnet/rollup_config.toml --output rollup_config.toml
mkdir -p genesis
curl https://raw.githubusercontent.com/chainwayxyz/citrea/nightly/resources/genesis/testnet/evm.json --output genesis/evm.json
curl https://raw.githubusercontent.com/chainwayxyz/citrea/nightly/resources/genesis/testnet/accounts.json --output genesis/accounts.json
curl https://raw.githubusercontent.com/chainwayxyz/citrea/nightly/resources/genesis/testnet/l2_block_rule_enforcer.json --output genesis/l2_block_rule_enforcer.json

./citrea-v2.4.0-osx-arm64 --network testnet --da-layer bitcoin --rollup-config-path ./rollup_config.toml --genesis-paths ./genesis
```

{% endhint %}

### Option 2: Build from source

1. Clone the repository and checkout the latest tag:

```sh
git clone https://github.com/chainwayxyz/citrea
cd citrea
git fetch --tags
git checkout $(git describe --tags `git rev-list --tags --max-count=1`)
```

2. Build and run:

```sh
SKIP_GUEST_BUILD=1 cargo build --release
./target/release/citrea --network mainnet --da-layer bitcoin --rollup-config-path ./resources/configs/mainnet/rollup_config.toml --genesis-paths ./resources/genesis/mainnet
```

{% hint style="info" %}
**Testnet:** the repo also ships testnet config and genesis. Build the same way and run with `--network testnet`:

```sh
./target/release/citrea --network testnet --da-layer bitcoin --rollup-config-path ./resources/configs/testnet/rollup_config.toml --genesis-paths ./resources/genesis/testnet
```

{% endhint %}

{% hint style="info" %}
**Want to sync faster?** Syncing from genesis can take a while. You can start from a recent snapshot instead — see [Full Node Snapshots](https://docs.citrea.xyz/developer-documentation/run-a-node/snapshots).
{% endhint %}

### Step 3: Check the sync status

You can check the status with the following command (you may need to arrange the URL at the end based on your setup):

```sh
curl -X POST --header "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"citrea_syncStatus","params":[], "id":31}' http://0.0.0.0:8080
```

A sample response (fields may vary based on the sync status):

```json
{
  "jsonrpc": "2.0",
  "id": 31,
  "result": {
    "l1Status": {
      "Synced": 46916
    },
    "l2Status": {
      "Syncing": {
        "headBlockNumber": 252441,
        "syncedBlockNumber": 123425
      }
    }
  }
}
```

## Hardware Requirements for running a node

A Linux/Mac/Windows system with a configuration of

* 8 GB RAM
* 2 TB SSD (NVMe recommended)
* 4 core CPU (if you're using cloud)
* 25+ Mbps network connection

should satisfy the minimum requirements to run a Citrea node. Allocating more resources improves the syncing speed.

***

If you encounter any problems during the node running even though you have a system that fits the requirements, please visit our [Discord](https://discord.gg/citrea) and let us know by opening a ticket.

{% hint style="info" %}
**Looking for Testnet?** There's no separate testnet guide — each step above has a Testnet info box showing the changes (set `NETWORK=testnet` / `--network testnet`, use the `testnet` config & genesis, and point at a Bitcoin Testnet4 node).
{% endhint %}


# Bitcoin Mainnet

Citrea uses Bitcoin Mainnet as a DA layer for its mainnet. Thus, it is necessary to have a syncing Bitcoin Mainnet node to run a Citrea Full Node.

In this section, we provide you with two ways to run a Mainnet node (Bitcoin v30.2).

* [Method 1 (Docker)](https://docs.citrea.xyz/developer-documentation/run-a-node/bitcoin-mainnet/mainnet-docker)
  * Easier to setup but less configurable
* [Method 2 (Source)](https://docs.citrea.xyz/developer-documentation/run-a-node/bitcoin-mainnet/mainnet-source)
  * Harder to setup but more configurable

{% hint style="info" %}
**Running Testnet4 instead?** Citrea's testnet uses Bitcoin Testnet4 as its DA layer. The setup is identical apart from adding the `-testnet4` flag and using the testnet4 RPC port (`18443`). Each page below includes a Testnet4 info box with the exact changes.
{% endhint %}

***

Once you're done syncing your Bitcoin node, you can proceed to run a Citrea Full Node [here](https://docs.citrea.xyz/developer-documentation/run-a-node).


# Mainnet Docker Setup

Using the available Docker image is fairly easy to run a Bitcoin Mainnet node.

### Step 1: Install Docker

Follow instructions to install Docker [here](https://docs.docker.com/engine/install/).

### Step 2: Run Mainnet node using Docker:

Pull the correct Bitcoin image and run:

```sh
docker run -d \
  --name bitcoin-mainnet \
  -p 8332:8332 \
  -p 8333:8333 \
  bitcoin/bitcoin:30 \
  -printtoconsole \
  -rest \
  -rpcbind=0.0.0.0 \
  -rpcallowip=0.0.0.0/0 \
  -rpcport=8332 \
  -rpcuser=citrea \
  -rpcpassword=citrea \
  -server \
  -txindex=1
```

Bitcoin Mainnet node should be running in your system. You can check it with the following command:

```sh
curl --user citrea --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getblockcount", "params": []}' -H 'content-type: text/plain;' http://0.0.0.0:8332
```

The `--user` flag and the password are the `rpcuser` and `rpcpassword` values that you used to run the Docker command above.

Now you can proceed to run the Citrea client from [here](https://docs.citrea.xyz/developer-documentation/run-a-node).

{% hint style="info" %}
**Testnet4 setup:** To run a Bitcoin Testnet4 node for Citrea's testnet, add the `-testnet4=1` flag and use the testnet4 ports (`18443` for RPC, `18444` for P2P):

```sh
docker run -d \
  --name bitcoin-testnet4 \
  -p 18443:18443 \
  -p 18444:18444 \
  bitcoin/bitcoin:29 \
  -printtoconsole \
  -testnet4=1 \
  -rest \
  -rpcbind=0.0.0.0 \
  -rpcallowip=0.0.0.0/0 \
  -rpcport=18443 \
  -rpcuser=citrea \
  -rpcpassword=citrea \
  -server \
  -txindex=1
```

Then check it with `http://0.0.0.0:18443` instead of `http://0.0.0.0:8332`.
{% endhint %}

***

If you do not want to use Docker to setup a Bitcoin node, you can build it from the source code [here](https://docs.citrea.xyz/developer-documentation/run-a-node/bitcoin-mainnet/mainnet-source).


# Build Bitcoin Core from Source

### Step 1: Clone the Bitcoin Core repository

Clone the repository from the official Bitcoin Core repository:

```sh
git clone https://github.com/bitcoin/bitcoin.git
cd bitcoin
git checkout v30.2
```

### Step 2: Build Bitcoin Core

Follow the instructions to build the repository for [Linux](https://github.com/bitcoin/bitcoin/blob/v30.2/doc/build-unix.md), [macOS](https://github.com/bitcoin/bitcoin/blob/v30.2/doc/build-osx.md), or [Windows](https://github.com/bitcoin/bitcoin/blob/v30.2/doc/build-windows.md). You don't need to reclone the repo if you're asked to, since we've already done that.

### Step 3: Run Mainnet Node

After building, you can run the following:

```sh
bitcoind -daemon -txindex=1 -rpcbind=0.0.0.0 -rpcport=8332 -rpcuser=citrea -rpcpassword=citrea
```

The arguments you provide here are important - if you modify any of these, you may also need to modify some fields before running a Citrea client in the next steps. Please check everything carefully before proceeding.

{% hint style="info" %}
**Testnet4 setup:** To run a Bitcoin Testnet4 node for Citrea's testnet, add the `-testnet4` flag and use the testnet4 RPC port `18443`:

```sh
bitcoind -testnet4 -daemon -txindex=1 -rpcbind=0.0.0.0 -rpcport=18443 -rpcuser=citrea -rpcpassword=citrea
```

{% endhint %}


# Full Node Snapshots

If you were following the [run Citrea full node](/developer-documentation/run-a-node) guide, you've probably seen the optional step and came here. Think of this as the last step before running your own node. This step is optional and aimed at people who want to reduce syncing time.

Syncing a full node from the genesis block can take a long time since Citrea state tends to grow quickly due to its two-second block time.

Instead of waiting for your node to sync from scratch, you can visit [Citrea Snapshots](https://snapshots.citrea.xyz/). There you will find full node snapshots of different Citrea networks. Pick your network to see the available snapshots.

Snapshots are usually created once every three days. When you use these snapshots, you only need to sync a few days of blocks instead of syncing from genesis.

### Downloading Snapshots

These snapshots can be very large in size, which is why it is **not** recommended to use a browser for downloading. Here's why:

* **No reliable resume support** - Most browsers can technically resume, but it's unreliable. If the connection drops mid-download or the browser crashes, you're often starting from zero.
* **Memory overhead** - Browsers keep download metadata in memory. Long downloads can cause memory bloat, and if the browser crashes, you lose your progress.
* **Poor timeout handling** - Browsers give up too easily on stalled connections.

This is where command line tools come in. You can use any of the following tools to download these snapshots. Click `copy url` next to the snapshot you want to download, open the terminal, and follow the steps for the tool of your choice:

First, create a directory for your downloads and navigate into it:

```sh
mkdir ~/citrea-snapshot && cd ~/citrea-snapshot
```

#### wget

```sh
wget -c <URL>
```

The -c flag enables resuming. **Optionally**, you can add `--timeout=60 --tries=0` for infinite retries on flaky connections.

#### aria2c

```sh
aria2c -x 16 -s 16 -k 100M -c --max-tries=0 --retry-wait=10 <URL>
```

* -x 16: 16 connections per server
* -s 16: split into 16 segments
* -k 100M: minimum split size
* -c: continue/resume
* \--max-tries=0: Infinite retries
* \--retry-wait=10: Retry 10 seconds after failing

#### rclone

```sh
rclone copyurl "<URL>" ~/citrea-snapshot --progress
```

Rclone resumes automatically. **Optionally**, use `--multi-thread-streams=16` to split a single file download across multiple streams, which may speed up your download.

### Extracting

The snapshots are `tar` files. To extract them, use the `tar` command:

```sh
tar -xvf <snapshot_file>.tar
```

No need for the compression flag as the database is not compressed, just packaged.

## Using the Snapshot to Run a Node

After extracting the snapshot, you should see a folder named `full-node`. Copy the absolute path to that folder.

To run the node with the snapshot:

### Using Config Files

Go to your `rollup_config.toml` and under `[storage]`, update the `path` variable with the path to your snapshot folder.

### Using Environment Variables

Update your `STORAGE_PATH` environment variable with the snapshot path:

```sh
export STORAGE_PATH=<path_to_your_snapshot_folder>
```

Now you can return to the [run Citrea full node](https://github.com/chainwayxyz/citrea-docs/blob/main/developer-documentation/run-a-node/citrea-testnet/README.md) guide and start running your node.

### Using Docker Compose

If you're running Citrea using Docker Compose, you can use snapshots by mounting the extracted snapshot directory as a volume.

After downloading and extracting your snapshot, modify the `docker-compose.yml` to mount the snapshot folder directly. Replace the named volume with a bind mount pointing to your extracted snapshot:

```yaml
services:
  citrea-full-node:
    # ... other configuration remains the same
    volumes:
      - /path/to/your/full-node:/mnt/task/citrea-db
```

For example, if you extracted the snapshot to `~/citrea-snapshot/full-node`:

```yaml
volumes:
  - ~/citrea-snapshot/full-node:/mnt/task/citrea-db
```

{% hint style="warning" %}
Make sure the snapshot folder has the correct permissions for Docker to read and write. You may need to run `chmod -R 755 ~/citrea-snapshot/full-node` if you encounter permission errors.
{% endhint %}

Then start your node with:

```sh
docker compose -f docker-compose.yml up
```


# Deployment Guide

Citrea is fully EVM-compatible.

The deployment of your EVM smart contracts and applications is as easy as changing the RPC endpoint. Let's continue by deploying some cool stuff!


# Deploy a Smart Contract Using Remix

## Deploy a Smart Contract Using Remix

This guide will walk you through deploying a smart contract using [Remix](https://remix.ethereum.org/), a web-based IDE for writing and deploying smart contracts.

Before you begin, make sure that you have cBTCs in your account and Citrea Testnet is added to your wallet. If these requirements are not met, follow [the faucet guide](https://docs.citrea.xyz/essentials/how-to-use-faucet) to get some cBTC and add the network to your wallet.

Note: The images below may say Devnet, but everything also applies to Citrea Testnet as well.

### Step 1: Open Remix

Open [Remix](https://remix.ethereum.org/) in your browser. You should see the following screen:

![Remix-1](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-92484d2488cecd34a999a72937e85a28d2be33f4%2F1.png?alt=media)

Select the contracts folder from the left sidebar and click on the `1_Storage.sol` file to open it. This file contains a simple smart contract that stores an integer value on Citrea.

### Step 2: Compile the Smart Contract

Click on the `Solidity Compiler` tab from the left sidebar. You should see something like the following:

![Remix-2](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-c3a3f3e48e5744f2e83b07fb9c179ada890e8a40%2F2.png?alt=media)

First, click on the advanced configurations section and then select `Shanghai` as the EVM version. After this, click on the `Compile 1_Storage.sol` button to compile the smart contract. Compiling the smart contract will generate the ABI and Bytecode required for deploying the smart contract.

> Normally, it's not necessary to select Shanghai as the EVM version. However, Citrea does not support Cancun update at the moment.
>
> If you try to deploy a more complex contract using default configs, there might be some opcode issues. That's why we advise you to pick Shanghai version for now.

### Step 3: Open the Deploy & Run Transactions Tab

Click on the `Deploy & run transactions` tab from the left sidebar. You should see the following screen:

![Remix-3](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-c51662710a9ea866382cded87279adc2b91997ee%2F3.png?alt=media)

### Step 4: Select Citrea Testnet as the Environment and Deploy the Smart Contract

Click on the `Environment` dropdown and select `Injected Provider - MetaMask`. This will automatically connect Remix to your MetaMask wallet. Make sure you have selected Citrea Testnet in your MetaMask wallet. Click on the `Deploy` button to deploy the smart contract.

![Remix-4](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-9005831a73a3a6489f3d4de695217e41bd56a8e8%2F4.png?alt=media)

### Step 5: Confirm the Transaction

MetaMask will prompt you to confirm the transaction. Click on the `Confirm` button to deploy the smart contract.

![Remix-5](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-b8829a69f7ca7877a6a0e3ba44d26ecd38ebc1e3%2F5.png?alt=media)

### Step 6: Interact with the Smart Contract

Once the smart contract is deployed, you can interact with it using the Remix IDE. You can call the `store` function to set the integer value and the `retrieve` function to get the integer value.

![Remix-6](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-8343c98749bf92c4b7ab7180add869fcd776b57f%2F6.png?alt=media)

## Congratulations!

You have successfully deployed a smart contract on Citrea using Remix. You can now start building decentralized applications on Citrea. If you have any questions or need help, feel free to ask in the [Citrea Discord](https://discord.gg/citrea).


# Deploy a Token

## Deploy a Token

This guide will walk you through deploying a smart contract using OpenZeppelin Smart Contract Wizard, a web-based tool for generating smart contracts, and Remix, a web-based IDE for writing and deploying smart contracts.

Before you begin, make sure that you have cBTCs in your account and Citrea Testnet is added to your wallet. If these requirements are not met, follow [the faucet guide](https://docs.citrea.xyz/essentials/how-to-use-faucet) to get some cBTC and add the network to your wallet.

### Step 1: Open OpenZeppelin Smart Contract Wizard

Open [OpenZeppelin Smart Contract Wizard](https://wizard.openzeppelin.com/) in your browser. You should see the following screen:

![OpenZeppelin-1](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-f0bdee6901eefe404c51cb7358e11e508e46b57d%2F1.png?alt=media)

Select the `ERC20` template from the list of available templates. This template will generate a standard ERC20 token smart contract.

### Step 2: Specify the Token Details

Fill in the token details such as `Name`, `Symbol`, `Decimals`, and `Initial Supply`. You can also specify the `Mintable` and `Burnable` options if you want to allow minting and burning of tokens.

![OpenZeppelin-2](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-5f59908dab3bd844059c74c899f026f54efe967d%2F2.png?alt=media)

### Step 3: Move to the Deployment

Click `Open in Remix` to open the generated smart contract in Remix. After this step, you need to compile your smart contract, select the environment, and deploy it. The rest of the guide is the same as the [Deploy a Smart Contract Using Remix](https://docs.citrea.xyz/developer-documentation/deployment-guide/deploy-a-smart-contract-using-remix) guide, from the step 2.

![OpenZeppelin-3](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-29209b0f1326ecd26b6b5601e27e2d46e3bfd98e%2F3.png?alt=media)

## Congratulations!

You have successfully deployed a token on Citrea using Remix. If you have any questions or need help, feel free to ask in the [Citrea Discord](https://discord.gg/citrea).


# Configure Hardhat

## Configure Hardhat

[Hardhat](https://hardhat.org/) is a development environment to compile, deploy, test, and debug your Ethereum software. It helps developers manage the entire development cycle of their smart contracts. Hardhat is a popular choice for developers who want to build, test, and deploy smart contracts on the Ethereum network.

This guide will walk you through configuring Hardhat to work with Citrea. You will learn how to set up Hardhat to deploy smart contracts on Citrea Testnet.

### Hardhat Installation

Before you begin, make sure you have Node.js installed on your machine. If you haven't installed Node.js yet, you can download it from the [official website](https://nodejs.org/).

To install Hardhat, run the following command in your terminal:

```bash
npm install --save-dev hardhat
```

This command will install Hardhat as a development dependency in your project.

### Create a Hardhat Project

To create a new Hardhat project, run the following command in your terminal:

```bash
npx hardhat init
```

Select the default options when prompted. This command will create a new Hardhat project in your current directory.

### Configure Hardhat for Citrea

To configure Hardhat for Citrea, you need to update the `hardhat.config.js` file in your project directory. Open the `hardhat.config.js` file in your code editor and add the following configuration:

```javascript
module.exports = {
    // ...rest of your config
    networks: {
        citrea: {
            url: "https://rpc.mainnet.citrea.xyz",
            chainId: 4114,
            accounts: ["YOUR_PRIVATE_KEY"],
        },
    },
    // ...rest of your config
};
```

{% hint style="info" %}
For testnet:

```javascript
module.exports = {
    // ...rest of your config
    networks: {
        citrea: {
            url: "https://rpc.testnet.citrea.xyz",
            chainId: 5115,
            accounts: ["YOUR_PRIVATE_KEY"],
        },
    },
    // ...rest of your config
};
```

{% endhint %}

Replace `YOUR_PRIVATE_KEY` with your private key. Make sure to keep your private key secure and never share it with anyone. You can obtain a private key from your Citrea Testnet wallet (e.g., MetaMask).

### Implement Your Smart Contract and Deploy

For the rest of the development process, you can follow the official Hardhat documentation to compile, deploy, test, and debug your smart contracts. You can find more information on the [Hardhat website](https://hardhat.org/).

Once you have implemented your smart contract, you can deploy it to Citrea Testnet using the following command:

```bash
npx hardhat run --network citrea scripts/deploy.js
```

This command will deploy your smart contract to the Citrea Testnet network. You can interact with your smart contract using the Citrea Testnet explorer or other tools.

## Congratulations!

You have successfully configured Hardhat to work with Citrea. You can now start building and deploying smart contracts on Citrea Testnet. If you have any questions or need help, feel free to ask in the [Citrea Discord](https://discord.gg/citrea).


# Ecosystem Tooling

This folder highlights ecosystem partners and tools useful for building on Citrea (SDKs, infra, wallets, cross‑chain, data, and more) for developers.

| Page                                                                                         | Description                                                                    |
| -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| [Interop, Bridges & Swaps](/developer-documentation/ecosystem-tooling/interop-bridges-swaps) | Cross‑chain messaging, third-party bridges, and intents‑based BTC swaps        |
| [Oracles & VRF](/developer-documentation/ecosystem-tooling/oracles-vrf)                      | Oracle providers and VRFs on Citrea with links to feeds and deployed contracts |
| [RPC & Indexers](/developer-documentation/ecosystem-tooling/rpc-indexers)                    | RPC access and indexing platforms for querying and mirroring on‑chain data     |
| [Wallets & AA](/developer-documentation/ecosystem-tooling/wallets-aa)                        | Wallets and account‑abstraction tooling                                        |

***

For the full list of partners, see the Citrea ecosystem page: [citrea.xyz/ecosystem](https://citrea.xyz/ecosystem).


# Interop, Bridges & Swaps

### Hyperlane

[Hyperlane](https://docs.hyperlane.xyz/) is a permissionless interoperability framework that lets you pass arbitrary messages/tokens between Citrea and any other Hyperlane‑connected chain. Because deployments are contract‑level (no governance votes), you can spin up **Warp Routes** for your bApp in minutes and own the bridge logic end‑to‑end.

***

### LayerZero

[LayerZero](https://docs.layerzero.network/) provides ultra‑lightweight cross‑chain messaging secured by Decentralised Verifier Networks (DVNs). Citrea Mainnet & Testnet is fully integrated in LayerZero v2, so builders can call contracts, move tokens or tap existing LayerZero SDK helpers using the familiar endpoint config.

***

### Garden Finance

[Garden Finance](https://testnet.garden.finance/?input-chain=citrea_testnet\&input-asset=cBTC) offers intents‑based BTC swaps that bridge native Bitcoin to cBTC on Citrea, using Hashed‑Timelock Contracts behind the scenes.

Garden also offers an SDK for bApp developers. You can find the SDK documentation [here](https://docs.garden.finance/developers/sdk/overview).


# Oracles & VRF

## Available on Mainnet and Testnet

### Redstone

[Redstone](https://redstone.finance) is a modular oracle network that provides secure price feeds for blockchain protocols.

The following price feeds are provided by Redstone on Citrea Mainnet: `BTC/USD`, `USDC/USD`, `USDT/USD`, `aUSD/USD`.

You can find the contract addresses & feeds on the Redstone documentation for [mainnet](https://app.redstone.finance/app/feeds/?page=1\&sortBy=popularity\&sortDesc=false\&perPage=32\&networks=4114) and for [testnet](https://app.redstone.finance/app/feeds/?page=1\&sortBy=popularity\&sortDesc=false\&perPage=32\&networks=5115).

***

## Available on Testnet

### Stork

[Stork](https://stork.network) provides real-time price feeds using a pull-oracle model. It allows developers to fetch the latest price data on demand, ensuring they always have access to the most current information.

You can check the Stork documentation [here](https://docs.stork.network/) to kickstart your development. Stork contracts deployed on Citrea Testnet are at the following address: [0x266795f5A45AEc26aBF7E1c923dC15Cbb1A4Ed96](https://explorer.testnet.citrea.xyz/address/0x266795f5A45AEc26aBF7E1c923dC15Cbb1A4Ed96?tab=contract)

***

### Supra dVRF

Supra dVRF delivers randomness that’s:

* Low-latency
* Tamper-proof (via threshold signatures + secret sharing)
* Unbiased + unpredictable (based on blockhash, nonce & user input)
* Verifiable on-chain with cryptographic proof

You can find the documentation for Supra dVRF [here](https://docs.supra.com/dvrf/v2-guide) and the contracts deployed on Citrea Testnet at the following addresses:

* **Router**: [0xDF666c76E859D6541FF17E1C6c215e46BfA563B2](https://explorer.testnet.citrea.xyz/address/0xDF666c76E859D6541FF17E1C6c215e46BfA563B2?tab=contract)
* **Deposit**: [0xcF99ab8c2AABC04349139484BAFC26f480Ef4cE4](https://explorer.testnet.citrea.xyz/address/0xcF99ab8c2AABC04349139484BAFC26f480Ef4cE4?tab=contract)


# RPC & Indexers

## RPC Providers

Citrea provides free RPC endpoints for developers to use: <https://rpc.mainnet.citrea.xyz> and <https://rpc.testnet.citrea.xyz>. For small projects & simple queries, you may use this endpoint safely as it offers generous rate limits.

However, for larger projects or production use, we recommend [setting up your own RPC node](https://docs.citrea.xyz/developer-documentation/run-a-node) or a dedicated RPC provider.

### Alchemy

[Alchemy](https://www.alchemy.com/docs/reference/citrea-api-quickstart?utm_source=chain_partner\&utm_medium=referral\&utm_campaign=citrea) is a high-performance RPC provider that offers a generous free tier and stronger paid plans for higher usage for Citrea. You may refer to their [webpage](https://www.alchemy.com/pricing?utm_source=chain_partner\&utm_medium=referral\&utm_campaign=citrea) for more details on the usage.

***

## Indexers

### Goldsky

[Goldsky](https://goldsky.com/) is a Web3-native, real-time data platform that lets you index and query on-chain data without wrangling infrastructure. Built for effortless scale and backed by 24 × 7 support, it frees you to ship features instead of managing servers.

Citrea supports both [Goldsky Subgraphs](https://docs.goldsky.com/subgraphs/introduction) and [Goldsky Mirrors](https://docs.goldsky.com/mirror/introduction). Subgraphs provide high-performance, custom-modeled queries with smart tagging for precise filtering for your development, and Mirrors stream live blockchain events straight into your own database and keep data continuously in sync.

As a developer building on Citrea, you can utilize Goldsky products at a discount. Check out the Citrea page on their [documentation](https://docs.goldsky.com/chains/citrea?utm_source=citrea\&utm_medium=docs) for more information and kickstart your development!

*Note*: The correct Citrea slug for Goldsky is `citrea-testnet-tangerine` for testnet, and `citrea` for mainnet.

### Envio

[Envio](https://envio.dev) is a super-fast data platform on Citrea with HyperIndex and HyperSync support.

Using [Envio HyperIndex](https://docs.envio.dev/docs/HyperIndex/overview) you can transform on-chain events into structured, queryable databases with GraphQL APIs.

[Envio HyperSync](https://docs.envio.dev/docs/HyperSync/overview) is Envio's high-performance blockchain data engine that serves as a direct replacement for traditional RPCs for read-only endpoints, delivering up to 2000x faster data access.


# Wallets & Account Abstraction

### Dynamic SDK

[Dynamic](https://www.dynamic.xyz) combines authentication, smart wallets, and secure key management into one flexible SDK. It is available on Citrea Testnet and you can onboard users with email, SMS or social login—no separate wallet extension required.

You can check the documentation from here: [Dynamic SDK Docs](https://www.dynamic.xyz/docs/introduction/welcome).

***

### Pimlico

[Pimlico](https://pimlico.io/) is the world's most popular ERC-4337 account abstraction infrastructure platform. Pimlico provides a suite of tools and services to help you build, deploy, and manage smart accounts on Ethereum and other EVM-compatible chains.

Pimlico's [Bundler](https://docs.pimlico.io/references/bundler) and [Paymaster](https://docs.pimlico.io/references/paymaster) are available on Citrea, allowing you to build account abstraction applications with ease.

You can access the bundler/paymaster endpoints at [https://api.pimlico.io/v2/5115/rpc?apikey=...](https://api.pimlico.io/v2/5115/rpc?apikey=).

***

### Safe{Wallet}

Deployed by [Protofire](https://www.protofire.io), [Safe{Wallet}](https://safe.citrea.xyz) is available on Citrea. It enables more choices for your custody needs, lets you set spending rules for your assets, and activates smarter & safer wallets.

***

{% hint style="info" %}
Citrea is EVM compatible, so you can add Citrea Mainnet & Citrea Testnet to any EVM wallet with the content available at the [chain information](/developer-documentation/chain-information) section.
{% endhint %}


# System Contracts

System contracts are a set of pre-deployed smart contracts on Citrea that are responsible for the core functionalities. These contracts are embedded in the genesis state. They contain functions that can only be processed through a system transaction, in addition to regular functions that can be called by any address.

{% hint style="success" %}
System contracts are also audited under Citrea and Clementine - you can find the reports at [https://docs.citrea.xyz/security/audits-inquiries](https://docs.citrea.xyz/security/audits-inquiries "mention") section.
{% endhint %}

| Address                                      | Name & Explorer Link                                                                                                          |
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `0x3100000000000000000000000000000000000001` | [Bitcoin Light Client Proxy](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000001)          |
| `0x3100000000000000000000000000000000000002` | [Bridge Proxy](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000002)                        |
| `0x3100000000000000000000000000000000000003` | [Base Fee Vault Proxy](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000003)                |
| `0x3100000000000000000000000000000000000004` | [L1 Fee Vault Proxy](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000004)                  |
| `0x3100000000000000000000000000000000000005` | [Priority Fee Vault Proxy](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000005)            |
| `0x3100000000000000000000000000000000000006` | [WCBTC](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000006)                               |
| `0x3100000000000000000000000000000000000007` | [Failed Deposit Vault Proxy](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000007)          |
| `0x3200000000000000000000000000000000000001` | [Bitcoin Light Client Implementation](https://explorer.mainnet.citrea.xyz/address/0x3200000000000000000000000000000000000001) |
| `0x3200000000000000000000000000000000000002` | [Bridge Implementation](https://explorer.mainnet.citrea.xyz/address/0x3200000000000000000000000000000000000002)               |
| `0x3200000000000000000000000000000000000003` | [Base Fee Vault Implementation](https://explorer.mainnet.citrea.xyz/address/0x3200000000000000000000000000000000000003)       |
| `0x3200000000000000000000000000000000000004` | [L1 Fee Vault Implementation](https://explorer.mainnet.citrea.xyz/address/0x3200000000000000000000000000000000000004)         |
| `0x3200000000000000000000000000000000000005` | [Priority Fee Vault Implementation](https://explorer.mainnet.citrea.xyz/address/0x3200000000000000000000000000000000000005)   |
| `0x3200000000000000000000000000000000000007` | [Failed Deposit Vault Implementation](https://explorer.mainnet.citrea.xyz/address/0x3200000000000000000000000000000000000007) |
| `0x31ffffffffffffffffffffffffffffffffffffff` | [Proxy Admin](https://explorer.mainnet.citrea.xyz/address/0x31ffffffffffffffffffffffffffffffffffffff)                         |

In this section we're going over three main system smart contracts of Citrea:

* [https://docs.citrea.xyz/developer-documentation/system-contracts/bitcoin-light-client](https://docs.citrea.xyz/developer-documentation/system-contracts/bitcoin-light-client "mention")
* [https://docs.citrea.xyz/developer-documentation/system-contracts/bridge](https://docs.citrea.xyz/developer-documentation/system-contracts/bridge "mention")
* [https://docs.citrea.xyz/developer-documentation/system-contracts/fee-vaults](https://docs.citrea.xyz/developer-documentation/system-contracts/fee-vaults "mention")

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FXOvqLtMbo8dA08qyO49X%2Fimage.png?alt=media&#x26;token=33de669b-1b70-4599-84af-36589ca28921" alt=""><figcaption></figcaption></figure>

### System Transactions

System transactions originate from a hardcoded address with no private key:

```solidity
address constant SYSTEM_CALLER = 0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD;
```

Finding the corresponding private key is a 1-in-2^160 problem, which is practically impossible within the lifetime of the universe.

The sequencer prepares the calls and injects them at the start of every block. They spend no balance from the sender, but their gas consumption still counts toward the block gas limit (which is *10 million*).

Typical system transactions include the one-time bootstraps

```solidity
lightClient.initializeBlockNumber(uint256 height);
bridge.initialize(bytes prefix, bytes suffix, uint256 depositAmount);
```

as well as the per-Bitcoin-block maintenance call

```solidity
lightClient.setBlockInfo(bytes32 blockHash, bytes32 witnessRoot, uint256 coinbaseDepth);
```

and the bridge’s deposit handler:

```solidity
bridge.deposit(Transaction moveTx, MerkleProof proof, bytes32 shaScriptPubkeys);
```

Because their inclusion is enforced, these transactions are deterministic and cannot be censored by external actors even though no private key signs them.


# Bitcoin Light Client

Citrea’s on-chain light client for Bitcoin. Each finalized Bitcoin block is pushed into this contract via a system transaction so that other contracts (most importantly the bridge) can prove transactions of Bitcoin. For each new Bitcoin block, the block hash and the witness root are written.

```solidity
address constant BITCOIN_LIGHT_CLIENT = 0x3100000000000000000000000000000000000001;
```

That proxy address `0x3100…0001` hosts the client on mainnet & testnet: [explorer link](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000001).

### Important to Know

```solidity
address constant SYSTEM_CALLER = 0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD;
```

The system caller is a hardcoded address with no private key. It is used to execute system transactions that mutate the state of the contract.

```solidity
event BlockInfoAdded(uint256 height, bytes32 blockHash, bytes32 witnessRoot, uint256 coinbaseDepth);
```

Only the system caller can mutate state; the modifier rejects everyone else and there is no separate admin role. All hashes are treated as ***little endian*** during verification - block hashes, wtxids, and each proof. Therefore, callers must respect that encoding when constructing proofs. Every update emits `BlockInfoAdded` with the height, block hash, witness root, and coinbase depth for indexing and debugging.

### State

```solidity
uint256 public blockNumber;
mapping(uint256 => bytes32) public blockHashes;
mapping(bytes32 => bytes32) public witnessRoots;
mapping(bytes32 => uint256) public coinbaseDepths;
```

The `blockNumber` slot marks the next Bitcoin height the contract expects to append. Each successful update stores the block hash at its height, and also keys `witnessRoots` and `coinbaseDepths` by that block hash. The depth tracks where the coinbase transaction sits inside the tree so proof lengths can be enforced.

Be careful when reading `witnessRoots`: a zero root can either mean “*not recorded*” or “*single-transaction block whose coinbase wtxid is zero*,” so downstream contracts must distinguish those cases instead of assuming zero means missing data.

### Access Control

```solidity
modifier onlySystem()
```

Calls that mutate state must come from the system caller. With no owner exposed, there is nothing to reconfigure or override once deployed, which keeps the light client deterministic and narrow in scope.

Citrea purposely lags behind Bitcoin by a configurable finality depth enforced in the node.

The sequencer only calls `setBlockInfo` for a Bitcoin block after it has sat that many confirmations deep, so `blockNumber` is always behind Bitcoin tip. This buffer avoids propagating shallow Bitcoin reorgs into Citrea (which could otherwise halt the chain).

{% hint style="warning" %}
In [batch proof circuit](https://github.com/chainwayxyz/citrea/blob/nightly/docs/batch-proof-circuit.md), committing to the last finalized Bitcoin hash in the Bitcoin Light Client contract, prevents the L2 from claiming validity on a forked Bitcoin chain
{% endhint %}

The confirmation depth differs by network:

* **Citrea Mainnet** — `6` confirmations, meaning roughly 6-block latency between a Bitcoin event and its availability to on-chain contracts like the bridge.
* **Citrea Testnet** — `100` confirmations, set higher to withstand the frequent deep reorgs on Bitcoin Testnet4, resulting in a correspondingly longer latency.

### Functions

```solidity
function initializeBlockNumber(uint256 _blockNumber) external onlySystem
```

This one-time bootstrap anchors the light client to the Bitcoin height used when Citrea genesis is derived. Any second attempt reverts, so the sequencer must ensure it runs exactly once in the first block.

```solidity
function setBlockInfo(bytes32 _blockHash, bytes32 _witnessRoot, uint256 _coinbaseDepth) external onlySystem
```

Appends the next Bitcoin block in order. The call writes the provided block hash to `blockHashes` at the current `blockNumber`, stores the witness root and coinbase depth keyed by that hash, emits `BlockInfoAdded`, and finally increments `blockNumber`. Heights cannot be skipped or overwritten - if the sequencer attempts to jump ahead or rewind, the transaction will fail, keeping the light client consistent with Bitcoin’s linear history.

```solidity
function getBlockHash(uint256 height) external view returns (bytes32)
function getWitnessRootByHash(bytes32 blockHash) external view returns (bytes32)
function getWitnessRootByNumber(uint256 height) external view returns (bytes32)
```

The getters expose stored data for other contracts. A missing block hash returns zero.

Witness root getters mirror the storage semantics: they return zero when data has not been written, but they also return zero legitimately when the witness root itself is zero (single-transaction blocks where the coinbase wtxid is zero). Callers must not treat a zero witness root as proof of absence without additional context.

```solidity
function verifyInclusion(
    bytes32 blockHash,
    bytes32 wtxId,
    bytes calldata proof,
    uint256 index
) external view returns (bool)
```

```solidity
function verifyInclusion(
    uint256 height,
    bytes32 wtxId,
    bytes calldata proof,
    uint256 index
) external view returns (bool)
```

Both overloads rebuild the witness Merkle root from the provided wtxid, proof bytes, and index and compare it against storage. The proof length must equal the stored coinbase depth multiplied by 32 bytes, which hardens the verifier against variable-depth Merkle tricks such as the [Bitslog](https://bitslog.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design/) attack.

```solidity
function verifyInclusionByTxId(
    uint256 height,
    bytes32 txId,
    bytes calldata blockHeader,
    bytes calldata proof,
    uint256 index
) external view returns (bool)
```

This variant works for legacy txids. It first hashes the provided header to confirm it matches the stored block hash, uses the coinbase depth to enforce proof length, extracts the transaction Merkle root from the header, and then delegates to `ValidateSPV.prove` for the inclusion check. Callers should keep the height in sync with the header to avoid mismatched proofs.

{% hint style="warning" %}
Passing a zero wtxid will verify because coinbase wtxids are zero. Please ensure that callers do not inadvertently prove inclusion of the coinbase transaction when they intended to prove user-supplied data, especially when any non-coinbase input is required for downstream logic.
{% endhint %}


# Bridge

The Citrea <> Bitcoin bridge contract, utilized by [Clementine](https://docs.citrea.xyz/essentials/clementine-trust-minimized-bitcoin-bridge). It validates Bitcoin deposits using the on-chain light client, mints cBTC on Citrea, and records withdrawal intents so BTC can be paid out on L1 using Clementine.

```solidity
address constant BRIDGE = 0x3100000000000000000000000000000000000002;
```

That proxy at `0x3100…0002` lives on mainnet & testnet: [explorer link](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000002). The implementation sits at `0x3200…0002`, managed by the proxy admin.

### Dependencies & Constants

```solidity
address constant BITCOIN_LIGHT_CLIENT = 0x3100000000000000000000000000000000000001;
address constant SYSTEM_CALLER = 0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD;
address constant SCHNORR_PRECOMPILE = 0x0000000000000000000000000000000000000200;
address constant FAILED_DEPOSIT_VAULT_PREDEPLOY = 0x3100000000000000000000000000000000000007;
uint256 constant SAT_TO_WEI = 10**10; // 1 sat = 1e10 wei
uint64 constant PAYOUT_ANCHOR_OUTPUT_AMOUNT = 240; // sats
```

All validation leans on the light client at `0x3100…0001`. Mutations can be triggered by the system caller and, for most flows, by the operator once configured. Schnorr verification delegates to the [precompile at `0x200`](https://docs.citrea.xyz/developer-documentation/schnorr-secp256r1).

If a deposit transfer into cBTC reverts, the contract forwards the amount to a failed deposit vault that defaults to the [FailedDepositFeeVault](https://docs.citrea.xyz/developer-documentation/system-contracts/fee-vaults) at `0x3100…0007`.

Values in Bitcoin are expressed in satoshis; conversions rely on the fixed `SAT_TO_WEI` ratio, and `safeWithdraw` expects a payout anchor of `240` sats to account for Taproot dust.

Because the light client only ingests Bitcoin blocks after they clear Citrea’s configured Bitcoin finality depth, bridge actions that rely on transaction inclusion proofs also experience this delay. A Bitcoin deposit does not become provable to the bridge until its block has reached the required confirmations and been written through `setBlockInfo`. This is a protection against re-orgs; if Bitcoin ever reorged deeper than that buffer, on-chain state could not be rewritten and operators would need to coordinate an out-of-band recovery.

{% hint style="warning" %}
The confirmation depth differs by network: Citrea Mainnet uses `6` confirmations, while Citrea Testnet uses `100` to withstand the frequent deep reorgs on Bitcoin Testnet4. Deposits and withdrawals appear on Citrea only after the respective number of confirmations.
{% endhint %}

### Data Structures

The bridge mirrors Clementine’s transaction representation.

| Transaction field   | Explanation                                                                                                                                   |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `version (bytes4)`  | Raw version bytes from the serialized transaction.                                                                                            |
| `flag (bytes2)`     | Marker for Segwit; expected to be `0x0001` for Taproot deposits.                                                                              |
| `vin (bytes)`       | Serialized inputs vector exactly as it appears on-chain.                                                                                      |
| `vout (bytes)`      | Serialized outputs vector, used to locate the deposit output and reconstruct the sighash.                                                     |
| `witness (bytes)`   | Concatenated witness stack for each input; for deposits the first item is the aggregated signature, followed by the script and control block. |
| `locktime (bytes4)` | Serialized `nLockTime`.                                                                                                                       |

| MerkleProof field           | Explanation                                                 |
| --------------------------- | ----------------------------------------------------------- |
| `intermediateNodes (bytes)` | Concatenated 32-byte siblings from the witness Merkle path. |
| `blockHeight (uint256)`     | Height of the Bitcoin block that included the transaction.  |
| `index (uint256)`           | Leaf index within the witness tree.                         |

| UTXO field          | Explanation                                                     |
| ------------------- | --------------------------------------------------------------- |
| `txId (bytes32)`    | *Little-endian* transaction id for the output being referenced. |
| `outputId (bytes4)` | *Little-endian* output index inside that transaction.           |

`shaScriptPubkeys` is an additional parameter for deposit and replace calls. It is the precomputed `sha_scriptpubkeys` Taproot component that stands in for the previous output script during BIP-341 sighash reconstruction, since the transaction itself cannot reveal the prevout script.

### Roles & Pausing

Ownership follows [*Ownable2Step*](https://docs.openzeppelin.com/contracts/4.x/api/access#Ownable2Step). The owner configures scripts, operator, vault, and withdrawal amount, and can pause or unpause the contract. The operator relays deposits and replacement transactions; it starts as the system caller to cover genesis bootstrapping. The system caller can always initialize and call deposit directly. `replaceDeposit` also stays callable while paused so operators can fix deposit records even if user-facing entry points are frozen.

### State Overview

```solidity
bool public initialized;
address public operator;
uint256 public depositAmount;
address public failedDepositVault;
bytes public depositPrefix;
bytes public depositSuffix;
bytes public replacePrefix;
bytes public replaceSuffix;
UTXO[] public withdrawalUTXOs;
bytes32[] public depositTxIds;
mapping(bytes32 => bool) public processedTxIds;
mapping(bytes32 => bool) public usedWithdrawalUTXO;
uint256 public optimisticWithdrawAmountSats;
```

Initialization of the bridge runs once to seed the script parts and `depositAmount`. That amount must be non-zero, convertible to sats without remainder (`depositAmount % SAT_TO_WEI == 0`), and small enough to fit into a `uint64` when expressed in sats so Bitcoin-side logic cannot overflow.

The `failedDepositVault` defaults to the predeploy, but owners can redirect it to a managed recovery contract. Deposit scripts are split into prefix and suffix to make recipient extraction deterministic; replacement scripts follow the same pattern but must embed the exact aggregated key used by the deposit script. Deposits write txids into `depositTxIds`; replacements mutate those entries while `processedTxIds` blocks reuse of any seen txid.

Withdrawals queue `UTXO` pairs, and a hash of each pair in `usedWithdrawalUTXO` prevents duplicate withdrawal intents. `optimisticWithdrawAmountSats` defaults to `depositAmount / SAT_TO_WEI` minus the 240-sat anchor, and `safeWithdraw` enforces it on payout transactions.

### Initialization & Configuration

```solidity
function initialize(bytes calldata depositPrefix, bytes calldata depositSuffix, uint256 depositAmount) external
```

Callable only by the system caller. It seeds the deposit script parts, validates the deposit amount (non-zero, divisible by `SAT_TO_WEI`, representable in `uint64` sats), and requires the prefix to be at least 34 bytes so the aggregated key and opcodes are fully present. The call computes `optimisticWithdrawAmountSats = depositAmount / SAT_TO_WEI - PAYOUT_ANCHOR_OUTPUT_AMOUNT`, sets the `operator` to the system caller, and points `failedDepositVault` to the predeploy. Any second invocation reverts to keep bootstrap deterministic.

```solidity
function setDepositScript(bytes calldata prefix, bytes calldata suffix) external onlyOwner
```

Updates the script template the bridge expects in deposit witness data. The prefix must be at least 34 bytes to cover the aggregated key plus Taproot opcodes. Changing the script effectively rotates the target Musig key or spending policy and should be coordinated with off-chain signers.

```solidity
function setReplaceScript(bytes calldata prefix, bytes calldata suffix) external onlyOwner
```

Sets the script template for replacement transactions. The contract extracts the aggregated key from the prefix and checks it matches the key embedded in the current depositPrefix, preventing a replacement that would be valid for a different signer set.

```solidity
function setFailedDepositVault(address newVault) external onlyOwner
```

Redirects failed deposit transfers to a different vault. Zero addresses are rejected so failed funds cannot be burned accidentally.

```solidity
function setOptimisticWithdrawAmountSats(uint256 amount) external onlyOwner
```

Tunes the payout amount that safeWithdraw expects. This is separate from depositAmount and allows adjustments for fee conditions on Bitcoin without changing the deposit denomination.

```solidity
function setOperator(address newOperator) external onlyOwner
```

Moves the operator role. The new address cannot be zero, and once set it gains access to deposit and replaceDeposit while the system caller retains deposit access.

```solidity
function pause() external
function unpause() external
```

Owner or operator can stop or resume deposit, withdraw, batchWithdraw (and safeWithdraw).

### Deposit Flow

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FvRk9rpcBVCKWxM1qQJZk%2Fimage.png?alt=media&#x26;token=c7233dbc-5bb3-4e54-b5dd-0da9ba1151c4" alt=""><figcaption></figcaption></figure>

```solidity
function deposit(
    Transaction calldata moveTx,
    MerkleProof calldata proof,
    bytes32 shaScriptPubkeys
) external onlySystemOrOperator whenNotPaused
```

The system caller and the operator can invoke deposit. The function begins by decoding the transaction fields, confirming that witness item counts match `vin` entries, computing the wtxid, and proving inclusion through the light client using the provided Merkle proof. It enforces exactly one input for the deposit transaction. The witness must contain three elements: the aggregated Schnorr signature, the Taproot script, and the control block. Using `shaScriptPubkeys`, the bridge reconstructs the [BIP-341](https://en.bitcoin.it/wiki/BIP_0341) sighash and verifies the signature against the aggregated key embedded in `depositPrefix`.

Replay protection relies on `processedTxIds`: any transaction id seen in `deposit` or `replaceDeposit` causes an immediate revert. A fresh txid is appended to `depositTxIds` so off-chain systems can correlate `depositId` with txid history, while the corresponding wtxid remains available in the event for Taproot-aware tooling. The contract then inspects the witness script and requires it to equal `depositPrefix` concatenated with a 20-byte recipient address and `depositSuffix`. The address in the middle is treated as the cBTC recipient.

Finally, the bridge transfers `depositAmount` of cBTC to that recipient. If the transfer reverts-for example because a contract rejects the payment or triggers a revert due to fallback logic-the bridge diverts the funds to the `failedDepositVault` instead. In both outcomes it emits a Deposit-like event so operators can reconcile on-chain balances with Bitcoin deposits.

Each successful deposit’s `depositId` matches its index in `depositTxIds` and is included in the `Deposit` event. Off-chain systems can map `depositId` back to the original Bitcoin txid for proof-of-reserve or auditing purposes.

### Replacing Deposits

```solidity
function replaceDeposit(
    Transaction calldata replaceTx,
    MerkleProof calldata proof,
    uint256 idToReplace,
    bytes32 shaScriptPubkeys
) external onlyOperator
```

Replacement covers scenarios where the original Move transaction must be swapped with a new Clementine transaction. The bridge validates the structure exactly like `deposit`, enforces the single input rule, and verifies the Taproot signature using `shaScriptPubkeys` and the aggregated key. It rejects any txid that has appeared before via `processedTxIds`.

The witness script must equal `replacePrefix` concatenated with the txid being replaced and `replaceSuffix`. That txid is read from `depositTxIds[idToReplace]`; the check ensures a replacement can only target a known deposit id. After validation, the bridge overwrites that array entry with the new txid and emits `DepositReplaced` so observers can link the new on-chain Bitcoin transaction to the existing deposit slot.

### Withdrawals

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FSPR9ZssOPjYOfenXCu0K%2Fimage.png?alt=media&#x26;token=1a63283e-d60d-4cda-aabd-a21b101446dd" alt=""><figcaption></figcaption></figure>

```solidity
function withdraw(bytes32 txId, bytes4 outputId) public payable whenNotPaused
```

`withdraw` burns or locks exactly `depositAmount` of cBTC (the function reverts unless `msg.value` equals that amount) and records a withdrawal intent tied to a specific UTXO on Bitcoin. The `txId`/`outputId` pair represents the dust input the user will spend in their payout transaction using `SIGHASH_ALL|ANYONECANPAY`. The contract hashes the pair and ensures it has never been used by checking `usedWithdrawalUTXO`, then appends the `UTXO` to `withdrawalUTXOs` and emits `Withdrawal` with the index and timestamp. Once recorded, operators can include the entry when constructing payout PSBTs.

```solidity
function batchWithdraw(bytes32[] calldata txIds, bytes4[] calldata outputIds) external payable whenNotPaused
```

`batchWithdraw` is a vectorized form of `withdraw`. It charges `depositAmount` times the number of provided UTXOs and applies the same uniqueness check to each hash before appending them in order. The event mirrors the single-withdraw path so downstream systems can index both.

```solidity
function safeWithdraw(
    Transaction calldata prepareTx,
    MerkleProof calldata prepareProof,
    Transaction calldata payoutTx,
    bytes calldata blockHeader,
    bytes calldata withdrawalAddressPubKey
) external payable
```

`safeWithdraw` is deliberately heavy but self-contained. The caller supplies a prepare transaction and proof to show inclusion via the light client, using the legacy txid path with the provided `blockHeader`. The payout transaction must have exactly one input and one output, with a valid witness structure, and the output value must equal `optimisticWithdrawAmountSats`. The output script pubkey is checked against `withdrawalAddressPubKey` to ensure the funds are headed to the claimed address.

The function confirms the payout input spends `prepareTx` and that the spent output is P2TR - it extracts the Taproot key, rebuilds the `SIGHASH_SINGLE|ANYONECANPAY` digest, and verifies the Schnorr signature through the precompile. On success it emits `SafeWithdrawal` and internally calls `withdraw` with the spent txid and index, enforcing the same uniqueness and `depositAmount` payment.

```solidity
function getWithdrawalCount() external view returns (uint256)
```

Returns the length of `withdrawalUTXOs` so clients can iterate or poll without fetching the full array.

### Helpers & Utilities

```solidity
function getAggregatedKey() external view returns (bytes32)
```

Extracts the aggregated [MuSig](https://bitcoinops.org/en/topics/musig/) key from the current `depositPrefix` so off-chain tooling can confirm which signer set is active. Internally the bridge also relies on byte comparison helpers and a `taggedHash` helper to mirror Taproot hashing. These do not expose new state but are essential for reconstructing sighashes faithfully.

### Events

```solidity
event Deposit(bytes32 wtxId, bytes32 txId, address recipient, uint256 timestamp, uint256 depositId);
event DepositTransferFailed(bytes32 wtxId, bytes32 txId, address recipient, uint256 timestamp, uint256 depositId);
event DepositReplaced(uint256 index, bytes32 oldTxId, bytes32 newTxId);
event Withdrawal(UTXO utxo, uint256 index, uint256 timestamp);
event SafeWithdrawal(Transaction payoutTx, UTXO spentUtxo, uint256 index);
event DepositScriptUpdate(bytes depositPrefix, bytes depositSuffix);
event ReplaceScriptUpdate(bytes replacePrefix, bytes replaceSuffix);
event FailedDepositVaultUpdated(address oldVault, address newVault);
event OptimisticWithdrawAmountSet(uint256 amount);
event OperatorUpdated(address oldOperator, address newOperator);
```

`Deposit` and `DepositTransferFailed` include both the wtxid and the legacy txid alongside the `depositId`, making it easy to correlate Taproot-level proof material with the bridge’s internal slot. `DepositReplaced` records the exact txid swap so watchers can audit history. `Withdrawal` and `SafeWithdrawal` surface the full `UTXO` or payout transaction involved, letting off-chain agents reconstruct the exact intent that was accepted. Script update events publish the current template, while `FailedDepositVaultUpdated`, `OptimisticWithdrawAmountSet`, and `OperatorUpdated` give an authoritative trail for configuration changes.


# Fee Vaults

Fee vaults collect native cBTC fees and forward them to configured recipients. All vault variants share the same implementation today and differ only by address.

| Vault              | Address                                                                                                                                |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| BaseFeeVault       | [`0x3100000000000000000000000000000000000003`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000003) |
| L1FeeVault         | [`0x3100000000000000000000000000000000000004`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000004) |
| PriorityFeeVault   | [`0x3100000000000000000000000000000000000005`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000005) |
| FailedDepositVault | [`0x3100000000000000000000000000000000000007`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000007) |

In genesis, the owner of each vault is set to the configured fee vault owner and the initial `recipient` and minimum withdraw values are populated (`0.5 cBTC` by default in deployment scripts). The implementations are upgradeable through the proxy admin so behavior can diverge across vaults if needed later. `FailedDepositVault` follows the same logic and simply serves as the catch-all destination for bridge deposits that could not be delivered to their intended recipients.

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2FGLQ2Uo4nnRIicjpCkYqg%2Fimage.png?alt=media&#x26;token=8d9aa22f-24a5-4267-b59f-3e4a0107171a" alt=""><figcaption></figcaption></figure>

### State

```solidity
address public recipient;
uint256 public minWithdraw;
```

The `receive()` hook accepts native cBTC from any sender. Execution nodes credit fees directly to the appropriate vault address: base fees accumulate in `BaseFeeVault`, L1 gas reimbursements accumulate in `L1FeeVault`, and priority tips accumulate in `PriorityFeeVault`. When a bridge deposit transfer fails on the recipient side, the bridge forwards the funds into `FailedDepositVault`. Each vault therefore acts as a passive accumulator until a withdrawal flushes its balance to an operational account.

### Access Control

Ownership is handled through [`Ownable2StepUpgradeable`](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/access/Ownable2StepUpgradeable.sol). Only the owner can adjust the recipient or the minimum withdrawal threshold, but anyone can trigger withdrawal once the balance is high enough. That design lets operators regularly sweep fees without exposing owner keys to every caller.

### Functions

```solidity
function withdraw() external
```

`withdraw` sends the entire vault balance to the configured recipient. It reverts if the recipient is unset or if the balance is below `minWithdraw`, so operators typically size `minWithdraw` to avoid dust withdrawals or to amortize L1 payout costs. The transfer uses a low-level call to avoid gas stipends interfering with cBTC delivery. On success the function emits `Withdrawal` with the amount paid out so accounting systems can reconcile accrual versus sweep amounts.

```solidity
function setRecipient(address _recipient) external onlyOwner
```

`setRecipient` rotates the payout address and rejects the zero address to avoid accidental burns. Events include both old and new values to keep monitoring systems in sync.

```solidity
function setMinWithdraw(uint256 _minWithdraw) external onlyOwner
```

`setMinWithdraw` tunes the lower bound for successful withdrawals. Raising the value delays sweeps until more fees accrue; lowering it enables more frequent but smaller payouts. The function emits `MinWithdrawUpdated` so fee collection dashboards can adapt thresholds.

### Events

```solidity
event Withdrawal(address recipient, uint256 amount);
event RecipientUpdated(address oldRecipient, address newRecipient);
event MinWithdrawUpdated(uint256 oldMinWithdraw, uint256 newMinWithdraw);
```

`Withdrawal` gives an on-chain record of every sweep. The update events track governance actions over the vault configuration, which is especially important for anyone following how fee flows are redirected or throttled over time.


# secp256r1 & Schnorr Precompiles

The secp256r1 and Schnorr precompiles are enabled with the [Tangerine](https://www.blog.citrea.xyz/tangerine-upgrade-bitvm-activation-on-clementine/) upgrade of Citrea. In this document we will go over the details of these precompiles and how to use them.

### secp256r1 Curve Support ([RIP 7212](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md))

RIP 7212 is an improvement proposal that introduces a precompile support for the secp256r1 curve. In Citrea, like other EVM rollups, this precompile is available at address `0x0000000000000000000000000000000000000100`.

This precompile enables a whole new set of applications and use cases, such as:

* **Hardware & Biometric Authentication**: Native support of secp256r1 allows smart contracts to directly validate the signatures from secure enclaves and passkey devices, such as Apple's [Secure Enclave](https://support.apple.com/guide/security/secure-enclave-sec59b0b31ff/web), Android's [Keystore](https://developer.android.com/privacy-and-security/keystore), Yubikeys, and WebAuthn authenticators.
* **Account Abstraction & Smart Wallets**: Combining features above with account abstraction & smart wallets, self-custodial platforms can be built much more easily and efficiently, such as [Tanari](https://www.tanari.io/). It also improves the security and the UX perspective of applications massively.
* **Gas-efficient signature verification**: With this precompile, secp256r1 signature verification comes down to `3450` gas, which is significantly cheaper than any other existing smart contract verification method.

#### Technical Details

The precompile accepts a 160-byte input, which is a concatenation of:

1. `Message Hash (32 bytes)`: The 32-byte hash of the message that was signed.
2. `Signature r value (32 bytes)`: The r component of the ECDSA signature.
3. `Signature s value (32 bytes)`: The s component of the ECDSA signature.
4. `Public Key X-coordinate (32 bytes)`: The X-coordinate of the uncompressed secp256r1 public key.
5. `Public Key Y-coordinate (32 bytes)`: The Y-coordinate of the uncompressed secp256r1 public key.

Upon successful verification, the precompile returns a 32-byte value `0x00...01`. On failure (e.g., invalid signature, malformed input), it returns empty bytes: `0x`.

### Example Smart Contract

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

/// @title secp256r1 Precompile Example
/// @notice Calls the secp256r1 precompile to verify secp256r1 ECDSA signatures
contract P256R1VerifyCaller {
    address constant P256R1_VERIFY_PRECOMPILE = 0x0000000000000000000000000000000000000100;

    /**
     * @notice Verifies a secp256r1 (RIP-7212) ECDSA signature.
     * @dev All inputs must be 32-byte big-endian values.
     * @param messageHash 32-byte message hash
     * @param r 32-byte signature r value
     * @param s 32-byte signature s value
     * @param pubKeyX 32-byte public key X coordinate
     * @param pubKeyY 32-byte public key Y coordinate 
     * @return isValid True if signature is valid, false otherwise.
     */
    function callP256R1Verify(
        bytes32 messageHash,
        bytes32 r,
        bytes32 s,
        bytes32 pubKeyX,
        bytes32 pubKeyY
    ) external view returns (bool isValid) {
        // Concatenate inputs in correct order: hash | r | s | pubKeyX | pubKeyY
        bytes memory input = abi.encodePacked(
            messageHash,
            r,
            s,
            pubKeyX,
            pubKeyY
        );
        (bool ok, bytes memory output) = P256R1_VERIFY_PRECOMPILE.staticcall(input);
        // 32-byte return, last byte == 0x01 means success
        return ok && output.length == 32 && output[31] == 0x01;
    }
}
```

***

### Schnorr Signature Verification

Schnorr signature is a Bitcoin-native, linear, and aggregation-friendly signature scheme. It is a key component of Bitcoin's Taproot upgrade ([BIP 340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki)) and also offers advantages for multi-signature schemes like [MuSig2](https://bitcoinops.org/en/topics/musig/). In Citrea, this precompile is available at the address `0x0000000000000000000000000000000000000200`.

Schnorr precompile enables an interesting set of developments, such as:

* **Scriptless cross-chain atomic swaps**: With Schnorr adaptor signatures it is possible to build BTC <> cBTC atomic swaps without HTLCs or any other third-party custody.
* **Bitcoin-aware oracles & bridges**: A smart contract on Citrea can now prove that a Taproot key signed some data without any external verifiers.

#### Technical Details

The precompile accepts a 128-byte input, concatenated as follows:

1. `Public Key X-coordinate (32 bytes)`: The 32-byte x-coordinate of the Schnorr public key. The y-coordinate is implicitly assumed to be even as per BIP340.
2. `Message Hash (32 bytes)`: The 32-byte hash of the message that was signed.
3. `Signature (64 bytes)`: The 64-byte Schnorr signature (typically r and s components, each 32 bytes).

If the signature is valid for the given message hash and public key, the precompile returns a 32-byte value `0x00...01`. If verification fails, it returns empty bytes: `0x`.

Base gas cost of Schnorr precompile is set to `4600`.

### Example Smart Contract

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

/// @title Schnorr Precompile Example
/// @notice Calls the Schnorr precompile to verify BIP340 secp256k1 signatures
contract SchnorrVerifyCaller {
    address constant SCHNORR_VERIFY_PRECOMPILE = 0x0000000000000000000000000000000000000200;

    /**
     * @notice Verifies a BIP340 Schnorr signature.
     * @dev All inputs must be big-endian byte sequences.
     * @param pubKeyX 32-byte public key X coordinate (big-endian, Y is implicitly even per BIP340)
     * @param messageHash 32-byte hash of the signed message
     * @param signature 64-byte Schnorr signature (r || s), both 32-byte values concatenated
     * @return isValid True if signature is valid, false otherwise.
     */
    function schnorrVerify(
        bytes32 pubKeyX,
        bytes32 messageHash,
        bytes calldata signature // must be 64 bytes
    ) external view returns (bool isValid) {
        require(signature.length == 64, "Invalid signature length");
        // Concatenate inputs in correct order: pubKeyX | messageHash | signature
        bytes memory input = abi.encodePacked(
            pubKeyX,
            messageHash,
            signature
        );
        (bool ok, bytes memory output) = SCHNORR_VERIFY_PRECOMPILE.staticcall(input);
        // 32-byte return, last byte == 0x01 means success
        return ok && output.length == 32 && output[31] == 0x01;
    }
}
```


# RPC Documentation

This folder contains JSON-RPC methods enabled on a Citrea node.

* [citrea-rpc-documentation.md](https://docs.citrea.xyz/developer-documentation/rpc-documentation/citrea-rpc-documentation) has the Citrea-specific RPC methods (prefixed `citrea_`, `ledger_`, `debug_`, etc.) that extend beyond the standard Ethereum API. These endpoints are particularly useful in the rollup/Bitcoin settlement context, such as sequencer commitments, proofs, and more.
* [eth-rpc-endpoints.md](https://docs.citrea.xyz/developer-documentation/rpc-documentation/eth-rpc-endpoints) has standard Ethereum JSON-RPC methods that are **also** implemented by Citrea for wallet / tool compatibility.


# Citrea JSON-RPC Endpoints

Complete reference for Citrea's special JSON-RPC API endpoints for interacting with the ledger data and debugging, outside of the standard Ethereum JSON-RPC methods.

## Base URLs

* **Local node:** `http://0.0.0.0:8080`
* **Mainnet:** `https://rpc.mainnet.citrea.xyz`
* **Testnet:** `https://rpc.testnet.citrea.xyz`
* [**Alchemy**](https://alchemy.com)**:** [`https://citrea-mainnet.g.alchemy.com/v2/{apiKey}`](https://citrea-mainnet.g.alchemy.com/v2/%7BapiKey%7D)
  * You can also view/test RPC endpoints using [Alchemy's documentation / playground](https://www.alchemy.com/docs/node/citrea/citrea-api-endpoints/citrea-get-l-2-status-heights-by-l-1-height).

***

## Table of Contents

### 1. [Sync & Status Endpoints](#sync--status-endpoints)

* [`citrea_syncStatus`](#citrea_syncstatus)

### 2. [L2 Block Endpoints](#l2-block-endpoints)

* [`ledger_getL2BlockByNumber`](#ledger_getl2blockbynumber)
* [`ledger_getL2BlockByHash`](#ledger_getl2blockbyhash)
* [`ledger_getL2BlockRange`](#ledger_getl2blockrange)
* [`ledger_getHeadL2Block`](#ledger_getheadl2block)
* [`ledger_getHeadL2BlockHeight`](#ledger_getheadl2blockheight)

### 3. [Genesis & State Endpoints](#genesis--state-endpoints)

* [`ledger_getL2GenesisStateRoot`](#ledger_getl2genesisstateroot)

### 4. [Sequencer Commitment Endpoints](#sequencer-commitment-endpoints)

* [`ledger_getSequencerCommitmentsOnSlotByNumber`](#ledger_getsequencercommitmentsonslotbynumber)
* [`ledger_getSequencerCommitmentsOnSlotByHash`](#ledger_getsequencercommitmentsonslotbyhash)
* [`ledger_getSequencerCommitmentByIndex`](#ledger_getsequencercommitmentbyindex)

### 5. [Proof Endpoints](#proof-endpoints)

* [`ledger_getVerifiedBatchProofsBySlotHeight`](#ledger_getverifiedbatchproofsbyslotHeight)
* [`ledger_getLastVerifiedBatchProof`](#ledger_getlastverifiedbatchproof)

### 6. [L1 Integration Endpoints](#l1-integration-endpoints)

* [`ledger_getLastScannedL1Height`](#ledger_getlastscannedl1height)

### 7. [Status Query Endpoints](#status-query-endpoints)

* [`citrea_getLastCommittedL2Height`](#citrea_getlastcommittedl2height)
* [`citrea_getLastProvenL2Height`](#citrea_getlastprovenl2height)
* [`citrea_getL2StatusHeightsByL1Height`](#citrea_getl2statusheightsbyl1height)

### 8. [Deposit Endpoints](#deposit-endpoints)

* [`citrea_sendRawDepositTransaction`](#citrea_sendrawdeposittransaction)

### 9. [Diff Size Estimation Endpoint](#diff-size-estimation-endpoint)

* [`eth_estimateDiffSize`](#eth_estimatediffsize)

***

## Sync & Status Endpoints

### `citrea_syncStatus`

**Description**\
Returns the current synchronization status of the local Citrea node for both L1 (Bitcoin) and L2 (Citrea).

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"citrea_syncStatus","params":[],"id":1}' \
http://0.0.0.0:8080
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "citrea_syncStatus",
  "params": [],
  "id": 1
}
```

#### Parameters

*None*

#### Example Response

**If fully synced:**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "l1Status": { "Synced": 19224 },
    "l2Status": { "Synced": 2326433 }
  }
}
```

**If still syncing:**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "l1Status": { "Synced": 19224 },
    "l2Status": {
      "Syncing": {
        "headBlockNumber": 264052,
        "syncedBlockNumber": 27050
      }
    }
  }
}
```

#### Response Fields

| Field                       | Type     | Description                         |
| --------------------------- | -------- | ----------------------------------- |
| `l1Status`                  | `object` | L1 (Bitcoin) synchronization status |
| `l2Status`                  | `object` | L2 (Citrea) synchronization status  |
| `Synced`                    | `number` | Block height when fully synced      |
| `Syncing.headBlockNumber`   | `number` | Latest known block number           |
| `Syncing.syncedBlockNumber` | `number` | Current synced block number         |

***

## L2 Block Endpoints

### `ledger_getL2BlockByNumber`

**Description**\
Returns a complete L2 block by its block number.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getL2BlockByNumber","params":[1000333],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getL2BlockByNumber",
  "params": [1000333],
  "id": 1
}
```

#### Parameters

| Name     | Type      | Required | Description              |
| -------- | --------- | -------- | ------------------------ |
| `number` | `integer` | **Yes**  | L2 block height to fetch |

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "header": {
      "height": "0xf438d",
      "hash": "999528b4d08dc8d0b05cbace0f5e661f36d824cedde1ffa75dc0c197b355c111",
      "prev_hash": "3dd4a535bc994f8f8d7d1f814be99f73dc522aa314905ca9985e479b350f17e7",
      "state_root": "c55d26ed7c1733d6be6283f68ab87db37271bf476008eba5231f5d321e0efe2c",
      "signature": "69f712ea23731ce8432867526084e260d1aeef9290f4c26889361e3bb5e168724bfe328986a56752778a2a93c360b9c291614ce4e15d4b1c2fac7bf31c7068e9",
      "l1_fee_rate": "0x9502f900",
      "timestamp": "0x67089f9c",
      "tx_merkle_root": "13148bcd464a1ef2824f13372513eda01d2f83d498790bf558060dc0bf4cbcbb"
    },
    "txs": [
      "00400000004f3fe920c0195eab45c67026fde19b23853c34e709c18e625e43702ca325f13f7a924be8beed58eb6afdaa596392fa7b40ccff1ead3a33e4db7617034366c2600201edff3b3ee593dbef54e2fbdd421070db55e2de2aebe75f398bd85ac97ed364ba0000000101000000b100000002f8ae8213fb6e018401312d0183021953945da3155a299558bcaa8da073ad74ed0827fb64a380b844a9059cbb000000000000000000000000ae45cbe2d1e90358cbd216bc16f2c9267a4ea80a00000000000000000000000000000000000000000000003b16c9e8eeb7c80000c080a04d09d171896b18b3651da059780fd92748b9813f1a6a11f26550cd759862fb99a03cb268a677ffdb6eb2e563e5ffda0fb32df547828ecf67affb03c087772daadc00000000000000009994040000000000"
    ]
  }
}
```

#### Response Fields

| Field                   | Type     | Description                             |
| ----------------------- | -------- | --------------------------------------- |
| `header.height`         | `string` | Block height in hex format              |
| `header.hash`           | `string` | 32-byte block hash                      |
| `header.prev_hash`      | `string` | Previous block hash                     |
| `header.state_root`     | `string` | State root after this block             |
| `header.signature`      | `string` | Sequencer signature                     |
| `header.l1_fee_rate`    | `string` | L1 fee rate in hex                      |
| `header.timestamp`      | `string` | Block timestamp in hex                  |
| `header.tx_merkle_root` | `string` | Merkle root of transactions             |
| `txs`                   | `array`  | Array of transaction data (hex-encoded) |

***

### `ledger_getL2BlockByHash`

**Description**\
Returns a complete L2 block by its block hash.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getL2BlockByHash","params":["999528b4d08dc8d0b05cbace0f5e661f36d824cedde1ffa75dc0c197b355c111"],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getL2BlockByHash",
  "params": ["999528b4d08dc8d0b05cbace0f5e661f36d824cedde1ffa75dc0c197b355c111"],
  "id": 1
}
```

#### Parameters

| Name   | Type     | Required | Description                 |
| ------ | -------- | -------- | --------------------------- |
| `hash` | `string` | **Yes**  | 32-byte L2 block hash (hex) |

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    /* Same structure as ledger_getL2BlockByNumber */
  }
}
```

***

### `ledger_getL2BlockRange`

**Description**\
Returns all L2 blocks in the inclusive range `[start, end]`.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getL2BlockRange","params":[1000333,1000335],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getL2BlockRange",
  "params": [1000333, 1000335],
  "id": 1
}
```

#### Parameters

| Name    | Type      | Required | Description                 |
| ------- | --------- | -------- | --------------------------- |
| `start` | `integer` | **Yes**  | First block number in range |
| `end`   | `integer` | **Yes**  | Last block number in range  |

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    { /* Block 1000333 in ledger_getL2BlockByNumber response structure */ },
    { /* Block 1000334 in ledger_getL2BlockByNumber response structure */ },
    { /* Block 1000335 in ledger_getL2BlockByNumber response structure */ }
  ]
}
```

***

### `ledger_getHeadL2Block`

**Description**\
Returns the latest (head) L2 block.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getHeadL2Block","params":[],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getHeadL2Block",
  "params": [],
  "id": 1
}
```

#### Parameters

*None*

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    /* Same structure as ledger_getL2BlockByNumber */
  }
}
```

***

### `ledger_getHeadL2BlockHeight`

**Description**\
Returns the block number of the latest L2 block.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getHeadL2BlockHeight","params":[],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getHeadL2BlockHeight",
  "params": [],
  "id": 1
}
```

#### Parameters

*None*

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xbed0d6"
}
```

#### Response Fields

| Field    | Type     | Description                          |
| -------- | -------- | ------------------------------------ |
| `result` | `string` | Latest L2 block height in hex format |

***

## Genesis & State Endpoints

### `ledger_getL2GenesisStateRoot`

**Description**\
Returns the 32-byte genesis state root for L2.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getL2GenesisStateRoot","params":[],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getL2GenesisStateRoot",
  "params": [],
  "id": 1
}
```

#### Parameters

*None*

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x785c6d461111b5e9fdc515e0955d55baddfd8eb2dd2769342cc58060d6f5e0c5"
}
```

#### Response Fields

| Field    | Type     | Description                      |
| -------- | -------- | -------------------------------- |
| `result` | `string` | 32-byte genesis state root (hex) |

***

## Sequencer Commitment Endpoints

### `ledger_getSequencerCommitmentsOnSlotByNumber`

**Description**\
Returns sequencer commitment(s) found in the specified DA slot height.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getSequencerCommitmentsOnSlotByNumber","params":[88001],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getSequencerCommitmentsOnSlotByNumber",
  "params": [88001],
  "id": 1
}
```

#### Parameters

| Name     | Type      | Required | Description       |
| -------- | --------- | -------- | ----------------- |
| `height` | `integer` | **Yes**  | L1 DA slot height |

#### Example Response

**If commitments exist:**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "merkleRoot": "0xd6dc3eb1a59be7bc1ece68318f82a60919f0f98d8c648337d588ce243a17f473",
      "index": "0xba5",
      "l2EndBlockNumber": "0xb7a20b"
    },
    {
      "merkleRoot": "0xf85a8f3f872fe8079fe778a2f6a8ebd92cf3d1a7c6324af025c8bffbb46d1811",
      "index": "0xba6",
      "l2EndBlockNumber": "0xb7a5f3"
    }
  ]
}
```

**If no commitments:**

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": null
}
```

#### Response Fields

| Field              | Type     | Description                            |
| ------------------ | -------- | -------------------------------------- |
| `merkleRoot`       | `string` | Merkle root of sequencer commitment    |
| `index`            | `string` | Global commitment index (hex)          |
| `l2EndBlockNumber` | `string` | Last L2 block in this commitment (hex) |

***

### `ledger_getSequencerCommitmentsOnSlotByHash`

**Description**\
Returns sequencer commitment(s) found in the DA slot identified by its L1 block hash.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getSequencerCommitmentsOnSlotByHash","params":["788636f732f490c5072582c7dcde85e34d737c8a4d98e792a59c9d0100000000"],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getSequencerCommitmentsOnSlotByHash",
  "params": ["788636f732f490c5072582c7dcde85e34d737c8a4d98e792a59c9d0100000000"],
  "id": 1
}
```

#### Parameters

| Name   | Type     | Required | Description                |
| ------ | -------- | -------- | -------------------------- |
| `hash` | `string` | **Yes**  | 32-byte DA slot hash (hex) |

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "merkleRoot": "0xd6dc3eb1a59be7bc1ece68318f82a60919f0f98d8c648337d588ce243a17f473",
      "index": "0xba5",
      "l2EndBlockNumber": "0xb7a20b"
    }
  ]
}
```

***

### `ledger_getSequencerCommitmentByIndex`

**Description**\
Returns a sequencer commitment by its global index.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getSequencerCommitmentByIndex","params":["0xba5"],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getSequencerCommitmentByIndex",
  "params": ["0xba5"],
  "id": 1
}
```

#### Parameters

| Name    | Type     | Required | Description            |
| ------- | -------- | -------- | ---------------------- |
| `index` | `string` | **Yes**  | Commitment index (hex) |

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "merkleRoot": "0xd6dc3eb1a59be7bc1ece68318f82a60919f0f98d8c648337d588ce243a17f473",
    "index": "0xba5",
    "l2EndBlockNumber": "0xb7a20b"
  }
}
```

***

## Proof Endpoints

### `ledger_getVerifiedBatchProofsBySlotHeight`

**Description**\
Returns verified ZK batch proof(s) for the specified DA slot height.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getVerifiedBatchProofsBySlotHeight","params":[85890],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getVerifiedBatchProofsBySlotHeight",
  "params": [85890],
  "id": 1
}
```

#### Parameters

| Name     | Type      | Required | Description         |
| -------- | --------- | -------- | ------------------- |
| `height` | `integer` | **Yes**  | DA slot height (L1) |

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "proof": "0x0300000000000000000000000000000081670c116a84c0351f18c3...", // ~2MB proof data
      "proofOutput": {
        "stateRoots": [
          "0x5e2a5b8da99b65c5eba4b36f2368321dad95c08c641d698b09ca6756caac589e",
          "0x182a9543bf64a90e78f7d810dedebdf4da3322752db5ee5533fae564e31033f7"
          // ... additional state roots
        ],
        "finalL2BlockHash": "0x8fe769cdb2d34f60b5a625caa8697ae1d1f213b558c9dc9e681059f18732e608",
        "stateDiff": {
          "0x412f612f0201edff3b3ee593dbef54e2fbdd421070db55e2de2aebe75f398bd85ac97ed364": "0xf4fd64e249e658fdb748f83190e47f0b1cd5e87fe30d005c257d7a94cca458e7167e690000000000"
          // ... state differences (truncated for readability)
        },
        "lastL2Height": "0xae0e97",
        "sequencerCommitmentIndexRange": ["0x92c", "0x92e"],
        "sequencerCommitmentHashes": [
          "0x8a9cd0b9fda255370073abff4176416665d14552d5f0d671998ca89523041b36"
          // ... additional hashes
        ],
        "lastL1HashOnBitcoinLightClientContract": "0xa1717b35aa14be01ce037d1a346c4c1714afcfa5e8a66a35af5ead0000000000",
        "previousCommitmentIndex": "0x92b",
        "previousCommitmentHash": "0xa37a45539d40448d22f6da7978ca58f5845b72a5043129941817099471198749"
      }
    }
  ]
}
```

> **Note:** The actual proof data is approximately 2MB. This example shows truncated data for documentation purposes.

#### Response Fields

| Field                                       | Type     | Description                     |
| ------------------------------------------- | -------- | ------------------------------- |
| `proof`                                     | `string` | ZK proof data (hex, \~2MB)      |
| `proofOutput.stateRoots`                    | `array`  | Array of state roots            |
| `proofOutput.finalL2BlockHash`              | `string` | Final L2 block hash in batch    |
| `proofOutput.stateDiff`                     | `object` | State changes (key-value pairs) |
| `proofOutput.lastL2Height`                  | `string` | Last L2 height in proof (hex)   |
| `proofOutput.sequencerCommitmentIndexRange` | `array`  | Range of commitment indices     |
| `proofOutput.sequencerCommitmentHashes`     | `array`  | Commitment hashes in range      |

***

### `ledger_getLastVerifiedBatchProof`

**Description**\
Returns the most recent verified batch proof.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getLastVerifiedBatchProof","params":[],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getLastVerifiedBatchProof",
  "params": [],
  "id": 1
}
```

#### Parameters

*None*

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    /* Same structure as ledger_getVerifiedBatchProofsBySlotHeight */
  }
}
```

***

## L1 Integration Endpoints

### `ledger_getLastScannedL1Height`

**Description**\
Returns the highest L1 block number the node has scanned so far.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"ledger_getLastScannedL1Height","params":[],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "ledger_getLastScannedL1Height",
  "params": [],
  "id": 1
}
```

#### Parameters

*None*

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x15e53"
}
```

#### Response Fields

| Field    | Type     | Description                        |
| -------- | -------- | ---------------------------------- |
| `result` | `string` | Last scanned L1 block height (hex) |

***

## Status Query Endpoints

### `citrea_getLastCommittedL2Height`

**Description**\
Returns the latest L2 block height that has been committed to Bitcoin via sequencer commitment.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"citrea_getLastCommittedL2Height","params":[],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "citrea_getLastCommittedL2Height",
  "params": [],
  "id": 1
}
```

#### Parameters

*None*

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "height": 12489007,
    "commitment_index": 3444
  }
}
```

#### Response Fields

| Field              | Type     | Description                      |
| ------------------ | -------- | -------------------------------- |
| `height`           | `number` | Latest committed L2 block height |
| `commitment_index` | `number` | Sequencer commitment index       |

***

### `citrea_getLastProvenL2Height`

**Description**\
Returns the latest L2 block height that has been proven on Bitcoin with a validity proof.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"citrea_getLastProvenL2Height","params":[],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "citrea_getLastProvenL2Height",
  "params": [],
  "id": 1
}
```

#### Parameters

*None*

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "height": 11457999,
    "commitment_index": 2401
  }
}
```

#### Response Fields

| Field              | Type     | Description                   |
| ------------------ | -------- | ----------------------------- |
| `height`           | `number` | Latest proven L2 block height |
| `commitment_index` | `number` | Sequencer commitment index    |

***

### `citrea_getL2StatusHeightsByL1Height`

**Description**\
Returns committed and proven L2 heights as of a given Bitcoin block.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"citrea_getL2StatusHeightsByL1Height","params":[800000],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "citrea_getL2StatusHeightsByL1Height",
  "params": [800000],
  "id": 1
}
```

#### Parameters

| Name        | Type      | Required | Description                   |
| ----------- | --------- | -------- | ----------------------------- |
| `l1_height` | `integer` | **Yes**  | Bitcoin block height to query |

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "committed": {
      "height": 12489007,
      "commitment_index": 3444
    },
    "proven": {
      "height": 11457999,
      "commitment_index": 2401
    }
  }
}
```

#### Response Fields

| Field       | Type     | Description                |
| ----------- | -------- | -------------------------- |
| `committed` | `object` | Latest committed L2 status |
| `proven`    | `object` | Latest proven L2 status    |

***

## Deposit Endpoints

### `citrea_sendRawDepositTransaction`

**Description**\
Submits a raw deposit transaction to the Citrea sequencer. The node first simulates the deposit; if valid, it is queued for inclusion.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"citrea_sendRawDepositTransaction","params":["0x01020304..."],"id":1}' \
http://0.0.0.0:8080
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "citrea_sendRawDepositTransaction",
  "params": ["0x01020304..."],
  "id": 1
}
```

#### Parameters

| Name      | Type     | Required | Description                          |
| --------- | -------- | -------- | ------------------------------------ |
| `deposit` | `string` | **Yes**  | Raw serialized deposit tx data (hex) |

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": null
}
```

#### Response Fields

| Field    | Type   | Description          |
| -------- | ------ | -------------------- |
| `result` | `null` | Success returns null |

***

### `eth_estimateDiffSize`

**Description**\
Returns estimated diff size and gas consumption for a potential transaction.

#### HTTP Request

```sh
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_estimateDiffSize","params":[{"from":"0x0452663bfc46B86aC93d8220D9847cF5220D7642","to":"0x5fbdb2315678afecb367f032d93f642f64180aa3","value":"10000"}],"id":1}' \
https://rpc.testnet.citrea.xyz
```

#### JSON-RPC Body

```json
{
  "jsonrpc": "2.0",
  "method": "eth_estimateDiffSize",
  "params": [{
    "from": "0x0452663bfc46B86aC93d8220D9847cF5220D7642",
    "to": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
    "value": "10000"
  }],
  "id": 1
}
```

#### Parameters

Same as [`eth_estimateGas`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_estimategas).

#### Example Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "gas": "0x5208",
    "l1DiffSize": "0x11"
  }
}
```

#### Response Fields

| Field        | Type     | Description                     |
| ------------ | -------- | ------------------------------- |
| `gas`        | `string` | Estimated gas consumption (hex) |
| `l1DiffSize` | `string` | Estimated L1 diff size (hex)    |

***

## Error Responses

All endpoints may return standard JSON-RPC error responses:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "Invalid params"
  }
}
```

### Common Error Codes

| Code     | Message          | Description                                  |
| -------- | ---------------- | -------------------------------------------- |
| `-32600` | Invalid Request  | The JSON sent is not a valid Request object  |
| `-32601` | Method not found | The method does not exist / is not available |
| `-32602` | Invalid params   | Invalid method parameter(s)                  |
| `-32603` | Internal error   | Internal JSON-RPC error                      |

***

## Notes

* All hex values should include the `0x` prefix
* Block heights can be specified as integers or hex strings (block tags of Ethereum-spec also work)
* Response data may be truncated in documentation for readability
* Large responses (like proofs) may be several MB in size
* Always check for error responses before processing results


# EVM JSON-RPC Endpoints

Complete reference for Ethereum-compatible JSON-RPC API endpoints supported by Citrea. These endpoints provide compatibility with existing EVM tooling and libraries.

## Base URLs

* **Local node:** `http://0.0.0.0:8080`
* **Mainnet:** `https://rpc.mainnet.citrea.xyz`
* **Testnet:** `https://rpc.testnet.citrea.xyz`
* [**Alchemy**](https://alchemy.com)**:** [`https://citrea-mainnet.g.alchemy.com/v2/{apiKey}`](https://citrea-mainnet.g.alchemy.com/v2/%7BapiKey%7D)
  * You can also view/test RPC endpoints using [Alchemy's documentation / playground](https://www.alchemy.com/docs/node/citrea/citrea-api-endpoints/citrea-get-l-2-status-heights-by-l-1-height).

***

## Supported JSON-RPC Methods

### Web3 Methods

* [**`web3_clientVersion`**](https://ethereum.org/en/developers/docs/apis/json-rpc#web3_clientversion) - Returns the current client version
* [**`web3_sha3`**](https://ethereum.org/en/developers/docs/apis/json-rpc#web3_sha3) - Returns Keccak-256 hash of the given data

### Net Methods

* [**`net_version`**](https://ethereum.org/en/developers/docs/apis/json-rpc#net_version) - Returns the current network ID

### Ethereum Methods

#### Synchronization & Status

* [**`eth_syncing`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_syncing) - Returns sync status object or false if fully synced
* [**`eth_chainId`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_chainid) - Returns the chain ID

#### Gas & Fees

* [**`eth_gasPrice`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_gasprice) - Returns current gas price estimate
* [**`eth_feeHistory`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_feehistory) - Returns historical base fees and reward percentiles (EIP-1559)
* [**`eth_maxPriorityFeePerGas`**](https://docs.blastapi.io/blast-documentation/apis-documentation/core-api/ethereum/eth_maxpriorityfeepergas) - Returns suggested priority fee (tip) per gas
* **`eth_maxFeePerGas`** - Returns estimated maximum fee per gas
  * `curl -H "Content-type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"eth_maxFeePerGas","params":[],"id":1}' https://rpc.testnet.citrea.xyz | jq .`

#### Account & Balance

* [**`eth_blockNumber`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_blocknumber) - Returns the latest block number
* [**`eth_getBalance`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getbalance) - Returns account balance at given address and block
* [**`eth_getStorageAt`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getstorageat) - Returns storage value at address/key for given block
* [**`eth_getTransactionCount`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_gettransactioncount) - Returns nonce for an address
* [**`eth_getCode`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getcode) - Returns contract bytecode at address

#### Block Information

* [**`eth_getBlockTransactionCountByHash`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getblocktransactioncountbyhash) - Returns number of transactions in block by hash
* [**`eth_getBlockTransactionCountByNumber`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getblocktransactioncountbynumber) - Returns number of transactions in block by number
* [**`eth_getBlockByHash`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getblockbyhash) - Returns block by hash
  * *Note*: There is an extra field in the response, `l1FeeRate`.
* [**`eth_getBlockByNumber`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getblockbynumber) - Returns block by number
  * *Note*: There is an extra field in this response, `l1FeeRate`.
* [**`eth_getUncleByBlockHashAndIndex`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getunclebyblockhashAndindex) - Returns null (no uncles in Citrea)

#### Transaction Methods

* [**`eth_sendRawTransaction`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_sendrawtransaction) - Submits a signed transaction
* [**`eth_sendRawTransactionSync`**](https://eips.ethereum.org/EIPS/eip-7966) - Submits a signed transaction and waits for it to be included in a block before returning (EIP-7966)
* [**`eth_getTransactionByHash`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_gettransactionbyhash) - Returns transaction details by hash
* [**`eth_getTransactionByBlockHashAndIndex`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_gettransactionbyblockhashAndindex) - Returns transaction by block hash and index
* [**`eth_getTransactionByBlockNumberAndIndex`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_gettransactionbyblocknumberandindex) - Returns transaction by block number and index
* [**`eth_getTransactionReceipt`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_gettransactionreceipt) - Returns transaction receipt by hash
  * *Note*: There are extra fields in the response, `l1FeeRate` and `l1DiffSize`.

#### Call & Execution

* [**`eth_call`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_call) - Executes a read-only call
* [**`eth_estimateGas`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_estimategas) - Returns gas estimate for a transaction
  * *Note*: eth\_estimateGas carries a tiny overhead for the L1 fee costs. For a more precise estimation that separates L1 and L2 costs, please use [`eth_estimateDiffSize`](https://docs.citrea.xyz/developer-documentation/citrea-rpc-documentation#eth_estimatediffsize) (Citrea-specific).

#### Logs

* [**`eth_getLogs`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getlogs) - Returns logs matching filter criteria

#### Filters

* [**`eth_newFilter`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_newfilter) - Creates a log filter and returns its ID
* [**`eth_newBlockFilter`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_newblockfilter) - Creates a filter for new blocks and returns its ID
* [**`eth_uninstallFilter`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_uninstallfilter) - Uninstalls a filter by ID
* [**`eth_getFilterChanges`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getfilterchanges) - Returns changes since the last poll for a filter
* [**`eth_getFilterLogs`**](https://ethereum.org/en/developers/docs/apis/json-rpc#eth_getfilterlogs) - Returns all logs matching a given filter ID

### State Proofs & Access Lists

* [**`eth_getProof`**](https://docs.blastapi.io/blast-documentation/apis-documentation/core-api/ethereum/eth_getproof) - Returns account and storage proof (EIP-1186)
* [**`eth_createAccessList`**](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-eth#eth-createaccesslist) - Generates access list for transaction (EIP-2930)

### Bulk Operations

* [**`eth_getBlockReceipts`**](https://docs.blastapi.io/blast-documentation/erigon-api/eth_getblockreceipts) - Returns all transaction receipts for a block
  * *Note*: There are extra fields in some objects of the response, such as `l1FeeRate` and `l1DiffSize`.

### Citrea-Specific Extensions

* [**`eth_estimateDiffSize`**](https://docs.citrea.xyz/developer-documentation/citrea-rpc-documentation#eth_estimatediffsize) - Estimates L1 data diff size for rollup transaction

### Debug Endpoints

* [**`debug_traceTransaction`**](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debug-tracetransaction) - Traces execution of a transaction (requires full node)
* [**`debug_traceBlockByHash`**](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debug-traceblockbyhash) - Traces all transactions in a block by hash
* [**`debug_traceBlockByNumber`**](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debug-traceblockbynumber) - Traces all transactions in a block by number
* [**`debug_traceCall`**](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debug-tracecall) - Traces execution of a read-only call without creating a transaction

### Subscription Methods (WebSocket only)

* [**`eth_subscribe`**](https://docs.blastapi.io/blast-documentation/apis-documentation/core-api/ethereum/eth_subscribe) - Creates subscription for events
* [**`eth_unsubscribe`**](https://docs.blastapi.io/blast-documentation/apis-documentation/core-api/ethereum/eth_unsubscribe) - Cancels active subscription
* [**`debug_subscribe`**](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug) - Creates a subscription for debug-namespace events

***

## Notes

* Almost all methods follow the standard Ethereum JSON-RPC specification formats (see notes above)
* You can use WebSocket connections for subscription methods (`eth_subscribe`/`eth_unsubscribe`) on your full node
* Please visit [Citrea-Specific RPC Documentation](https://docs.citrea.xyz/developer-documentation/rpc-documentation/citrea-rpc-documentation) for Citrea-specific endpoints


# Bitcoin Appchains (L3)

Citrea lets you deploy **Bitcoin Appchains (L3s)**: application-specific OP Stack chains that **settle to Citrea**, while using a modular **Data Availability (DA)** layer like **Celestia** or **Avail**.

From an architecture point of view:

* **Bitcoin** is the base layer.
* **Citrea (L2)** is a rollup on Bitcoin (zkEVM).
* **Your Appchain (L3)** is an OP Stack chain that treats **Citrea as its settlement layer**, and uses **Celestia/Avail for DA**.

***

### Why an L3 ₿appchain?

An L3 is useful when you want **dedicated blockspace** and **predictable execution** for a single application (or app ecosystem), without competing for fees with everything else.

Some easy benefits from an infra perspective are as follows:

* **Dedicated blockspace**: your app’s throughput/fees are isolated from other apps.
* **Custom chain parameters**: block time, gas limits, sequencing policy, etc.
* **Lower DA costs**: batch data goes to a DA network (Avail/Celestia) instead of being fully posted on the settlement layer.
* **EVM + Ethereum tooling**: standard JSON-RPC, op-geth/op-node, Foundry, etc.

{% hint style="info" %}
Note: Citrea does not support EIP-4844 blobs at the moment. Therefore using an external DA layer keeps data costs and throughput more flexible.
{% endhint %}

***

### How an L3 works on Citrea

At a high level, an OP Stack L3 has the usual OP Stack components — except it settles to **Citrea**, and uses **Alt-DA mode** for data availability.

```
Users
  |
  | (JSON-RPC)
  v
L3 execution (op-geth)  <----- engine API ----->  L3 rollup node (op-node)
  |                                               |
  | produces blocks                               | derives chain by reading:
  v                                               |  - Citrea commitments
op-batcher                                        |  - DA data (Celestia/Avail)
  |
  | uploads batch data
  v
DA Server  --->  DA Layer (Celestia or Avail)
  |
  | submits DA commitment tx to Citrea
  v
Citrea (settlement + OP Stack contracts for the L3)
  ^
  | proposes outputs
  v
op-proposer
```

#### What each component does

* `op-geth`: Executes L3 transactions and serves the L3 JSON-RPC.
* `op-node`: Derives the canonical L3 chain by combining:
  * commitments on **Citrea**, and
  * batch data retrieved from the **DA layer**.
* `op-batcher`: Compresses L3 blocks into batches and publishes them.
* `DA Server (sidecar)`: The adapter between OP Stack and the DA network.
* `op-proposer`: Submits L3 output roots to Citrea (settlement/bridging logic).

***

### Data Availability via OP Stack Alt-DA mode

These ₿appchains use **Alt-DA mode** in the OP Stack:

1. The batcher **uploads** compressed batch data to the DA layer (via the DA Server).
2. The batcher **posts a commitment** on Citrea that points to that data.
3. Any node can follow Citrea, then use the DA Server to fetch the underlying batch data and fully derive the L3 chain.

{% hint style="info" %}
Note: Alt-DA mode is a beta OP Stack feature. The “generic commitment / DA-server” flow adds additional trust assumptions compared to posting all batch data directly on the settlement layer.
{% endhint %}

Both Celestia and Avail are DA networks designed to keep large volumes of transaction data available at lower cost than typical settlement layers.

#### Avail DA

* You run an **Avail DA Server** sidecar and publish data under an **AppID**.
* Avail’s model includes **light clients performing DAS**, with availability verification built around commitments/proofs (e.g., KZG-based designs).

#### Celestia DA

* You run a **Celestia Light Node** and a **Celestia DA Server** sidecar.
* Celestia is built around **Data Availability Sampling (DAS)** and **Namespaced Merkle Trees (NMTs)**.

***

### Transaction lifecycle (end-to-end)

1. A user sends a transaction to your **L3 RPC**.
2. The **sequencer** orders transactions and executes them in **op-geth**.
3. **op-batcher** collects L3 blocks and compresses them into batches.
4. Batch data is posted to **Celestia/Avail** via the **DA Server**.
5. A **DA commitment** is submitted to **Citrea**.
6. **op-node** derives the L3 state by reading Citrea + pulling batch data from the DA layer.
7. **op-proposer** periodically posts output roots to Citrea.

***

### Security model and tradeoffs

An L3 ₿appchain inherits different guarantees from different layers:

* **Settlement**: anchored to **Citrea** (and Citrea anchors to Bitcoin).
* **Execution correctness**: enforced by OP Stack rules and the L3 derivation pipeline.
* **Data availability**: depends on the selected DA layer **and** the Alt-DA publication/retrieval path.

If you are deploying an L3 beyond experimentation, you should add operational monitoring for:

* batch publication to DA,
* DA retrieval health,
* consistency between Citrea commitments and DA data.

***

For the remainder of this section we provide example deployments of ₿appchains.

If you want to learn more or build one from a business perspective, feel free to reach us at [https://origins.citrea.xyz](https://origins.citrea.xyz/).


# Deploy an L3 using Avail

In this guide, we will walk through the process of deploying a Bitcoin Appchain (L3) on Citrea Testnet using the OP Stack, with [Avail](https://availproject.org/) as the data availability layer.

The following steps are appropriately modified from the [Optimism documentation](https://docs.optimism.io/operators/chain-operators/tutorials/create-l2-rollup#deploy-the-l1-contracts).

#### Prerequisites

* [Avail Network Info](https://docs.availproject.org/da/networks) (RPC Endpoints)
* [How to get Avail AppID](https://docs.availproject.org/da/build-with-avail/interact-with-avail-da/app-id)
* [How to get Avail Seed (Avail Account)](https://docs.availproject.org/user-guides/accounts#creating-an-account-on-avail-da)
* [Docker](https://docs.docker.com/engine/install/) (for running the Avail DA Server with docker-compose)
* [Foundry](https://getfoundry.sh/) for contract deployment
* [Git](https://git-scm.com/)
* [Go](https://go.dev/)

We recommend opening a separate folder in your filesystem for the rest of this guide.

{% hint style="success" %}
Appchains require strong hardware to function properly. For demo purposes, we used a machine with **AMD EPYC 9124 @ 3.71GHz** and **128 GB of RAM**.
{% endhint %}

#### Step 1: Set up Avail DA prerequisites

**Step 1.1 Create an Avail account (seed)**

To submit data to Avail DA, you will need an Avail account (seed phrase). Follow the steps [here](https://docs.availproject.org/user-guides/accounts#creating-an-account-on-avail-da).

**Step 1.2 Get funds to your address**

To write data into Avail DA, your Avail account must be funded with AVAIL tokens. Follow the steps [here](https://docs.availproject.org/da/build-with-avail/interact-with-avail-da/faucet).

**Step 1.3 Create an AppID**

Create an AppID on Avail DA and save the AppID value. Follow the steps [here](https://docs.availproject.org/da/build-with-avail/interact-with-avail-da/app-id).

#### Step 2: DA Server Setup

This introduces a sidecar DA Server for Optimism that interacts with Avail DA for posting and retrieving data.

**Step 2.1 Build Avail DA Server**

Let's clone the `avail-alt-da-server` repository first and build the `avail-da-server` binary:

```bash
git clone https://github.com/availproject/avail-alt-da-server.git
cd avail-alt-da-server

make da-server
```

This will create the `avail-da-server` binary in the `bin` folder.

**Step 2.2 Run `avail-da-server` binary (Option 1)**

Run your DA sidecar (use an Avail RPC endpoint from the Network Info page):

```bash
./bin/avail-da-server \
  --addr=localhost \
  --port=8000 \
  --avail.rpc=https://turing-rpc.avail.so/rpc \
  --avail.seed="<YOUR_AVAIL_SEED_PHRASE>" \
  --avail.appid=<YOUR_AVAIL_APP_ID>
```

**Step 2.3 Run using `docker` (Option 2)**

* Copy `.env.example` to `.env`. Fill the values inside.
* Run the following commands:

```bash
docker-compose build
docker-compose up
```

#### Step 3: Setup Optimism repositories and configure environment

**Step 3.1: Clone repositories**

Clone `op-geth` and Optimism mono-repository, then checkout to `v1.9.2` for development purposes:

```bash
git clone https://github.com/ethereum-optimism/op-geth.git

git clone https://github.com/ethereum-optimism/optimism.git
cd optimism
git checkout v1.9.2
```

**Step 3.2: Setup environment**

Then, let's setup our environment using the `.envrc` file (alternatively you can set them in your shell):

```bash
##################################################
#                 Getting Started                #
##################################################
# Admin account
export GS_ADMIN_ADDRESS=[YOUR_CITREA_ADDRESS]
export GS_ADMIN_PRIVATE_KEY=[YOUR_CITREA_PRIVATE_KEY]

# Batcher account
export GS_BATCHER_ADDRESS=[YOUR_CITREA_ADDRESS]
export GS_BATCHER_PRIVATE_KEY=[YOUR_CITREA_PRIVATE_KEY]

# Proposer account
export GS_PROPOSER_ADDRESS=[YOUR_CITREA_ADDRESS]
export GS_PROPOSER_PRIVATE_KEY=[YOUR_CITREA_PRIVATE_KEY]

# Sequencer account
export GS_SEQUENCER_ADDRESS=[YOUR_CITREA_ADDRESS]
export GS_SEQUENCER_PRIVATE_KEY=[YOUR_CITREA_PRIVATE_KEY]
##################################################
#              op-node Configuration             #
##################################################

# The kind of RPC provider, used to inform optimal transaction receipts
# fetching. Valid options: alchemy, quicknode, infura, parity, nethermind,
# debug_geth, erigon, basic, any.
export L1_RPC_KIND=basic

##################################################
#               Contract Deployment              #
##################################################

# RPC URL for the L1 network to interact with
export L1_RPC_URL=https://rpc.testnet.citrea.xyz

# Salt used via CREATE2 to determine implementation addresses
# NOTE: If you want to deploy contracts from scratch you MUST reload this
#       variable to ensure the salt is regenerated and the contracts are
#       deployed to new addresses (otherwise deployment will fail)
export IMPL_SALT=$(openssl rand -hex 32)

# Name for the deployed network
export DEPLOYMENT_CONTEXT=getting-started

# Optional Tenderly details for simulation link during deployment
export TENDERLY_PROJECT=
export TENDERLY_USERNAME=

# Optional Etherscan API key for contract verification
export ETHERSCAN_API_KEY=

# Private key to use for contract deployments, you don't need to worry about
# this for the Getting Started guide.
export PRIVATE_KEY=
export L1_CHAIN_ID=5115
export L2_CHAIN_ID=511551155115
export L1_BLOCK_TIME=2
export L2_BLOCK_TIME=2
```

If you're using `direnv`, run:

```bash
direnv allow .
```

**Step 3.3: Run configuration scripts**

Navigate to the `optimism` directory and generate the configuration:

```bash
# ~/optimism
cd packages/contracts-bedrock
./scripts/getting-started/config.sh
```

Later in the same folder, let's run the deployment script using `forge` to deploy the necessary contracts on Citrea Testnet:

```bash
forge install

DEPLOY_CONFIG_PATH=./deploy-config/getting-started.json \
  forge script scripts/deploy/Deploy.s.sol:Deploy \
  --private-key $GS_ADMIN_PRIVATE_KEY \
  --broadcast \
  --rpc-url $L1_RPC_URL
```

And also run the L3 genesis configuration script:

```bash
DEPLOY_CONFIG_PATH=./deploy-config/getting-started.json \
CONTRACT_ADDRESSES_PATH=./deployments/5115-deploy.json \
  forge script scripts/L2Genesis.s.sol:L2Genesis \
  --sig "runWithStateDump()"
```

#### Step 4: Generate node configurations

Navigate to the `op-node` and generate the configuration for the L3 node:

{% hint style="info" %}
Note: Make sure your `state-dump` file matches your chain ID. It should be in the format `../packages/contracts-bedrock/state-dump-<L2_CHAIN_ID>-fjord.json`.
{% endhint %}

```bash
cd ../../op-node

go run cmd/main.go genesis l2 \
  --deploy-config ../packages/contracts-bedrock/deploy-config/getting-started.json \
  --l1-deployments ../packages/contracts-bedrock/deployments/5115-deploy.json \
  --outfile.l2 genesis.json \
  --l2-allocs ../packages/contracts-bedrock/state-dump-511551155115-fjord.json \
  --outfile.rollup rollup.json \
  --l1-rpc $L1_RPC_URL

openssl rand -hex 32 > jwt.txt

# If you cloned `op-geth` next to `optimism`, this path should work:
cp genesis.json ../../op-geth
cp jwt.txt ../../op-geth
```

#### Step 5: Initialize and start op-geth

Navigate to the `op-geth` directory and initialize the genesis configuration:

```bash
cd ../../op-geth

mkdir datadir
make geth
build/bin/geth init --state.scheme=hash --datadir=datadir genesis.json
```

Then, start the `op-geth`:

```bash
./build/bin/geth \
  --datadir ./datadir \
  --http \
  --http.corsdomain="*" \
  --http.vhosts="*" \
  --http.addr=0.0.0.0 \
  --http.api=web3,debug,eth,txpool,net,engine \
  --ws \
  --ws.addr=0.0.0.0 \
  --ws.port=8546 \
  --ws.origins="*" \
  --ws.api=debug,eth,txpool,net,engine \
  --syncmode=full \
  --gcmode=archive \
  --nodiscover \
  --maxpeers=0 \
  --networkid=511551155115 \
  --authrpc.vhosts="*" \
  --authrpc.addr=0.0.0.0 \
  --authrpc.port=8551 \
  --authrpc.jwtsecret=./jwt.txt \
  --rollup.disabletxpoolgossip=true
```

#### Step 6: Add DA-config to op-node

Navigate to `op-node` folder and add the following to the `rollup.json`:

```bash
cd ../optimism/op-node
nano rollup.json
```

Add:

```json
"alt_da": {
  "da_commitment_type": "GenericCommitment",
  "da_challenge_contract_address": "0x0000000000000000000000000000000000000000",
  "da_challenge_window": 160,
  "da_resolve_window": 160
}
```

{% hint style="info" %}
Note: at the top of `rollup.json` the L1 blockhash may be incorrect with respect to L1 block number. Be sure to check and replace the hash. This is a bug in OP Stack repo.
{% endhint %}

Go to <https://explorer.testnet.citrea.xyz/> to check for the correct hash.

```json
{
  "genesis": {
    "l1": {
      "hash": "", // check and replace this hash in rollup.json
      "number": 15360561
    },
    "l2": {
      "hash": "0x550d7172f4bb962f75aa50a2c5176cfc5234166a08416169f356512293d05a37",
      "number": 0
    }
  }
}
```

#### Step 7: Run op-node

Go back to the main `optimism` directory, and build `op-node`:

```bash
cd ..
make op-node
```

Then let's run the node:

```bash
cd op-node

./bin/op-node \
  --l2=http://localhost:8551 \
  --l2.jwt-secret=./jwt.txt \
  --sequencer.enabled \
  --sequencer.l1-confs=5 \
  --verifier.l1-confs=4 \
  --rollup.config=./rollup.json \
  --rpc.addr=0.0.0.0 \
  --p2p.disable \
  --rpc.enable-admin \
  --p2p.sequencer.key=$GS_SEQUENCER_PRIVATE_KEY \
  --l1=$L1_RPC_URL \
  --l1.rpckind=$L1_RPC_KIND \
  --altda.enabled=true \
  --altda.da-service=true \
  --altda.da-server=http://localhost:8000 \
  --l1.beacon=$L1_RPC_URL \
  --l1.beacon.ignore=true \
  --l1.trustrpc=true \
  --l1.http-poll-interval=2s
```

#### Step 8: Run op-batcher

Go back to the main `optimism` directory, and build the `op-batcher`:

```bash
cd ..
make op-batcher
```

Then let's run the batcher:

```bash
cd op-batcher

./bin/op-batcher \
  --l2-eth-rpc=http://localhost:8545 \
  --rollup-rpc=http://localhost:9545 \
  --poll-interval=1s \
  --sub-safety-margin=6 \
  --num-confirmations=1 \
  --safe-abort-nonce-too-low-count=3 \
  --resubmission-timeout=30s \
  --rpc.addr=0.0.0.0 \
  --rpc.port=8548 \
  --rpc.enable-admin \
  --max-channel-duration=25 \
  --l1-eth-rpc=$L1_RPC_URL \
  --private-key=$GS_BATCHER_PRIVATE_KEY \
  --altda.enabled=true \
  --altda.da-service=true \
  --altda.da-server=http://localhost:8000
```

#### Step 9: Run op-proposer

Go back to optimism main folder, and build the op-proposer:

```bash
cd ..
make op-proposer
```

Then let's run the proposer:

```bash
cd op-proposer

./bin/op-proposer \
  --poll-interval=2s \
  --rpc.port=8560 \
  --rollup-rpc=http://localhost:9545 \
  --l2oo-address=$(cat ../packages/contracts-bedrock/deployments/5115-deploy.json | jq -r .L2OutputOracleProxy) \
  --private-key=$GS_PROPOSER_PRIVATE_KEY \
  --l1-eth-rpc=$L1_RPC_URL
```

***

That’s it! Enjoy your Bitcoin Appchain on Citrea Testnet!


# Deploy an L3 using Celestia

In this guide, we will walk through the process of deploying a Bitcoin Appchain (L3) on Citrea Testnet using the OP Stack, with [Celestia](https://celestia.org/) as the data availability layer.

The following steps are appropriately modified from the [Optimism documentation](https://docs.optimism.io/operators/chain-operators/tutorials/create-l2-rollup#deploy-the-l1-contracts).

### Prerequisites

* [Docker](https://docs.docker.com/engine/install/) for Celestia Light Node
* [Foundry](https://getfoundry.sh/) for contract deployment
* [Git](https://git-scm.com/)
* [Go](https://go.dev)

We recommend opening a separate folder in your filesystem for the rest of this guide.

{% hint style="success" %}
Appchains require strong hardware to function properly. For demo purposes, we used a machine with **AMD EPYC 9124 @ 3.71GHz** and **128 GB of RAM**.
{% endhint %}

### Step 1: Install & Run Celestia Light Node

#### Step 1.1 Install Celestia Light Node

Follow the steps [here](https://docs.celestia.org/how-to-guides/celestia-node) to install Celestia Light Node. You may install the latest version.

#### Step 1.2 Run Celestia Light Node

Run the following to start a Celestia Mocha Light Node:

```bash
celestia light init --p2p.network mocha
celestia light start --core.ip rpc-mocha.pops.one --p2p.network mocha
```

#### Step 1.3 Get funds to your address

To write data into Celestia, you will need an address & funds. Please follow the steps [here](https://docs.celestia.org/tutorials/celestia-node-key#steps-for-generating-node-keys).

### Step 2: DA Server Setup

#### Step 2.1 Build DA Server

Let's clone the `op-plasma-celestia` repository first and build the `da-server`:

```bash
git clone https://github.com/celestiaorg/op-plasma-celestia
cd op-plasma-celestia

make da-server
```

This will create the `da-server` binary in the `bin` folder.

{% hint style="info" %}
If you encounter this [issue](https://github.com/fjl/memsize/issues/4) while building `da-server`, you can continue by reinstalling `go` with version 1.22.0 or lower.
{% endhint %}

#### Step 2.2 Run DA Server

Then, let's create a namespace:

```bash
export NAMESPACE=00000000000000000000000000000000000000$(openssl rand -hex 10)
```

Lastly, let's get the Celestia auth token for the light node and put it into `AUTH_TOKEN` env variable to start the DA server:

```bash
export AUTH_TOKEN=$(celestia light auth admin --p2p.network mocha)

./da-server --generic-commitment=true --celestia.server=http://localhost:26658 --celestia.auth-token=$AUTH_TOKEN --celestia.namespace=$NAMESPACE --addr=127.0.0.1 --port=3100
```

This will start the DA server.

### Step 3: Setup Optimism repositories and configure environment

#### Step 3.1: Clone repositories

Clone `op-geth` and Optimism mono-repository, then check out to `v1.9.2` for development purposes:

```bash
git clone https://github.com/ethereum-optimism/op-geth.git

git clone https://github.com/ethereum-optimism/optimism.git
cd optimism
git checkout v1.9.2
```

#### Step 3.2: Setup environment

Then, let's setup our environment using the `.envrc` file (alternatively you can set them in your shell):

```bash
##################################################
#                 Getting Started                #
##################################################
# Admin account
export GS_ADMIN_ADDRESS=[YOUR_CITREA_ADDRESS]
export GS_ADMIN_PRIVATE_KEY=[YOUR_CITREA_PRIVATE_KEY]

# Batcher account
export GS_BATCHER_ADDRESS=[YOUR_CITREA_ADDRESS]
export GS_BATCHER_PRIVATE_KEY=[YOUR_CITREA_PRIVATE_KEY]

# Proposer account
export GS_PROPOSER_ADDRESS=[YOUR_CITREA_ADDRESS]
export GS_PROPOSER_PRIVATE_KEY=[YOUR_CITREA_PRIVATE_KEY]

# Sequencer account
export GS_SEQUENCER_ADDRESS=[YOUR_CITREA_ADDRESS]
export GS_SEQUENCER_PRIVATE_KEY=[YOUR_CITREA_PRIVATE_KEY]
##################################################
#              op-node Configuration             #
##################################################

# The kind of RPC provider, used to inform optimal transaction receipts
# fetching. Valid options: alchemy, quicknode, infura, parity, nethermind,
# debug_geth, erigon, basic, any.
export L1_RPC_KIND=any

##################################################
#               Contract Deployment              #
##################################################

# RPC URL for the L1 network to interact with
export L1_RPC_URL=https://rpc.testnet.citrea.xyz

# Salt used via CREATE2 to determine implementation addresses
# NOTE: If you want to deploy contracts from scratch you MUST reload this
#       variable to ensure the salt is regenerated and the contracts are
#       deployed to new addresses (otherwise deployment will fail)
export IMPL_SALT=$(openssl rand -hex 32)

# Name for the deployed network
export DEPLOYMENT_CONTEXT=getting-started

# Optional Tenderly details for simulation link during deployment
export TENDERLY_PROJECT=
export TENDERLY_USERNAME=

# Optional Etherscan API key for contract verification
export ETHERSCAN_API_KEY=

# Private key to use for contract deployments, you don't need to worry about
# this for the Getting Started guide.
export PRIVATE_KEY=
export L1_CHAIN_ID=5115
export L2_CHAIN_ID=511551155115
export L1_BLOCK_TIME=2
export L2_BLOCK_TIME=2
```

#### Step 3.3: Run configuration scripts

Navigate to the `op-node` directory and generate the configuration:

```bash
cd packages/contracts-bedrock
./scripts/getting-started/config.sh
```

Later in the same folder, let's run the deployment script using `forge` to deploy the necessary contracts on Citrea Testnet:

```bash
forge install

DEPLOY_CONFIG_PATH=./deploy-config/getting-started.json forge script scripts/deploy/Deploy.s.sol:Deploy --private-key $GS_ADMIN_PRIVATE_KEY --broadcast --rpc-url $L1_RPC_URL
```

And also run the L3 genesis configuration script:

```bash
DEPLOY_CONFIG_PATH=./deploy-config/getting-started.json CONTRACT_ADDRESSES_PATH=./deployments/5115-deploy.json forge script scripts/L2Genesis.s.sol:L2Genesis --sig "runWithStateDump()"
```

### Step 4: Generate node configurations

Navigate to the `op-node` directory and generate the configuration for the L3 node:

```bash
cd ../../op-node

go run cmd/main.go genesis l2   --deploy-config ../packages/contracts-bedrock/deploy-config/getting-started.json   --l1-deployments ../packages/contracts-bedrock/deployments/5115-deploy.json   --outfile.l2 genesis.json --l2-allocs ../packages/contracts-bedrock/state-dump-511551155115-fjord.json --outfile.rollup rollup.json   --l1-rpc $L1_RPC_URL

openssl rand -hex 32 > jwt.txt
cp genesis.json ../op-geth
cp jwt.txt ../op-geth
```

### Step 5: Initialize and start op-geth

Navigate to the `op-geth` directory and initialize the genesis configuration:

```bash
cd ../../op-geth

mkdir datadir
make geth
build/bin/geth init --state.scheme=hash --datadir=datadir genesis.json
```

Then, start the `op-geth`:

```bash
./build/bin/geth   --datadir ./datadir   --http   --http.corsdomain="*"   --http.vhosts="*"   --http.addr=0.0.0.0   --http.api=web3,debug,eth,txpool,net,engine   --ws   --ws.addr=0.0.0.0   --ws.port=8546   --ws.origins="*"   --ws.api=debug,eth,txpool,net,engine   --syncmode=full   --gcmode=archive   --nodiscover   --maxpeers=0   --networkid=511551155115   --authrpc.vhosts="*"   --authrpc.addr=0.0.0.0   --authrpc.port=8551   --authrpc.jwtsecret=./jwt.txt   --rollup.disabletxpoolgossip=true
```

### Step 6: Add DA-config to op-node

Navigate to `op-node` folder and add the following to the `rollup.json`:

```bash
cd ../optimism/op-node
```

```json
"alt_da": {
    "da_commitment_type": "GenericCommitment",
    "da_challenge_contract_address": "0x0000000000000000000000000000000000000000",
    "da_challenge_window": 1000,
    "da_resolve_window": 2000
}
```

### Step 7: Run op-node

Go back to the main `optimism` directory, and build `op-node`:

```bash
cd ..
make op-node
```

Then let's run the node:

```bash
cd op-node

./bin/op-node   --l2=http://localhost:8551   --l2.jwt-secret=./jwt.txt   --sequencer.enabled   --sequencer.l1-confs=5   --verifier.l1-confs=4   --rollup.config=./rollup.json   --rpc.addr=0.0.0.0   --p2p.disable   --rpc.enable-admin   --p2p.sequencer.key=$GS_SEQUENCER_PRIVATE_KEY   --l1=$L1_RPC_URL   --l1.rpckind=$L1_RPC_KIND --altda.enabled=true --altda.da-service=true --l1.beacon=$L1_RPC_URL --l1.beacon.ignore=true --altda.da-server=http://localhost:3100 --l1.trustrpc=true --l1.http-poll-interval=2s
```

### Step 8: Run op-batcher

Go back to the main `optimism` directory, and build the `op-batcher`:

```bash
cd ..
make op-batcher
```

Then let's run the batcher:

```bash
cd op-batcher 

./bin/op-batcher   --l2-eth-rpc=http://localhost:8545   --rollup-rpc=http://localhost:9545   --poll-interval=1s   --sub-safety-margin=6   --num-confirmations=1   --safe-abort-nonce-too-low-count=3   --resubmission-timeout=30s   --rpc.addr=0.0.0.0   --rpc.port=8548   --rpc.enable-admin   --max-channel-duration=25   --l1-eth-rpc=$L1_RPC_URL   --private-key=$GS_BATCHER_PRIVATE_KEY --altda.enabled=true --altda.da-service=true --altda.da-server=http://localhost:3100
```

### Step 9: Run op-proposer

Go back to optimism main folder, and build the op-proposer:

```bash
cd ..
make op-proposer
```

Then let's run the proposer:

```bash
cd op-proposer

./bin/op-proposer   --poll-interval=2s   --rpc.port=8560   --rollup-rpc=http://localhost:9545   --l2oo-address=$(cat ../packages/contracts-bedrock/deployments/5115-deploy.json | jq -r .L2OutputOracleProxy) --private-key=$GS_PROPOSER_PRIVATE_KEY   --l1-eth-rpc=$L1_RPC_URL
```

***

That’s it! Enjoy your Bitcoin Appchain on Citrea Testnet!


# Fee Model

Citrea implements a hybrid fee model that combines Ethereum's EIP-1559 mechanism with a novel L1 data availability fee. This dual approach ensures users pay for both L2 execution and the cost of posting state changes to Bitcoin.

## Fee Components

Every transaction on Citrea incurs three types of fees:

| Component        | Description                              | Destination                                                              |
| ---------------- | ---------------------------------------- | ------------------------------------------------------------------------ |
| **Base Fee**     | EIP-1559 base fee for L2 execution       | [BaseFeeVault](/developer-documentation/system-contracts/fee-vaults)     |
| **Priority Fee** | Optional tip to incentivize inclusion    | [PriorityFeeVault](/developer-documentation/system-contracts/fee-vaults) |
| **L1 Fee**       | Data availability cost for state changes | [L1FeeVault](/developer-documentation/system-contracts/fee-vaults)       |

The total transaction cost is:

```
Total Fee = (base_fee_per_gas + priority_fee_per_gas) × gas_used + L1_fee
```

## Base Fee (EIP-1559)

Citrea uses Ethereum's EIP-1559 fee mechanism with the following parameters:

| Parameter                   | Value                      |
| --------------------------- | -------------------------- |
| Block gas limit             | 10,000,000                 |
| Minimum base fee            | 0.001 gwei (1,000,000 wei) |
| Elasticity multiplier       | 2                          |
| Base fee change denominator | 8                          |

The base fee adjusts dynamically based on network congestion. When blocks are more than 50% full, the base fee increases; when blocks are less than 50% full, it decreases. This mechanism helps maintain predictable transaction inclusion while preventing spam.

{% hint style="info" %}
The minimum base fee ensures a floor price for transactions even during periods of low network activity. This prevents potential spam attacks that could occur with near-zero fees.
{% endhint %}

## L1 Data Availability Fee

The L1 fee is Citrea's unique mechanism for charging users for the Bitcoin data availability cost. When you execute a transaction, any state changes (storage modifications, balance updates, contract deployments) must eventually be posted to Bitcoin as part of a [batch proof](/essentials/architecture-and-transaction-lifecycle#5-batch-proof-generation-submission).

### How L1 Fee is Calculated

```
L1_fee = l1_fee_rate × diff_size
```

Where:

* **l1\_fee\_rate**: Current cost in wei per byte, derived from Bitcoin fee rates
* **diff\_size**: `(uncompressed_diff × 0.48) + 2` — the compressed state diff size plus 2 bytes overhead that are always posted even when no transactions take place

### State Diff Size Calculation

The state diff represents all changes your transaction makes to the blockchain state. Citrea calculates this based on the [`calc_diff_size` function](https://github.com/chainwayxyz/citrea/blob/main/crates/evm/src/evm/handler.rs#L430) and works as follows:

| Change Type             | Raw Size                     | Charged % |
| ----------------------- | ---------------------------- | --------- |
| Account info (EOA)      | 53 bytes (41 value + 12 key) | 32%       |
| Account info (Contract) | 85 bytes (73 value + 12 key) | 32%       |
| Storage slot change     | 68 bytes (36 key + 32 value) | 66%       |
| New account index       | 32 bytes (24 key + 8 value)  | 100%      |

The "Charged %" column indicates what fraction of the raw size users pay. For example, account changes are charged at 32% of their raw size, meaning users effectively receive a 68% discount.

**Why discounts exist:** When multiple transactions in the same batch modify identical accounts or storage slots, their state diffs merge during batch proof creation. Historical data from Ethereum shows that approximately 68% of account changes and 34% of storage changes merge with other transactions. The charged percentages reflect these merging ratios, ensuring users collectively pay fair prices without overcharging individuals.

The final uncompressed diff size is calculated as:

```
uncompressed_diff = (account_bytes × 0.32) + (storage_bytes × 0.66) + new_account_index_bytes
```

Where `account_bytes` is the sum of raw byte sizes for all changed accounts, `storage_bytes` is the sum for all changed storage slots, and `new_account_index_bytes` covers first-time account indexing.

{% hint style="info" %}
A 48% Brotli compression ratio is then applied to all state diff calculations, reflecting the average compression achieved when posting data to Bitcoin. The final compressed size adds a 2-byte overhead per transaction.
{% endhint %}

### Example: Simple cBTC Transfer

A simple cBTC transfer between two existing EOAs modifies two accounts (sender and receiver):

* Both accounts: (53 + 53) bytes × 32% = 33 bytes
* After 48% compression: 33 × 0.48 ≈ 15 bytes
* Plus overhead: 15 + 2 = **17 bytes**

If the recipient is a **new address** (first time receiving), add a 32-byte account index:

* Account changes: 33 bytes (after discount)
* New account index: 32 bytes (no discount)
* Total uncompressed: 65 bytes
* After 48% compression: 65 × 0.48 ≈ 31 bytes
* Plus overhead: 31 + 2 = **33 bytes**

At an L1 fee rate of 5 sat/vByte (12.5 gwei/byte), these transfers cost approximately 212 gwei and 412 gwei respectively.

### L1 Fee Rate Source

The L1 fee rate is dynamically derived from Bitcoin's current fee market and is determined by the sequencer:

1. The sequencer fetches the current Bitcoin fee rate (in sat/vByte)
2. The rate is converted to wei/byte using: `1 sat/vByte = 2,500,000,000 wei/byte`
3. A maximum cap (default: 15 sat/vByte) prevents excessive charges during Bitcoin fee spikes

The conversion factor derives from: 1 satoshi = 10^10 wei (since 1 BTC = 10^8 sat and 1 cBTC = 10^18 wei), divided by 4 to account for Bitcoin's SegWit witness discount where witness data has 1/4 the weight of regular data.

This direct linkage means L1 fees on Citrea fluctuate with Bitcoin network congestion. Each block stores the current `l1FeeRate` (in wei/byte) in its header, which is calculated as:

```
l1_fee_rate = min(btc_fee_rate × multiplier, max_rate) × 2.5×10^9  (wei/byte)
```

The final L1 fee for a transaction is then: `l1_fee = l1_fee_rate × diff_size`

## Fee Estimation

Citrea provides a dedicated RPC method [`eth_estimateDiffSize`](/developer-documentation/rpc-documentation/citrea-rpc-documentation#eth_estimatediffsize) for estimating L1 data costs:

| Field        | Description                        |
| ------------ | ---------------------------------- |
| `gas`        | Estimated gas consumption          |
| `l1DiffSize` | Estimated state diff size in bytes |

The standard `eth_estimateGas` method returns an effective gas value that includes L1 costs:

```
effective_gas = gas_used + ceil(l1_fee / base_fee)
```

This allows standard Ethereum wallets to display meaningful cost estimates by expressing the L1 fee as equivalent gas units. The L1 fee itself can be calculated as:

```
l1_fee = l1DiffSize × current_l1_fee_rate
```

where `current_l1_fee_rate` is available in block headers via the `l1FeeRate` field.

After a transaction executes, its receipt includes an `l1DiffSize` field showing the actual state diff size that was charged.

## Typical Transaction Costs

The following table shows estimated costs for common transaction types at a Bitcoin fee rate of 5 sat/vByte (\~$100K BTC). These costs are indicatives and can vary between ERC-20 transfers and DeFi interactions. They are based on typical transaction patterns observed on Citrea's testnet. Actual costs vary with Bitcoin network congestion.

| Transaction Type                     | Gas       | Base Fee | L1 Diff Size | L1 Fee  | Total       |
| ------------------------------------ | --------- | -------- | ------------ | ------- | ----------- |
| cBTC Transfer (existing recipient)   | \~21,000  | \~$0.002 | \~17 bytes   | \~$0.02 | **\~$0.02** |
| cBTC Transfer (new recipient)        | \~21,000  | \~$0.002 | \~33 bytes   | \~$0.04 | **\~$0.04** |
| ERC-20 Transfer                      | \~65,000  | \~$0.006 | \~20 bytes   | \~$0.02 | **\~$0.03** |
| Token Approval                       | \~50,000  | \~$0.005 | \~30 bytes   | \~$0.04 | **\~$0.04** |
| DEX Swap                             | \~180,000 | \~$0.02  | \~70 bytes   | \~$0.09 | **\~$0.11** |
| DeFi Interaction (lending/borrowing) | \~300,000 | \~$0.03  | \~120 bytes  | \~$0.15 | **\~$0.18** |
| Simple Contract Deployment           | \~700,000 | \~$0.07  | \~40 bytes   | \~$0.05 | **\~$0.12** |

{% hint style="info" %}
Base fees scale with gas consumption, while L1 fees scale with state changes. A complex DeFi transaction that modifies many storage slots will have higher L1 fees than a simple transfer, even if gas consumption is similar.
{% endhint %}

### Bitcoin Fee Rate Impact

Since L1 fees derive directly from Bitcoin's fee market, costs fluctuate with Bitcoin network congestion. The following shows how a simple cBTC transfer (to existing address) varies across fee rates:

| Bitcoin Fee Rate       | L1 Fee Rate (wei/byte) | L1 Fee   | Total Tx Cost |
| ---------------------- | ---------------------- | -------- | ------------- |
| 1 sat/vByte            | 2.5 gwei/byte          | \~$0.004 | \~$0.01       |
| 5 sat/vByte            | 12.5 gwei/byte         | \~$0.02  | \~$0.02       |
| 10 sat/vByte           | 25 gwei/byte           | \~$0.04  | \~$0.04       |
| 15 sat/vByte (max cap) | 37.5 gwei/byte         | \~$0.06  | \~$0.07       |

The maximum L1 fee rate cap (default: 15 sat/vByte) protects users from extreme costs during Bitcoin fee spikes. Historical data shows Bitcoin fees typically range from 1-10 sat/vByte during normal conditions, with periodic spikes during high-demand periods.

{% hint style="warning" %}
During Bitcoin congestion events, fees can spike significantly. The sequencer caps the L1 fee rate to prevent excessive user charges, but this means the protocol may operate at reduced margins during these periods.
{% endhint %}

## Fee Distribution

All collected fees flow to dedicated [Fee Vault system contracts](/developer-documentation/system-contracts/fee-vaults):

| Vault            | Address                                      | Source                    |
| ---------------- | -------------------------------------------- | ------------------------- |
| BaseFeeVault     | `0x3100000000000000000000000000000000000003` | EIP-1559 base fees        |
| L1FeeVault       | `0x3100000000000000000000000000000000000004` | L1 data availability fees |
| PriorityFeeVault | `0x3100000000000000000000000000000000000005` | Priority tips             |

These vaults accumulate fees until withdrawn to configured recipient addresses. The separation enables transparent accounting of L2 operational costs versus L1 data availability costs.

## Reverted Transactions

Even if a transaction reverts or fails during execution, it still incurs L1 fees for the minimal state changes it causes. These include:

* The sender's nonce increment
* Balance reductions for gas fees

The L1 diff size for a failed transaction is significantly smaller than a successful one, but it is never zero. This ensures users cannot spam the network with intentionally failing transactions without cost.

## Transactions That Cannot Pay L1 Fees

Since the exact state diff size cannot be determined until a transaction executes, the sequencer must run the transaction first to calculate the required L1 fee. If during execution the sequencer determines that the sender lacks sufficient cBTC to pay the computed L1 fees, the transaction is not reverted—it is completely removed as if it was never executed. Importantly, the user pays no fees in this case, including no gas fees or L1 fees.

This design prevents situations where transactions consume gas to compute state diffs but then fail to pay the resulting L1 fees.

## Optimizing Transaction Costs

To minimize fees on Citrea:

1. **Batch operations**: Combine multiple state changes into fewer transactions when possible
2. **Avoid unnecessary storage writes**: Each storage slot modification incurs L1 costs
3. **Use efficient data structures**: Minimize the number of storage slots your contracts use
4. **Time transactions wisely**: L1 fees fluctuate with Bitcoin network congestion
5. **Set appropriate priority fees**: During low congestion, minimal priority fees suffice

## System Transactions

Certain protocol-level operations ([system transactions](https://docs.citrea.xyz/developer-documentation/system-contracts#system-transactions)) are exempt from fees. These transactions originate from the system signer and perform essential network functions without charging the network itself.


# Proofs

Citrea's proof system is the backbone of its security model. By generating zero-knowledge proofs of correct state transitions, Citrea ensures that anyone can verify the rollup's integrity without re-executing every transaction. This page provides a technical deep dive into the proof architecture, covering prover nodes, circuits, and the verification pipeline.

## Proof System Overview

***

Citrea employs a two-tier proving architecture:

* **Batch Proofs:** Prove the correct execution of sequencer commitments (L2 state transitions)
* **Light Client Proofs:** Aggregate batch proofs and verify Bitcoin consensus, forming a recursive proof chain

Both proof types are generated using the **RISC-0 zkVM**, which executes RISC-V programs and produces STARK proofs that are then wrapped in **Groth16 SNARKs** for succinct verification by full nodes and the Light Client Prover. Proofs are inscribed on Bitcoin for permanent availability. The design enables full nodes to verify proofs directly, while the Light Client Prover produces a single recursive proof that external verifiers (including the Clementine bridge) can check without processing the entire chain history.

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-138abab68bd1abea72beb1b0e4e06c0e7bc14dee%2Fproof-system-overview.png?alt=media" alt=""><figcaption><p>Proof System Architecture</p></figcaption></figure>

In addition to these two proof types, Citrea's bridge Clementine uses two more proof types:

* **Bridge Proofs:** Proves the honesty of the bridge operator by recursively verifying light client proofs and proving that withdrawals are paid out correctly.
* **Header chain proofs:** Prove the correctness of the Bitcoin header chain by verifying the difficulty adjustments, timestamps, and previous block hash linkage.

Header chain proofs are used by Watchtowers to challenge a bridge operator by proving the total work of the longest chain, later the challenged operator will need to prove it's honesty by providing a light client proof with more work than the Watchtower's proof. More details about the challenge process can be found in the [Clementine](/essentials/clementine-trust-minimized-bitcoin-bridge) documentation.

## Node Types

***

### Batch Prover

The Batch Prover is a dedicated node that monitors Bitcoin for finalized sequencer commitments and generates proofs of correct L2 execution. It maintains a replica of the rollup state and coordinates with the zkVM to produce succinct proofs.

**Core Responsibilities:**

* Syncs L1 (Bitcoin) blocks to track finalized sequencer commitments
* Syncs L2 blocks from the sequencer to maintain state
* Partitions commitments into provable batches
* Generates circuit inputs and coordinates proof generation
* Submits verified proofs to Bitcoin

<details>

<summary><strong>Batch Prover Architecture</strong></summary>

The Batch Prover consists of three interdependent modules:

**L1 Syncer:**

* Tracks finalized Bitcoin blocks via the DA service
* Extracts sequencer commitments from Bitcoin blocks
* Stores short header proofs for verifying `setBlockInfo` system transactions
* Records block height-to-hash mappings and commitment indices
* Signals the prover when new L1 blocks are processed

**L2 Syncer:**

* Fetches L2 blocks from the sequencer's RPC endpoint
* Applies blocks to the state transition function (STF)
* Maintains current state root and L2 block hash
* Validates state against sequencer claims

**Prover Core:**

* Receives signals from both syncers
* Manages proving session lifecycle
* Creates circuit inputs from commitment partitions
* Coordinates with parallel proving service
* Handles proof verification and submission

</details>

### Light Client Prover

The Light Client Prover (LCP) produces recursive proofs that encapsulate the entire rollup state. Each proof builds on the previous one, verifying both the batch proofs and Bitcoin's consensus rules. Verifying a single proof attests that, for the given Bitcoin chain up to that DA block, the L2 state produced by the circuit is correct, verified, and consistent with the on-chain commitments. For a detailed explanation, see the [light client circuit documentation](https://github.com/chainwayxyz/citrea/blob/nightly/docs/light-client-circuit.md).

**Core Responsibilities:**

* Processes each Bitcoin block containing Citrea data
* Verifies Bitcoin header chain (proof-of-work, difficulty adjustments)
* Validates and aggregates batch proofs
* Maintains a Jellyfish Merkle Tree (JMT) state for commitment tracking
* Produces recursive proofs for external verification

{% hint style="info" %}
The Light Client Prover's output feeds directly into Clementine. The bridge uses the LCP proof in BitVM to verify rollup state without trusting any single party.
{% endhint %}

## Circuits

***

Citrea and Clementine circuits run as RISC Zero guest programs and each cover a distinct part of the verification pipeline. Citrea proves L2 execution and light-client state, while Clementine provides the Header Chain, Work-Only, and Bridge circuits for Bitcoin header verification, compact work extraction, and bridge payout validation.

### Batch Proof Circuit

The Batch Proof Circuit verifies that a sequence of L2 blocks was executed correctly, producing a valid state transition from the previous proven state.

**Circuit Inputs:**

| Field                           | Description                                                                                      |
| ------------------------------- | ------------------------------------------------------------------------------------------------ |
| `initial_state_root`            | State root before batch execution                                                                |
| `final_state_root`              | State root after batch execution (host-side reference; not consumed by the V3 guest input split) |
| `sequencer_commitments`         | Commitments being proven                                                                         |
| `l2_blocks`                     | L2 blocks grouped by commitment (as `VecDeque<Vec<L2Block>>`)                                    |
| `state_transition_witnesses`    | State and offchain witnesses per block (as `VecDeque<Vec<(Witness, Witness)>>`)                  |
| `short_header_proofs`           | Bitcoin header proofs for verifying `SetBlockInfo` system transactions                           |
| `previous_sequencer_commitment` | Prior commitment (None if this is the first batch proof)                                         |
| `prev_hash_proof`               | Merkle proof for verifying the `prev_hash` of the first L2 block                                 |
| `cache_prune_l2_heights`        | L2 heights at which to prune witness cache (zkVM memory management)                              |
| `last_l1_hash_witness`          | Witness for reading the last L1 hash from the Bitcoin light client contract                      |

**Circuit Execution:**

1. Deserializes circuit input (split into two parts to manage zkVM memory)
2. Initializes the State Transition Function with storage runtime
3. Verifies L2 block chain continuity using `prev_hash_proof`
4. Replays L2 blocks against the initial state, applying transactions
5. Validates intermediate state roots at commitment boundaries
6. Accumulates state diffs across all processed blocks
7. Verifies short header proofs for system transactions (e.g., `setBlockInfo`)
8. Commits output (state roots, state diff, commitment range) to the journal

<details>

<summary><strong>Batch Proof Output Structure</strong></summary>

```
BatchProofCircuitOutputV3:
├── state_roots: Vec<[u8; 32]>                               // State roots: [initial, after_commit_1, ..., final]
│                                                            // Length = num_commitments + 1
├── final_l2_block_hash: [u8; 32]                            // Hash of last L2 block processed
├── state_diff: CumulativeStateDiff                          // Cumulative state changes across batch
├── last_l2_height: u64                                      // Final L2 block height
├── sequencer_commitment_hashes: Vec<[u8; 32]>               // SHA256 hashes of processed commitments
├── sequencer_commitment_index_range: (u32, u32)             // Range (start, end) inclusive
├── last_l1_hash_on_bitcoin_light_client_contract: [u8; 32]  // Latest Bitcoin hash known
├── previous_commitment_index: Option<u32>                   // Index of prior commitment (None if first)
└── previous_commitment_hash: Option<[u8; 32]>               // Hash of prior commitment (None if first)
```

</details>

### Light Client Circuit

The Light Client Circuit verifies Bitcoin consensus and aggregates batch proofs into a single recursive proof. It maintains persistent state via a Jellyfish Merkle Tree, enabling flexible proof chaining even when proofs arrive out of order.

**Circuit Inputs:**

| Field                          | Description                                                               |
| ------------------------------ | ------------------------------------------------------------------------- |
| `da_block_header`              | Bitcoin block header being processed                                      |
| `inclusion_proof`              | Merkle proof of transaction inclusion (wtxids, coinbase tx, merkle proof) |
| `completeness_proof`           | Raw transactions matching relevant wtxid prefixes                         |
| `previous_light_client_proof`  | Prior LCP proof bytes (None for the first proof)                          |
| `witness`                      | JMT state hints for verification                                          |
| `light_client_proof_method_id` | Current circuit version identifier (256 bits)                             |

**Circuit Execution:**

1. Verifies the previous light client proof (if exists) using the method ID and extracts its output
2. Validates the Bitcoin header chain against consensus rules (PoW, difficulty, timestamps, continuity)
3. Verifies transaction inclusion and completeness proofs against the block header
4. Inserts the current Bitcoin block hash into the JMT state
5. Processes relevant transactions from the block:
   * **Chunks**: Stored in JMT by wtxid for later aggregation
   * **Complete proofs**: Decompressed, verified against method ID, state transitions recorded
   * **Aggregates**: Chunks retrieved by wtxid, concatenated, decompressed, verified
   * **Sequencer commitments**: Stored in JMT by index (sender verified)
   * **Method ID upgrades**: 3-of-5 security council signatures verified, chain ID checked, new IDs recorded
6. Chains verified state transitions to advance L2 state root (processes in order by commitment index)
7. Computes and validates JMT state root transition
8. Outputs new LCP proof with updated L2 state, LCP state root, and DA state

<details>

<summary><strong>Light Client Output Structure</strong></summary>

```
LightClientCircuitOutput:
├── l2_state_root: [u8; 32]                 // Current L2 state
├── lcp_state_root: [u8; 32]                // JMT state root
├── light_client_proof_method_id: [u32; 8]  // Circuit version
├── latest_da_state: LatestDaState          // Bitcoin chain state
│   ├── block_hash: [u8; 32]
│   ├── block_height: u64
│   ├── total_work: [u8; 32]
│   ├── current_target_bits: u32
│   ├── epoch_start_time: u32
│   └── prev_11_timestamps: [u32; 11]
├── last_l2_height: u64                     // Highest proven L2 block
└── last_sequencer_commitment_index: u32    // Highest proven commitment
```

</details>

### Bitcoin Verification in the Light Client Circuit

The Light Client Circuit performs Bitcoin header-chain verification, ensuring that proofs are anchored to valid Bitcoin blocks:

**Proof-of-Work Validation:**

* Verifies block hash is below the current difficulty target
* Converts compact bits to full target representation
* Accumulates total work across the header chain

**Difficulty Adjustment:**

* Detects epoch boundaries (every 2016 blocks on mainnet)
* Calculates new target based on actual vs expected time (14 days expected)
* Enforces minimum and maximum target bounds

**Header Continuity:**

* Validates previous block hash linkage
* Ensures consecutive block heights
* Checks timestamp validity against median time past

**SegWit Commitment Verification:**

* Locates witness commitment in coinbase output (script starting with `0x6a24aa21a9ed`)
* Computes wtxid merkle root from all block transactions
* Validates commitment equals `sha256(sha256(wtxid_merkle_root || witness_reserved_value))`
* Ensures witness data integrity for inscribed proofs

### Header Chain Circuit

The Header Chain Circuit verifies Bitcoin block headers against Bitcoin consensus rules and commits an updated chain state. It supports recursive proof chaining: the first proof starts from a genesis `ChainState`, and subsequent proofs verify the previous Header Chain proof before applying more headers.

State is maintained in `ChainState`, which includes the current Bitcoin height, accumulated work, best block hash, difficulty state, previous 11 timestamps, and a Merkle Mountain Range (MMR) of verified block hashes. The MMR lets later circuits prove that a Bitcoin block hash belongs to the verified chain without replaying every header.

**Circuit Inputs:**

| Field           | Description                                                                                                            |
| --------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `method_id`     | Header Chain circuit version identifier. It must match any prior proof's method ID.                                    |
| `prev_proof`    | Either `GenesisBlock(ChainState)` for the first proof or `PrevProof(BlockHeaderCircuitOutput)` for recursive chaining. |
| `block_headers` | Contiguous Bitcoin headers, ordered from the next expected block after the current chain state.                        |

**Circuit Execution:**

1. Reads `HeaderChainCircuitInput` from the zkVM host.
2. Initializes state from either the genesis `ChainState` or a verified previous `BlockHeaderCircuitOutput`.
3. If a previous proof is provided, checks that its `method_id` matches the current input and recursively verifies it with `guest.verify`.
4. Initializes the active target from the current chain state and initializes a local accumulated-work value.
5. Iterates over every header in `block_headers`. For each header:
   * Advances the working block height by one.
   * Selects the target, expected `bits`, and work increment for that height and network.
   * Computes the Bitcoin block hash.
   * Checks chain continuity by requiring `prev_block_hash` to equal the current `best_block_hash`.
   * Validates the header `bits` field against the expected network difficulty.
   * Validates proof of work by checking the block hash against the selected target.
   * Enforces median-time-past by requiring the block timestamp to be greater than the median of the previous 11 timestamps.
   * Appends the verified block hash to the MMR.
   * Updates the working best block hash, accumulated work, timestamp ring buffer, epoch start time when applicable, and the previous-header timestamp used by Testnet4's minimum-difficulty rule.
   * After the last block of a non-regtest difficulty epoch, recomputes and stores the target bits to use for the next epoch.
6. After all provided headers have been processed, writes the final accumulated work back into `chain_state.total_work`.
7. Commits one `BlockHeaderCircuitOutput` for the whole batch.

<details>

<summary><strong>Header Chain Output Structure</strong></summary>

```
BlockHeaderCircuitOutput:
├── method_id: [u32; 8]
├── genesis_state_hash: [u8; 32]
└── chain_state: ChainState
    ├── block_height: u32
    ├── total_work: [u8; 32]
    ├── best_block_hash: [u8; 32]
    ├── current_target_bits: u32
    ├── epoch_start_time: u32
    ├── prev_11_timestamps: [u32; 11]
    └── block_hashes_mmr: MMRGuest
        ├── subroots: Vec<[u8; 32]>
        └── size: u32
```

</details>

### Work-Only Circuit

The Work-Only Circuit verifies a Header Chain proof and extracts only the data needed by watchtowers and the Bridge Circuit: accumulated Bitcoin work and the genesis state hash. It makes watchtower challenges compact by converting the Header Chain proof's 256-bit total work into a 128-bit value that can be included alongside a compressed Groth16 proof.

**Circuit Inputs:**

| Field                         | Description                                    |
| ----------------------------- | ---------------------------------------------- |
| `header_chain_circuit_output` | Public output of a Header Chain Circuit proof. |

**Circuit Execution:**

1. Reads `WorkOnlyCircuitInput` from the zkVM host.
2. Uses the Header Chain method ID baked into the circuit for the compile-time `BITCOIN_NETWORK`.
3. Checks that `header_chain_circuit_output.method_id` matches the expected Header Chain method ID.
4. Verifies the Header Chain proof with `env::verify`.
5. Reads `chain_state.total_work` from the verified Header Chain output and converts it from a 256-bit value to a 128-bit value by keeping the lower 128 bits.
6. Commits `WorkOnlyCircuitOutput` containing the 128-bit work value and the Header Chain `genesis_state_hash`.

<details>

<summary><strong>Work-Only Output Structure</strong></summary>

```
WorkOnlyCircuitOutput:
├── work_u128: [u8; 16]
└── genesis_state_hash: [u8; 32]
```

</details>

### Bridge Circuit

The Bridge Circuit verifies that an operator is entitled to reimburse a withdrawal from the bridge vault during the BitVM challenge flow. It combines the operator's Header Chain proof, watchtower challenge data, payout transaction SPV proof, and a Citrea Light Client proof. The light-client output provides the Citrea L2 state root, which is then used to verify Clementine bridge contract storage proofs for the withdrawal and deposit data.

The circuit's public output is a 32-byte journal hash. That hash commits to the payout block hash, the operator's latest verified Bitcoin block hash, which watchtowers sent valid challenges, and a deposit constant derived from deposit-specific bridge data.

**Circuit Inputs:**

| Field                                      | Description                                                                                                                                                                     |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kickoff_tx`                               | Kickoff transaction for the reimbursement flow; it contains the reimbursement connector and connector outputs used by challenge, Assert, and Disprove paths.                    |
| `all_tweaked_watchtower_pubkeys`           | Registered tweaked x-only public keys for watchtower challenge outputs.                                                                                                         |
| `watchtower_inputs`                        | Watchtower challenge transactions, prevouts, witnesses, input indexes, watchtower indexes, and optional annex digests.                                                          |
| `hcp`                                      | Operator's `BlockHeaderCircuitOutput` from the Header Chain Circuit.                                                                                                            |
| `payout_spv`                               | SPV proof for the payout transaction, including the payout transaction, block inclusion proof, block header, and MMR inclusion proof.                                           |
| `payout_input_index`                       | Input index in the payout transaction that should spend the user's verified withdrawal outpoint.                                                                                |
| `lcp`                                      | Citrea light-client proof journal bytes. The Bridge Circuit verifies the journal against the configured light-client image ID, then deserializes it as the light-client output. |
| `sp`                                       | Storage proof input for Clementine bridge contract data on Citrea: withdrawal UTXO txid, withdrawal vout, and deposit move txid.                                                |
| `watchtower_challenge_connector_start_idx` | Kickoff output index where watchtower challenge connector outputs begin.                                                                                                        |

**Circuit Execution:**

1. Reads `BridgeCircuitInput` from the zkVM host.
2. Checks that `hcp.method_id` matches the expected Header Chain method ID for the compile-time `BITCOIN_NETWORK`.
3. Verifies the operator's Header Chain proof with `guest.verify`.
4. Verifies each watchtower challenge input:
   * The challenge input must spend the kickoff output at `watchtower_challenge_connector_start_idx + watchtower_idx * 2`.
   * The spent kickoff output must be P2TR.
   * The output x-only key must match the registered watchtower key.
   * The Taproot key-path Schnorr signature must verify under BIP341 sighash rules.
5. Records a 160-bit bitmap of watchtowers that sent valid challenge transactions.
6. Parses each valid watchtower challenge commitment in one of two forms:
   * A first `OP_RETURN` output containing 128 bytes of compressed Groth16 proof plus 16 bytes of total work.
   * First and second P2TR outputs containing the first 64 proof bytes, followed by a third `OP_RETURN` output containing the remaining 64 proof bytes plus 16 bytes of total work.
7. Sorts valid watchtower commitments by claimed total work in descending order.
8. Verifies compressed Groth16 Work-Only proofs until the first valid proof is found. This produces `max_total_work`.
9. Compares the operator's Header Chain total work against `max_total_work`; the operator must have at least as much verified work as the strongest valid watchtower challenge.
10. Verifies the payout SPV proof:
    * Computes the payout transaction mid-state txid.
    * Reconstructs the Bitcoin Merkle root using the mid-state inclusion proof.
    * Checks the reconstructed Merkle root against the `merkle_root` field of `payout_spv.block_header`.
    * Checks the payout block hash against the Header Chain MMR inclusion proof.
11. Verifies the Citrea light-client journal against the network light-client image ID.
12. Deserializes the light-client output and checks its method ID against the configured image ID.
13. Requires the light-client latest DA block hash to equal the payout SPV block hash.
14. Verifies Clementine contract storage proofs against the light-client L2 state root:
    * withdrawal outpoint txid,
    * withdrawal vout,
    * deposit move txid.
15. Requires the payout transaction input at `payout_input_index` to spend the verified withdrawal outpoint and vout.
16. Reads the operator x-only public key from the first `OP_RETURN` output of the payout transaction.
17. Computes `deposit_constant` from the operator key, watchtower keys, watchtower connector start index, move txid, kickoff round outpoint, and Header Chain genesis state hash.
18. Truncates the payout block hash and latest Header Chain block hash to their final 20 bytes.
19. Computes the final journal hash:
    * `inner = blake3(payout_tx_blockhash || latest_blockhash || challenge_sending_watchtowers)`
    * `journal_hash = blake3(deposit_constant || inner)`
20. Commits the 32-byte journal hash.

<details>

<summary><strong>Bridge Circuit Committed Output</strong></summary>

```
Bridge Circuit journal:
└── journal_hash: [u8; 32]
```

</details>

### Circuit Relations

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-9649b994891a1c004189a429da2bc8766312ff29%2Fcircuit-relations.svg?alt=media" alt="Diagram showing the relationships between Citrea and Clementine circuits"><figcaption><p>Circuit Relations</p></figcaption></figure>

## ZKVM and Proof Generation

***

### RISC-0 zkVM

Citrea uses the **RISC-0 zkVM** as its primary proving backend. RISC-0 executes RISC-V programs and generates STARKs that are wrapped in Groth16 SNARKs for succinct verification by nodes.

**Guest Programs (ELF Binaries):**

* `batch-proof-bitcoin`: Batch proof circuit for Bitcoin DA
* `light-client-proof-bitcoin`: Light client circuit for Bitcoin DA
* `header-chain-guest`: Clementine Header Chain circuit
* `work-only-guest`: Clementine Work-Only circuit
* `bridge-circuit-guest`: Clementine Bridge Circuit

**Proving Modes:**

* `Skip`: Skip proving entirely
* `Execute`: Execute the zkVM without generating proofs (testing/development)
* `ProveWithSampling`: The prover runs the rollup verification logic in the zkVM and produces a zk proof
* `ProveWithSamplingWithFakeProofs(N)`: The prover runs the rollup verification logic in the zkVM and produces a zk/fake proof. If proof\_sampling\_number is 0, then we always produce real proofs Otherwise we prove with a probability of 1/proof\_sampling\_number

**Proof Pipeline:**

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-3416b70686264727d8663655170ed35921130658%2Fproof-pipeline.png?alt=media" alt=""><figcaption><p>Proof Pipeline</p></figcaption></figure>

### Code Commitments (Method IDs)

Each circuit version is identified by a **method ID** — a 256-bit hash derived from the compiled ELF binary. Method IDs serve as code commitments, ensuring proofs were generated with the expected circuit logic.

```
Method ID: [u32; 8] (256 bits)
Computed from: risc0_zkvm::compute_image_id(elf_binary)
```

**Method ID Security:**

* Initial method IDs hardcoded per network at genesis
* Upgrades require 3-of-5 security council signatures (ECDSA over EIP-191 prefixed, keccak256-hashed message)
* Activation L2 height must exceed previous method ID's activation height
* Chain ID embedded in upgrade body prevents cross-network replay attacks
* Method IDs stored as `Vec<(activation_l2_height, [u32; 8])>` to support versioned circuits

{% hint style="warning" %}
Method ID upgrades are protected by the security council multisig. This prevents unauthorized circuit changes while enabling protocol upgrades when needed.
{% endhint %}

## Commitment Partitioning

***

Before proving, the Batch Prover partitions pending commitments into provable chunks. This balances proof generation efficiency with Bitcoin transaction size constraints.

**Pre-Partition Filtering:**

Before partitioning, the prover filters commitments:

* **Unsynced filter:** Excludes commitments whose L2 blocks haven't been synced yet
* **Index gap filter:** Excludes commitments that lack a known previous commitment (ensures sequential proving)

**Partition Boundary Conditions:**

| Condition        | Description                                                                               |
| ---------------- | ----------------------------------------------------------------------------------------- |
| Spec Change      | Fork/specification change between commitments triggers a new partition                    |
| State Diff Size  | Compressed state diff exceeds `MAX_TX_BODY_SIZE` (397,000 bytes) triggers a new partition |
| Commitment Count | Exceeds `max_commitments_per_proof` limit triggers a new partition                        |
| One-by-One Mode  | Each commitment becomes its own partition (optional mode)                                 |

**Partitioning Flow:**

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-e5bc6bd87a148e799c7ada176d43f5e7977936b0%2Fpartitioning-flow.png?alt=media" alt=""><figcaption><p>Partitioning Flow</p></figcaption></figure>

## Proof Formats on Bitcoin

***

Proofs are inscribed on Bitcoin using SegWit witness data. Due to Bitcoin's transaction size limits, large proofs are split into chunks and later aggregated.

### Transaction Types

| Type                  | Description                                                      |
| --------------------- | ---------------------------------------------------------------- |
| `Complete`            | Full proof fitting in a single transaction                       |
| `Aggregate`           | References chunk txids and wtxids for reconstruction             |
| `Chunk`               | Partial proof segment (stored by wtxid in LCP JMT state)         |
| `BatchProofMethodId`  | Circuit upgrade with 3-of-5 security council signatures          |
| `SequencerCommitment` | L2 block range commitment (merkle root, index, end block number) |

### Aggregation Mechanism

When a proof exceeds Citrea's `MAX_TX_BODY_SIZE` (397,000 bytes):

1. **Compression:** Proof is serialized and compressed
2. **Chunking:** Compressed data split into segments fitting within `MAX_TX_BODY_SIZE`
3. **Inscription:** Each chunk inscribed as `DataOnDa::Chunk` in a separate transaction
4. **Aggregation:** Parent transaction (`DataOnDa::Aggregate`) lists chunk wtxids for retrieval
5. **Reconstruction:** Light Client retrieves chunks by wtxid from JMT state, concatenates them
6. **Decompression:** Combined chunks decompressed to original proof
7. **Verification:** Proof verified against the batch proof method ID for the relevant L2 height

{% hint style="info" %}
The chunking mechanism keeps individual transactions under `MAX_TX_BODY_SIZE` (397,000 bytes) while enabling arbitrarily large proofs. Chunks are stored in the Light Client's JMT state indexed by wtxid until the aggregate transaction arrives.
{% endhint %}

## Verification Pipeline

***

### On-Chain Flow (Bitcoin)

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-7fc3178d13cf60199223fa00c878eeb9e1151940%2Fonchain-flow.png?alt=media" alt=""><figcaption><p>On-Chain Verification Flow</p></figcaption></figure>

### Full Node Verification

Full nodes verify proofs as they arrive on Bitcoin:

1. **Fetch:** Retrieve proof transaction from Bitcoin block
2. **Decompress:** Extract and decompress proof blob
3. **Verify SNARK:** Check Groth16 proof against method ID
4. **Validate Output:** Confirm the L1 hash is known, commitment hashes match, and the pre-state root matches ledger state
5. **Update State:** Apply state diff and advance proven tip

### Light Client State Chaining

The Light Client uses state root chaining to connect batch proofs:

```rust
// State chaining logic (from light-client-prover/src/circuit/mod.rs)
while let Some(sequencer_commitment_info) =
    VerifiedStateTransitionForSequencerCommitmentIndexAccessor::<S>::get(
        last_sequencer_commitment_index + 1,
        &mut working_set,
    )
{
    if sequencer_commitment_info.initial_state_root == last_l2_state_root {
        // Chain this proof to advance L2 state
        last_l2_state_root = sequencer_commitment_info.final_state_root;
        last_l2_height = sequencer_commitment_info.last_l2_height;
        last_sequencer_commitment_index += 1;
    } else {
        // State root mismatch - should be unreachable if batch proofs are valid
        unreachable!("Commitment with the next index having an unexpected state root");
    }
}
```

**Key Properties:**

* Proofs can arrive out of order on Bitcoin
* Proof ranges may overlap. A later proof can cover already-verified commitments while extending with newer ones
* JMT stores verified state transitions indexed by commitment number
* State root continuity ensures chain integrity
* Chaining advances automatically when gaps are filled

## Settlement via Clementine

***

The Light Client Prover's output enables trust-minimized settlement through Clementine:

1. **LCP Proof Generation:** Light Client produces recursive proof of current state
2. **BitVM Verification:** Bridge operators can be challenged using LCP proof
3. **Dispute Resolution:** Invalid claims disproven via proof verification in BitVM
4. **Settlement:** Valid withdrawals proceed once verification completes

{% hint style="success" %}
The LCP combines Bitcoin consensus verification with batch proof aggregation into a single artifact. This enables Clementine to verify rollup state with Bitcoin-level security guarantees, without trusting the sequencer or any bridge operator.
{% endhint %}

## Security Considerations

***

### Proof Soundness

* **Computational Soundness:** Groth16 proofs are computationally sound under standard cryptographic assumptions
* **Code Commitment:** Method IDs bind proofs to specific circuit logic
* **Security Council:** 3-of-5 multisig protects method ID upgrades

### Liveness Guarantees

* **Proof Sampling:** `ProveWithSamplingWithFakeProofs` mode enables testing with occasional real proofs based on configurable probability
* **Recovery Mode:** Interrupted proving sessions tracked in ledger DB and recovered on restart
* **Parallel Proving:** Multiple proofs generated concurrently via the parallel prover service
* **Partition Flexibility:** Large commitment ranges automatically split to fit transaction limits

### Bitcoin Anchoring

* **Immutable Ordering:** After finality depth, sequencer commitments are treated as fixed; before that, L1 reorgs can reorder data
* **Data Availability:** State diffs inscribed alongside proofs enable state reconstruction
* **Fork Resistance:** Deep Bitcoin reorg required to reverse proven batches

## Summary

***

Citrea's proof system achieves trust-minimized verification through a carefully designed architecture:

| Component                                                                                               | Role                                                             |
| ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| [Batch Prover](/essentials/architecture-and-transaction-lifecycle#batch-prover)                         | Proves L2 state transitions for sequencer commitments            |
| [Light Client Prover](/essentials/architecture-and-transaction-lifecycle#light-client-prover)           | Aggregates proofs and verifies Bitcoin header-chain rules        |
| [Batch Proof Circuit](https://github.com/chainwayxyz/citrea/blob/nightly/docs/batch-proof-circuit.md)   | Verifies correct execution of L2 blocks                          |
| [Light Client Circuit](https://github.com/chainwayxyz/citrea/blob/nightly/docs/light-client-circuit.md) | Recursive verification with Bitcoin header chain                 |
| [RISC-0 zkVM](https://www.risczero.com/)                                                                | Executes circuits and generates Groth16 proofs                   |
| [Bitcoin DA](https://github.com/chainwayxyz/citrea/blob/nightly/docs/da.md)                             | Data availability layer enabling ZK verification of rollup state |
| [Clementine](/essentials/clementine-trust-minimized-bitcoin-bridge)                                     | Consumes LCP proofs for trust-minimized settlement               |

The two-tier architecture separates concerns: Batch Proofs handle high-throughput L2 verification, while Light Client Proofs provide succinct recursive verification for external consumers. Together, they enable Citrea to inherit Bitcoin's security while maintaining EVM compatibility and scalability.


# Data Availability

Citrea utilizes Bitcoin as its unified layer for data availability and settlement. The [`bitcoin-da`](https://github.com/chainwayxyz/citrea/tree/nightly/crates/bitcoin-da) implementation handles publishing rollup data to Bitcoin and retrieving that data for verification within the [light client proof](/essentials/architecture-and-transaction-lifecycle#light-client-prover) circuit:

By leveraging the transaction Merkle root in Bitcoin block headers and verifying the header-chain proof-of-work, Citrea generates ZK proofs that cryptographically confirm specific transactions exist on the blockchain. This allows the protocol to verify data inclusion mathematically, ensuring the rollup state is always derivable from Bitcoin itself.

## Bitcoin as Settlement Layer

Beyond data availability, Bitcoin serves as Citrea's settlement layer. Unlike Ethereum rollups that settle via on-chain verifier contracts, Citrea achieves settlement through a cryptographic proof chain anchored to Bitcoin's proof-of-work; the proofs themselves are the settlement mechanism.

### State Commitment Pipeline

Settlement on Citrea follows a three-stage pipeline, each stage publishing data to Bitcoin:

1. **Sequencer Commitments**: The [sequencer](/essentials/architecture-and-transaction-lifecycle#sequencer) periodically publishes [commitments](/essentials/architecture-and-transaction-lifecycle#4-sequencer-commitments-on-bitcoin) containing a Merkle root over sequential L2 block hashes and the batch's ending L2 block number (the start is implicitly the previous commitment's end + 1). Once finalized on Bitcoin, these commitments pin the canonical ordering of L2 blocks, the sequencer cannot reorder or omit transactions without contradicting data already settled on Bitcoin.
2. **Batch Proofs**: The [batch prover](/essentials/architecture-and-transaction-lifecycle#batch-prover) generates a zkSNARK proving that executing all transactions in a committed batch, starting from the previous proven state root, produces the claimed new state root. This proof, along with compressed state diffs, is published to Bitcoin. The proof attests: *"the state transition is valid"*. Proof payloads are Brotli-compressed before inscribed on-chain. Batch proofs under [MAX\_TX\_BODY\_SIZE](https://github.com/chainwayxyz/citrea/blob/nightly/crates/primitives/src/constants.rs#L24) (397KB) fit in a single transaction; larger proofs are chunked and later aggregated.
3. **Light Client Proofs**: The [light client prover](/essentials/architecture-and-transaction-lifecycle#light-client-prover) produces recursive proofs that chain together, each verifying the previous proof plus new batch proofs. The resulting proof encapsulates the entire rollup history: *"starting from genesis and applying all batches yields state root X"*. This single proof is sufficient for external verifiers to confirm Citrea's state without processing the full history.

### Settlement Without Smart Contracts

Bitcoin lacks the programmability to verify zkSNARKs directly on-chain. Citrea addresses this through two mechanisms:

* **Full node verification**: Citrea full nodes fetch batch proofs from Bitcoin and verify them locally. Once verified, the batch reaches [proven finality](/essentials/transaction-finality#proven). The state transition is cryptographically guaranteed, secured by both the zkSNARK soundness and Bitcoin's proof-of-work protecting the data.
* **BitVM-based bridge verification**: The [Clementine bridge](https://github.com/chainwayxyz/citrea-docs/blob/main/essentials/clementine-bridge.md) uses BitVM to optimistically verify light client proofs on Bitcoin. Operators can be challenged if they claim an incorrect state, with the light client proof serving as the dispute resolution mechanism. This enables trust-minimized BTC withdrawals without requiring Bitcoin soft forks.

### Finality Guarantees

L2 transactions inherit Bitcoin's finality in stages (see [Transaction Finality](/essentials/transaction-finality)):

| Stage          | Anchor                          | Guarantee                                                                                  |
| -------------- | ------------------------------- | ------------------------------------------------------------------------------------------ |
| Soft-confirmed | Sequencer signature             | Fast UX, but can still be reorged                                                          |
| Finalized      | Sequencer commitment on Bitcoin | Transactions are considered finalized after [6 L1 confirmations](/advanced/reorg-handling) |
| Proven         | Batch proof on Bitcoin          | Execution validity is cryptographically verified                                           |

Once proven, reverting an L2 transaction would require either breaking the zkSNARK (computationally infeasible) or executing a deep Bitcoin reorganization beyond the finality depth—making proven L2 transactions effectively as secure as L1 Bitcoin transactions.

## Publishing Data on Bitcoin Using Inscriptions

Citrea publishes data using a Taproot commit-reveal scheme. The commit transaction locks funds to a script that can only be spent by revealing the inscription data. The reveal transaction then spends this output, embedding the data in the witness. This type of data was popularized and named "inscriptions" by the [Ordinals protocol](https://docs.ordinals.com/inscriptions.html).

The reveal script has a header identifying the transaction type:

```
PushBytes(XOnlyPublicKey)
OP_CHECKSIGVERIFY
PushBytes([2 bytes for transaction type in LE])
```

The body follows with an `OP_FALSE OP_IF ... OP_ENDIF` pattern that creates an unexecuted code branch, allowing data storage without affecting script execution. Each body chunk is limited to 520 bytes due to Bitcoin's script push size limit.

Witness data benefits from the SegWit discount, costing approximately 1/4 the fee of equivalent data stored in transaction outputs.

## WTXID Prefix

The [light client proof](/essentials/architecture-and-transaction-lifecycle#light-client-prover) must verify that all relevant DA transactions in a Bitcoin block are included. Scanning and parsing every transaction in a block to check if it's a Citrea inscription adds significant overhead to the ZK circuit—the circuit cost grows linearly with the number of transactions, regardless of whether they are Citrea-related.

Citrea uses a witness transaction ID (WTXID) prefix mechanism to reduce this overhead. The transaction publisher (sequencer, batch prover, or security council) adjusts a nonce in the reveal script until the resulting WTXID starts with a specific prefix ([`0x0202`](https://github.com/chainwayxyz/citrea/blob/nightly/crates/primitives/src/constants.rs#L7)). The circuit then filters candidate transactions by checking only the first two bytes of each WTXID, parsing only those that match.

With a 2-byte prefix, a random transaction has a 1/65,536 chance of matching, resulting in approximately 0.0015% false positives per block. These are filtered out during [transaction format parsing](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/helpers/parsers.rs). The prefix mechanism is purely a performance optimization for the ZK circuit—it has no security value since anyone can craft a matching nonce. Security comes entirely from signature verification: all Citrea inscriptions must contain a valid signature from an authorized key (sequencer, batch prover, or security council).

## Transaction Types

The bitcoin-da implementation supports [multiple transaction types](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/helpers/mod.rs#L21-L36): Complete batch proofs (type `0x00`), Aggregate batch proofs (`0x01`), Chunks (`0x02`), BatchProofMethodId updates (`0x03`), and Sequencer Commitments (`0x04`).

### Batch Proofs

A batch proof that fits within 397KB is published as a single Complete transaction. This limit exists because Bitcoin Core's [default mempool policy](https://github.com/bitcoin/bitcoin/blob/d52ba21dfff99173abb927bc964ce831071c2f6f/src/policy/policy.h#L26-L27) rejects transactions exceeding 400KB (MAX\_STANDARD\_TX\_WEIGHT), and 397KB leaves room for script overhead while ensuring transactions propagate across the network. The inscription contains a signature, the [batch prover's](/essentials/architecture-and-transaction-lifecycle#batch-prover) public key, and the compressed proof data split into 520-byte chunks:

```
OP_FALSE
OP_IF
  OP_PUSHDATA(signature)
  OP_PUSHDATA(batch_prover_public_key)
  OP_PUSHDATA(proof_chunk_1)
  ...
  OP_PUSHDATA(proof_chunk_n)
OP_ENDIF
OP_PUSHDATA(8 random bytes [nonce])
OP_NIP
```

When a batch proof exceeds 397KB, it's split across multiple Chunk transactions. Each chunk contains only the raw data (no signature or public key). An Aggregate transaction then ties these chunks together by containing pointers to each chunk's txid and wtxid, along with a signature from the batch prover covering the aggregate data. The light client proof verifies the aggregate transaction's signature and uses the pointers to locate and reconstruct the full proof from the referenced chunks.

### BatchProofMethodId

The [BatchProofMethodId](https://github.com/chainwayxyz/citrea/blob/nightly/crates/sovereign-sdk/rollup-interface/src/state_machine/da.rs#L61-L74) transaction allows the security council to update the ZK verification key (method ID) used by the light client proof to verify batch proofs. This enables the light client proof to verify batch proofs generated with an updated proving system. It contains a new method ID, the L2 activation height, and 3-of-5 security council signatures.

### Sequencer Commitment

The [sequencer](/essentials/architecture-and-transaction-lifecycle#sequencer) publishes [commitments](/essentials/architecture-and-transaction-lifecycle#4-sequencer-commitments-on-bitcoin) that include a Merkle root of L2 block hashes, a monotonic index, and the ending L2 block number. See [`SequencerCommitment`](https://github.com/chainwayxyz/citrea/blob/nightly/crates/sovereign-sdk/rollup-interface/src/state_machine/da.rs#L21-L28) for the full structure.

{% hint style="info" %}
For implementation details and full transaction format specifications, see the [bitcoin-da crate](https://github.com/chainwayxyz/citrea/tree/nightly/crates/bitcoin-da).
{% endhint %}

## Verification in the Light Client Proof

The [DA verifier](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/verifier.rs#L36) runs inside the light client proof circuit and enforces both completeness and correctness of data.

**Completeness** ensures no relevant transactions are omitted. A transaction is "relevant" if its WTXID starts with the Citrea prefix (`0x0202`) and successfully parses as a valid Citrea inscription. The verifier iterates through all transaction WTXIDs in the block, filters by prefix, parses matching transactions, and rejects the proof if any valid Citrea transaction is missing from the provided data.

**Correctness** ensures included data is valid and untampered:

* **Witness data verification**: The verifier computes the witness Merkle root from all WTXIDs in the block. The coinbase transaction contains a SegWit commitment in its output (prefixed [`0x6a24aa21a9ed`](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/verifier.rs#L21)). The verifier confirms `SHA256d(witness_merkle_root || witness_nonce)` matches this commitment.
* **Coinbase inclusion**: The coinbase transaction itself is verified against the header's Merkle root via a txid Merkle proof, establishing that the witness commitment comes from the actual block.
* **Sender authentication**: Inscriptions include the sender's public key and a signature over `SHA256(blob_body)`. The verifier checks this ECDSA signature to confirm data originated from an authorized party (sequencer, batch prover, or security council).
* **Decompression bounds**: When reconstructing Brotli-compressed payloads, the circuit enforces protocol size limits on the decompressed output. Any payload that expands beyond allowed bounds of 100 MB (see [MAX\_DECOMPRESSED\_BLOB\_SIZE](https://github.com/chainwayxyz/citrea/blob/nightly/crates/primitives/src/constants.rs#L58)) causes proof failure, preventing decompression-bomb style attacks inside the circuit.

The verifier also validates the Bitcoin header chain itself—checking block hashes, height continuity, difficulty targets, proof of work, and timestamp validity. On mainnet, [6 block confirmations](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/network_constants.rs#L12) are required before data is considered final (see [Transaction Finality](/essentials/transaction-finality)). See [`NetworkConstants`](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/network_constants.rs#L52-L59) for network-specific parameters.

### Recursive Proof Accumulation

The light client proof is recursive: each proof verifies the previous proof before processing the next L1 block. This creates a chain where verifying a single proof attests that, for the given Bitcoin chain up to that block, the L2 state produced by the circuit is correct and consistent with all on-chain commitments.

#### Chain Structure

Each light client proof takes as input:

* The previous light client proof (None for the genesis proof)
* A Bitcoin block header with inclusion and completeness proofs
* A witness for accessing the circuit's JMT state

The circuit first verifies the previous proof using the zkVM's verification API, extracting the previous output. It then verifies the new block header follows the previous block under Bitcoin's consensus rules—checking proof-of-work, height continuity, difficulty targets, and timestamp validity.

#### Accumulated State

The circuit maintains a [JellyFish Merkle Tree](https://github.com/penumbra-zone/jmt) (JMT) that accumulates the following data across blocks:

| Data Type                  | Purpose                                                                          |
| -------------------------- | -------------------------------------------------------------------------------- |
| Block hashes               | Proves a specific L1 block was seen by the circuit                               |
| Sequencer commitments      | Stores commitment data indexed by monotonic index                                |
| Verified state transitions | Maps commitment index to verified (initial\_root, final\_root, last\_l2\_height) |
| Proof chunks               | Stores chunk bodies by wtxid for later aggregation                               |
| Batch proof method IDs     | Tracks verification keys with activation heights                                 |

#### Transaction Processing

For each Bitcoin block, the circuit processes all relevant transactions extracted via the completeness proof:

1. **Sequencer commitments**: Stored in the JMT by their index. The circuit verifies the sender is the authorized sequencer.
2. **Batch proofs** (Complete or Aggregate): The circuit verifies the zkSNARK using the appropriate method ID from the JMT. It then validates the sequencer commitment relation—ensuring the batch proof's referenced commitments exist in the JMT with matching hashes. Upon successful verification, each commitment in the batch's range is marked as a `VerifiedStateTransition` in the JMT.
3. **Proof chunks**: Stored in the JMT by their wtxid. When an Aggregate transaction arrives, the circuit retrieves and concatenates the chunks to reconstruct the full proof.
4. **Method ID updates**: Stores new verification keys with their activation L2 height after validating 3-of-5 security council signatures.

#### State Root Advancement

After processing all transactions, the circuit attempts to advance the L2 state. It checks if the next sequencer commitment index has a verified state transition whose initial state root matches the current L2 state root. If so, it updates:

* The L2 state root to the transition's final state root
* The last L2 height
* The last sequencer commitment index

This advancement continues for as many consecutive verified transitions as available, ensuring the L2 state only advances through cryptographically verified state transitions that form a continuous chain from genesis.

#### Output

The circuit output contains:

* `l2_state_root`: The verified L2 state root
* `lcp_state_root`: Root of the circuit's JMT, committing to all accumulated data
* `light_client_proof_method_id`: The verification key of this proof, used to ensure the next proof verifies against the same circuit version
* `latest_da_state`: Bitcoin chain state (block hash, height, total work, difficulty parameters)
* `last_l2_height` and `last_sequencer_commitment_index`: Progress markers

By the time a proof is generated for block height `h`, every Citrea transaction from the initial Bitcoin block to `h` has been extracted, verified for sender authorization, and processed. The `lcp_state_root` cryptographically commits to this complete history. The [Clementine bridge](https://github.com/chainwayxyz/citrea-docs/blob/main/essentials/clementine-bridge.md) uses this proof to obtain the verified L2 state root, which it then uses to validate withdrawal claims via storage proofs.

## References

* [SegWit Commitment - BIP 141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)
* [Citrea bitcoin-da crate](https://github.com/chainwayxyz/citrea/tree/nightly/crates/bitcoin-da)


# Reorg Handling

This page outlines how Citrea handles blockchain reorganizations (reorgs). To ensure data consistency, Citrea implements specific checks at both layers:

1. **L1 (Bitcoin) Reorgs:** How the system detects and recovers from Bitcoin reorgs that could affect validity proofs or data availability.
2. **L2 (Citrea) Reorgs:** How the protocol defends against malicious sequencers attempting to rewrite Citrea's history.

These defenses guarantee that the rollup state tracks Bitcoin's finality without compromising user funds.

## L1 - Bitcoin Reorg Handling

Citrea currently has 4 types of nodes, [sequencer](/essentials/architecture-and-transaction-lifecycle#sequencer), [batch prover](/essentials/architecture-and-transaction-lifecycle#batch-prover), [full node](/essentials/architecture-and-transaction-lifecycle#full-nodes), and [light client prover](/essentials/architecture-and-transaction-lifecycle#light-client-prover). All of these nodes scan every Bitcoin block starting from a pre-configured block number up to a block with at least `n` number of confirmations, which is called the finality depth.

### Finality Depth

In Bitcoin, finality is probabilistic rather than deterministic - the more confirmations a block has, the exponentially harder it becomes to reverse. Finality depth (also called confirmation depth) is the number of blocks that must be built on top of a transaction's block before it's considered secure enough to be irreversible.

#### How Bitcoin Confirmations Work

When a transaction is included in a block, that block counts as confirmation 1. Each subsequent block adds another confirmation. The deeper a block is buried, the more computational work required to reorganize the chain.

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-af27872d7f1732e4e4a344190c42093d15b41326%2Fbitcoin-finality.png?alt=media" alt=""><figcaption><p>Bitcoin Finality</p></figcaption></figure>

For example, a transaction in block 896 has 5 confirmations if the chain tip is at block 900 (896, 897, 898, 899, 900).

#### Why Finality Depth Matters for Citrea

A blockchain reorganization (reorg) occurs when a competing chain becomes longer than the current chain, causing nodes to switch to the new chain:

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-8728b4c63f3d7c945e93a398ff309b381c29a382%2Fbitcoin-fork.png?alt=media" alt=""><figcaption><p>Bitcoin Fork</p></figcaption></figure>

**If Citrea had processed block 896 immediately**, it would have seen TX A. But after the reorg, TX A might not exist in the canonical chain at that position, causing state inconsistencies.

**Citrea only processes finalized blocks** that have sufficient confirmations, making it robust against L1 reorgs:

{% hint style="info" %}
This means that no Bitcoin block will be recorded in [Bitcoin Light Client Contract](/developer-documentation/system-contracts/bitcoin-light-client) unless it is finalized.
{% endhint %}

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-a9959d083f5eb7b735dab0432c89ed802e521e50%2Fbitcoin-last-processed.png?alt=media" alt=""><figcaption><p>Safe Processing with Finality Depth = 6</p></figcaption></figure>

#### Standard Confirmation Depths in Bitcoin

* **1 confirmation:** Sufficient for small, low-value transactions.
* **3 confirmations:** Medium security; widely used by exchanges and merchants for standard deposits.
* **6 confirmations:** The industry standard for high security and settlement finality (Citrea Mainnet default).
* **100 confirmations:** Coinbase Maturity. This is a Bitcoin protocol rule preventing miners from spending newly mined coins for 100 blocks.

{% hint style="info" %}
Probability of 6-block reorg: \~0.000001%
{% endhint %}

#### Citrea Finality Depth Configuration

Citrea's finality depth is configurable and varies based on the underlying Bitcoin network:

* **Mainnet**: 6 confirmations
* **Testnet4**: 100 confirmations

{% hint style="info" %}
**Note on Testnet4 Configuration**: Bitcoin's testnet4 exhibits significantly higher volatility in terms of blockchain reorganizations compared to mainnet. During early Citrea Testnet operation, the finality depth was initially set to 8 blocks. However, a [12-block reorganization occurred](https://x.com/citrea_xyz/status/1867578624284696669), prompting an increase to 30 blocks. Subsequently, a [30-block reorganization was observed](https://x.com/citrea_xyz/status/1896000393517449335), leading to the current configuration of 100 confirmations for testnet4. This behavior is related to Testnet4's [20-minute Exception Rule](https://bips.dev/94/#1:~:text=1.%2020%2Dminute%20Exception%20Rule), which allows for reduced difficulty under specific conditions.
{% endhint %}

### Handling Deep Reorganizations

While deep reorganizations beyond the finality depth are extremely rare (probability of 6-block reorg: \~0.000001%), they can still occur and have occurred in the past on Testnet4.

{% hint style="warning" %}
**Manual Process**: Handling deep reorganizations is not automated. When a deep reorg is detected, the Citrea team coordinates the recovery process and provides specific instructions to node operators.
{% endhint %}

When a deep reorganization occurs, the recovery process works as follows:

1. **Detection**: The Citrea team detects that a reorganization has exceeded the configured finality depth
2. **Communication**: The team announces the incident and provides rollback instructions to all node operators via official channels
3. **Manual Rollback**: Node operators execute the provided rollback commands to restore their node's state to the last consistent checkpoint before the affected blocks
4. **Reprocessing**: After rollback, nodes reprocess blocks from the canonical Bitcoin chain

For example, if a 7-block reorganization occurred on Bitcoin mainnet (where Citrea uses 6-block finality depth), the Citrea team would detect the issue, publish rollback commands, and coordinate with independent full node operators to execute the recovery. This manual coordination ensures network-wide consistency and maintains the integrity of the rollup state relative to Bitcoin's canonical chain.

## L2 - Native Reorg Handling

### Centralized Sequencer Architecture

Citrea **currently** utilizes a centralized sequencer as the sole authority for transaction ordering and block production. Under normal operation, this design makes L2 reorganizations impossible.

However, **Citrea does not rely solely on the sequencer's honesty**; the system includes multiple security mechanisms to protect users in the event of a compromised sequencer.

### Security Against Malicious Sequencer

Citrea's architecture ensures that even a compromised sequencer cannot force full nodes to accept invalid state transitions through two complementary verification mechanisms.

#### 1. Invalid L2 State Transitions

Full nodes independently execute every transaction in every L2 block. Any block containing an invalid state transition is immediately rejected by the network, preventing the sequencer from enforcing an incorrect state.

#### 2. Sequencer Commitment Verification

Full nodes rely on [sequencer commitments](/essentials/architecture-and-transaction-lifecycle#4-sequencer-commitments-on-bitcoin) published to Bitcoin to verify the canonical L2 chain. Verification involves:

* **Merkle root Validation:** Calculating the Merkle root of received blocks and comparing it to the published commitment to detect **malicious modifications, tampering, inconsistencies**.
* **Sequential index:** Ensuring commitment indices are strictly sequential; preventing any gaps in the history.
* **L2 end block number:** Verifying that each commitment's start block strictly follows the previous commitment's end block.

This prevents the sequencer from building a different chain than what it broadcasts to full nodes, rewriting history, or publishing different block histories to different parties.

#### Batch Proof Validation

[Batch proofs](https://www.blog.citrea.xyz/citreas-batch-proofs/) are Groth16 zero-knowledge proofs that cryptographically verify state transition correctness. The batch proof circuit validates:

* **Block signatures** using the sequencer's public key
* **Chain continuity** via `prev_hash` verification between consecutive blocks
* **State transitions** by applying all L2 blocks through the State Transition Function (STF) and verifying state roots match
* **Storage integrity** using Jellyfish Merkle Tree (JMT) proofs for all storage accesses
* **Commitment consistency** by recalculating Merkle roots and verifying they match published commitments
* **L1 anchoring** by committing to the last Bitcoin hash in the [Bitcoin Light Client contract](/developer-documentation/system-contracts/bitcoin-light-client), preventing the L2 from claiming validity on a forked Bitcoin chain

**Key constraint:** The circuit's mathematical constraints make it impossible to generate a valid proof for invalid state transitions (e.g., unauthorized token mints or invalid transfers). If a malicious sequencer publishes invalid blocks, batch proof generation will fail.

Full nodes extract batch proofs from Bitcoin, verify their cryptographic validity, and confirm the outputs match their local state. Any mismatch results in proof rejection.

### Security Against Malicious Batch Prover

The batch prover is an untrusted entity, strictly bound by the ZK circuit's logic. Even if an attacker controls the prover, they cannot compromise the network's safety due to:

* **Mathematical Soundness:** It is computationally infeasible to generate a valid ZK proof for an invalid state transition. The circuit constraints simply will not be satisfied.
* **Input Integrity:** The prover cannot modify block data. Any change to the transaction data would alter the Merkle root, causing the proof verification to fail against the published commitment.
* **Strict Ordering:** The protocol enforces sequential processing. The prover cannot skip batches or rearrange history; it must prove the exact sequence defined by the sequencer.

### Bitcoin as the Canonical Trust Anchor

Citrea's security model is strictly anchored to Bitcoin finality. The system treats L2 state as canonical **only** after the corresponding proofs and commitments are finalized on Bitcoin (e.g., 6 confirmations on Mainnet). This applies to all network participants:

* **Full Nodes:** Reject any alternative chain proposed by the sequencer if it conflicts with the history already finalized on Bitcoin. This prevents "private chain" attacks or deep L2 reorgs.
* **Light Client Prover:** Transitions state solely based on finalized batch proofs. Each proof verifies against the previous finalized output, ensuring a verifiable state history back to genesis.
* [**Clementine Bridge**](/essentials/clementine-trust-minimized-bitcoin-bridge)**:** Enforces finality in the challenge-response mechanism. A proof anchored to a Bitcoin block with insufficient confirmations (e.g., 1 confirmation) is invalid, preventing theft via shallow forks or reorg attacks.

In short, while L2 actors (sequencers, provers) operate in real-time, they cannot alter history once it is finalized on Bitcoin.


# Citrea Mempool

As a Type-2 zkEVM rollup, Citrea inherits its transaction pool architecture from [Reth](https://github.com/paradigmxyz/reth/), the high-performance Ethereum execution client. This page explains how the Citrea mempool works, its architecture, and key differences from the standard Reth implementation.

## Architecture Overview

Citrea uses a **dual-mempool architecture**:

1. **Main Transaction Mempool**: Handles regular EVM transactions using Reth's transaction pool
2. **Deposit Data Mempool**: A separate FIFO queue specifically for Bitcoin deposit transactions

### Reth Transaction Pool Foundation

The main mempool is built on Reth's `Pool` type with the following components:

| Component      | Implementation            | Purpose                                           |
| -------------- | ------------------------- | ------------------------------------------------- |
| **Validator**  | `EthTransactionValidator` | Validates transactions against current state      |
| **Ordering**   | `CoinbaseTipOrdering`     | Orders transactions by effective tip/priority fee |
| **Blob Store** | `NoopBlobStore`           | EIP-4844 blob storage (disabled)                  |

## Sub-Pool Structure

[Reth's transaction pool](https://reth.rs/docs/reth_transaction_pool/index.html) uses a three-layer sub-pool model that Citrea inherits:

### Pending Sub-Pool

Contains transactions that are ready for immediate block inclusion:

* Nonce matches the account's next expected nonce
* Balance covers gas costs and value
* Gas price meets the current base fee

### Base-Fee Sub-Pool

Holds transactions that are valid but currently below the base fee:

* Transactions move here when base fee increases
* Automatically promoted to pending when base fee drops

### Queued Sub-Pool

Stores transactions that cannot yet be executed:

* Nonce gaps exist (waiting for earlier transactions)
* Insufficient balance (waiting for deposits)

Transactions automatically move between sub-pools as conditions change. When a nonce gap is filled, queued transactions are promoted. When base fee changes, transactions shift between pending and base-fee pools.

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-217898816c6b07ccdfcfcdff1f44684fce43f716%2Freth-pool-diagram.png?alt=media" alt=""><figcaption><p>Simplified Reth Transaction Pool Architecture</p></figcaption></figure>

## Transaction Validation

### Stateless Validation

Before entering the pool, transactions undergo stateless checks:

* Transaction type is supported for the current fork
* Input data does not exceed limits
* Gas limits and fee requirements are met
* Chain ID matches
* Intrinsic gas calculations are valid

### Stateful Validation

Additional checks against the current blockchain state:

* Sender account has no bytecode (unless EIP-7702 delegated)
* Nonce is greater than or equal to account nonce
* Balance covers value plus gas costs

### Citrea-Specific Validation

Citrea adds additional validation rules:

**System Transaction Filtering**: Transactions signed by the system signer are rejected from user submissions. System transactions are reserved for internal operations like Bitcoin light client updates and bridge deposits.

**EIP-4844 Blob Transactions**: Explicitly disabled on Citrea. Blob transactions are rejected at submission time.

**L1 Fee Validation**: Transactions must have sufficient balance to cover [L1 data availability fees](/advanced/fee-model#l1-data-availability-fee). Transactions failing L1 fee validation during block production are evicted from the mempool.

## Transaction Ordering

Citrea uses `CoinbaseTipOrdering`, which orders transactions by their effective tip:

```
effective_tip = priority_fee + max_fee_per_gas - base_fee
```

This creates MEV-resistant ordering similar to Ethereum's approach. Only the pending pool uses priority-based ordering for block production; other pools use different sorting criteria (base-fee pool by fee, queued pool by nonce distance).

## Configuration

Citrea's mempool is configured with **significantly larger limits** than standard Reth defaults to handle high throughput from the 2-second block time:

| Parameter         | Citrea Default | Standard Reth |
| ----------------- | -------------- | ------------- |
| Pending TX Limit  | 100,000        | \~10,000      |
| Pending TX Size   | 200 MB         | \~20 MB       |
| Queued TX Limit   | 100,000        | \~10,000      |
| Queued TX Size    | 200 MB         | \~20 MB       |
| Base-Fee TX Limit | 100,000        | \~10,000      |
| Base-Fee TX Size  | 200 MB         | \~20 MB       |
| Max Account Slots | 64             | 64            |
| Max TX Lifetime   | 3 hours        | 3 hours       |

### Environment Variables

| Variable            | Description                               |
| ------------------- | ----------------------------------------- |
| `PENDING_TX_LIMIT`  | Maximum transactions in pending sub-pool  |
| `PENDING_TX_SIZE`   | Maximum MB in pending sub-pool            |
| `QUEUE_TX_LIMIT`    | Maximum transactions in queued sub-pool   |
| `QUEUE_TX_SIZE`     | Maximum MB in queued sub-pool             |
| `BASE_FEE_TX_LIMIT` | Maximum transactions in base-fee sub-pool |
| `BASE_FEE_TX_SIZE`  | Maximum MB in base-fee sub-pool           |
| `MAX_ACCOUNT_SLOTS` | Guaranteed slots per account              |

## Eviction Policies

Transactions are evicted from the mempool when:

1. **Size limits exceeded**: When a sub-pool exceeds its transaction count or size limit, the lowest-priority transactions are removed
2. **Lifetime exceeded**: Non-executable transactions older than 3 hours are removed
3. **Account slot limit**: If an account exceeds its guaranteed slots, lowest-priority transactions from that account are evicted
4. **L1 fee failure**: Transactions that fail L1 fee validation during dry-run are removed

## Deposit Data Mempool

Citrea maintains a separate mempool for Bitcoin deposit transactions with different characteristics:

| Aspect     | Main Mempool      | Deposit Mempool                      |
| ---------- | ----------------- | ------------------------------------ |
| Ordering   | Priority (by fee) | FIFO (first-in-first-out)            |
| Validation | EVM rules         | ABI decoding + Bitcoin TX validation |
| Duplicates | By hash           | By Bitcoin TX ID (SHA256)            |

Deposit transactions are processed in order of arrival, not by fee, ensuring fair treatment of bridge deposits.

## Block Production Flow

During block production, the sequencer:

1. **Fetches best transactions** from the mempool based on current base fee
2. **Dry-runs each transaction** against the block state
3. **Validates L1 fees** and removes failing transactions
4. **Builds the block** with successful transactions
5. **Notifies the mempool** of included transactions for removal
6. **Triggers maintenance** to update account states and promote/demote transactions

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-31017ac9cb75cbf2f02b18b3945c95fd7c194c11%2Fsequencer-tx-flow-diagram.png?alt=media" alt=""><figcaption><p>Sequencer Block Production Flow</p></figcaption></figure>

## Mempool Maintenance

A background maintenance task runs continuously to keep the mempool consistent:

* **Account state updates**: Reloads nonces and balances after new blocks
* **Transaction promotion**: Moves newly-executable transactions to pending
* **Transaction demotion**: Moves no-longer-executable transactions to queued
* **Expiration cleanup**: Removes transactions exceeding the lifetime limit

## RPC Methods

### Standard Ethereum Methods

| Method                     | Description                              |
| -------------------------- | ---------------------------------------- |
| `eth_sendRawTransaction`   | Submit a transaction to the mempool      |
| `eth_getTransactionByHash` | Get transaction from mempool or chain    |
| `txpool_content`           | View all pending and queued transactions |

### Citrea-Specific Deposit Data Mempool RPC Method

| Method                             | Description                                                                                                   |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `citrea_sendRawDepositTransaction` | Submit a [deposit transaction](/developer-documentation/system-contracts/bridge#deposit-flow) with validation |

## Key Differences from Standard Reth

| Aspect              | Standard Reth  | Citrea                                |
| ------------------- | -------------- | ------------------------------------- |
| Pool Size           | Default limits | 10x larger capacity                   |
| Blob Transactions   | Supported      | Disabled                              |
| System Transactions | Not filtered   | Rejected from RPC                     |
| Deposit Handling    | N/A            | Separate FIFO mempool                 |
| L1 Fee Validation   | N/A            | Custom validation and eviction        |
| Persistence         | In-memory      | Stored in LedgerDB for crash recovery |


# Security Council

The Security Council is a trusted group responsible for safeguarding Citrea and [Clementine](/essentials/clementine-trust-minimized-bitcoin-bridge) operations. It is not a governance body but a security-critical role focused on bridging, vault operations, and system upgrades.

## Composition

The Security Council consists of **5 members** operating under a **3-of-5 multisignature scheme**. At least three members must provide verifiable signatures for any action to be valid.

The majority of the security council operates independently from Chainway Labs, ensuring developers cannot unilaterally control Citrea.

## Responsibilities

The Security Council has authority over critical operations on both Bitcoin L1 and Citrea L2.

### Clementine Side (L1)

**Clementine Spending Paths**

* The Security Council controls one of the spending paths for all L1 deposits processed by the Clementine N-of-N multisig
* In case of signer changes or emergencies, it can spend and send a replacement deposit to a new vault address

**Vault Management**

* Upgrading vaults that store BTC deposited into Citrea during emergencies or planned upgrades
* Receiving and storing BTC in case of an emergency; funds are held until the emergency is resolved and a replacement deposit is sent

**Bridge Signer Management**

* Adding and removing bridge signers and migrating control to a new N-of-N signer set if existing members are unavailable or compromised

#### Replacement Deposits

A replacement deposit is a Security Council-created deposit that replaces an old move-to-vault transaction when the system needs to update the deposit covenant on-chain. It is not created by users. Instead, it is constructed by the Security Council and commits to the *old* move-to-vault transaction ID inside the deposit script (the `citreaReplace` tag plus `old_move_txid`). This links the new deposit to the previous move transaction, which is useful for the Citrea contract to identify which move transaction is being replaced, while using the new verifier N-of-N key so the current verifiers can sign again.

Replacement deposit outputs have two spend paths:

* The replacement deposit script (the aggregated MuSig2 verifier key for the current signer set)
* The Security Council's m-of-n multisig path. The old move-to-vault output being replaced is spent via the Security Council multisig to fund the replacement deposit.

#### When Replacements Happen

Replacement deposits are used in these situations:

* **Bridge issues / upgrades:** If a bug is discovered or design changes are made to Clementine or Citrea, funds are moved by the Security Council to a new deposit that encodes the updated rules. This is the primary "upgrade" mechanism for deposits on-chain.
* **Signer changes:** If the verifier (signer) set changes, the old N-of-N key may no longer be usable. The Security Council creates a replacement deposit that updates the N-of-N key while keeping a link to the old move transaction.

#### Emergency Stop Flow

An emergency stop transaction provides a fallback mechanism in the event that a soundness bug is identified, allowing operations to be temporarily paused while the issue is addressed. Once a fix is in place, a replacement deposit transaction is submitted to resume normal operation.

The emergency stop path is a two-step flow:

1. An emergency stop transaction spends the move-to-vault output and sends funds to a Security Council-controlled multisig output.
2. The Security Council then creates and signs a replacement deposit transaction that spends that emergency stop output to create a new replacement deposit output.

### Citrea Side (L2)

**System Contract Upgrades**

* Upgrading the [Bridge system contract](/developer-documentation/system-contracts/bridge)
* Upgrading the [Fee Vaults](/developer-documentation/system-contracts/fee-vaults) contracts
* Upgrading the [Bitcoin Light Client](/developer-documentation/system-contracts/bitcoin-light-client) contract
* Changing parameters in system contracts during emergencies or planned upgrades

**Method ID Updates**

* Updating the batch prover circuit Method ID stored on Bitcoin when the ZK circuit changes (for security fixes or planned upgrades)

#### Method ID Updates

The Method ID is the cryptographic identifier of the batch prover ZK circuit. When the circuit changes (due to security fixes or upgrades), the Security Council must update the Method ID on Bitcoin.

#### How It Works

Method ID updates are published to Bitcoin as a special inscription transaction type (`BatchProofMethodId`). Unlike regular transactions signed by a single sequencer or prover key, these transactions contain:

1. **Body**: The new Method ID, activation L2 height, and chain ID
2. **Security Council signatures**: Exactly 3 EIP-191 signatures from council members
3. **Public key indices**: Index (0-4) identifying which council member signed

```
┌──────────────────────────────────────────────┐
│         BatchProofMethodId Transaction       │
├──────────────────────────────────────────────┤
│  Body:                                       │
│    - method_id (ZK circuit identifier)       │
│    - activation_l2_height                    │
│    - chain_id                                │
│                                              │
│  Security Council Data (3 entries):          │
│    - (signature_1, pubkey_index_1)           │
│    - (signature_2, pubkey_index_2)           │
│    - (signature_3, pubkey_index_3)           │
└──────────────────────────────────────────────┘
```

#### Verification in the ZK Circuit

The Security Council's 5 public keys are **hardcoded in the ZK circuit** at compile time for each network. When verifying a Method ID update, the circuit performs the following checks:

1. **Activation height check**: The new activation L2 height must be greater than the last known activation height (prevents replay attacks)
2. **Chain ID validation**: The `chain_id` in the transaction must match the network's chain ID (prevents cross-network replay attacks)
3. **Index validation**: Each public key index must be between 0-4 (in correspondence with the signer set)
4. **Ascending order check**: Indices must be in strict ascending order to prevent duplicate signatures from the same member
5. **Signature verification**: Each signature is verified using EIP-191 standard against the hardcoded public key at that index
6. **All-or-nothing**: If any single check fails, the entire update is rejected

<figure><img src="https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-27d3899ecf339d1fa58869c675feef9daa8aad4a%2Fmethod-id-update-verification.png?alt=media" alt=""><figcaption><p>Batch Proof Method ID Update Transaction Verification</p></figcaption></figure>

#### Network Chain IDs

Each Citrea network has a unique chain ID used for Method ID validation:

| Network | Chain ID |
| ------- | -------- |
| Mainnet | 4114     |
| Testnet | 5115     |

This design ensures that only legitimate updates signed by at least 3 distinct council members can modify the batch prover Method ID, and prevents replay attacks across networks or from historical transactions.

## Trust Model

The Security Council represents a trusted component in Citrea's security model

As Citrea evolves, the goal is to minimize reliance on trusted parties through cryptographic and protocol-level guarantees. The Security Council serves as a practical security mechanism during the early phases of the network.


# Clementine Signers

[Clementine](/essentials/clementine-trust-minimized-bitcoin-bridge), Citrea's trust-minimized Bitcoin bridge, relies on a set of **Signers** (also called **Verifiers**) to secure the bridge. These entities pre-sign the allowed spend rules, emulating covenant-like restrictions on Bitcoin. As long as one signer remains honest, funds can only move along Clementine's approved paths.

{% hint style="info" %}
In Clementine, the terms "Signer" and "Verifier" are often used interchangeably. These entities participate in the MuSig2 signing protocol to secure deposits and enable withdrawals.
{% endhint %}

## Role of Signers

Signers are a committee of N participants that:

* **Pre-sign allowed spend rules** - Funds can only move along Clementine's approved paths if at least one signer is honest
* **Participate in MuSig2 aggregation** - Sign `MoveToVault` transactions that move deposits into the bridge vault
* **Enable optimistic payouts** - When all signers are online, they can directly sign withdrawals without operator involvement
* **Monitor the bridge** - Signers also function as [watchtowers and challengers](/essentials/clementine-trust-minimized-bitcoin-bridge#roles-and-responsibilities)

{% hint style="success" %}
The bridge uses an N-of-N signing scheme for deposits, functioning as a key deletion covenant. This means the bridge remains secure as long as **at least one** signer's key is secure.
{% endhint %}

## Mainnet Signers

The following entities operate as Clementine signers on Citrea mainnet:

### Chainway Labs

Chainway Labs is the core development team behind Citrea and operates as both a verifier and operator.

| Property   | Value                                                                |
| ---------- | -------------------------------------------------------------------- |
| Website    | [citrea.xyz](https://citrea.xyz)                                     |
| Public Key | `024ebf6626277c974726217b20bae9fc088e7f66a530b5ea21d0d1650513a99fb0` |

***

### Galaxy

Galaxy Digital is a leading digital asset and blockchain company providing institutional-grade financial services.

Galaxy operates as both a verifier and operator.

| Property   | Value                                                                |
| ---------- | -------------------------------------------------------------------- |
| Website    | [galaxy.com](https://www.galaxy.com)                                 |
| Public Key | `02b0895dc582479793abb442d77e0f71bc040a7400eedb52ad4d1ce1e200be0560` |

***

### Coinsummer

Coinsummer provides blockchain infrastructure and validation services.

| Property   | Value                                                                |
| ---------- | -------------------------------------------------------------------- |
| Website    | [coinsummer.io](https://coinsummer.io)                               |
| Public Key | `0338c5e8932ed6b084f163a6d7a2b9a0af95f57d07c4c69567c0544e7fbfd93b98` |

***

### Omakase

Omakase is a professional node operator providing infrastructure services for blockchain networks.

| Property   | Value                                                                |
| ---------- | -------------------------------------------------------------------- |
| Website    | [0xmakase.co.jp](https://0xmakase.co.jp)                             |
| Public Key | `034c027c18a980c76b55a99d015cb0c845eb8875f2a403ff957b7e266d0aa66e1d` |

***

### Nansen

Nansen is a blockchain analytics platform that also provides staking and infrastructure services.

| Property   | Value                                                                |
| ---------- | -------------------------------------------------------------------- |
| Website    | [nansen.ai](https://www.nansen.ai)                                   |
| Public Key | `02c585eb3acfff97b5d1caf73368cb9e0139fd6c42ebe4b13c68d24e9e77d9d7c7` |

***

### Nethermind

Nethermind is a blockchain research and software engineering company known for building Ethereum clients and infrastructure.

| Property   | Value                                                                |
| ---------- | -------------------------------------------------------------------- |
| Website    | [nethermind.io](https://www.nethermind.io)                           |
| Public Key | `02582cb654c6ccc6fb4cd11a6c88af83a961b918385e9f30411ca94b5395e75048` |

***

### Laminated Labs

Laminated Labs provides professional validator and infrastructure services for blockchain networks.

| Property   | Value                                                                |
| ---------- | -------------------------------------------------------------------- |
| Website    | [laminatedlabs.net](https://laminatedlabs.net)                       |
| Public Key | `0310cc0687c18427ade30226629c30b1de5c6e714b261c4909172a6e4797f5bd51` |

***

### Hashkey Cloud

Hashkey Cloud is the infrastructure arm of HashKey Group, providing institutional-grade staking and validation services.

| Property   | Value                                                                |
| ---------- | -------------------------------------------------------------------- |
| Website    | [hashkey.cloud](https://www.hashkey.cloud)                           |
| Public Key | `025668e399d27f0b799ed8e87c3cdb2c142c12afe97d252bcb338be6146378f526` |

***

### Finoa

Finoa is a regulated digital asset custodian providing secure storage and staking services for institutional clients.

| Property   | Value                                                                |
| ---------- | -------------------------------------------------------------------- |
| Website    | [finoa.io](https://www.finoa.io)                                     |
| Public Key | `03e4674d0c2091c7f408c93ea5e5d94ee231c563cecc714c24da9cd37b24b22104` |

***

### Luxor

Luxor is a Bitcoin mining company and hashrate provider that also operates validation infrastructure.

| Property   | Value                                                                |
| ---------- | -------------------------------------------------------------------- |
| Website    | [luxor.tech](https://luxor.tech)                                     |
| Public Key | `03296b46f3f622d4d7f004c7c5b10f77fe3e6384358f87606ebe41b14919f7211b` |

***

## Aggregated Public Key

All signer public keys are aggregated using MuSig2 to form a single N-of-N aggregated key that controls the bridge vault.

Mainnet signer set public keys:

```
024ebf6626277c974726217b20bae9fc088e7f66a530b5ea21d0d1650513a99fb0
02b0895dc582479793abb442d77e0f71bc040a7400eedb52ad4d1ce1e200be0560
0338c5e8932ed6b084f163a6d7a2b9a0af95f57d07c4c69567c0544e7fbfd93b98
034c027c18a980c76b55a99d015cb0c845eb8875f2a403ff957b7e266d0aa66e1d
02c585eb3acfff97b5d1caf73368cb9e0139fd6c42ebe4b13c68d24e9e77d9d7c7
02582cb654c6ccc6fb4cd11a6c88af83a961b918385e9f30411ca94b5395e75048
0310cc0687c18427ade30226629c30b1de5c6e714b261c4909172a6e4797f5bd51
025668e399d27f0b799ed8e87c3cdb2c142c12afe97d252bcb338be6146378f526
03e4674d0c2091c7f408c93ea5e5d94ee231c563cecc714c24da9cd37b24b22104
03296b46f3f622d4d7f004c7c5b10f77fe3e6384358f87606ebe41b14919f7211b
```

the N-of-N aggregated key:

```
70458db6f75b129ad93878e7781eeb9ba24bf4bbd498d6a9d3f27827b25c8f81
```

### Verify the musig2 aggregated key

You can verify the musig2 aggregated key using [Clementine CLI](/essentials/using-clementine/clementine-cli), with the following command:

```
clementine-cli musig2-key-aggregation 024ebf6626277c974726217b20bae9fc088e7f66a530b5ea21d0d1650513a99fb0,02b0895dc582479793abb442d77e0f71bc040a7400eedb52ad4d1ce1e200be0560,0338c5e8932ed6b084f163a6d7a2b9a0af95f57d07c4c69567c0544e7fbfd93b98,034c027c18a980c76b55a99d015cb0c845eb8875f2a403ff957b7e266d0aa66e1d,02c585eb3acfff97b5d1caf73368cb9e0139fd6c42ebe4b13c68d24e9e77d9d7c7,02582cb654c6ccc6fb4cd11a6c88af83a961b918385e9f30411ca94b5395e75048,0310cc0687c18427ade30226629c30b1de5c6e714b261c4909172a6e4797f5bd51,025668e399d27f0b799ed8e87c3cdb2c142c12afe97d252bcb338be6146378f526,03e4674d0c2091c7f408c93ea5e5d94ee231c563cecc714c24da9cd37b24b22104,03296b46f3f622d4d7f004c7c5b10f77fe3e6384358f87606ebe41b14919f7211b
```

## Security Model

The signer set provides the following security guarantees:

* **1-of-N Honesty**: The bridge is secure as long as at least one signer remains honest
* **Covenant Emulation**: Pre-signed transactions ensure funds can only move along approved paths
* **No Single Point of Failure**: Multiple independent entities from different jurisdictions operate the signer set
* **M-of-N Upgrade Path**: A separate M-of-N multisig can update the N-of-N set if needed.

{% hint style="info" %}
While the N-of-N scheme provides strong security, it requires all signers to be available for certain operations like optimistic payouts. If a signer is unavailable, the protocol falls back to operator-assisted withdrawals.
{% endhint %}

## Related Resources

* [Clementine: Trust-Minimized Bitcoin Bridge](/essentials/clementine-trust-minimized-bitcoin-bridge)
* [Clementine CLI](/essentials/using-clementine/clementine-cli) - Command-line tool for deposits and withdrawals
* [Clementine Whitepaper](https://citrea.xyz/clementine_whitepaper.pdf)
* [Clementine Source Code](https://github.com/chainwayxyz/clementine)


# Audits & Security

Below you may find the security audits and security-related information for Citrea.

## Audits

| Auditor                                                                                      | Scope                  | Date (publish) | Report                                                                                                                                               |
| -------------------------------------------------------------------------------------------- | ---------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| [SigmaPrime](https://sigmaprime.io/)                                                         | Citrea                 | July 2025      | [view](https://github.com/chainwayxyz/citrea/blob/nightly/audits/Sigma_Prime_Chainway_Citrea_Security_Assessment_Report_v2_2.pdf)                    |
| [SigmaPrime](https://sigmaprime.io/)                                                         | Clementine             | August 2025    | [view](https://github.com/chainwayxyz/clementine/blob/main/audits/Sigma_Prime_Chainway_Labs_Clementine_Security_Assessment_Report_v2_0.pdf)          |
| [Cantina Competition](https://cantina.xyz/competitions/49b9e08d-4f8f-4103-b6e5-f5f43cf9faa1) | Citrea                 | Oct 2025       | [view](https://github.com/chainwayxyz/citrea/blob/nightly/audits/cantina_competition_citrea_jul2025.pdf)                                             |
| [Cantina Competition](https://cantina.xyz/competitions/ce181972-2b40-4047-8ee9-89ec43527686) | Clementine             | Oct 2025       | [view](https://github.com/chainwayxyz/clementine/blob/main/audits/cantina-competition-report.pdf)                                                    |
| [Guardian](https://guardianaudits.com)                                                       | USDT.e & USDC.e Bridge | Oct 2025       | [view](https://github.com/chainwayxyz/token-bridge/blob/main/audits/Guardian_Chainway_Stablecoin_Bridge_Security_Assessment_Report.pdf)              |
| [OtterSec](https://osec.io)                                                                  | WBTC.e Bridge          | Sept 2024      | [view](https://github.com/LayerZero-Labs/Audits/blob/d98efc2e0c4e6d7137a30529d1e55a9df7a4fbfd/audits/LZ_WBTC-OFT-Conversion_OtterSec_23-Sept-24.pdf) |
| [Zellic](https://zellic.io)                                                                  | BitVM2                 | August 2025    | [view](https://github.com/BitVM/BitVM/blob/1f42f41c00d935988d87529e79e7d950d3bf9503/aduits/BitVM%20-%20Zellic%20Audit%20Report.pdf)                  |
| [Guardian](https://guardianaudits.com)                                                       | CTR & xCTR             | Feb 2026       | [view](https://static.citrea.xyz/audits/ctr-xctr-guardian.pdf)                                                                                       |
| [Sherlock](https://sherlock.xyz)                                                             | CTR & xCTR             | Feb 2026       | [view](https://static.citrea.xyz/audits/ctr-xctr-sherlock.pdf)                                                                                       |

Further audits of Citrea and Clementine will also be published on this page.

## Active Bug Bounties

| Bounty Location                                                                     | Scope                             | Date (start) | Maximum Bounty |
| ----------------------------------------------------------------------------------- | --------------------------------- | ------------ | -------------- |
| [HackenProof](https://hackenproof.com/programs/citrea-protocol-and-smart-contracts) | Citrea Protocol & Smart Contracts | Feb 2026     | $250,000       |
| [HackenProof](https://hackenproof.com/programs/citrea-web-and-apps)                 | Citrea Web & Apps                 | Feb 2026     | $25,000        |

***

## Security

For security related inquiries, please contact the Citrea security team by email with the following email address:

```
security@citrea.xyz
```

If the issue is sensitive, please encrypt your email using the provided GPG key:

<details>

<summary>Click here for the GPG Key</summary>

```
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBGhZQXgBEADs4X61A9OcXJ1vbsFwq/tCm8FVCjHx9KADZ7WRht4Tr/4tlrXP
VT7PeMjf97osh131ofq0i5fmumXSRHRTakn5hUJiIAGPQyaxJd6gXp3U9D8p2Q0S
xb/8sQmkncIqg1a1ZmUxekbBM0PXDePGMUVCFdpIFGiCh1QEES2Or2vI6PPwPFuA
VhAre+HGFnhIk0jtHqOntpviHuWx5Oqp7kmelvdvYqMAOjdWUYG7LUyykJc/xBvD
k9YLYHYa1ItWuQFHsR4GBraTrGOJ7sCgbkT4eneGBQRdwnhRxuWWsDyC5BKT2mq1
RmhVMd4RmYdmmvlIk9ACOGHRDV4Hi7ymZTgCH1DOhBDHoTHtq4SKUsFHh0+BnZZH
PNGOnw3fRq8mC6tOrBQrf1/iTWPoM3i6hZlBWKdhQf0mwuF5DAo5mvYXc2RUUwY/
pfYWjiEr+ItanJrzkLPDMedPdMbAW/87CpAKoGkMeg6CmftQgPE30Ksue3b6HExz
wrHIrqqD8JqWxwLIp0eMkh7soMp1avFCUOx57c1hXP3bqGEX9AABur4b3MyIp2QZ
jeyzmXc+3Z4XYZpJz98YRiiQQBkOZ+eZgrTPq7JoQ8gG8GnngEmPY67Ak+dWtRNR
hSJb3mQHwrveoX1aRp7+wtsWpIqplxdEulg7LqHDHyHAYN+h2sO8JPdvhQARAQAB
tCVTZWN1cml0eSBDaXRyZWEgPHNlY3VyaXR5QGNpdHJlYS54eXo+iQJOBBMBCAA4
FiEEJrjWfVY4H6mv/nsGxnvc0y/0jG4FAmhZQXgCGwMFCwkIBwIGFQoJCAsCBBYC
AwECHgECF4AACgkQxnvc0y/0jG4cdA//V/FR/n1aA58VTOY2Rsf/ou45Dc4SRihJ
PO0fMtsbtKGGEopYob522hUlEqxvq4Kw1g73PXjlhFMD8Qvne/yoKJ9plsKbd121
DZ9aSGoycAoaFzDX1zUJfSUaEuGu7V6wymdRz48/gC+zQw0gPCE+Muf/Bd7ZNOui
wNoBPSRWG/3Z1pyaAqjAHlRHQ+T9ue7veqVxHQUkQy4nz2kOsHLu4g/LUNjvtqC8
h4MweQbzyvgjULZkZZYjpWaRtgwCqqhvho46AwVcZ2HOSj+xRc0TQUvx3h74I4vO
vvjZQymIkp0bCQ8muemiZeMpolXh6YH3rWir1Xi72ljgJMI38PD1cd1QlLaFGuoL
yLPTUNUwOmrRI7gDLeyL5LbxvfojGDhpmiGeMQEHYj3fGFEmBjX4yZTsX+ZmQTHC
NH8X8aDFcHMhKxnntUj4O+qWHwSqY72NtKvJhfOZwZUNBH6/zHElyZbHftV2jbKB
QRPrPBmA9qcV91d6IwDrTKUr0xOGJCY9MtATlkSFpfCYxGGgPPw028QlNUlpVG1A
KV79kpYJJPZKF3iFgu00T8PSoAbQvosVCDytb7cYZfdFW51xUZ4T7Lg8Ll/NgX/X
nEcc9Z5NvKUkZZ6R30Pj4rzwIsIPoZaDumkJw9GF7LRArurgyl1e0jAkDk4uwzFE
Jijf9586ypi5Ag0EaFlG3wEQALcC3wL/hBNWvjx51Wl7zRUwr3tJFjKZ4rQrJzII
zsj+R9BZOAvp3Uo/WK4m0oAWLeqhP37m7vn0zoWJzZrOjX5NhuaGNyo3bCBlFvLV
p6R+NyamPqVutSNBbh/Do3F15AdTKaQQidesrNzf0UuVk8wI6jCJKcJODCsdxA3Y
QaoF8uVB9Rcx5EktB5o44hJH78/a8tIZFM5VuesbRBxtItyDeIpG+VZZMAFqx740
B7PoOs/HUtvY683bfidH9EtV7sOMPgUnRMfyFgUTfQPdyOzrUF1h2G92bEupD35U
xiUT43X48UCZl6uOYScKa4/8ftpPmwdWBrBRkLbhI2wCOun/Kthdww03H738AuUa
JuJOBevuquH2ULjdZfHEj9Hqo32x1dbFueLfoR2Rp2nFlAGVyoTCsNxHVuXySSq6
kWZBFJi3e0R5+LkVV2tztn/9EBqYXKSRADhbR1BNdJbCMIAk9caLDnD7cPkiS3CQ
URQMz/G95InasXgGmBM6rno5dGhJZ3XD+mWPg/eRtvICYaVSo87rR60GEh36IvBe
kHIdxRkIyjZASbJI+f+00Lxk7D8ZmPZjQ+HrsaWOZq6FDRd9dM9OwFqk4MJBOAeI
1I76VDUsVH3rzeWmVs7vUWFMdFczY6xYpP7sJQkP26Res0rxTGSU5C80tiLcykqN
mECZABEBAAGJAjwEGAEIACYWIQQmuNZ9Vjgfqa/+ewbGe9zTL/SMbgUCaFlG3wIb
DAUJB4YfagAKCRDGe9zTL/SMbm33D/4rB3w9iXxRF9T1QUIfUajvZbWVGmbDFiZ1
XB0JI38EqgUKGm36ykyQbcfSeJKNgWBkOEEO8q9fw8EARkZPbv9fSDtW/3i5jNIW
ygSN36fAIaIUWcZ+Rnkl8C5/9cYIgZuwaWYBearlW75GPqGMNbW92U1GN93QWn3l
Q5/I474MJdHpQpGFOVnhitoLPqBxFOxhRoxSpMQaL8iozmAN7N5K002TcYt95JiO
rH2T3YgOdCnEbDAfpnpvWqMqBtu3ydXnLcHmVuuHJSCaE9tM/WcdUdiLHP9D4qZB
FxY9nFycgH9pYhPAvgSE/HM7HePx9kc22wJiXLzXviGIFYl40su+lzs4fuFMgC6E
c9Hj39reL85QaobPNJI+dcgpsVs0xsKROXPyZYQai8PayJJc1f1V+/tMS14ef7MM
LIYvMmi1uPFaRCFEHnA4onXkB52rYXt5acyrl24a5eDNZD/qRrrDKMqkgXrPrxHJ
23S73LUQFpvDQ+DA/fZor516H3HWHYro1nINLXwip1cX2e2AoaJFP+gWZ2HCypWZ
WkSRLz/cyZC1U7LdMA5Z3whFAwVcI91FHEgbMgdGTWGtNbeKOp5sDqIgmduxXzCu
6Ztsw6ECa11z3k977nN+56AKH/OdbrEtHu9lZLds8yglJpgp9JN7f54CadhxIozi
cXvJNNsO+w==
=0vMP
-----END PGP PUBLIC KEY BLOCK-----
```

</details>


# Trusted Setup Verification

[Clementine](https://docs.citrea.xyz/essentials/clementine-trust-minimized-bitcoin-bridge), Citrea’s BitVM‑based bridge, proves execution with RISCZero (STARK) and wraps those receipts in a Groth16 SNARK so that it can be verified on Bitcoin efficiently.

The **Citrea Risc0‑to‑BitVM trusted setup ceremony** establishes the public parameters for a Groth16 verifier that checks RISCZero STARK receipts via BitVM, enabling a single compact proof to be verified on Bitcoin without consensus changes and moving BitVM‑based bridges into their implementation phase.

***

Verification below matters to confirm the setup wasn’t manipulated and that Clementine points to the exact parameters produced. By rebuilding the circuit, fetching the precise Powers of Tau and final zkey, and checking the transcript, you can reproduce the commitments and compare them to the published parameter and verifying‑key hashes.

{% hint style="success" %}
This setup uses a similar methodology to RISCZero's Groth16 trusted setup. You can read more about the security details [here](https://dev.risczero.com/api/trusted-setup-ceremony).
{% endhint %}

A copy of the verification logs are available [on Github](https://gist.github.com/ekrembal/527f44c91736a511f6bfd61e01bc4f22).

You can also find each individual attestation by visiting gist pages of the contributors (unless it's removed/hidden by the contributor). An example can be found [here](https://gist.github.com/otaliptus/f35c53a3c9b68332321c61dcc0716a85).

***

The commands below show the exact steps for verification and should conclude with `snarkJS: ZKey Ok!`.

{% hint style="warning" %}
The verification requires more than 32 GB RAM (i.e. 64 GB RAM suffices).

Guide below is tested for Ubuntu 24.04.
{% endhint %}

### 1) Setup Circom & SnarkJS

```bash
# deps
sudo apt-get update
sudo apt-get install -y build-essential git npm

# Rust (for building circom)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
. "$HOME/.cargo/env"

# circom (v2.2.x)
git clone https://github.com/iden3/circom.git
cd circom
cargo install --path circom          # installs the 'circom' binary into ~/.cargo/bin
circom --version                     # sanity check (expect v2.2.x)
cd ..

# snarkjs
npm install -g snarkjs
snarkjs --version
```

### 2) Clone Citrea RiscZero to BitVM repository

```bash
git clone https://github.com/chainwayxyz/risc0-to-bitvm2
cd risc0-to-bitvm2
```

### 3) Install git-lfs and pull larger files in the repository

```bash
sudo apt-get install -y git-lfs
git lfs pull
```

### 4) Generate r1cs file

```bash
# circomlib (used by the circuit)
git clone https://github.com/iden3/circomlib.git

# compile the circuit -> verify_for_guest.r1cs
sed -i '$d' ./groth16_proof/circuits/stark_verify.circom
circom groth16_proof/circuits/verify_for_guest.circom --r1cs --O2

# (optional) shasum check of the r1cs you built
sha256sum verify_for_guest.r1cs
# c90be1fb4b83f8f10f4be51e47ebdde2fd97dacd60d658d63d6828f3f642a116
```

### 5) Install Powers of Tau and the final zkey

```bash
# download the exact artifacts used for the ceremony (10+ GB download)
wget https://pse-trusted-setup-ppot.s3.eu-central-1.amazonaws.com/pot28_0080/ppot_0080_23.ptau
wget https://static.mainnet.citrea.xyz/verify_for_guest_final.zkey

# (optional) check them, too
sha256sum ppot_0080_23.ptau verify_for_guest_final.zkey
# 05085994c8aa34e4925585202e178e09fb8acc04e9565311751e8a04dec81cb1  ppot_0080_23.ptau
# 86fc7478fce8b91b502538cc64e8295a104f68ecf025042a21b10b54d7d504c0  verify_for_guest_final.zkey
```

### 6) Run snarkJS for verification

```bash
# increase Node memory for large circuits
export NODE_OPTIONS="--max-old-space-size=32768"

# verify that the zkey transcript matches your r1cs and the ptau
# can take between 30 mins to hours depending on your system
snarkjs zkey verify verify_for_guest.r1cs ppot_0080_23.ptau verify_for_guest_final.zkey
```

You can also compare the result with [our published logs](https://gist.github.com/ekrembal/527f44c91736a511f6bfd61e01bc4f22).


# Decentralized Sequencer Network

A decentralized sequencer network is composed of multiple sequencers, each tasked with block production and transaction ordering according to the network’s algorithm. Citrea is a ZK Rollup that currently relies on a single sequencer, which provides strong security and non-custodial operation. However, it also introduces a single point of failure for liveness. Although censorship resistance can be achieved through force transactions, a decentralized sequencer network is ideal for addressing the liveness challenge by distributing responsibilities among multiple participants.

A few key challenges of decentralized sequencer networks are as follows:

* **Architecture**: Deciding the sequencer set (permissionless or not), modifying the architecture, determining the optimal consensus mechanism (e.g., CometBFT, Hotstuff, MonadBFT).
* **Latency**: Achieving consensus among multiple sequencers poses significant challenges due to the latency introduced by communication between sequencers. Ideally, a decentralized sequencer network should not introduce observable latency compared to the current implementation.
* **Economic Incentives**: The economic model should be designed to ensure that sequencers are rewarded for their work and penalized for misbehavior, for the network's security and liveness.

***

The concept is on the roadmap and active development & implementation will kick off after the mainnet launch.


# Lightning Integration

Trustless atomic swaps between Citrea and Lightning Network are being actively implemented at the moment through third-party applications, such as [Atomiq](https://testnet4.atomiq.exchange). This will allow users of Citrea to pay Lightning invoices directly from the Citrea network or on- and off-ramp from Citrea without needing to leverage the Bitcoin base layer.

For both swap directions, the smart contract on Citrea simply emulates Lightning's HTLC. An LP (Liquidity Provider) behaves as a proxy on Lightning and it is responsible for all cross-network interactions - with liquidity maintained on both sides.

![Lightning Atomic Swap Diagram](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-b6183bbcc524b2ccdfe8101bbf529814cbf9aefb%2Flightning_atomic_swap.png?alt=media)

For the path from Lightning to Citrea, here's a basic explanation:

* The receiver on the LN side creates an invoice and sends it to the sender on Citrea side.
* Sender locks cBTC on the HTLC contract with the invoice.
* LP makes the payment on LN on behalf of the sender.
* The preimage of the invoice gets revealed to the LP upon payment.
* LP uses the preimage to claim the cBTC from the HTLC contract.


# Multi Prover

Citrea uses ZK proofs to prove the validity of the state transitions. Full nodes verify the batch proofs produced by the prover. These batch proofs are also used to generate Light Client Proofs for the BitVM-based bridge Clementine.

An idea to make the proof generation process more resilient is to implement a multi-prover system. This approach increases the security as it reduces the chance of a single point of failure algorithm-wise in case there's a vulnerability in a proof system (e.g. soundness).

Currently Citrea has a template multi-prover system implemented using [RISC Zero](https://risczero.com) and [SP1](https://docs.succinct.xyz/docs/introduction). You can check the initial guest code implementation from [here](https://github.com/chainwayxyz/citrea/tree/nightly/guests).

As of Citrea Testnet, SP1 prover is not active, and we are only utilizing RISC Zero. After the mainnet launch, we are planning to activate SP1 prover with additional prover implementations for multi-prover system, with a possible SGX-extension.

***


# Multi VM Approach

Citrea is designed to be compatible and interoperable with multiple virtual machines. It runs inside a generic STARK zkVM, meaning any virtual machine can be implemented and will produce execution proofs. Citrea currently implements Ethereum Virtual Machine (EVM).

Implementing different VMs like SVM or integrating WASM-based smart contracts to Citrea is also possible thanks to its future-proof design. The objective in this approach is to build an environment where contracts can be written in multiple languages like Solidity (EVM) or Rust, C++ (WASM) and run & interact on the same blockchain, natively.

Two main methods that fit into this approach are:

* Integrating Arbitrum Stylus-like\* solutions to Citrea's EVM module: Essentially bringing a WASM execution model into the system.
* Building a Wasm-based sovereign module from scratch: A dedicated WASM execution environment needs to be built and integrated with custom precompiles.

***

The concept is quite experimental and it will be further researched after the mainnet launch.

* Arbitrum Stylus is under the BUSL License, and it is currently allowed for specific use cases in the Arbitrum Ecosystem. The term is used here to describe a similar approach, not the exact implementation.


# Trustless Atomic Swaps

Trustless atomic swaps allow users to on- and off-ramp between Citrea and Bitcoin without using the peg mechanism. They are implemented via third-party providers and are already live on Citrea Mainnet through services such as [Atomiq Exchange](https://app.atomiq.exchange/), which also supports Bitcoin Lightning routes (see [Bridge to Citrea](/welcome/bridge-to-citrea)).

A very basic atomic swap works as follows:

* A smart contract on Citrea is used to lock some amount of cBTC. This smart contract also utilizes BitcoinLightClient on Citrea to verify Bitcoin transactions on-chain (see below).
* User A locks some cBTC into the smart contract, and demands an equivalent amount of Bitcoin in return.
* Some User B sees the request, and locks the equivalent amount of Bitcoin into the desired address of User A in the Bitcoin network.
* Upon finalization of the transaction, user B can then submit the transaction details to the Atomic Swap smart contract on Citrea, which verifies the transaction and lets user B claim the locked cBTC.

Here's a basic diagram of the process:

![Basic Atomic Swap Diagram](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-702bc24b767e5b1416577f815188a8a152d5e6ae%2Fatomic_swap.png?alt=media)


# Trustless Settlement

In order to achieve trustless settlement for Citrea, there needs to be opcode change(s).

Mainly, an opcode that can verify ZK proofs and a [covenant opcode](https://covenants.info) would be required to implement completely trustless Bitcoin settlement. Specifically, it is theoretically possible to implement a trustless bridge using OP\_CAT opcode, if activated.

In the current architecture, BitVM/Clementine provides a trust-minimized settlement with 1-of-N honest minority trust assumption - which is a great improvement over the existing insecure implementations of sidechains. In case a suitable opcode is added to Bitcoin, Citrea will also adopt a cheaper/more secure/faster/trustless solution if possible.


# Volition Model

Volition is a special type of data availability solution that combines off-chain and on-chain data storage.

Traditionally, there are two categories of rollups regarding the data storage:

* **On-chain Data Availability** (e.g. Citrea): All transaction data / state diffs are stored on the L1 chain. Full nodes can simply scan L1 blocks to sync with the network. This is the most secure and trustless\* way to provide data for the network.
  * `Trustless` here is in the context of data only and it indicates that chain data is always available as long as the L1 chain is secure.
* **Off-chain Data Availability** (i.e. Validiums): All transaction data / state diffs are stored off-chain. Validiums are mostly cheaper than pure rollups; however, they rely on some other DA solutions and DACs. It introduces more trust assumptions to the system.

Volition, compared to two categories above, offers a hybrid approach - it allows users to choose where to publish transactions (or relevant data), and choose the security of on-chain data availability or the cost efficiency of off-chain data availability. There will be two states for two DA branches, and the latest Citrea state will be the combination of these two branches.

![Volition Model Diagram](https://4199298141-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtFU3ZD7rSzMi2uz6wz9W%2Fuploads%2Fgit-blob-cf96881fd7d69b2c5ba05be25b843a1e73ea2f09%2Fvolition.png?alt=media)

Regardless of the DA preference, all transactions will still be processed by the STF (State Transition Function), and will be verified via ZK proofs.

There are two major challenges in this direction:

a) Complexity: Volition implementation requires modifications to the Citrea STF and overall architecture, particularly in terms of sequencing, proving, and running full nodes.

b) Guarantees: For users who prefer to use an alternative DA branch, trust assumptions will be different as the off-chain DA solution does not provide the same trust assumptions as Bitcoin L1.

***

The concept is on the roadmap and it will be actively implemented after the mainnet launch upon more research.


# Citrea Meetups

Citrea is the first rollup that enhances the capabilities of Bitcoin blockspace with zero-knowledge technology. Citrea activates Bitcoin blockspace for developers to build decentralized applications and facilitates the most trust-minimized way to use BTC. As we work towards making Bitcoin the execution layer of global finance, we are grateful to have an incredible community that has supported us since day one.

With Citrea now live on Bitcoin mainnet, our development and community efforts are accelerating as we spread the word. This is the perfect opportunity for our community to share what Citrea brings to the world.

We’re excited to introduce **Citrea Meetups** — a series of community-organized events that will enable members to actively contribute to Citrea’s vision of making Bitcoin the foundation of the world’s finance.

{% hint style="info" %}
As a Citrea Meetup organizer, you will be expected to:

* Host Citrea Meetups and lead community initiatives in your local region
* Host local community in-person and attend virtual meetups
* Create resources and tooling
* Create high-quality and engaging content
* Make an impact within the Citrea ecosystem
  {% endhint %}

This guide aims to empower meetup organizers by providing education and support, and encouraging collaboration within Bitcoin and Citrea ecosystems. You can find more information in the following sections:

* [Meetup Guide](https://docs.citrea.xyz/community/community/meetup-guide)
* [Code of Conduct](https://docs.citrea.xyz/community/community/code-of-conduct)
* [Resources](https://docs.citrea.xyz/community/community/resources)

To become a Citrea Meetup organizer and contribute to the ecosystem, please read the links above first. Then, you can fill out the [application form](https://forms.gle/saqyYXqQLZksiQWG9). Citrea team will evaluate your application and get back to you shortly.


# Meetup Guide

Here's a short list for Citrea Meetup organizers to check regarding hosting a Citrea Meetup. Details & topics can be discussed further upon the application.

## Before the Meetup

1. Determine the meetup topic and agenda
2. Choose a date and time
3. Secure an accessible venue
4. Finalize the event schedule or agenda
5. Send out invitations (email, social media, community platforms)
6. Confirm speakers and their requirements
7. Arrange necessary equipment (microphones, projectors, whiteboards)
8. Plan refreshments, if applicable
9. Print required materials (agendas, name tags, feedback forms)
10. Send reminder messages to attendees

## During the Meetup

1. Welcome attendees and present the event schedule
2. Introduce speakers and manage presentations or discussions
3. Promote networking during breaks
4. Capture photos or videos for future use

## After the Meetup

1. Send thank-you messages to attendees and request feedback
2. Review feedback and key performance indicators to evaluate event success
3. Share event highlights, photos, and takeaways via social media, blogs, or newsletters
4. Let the Citrea community know about the event on the Discord channel
5. Connect with speakers, attendees, and volunteers to strengthen relationships
6. Start planning the next meetup, using insights to improve the experience
7. Give a heads up to the Citrea team via email

***

*Some points in this guideline are inspired by the efforts of Arbitrum and Celestia teams. We are grateful for their contributions.*


# Resources

We deeply value the content quality & speaker knowledge for Citrea Meetups. Therefore, here are some helpful topics & links that you and the speaker can utilize for the meetups. While they're available to be used in the meetup, preparing an original talk is **quite encouraged**. You can make a copy of below and edit from there.

### Sample Slides

* [An Introduction to Blockchains & Citrea](https://docs.google.com/presentation/d/1IpHKM3A86zdE848NSQtQepNJzY9Y-1pyDiv0-Vyo3Gw/edit?usp=sharing): A sample community meetup presentation for everyone
* [Sample Smart Contract Workshop](https://docs.google.com/presentation/d/1aJjovmo5fs0LJuev_pGysE7MjEVVO4PUb3KA8zwovj8/edit?usp=sharing): A sample community meetup presentation particularly for developers
* [Bitcoin Scaling Solutions & Citrea](https://docs.google.com/presentation/d/1L-xhlKb3NKkZdWkdcGDrtQKmySp8tWpsezuUVwuUFXE/edit?usp=sharing): A sample community meetup presentation for experienced people in the Web3 ecosystem

### Helpful Readings

* [Announcing Citrea Testnet](https://www.blog.citrea.xyz/citrea-testnet-live-on-bitcoin-testnet4/): A zk-rollup that enhances the capabilities of Bitcoin blockspace with zero-knowledge technology, now live on Bitcoin Testnet4, for the first time in history.
* [Introducing Citrea](https://www.blog.citrea.xyz/introducing-citrea/): A brief introduction to Citrea, our mission, and our vision.
* [Lifecycle of a Citrea Transaction](https://www.blog.citrea.xyz/lifecycle-of-a-citrea-transaction/): From start to finish, how Citrea transactions are processed and where they go.
* [Unveiling Clementine](https://www.blog.citrea.xyz/unveiling-clementine/): Citrea's BitVM-based trust-minimized two-way peg program, one of its kind.
* [Deep Dive into Citrea's Batch Proofs](https://www.blog.citrea.xyz/citreas-batch-proofs/): ZK, States, Batches, Blockspace Proving, and more.
* [Using Bitcoin as a Data Availability Layer](https://www.blog.citrea.xyz/bitcoin-as-a-data-availability-layer-what-why-how/): Some insights on Citrea's approach to using Bitcoin as a data availability layer.


# Code of Conduct

At Citrea Meetups, we are dedicated to fostering a welcoming, inclusive, and safe environment for all participants, regardless of their background, identity, or experience level. By attending a Citrea Meetup, you agree to follow this Code of Conduct, which is in place to ensure that every attendee has a positive experience.

## 1. Expected Behavior

All attendees, speakers, sponsors, and volunteers at Citrea Meetups are required to:

* **Be respectful**: Treat everyone with respect, kindness, and professionalism. Debate ideas constructively but avoid personal attacks.
* **Be inclusive**: We value diversity. Be mindful of how you interact with others, and ensure that the event is a space where everyone feels welcome, regardless of race, gender identity, sexual orientation, disability, ethnicity, religion, age, or any other identity.
* **Be considerate**: Your actions affect other people. Think about the impact of your words and behaviors, and work to create a positive experience for everyone.
* **Avoid disruption**: Refrain from monopolizing discussions, interrupting speakers, or being disruptive during sessions or activities. Respect privacy: Be mindful of photography, recording, and sharing of information.
* **Respect the privacy** and consent of other attendees when taking photos or sharing content publicly.

## 2. Unacceptable Behavior

Unacceptable behaviors include, but are not limited to:

* **Harassment**: Any form of harassment, intimidation, or discrimination. This includes offensive comments, verbal abuse, or unwelcome attention regarding personal attributes or identities.
* **Inappropriate physical contact**: This includes unwanted physical contact or unwelcome sexual attention. Trolling or disruptive behavior: This includes sustained disruptions during talks, deliberate intimidation, or inappropriate online conduct.
* **Hate speech**: Speech that promotes violence or hatred against individuals or groups based on identity is strictly prohibited.
* **Inappropriate use of the event platform**: This includes spamming, posting inappropriate or harmful content, and engaging in harmful or illegal activities.

## 3. Consequences of Unacceptable Behavior

Participants asked to stop unacceptable behavior are expected to comply immediately. If a participant engages in behavior that violates this Code of Conduct, the event organizers may take any action they deem appropriate, including:

* A verbal warning.
* Expulsion from the event.
* Banning from future Citrea events.

## 4. Reporting Issues

If you experience or witness unacceptable behavior or have any concerns, please contact a member of the Citrea Meetup team immediately. All reports will be handled with confidentiality.

On-site contact: Designated event organizer or volunteer (they will be identifiable by badges).

Email: <info@chainway.xyz>

Chainway Labs team is committed to taking action against such behavior. We do not tolerate any violations of our Code of Conduct and will address all concerns swiftly and appropriately. We will respond to all reports as quickly as possible and work with individuals to investigate and resolve the issue.

## 5. Enforcement

Citrea Meetup organizers are committed to enforcing this Code of Conduct. Any violations will be addressed with seriousness, ensuring a safe and respectful environment for all.

## 6. Conclusion

We believe that a safe, inclusive, and supportive environment is crucial for the success of Citrea Meetups. By enforcing this Code of Conduct, we aim to foster a community where everyone can learn, share, and network in a positive atmosphere. Thank you for being a part of Citrea Meetups and helping us create a welcoming and respectful community!


# Glossary

## Architecture & Core Components

* **Batch Prover**: A dedicated node that generates zero-knowledge proofs attesting to the correctness of Citrea blocks in batches. After sequencer commitments are finalized on Bitcoin, the batch prover fetches the corresponding batch of Citrea blocks, replays their execution inside a zkVM, and produces a succinct proof for the entire state transition.
* **Batch Proof**: A succinct ZK proof proving that if one starts from the previous proven state and executes all transactions in a batch, the resulting state matches the sequencer's claims. Includes the state diff, initial/final state roots, and the batch block range.
* **Batch Proof Method ID**: A unique 256-bit identifier for a specific version of the batch proof circuit. When the batch proof circuit is upgraded (e.g., during a fork), the method ID changes. Updates to the method ID are authorized by the Security Council via a 3-of-5 multisig (size of the multisig is prone to changes) and published to Bitcoin, specifying the new method ID and the L2 activation height.
* **Bitcoin Light Client**: Citrea's on-chain smart contract that maintains a record of finalized Bitcoin blocks. Each finalized Bitcoin block is pushed into this contract via system transactions, storing the block hash and witness root so other contracts (like the bridge) can prove Bitcoin transactions.
* **Clementine**: Citrea's native BitVM-based trust-minimized two-way peg for BTC ↔ cBTC that enables optimistic verification of ZK proofs directly on Bitcoin without consensus changes. Uses a 1-of-N trust model where one honest Signer, Watchtower, and Challenger can protect funds.
* **Full Node**: A permissionless participant that keeps a complete copy of Citrea's state and transaction history, verifies all rollup blocks by replaying transactions, monitors Bitcoin for finalized sequencer commitments and batch proofs, and exposes a standard JSON-RPC API.
* **Light Client Prover**: A specialized node that produces a recursive proof of the entire Citrea rollup state. Continuously processes each new Bitcoin block along with the previous light client proof, producing a new proof that verifies the correct Citrea state root for that block, forming an unbroken chain of proofs from genesis.
* **Light Client Proof**: A recursive proof of the entire Citrea Rollup state, while keeping its own JMT state. Verifies the relation between sequencer commitments and batch proofs and transitions the state accordingly. Includes L2 state root, circuit state root, method id of the previous light client proof, latest da state, last l2 height and sequencer commitment index from the last transitioned state.
* **Mempool**: A private memory pool serving as a temporary staging area for pending transactions before inclusion in a block. Citrea uses [Reth's transaction pool](https://reth.rs/docs/reth_transaction_pool/index.html) architecture underneath with some [modifications](/advanced/citrea-mempool)
* **Security Council**: A trusted multisignature committee responsible for safeguarding critical operations across the Citrea network. Operating under a 3-of-5 threshold scheme, the Security Council manages emergency responses, system contract upgrades, bridge signer operations, and vault security on both Bitcoin L1 and Citrea L2.

The council's authority includes upgrading system contracts (Bridge, Fee Vaults, Bitcoin Light Client), managing Clementine bridge signers, controlling emergency vault operations, and updating the batch prover Method ID when ZK circuits change.

* **Sequencer**: A specialized full node responsible for ordering user transactions and constructing rollup blocks. Every 2 seconds, it selects valid transactions prioritized by fees, injects system transactions, executes them against current state, updates the state root, and generates L2 Blocks.
* **Sequencer Commitment**: A Merkle root of L2 Block hashes covering a sequence of Citrea blocks, posted to Bitcoin to secure transaction ordering. Includes the batch window's height and a sequential index. Once finalized on Bitcoin, the ordering of blocks in that window is pinned.
* **State Transition Function**: The function that updates the Citrea state by applying transactions. Full nodes and batch proof circuit execute this function on each block by replaying transactions, applying state changes, and recomputing the state root.
* **zkEVM**: Citrea's special EVM implementation (Type 2 zkEVM) that makes the full VM implementation provable. Built using RISC Zero, it provides full equivalency to Ethereum while enabling scalable and trustless proofs based on zk-STARKs.
* **Type 2 zkEVM**: A zkEVM classification indicating full equivalency to Ethereum with a scalable and trustless proof system based on zk-STARKs (zero-knowledge Scalable Transparent Arguments of Knowledge).

## Transaction Finality

* **Confirmed**: The first level of finality when a transaction appears inside a sequencer-signed L2 Block. The transaction has been executed in the zkEVM and assigned an order, but is not yet anchored to Bitcoin.
* **Finalized**: The second level of finality when a batch window containing a transaction is finalized on Bitcoin. A sequencer commitment (Merkle root of L2 block hashes) reaches the required confirmation depth on Bitcoin, pinning the transaction's ordering immutably.
* **Proven**: The highest level of finality when a batch's execution is proven via a succinct ZK proof inscribed on Bitcoin with sufficient confirmations. The entire state transition is cryptographically validated end-to-end, and the necessary state data is available on Bitcoin for state reconstruction.
* **L2 Block**: A rollup block produced by the sequencer. It contains a signed header and a vector of transactions. The header includes the header hash, signature, block height, previous block header hash, state root at the end of that block, L1 fee rate, transactions merkle root, and timestamp.
* **Soft Confirmation**: The old name of L2 Block may be seen in some old comments throughout the codebase.
* **State Root**: The root hash of the rollup state after applying transactions in an L2 Block or batch proof. Used as a public input to circuits and helps nodes verify that they are applying the correct batch in sequence.

## Proofs & Cryptography

* **Groth16**: A succinct non-interactive zero-knowledge proof system used by Citrea. Citrea's batch proof circuit running in RISC Zero zkVM generates STARK proofs initially then another circuit in the zkVM wraps the stark proof with recursive proof composition to produce the Groth16 proof that prove correctness of Citrea blocks
* **RISC Zero**: A zkVM (zero-knowledge virtual machine) environment that Citrea uses to generate batch proofs, light client proofs and bridge proofs. Runs Groth16 circuits to prove the validity of state transitions, with proofs later wrapped into SNARKs for Bitcoin verification via Clementine.
* **SNARK**: Succinct Non-Interactive Argument of Knowledge. Citrea generates STARK proofs for transactions, then wraps them into succinct SNARK proofs for publication to Bitcoin in an inscription-like envelope for efficient verification.
* **STARK**: Scalable Transparent Argument of Knowledge. Citrea generates STARK proofs for batches of zkEVM transactions, which are then wrapped into SNARK proofs for publication to Bitcoin.
* **Zero-Knowledge Proof**: A cryptographic proof that demonstrates knowledge of a fact without revealing the fact itself. Citrea uses ZK proofs to prove the correctness of state transitions without requiring verification of every transaction individually.

## Bitcoin Integration

* **Bitcoin Data Availability**: Citrea's use of Bitcoin as its data availability layer. Instead of posting full transactions, Citrea publishes Brotli compressed state differences (state diffs) plus the latest state root to Bitcoin, allowing full nodes to reconstruct the entire rollup state from Bitcoin alone.
* **BitVM**: A breakthrough technology enabling optimistic verification of complex computations directly on Bitcoin without consensus changes. Citrea uses BitVM (specifically BitVM2) to verify ZK proofs on Bitcoin for the Clementine bridge, allowing off-chain computation with on-chain dispute resolution.
* **BitVM2**: An enhanced version of BitVM that significantly reduces on-chain footprint and improves permissionlessness. While both BitVM1 and BitVM2 use optimistic verification (assuming validity unless challenged), BitVM2 introduces key improvements: (1) **SNARK verification instead of arbitrary computation** - focuses specifically on verifying succinct proofs rather than general computation, (2) **Permissionless challenges** - anyone can challenge fraudulent claims, not just designated parties, and (3) **Reduced transaction complexity** - requires far fewer pre-signed transactions and on-chain interactions. Clementine is built on BitVM2 to create a trust-minimized bridge.
* **Coinbase Depth**: The position/depth of the coinbase transaction within a Bitcoin block's Merkle tree. Stored by the Bitcoin Light Client and used to enforce proof lengths for witness verification, preventing Merkle tree attacks explained in [this blog](https://bitslog.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design/#:~:text=Another%20way%20to,equal%20tree%20depths)..
* **Covenant**: A Bitcoin mechanism that restricts how a UTXO can be spent. Clementine emulates covenant-like restrictions using pre-signed transactions and MuSig2 aggregation, ensuring funds can only follow pre-approved spend paths.
* **Finality Depth**: The number of Bitcoin block confirmations required before Citrea considers a Bitcoin block finalized. Set to 6 on mainnet and 100 on testnet4 to withstand deep reorgs. The sequencer and full nodes only process Bitcoin blocks that have reached this depth.
* **MuSig2**: A two-round multi-signature scheme for creating aggregate Schnorr signatures from multiple keys, improving on the original MuSig protocol by reducing the number of communication rounds required. Clementine uses MuSig2 for pre-signed transactions, enabling n-of-n multisig functionality where all signers must participate to produce a single valid signature, with key deletion providing covenant-like spending restrictions.
* **Schnorr Signature**: A digital signature scheme used by Citrea for transaction verification. Citrea includes a Schnorr precompile and uses Schnorr signatures in the Clementine bridge for transaction authorization.
* **Taproot**: A Bitcoin upgrade enabling Taproot addresses that support multiple spending paths and Schnorr signatures. Clementine uses Taproot addresses encoding two paths: bridge paths (pre-signed by signers) and refund paths (user timelock).
* **Witness Root**: The Merkle root of a Bitcoin block's witness data (wtxids). Stored by the Bitcoin Light Client for each block to enable verification of transaction inclusion via witness Merkle trees.
* **Txid**: Transaction ID - The hash of a Bitcoin transaction not including its witness data.
* **Wtxid**: Witness transaction ID - the hash of a Bitcoin transaction including its witness data. Used by Citrea's Bitcoin Light Client for transaction inclusion proofs and verification against the witness root.
* **BIP 340**: Bitcoin Improvement Proposal defining Schnorr signature scheme used in Taproot (BIP 341).
* **BIP 341**: Bitcoin Improvement Proposal defining Taproot script path spending; used for bridge deposit/withdrawal witness structure and sighash reconstruction.

## Bridge & Cross-Chain

* **cBTC**: Citrea Bitcoin, the native asset on Citrea representing 1:1-backed Bitcoin from the Clementine bridge. Used for gas fees and transfers on Citrea, with 18 decimals (unlike 8 in Bitcoin mainnet).
* **Peg-In**: The process of depositing BTC to the Clementine bridge to mint cBTC on Citrea. User sends BTC to a Taproot address with two paths (bridge path and refund timeout), operators move it to a vault, and the bridge mints equivalent cBTC.
* **Peg-Out**: The process of withdrawing BTC by burning cBTC through the Clementine bridge smart contract on Citrea. User burns cBTC, submits withdrawal request to operators with a payout transaction template, and receives BTC on Bitcoin.
* **Bridge Contract**: The smart contract on Citrea (at address [`0x3100000000000000000000000000000000000002`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000002)) that validates Bitcoin deposits using the on-chain light client, mints cBTC for deposits, and records withdrawal intents for peg-outs.
* **Failed Deposit Vault**: A system contract that receives cBTC if a deposit transfer reverts (e.g., due to contract rejection). Allows operators and administrators to recover failed deposit funds rather than burning them.

## Clementine Bridge Roles

* **Challenger**: An entity who detects fraudulent reimbursement claims by operators on Bitcoin and initiates a Challenge transaction to force the operator to prove their intent in a dispute resolution game.
* **Operator**: An entity that facilitates fast peg-outs by fronting BTC payments to users and later claiming reimbursement from the bridge vault. Posts a KickOff claim transaction and can be slashed if proven fraudulent via challenge-response game. Requires a collateral bond (\~2 BTC).
* **Signer**: A member of the n-signer committee in Clementine that pre-signs allowed spend rules for bridge funds. Ensures funds can only move along approved paths via covenant-like restrictions. One honest signer protects funds against theft under 1-of-N assumption.
* **Watchtower**: An entity that monitors both Citrea and Bitcoin for malicious operator behavior. Publishes compact Bitcoin header-chain proofs with total work in response to fraud challenges, enabling challengers to prove invalid operator claims.

## Security & Dispute Resolution

* **Challenge-Response Game**: A BitVM2-based dispute resolution process triggered when a challenger contests an operator's reimbursement claim. The operator must prove correctness by posting Assert transactions that reveal intermediate computation results. If any step is incorrect, challengers can post a Disprove transaction to verify that single step on-chain and slash the operator's collateral. The operator's Bridge Proof must demonstrate their Header Chain Proof has more total work than Watchtower challenges and that the payout transaction is valid.
* **Bridge Proof**: A Groth16 zero-knowledge proof generated by an operator to defend their reimbursement claim during the BitVM2 challenge-response game. The proof verifies: (1) the operator's Header Chain Proof has more total work than the highest valid Watchtower challenge, (2) the payout transaction is included in the claimed Bitcoin block via SPV, (3) the Light Client Proof confirming the L1 block hash matches the payout transaction's block, and (4) EVM storage proofs showing the withdrawal data on Citrea matches the payout transaction. If any verification fails, challengers can use a Disprove transaction to slash the operator's collateral. For detailed information see [Bridge Circuit](https://github.com/chainwayxyz/clementine/blob/main/docs/bridge-circuit.md)
* **Collateral Bond**: BTC locked by each operator in Clementine (approximately 2 BTC) to back their reimbursement claims. If any claim in a round is proven fraudulent, the entire bond is slashed, preventing the operator from claiming reimbursements.
* **Optimistic Verification**: The process of accepting state updates optimistically (without immediate verification) and allowing them to be disputed within a challenge period. Clementine uses optimistic verification of ZK proofs on Bitcoin via BitVM.
* **Slashing**: Economic punishment mechanism in Clementine where an operator's entire collateral bond is forfeited if their reimbursement claim is proven fraudulent via the challenge-response game, and they are kicked out of the operator set.
* **Trust-Minimized**: A security model that minimizes the number and power of trusted entities. Clementine achieves trust-minimization through 1-of-N trust assumption, where only one honest participant per role is needed to protect the system.
* **1-of-N Trust Assumption**: A security model where the system remains secure as long as one honest participant exists among N participants. Clementine's bridge requires one honest Signer (prevents theft), one honest Watchtower (prevents chain anchoring to wrong fork), and one rational Challenger (forces honest operator behavior).

## Clementine Transactions

### Deposit & Collateral Transactions

* **Round**: A Bitcoin transaction that creates collateral for withdrawals, kickoff UTXOs for the current round, and reimburse connectors for the previous round. Chains rounds together using the first output of the previous ready-to-reimburse transaction.
* **Move to Vault**: A Bitcoin transaction that moves deposited BTC from the user's Taproot deposit address into the bridge vault UTXO, which is only spendable via the bridge's allowed exit paths. Requires all verifier signatures via MuSig2 aggregation.
* **Replacement Deposit**: A Bitcoin transaction that replaces a previous deposit when an emergency stop is triggered. Commits the old move-to-vault txid it replaces, allowing funds to be redeposited after security issues are resolved.
* **Emergency Stop**: A Bitcoin transaction that moves funds from a move-to-vault address to a security council controlled address, halting the deposit process in case of a security issue. Funds can later be redeposited via a replacement deposit.

### Payout & Reimbursement Transactions

* **Payout**: A Bitcoin transaction where an operator fronts a peg-out (withdrawal) to a user. The input is the user's withdrawal UTXO committed in Citrea, and the output goes to the user's address with an OP\_RETURN containing the operator's x-only pubkey.
* **Optimistic Payout**: A Bitcoin transaction where verifiers give deposited funds directly to a withdrawing user without the operator/BitVM process. Requires all verifier signatures and uses the move-to-vault output as collateral.
* **Reimburse**: A Bitcoin transaction where an operator claims reimbursement after no challenge is sent, or after a challenge is sent but no disprove follows. Spends the move-to-vault, kickoff reimburse connector, and round reimburse connector outputs.
* **Ready to Reimburse**: A Bitcoin transaction that spends the operator's collateral burn connector from the round transaction and returns collateral to the operator after a timeout period expires.
* **Kickoff Not Finalized**: A Bitcoin transaction that burns an operator's collateral if they send a ready-to-reimburse transaction while not all round kickoffs are finalized.
* **Unspent Kickoff**: A Bitcoin transaction that burns unused kickoff connectors when an operator sends ready-to-reimburse without spending all kickoff UTXOs.
* **Burn Unused Kickoff Connectors**: A Bitcoin transaction that burns multiple unused kickoff connectors from a single round transaction and returns change to a provided address.

### Challenge & Dispute Transactions

* **KickOff**: A Bitcoin transaction that initializes the protocol state when an operator fronts a peg-out seeking reimbursement. Sets up outputs for challenge, reimbursement, asserts, watchtower challenges, and latest blockhash commitments.
* **Challenge**: A Bitcoin transaction initiated by a challenger to dispute a fraudulent operator reimbursement claim (KickOff transaction). Covers the challenger's costs and includes an OP\_RETURN with the challenger's EVM address for reimbursement if the challenge is valid.
* **Challenge Timeout**: A Bitcoin transaction that finalizes a kickoff if no challenge is submitted in time, allowing the operator to proceed faster to the next round. Uses the challenge timeout and kickoff finalizer outputs.
* **Watchtower Challenge**: A Bitcoin transaction where a watchtower submits a challenge proof (Groth16 proof with public inputs). Encodes 144 bytes as Taproot outputs (32+32 bytes) and OP\_RETURN (80 bytes).
* **Watchtower Challenge Timeout**: A Bitcoin transaction where an operator claims timeout if a watchtower doesn't submit a challenge in time. Uses the watchtower challenge and challenge ack outputs.
* **Operator Challenge Ack**: A Bitcoin transaction where an operator acknowledges a watchtower challenge and reveals a preimage. Spends the watchtower challenge ack output.
* **Operator Challenge Nack**: A Bitcoin transaction where the N-of-N signers burn an operator's collateral if the operator doesn't reveal a preimage within the timelock. Spends challenge ack, kickoff finalizer, and burn connector outputs.
* **Disprove**: A Bitcoin transaction where the N-of-N signers penalize a malicious operator by burning their collateral. Uses BitVM disprove scripts or additional disprove scripts for invalid proofs. Spends disprove and burn connector outputs.
* **Disprove Timeout**: A Bitcoin transaction that an operator sends to enable the reimburse transaction if their proof wasn't disproved in time. Spends disprove and kickoff finalizer outputs.
* **No Challenge**: A Bitcoin transaction posted by an operator after the challenge window expires without disputes, using a timelock to unlock reimbursement funds from the bridge vault.

### BitVM Assertion Transactions

* **Assert Timeout**: A Bitcoin transaction where the N-of-N signers burn an operator's collateral if the operator doesn't provide valid assertion proofs within the timelock. Spends assert, kickoff finalizer, and burn connector outputs.
* **Mini Assert**: A Bitcoin transaction that commits a BitVM assertion of an operator's proof showing they paid the payout. Lightweight assertion transactions that create an anchor for CPFP (Child Pays For Parent).
* **Latest Blockhash**: A Bitcoin transaction where an operator commits the latest Bitcoin blockhash to reduce the time available for building a private fork. Used in the operator's bridge proof.
* **Latest Blockhash Timeout**: A Bitcoin transaction where the N-of-N signers burn an operator's collateral if the latest blockhash is not submitted in time. Spends blockhash, kickoff finalizer, and burn connector outputs.

## System Contracts

* **Bitcoin Light Client Proxy**: On-chain light client at [`0x3100000000000000000000000000000000000001`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000001) that maintains finalized Bitcoin block data (hashes, witness roots, coinbase depths) on Citrea for SPV-like proofs and bridge validation.
* **Bridge Proxy**: System contract at [`0x3100000000000000000000000000000000000002`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000002) that validates Bitcoin deposits using the light client, mints cBTC on Citrea, and records withdrawal intents for the Clementine bridge.
* **Base Fee Vault**: Pre-deployed contract at [`0x3100000000000000000000000000000000000003`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000003) that accumulates base fees in native cBTC. Acts as a passive accumulator until withdrawn to an operational account.
* **L1 Fee Vault**: Pre-deployed contract at [`0x3100000000000000000000000000000000000004`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000004) that accumulates L1 gas reimbursements in cBTC from state diff postings to Bitcoin.
* **Priority Fee Vault**: System contract at [`0x3100000000000000000000000000000000000005`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000005) that accumulates priority tips/MEV fees in native cBTC.
* **WCBTC**: Wrapped cBTC ERC-20 token at [`0x3100000000000000000000000000000000000006`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000006) for compatibility with standard token interfaces.
* **Failed Deposit Vault Proxy**: Contract at [`0x3100000000000000000000000000000000000007`](https://explorer.mainnet.citrea.xyz/address/0x3100000000000000000000000000000000000007) that serves as the catch-all destination for bridge deposits that could not be delivered to their intended recipients.
* **Fee Vault**: Generic term for contracts that collect and manage native cBTC fees, including Base Fee Vault, L1 Fee Vault, and Priority Fee Vault.
* **Proxy Admin**: Admin contract at [`0x31ffffffffffffffffffffffffffffffffffffff`](https://explorer.mainnet.citrea.xyz/address/0x31fFFfFfFFFffFFFFFFfFFffffFFffffFfFFfffF) responsible for managing upgrades of all system contracts through transparent proxy pattern.
* **System Caller**: Hardcoded address [`0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD`](https://explorer.mainnet.citrea.xyz/address/0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD) (no private key exists) that executes system transactions without consuming balance but whose gas usage counts toward block limits.
* **System Transaction**: Special transactions initiated by the System Caller that perform critical bootstrapping and maintenance: initializing the light client, updating Bitcoin block info, and processing bridge deposits.

## State Management

* **Jellyfish Merkle Tree**: Citrea's state tree structure (instead of Ethereum's Patricia Merkle Tree) used for efficient state representation and zero-knowledge proofs.
* **Merkle Proof**: Cryptographic proof of inclusion containing intermediate tree nodes needed to verify a leaf's membership in a Merkle tree.
* **Merkle Root**: The root hash of a Merkle tree summarizing all transactions or state changes in a batch.
* **State Diff**: Compressed representation of state changes between pre-state and post-state, posted to Bitcoin instead of full transaction data to minimize L1 footprint.
* **Witness Merkle Path**: The path of intermediate hashes from a transaction's wtxid to the witness root used in SPV inclusion proofs.

## Transaction & Block Structure

* **Batch Window**: A period of Citrea blocks whose ordering is locked by a single sequencer commitment inscription on Bitcoin.
* **Block Height**: Sequential index of a block starting from genesis; Citrea tracks Bitcoin block heights for finality anchoring.
* **Inscription**: Data inscribed on Bitcoin via transaction witness data, used for sequencer commitments and batch proofs.
* **nLockTime**: Bitcoin transaction field specifying the earliest time/block height at which the transaction can be mined.
* **Transaction Merkle Root**: Merkle root of all transaction hashes in a block; in Bitcoin, there are both transaction roots and witness transaction roots.
* **UTXO**: Unspent Transaction Output on Bitcoin; represented as (txId, outputId) pair for bridge withdrawal intents and coin management.

## Fees & Gas

* **Base Fee**: Per-byte cost applied to all transactions on Citrea, accumulated in the Base Fee Vault; varies with network congestion.
* **Diff Size**: Size of the state diff in bytes posted to Bitcoin for a transaction, used to calculate L1 fees.
* **L1 Fee**: Cost charged per transaction to cover Bitcoin data availability postings, calculated as `l1FeeRate * diffSize`; deducted at transaction end.
* **L1 Fee Rate**: Variable rate (wei per byte) for state diff costs on Bitcoin; reflects current Bitcoin transaction fees.
* **Priority Fee**: Tip amount paid to sequencers for transaction ordering priority, accumulated in the Priority Fee Vault.

## EVM & Execution

* **EIP-2935**: Ethereum Improvement Proposal for block hash historical access; NOT supported on Citrea.
* **EIP-4844**: Ethereum blob transaction standard for cheap data availability; NOT supported on Citrea (no blob pool).
* **KZG Precompile**: Kate-Zaverucha-Goldberg commitment verification precompile for EIP-4844; NOT available on Citrea (address 0x0A behaves as EOA).
* **Precompile**: Pre-compiled smart contract at a fixed address providing cryptographic operations at reduced gas cost.

## Precompiles

* **secp256r1 Precompile**: Precompile at `0x0000000000000000000000000000000000000100` (RIP-7212) for ECDSA signature verification on the secp256r1 curve; enables hardware/biometric authentication and passkeys at 3,450 gas.
* **Schnorr Precompile**: Precompile at `0x0000000000000000000000000000000000000200` for Bitcoin-native Schnorr signature verification (BIP 340); enables scriptless atomic swaps and Taproot key verification at 4,600 base gas.

## Network & Connectivity

* **Chain ID**: Network identifier: 4114 for Citrea Mainnet (hex: `0x1012`) and 5115 for Citrea Testnet (hex: `0x13FB`).
* **Testnet4**: Bitcoin's longest-lived testnet with frequent deep reorgs; Citrea Testnet uses 100-block finality depth as buffer against Testnet4 reorgs.

## Data & Availability

* **Reorg Resistance**: System's ability to withstand Bitcoin reorgs without halting.
* **State Reconstruction**: Ability to rebuild Citrea state independently from Bitcoin L1 by replaying state diffs and batch proofs from genesis.
* **Blockspace**: The limited data capacity within each Bitcoin block that Citrea competes for when posting sequencer commitments, batch proofs, and state diffs. Bitcoin's \~4MB block weight limit constrains how much rollup data can be inscribed per block, directly affecting Citrea's throughput and L1 fees.

## Future Research

* **Decentralized Sequencer Network**: Multiple sequencers sharing block production and transaction ordering via consensus algorithm instead of single sequencer; addresses liveness challenges.
* **Lightning Integration**: HTLC-based trustless atomic swaps between Citrea and Lightning Network for off-ramp/on-ramp without Bitcoin L1.
* **Multi-Prover System**: Combining multiple ZK proof systems (RISC Zero + SP1) to reduce single-point-of-failure risk in soundness; template implementation exists, SP1 activation post-mainnet.
* **Multi-VM Approach**: Future research into supporting multiple virtual machines beyond EVM on Citrea for broader developer ecosystem.
* **Trustless Settlement**: End-goal of fully trustless Bitcoin bridge without 1-of-N trust assumptions; requires Bitcoin opcodes like OP\_CAT for covenant-based proof verification.
* **Volition Model**: Hybrid data availability allowing users to choose between on-chain (Bitcoin) or off-chain DA branches; offers cost/security tradeoff.
* **Force Transactions**: Mechanism for users to bypass sequencer censorship by forcing transactions through a timeout-based mechanism.


