AI agent documentation index: llms.txt. Raw markdown for any page is available by appending .md to the URL. Full content snapshot: llms-full.txt.
llms.txt — complete Cartesi documentation index. Append .md to any page URL for raw Markdown (e.g. /cartesi-rollups/2.0/development/building-an-application.md).
Skip to main content

Self-hosted with Emergency Withdrawal

This guide runs a self-hosted node and deploys an application that supports emergency withdrawal: a guardian can foreclose it, and users can then recover their funds directly from the contracts. It follows the same flow as the standard deployment, with a few additions. Read the Foreclosure & Emergency Withdrawal overview first for the concept.

Production Warning

Like the standard setup, this is for development and testing on testnet, not production.

Prerequisites

In addition to the standard prerequisites (Cartesi CLI and Docker Desktop), you need:

  • A guardian address. This account, and only this account, can foreclose the application.
  • A withdrawal output builder for your token. For a single ERC-20, deploy one with the UsdWithdrawalOutputBuilderFactory, or reuse an existing one for the same token. Note its address.
  • An application whose guest maintains an accounts drive in a known layout. See Emergency Withdrawal (guest requirements).

Configure the machine and ledger (cartesi.toml)

For an application to support emergency withdrawal, its Cartesi Machine must include a dedicated accounts drive: a raw, unmounted flash drive that holds the balance ledger. You declare it in cartesi.toml alongside the root drive, size it to fit the account tree, and enable final_hash so the machine hash is produced for deployment. The guest then writes balances into that drive using a ledger library, in a layout that matches the application's WithdrawalConfig.

Because those choices (the drive declaration, its size and position, and the record layout) belong to the guest application, they are documented once, in full, on the guest-requirements page. Set the drive up as described in Creating the accounts drive before continuing, and see Keeping the balances for the ledger library.

Configuration

Configure your .env file exactly as in the standard flow:

BLOCKCHAIN_ID=<blockchain-id>
AUTH_KIND="private_key"
CARTESI_AUTH_PRIVATE_KEY="<funded-private-key>"
BLOCKCHAIN_WS_ENDPOINT="<ws-endpoint>"
BLOCKCHAIN_HTTP_ENDPOINT="<http-endpoint>"
CARTESI_BLOCKCHAIN_DEFAULT_BLOCK="<latest or finalized>"
VariableDescription
BLOCKCHAIN_IDYour blockchain network ID
BLOCKCHAIN_WS_ENDPOINTYour WebSocket endpoint
BLOCKCHAIN_HTTP_ENDPOINTYour HTTP endpoint
AUTH_KINDSet to private_key for local development
CARTESI_AUTH_PRIVATE_KEYA funded private key for the selected chain
CARTESI_BLOCKCHAIN_DEFAULT_BLOCKSet to either latest or finalized
Security

Follow best practices when handling private keys during local development and deployment.

Prepare the withdrawal config

Create a withdrawal.json describing the guardian and the accounts-drive layout. These values must match what your guest application actually writes (see WithdrawalConfig):

{
"guardian": "<guardian-address>",
"log2_leaves_per_account": 0,
"log2_max_num_of_accounts": 12,
"accounts_drive_start_index": 309237645312,
"withdrawal_output_builder": "<withdrawal-output-builder-address>"
}

Setting up the local node

  1. Download the Cartesi Rollups Node docker compose file in your project root:

    curl -L https://raw.githubusercontent.com/Mugen-Builders/deployment-setup-v2.0/main/compose.local.yaml -o compose.local.yaml

    This is the same compose file used by the standard flow. It already includes the machine-tool service used later for recovery, so there is nothing extra to add.

  2. Build the application with the Cartesi CLI:

    cartesi build

    This compiles your application into RISC-V and creates a Cartesi machine snapshot locally. Make sure your application maintains its accounts drive in the layout described by withdrawal.json.

  3. Run the Cartesi Rollups Node with the application's initial snapshot attached:

    docker compose -f compose.local.yaml --env-file .env up -d
  4. Deploy and register the application with its withdrawal config:

    Make the config file readable inside the advancer container, then deploy with --withdrawal-config-file:

    docker compose --project-name cartesi-rollups-node cp withdrawal.json advancer:/tmp/withdrawal.json

    docker compose --project-name cartesi-rollups-node \
    exec advancer cartesi-rollups-cli deploy application <app-name> /var/lib/cartesi-rollups-node/snapshot \
    --epoch-length 10 \
    --withdrawal-config-file /tmp/withdrawal.json \
    --salt <salt> \
    --register

    Replace <app-name> with your application name and <salt> with a unique identifier (generate one with cast keccak256 "your-unique-string"). The deployment is rejected if the config is invalid, meaning its accounts-drive layout does not fit the machine memory. A zero-valued config would deploy an application without emergency withdrawal, which is the standard case.

    After this, your application is deployed and registered, and a guardian can foreclose it when needed.

Recovery

When the operator is gone, the guardian forecloses and users withdraw directly from the contracts. The full procedure (foreclose, replay, prove the accounts drive, anchor the root, withdraw, and verify) is in the Emergency Withdrawal Recovery Guide.

We use cookies to ensure that we give you the best experience on our website. By using the website, you agree to the use of cookies.