vaultId. The Vault enforces multi-party control over funds without any custodian.
How Vaults Work
Key Parameters
| Parameter | Type | Description |
|---|---|---|
vaultId | bytes32 | Unique identifier linking covenants to this vault |
requiredApprovals | int | M in M-of-N (currently max 2-of-3 pre-Loops CHIP) |
signer1Hash | bytes20 | hash160 of signer 1 pubkey |
signer2Hash | bytes20 | hash160 of signer 2 pubkey |
signer3Hash | bytes20 | hash160 of signer 3 pubkey |
periodDuration | int | Seconds per spending period (0 = no period cap) |
periodCap | int | Max satoshis spendable per period (0 = unlimited) |
recipientCap | int | Max satoshis per single spend (0 = unlimited) |
allowlistEnabled | int | 1 = only allowedAddr1/2/3 can receive funds |
allowedAddr1/2/3 | bytes20 | Recipient allowlist (up to 3 addresses pre-Loops CHIP) |
NFT State Layout (32 bytes)
Functions
spend() — Execute a payout with M-of-N approval
spend() — Execute a payout with M-of-N approval
Called by any M signers simultaneously. Verifies two distinct signers from the registered set, enforces period cap, recipient cap, and allowlist. Automatically rolls the period forward if
periodDuration has elapsed.unlockPeriod() — Roll period forward without spending
unlockPeriod() — Roll period forward without spending
Any registered signer can call this after
periodDuration has elapsed. Resets spent_this_period to 0 and increments current_period_id. Does not move any funds.pause() — Freeze the vault
pause() — Freeze the vault
Any single registered signer can pause the vault immediately. Use for fast incident response. Resume requires M-of-N.
resume() — Unfreeze the vault
resume() — Unfreeze the vault
Requires M-of-N signers. Transitions status from PAUSED back to ACTIVE.
emergencyLock() — Full lockdown
emergencyLock() — Full lockdown
Requires all 3 registered signers simultaneously. Transitions to
EMERGENCY_LOCK. No spending path is available from this state in the current contract version.Spending Roles
| Who | Can Do |
|---|---|
| Any single signer | pause(), unlockPeriod() |
| M-of-N signers | spend(), resume() |
| All N signers | emergencyLock() |
| No one | Override covenant math, skip period cap |
Pre-Loops CHIP, the vault hardcodes a maximum of 3 signers. Post-Loops CHIP activation will allow arbitrary N via dynamic signer arrays.

