posl docs
poslProtocol reference

Instructions

Every PoSL instruction of the zkcash program: what it does, its arguments, its accounts and the checks it runs, in the order they run. Argument and account tables are read from the source.

Common rules

Every instruction that grows a tree (transact, lock, unlock, both claims) must run at the top level of the transaction, after compute-budget instructions only (UnsafeTransaction). Solana keeps only 10 KB of logs per transaction; this rule stops anyone from cutting the events wallets need to rebuild the trees. Every proof is checked with public inputs that are all below the BN254 field size, and proof point A is validated before the pairing.

posl_initialize#

Creates the pool once: state, the three trees, epoch 0 (opened), and the vault. Checks: the signer is the admin written in the program (mainnet, devnet); check_params; on mainnet the mint must be the ZEC SPL mint A7bdiYdS5GjqGFtxf17ppRHtDKPkkRqbKtR27dxvQXaS (WrongMint).

ArgumentType
paramsPoslParams
AccountKindConstraintsNote
stateaccountcreated, writable, PDA "posl_state"
main_treezero-copy accountcreated, writable, PDA "posl_main"
stake_treezero-copy accountcreated, writable, PDA "posl_stake"
credit_treezero-copy accountcreated, writable, PDA "posl_credit"
epoch0accountcreated, writable, PDA "posl_epoch"
mintaccount
vaultaccountcreated if missing, writable, pool vault (ATA of the state)
authoritysignerwritable
token_programprogram
associated_token_programprogram
system_programprogram

posl_update_params#

Admin only (has_one = authority). Runs check_params, refuses a new epoch length, and stores the parameters as pending. posl_advance_epoch applies them after the delay (Admin powers).

ArgumentType
paramsPoslParams
AccountKindConstraintsNote
stateaccountwritable, PDA "posl_state", must be the pool authority
authoritysigner

posl_set_paused#

Admin only (has_one = authority), immediate. Sets paused. While paused, posl_transact refuses a deposit (ext_amount > 0) and posl_lock refuses every lock (Paused). Withdrawals, private transfers, unlocks and claims are not touched (Admin powers).

ArgumentType
pausedbool
AccountKindConstraintsNote
stateaccountwritable, PDA "posl_state", must be the pool authority
authoritysigner

posl_advance_epoch#

Permissionless. Opens epoch = current + 1 once now >= genesis_ts + epoch_len * epoch (WrongEpoch, EpochNotOver). Applies a due pending parameter change, removes the locks that ended with the previous epoch from active_stake, and snapshots active_stake and stake_start_index for the new epoch. Creates the epoch account if a lock has not created it already.

ArgumentType
epochu32
AccountKindConstraintsNote
stateaccountwritable, PDA "posl_state"
prev_epochaccountPDA "posl_epoch"
new_epochaccountcreated if missing, writable, PDA "posl_epoch"
stake_treezero-copy accountPDA "posl_stake"
payersignerwritable
system_programprogram

posl_fund#

Anyone adds ZEC to the current epoch's budget, split by stake_share_bps. Amount must be above 0.

ArgumentType
amountu64
AccountKindConstraintsNote
stateaccountwritable, PDA "posl_state"
epochaccountwritable, PDA "posl_epoch"
vaultaccountwritable, pool vault (ATA of the state), mint = pool mint
funder_token_accountaccountwritable, mint = pool mint
fundersigner
token_programprogram

posl_finalize_epoch#

Permissionless. For an epoch before the current one, opened and not yet finalized: fixes stake_rate and volume_rate, records what they allocate, rolls the rest into the current epoch, adds the allocation to total_allocated and emits PoslEpochFinalized.

ArgumentType
epochu32
AccountKindConstraintsNote
stateaccountwritable, PDA "posl_state"
epoch_accountaccountwritable, PDA "posl_epoch"
current_epochaccountwritable, PDA "posl_epoch"

posl_transact#

Deposit (ext_amount > 0), withdrawal (< 0) or private transfer (= 0) through the unmodified core circuit transaction2. Checks, in order: clean logs; the signer owns signer_token_account; the root is known; publicAmount = ext_amount - fee (a deposit must exceed its fee); the fee matches the deposit or withdrawal rate within the margin; the credit key and blinding are field elements; the proof, with the ext data hash computed on chain. Then: moves tokens (deposit capped by max_deposit_amount), pays the relayer share of the fee, adds the protocol share to the epoch budgets, appends both outputs to the main tree, and appends a volume credit worth credit_value(fee) to the credit tree when above 0. The credit blinding is the first input nullifier (unique and already public).

ArgumentType
proofGroth16Proof
root[u8; 32]
input_nullifiers[[u8; 32]; 2]
output_commitments[[u8; 32]; 2]
ext_amounti64
feeu64
encrypted_output1Vec<u8>
encrypted_output2Vec<u8>
credit_pubkey[u8; 32]
AccountKindConstraintsNote
stateaccountwritable, PDA "posl_state"
epochaccountwritable, PDA "posl_epoch"
main_treezero-copy accountwritable, PDA "posl_main"
credit_treezero-copy accountwritable, PDA "posl_credit"
nullifier0accountcreated, writable, PDA "posl_nf0"
nullifier1accountcreated, writable, PDA "posl_nf1"
nullifier2must not existPDA "posl_nf0"Cross checks: a nullifier used in one slot cannot be reused in the other.
nullifier3must not existPDA "posl_nf1"
vaultaccountwritable, pool vault (ATA of the state), mint = pool mint
signer_token_accountaccountwritable, mint = pool mint
recipient_token_accountaccountwritable, mint = pool mint
fee_recipient_ataaccountwritable, mint = pool mint
signersignerwritable
token_programprogram
system_programprogram
instructionssysvarfixed addressthe instructions sysvar (address checked), read by require_clean_logs.

posl_lock#

Moves a denomination from the main tree to the stake tree. Checks: clean logs; denom is one of the pool's denominations (InvalidDenomination); current < lock_epoch <= current + max_lock_epochs (InvalidLockEpoch); fee <= max_relayer_fee; known root; the lock proof. Then: pays the fee to the relayer, appends the change note (main) and the locked note (stake), adds the size to the end epoch's expiring, to active_stake and to total_locked.

ArgumentType
proofGroth16Proof
root[u8; 32]
input_nullifiers[[u8; 32]; 2]
change_commitment[u8; 32]
locked_commitment[u8; 32]
denomu64
lock_epochu32
feeu64
encrypted_changeVec<u8>
encrypted_lockedVec<u8>
AccountKindConstraintsNote
stateaccountwritable, PDA "posl_state"
main_treezero-copy accountwritable, PDA "posl_main"
stake_treezero-copy accountwritable, PDA "posl_stake"
expiry_epochaccountcreated if missing, writable, PDA "posl_epoch"
nullifier0accountcreated, writable, PDA "posl_nf0"
nullifier1accountcreated, writable, PDA "posl_nf1"
nullifier2must not existPDA "posl_nf0"
nullifier3must not existPDA "posl_nf1"
vaultaccountwritable, pool vault (ATA of the state), mint = pool mint
fee_recipient_ataaccountwritable, mint = pool mint
signersignerwritable
token_programprogram
system_programprogram
instructionssysvarfixed addressthe instructions sysvar (address checked), read by require_clean_logs.

posl_unlock#

Returns a locked note after its end epoch. Checks: clean logs; fee <= max_relayer_fee; known stake root; the unlock proof with the current epoch as public input (the circuit proves lockEpoch < currentEpoch). Creates the unlock marker, pays the fee, appends the output note.

ArgumentType
proofGroth16Proof
stake_root[u8; 32]
nullifier[u8; 32]
output_commitment[u8; 32]
feeu64
encrypted_outputVec<u8>
AccountKindConstraintsNote
stateaccountPDA "posl_state"
main_treezero-copy accountwritable, PDA "posl_main"
stake_treezero-copy accountPDA "posl_stake"
stake_nullifieraccountcreated, writable, PDA "posl_snf"
vaultaccountwritable, pool vault (ATA of the state), mint = pool mint
fee_recipient_ataaccountwritable, mint = pool mint
signersignerwritable
token_programprogram
system_programprogram
instructionssysvarfixed addressthe instructions sysvar (address checked), read by require_clean_logs.

posl_claim_stake#

One locked note, one finalized epoch (NotFinalized). The proof uses the epoch's stake_start_index and stake_rate as public inputs. Creates the reward marker ["posl_rnf", reward_nullifier], appends the reward note, counts the claim.

ArgumentType
proofGroth16Proof
epochu32
stake_root[u8; 32]
reward_nullifier[u8; 32]
reward_commitment[u8; 32]
encrypted_outputVec<u8>
AccountKindConstraintsNote
stateaccountwritable, PDA "posl_state"
epoch_accountaccountwritable, PDA "posl_epoch"
main_treezero-copy accountwritable, PDA "posl_main"
stake_treezero-copy accountPDA "posl_stake"
reward_nullifier_accountaccountcreated, writable, PDA "posl_rnf"
signersignerwritable
system_programprogram
instructionssysvarfixed addressthe instructions sysvar (address checked), read by require_clean_logs.

posl_claim_volume#

Up to four credit notes of one finalized epoch. The proof uses the epoch's volume_rate; the circuit refuses a reward of 0. Creates four credit markers, appends the reward note, counts the claim.

ArgumentType
proofGroth16Proof
epochu32
credit_root[u8; 32]
credit_nullifiers[[u8; 32]; 4]
reward_commitment[u8; 32]
encrypted_outputVec<u8>
AccountKindConstraintsNote
stateaccountwritable, PDA "posl_state"
epoch_accountaccountwritable, PDA "posl_epoch"
main_treezero-copy accountwritable, PDA "posl_main"
credit_treezero-copy accountPDA "posl_credit"
credit_nf0accountcreated, writable, PDA "posl_cnf"
credit_nf1accountcreated, writable, PDA "posl_cnf"
credit_nf2accountcreated, writable, PDA "posl_cnf"
credit_nf3accountcreated, writable, PDA "posl_cnf"
signersignerwritable
system_programprogram
instructionssysvarfixed addressthe instructions sysvar (address checked), read by require_clean_logs.