Docs Técnicas
Dev Chain Snapshots and Fixtures
Snapshots and fixtures let you freeze a known chain state and restore it deterministically any number of times. Use them to write independent test cases that start from a shared precondition without re-deploying contracts in every test run.
Snapshots and fixtures let you freeze a known chain state and restore it deterministically any number of times. Use them to write independent test cases that start from a shared precondition without re-deploying contracts in every test run.
How Determinism Works
The dev chain is seed-driven: every account address is derived from the seed field in trea.dev.toml combined with an account index. Because the seed is fixed, the same sequence of operations always produces the same addresses, contract storage, and state root.
A snapshot does not serialise the raw in-memory ledger state. Instead it records the ordered list of publish, deploy, and call operations that were applied since genesis. Restoring a snapshot creates a fresh chain from the same config and replays those operations — two restores of the same snapshot always yield identical state roots.
This approach sidesteps binary-format coupling between runtime versions and makes snapshot files human-readable JSON.
Snapshot File Format
Snapshots are stored under <data-dir>/snapshots/ as <name>.snap.json files.
{
"metadata": {
"name": "counter-ready",
"seed": "atlas-dev-chain",
"chain_id": "atlas-dev-chain-1",
"runtime_version": "trea-v3",
"height": 3,
"state_root": "a3f9…",
"created_at": 1751000000,
"contract_artifact_ids": ["dev-counter:v1"]
},
"operations": [
{ "op": "publish", "signer": "admin",
"artifact_id": "dev-counter:v1",
"source": "contract DevCounter:\n …" },
{ "op": "deploy", "signer": "admin",
"artifact_id": "dev-counter:v1",
"contract_id": "counter-1" },
{ "op": "call", "signer": "admin",
"contract_id": "counter-1",
"entrypoint": "increment",
"args": ["int:7"] }
],
"dev_accounts": [
{ "name": "admin", "index": 0, "next_nonce": 4 }
],
"receipts": {},
"blocks": [],
"config": { "…": "original trea.dev.toml fields" }
}The metadata.runtime_version field is a human-readable marker. No automatic migration is attempted between incompatible versions; re-generate snapshots when you upgrade the runtime.
CLI Commands
These commands talk to a running dev chain server.
Save a snapshot
trea-dev snapshot counter-readySaves the current chain state as counter-ready.snap.json inside the data directory's snapshots/ subfolder. Prints the saved path.
Use --json for script-friendly output:
trea-dev --json snapshot counter-ready
# {"name":"counter-ready","path":".atlas-dev-chain/snapshots/counter-ready.snap.json","height":3,"state_root":"a3f9…"}List snapshots
trea-dev snapshotsPrints a table of available snapshots with name, height, and state root.
trea-dev --json snapshotsReturns a JSON array of metadata objects.
Restore a snapshot
trea-dev restore counter-readyReplays the recorded operations on a fresh in-memory chain. The server continues running with the restored state. All previous blocks and receipts in the running server's session are replaced by the snapshot's.
trea-dev restore counter-ready
# restored to snapshot 'counter-ready' at height 3Reset to genesis
trea-dev reset-genesisDiscards all chain state and restarts from a clean genesis without stopping the server.
HTTP Endpoints
The same actions are available over HTTP for SDK and CI use.
| Method | Path | Purpose | |--------|------|---------| | GET | /snapshots | List metadata for all saved snapshots | | POST | /snapshots | Save the current state as a named snapshot | | POST | /snapshots/{name}/restore | Restore from a saved snapshot | | POST | /reset | Reset to genesis |
Save snapshot
curl -s -XPOST http://localhost:8545/snapshots \
-H 'content-type: application/json' \
-d '{"name":"counter-ready"}'{
"name": "counter-ready",
"path": ".atlas-dev-chain/snapshots/counter-ready.snap.json",
"height": 3,
"state_root": "a3f9…"
}Restore snapshot
curl -s -XPOST http://localhost:8545/snapshots/counter-ready/restore{ "name": "counter-ready", "height": 3, "state_root": "a3f9…" }Reset to genesis
curl -s -XPOST http://localhost:8545/reset{ "height": 0, "state_root": "…genesis root…" }Fixtures in `trea.dev.toml`
Fixtures are named sequences of operations defined in the config file. When the dev chain server starts (or restarts), it runs all fixtures in order and optionally saves a snapshot after each one.
seed = "atlas-dev-chain"
chain_id = "atlas-dev-chain-1"
start_time = 1800000000
block_time_ms = 1000
[[accounts]]
name = "admin"
index = 0
balance = 100_000_000
[[accounts]]
name = "alice"
index = 1
balance = 10_000_000
[[fixtures]]
name = "counter-ready"
auto_snapshot = true
[[fixtures.steps]]
op = "publish"
signer = "admin"
artifact_id = "dev-counter:v1"
source_file = "contracts/counter.trea" # relative to trea.dev.toml
[[fixtures.steps]]
op = "deploy"
signer = "admin"
artifact_id = "dev-counter:v1"
contract_id = "counter-1"
[[fixtures.steps]]
op = "call"
signer = "admin"
contract_id = "counter-1"
entrypoint = "increment"
args = ["int:100"]When auto_snapshot = true, the runner saves a snapshot named after the fixture immediately after all its steps succeed. The snapshot is written to <data-dir>/snapshots/counter-ready.snap.json.
Step types
`publish` — compile and register a TREA contract artifact.
| Field | Required | Description | |-------|----------|-------------| | op | yes | "publish" | | signer | yes | Dev account name | | artifact_id | yes | Artifact identifier | | source | one of | Inline TREA source string | | source_file | one of | Path to a .trea file (relative to the config file) |
`deploy` — instantiate a published artifact.
| Field | Required | Description | |-------|----------|-------------| | op | yes | "deploy" | | signer | yes | Dev account name | | artifact_id | yes | Artifact to instantiate | | contract_id | yes | Unique instance identifier |
`call` — call a contract entrypoint.
| Field | Required | Description | |-------|----------|-------------| | op | yes | "call" | | signer | yes | Dev account name | | contract_id | yes | Instance to call | | entrypoint | yes | Entrypoint name | | args | no | Argument list in TYPE:VALUE format |
Argument types are the same as in the CLI: bool:true, int:1000, addr:wallet:nbex…, text:hello.
Testing Pattern
A common pattern in Rust integration tests:
#[tokio::test]
async fn independent_test_a() {
let dir = tempfile::tempdir().unwrap();
let mut world = DevWorld::new(dir.path(), DevChainConfig::default()).await.unwrap();
// Each test restores from the same snapshot instead of re-deploying.
let snap_path = PathBuf::from("test-fixtures/counter-ready.snap.json");
let restore_dir = tempfile::tempdir().unwrap();
let world = DevWorld::restore_snapshot(&snap_path, restore_dir.path())
.await
.unwrap();
// state_root is identical to what was captured at snapshot time
assert_eq!(
world.state_root().await.unwrap(),
expected_state_root,
);
}The acceptance test for the snapshot feature (e2e_snapshot_save_restore_deterministic in lib.rs) verifies this property end-to-end: it runs the counter sequence, saves a snapshot, restores twice in isolation, and asserts that all three state roots match.
Scope and Limitations
- Snapshots are local-only. They capture the in-memory dev chain state and
cannot be imported into a production AtlasDB cluster.
- Snapshots record operations, not raw ledger state. If you perform operations
outside the recorded set (e.g., direct state manipulation) those changes will not be captured.
- No migration between incompatible runtime versions. Re-generate snapshots
after upgrading TREA runtime.
- The
contract_event_logis not included in the snapshot; events are
reconstructed when operations are replayed.