Verax program reference.
Verax is a Solana program plus a thin TypeScript SDK. This page documents the on-chain instructions, the account layouts, the trust-to-cap formula, and the deployment status.
Eight primitives.
Single program-derived address holds capital under your authority. Seeds: ["reserve", authority]. The PDA has no private key; only the program can move funds.
Per-agent sub-account derived as ["lane", reserve, handle]. Holds: trust score (bps), base daily cap (lamports), spent window, runs, paused flag.
u16 basis points (0–10000). Initialised at 5000 = 0.50. Updated by attest(deltaBps). Clamped to [50, 9900].
effective_cap = base × mult(trust_bps). The multiplier is a piecewise-linear sigmoid approximation — verified inside settle, atomic revert on overflow.
Off-chain in v0.1. Planned: on-chain allowlist with mutate-by-authority and mutate-by-quorum modes.
Off-chain in v0.1. Planned: window enforcement using Solana clock (Clock::get) inside settle.
Off-chain in v0.1. Planned: permissionless crank that refills lanes from reserve when balance < floor.
Off-chain in v0.1. Planned: m-of-n proposals, automatically required when amount > k(trust).
Cap formula.
Trust is stored as u16 basis points in [50, 9900]. The on-chain settle instruction multiplies the lane's base daily cap by a piecewise-linear approximation of a sigmoid centred at trust=0.50. Misbehaviour shrinks the cap fast; earned trust grows it gently and asymptotes near ×2.45.
fn cap_multiplier_bps(trust_bps: u16) -> u32 {
let t = trust_bps as u32;
match t {
0..=2500 => 500 + (t * 600) / 2500, // 0.05× → 0.11×
2501..=5000 => 1100 + ((t - 2500) * 8900) / 2500, // 0.11× → 1.00×
5001..=8500 => 10_000 + ((t - 5000) * 11_000) / 3500, // 1.00× → 2.10×
_ => 21_000 + ((t.min(10_000) - 8500) * 3500) / 1500, // 2.10× → 2.45×
}
}
fn effective_cap(base: u64, trust_bps: u16) -> u64 {
((base as u128) * (cap_multiplier_bps(trust_bps) as u128) / 10_000) as u64
}Five on-chain instructions.
pub fn create_reserve(name: String) -> Result<()>
- — authority (signer, mut)
- — reserve (init, pda)
- — system_program
Creates the reserve PDA under the signing wallet. One reserve per authority.
pub fn open_lane(handle: String, base_daily_cap_lamports: u64) -> Result<()>
- — authority (signer, mut)
- — reserve (mut)
- — lane (init, pda)
- — system_program
Opens a per-agent lane. trust_bps starts at 5000.
pub fn attest(delta_bps: i32) -> Result<()>
- — authority (signer)
- — reserve
- — lane (mut)
Mutates trust. v0.1: only authority. v0.2: signed attestations from approved attestors.
pub fn set_paused(paused: bool) -> Result<()>
- — authority (signer)
- — reserve
- — lane (mut)
Pause/resume a lane. Paused lanes reject settle.
pub fn settle(amount_lamports: u64) -> Result<()>
- — authority (signer)
- — reserve (mut, PDA signer)
- — lane (mut)
- — recipient (mut)
- — system_program
Atomic: checks pause + cap, transfers from reserve PDA via CPI, updates lane.spent_window.
What's stored on chain.
authority : Pubkey name : String (max 32) lane_count : u32 created_at : i64 bump : u8 seeds : ["reserve", authority]
reserve : Pubkey handle : String (max 32) base_daily_cap : u64 (lamports) trust_bps : u16 (0..10000) spent_window : u64 window_start : i64 runs : u64 paused : bool bump : u8 seeds : ["lane", reserve, handle]
Quickstart.
- 01Open the console and connect Phantom or Solflare. Switch the wallet to Devnet.
- 02Use the wallet dropdown → Request 1 devnet SOL if you have nothing.
- 03In the Your reserve panel, click Create reserve — one signature.
- 04Open a lane (handle + base cap in SOL), top the reserve up, and try attest +200 / −200 bps to watch the cap move.
- 05Click settle ↗ to send SOL out of the reserve PDA through the program.