Skip to content

Animica L2 — Transaction Lifecycle

The explicit state machine every L2 transaction moves through, from submission to L1 settlement, and what each status does and does not guarantee about finality.

4 min read 839 words View docs/l2/TRANSACTION_LIFECYCLE.md on GitHub

Source: docs/l2/TRANSACTION_LIFECYCLE.md — this page mirrors the repository documentation.

Every L2 transaction moves through an explicit state machine (l2/constants.py::TxStatus). The design rule is honesty about finality: sequencer acceptance is never presented as L1 finality.

The nine states

#StateMeaningSet where
1RECEIVEDRaw bytes arrived at the sequencer; decoded, not yet judgedSequencer.submit
2VALIDATEDPassed cheap structural checks (size limits, chain id, scheme) and dedupeadmission pipeline
3SOFT_CONFIRMEDSignature verified (ML-DSA-65) + nonce/balance admission passed; ordered into the open batch. The sequencer promises inclusionadmission pipeline
4BATCHEDThe batch containing the tx closed and executed; the tx has a receipt and is inside a committed batch with a header + DA blobSequencer.tick_seal
5PROVENThe batch’s proof was generated by the active settlement backend (l2/proof.py)seal pipeline
6L1_SUBMITTEDThe batch commitment (state root + DA) has been submitted to Animica L1 as an anchoring tx to the bridge addresssettlement submitter
7L1_FINALIZEDThe anchoring L1 tx is L1_FINALITY_DEPTH (64) blocks deep. This is real finality: withdrawals in this batch become claimable on L1L1 tracking
8FAILEDRejected before ordering (bad signature, bad nonce, insufficient balance, queue full, expired, oversized…). Never entered a batch; TxRecord.reason says whyadmission pipeline
9REVERTEDAdmitted, executed inside a batch, but the authoritative re-validation at execution time failed (e.g. balance raced away). The tx changed nothing but is part of the batch record with a reverted receiptexecutor

Terminal states: L1_FINALIZED, FAILED, REVERTED.

Notes:

  • Admission (step 3) is an optimization, never trusted: the executor re-validates nonce/balance/expiry authoritatively at execution time. That is why REVERTED exists as distinct from FAILED.
  • In the all-in-one dev node, SOFT_CONFIRMED → BATCHED → PROVEN can happen within one tick(); a production deployment separates proving and settlement onto their own services behind the same interfaces.

Three grades of confirmation

GradeState(s)Who vouchesAppropriate for
SoftSOFT_CONFIRMEDThe designated sequencer alone (a promise)Low-value UX: show “paid” optimistically, small-amount micropayments between parties who already accept sequencer trust
ProvenBATCHED + PROVENDeterministic re-execution: anyone with the DA blob + prior state can verify the transition (l2_verifyBatch)Values where you want the tx to be independently checkable but can tolerate the anchoring not yet being L1-final
L1-finalizedL1_FINALIZEDAnimica L1 consensus (anchoring tx 64 blocks deep)Withdrawals, exchange credits, anything irreversible

Worked user flow (the README example)

Alice deposits 10,000 ANM to L2, pays Bob 25 ANM, and Bob exits to L1. All amounts on the wire are integer nanos (1 ANM = 10⁹ nanos).

 1. DEPOSIT      Alice sends 10,000 ANM on L1 to the canonical bridge address,
                 memo magic ANML2D1 naming her L2 account.
                     └─ bridge observes it: OBSERVED → CONFIRMED (12 blocks)
                        → FINALIZED (64 blocks).  Not credited before that —
                        an L1 reorg must never mint L2 ANM.

 2. CREDIT       Once FINALIZED, a protocol-minted DEPOSIT_CLAIM credits
                 Alice's L2 account 10,000 ANM (fee = 0 for deposit claims).
                 The bridge marks the deposit credited; locked_on_l1 and
                 credited_total move in lockstep.

 3. SEND         Alice signs a TRANSFER of 25 ANM (25_000_000_000 nanos) to
                 Bob with her ML-DSA-65 key and submits it
                 (l2_sendRawTransaction).           → RECEIVED → VALIDATED

 4. SOFT-CONFIRM Signature + nonce/balance admission pass in milliseconds.
                                                    → SOFT_CONFIRMED
                 Bob's wallet can show the incoming 25 ANM as "pending".

 5. BATCH        The open batch closes (tx count / bytes / age — default
                 250 ms max age).  Deterministic execution debits Alice
                 25 ANM + fee, credits Bob 25 ANM, fee → L2 treasury.
                                                    → BATCHED

 6. ROOT         The batch header commits prev_state_root → new_state_root
                 (plus transactions/receipts/escrow/data roots).

 7. PROOF        The VALIDITY backend produces the proof (DA blob + public
                 inputs); anyone can re-derive the new root from it.
                                                    → PROVEN

 8. L1 SETTLE    The commitment is submitted to L1 (memo ANML2C1).
                                                    → L1_SUBMITTED
                 64 L1 blocks later:                → L1_FINALIZED

 9. WITHDRAW     Bob signs a WITHDRAW of his 25 ANM naming his L1 address.
                 It burns on L2 (state BURNED, unique nullifier =
                 sha3_256(withdraw txid)).  When its batch reaches
                 L1_FINALIZED the withdrawal becomes CLAIMABLE; Bob's L1
                 claim spends the nullifier exactly once and the bridge
                 releases 25 ANM of locked L1 funds.        → CLAIMED

At every step the conservation invariant holds: balances + open escrows + unclaimed burns == credited_total − claimed_on_l1, and withdrawable value never exceeds ANM locked on L1.

Querying status

  • l2_getTransaction(txid){status, batchNumber, reason, receiptStatus, receivedMs}
  • l2_getReceipt(txid) → execution receipt once BATCHED
  • l2_getBatch(n) / l2_getBatchData(n) → header / DA blob
  • l2_getProofStatus(n), l2_verifyBatch(n) → proof + independent re-verification
  • Withdrawals: l2_getWithdrawalProof(nullifier); deposits: l2_getDeposit(depositId)

This page mirrors a file in the animicaorg/all repository. If the repository and this page ever disagree, the repository is authoritative. For long-form explainers written for newcomers, see Learn.