Project
Changelog
TypeSOL follows semantic versioning with the 0.x rules described in CONTRIBUTING.md: until 1.0, a minor version may change the language, the IDL layout or error codes, and says so here.
Unreleased
In progress for the next releaseChanged
- The project is now spelled TypeSOL, in docs, CLI help and runtime messages (
TypeSOL: arithmetic overflow (file.ts:12)). Tools that match log text on the old spelling need updating. The npm package and command staytypesol.
Performance
Same checks, error codes and account state; fewer compute units and smaller binaries. counter.increment 926 → 143 CU, vault.withdraw 1,394 → 352, vault.shut 1,190 → 201, vault.deposit 2,436 → 1,358; counter / vault binaries 29.9 / 33.6 KB → 12.3 / 16.1 KB (see the README numbers).
- Pubkey, discriminator and other byte comparisons, copies and zeroing work 8 bytes at a time (
ts_key_eq,ts_mem_eq,ts_memcpy,ts_memzero) instead of the SDK's byte loops. - Instruction dispatch compares an 8-byte discriminator as one u64.
- The entry point deserializes accounts with
ts_deserialize: same layout and duplicate handling as the SDK'ssol_deserialize, without its per-account bound branch (the account count is already capped) or bool normalization (the loader writes 0 or 1). - The rent-exempt minimum uses integer math when the exemption threshold is a whole number (every cluster) and the product stays below 2^53, where it is bit-identical to the floating-point formula; other thresholds still take it.
- Checked u64
+,-and*compile to one compare;*skips the 128-bit multiply when both factors fit in 32 bits. - Programs link with
--gc-sectionsand--strip-all(clang-ffunction-sections -fdata-sections): unused compiler-builtins code and the symbol tables are dropped. Build manifests' binary hashes change accordingly.
- The project is now spelled TypeSOL, in docs, CLI help and runtime messages (
0.10.0
LatestFirst release candidate. Not externally audited (see SECURITY.md).
Breaking
verifySecp256k1(hash, …):hashmust bekeccak256(...)or the newethMessageHash(message)written inline.switchboardValue(feed, expectedFeed, maxStaleSlots, decimals): newexpectedFeedargument.- Pubkey, struct and data-enum helper arguments are copies (code that relied on seeing later writes through them changes).
log(integer)prints decimal instead ofsol_log_64hex words.- IDL
relationsnow follow Anchor (on the account ahas_onenames, listing its holders): IDL bytes change. typesol verifyexits 3 on a mismatch (2 is now "usage error"); unknown CLI options are errors.typesol.jsonprogram entries become{ "path", "address" }objects on first build (plain paths still accepted).- Node.js 22.12+ is required.
Security fixes (internal audit)
- Event,
emitCpi,invokeand Metaplex data buffers check bounds on every write after a variable-size field (previously a long string followed by fixed fields could write past the stack buffer). reallocnever moves lamports out of the account: growth is paid by the payer (rent difference), shrinking refunds nothing, and it takes onlyMut<Struct>accounts of this program.- Optional program accounts are checked before their methods run;
loadForeignvalidates bools, enums and text (3003); cached account lengths are refreshed after every CPI. - A discriminator that collides with the
emitCpievent tag is a compile error. - Constraints may no longer depend on optional accounts (they could be skipped by leaving the account out).
verifySecp256k1requires the hash to be computed in the program (keccak256(...)orethMessageHash(...)).- Token-2022 extension readers refuse multisig and non-mint accounts;
Ata<>also checks the owner and mint fields;switchboardValuetakes the expected feed;rentExemptoverflow aborts.
Correctness fixes
Vec.push/setevaluate their value before the Vec changes; object literals and event fields evaluate in source order; builtin and helper arguments are read left to right; seeds are copied as they are evaluated.- Pubkey, struct and data-enum helper arguments are values; a helper that may replace a struct while a reference into it is still used is a compile error.
- IDL
relationsfollow Anchor's direction; nested event structs with Options are refused; reserved IDL type names, duplicate error names, duplicate data-enum cases, bad seed literals and barenullin CPI data are diagnostics. - String arguments must be valid UTF-8 (102); empty Options in struct arguments must be zeroed.
- C string literals use octal escapes (non-ASCII text followed by hex-digit letters was mis-encoded).
log(integer)prints decimal.- A local may not shadow an instruction or helper parameter (lookups resolved to the account).
a.equals(f()),place = f()(the target is chosen first),requirePda,pythPrice,verifyEd25519andmerkleVerifyevaluate left to right; assigning a helper result into a Vec element the helper may change is an error.- u128/i128 constant seeds are 16 bytes in the IDL (as in the program).
- Struct helper arguments in loops reuse one buffer per call site instead of taking heap on every pass.
- Generated CPI bindings accept enum arguments; helper parameter names reserve
__and$; file names with quotes, self-comparisons and 256-variant enums compile.
Tooling
- Strict per-command options (
typesol <command> --help), exit code 2 for usage errors, 3 forverifymismatches. - Project builds honour
--sbpf/--profile; program addresses are recorded intypesol.jsonand checked against the keypair; a program's.tsbuilds as that program. - Clearer errors (missing toolchain,
solananot on PATH, invalidtypesol.json, missing files). - Toolchain discovery next to
cargo-build-sbfon PATH;.d.tsfor every subpath export; one version number. - The code generator is split into layered modules under
src/compiler/emit/(generated C is byte-identical).
Earlier (0.1 – 0.9, development)
Compiler, runtime and CLI built up to: accounts and Anchor-style constraints, PDAs, CPIs (System, SPL Token, Token-2022, ATA, Metaplex Token Metadata / Core / Bubblegum, generic
invoke, typed helpers from IDLs), events andemitCpi, data enums, Options, Vecs, 128-bit integers, oracles (Pyth, Switchboard), signature checks, optional accounts, realloc, transfer hooks, Anchor-compatible IDLs and error codes, on-chain IDL publishing, profiling, SBPF v0–v2, reproducible builds.