๐Ÿฅท Madara: Starknet Client

June 15, 2026 ยท View on GitHub

Ask DeepWiki Workflow - Push Project license Pull Requests welcome Follow on Twitter GitHub Stars

๐Ÿฅท Madara: Starknet Client

Madara is a powerful Starknet client written in Rust.

Table of Contents

โฌ‡๏ธ Installation

โฌ…๏ธ back to top

Tip

For an easier time setting up machine for local development, consult Using Dev Containers.

Run from Source

1. Install dependencies

Ensure you have all the necessary dependencies available on your host system.

DependencyVersionInstallation
Rustrustc 1.89curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
ClangLatestsudo apt-get install clang
Openssl0.10sudo apt install openssl

Once all dependencies are satisfied, you can clone the Madara repository:

cd <your-destination-path>
git clone https://github.com/madara-alliance/madara
cd madara

2. Build Madara

Tip

Build scripts normally fetch the published contract artifacts automatically. If you need to regenerate local artifacts, run make artifacts before building. This requires Docker.

You can choose between different build modes:

  • Debug (low performance, fastest builds, for testing purposes only):

    cargo build
    
  • Release (fast performance, slower build times):

    cargo build --release
    
  • Production (fastest performance, very slow build times):

    cargo build --profile=production
    

3. Run Madara

Start the Madara client with a basic set of arguments depending on your chosen mode:

Note

Head to the Configuration section to learn more about customizing your node.

Full Node

Synchronizes the state of the chain from genesis.

cargo run --bin madara --release --        \
  --name Madara               \
  --full                      \
  --base-path /var/lib/madara \
  --network mainnet           \
  --l1-endpoint ${ETHEREUM_API_URL}

The user JSON-RPC endpoint is enabled on localhost by default. For a private full node, omit --rpc; set --rpc-port only if you need a non-default local port.

Sequencer

Produces new blocks for other nodes to synchronize.

cargo run --bin madara --release --        \
  --name Madara               \
  --sequencer                 \
  --base-path /var/lib/madara \
  --preset sepolia            \
  --l1-endpoint ${ETHEREUM_API_URL}

Devnet

A node in a private local network.

 cargo run --bin madara --release --    \
  --name Madara            \
  --devnet                 \
  --base-path ../madara_db \
  --chain-config-override=chain_id=MY_CUSTOM_DEVNET

Caution

Make sure to use a unique chain_id for your devnet to avoid potential replay attacks in other chains with the same chain id!

4. Presets

You can use cli presets for certain common node configurations. The --rpc preset is for public RPC provider mode: it exposes user RPC on 0.0.0.0, enables admin RPC on localhost, and allows all CORS origins. Do not use it for a private/local-only full node:

cargo run --bin madara --release -- \
   --name Madara       \
   --full              \
   --preset mainnet    \
   --rpc

...or the madara feeder gateway:

cargo run --bin madara --release -- \
   --name Madara       \
   --full              \
   --preset mainnet    \
   --gateway

Run with Docker

1. Manual Setup

DependencyVersionInstallation
DockerLatestOfficial instructions

Once you have Docker installed, you will need to pull the madara image from the github container registry (ghr):

docker pull ghcr.io/madara-alliance/madara:latest
docker tag ghcr.io/madara-alliance/madara:latest madara:latest
docker rmi ghcr.io/madara-alliance/madara:latest

You can then launch madara as follows:

docker run -d                    \
  -p 9944:9944                   \
  -v /var/lib/madara:/tmp/madara \
  --name Madara                  \
  madara:latest                  \
  --name Madara                  \
  --full                         \
  --network mainnet              \
  --l1-endpoint ${ETHEREUM_API_URL}

To display the node's logs, you can use:

docker logs -f -n 100 Madara

Warning

Make sure to change the volume -v of your container if ever you update --base-path.

2. Using the project Makefile

Alternatively, you can use the provided Makefile and compose.yaml to simplify this process.

DependencyVersionInstallation
Docker ComposeLatestOfficial instructions
Gnu MakeLatestsudo apt install make

Once you have all the dependencies installed, start by saving your rpc key to a .secrets folder:

mkdir .secrets
echo "${ETHEREUM_API_URL}" > .secrets/rpc_api.secret

Then, run madara with the following commands:

make start    # This will automatically pull the madara image if not available
make logs     # Displays the last 100 lines of logs
make stop     # Stop the madara node
make clean-db # Removes the madara db, including files on the host
make restart  # Restarts the madara node

Important

By default, make start will try and restart Madara indefinitely if it is found to be unhealthy using docker autoheal. This is done by checking the availability of http://localhost:9944/health, which means your container will be marked as unhealthy and restart if you have disabled the RPC service! You can run watch docker ps to monitor the health of your containers.

To change runtime arguments, you can update the script in madara-runner.sh:

#!/bin/sh
export RPC_API_KEY=$(cat $RPC_API_KEY_FILE)

./madara                   \
  --name madara            \
  --network mainnet        \
  --rpc-external           \
  --rpc-cors all           \
  --full                   \
  --l1-endpoint $RPC_API_KEY

For more information, run:

make help

Tip

When running Madara from a docker container, make sure to set options such as --rpc-external, --gateway-external and --rpc-admin-external so as to be able to access these services from outside the container.

โš™๏ธ Configuration

โฌ…๏ธ back to top

For a comprehensive list of all command-line options, check out:

cargo run --bin madara -- --help

Or if you are using docker, simply:

docker run madara:latest --help

Basic Command-Line Options

Here are some recommended options to get up and started with your Madara client:

OptionAbout
--name <NAME>The human-readable name for this node. It's used as the network node name.
--base-path <PATH>Sets the database location for Madara (default is/tmp/madara)
--fullThe mode of your Madara client (either --sequencer, --full, or --devnet)
--l1-endpoint <URL>The Layer 1 endpoint the node will verify its state from
--rpc-port <PORT>The JSON-RPC server TCP port, used to receive requests
--rpc-cors <ORIGINS>Browser origins allowed to make calls to the RPC servers
--rpc-externalExposes the rpc service on 0.0.0.0

Environment Variables

Each cli argument has its own corresponding environment variable you can set to change its value. For example:

  • MADARA_BASE_PATH=/path/to/db
  • MADARA_RPC_PORT=1111

These variables allow you to adjust the node's configuration without using command-line arguments, which can be useful in CI pipelines or with docker.

Configuration files

You can load the arguments directly from a file for ease of use. The supported file formats are json, toml and yaml. You can find examples on configs.

Note

If the command-line argument is specified then it takes precedent over the environment variable.

๐ŸŒ Interactions

โฌ…๏ธ back to top

Madara supports Starknet JSON-RPC routes v0.7.1, v0.8.1, v0.9.0, v0.10.0, and v0.10.2. Method-level availability can vary depending on current implementation status and runtime retention/configuration. The default user RPC version is v0.10.2; the explicit route is rpc/v0_10_2. Legacy user routes are also available under rpc/v0_7_1, rpc/v0_8_1, rpc/v0_9_0, and rpc/v0_10_0. Admin RPC methods are exposed under rpc/v0_1_0 (default port 9943) when --rpc-admin is enabled. These methods can be categorized into three main types: Read-Only Access Methods, Trace Generation Methods, and Write Methods. They are accessible through port 9944 unless specified otherwise with --rpc-port.

Tip

You can use the special rpc_methods call to view a list of all the methods which are available on an endpoint.


Supported JSON-RPC Methods

Here is a list of all the supported methods with their current status:

Read Methods
StatusMethod
โœ…starknet_specVersion
โœ…starknet_getBlockWithTxHashes
โœ…starknet_getBlockWithTxs
โœ…starknet_getBlockWithReceipts
โœ…starknet_getStateUpdate
โœ…starknet_getStorageAt
โœ…starknet_getTransactionStatus
โœ…starknet_getTransactionByHash
โœ…starknet_getTransactionByBlockIdAndIndex
โœ…starknet_getTransactionReceipt
โœ…starknet_getClass
โœ…starknet_getClassHashAt
โœ…starknet_getClassAt
โœ…starknet_getBlockTransactionCount
โœ…starknet_call
โœ…starknet_estimateFee
โœ…starknet_estimateMessageFee
โœ…starknet_blockNumber
โœ…starknet_blockHashAndNumber
โœ…starknet_chainId
โœ…starknet_syncing
โœ…starknet_getEvents
โœ…starknet_getNonce
โœ…starknet_getCompiledCasm (v0.8.1+)
โœ…starknet_getMessagesStatus (v0.9.0+)
โŒstarknet_getStorageProof (v0.8.1+, currently unavailable in default profile)
Trace Methods
StatusMethod
โœ…starknet_traceTransaction
โœ…starknet_simulateTransactions
โœ…starknet_traceBlockTransactions
Write Methods
StatusMethod
โœ…starknet_addInvokeTransaction
โœ…starknet_addDeclareTransaction
โœ…starknet_addDeployAccountTransaction
Websocket Methods
StatusMethod
โœ…starknet_unsubscribe (v0.8.1+)
โŒstarknet_subscribeNewHeads (placeholder)
โŒstarknet_subscribeEvents (placeholder)
โŒstarknet_subscribeTransactionStatus (placeholder)
โŒstarknet_subscribePendingTransactions (placeholder)
โŒstarknet_subscriptionReorg

Note

Subscription methods are currently placeholders and return UnimplementedMethod. This applies to v0.8.1, v0.9.0, v0.10.0, and v0.10.2 (the v0.10 routes delegate subscription placeholders to v0.9.0).

Important

starknet_getStorageProof is currently treated as unavailable in the default node profile because the required retention is disabled in configs/args/config.json: db_max_saved_trie_logs = 0, db_max_kept_snapshots = 0, and rpc_storage_proof_max_distance = 0. Madara loads this file by default when run without explicit CLI/config overrides.

Important

Write methods are forwarded to the Sequencer and are not executed by Madara. These might fail if you provide the wrong arguments or in case of a conflicting state. Make sure to refer to the Starknet JSON-RPC specs for a list of potential errors.

Madara-specific JSON-RPC Methods

As well as the official RPC methods, Madara also supports its own set of custom extensions to the starknet specs. These are referred to as admin methods and are exposed on a separate port 9943 unless specified otherwise with --rpc-admin-port.

Write Methods
MethodAbout
madara_addDeclareV0TransactionAdds a legacy Declare V0 transaction
madara_bypassAddDeclareTransactionBypasses mempool/validation for Declare transactions
madara_bypassAddDeployAccountTransactionBypasses mempool/validation for DeployAccount transactions
madara_bypassAddInvokeTransactionBypasses mempool/validation for Invoke transactions
madara_closeBlockForces block closure in block production mode
madara_revertToAndShutdownReverts chain state to a block hash and shuts down the node
madara_addL1HandlerMessagePushes an L1 handler message into bypass input
madara_setCustomBlockHeaderSets custom block header fields for upcoming block
Read Methods
MethodAbout
madara_getBlockBuiltinWeightsReturns builtin weights for a block
Status Methods
MethodAbout
madara_pingReturn the unix time at which this method was called
madara_shutdownGracefully stops the running node
madara_serviceSets the status of one or more services
madara_serviceStatusReturns requested and actual service statuses
Websocket Methods
MethodAbout
madara_pulsePeriodically sends a signal that the node is alive

Caution

These methods are exposed on localhost by default for obvious security reasons. You can always expose them externally using --rpc-admin-external, but be very careful when doing so as you might be compromising your node! Madara does not do any authorization checks on the caller of these methods and instead leaves it up to the user to set up their own proxy to handle these situations.


Example of Calling a JSON-RPC Method

You can use any JSON-RPC client to interact with Madara, such as curl, httpie, websocat or any client sdk in your preferred programming language. For more detailed information on how to call each method, please refer to the Starknet JSON-RPC specs.

Http RPC

DependencyVersionInstallation
CurlLatestsudo apt install curl

Here is an example of how to call a JSON-RPC method using Madara. Before running the bellow code, make sure you have a node running with rpc enabled on port 9944 (this is the default configuration).

Important

Madara currently defaults to v0.10.2 for RPC calls. To access specific versions, add rpc/v*_*_*/ to your RPC URL. This also works for websocket methods.

curl --location 'http://localhost:9944/rpc/v0_10_2/' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "rpc_methods",
    "params": [],
    "id": 1
  }' | jq --sort-keys

You should receive something like the following:

{
  "id": 1,
  "jsonrpc": "2.0",
  "result": {
    "methods": [
      "rpc/V0_7_1/starknet_addDeclareTransaction",
      "rpc/V0_7_1/starknet_addDeployAccountTransaction",
      "rpc/V0_7_1/starknet_addInvokeTransaction",
      ...
      "rpc/V0_10_2/starknet_traceBlockTransactions",
      "rpc/V0_10_2/starknet_traceTransaction",
      "rpc/V0_10_2/starknet_unsubscribe",
      "rpc/rpc_methods"
    ]
  }
}

Websocket RPC

DependencyVersionInstallation
WebsocatLatestOfficial instructions

Websockets methods are enabled by default and are accessible through the same port as http RPC methods.

Note

Subscription methods are currently placeholders and return UnimplementedMethod on v0.8.1, v0.9.0, v0.10.0, and v0.10.2. starknet_unsubscribe is available, but active subscription streams are not yet available.

You can still use websocket transport to call methods and validate responses using websocat:

websocat -v ws://localhost:9944/rpc/v0_10_2

Tip

Once connected, paste JSON-RPC payloads directly in the terminal. For example:

{ "jsonrpc": "2.0", "method": "starknet_subscribeNewHeads", "params": {"block_id":"latest"}, "id": 1 }

This currently returns UnimplementedMethod until subscription support is re-enabled.

๐Ÿ“š Database Migration

โฌ…๏ธ back to top

Database Version Management

Madara now performs automatic database schema migration on startup when needed. This keeps binary and database versions aligned without manual migration steps in the common case.

Current migration metadata is tracked in .db-versions.yml:

  1. Current schema version: 14
  2. Minimum migratable version: 8
  3. Migrations are resumable and protected by migration lock/state files

Important

Backups are created before migrations by default. Use --skip-migration-backup only when you already have external backups.

Caution

Database migrations are forward-oriented. After migrating to a newer schema version, you cannot safely reuse the same database with an older Madara binary. To roll back, restore from a backup taken before migration.

To migrate your database, you have two options:

  1. Start the node and let automatic in-place migration run
  2. Use Madara's warp update feature (recommended for fast local migration)
  3. Re-synchronize from genesis (not recommended)

The warp update feature provides a trusted sync from a local source, offering better performance than re-synchronizing the entirety of your chain's state from genesis.

Warp Update

Warp update requires a working database source for the migration. If you do not already have one, you can use the following command to generate a sample database:

cargo run --bin madara --release --      \
  --name madara             \
  --network mainnet         \
  --full                    \
  --l1-sync-disabled        `# We disable sync, for testing purposes` \
  --sync-stop-at 1000       `# Only synchronize the first 1000 blocks` \
  --stop-on-sync            `# ...and shutdown the node once this is done`

To begin the database migration, you will need to start your node with admin methods and feeder gateway enabled. This will be the source of the migration. You can do this with the --warp-update-sender preset:

cargo run --bin madara --release -- \
  --name Sender        \
  --full               `# This also works with other types of nodes` \
  --network mainnet    \
  --warp-update-sender \
  --l1-sync-disabled   `# We disable sync, for testing purposes` \
  --l2-sync-disabled

Tip

Here, we have disabled sync for testing purposes, so the migration only synchronizes the blocks that were already present in the source node's database. In a production usecase, you most likely want the source node to keep synchronizing with an --l1-endpoint, that way when the migration is complete the receiver is fully up-to-date with any state that might have been produced by the chain during the migration.

You will then need to start a second node to synchronize the state of your database:

cargo run --bin madara --release --            \
  --name Receiver                 \
  --base-path /tmp/madara_new     `# Where you want the new database to be stored` \
  --full                          \
  --network mainnet               \
  --l1-sync-disabled              `# We disable sync, for testing purposes` \
  --warp-update-receiver          \
  --warp-update-shutdown-receiver `# Shuts down the receiver once the migration has completed`

This will start generating a new up-to-date database under /tmp/madara_new. Once this process is over, the receiver node will automatically shutdown.

Tip

There also exists a --warp-update-shutdown-sender option which allows the receiver to take the place of the sender in certain limited circumstances.

Running without --warp-update-sender

Up until now we have had to start a node with --warp-update-sender to begin a migration, but this is only a preset. In a production environment, you can start your node with the following arguments and achieve the same results:

cargo run --bin madara --release --    \
  --name Sender           \
  --full                  `# This also works with other types of nodes` \
  --network mainnet       \
  --feeder-gateway-enable `# The source of the migration` \
  --gateway-port 8080     `# Default port, change as required` \
  --rpc-admin             `# Used to shutdown the sender after the migration` \
  --rpc-admin-port 9943   `# Default port, change as required` \
  --l1-sync-disabled      `# We disable sync, for testing purposes` \
  --l2-sync-disabled

--warp-update-receiver doesn't override any cli arguments but is still needed on the receiver end to start the migration. Here is an example of using it with custom ports:

Important

If you have already run a node with --warp-update-receiver following the examples above, remember to delete its database with rm -rf /tmp/madara_new.

cargo run --bin madara --release --            \
  --name Receiver                 \
  --base-path /tmp/madara_new     `# Where you want the new database to be stored` \
  --full                          \
  --network mainnet               \
  --l1-sync-disabled              `# We disable sync, for testing purposes` \
  --warp-update-port-rpc 9943     `# Same as set with --rpc-admin-port on the sender` \
  --warp-update-port-fgw 8080     `# Same as set with --gateway-port on the sender` \
  --feeder-gateway-enable         \
  --warp-update-receiver          \
  --warp-update-shutdown-receiver `# Shuts down the receiver once the migration has completed`

โœ… Supported Features

โฌ…๏ธ back to top

Starknet compliant

Madara supports Starknet JSON-RPC v0.7.1, v0.8.1, v0.9.0, v0.10.0, and v0.10.2 (default version: v0.10.2). You can find out more in the interactions section and the official Starknet JSON-RPC specs.

Feeder-Gateway State Synchronization

Madara supports its own implementation of the Starknet feeder gateway, which allows nodes to synchronize state from each other at much faster speeds than a regular sync.

Note

Starknet does not currently have a specification for its feeder-gateway protocol, so despite our best efforts at output parity, you might still notice some discrepancies between official feeder gateway endpoints and our own implementation. Please let us know about if you encounter this by raising an issue

Mainnet Full-Node Bootstrap

Madara can bootstrap a mainnet full node in a few ways:

PathUse whenNotes
Full syncYou need the most complete local history.This is the slowest path.
--snap-syncYou want faster catchup.Storage proofs are not guaranteed for every snap-synced block, and admin revert cannot target blocks before snap_sync_latest_block.
Existing Madara DBYou already have a compatible Madara database.Stop the node that owns the DB, then start Madara with --base-path pointing at the same base path. Keep a backup before reusing or migrating a DB.

If catchup logs Rate limited, retrying, the selected gateway is throttling requests. Use --gateway-key only when you have been issued a key for that gateway, or use --gateway-url to point at a gateway source that you operate or trust. When reporting rate-limit issues, include the Madara commit, full command line, current block, target block, blocks/sec, DB size, and how often the rate-limit message appears.

State Commitment Computation

Madara supports merkelized state commitments through its own implementation of Besu Bonsai Merkle Tries. See the bonsai lib. You can read more about Starknet Block structure and how it affects state commitment in the Starknet documentation.

SnapSync

Madara supports SnapSync (--snap-sync) to accelerate state synchronization by batching trie computations.

SnapSync uses a batched trie-apply path when both conditions hold:

  1. --snap-sync is enabled
  2. The distance to the sync target is >= 1000 blocks

When the remaining distance is below this threshold, Madara flushes accumulated state diffs and returns to block-by-block trie updates.

Important

SnapSync is a performance tradeoff with historical-data implications:

  • For blocks synchronized through SnapSync batches, per-block trie logs ("trielogs") are not produced for each intermediate block in that range.
  • As a result, storage proofs are not guaranteed for every block in snap-synced ranges.
  • Reverting into the snap-synced range is blocked by design. The admin revert API rejects targets lower than the recorded snap_sync_latest_block because trie data is only available from that boundary onward.

Cairo Native Execution

Madara supports opt-in Cairo Native execution controlled by a single flag:

--enable-native-execution true

By default, this is disabled and Cairo VM execution remains the execution path.

When native execution is enabled:

  1. Madara compiles Sierra classes into native artifacts and caches them.
  2. Compilation mode is controlled by --native-compilation-mode:
    • async (default): compile in background, execute immediately with Cairo VM fallback.
    • blocking: wait for compilation; compilation failure/timeout fails execution.
  3. Native artifacts are cached on disk under <base-path>/native_classes and reused on restart.
  4. Async compilation retries are controlled by --native-enable-retry (default: true).

This means native compilation is resumable in practice through persisted cache reuse: compiled classes survive restarts, while classes not yet compiled are compiled on-demand after restart.

L3 Support

Madara supports running with different settlement layers via --settlement-layer:

  • Eth (default)
  • Starknet (L3-oriented deployment mode)

When --settlement-layer Starknet is used:

  1. --l1-endpoint is treated as a Starknet RPC endpoint (not Ethereum RPC).
  2. The settlement client switches to Starknet settlement sync.
  3. --l1-gas-price and --blob-gas-price are interpreted in FRI (instead of WEI on Ethereum settlement).
  4. Chain execution is marked as L3 (is_l3 = true), which changes how blockifier treats settlement-layer addresses.

Automatic Database Migrations

Madara includes an automatic migration system with checkpoint backups and resume support to simplify upgrades across database schema versions.

๐Ÿ’ฌ Get in touch

โฌ…๏ธ back to top

Contributing

Start with an issue using the templates under .github/ISSUE_TEMPLATE/, then open a pull request using .github/PULL_REQUEST_TEMPLATE.md.

Partnerships

To establish a partnership with the Madara team, or if you have any suggestions or special requests, feel free to reach us on Telegram.

License

Madara is open-source software licensed under the Apache-2.0 License.