You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The DLV (Deterministic Limbo Vault) lifecycle is not a closed settlement protocol in code. create and unlock
have real, self-contained effects, but claim and invalidation move no value — they flip an in-memory enum
and return unsigned operations whose balance handlers are explicit no-ops, and the SDK discards those operations.
Severity: Medium (correctness / stranded funds — not an active exploit). This is incomplete settlement
machinery, not a mint vulnerability: the credit paths were deliberately disabled because wiring them naively
enabled arbitrary mint (per the module's own notes on the reverted PR #196). The real risk is stranded funds
(DlvCreate debits the creator, but invalidation never re-credits) plus a false API contract (claim returns Ok while settling nothing).
Create (real, in-memory + debit): dsm/src/vault/limbo_vault.rs:1035,1210 (crypto), dsm/src/vault/dlv_manager.rs:98
(in-memory HashMap insert + unsigned DlvCreate). The one real value movement: dsm/src/core/token_state_manager.rs:360-396
debits the creator by locked_amount (insufficient-balance check at :379).
Unlock (real predicate verification, state-only by design): dsm/src/vault/limbo_vault.rs:1895 (verify_fulfillment,
then state = Unlocked); token_state_manager.rs:424 ("DlvUnlock is a state-only transition — no balance change"). Correct.
Claim — not wired:dsm/src/vault/limbo_vault.rs:1991 flips local state only (:2035,:2093), dBTC path
defers to draw_tap (:2028); dsm/src/vault/dlv_manager.rs:241 returns an unsigned DlvClaim with only a
proof hash (no token_id/amount/claimant credit); balance handler is a no-op
(token_state_manager.rs:413-422, let _ = claimant_public_key;); SDK discards the op
(dsm_sdk/src/sdk/dlv_sdk.rs:475, let (content, _op) = ...).
Invalidation — not wired:dsm/src/vault/limbo_vault.rs:2112 flips state only (:2145, no fund return); dlv_manager.rs:267 returns unsigned DlvInvalidate; balance handler is a no-op
(token_state_manager.rs:399-411); SDK discards the op (dsm_sdk/src/sdk/dlv_sdk.rs:497).
The module documents its own gap: dsm/src/vault/dlv_manager.rs:10-47 — DlvClaim/DlvInvalidate are
"unsigned signals — they do NOT themselves mutate token balances"; lists the per-vault state registry / claim
availability proof required by SoFi §10.3 as "NOT enforced"; notes PR core/token: unresolved tokens fall back to synthetic policy commits and DLV claim/invalidate remain non-atomic #196's naive credit path was reverted
because the fork lacks the registry and "the self-attested credit path enabled arbitrary mint."
dBTC vaults are masked because they carry locked_amount = None and settle out-of-band via dsm_sdk/src/sdk/bitcoin_tap_sdk.rs (draw_tap, mint/burn against Bitcoin SPV proofs). The token-ledger DLV path
is the dead one.
What closure requires
A per-vault encumbrance/claim registry (SMT leaf keyed by vault_id, Created→Claimed/Invalidated) consulted
atomically so locked_amount releases exactly once (prevents double-claim across stitched receipts). Scaffolding
exists in dsm/src/dlv/vault_smt_leaf.rs / vault_state_anchor.rs but is not consulted by claim/invalidate.
Carry token_id + locked_amount on Operation::DlvClaim / DlvInvalidate and implement the credit/restore
branches in token_state_manager.rs:399/:413, gated on the registry.
Stop discarding the operation in dsm_sdk/src/sdk/dlv_sdk.rs:475,497 — sign and submit it through the
transition path so the delta is part of an authoritative, hash-chained receipt.
Summary
The DLV (Deterministic Limbo Vault) lifecycle is not a closed settlement protocol in code.
createandunlockhave real, self-contained effects, but
claimandinvalidationmove no value — they flip an in-memory enumand return unsigned operations whose balance handlers are explicit no-ops, and the SDK discards those operations.
Severity: Medium (correctness / stranded funds — not an active exploit). This is incomplete settlement
machinery, not a mint vulnerability: the credit paths were deliberately disabled because wiring them naively
enabled arbitrary mint (per the module's own notes on the reverted PR #196). The real risk is stranded funds
(
DlvCreatedebits the creator, but invalidation never re-credits) plus a false API contract (claimreturnsOkwhile settling nothing).Evidence (
dsm_client/deterministic_state_machine/)dsm/src/vault/limbo_vault.rs:1035,1210(crypto),dsm/src/vault/dlv_manager.rs:98(in-memory HashMap insert + unsigned
DlvCreate). The one real value movement:dsm/src/core/token_state_manager.rs:360-396debits the creator by
locked_amount(insufficient-balance check at:379).dsm/src/vault/limbo_vault.rs:1895(verify_fulfillment,then
state = Unlocked);token_state_manager.rs:424("DlvUnlock is a state-only transition — no balance change"). Correct.dsm/src/vault/limbo_vault.rs:1991flips local state only (:2035,:2093), dBTC pathdefers to
draw_tap(:2028);dsm/src/vault/dlv_manager.rs:241returns an unsignedDlvClaimwith only aproof hash (no token_id/amount/claimant credit); balance handler is a no-op
(
token_state_manager.rs:413-422,let _ = claimant_public_key;); SDK discards the op(
dsm_sdk/src/sdk/dlv_sdk.rs:475,let (content, _op) = ...).dsm/src/vault/limbo_vault.rs:2112flips state only (:2145, no fund return);dlv_manager.rs:267returns unsignedDlvInvalidate; balance handler is a no-op(
token_state_manager.rs:399-411); SDK discards the op (dsm_sdk/src/sdk/dlv_sdk.rs:497).dsm/src/vault/dlv_manager.rs:10-47—DlvClaim/DlvInvalidateare"unsigned signals — they do NOT themselves mutate token balances"; lists the per-vault state registry / claim
availability proof required by SoFi §10.3 as "NOT enforced"; notes PR core/token: unresolved tokens fall back to synthetic policy commits and DLV claim/invalidate remain non-atomic #196's naive credit path was reverted
because the fork lacks the registry and "the self-attested credit path enabled arbitrary mint."
dBTC vaults are masked because they carry
locked_amount = Noneand settle out-of-band viadsm_sdk/src/sdk/bitcoin_tap_sdk.rs(draw_tap, mint/burn against Bitcoin SPV proofs). The token-ledger DLV pathis the dead one.
What closure requires
Created→Claimed/Invalidated) consultedatomically so
locked_amountreleases exactly once (prevents double-claim across stitched receipts). Scaffoldingexists in
dsm/src/dlv/vault_smt_leaf.rs/vault_state_anchor.rsbut is not consulted by claim/invalidate.token_id+locked_amountonOperation::DlvClaim/DlvInvalidateand implement the credit/restorebranches in
token_state_manager.rs:399/:413, gated on the registry.dsm_sdk/src/sdk/dlv_sdk.rs:475,497— sign and submit it through thetransition path so the delta is part of an authoritative, hash-chained receipt.
Affected files
dsm_client/deterministic_state_machine/dsm/src/vault/limbo_vault.rsdsm_client/deterministic_state_machine/dsm/src/vault/dlv_manager.rsdsm_client/deterministic_state_machine/dsm/src/core/token_state_manager.rsdsm_client/deterministic_state_machine/dsm_sdk/src/sdk/dlv_sdk.rsdsm_client/deterministic_state_machine/dsm/src/dlv/{vault_smt_leaf.rs,vault_state_anchor.rs}