stacks-block-time (the current block timestamp) and last-heartbeat (the timestamp of the owner’s most recent heartbeat). No separate transaction is required to advance the state.
The Five States
Active
The heartbeat timer is running and within the configured interval. The vault is fully locked. Only the owner can interact with it (heartbeat, deposit, update heirs, emergency-withdraw).
Grace
The heartbeat interval has expired but the grace period has not. Heirs cannot claim yet. The guardian (if set) can use their one-time pause here to extend the deadline by 30 days.
Claimable
Both the heartbeat interval and grace period have expired. Each registered heir can independently call
claim() to receive their share. The owner can still send a heartbeat to recover the vault if not all heirs have claimed.Distributed
All heirs have successfully claimed their shares. The vault is closed. No further actions are possible. The owner may create a new vault from the same address.
Cancelled
The owner called
emergency-withdraw() before distribution completed. All assets were returned to the owner. The vault is closed (internally, is-distributed is set to true). A new vault can be created from the same address.State Transition Diagram
How State Is Computed
Vault state is not stored as an enum. There is nostate field in the on-chain vault map. Instead, the get-vault-status read-only function derives state fresh on every call:
elapsed=stacks-block-time−last-heartbeatdeadline=heartbeat-interval+grace-period+ (2,592,000 ifguardian-pause-used, else 0)
get-vault-status is always current — there is no window where a vault appears active but is secretly claimable.
State Reference Table
| State | Condition | Owner Can | Heirs Can | Guardian Can |
|---|---|---|---|---|
| active | elapsed < interval | Heartbeat, Deposit, Update heirs, Emergency-withdraw | — | — |
| grace | interval ≤ elapsed < deadline | Heartbeat, Deposit, Update heirs, Emergency-withdraw | — | Pause (once) |
| claimable | elapsed ≥ deadline | Heartbeat (recovery), Emergency-withdraw | Claim | — |
| distributed | is-distributed = true | Create new vault | — | — |
| cancelled | is-distributed = true (via emergency-withdraw) | Create new vault | — | — |
Time Calculation Fields
Theget-vault-status response includes pre-computed time fields so you don’t need to calculate them manually:
| Field | Meaning |
|---|---|
elapsed-seconds | Seconds since last-heartbeat |
seconds-until-grace | Seconds remaining before grace begins (0 if already in grace or beyond) |
seconds-until-claimable | Seconds remaining before heirs can claim (0 if already claimable) |
Guardian Pause Effect on Lifecycle
When the guardian callsguardian-pause() during the grace period, the contract sets guardian-pause-used = true. This adds GUARDIAN-PAUSE-BONUS (2,592,000 seconds = 30 days) to the effective deadline used in all subsequent state computations.
guardian-pause-used flag persists.
Even after a guardian pause is used, the owner can still heartbeat to reset the timer. The pause bonus only matters if the owner fails to recover.
Emergency Withdrawal
The owner can callemergency-withdraw() at any time before the vault is fully distributed. This:
- Returns all sBTC and USDCx to the owner’s wallet.
- Sets
sbtc-balanceandusdcx-balanceto zero. - Sets
is-distributed = true, closing the vault.
CANCELLED state. It is indistinguishable from a distributed vault at the contract level (is-distributed = true in both cases). A new vault can be created from the same address.
