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 rulesEvery 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).
| Argument | Type |
|---|
params | PoslParams |
| Account | Kind | Constraints | Note |
|---|
state | account | created, writable, PDA "posl_state" | |
main_tree | zero-copy account | created, writable, PDA "posl_main" | |
stake_tree | zero-copy account | created, writable, PDA "posl_stake" | |
credit_tree | zero-copy account | created, writable, PDA "posl_credit" | |
epoch0 | account | created, writable, PDA "posl_epoch" | |
mint | account | | |
vault | account | created if missing, writable, pool vault (ATA of the state) | |
authority | signer | writable | |
token_program | program | | |
associated_token_program | program | | |
system_program | program | | |
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).
| Argument | Type |
|---|
params | PoslParams |
| Account | Kind | Constraints | Note |
|---|
state | account | writable, PDA "posl_state", must be the pool authority | |
authority | signer | | |
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).
| Account | Kind | Constraints | Note |
|---|
state | account | writable, PDA "posl_state", must be the pool authority | |
authority | signer | | |
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.
| Account | Kind | Constraints | Note |
|---|
state | account | writable, PDA "posl_state" | |
prev_epoch | account | PDA "posl_epoch" | |
new_epoch | account | created if missing, writable, PDA "posl_epoch" | |
stake_tree | zero-copy account | PDA "posl_stake" | |
payer | signer | writable | |
system_program | program | | |
posl_fund#
Anyone adds ZEC to the current epoch's budget, split by stake_share_bps. Amount must be above 0.
| Account | Kind | Constraints | Note |
|---|
state | account | writable, PDA "posl_state" | |
epoch | account | writable, PDA "posl_epoch" | |
vault | account | writable, pool vault (ATA of the state), mint = pool mint | |
funder_token_account | account | writable, mint = pool mint | |
funder | signer | | |
token_program | program | | |
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.
| Account | Kind | Constraints | Note |
|---|
state | account | writable, PDA "posl_state" | |
epoch_account | account | writable, PDA "posl_epoch" | |
current_epoch | account | writable, 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).
| Argument | Type |
|---|
proof | Groth16Proof |
root | [u8; 32] |
input_nullifiers | [[u8; 32]; 2] |
output_commitments | [[u8; 32]; 2] |
ext_amount | i64 |
fee | u64 |
encrypted_output1 | Vec<u8> |
encrypted_output2 | Vec<u8> |
credit_pubkey | [u8; 32] |
| Account | Kind | Constraints | Note |
|---|
state | account | writable, PDA "posl_state" | |
epoch | account | writable, PDA "posl_epoch" | |
main_tree | zero-copy account | writable, PDA "posl_main" | |
credit_tree | zero-copy account | writable, PDA "posl_credit" | |
nullifier0 | account | created, writable, PDA "posl_nf0" | |
nullifier1 | account | created, writable, PDA "posl_nf1" | |
nullifier2 | must not exist | PDA "posl_nf0" | Cross checks: a nullifier used in one slot cannot be reused in the other. |
nullifier3 | must not exist | PDA "posl_nf1" | |
vault | account | writable, pool vault (ATA of the state), mint = pool mint | |
signer_token_account | account | writable, mint = pool mint | |
recipient_token_account | account | writable, mint = pool mint | |
fee_recipient_ata | account | writable, mint = pool mint | |
signer | signer | writable | |
token_program | program | | |
system_program | program | | |
instructions | sysvar | fixed address | the 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.
| Argument | Type |
|---|
proof | Groth16Proof |
root | [u8; 32] |
input_nullifiers | [[u8; 32]; 2] |
change_commitment | [u8; 32] |
locked_commitment | [u8; 32] |
denom | u64 |
lock_epoch | u32 |
fee | u64 |
encrypted_change | Vec<u8> |
encrypted_locked | Vec<u8> |
| Account | Kind | Constraints | Note |
|---|
state | account | writable, PDA "posl_state" | |
main_tree | zero-copy account | writable, PDA "posl_main" | |
stake_tree | zero-copy account | writable, PDA "posl_stake" | |
expiry_epoch | account | created if missing, writable, PDA "posl_epoch" | |
nullifier0 | account | created, writable, PDA "posl_nf0" | |
nullifier1 | account | created, writable, PDA "posl_nf1" | |
nullifier2 | must not exist | PDA "posl_nf0" | |
nullifier3 | must not exist | PDA "posl_nf1" | |
vault | account | writable, pool vault (ATA of the state), mint = pool mint | |
fee_recipient_ata | account | writable, mint = pool mint | |
signer | signer | writable | |
token_program | program | | |
system_program | program | | |
instructions | sysvar | fixed address | the 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.
| Argument | Type |
|---|
proof | Groth16Proof |
stake_root | [u8; 32] |
nullifier | [u8; 32] |
output_commitment | [u8; 32] |
fee | u64 |
encrypted_output | Vec<u8> |
| Account | Kind | Constraints | Note |
|---|
state | account | PDA "posl_state" | |
main_tree | zero-copy account | writable, PDA "posl_main" | |
stake_tree | zero-copy account | PDA "posl_stake" | |
stake_nullifier | account | created, writable, PDA "posl_snf" | |
vault | account | writable, pool vault (ATA of the state), mint = pool mint | |
fee_recipient_ata | account | writable, mint = pool mint | |
signer | signer | writable | |
token_program | program | | |
system_program | program | | |
instructions | sysvar | fixed address | the 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.
| Argument | Type |
|---|
proof | Groth16Proof |
epoch | u32 |
stake_root | [u8; 32] |
reward_nullifier | [u8; 32] |
reward_commitment | [u8; 32] |
encrypted_output | Vec<u8> |
| Account | Kind | Constraints | Note |
|---|
state | account | writable, PDA "posl_state" | |
epoch_account | account | writable, PDA "posl_epoch" | |
main_tree | zero-copy account | writable, PDA "posl_main" | |
stake_tree | zero-copy account | PDA "posl_stake" | |
reward_nullifier_account | account | created, writable, PDA "posl_rnf" | |
signer | signer | writable | |
system_program | program | | |
instructions | sysvar | fixed address | the 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.
| Argument | Type |
|---|
proof | Groth16Proof |
epoch | u32 |
credit_root | [u8; 32] |
credit_nullifiers | [[u8; 32]; 4] |
reward_commitment | [u8; 32] |
encrypted_output | Vec<u8> |
| Account | Kind | Constraints | Note |
|---|
state | account | writable, PDA "posl_state" | |
epoch_account | account | writable, PDA "posl_epoch" | |
main_tree | zero-copy account | writable, PDA "posl_main" | |
credit_tree | zero-copy account | PDA "posl_credit" | |
credit_nf0 | account | created, writable, PDA "posl_cnf" | |
credit_nf1 | account | created, writable, PDA "posl_cnf" | |
credit_nf2 | account | created, writable, PDA "posl_cnf" | |
credit_nf3 | account | created, writable, PDA "posl_cnf" | |
signer | signer | writable | |
system_program | program | | |
instructions | sysvar | fixed address | the instructions sysvar (address checked), read by require_clean_logs. |