Reference
Instructions
The six instructions: accounts, arguments, checks and errors for each.
Six instructions. The first two put value in and are deliberately permissive. The other four are the withdrawal. No instruction that moves value checks a signer against anything; a Signer appears only where something must pay fees or rent.
declare_id!("MeTaSpaceVau1t11111111111111111111111111111");init_vault
Open a vault behind a commitment. The signer pays rent and is recorded as a hint, not as an authority.
pub fn init_vault(ctx: Context<InitVault>, args: InitVaultArgs) -> Result<()>
pub struct InitVaultArgs {
pub commitment: [u8; 32], // hash of the 34 public-key chain endpoints
pub label: [u8; 16], // lets one owner hold several vaults
}Accounts
- payer (signer, mut)
- Pays the rent. Stored as owner_hint.
- vault (init)
- PDA at
["vault", payer, label]. 8 + 105 bytes. - system_program
- The system program.
Checks
commitment != [0; 32], elseZeroCommitment.
Effect
Writes commitment, nonce = 0, owner_hint = payer, label, created_at, rotations = 0, bump.
deposit
Fund a vault. Anyone may fund any vault; there is nothing to protect on the way in.
pub fn deposit(ctx: Context<Deposit>, lamports: u64) -> Result<()>Accounts
- depositor (signer, mut)
- The account the lamports leave.
- vault (mut)
- Any vault.
- system_program
- The system program.
Checks
lamports > 0, elseZeroAmount.
Effect
A system transfer of lamports from the depositor to the vault.
open_withdrawal
Write down the withdrawal before revealing anything. The digest of this request is what gets signed.
pub fn open_withdrawal(ctx: Context<OpenWithdrawal>, args: OpenWithdrawalArgs) -> Result<()>
pub struct OpenWithdrawalArgs {
pub amount: u64, // lamports
pub destination: Pubkey,
pub next_commitment: [u8; 32], // what the lock becomes afterwards
}Accounts
- payer (signer, mut)
- Pays the request's rent and gets it back. Proves nothing about the vault.
- vault (mut)
- PDA at
["vault", owner_hint, label]. - request (init)
- PDA at
["request", vault, vault.nonce]. 8 + 1,246 bytes. - system_program
- The system program.
Checks
amount > 0, elseZeroAmount.next_commitment != [0; 32], elseZeroCommitment.next_commitment != vault.commitment, elseCommitmentReused.
Effect
Writes vault, nonce = vault.nonce, amount, destination, next_commitment, an empty chain_endpoints, chains_filled = 0, opened_at, payer, bump.
push_signature
Deliver up to 8 chains of the one-time signature, verifying each walk as it arrives.
pub fn push_signature(ctx: Context<PushSignature>, values: Vec<[u8; 32]>) -> Result<()>Accounts
- submitter (signer)
- Anyone. Pays the fee and nothing else.
- vault
- PDA at
["vault", owner_hint, label]. - request (mut)
- PDA at
["request", vault, request.nonce], withrequest.vault == vault.
Checks
- The request is not already complete, else
SignatureComplete. request.nonce == vault.nonce, elseStaleNonce.1 <= values.len() <= 8andchains_filled + values.len() <= 34, elseChainOutOfOrder.
Effect
For each value, at index chains_filled + i, computes the chain length from the request’s digest, walks the value the remaining 255 - m steps, and appends the endpoint. Advances chains_filled.
finalize_withdrawal
Check the accumulated endpoints against the commitment, pay the destination, rotate the lock. Permissionless.
pub fn finalize_withdrawal(ctx: Context<FinalizeWithdrawal>) -> Result<()>Accounts
- vault (mut)
- PDA at
["vault", owner_hint, label]. - request (mut, close)
- PDA at
["request", vault, request.nonce]. Closed torent_recipient. - destination (mut)
- Must equal
request.destination. May be a wallet, a PDA or a program-owned account. - rent_recipient (mut)
- Must equal
request.payer.
Checks
- All 34 chains are present, else
SignatureIncomplete. request.nonce == vault.nonce, elseStaleNonce.commitment_of(chain_endpoints) == vault.commitment, elseCommitmentMismatch.- The vault keeps at least its rent-exempt minimum after paying, else
InsufficientFunds.
Effect
Moves amount lamports from the vault to the destination. Sets vault.commitment = next_commitment, increments vault.nonce and vault.rotations. Closes the request and returns its rent to the payer. Arithmetic that overflows fails with Overflow.
cancel_withdrawal
Reclaim an abandoned or superseded request. Permissionless, and expiry-gated while the request is live.
pub fn cancel_withdrawal(ctx: Context<CancelWithdrawal>) -> Result<()>Accounts
- vault
- PDA at
["vault", owner_hint, label]. - request (mut, close)
- PDA at
["request", vault, request.nonce]. Closed torent_recipient. - rent_recipient (mut)
- Must equal
request.payer.
Checks
- If
request.nonce == vault.nonce, thennow - opened_at >= 86400, elseNotExpired. A request whose nonce no longer matches closes without waiting.
Effect
Closes the request and returns its rent to the payer.
Every error above is listed with its message in Errors.