~/bend-docscommunity

sol.bend source

sol.bend on the hub · documented module

import Base# Shared Solana view. The runtime maps the transaction onto this first-order# World. List<&2, U32> is the account-data word view: the checker sees a# linked list; the compiler emits O(1) slice ops (zero-copy).## PDA derivation and system-transfer CPI are trusted primitives. Prove# `pda_matches` / `Pubkey.eq` and the helpers below — not SHA256.type Pubkey is Data:  Pk{w0: U32, w1: U32, w2: U32, w3: U32, w4: U32, w5: U32, w6: U32, w7: U32}# Book U64: two little-endian U32 words. The C backend implements# U64.* as a real machine u64; on-chain lamports and token amounts# are never truncated.type U64 is Data:  U64{lo: U32, hi: U32}type Account is Data:  Acc{    key: Pubkey,    owner: Pubkey,    lamports: U64,    data: List<&2, U32>,    is_signer: Bool,    is_writable: Bool  }# Stand-in for find_program_address([seed_le, owner], program_id).# On-chain the compiler replaces derive_pda / find_pda with the syscall.type Pda is Data:  Pda{key: Pubkey, bump: U32}# Two CPI slots. queue_cpi fills cpi then cpi1. The runtime invokes# both after process returns Ok. Indices are World account slots.type Cpi is Data:  CpiNone{}  CpiTransfer{from: U32, to: U32, lamports: U64, sign: Bool, bump: U32}  CpiTokenTransfer{from: U32, to: U32, mint: U32, auth: U32, amount: U64, decimals: U32, sign: Bool, bump: U32}type World is Data:  World{    n: U32,    ix0: U32,    ix1: U64,    ix2: U64,    ix3: U64,    pda_seed: U32,    program_id: Pubkey,    a0: Account,    a1: Account,    a2: Account,    a3: Account,    a4: Account,    a5: Account,    a6: Account,    a7: Account,    cpi: Cpi,    cpi1: Cpi  }type Outcome is Data:  Ok{world: World}  Err{code: U32}def ok(+w: World) -> Outcome:  Ok{w}def fail(+code: U32) -> Outcome:  Err{code}def E.ok() -> U32:  0def E.accounts() -> U32:  1def E.data() -> U32:  2def E.auth() -> U32:  3def E.init() -> U32:  4def E.missing() -> U32:  5def E.overflow() -> U32:  6def E.underflow() -> U32:  7def E.threshold() -> U32:  8def E.executed() -> U32:  9def E.owner() -> U32:  10def E.pda() -> U32:  11def E.cpi() -> U32:  12def E.token() -> U32:  13def U64.pack(lo: U32, hi: U32) -> U64:  U64{lo, hi}def U64.from_u32(lo: U32) -> U64:  U64{lo, 0}def U64.zero() -> U64:  U64{0, 0}def U64.lo(x: U64) -> U32:  match x:    case U64{+lo, hi}:      lodef U64.hi(x: U64) -> U32:  match x:    case U64{lo, +hi}:      hidef U64.is_eq(+a: U64, +b: U64) -> Bool:  match a b:    case U64{+a0, +a1} U64{+b0, +b1}:      Bool.and(U32.is_eq(a0, b0), U32.is_eq(a1, b1))def U64.is_ne(+a: U64, +b: U64) -> Bool:  Bool.not(U64.is_eq(a, b))def U64.is_lt(+a: U64, +b: U64) -> Bool:  match a b:    case U64{+a0, +a1} U64{+b0, +b1}:      Bool.or(U32.is_lt(a1, b1), Bool.and(U32.is_eq(a1, b1), U32.is_lt(a0, b0)))def U64.is_gt(+a: U64, +b: U64) -> Bool:  U64.is_lt(b, a)def U64.is_le(+a: U64, +b: U64) -> Bool:  Bool.not(U64.is_lt(b, a))def U64.is_ge(+a: U64, +b: U64) -> Bool:  Bool.not(U64.is_lt(a, b))def U64.is_zero(+a: U64) -> Bool:  match a:    case U64{+lo, +hi}:      Bool.and(U32.is_zero(lo), U32.is_zero(hi))def U64.carry(c: Bool, +hi: U32) -> U32:  match c:    case True{}:      (hi + 1 : U32)    case False{}:      hidef U64.borrow(c: Bool, +hi: U32) -> U32:  match c:    case True{}:      (hi - 1 : U32)    case False{}:      hidef U64.add(+a: U64, +b: U64) -> U64:  match a b:    case U64{+a0, +a1} U64{+b0, +b1}:      +lo = (a0 + b0 : U32)      +c = U32.is_lt(lo, a0)      +hi = (a1 + b1 : U32)      U64{lo, U64.carry(c, hi)}def U64.sub(+a: U64, +b: U64) -> U64:  match a b:    case U64{+a0, +a1} U64{+b0, +b1}:      +lo = (a0 - b0 : U32)      +br = U32.is_lt(a0, b0)      +hi = (a1 - b1 : U32)      U64{lo, U64.borrow(br, hi)}def U64.would_ovf(+a: U64, +b: U64) -> Bool:  U64.is_lt(U64.add(a, b), a)def Pubkey.eq(+a: Pubkey, +b: Pubkey) -> Bool:  match a b:    case Pk{+a0, +a1, +a2, +a3, +a4, +a5, +a6, +a7} Pk{+b0, +b1, +b2, +b3, +b4, +b5, +b6, +b7}:      Bool.and(U32.is_eq(a0, b0),        Bool.and(U32.is_eq(a1, b1),          Bool.and(U32.is_eq(a2, b2),            Bool.and(U32.is_eq(a3, b3),              Bool.and(U32.is_eq(a4, b4),                Bool.and(U32.is_eq(a5, b5),                  Bool.and(U32.is_eq(a6, b6), U32.is_eq(a7, b7))))))))def Pubkey.zero() -> Pubkey:  Pk{0, 0, 0, 0, 0, 0, 0, 0}def system_id() -> Pubkey:  Pubkey.zero()def auth_ok(is_signer: Bool, same: Bool) -> Bool:  Bool.and(is_signer, same)def word_at(xs: List<&2, U32>, i: Nat) -> U32:  match xs i:    case Nil{} _:      0    case h <> t 0n:      h    case h <> t 1n+p:      word_at(t, p)def word_set(xs: List<&2, U32>, i: Nat, v: U32) -> List<&2, U32>:  match xs i:    case Nil{} _:      Nil{}    case h <> t 0n:      v <> t    case h <> t 1n+p:      h <> word_set(t, p, v)def words_len(xs: List<&2, U32>) -> Nat:  match xs:    case Nil{}:      0n    case h <> t:      1n+words_len(t)def has_words(xs: List<&2, U32>, n: Nat) -> Bool:  Nat.is_ge(words_len(xs), n)def has_disc(xs: List<&2, U32>, d: U32) -> Bool:  U32.is_eq(word_at(xs, 0n), d)def load_u32(xs: List<&2, U32>, i: Nat) -> U32:  word_at(xs, i)def store_u32(xs: List<&2, U32>, i: Nat, v: U32) -> List<&2, U32>:  word_set(xs, i, v)def acc_key(a: Account) -> Pubkey:  match a:    case Acc{+key, owner, lamports, data, is_signer, is_writable}:      keydef acc_owner(a: Account) -> Pubkey:  match a:    case Acc{key, +owner, lamports, data, is_signer, is_writable}:      ownerdef acc_signer(a: Account) -> Bool:  match a:    case Acc{key, owner, lamports, data, +is_signer, is_writable}:      is_signerdef acc_writable(a: Account) -> Bool:  match a:    case Acc{key, owner, lamports, data, is_signer, +is_writable}:      is_writabledef acc_lamports(a: Account) -> U64:  match a:    case Acc{key, owner, +lamports, data, is_signer, is_writable}:      lamportsdef acc_data(a: Account) -> List<&2, U32>:  match a:    case Acc{key, owner, lamports, +data, is_signer, is_writable}:      datadef acc_set_data(a: Account, data: List<&2, U32>) -> Account:  match a:    case Acc{key, owner, lamports, old, is_signer, is_writable}:      Acc{key, owner, lamports, data, is_signer, is_writable}def acc_set_lamports(a: Account, lamports: U64) -> Account:  match a:    case Acc{key, owner, old, data, is_signer, is_writable}:      Acc{key, owner, lamports, data, is_signer, is_writable}def acc_credit(+a: Account, amt: U64) -> Account:  acc_set_lamports(a, U64.add(acc_lamports(a), amt))def acc_debit(+a: Account, amt: U64) -> Account:  acc_set_lamports(a, U64.sub(acc_lamports(a), amt))def acc_owned(+a: Account, +program_id: Pubkey) -> Bool:  Pubkey.eq(acc_owner(a), program_id)def acc_is_system(+a: Account) -> Bool:  Pubkey.eq(acc_key(a), system_id())def pda_key(p: Pda) -> Pubkey:  match p:    case Pda{+key, bump}:      keydef pda_bump(p: Pda) -> U32:  match p:    case Pda{key, +bump}:      bumpdef pda_matches(+got: Pubkey, +want: Pubkey) -> Bool:  Pubkey.eq(got, want)# Default seed bytes `bend`. Programs may pass another U32 seed.def PDA_SEED() -> U32:  1684956514# Checker / host XOR stand-in. Not SHA256. On-chain the compiler# replaces derive_pda_seeded with sol_try_find_program_address# ([seed_le_bytes, owner], program_id). Prove pda_matches / Pubkey.eq.def derive_pda_seeded(+program_id: Pubkey, +owner: Pubkey, +seed: U32) -> Pda:  match program_id owner:    case Pk{+p0, +p1, +p2, +p3, +p4, +p5, +p6, +p7} Pk{+o0, +o1, +o2, +o3, +o4, +o5, +o6, +o7}:      Pda{Pk{        U32.xor(U32.xor(p0, o0), seed),        U32.xor(p1, o1),        U32.xor(p2, o2),        U32.xor(p3, o3),        U32.xor(p4, o4),        U32.xor(p5, o5),        U32.xor(p6, o6),        U32.xor(p7, o7)      }, 255}def derive_pda(+program_id: Pubkey, +owner: Pubkey) -> Pda:  derive_pda_seeded(program_id, owner, PDA_SEED())def find_pda(+program_id: Pubkey, +owner: Pubkey, +bump: U32) -> Pubkey:  pda_key(derive_pda(program_id, owner))def cpi_none() -> Cpi:  CpiNone{}def cpi_is_none(c: Cpi) -> Bool:  match c:    case CpiNone{}:      True{}    case CpiTransfer{from, to, lamports, sign, bump}:      False{}    case CpiTokenTransfer{from, to, mint, auth, amount, decimals, sign, bump}:      False{}def world_a0(w: World) -> Account:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, +a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      a0def world_a1(w: World) -> Account:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, +a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      a1def world_a2(w: World) -> Account:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, +a2, a3, a4, a5, a6, a7, cpi, cpi1}:      a2def world_a3(w: World) -> Account:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, +a3, a4, a5, a6, a7, cpi, cpi1}:      a3def world_a4(w: World) -> Account:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, +a4, a5, a6, a7, cpi, cpi1}:      a4def world_a5(w: World) -> Account:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, +a5, a6, a7, cpi, cpi1}:      a5def world_a6(w: World) -> Account:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, +a6, a7, cpi, cpi1}:      a6def world_a7(w: World) -> Account:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, +a7, cpi, cpi1}:      a7def world_n(w: World) -> U32:  match w:    case World{+n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      ndef world_ix0(w: World) -> U32:  match w:    case World{n, +ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      ix0def world_ix1(w: World) -> U64:  match w:    case World{n, ix0, +ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      ix1def world_ix2(w: World) -> U64:  match w:    case World{n, ix0, ix1, +ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      ix2def world_ix3(w: World) -> U64:  match w:    case World{n, ix0, ix1, ix2, +ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      ix3def world_pda_seed(w: World) -> U32:  match w:    case World{n, ix0, ix1, ix2, ix3, +pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      pda_seeddef world_program_id(w: World) -> Pubkey:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, +program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      program_iddef world_cpi(w: World) -> Cpi:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, +cpi, cpi1}:      cpidef world_cpi1(w: World) -> Cpi:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, +cpi1}:      cpi1def world_set_a0(w: World, a0: Account) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, old, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def world_set_a1(w: World, a1: Account) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, old, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def world_set_a2(w: World, a2: Account) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, old, a3, a4, a5, a6, a7, cpi, cpi1}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def world_set_a3(w: World, a3: Account) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, old, a4, a5, a6, a7, cpi, cpi1}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def world_set_a4(w: World, a4: Account) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, old, a5, a6, a7, cpi, cpi1}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def world_set_a5(w: World, a5: Account) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, old, a6, a7, cpi, cpi1}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def world_set_a6(w: World, a6: Account) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, old, a7, cpi, cpi1}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def world_set_a7(w: World, a7: Account) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, old, cpi, cpi1}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def world_set_cpi(w: World, cpi: Cpi) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, old, cpi1}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def world_set_cpi1(w: World, cpi1: Cpi) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, old}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def world_set_pda_seed(w: World, pda_seed: U32) -> World:  match w:    case World{n, ix0, ix1, ix2, ix3, old, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}:      World{n, ix0, ix1, ix2, ix3, pda_seed, program_id, a0, a1, a2, a3, a4, a5, a6, a7, cpi, cpi1}def queue_cpi(empty: Bool, +w: World, c: Cpi) -> World:  match empty:    case True{}:      world_set_cpi(w, c)    case False{}:      world_set_cpi1(w, c)def cpi_transfer(+w: World, +from: U32, +to: U32, +lamports: U64) -> World:  queue_cpi(cpi_is_none(world_cpi(w)), w, CpiTransfer{from, to, lamports, False{}, 0})def cpi_transfer_signed(+w: World, +from: U32, +to: U32, +lamports: U64, +bump: U32) -> World:  queue_cpi(cpi_is_none(world_cpi(w)), w, CpiTransfer{from, to, lamports, True{}, bump})def cpi_token_transfer(+w: World, +from: U32, +to: U32, +mint: U32, +auth: U32, +amount: U64, +decimals: U32) -> World:  queue_cpi(cpi_is_none(world_cpi(w)), w, CpiTokenTransfer{from, to, mint, auth, amount, decimals, False{}, 0})def cpi_token_transfer_signed(+w: World, +from: U32, +to: U32, +mint: U32, +auth: U32, +amount: U64, +decimals: U32, +bump: U32) -> World:  queue_cpi(cpi_is_none(world_cpi(w)), w, CpiTokenTransfer{from, to, mint, auth, amount, decimals, True{}, bump})def world_amt(+w: World) -> U64:  world_ix1(w)def need_accounts(w: World, k: U32) -> Bool:  U32.is_ge(world_n(w), k)def counter_inc(+value: U32) -> U32:  (value + 1 : U32)def dec_if(z: Bool, value: U32) -> Maybe<&2, U32>:  match z:    case True{}:      None{}    case False{}:      Some{(value - 1 : U32)}def counter_dec(+value: U32) -> Maybe<&2, U32>:  dec_if(U32.is_zero(value), value)def withdraw_if(lt: Bool, bal: U64, amt: U64) -> Maybe<&2, U64>:  match lt:    case True{}:      None{}    case False{}:      Some{U64.sub(bal, amt)}def try_withdraw(+bal: U64, +amt: U64) -> Maybe<&2, U64>:  withdraw_if(U64.is_lt(bal, amt), bal, amt)def deposit_if(ovf: Bool, bal: U64, amt: U64) -> Maybe<&2, U64>:  match ovf:    case True{}:      None{}    case False{}:      Some{U64.add(bal, amt)}def try_deposit(+bal: U64, +amt: U64) -> Maybe<&2, U64>:  deposit_if(U64.would_ovf(bal, amt), bal, amt)def load_u64(+xs: List<&2, U32>, +i: Nat) -> U64:  U64.pack(word_at(xs, i), word_at(xs, 1n+i))def store_u64(+xs: List<&2, U32>, +i: Nat, v: U64) -> List<&2, U32>:  match v:    case U64{+lo, +hi}:      word_set(word_set(xs, i, lo), 1n+i, hi)def popcount.go(fuel: Nat, +mask: U32, acc: U32) -> U32:  match fuel:    case 0n:      acc    case 1n+p:      popcount.go(p, U32.shr(mask), (acc + U32.and(mask, 1) : U32))def popcount(mask: U32) -> U32:  popcount.go(32n, mask, 0)def can_execute(approvals: U32, threshold: U32) -> Bool:  U32.is_ge(popcount(approvals), threshold)def bit_set(mask: U32, i: U32) -> U32:  U32.or(mask, U32.shln(1, U32.to_nat(i)))def pick_u32(b: Bool, t: U32, f: U32) -> U32:  match b:    case True{}:      t    case False{}:      fdef maybe_u32(b: Bool, v: U32) -> Maybe<&2, U32>:  match b:    case True{}:      Some{v}    case False{}:      None{}def zeros(n: Nat) -> List<&2, U32>:  match n:    case 0n:      Nil{}    case 1n+p:      0 <> zeros(p)def ensure_if(ok: Bool, xs: List<&2, U32>, n: Nat) -> List<&2, U32>:  match ok:    case True{}:      xs    case False{}:      zeros(n)def ensure_words(+xs: List<&2, U32>, +n: Nat) -> List<&2, U32>:  ensure_if(Nat.is_ge(words_len(xs), n), xs, n)def read_pk(+xs: List<&2, U32>, +off: Nat) -> Pubkey:  Pk{    word_at(xs, off),    word_at(xs, 1n+off),    word_at(xs, 2n+off),    word_at(xs, 3n+off),    word_at(xs, 4n+off),    word_at(xs, 5n+off),    word_at(xs, 6n+off),    word_at(xs, 7n+off)  }def write_pk(xs: List<&2, U32>, +off: Nat, p: Pubkey) -> List<&2, U32>:  match p:    case Pk{+w0, +w1, +w2, +w3, +w4, +w5, +w6, +w7}:      word_set(word_set(word_set(word_set(word_set(word_set(word_set(word_set(        xs, off, w0), 1n+off, w1), 2n+off, w2), 3n+off, w3), 4n+off, w4), 5n+off, w5), 6n+off, w6), 7n+off, w7)def pk_eq_at(+xs: List<&2, U32>, +off: Nat, +k: Pubkey) -> Bool:  Pubkey.eq(read_pk(xs, off), k)def pk_eq_words(+a: List<&2, U32>, +ao: Nat, +b: List<&2, U32>, +bo: Nat) -> Bool:  Pubkey.eq(read_pk(a, ao), read_pk(b, bo))def owner_pick(is0: Bool, is1: Bool) -> Maybe<&2, U32>:  match is0:    case True{}:      Some{0}    case False{}:      maybe_u32(is1, 1)def owner_index(+key: Pubkey, +o0: Pubkey, +o1: Pubkey, +n: U32) -> Maybe<&2, U32>:  owner_pick(    Bool.and(U32.is_gt(n, 0), Pubkey.eq(key, o0)),    Bool.and(U32.is_gt(n, 1), Pubkey.eq(key, o1)))