Skip to main content

Crate thruput_sdk

Crate thruput_sdk 

Source
Expand description

This SDK facilitates writing Thruput contracts in Rust.

A contract is an ordinary Rust crate. Its persistent state lives in one or more structs deriving Storage; its behavior lives in one or more impl or trait blocks marked #[contract], which generate the guest entrypoints and a typed client that other contracts and tests call through.

ⓘ
use thruput_sdk::storage::Value;
use thruput_sdk::*;

#[derive(Storage)]
pub struct MyContract {
    contract_owner: Value<ContractAddress>,
}

#[contract]
impl MyContract {
    pub fn initialize(&mut self, contract_owner: &ContractAddress) {
        self.contract_owner.set(contract_owner);
    }

    pub fn get_owner(&self) -> ContractAddress {
        self.contract_owner.get()
    }
}

#[derive(Storage)] can also be spelled #[storage].

That expands to a MyContractClient for callers, guest entrypoints for the deployed artifact, and a contract spec describing the interface. Declaring exceptions is a separate step, covered under calling and errors.

Sections: Cargo features, storage, calling and errors, events, authorization, arithmetic, system functions, interfaces and specs, and testing.

§Cargo features

The features are layered: each implies the one above it. A contract targeting riscv32im-unknown-none-elf normally enables none of them; the host-side test build enables dev.

  • (none) — the default, and what a deployed contract is built with: no_std, no allocator, no host dependencies. storage, events, exceptions, authorization and the syscall wrappers all work here. Only the allocating and host-side APIs need more.
  • alloc — links the alloc crate, making Vec, String, and other allocating types usable in contract code and in storage. See Allocation for what backs it on a guest.
  • std — implies alloc. Adds the interfaces that need std, owned (allocating) contract-spec models, and detailed XDR decode errors. Host-only: enabling std for a riscv32 build is a hard compile error, as is omitting it for a native build.
  • dev — implies std. The native mock executor and everything that hangs off it: TestEnvironment, client_test, test_rv32(), declare_mock_contract!, and the storage-cost helpers. A contract crate forwards this from its own dev feature. It is the only feature that pulls thruput-native-exec, and through it the hogd FFI library, into the dependency graph. That is why it is a feature: crates that only read contract specs build thruput-sdk without it and never fetch that library.
  • logging — trace contract calls during native tests. Not implied by dev; enable it when you want the trace.
  • source-build — compile the cmake source-build path into thruput-sys. It does not select that path: HOGD_FFI_BUILD=1 does, and it needs this feature to have something to select. Set both to build the hogd FFI library from source rather than download a prebuilt one, which is also the only way to build on a platform with no prebuilt binary. Only meaningful alongside dev.

With alloc, owned String values can also be contract parameters and return values, including inside Option. Borrowed &str inputs and heapless::String<N> are alternatives when a bounded representation is useful.

A contract crate wires them up like this:

[features]
# Yours, not the SDK's. `#[contract]` gates guest entrypoint codegen on it,
# so a dependency cannot inject entrypoints into your binary.
entrypoints = []
dev = ["thruput-sdk/dev"]

[lib]
crate-type = ["rlib"]

# The rv32 artifact. `thruput build -p my-contract` derives
# `--bin my-contract` from the package name, so this name must match it.
# src/main.rs is a `#![no_std] #![no_main]` wrapper whose `extern crate
# my_contract;` force-links the rlib so the entrypoint records reach the
# binary.
[[bin]]
name = "my-contract"
path = "src/main.rs"
required-features = ["entrypoints"]

[dependencies]
thruput-sdk = { workspace = true }

[dev-dependencies]
my-contract = { path = ".", features = ["dev"] }

Two things that look like features are keyed on the target instead:

  • Diagnostics. The Display impls on exception types and the formatting they need are host-only. Off a Cargo feature, no dependency can turn them on for a deployed contract, so they cannot change what a contract computes.
  • The guest runtime. #[global_allocator], #[panic_handler], _start and entrypoint dispatch come from thruput-rv32-runtime, force-linked on riscv32 and absent from host builds.

§Allocation

§Stack and heap budgets

Each RV32 invocation shares a fixed memory budget between stack, static data and heap. Increasing the stack reserve reduces heap capacity; enabling alloc does not increase memory. See the runtime stack and memory configuration for defaults and overrides.

Without alloc, SDK call scratch and entrypoint calldata use fixed buffers of about 4 KiB. An owned exn::RawException also holds an inline buffer of about 4 KiB. Result temporaries and nested calls can keep several buffers on the stack, even when the exception payload itself is small. Inlining can keep those slots in a caller’s frame after their values are no longer live, so source scopes alone do not establish peak stack use.

NeedChoice
Bounded, short-lived values and scratchStack storage is appropriate; budget the whole call chain.
Classify a caught exception immediatelyMapExceptions returns a compact value without retaining its wire buffer.
Keep the full exception for laterOrdinary try_* retains an owned error; account for its storage.
Dynamic collections or larger working buffersEnable alloc and bound cumulative allocation per invocation.

The guest allocator does not reclaim dropped values during an invocation. SDK call scratch is pooled under alloc, but other allocations, including owned exceptions and collection growth, can accumulate. Construct large buffers directly in heap storage: Box::new(large_value) can still create a large stack temporary.

Native tests enable dev, which enables alloc, and do not establish guest stack headroom. Test release RV32 artifacts with maximum inputs, nested calls and error paths.

§Static

Static allocations are facilitated in contracts by ContractCell and contract_local!.

§Heap

With feature alloc:

  • The alloc crate is linked in, giving access to allocating datatypes like String and Vec.
  • A simple bump allocator is installed by the guest runtime crate (thruput-rv32-runtime). Allocations are not freed until the current contract invocation terminates.

Datatypes defined by third-party libraries or by the user may be used in memory and in persistent storage, noting that:

  • Heap allocation requires feature alloc.
  • Persistent storage fields must use SDK storage types or nested structs derived with Storage.

§Storage

The storage module provides a high-level layer over persistent state, including collection types like Map, Vector and Array. It is available in every feature configuration.

Important storage-model rules:

  • Plain data in persistent state must be wrapped in Value<T>.
  • Map<K, V> entries are individually addressed and may be absent.
  • Vector<S> is sparse-capable. Vector::len() reports the in-bounds extent; individual slots may still be empty if their storage has been deleted.
  • Array<S, N> is a fixed-length Map<u32, S>: indices 0..N are always in bounds, and individual elements may be unset.
  • Use Vector::push_with() for the common append-and-initialize flow, and Vector::push_empty_slot() only when you intentionally want to expose the new slot before initializing it.
  • Value::load_mut() returns an auto-flushing edit guard: the updated value is written back when the guard is dropped.
  • Nested storage structs inside collections must be wrapped in Node<T>, for example Vector<Node<MyFields>>.

Two types enforce their invariant in the storage layer instead of in contract code: NNInt for counters that must not go negative, and Balance, whose increase/decrease fail on overflow and overdraft in every build profile (see Arithmetic). This matters most under concurrency: when two transactions in the same block both move a balance, the check has to hold against the committed value, not the one the contract read. Deletable derives recursive deletion for a storage struct.

Each contract’s state occupies its own storage domain. #[contract] generates a per-crate test asserting the crate’s own roots do not collide; a binary that links several contract crates should also invoke storage_domain_uniqueness_test! so the aggregate is checked.

The low-level syscall wrappers (bytestring_set and friends) will corrupt this module’s bookkeeping if pointed at the same keys. Use them, with static_key!, only for state that storage does not own.

§Contract macros

The storage macro is shorthand for #[derive(Storage)].

The contract macro exports contract methods for cross-contract calls and also generates client types for calling those methods. It applies to a trait, a trait impl, an inherent impl, or a free function — see its own page for the interface-versus-implementation split, throws, and entrypoint-identifier customization.

Client naming defaults:

  • #[contract] trait Foo generates FooClient
  • #[contract] impl Foo { ... } generates FooClient
  • client = CustomClient is an override, not a requirement

§Calling And Errors

ContractClient is the low-level call surface. Most code goes through a generated client, which exposes these calling styles:

  • client.method(...): success-oriented path. Typed exceptions are re-thrown to the caller, and faults stay faults.
  • client.try_method(...): inspection path. Returns Result<ReturnType, CallError>. A caught exception stays undecoded: match it with match_exn!, or decode it as a named type with try_as / try_decode.
  • client.map_exceptions(classify).try_method(...): returns Result<ReturnType, RawCallError<X>>, where the mapper produces X from a borrowed exn::RawExceptionRef. See MapExceptions for the callback contract.
ⓘ
match token.try_transfer(&to, amount) {
    Ok(()) => { /* ... */ }
    Err(CallError::Fault(f)) => { /* ... */ }
    Err(e) => match_exn!(e, {
        ERC20Error::TooLarge               => { /* ... */ }
        LibraryExn::NonNegativeIntOverflow => { /* ... */ }
        _ => e.re_throw(),
    }),
}

When only a classification is needed, avoid retaining the full exception:

let outcome = token.map_exceptions(|exn| {
    match_exn!(exn, {
        ERC20Error::TooLarge => true,
        _ => exn.re_throw(),
    })
}).try_transfer(&to, amount);

match outcome {
    Ok(()) => { /* ... */ }
    Err(RawCallError::Exception(true)) => { /* handle TooLarge */ }
    Err(other) => { /* handle call faults and other failures */ }
}

Everything structural — Ok, Fault, Invalid — stays an ordinary Rust match with real exhaustiveness checking; the macro’s only job is typed downcasting. See match_exn! for the matching rules.

Use InvokeConfig (or the generated with_gas_limit constructor) to bound the gas a subcall may spend, and deploy_contract to create new contracts. get_deploy_address computes the resulting address ahead of time.

At the frame level, contract execution ends in one of three states:

  • Success: return data is produced and the frame commits.
  • Exception: the frame reverts with a structured payload (throw, library exception, or forwarded exception).
  • Fault: the frame reverts without a structured exception payload (for example panic!).

Only success commits the current invocation frame’s storage changes.

§Exceptions

A throwable type is one annotated with #[contract_exception] (or #[exn] if you write your own derives), which implements Exn and gives the type a selector derived from its canonical signature. Clients dispatch on that selector, so a caller can tell your exceptions apart from an unrelated contract’s without agreeing on discriminant numbering. Declare which ones a contract may throw with throws = ... on #[contract].

The SDK’s own failures arrive as LibraryExn. Absence (a missing key, an empty queue) is an expected outcome, and comes back the same way; identify it with is_storage_missing, or use none_if_missing to narrow just that case to None while re-throwing everything else.

A try_* function never aborts the VM on its own account: its syscalls, buffer fetches and decoding all report failure through the return type, so the only way one aborts is a closure you handed it. exn states this in full.

§Events

Emit with event; derive the type with #[derive(Event)].

Declare emitted types with #[contract(emits(MyEvent))] so their definitions are retained in the generated contract spec. Emitting an event at runtime does not by itself retain its spec; see #[contract].

Derived events reserve topic 0 for the event signature. That signature is based on the package name, package version, and event type name, so changing any of those changes the emitted signature topic.

Thruput currently supports up to three total topics per event. With #[derive(Event)], that means the signature plus up to two additional #[topic] fields.

Topic fields use their IntoTopic representation. Supported scalar types encode directly; strings and byte slices are hashed and cannot be recovered from a topic. Non-topic fields form the decoded payload. TypedEvent holds the raw topics and that payload. The harness queries assert_event and filter_events provide this typed view.

§Authorization

Authorization travels with the call. A Signed<T> parameter is a handle to a host-held auth token: it encodes to zero bytes, and the handle rides alongside the XDR arguments. A method signature therefore states in its types which arguments must have been authorized.

Signed::consume hands back the payload and the address that minted the token. Any contract can mint a token whose payload decodes as T, so consuming proves only that some contract minted it and that this contract is its intended consumer. Check the returned minter against an address you trust before acting on the payload. Skipping that check is an authorization bypass.

  • #[contract_type] makes a struct or enum usable as an argument, return value, or auth-token payload. It generates the auth-handle walkers that let a Signed<T> nest inside it (an enum variant included), and the Mintable preimage mirror used to mint tokens.
  • signer holds the token vocabulary: Signed<Opaque> for a token whose payload type is not yet known, Signed::assume to reinterpret one, and AssumeTokens to destructure a Vec<Signed<Opaque>> into a typed tuple.
  • get_auth_claim reads the current transaction’s AuthClaim; for a contract acting as an account, set_address_required_weight, add_address_public_key, and remove_address_public_key declare the public keys and weights its address requires.

thruput-signed-op is the wallet-facing shape of this — Thruput’s ERC-1271 equivalent, with the message typed and domain-separated in the spirit of EIP-712 and replay-protected by the chain’s uniquifier model. execute_signed_op returns the one auth token a wallet mints — the root of whatever it authorizes, with tokens for downstream contracts as child nodes. The caller names its payload type with Signed::assume, then consumes it and checks its minter against the wallet address it trusts.

§Minting limits

A token node carries at most 4 direct children (thruput_xdr::auth_token::kAuthTokenMaxChildNodes), and mint_auth_token panics past that rather than reporting it. The count is per node and per level of the preimage — containers do not open a new level, so five elements in a Vec<Signed<u64>> field are five children of one node. A nested Signed<T> does open a level: its own payload gets its own budget of four.

This matters more on chain than in a test: a panicking contract faults with no message, code or location (#358), so a preimage that outgrew the cap is indistinguishable from any other trap. Keep preimage shapes within the cap by construction.

The encoded payload is separately capped at 256 bytes (kAuthTokenMaxLen), which is reported — as AuthTokenError::MintEncodeFailure.

§Arithmetic

U256 and its signed counterpart I256 behave like u128 and i128, including on overflow: the operators wrap when overflow-checks is off — as in every contract profile — and panic when it is on. The native test harness builds with overflow checks on, so an overflow that fails a test wraps silently on-chain. A passing test proves nothing about overflow behavior in deployment.

Signed division is the one exception, and it follows the primitives: I256::MIN / -1 and I256::MIN % -1 panic in every profile, because that is what i128 does — the hardware alternative is a trap, so Rust does not gate it on overflow-checks. Use wrapping_div / wrapping_rem if you need the wrap.

Both types store eight 32-bit limbs, which is what the rv32 guest multiplies natively, and I256 is the same bits read signed rather than a second implementation. Prefer them over a general-purpose big-integer crate: those typically use 64-bit limbs and multiply through u128, which the guest has to synthesize, so they cost far more code and gas for the same arithmetic.

For money math, be explicit rather than relying on operators:

  • checked_add / checked_sub / checked_mul on the primitives and on U256, with a typed throw on None;
  • mul_div_u128 / checked_mul_div_u128 for a * b / d with a 256-bit intermediate (the panics of mul_div_u128 are unconditional, not overflow-checks-gated);
  • U256::mul_div when the operands are themselves 256-bit — full precision, on an exact 512-bit intermediate;
  • the storage-level guards NNInt and Balance, which check in every profile.

Beyond that, U256 and I256 carry OpenZeppelin’s Math.sol and SignedMath.sol surfaces — mul_shr, mul_mod, mod_exp, inv_mod, average, ceil_div, and integer_sqrt/log2/log10/log256 with a Rounding direction — so a Solidity port has the same vocabulary. Every fallible one ships as a checked_ form beside the panicking one.

§System functions

The SDK provides convenient wrappers around Thruput syscalls:

Context about the running transaction:

Other useful modules and types:

§Interfaces And Specs

#[contract] on a trait defines a reusable interface; #[contract] on an impl of that trait exports an implementation. Callers depend on the interface crate and get the same generated client either way. That is how the standard interfaces in standard-interfaces/ (the thruput-*-if crates: thruput-erc20-if, thruput-erc20-metadata-if, thruput-erc20-pausable-if, thruput-erc20-permit-if, thruput-erc721-if, thruput-erc165-if, thruput-access-control-if, thruput-signed-op-if) are consumed.

Every #[contract] trait also carries an InterfaceId as Trait::INTERFACE_ID, derived from its name and major version, and every #[contract] impl block leaves a record of its interface’s id in the contract’s interface table. thruput-erc165 is the query surface: impl_erc165!() adds a supports_interface entrypoint answered by implements!(id) from the impls that actually linked, and a supports_interfaces entrypoint that answers a bounded list of ids in one call. A contract without it carries no table in its deployed image.

Alongside the entrypoints, the macros emit a machine-readable contract spec: the interface’s methods, their argument and return types, and the exceptions it declares. Types reach the spec through #[contract_type] or ContractTypeSpec.

§Testing

Three testing lanes, all behind feature dev:

  • client_test: simplest path for exercising a generated client against a mock registration
  • TestEnvironment: direct control over environment, blocks, deployment, and multi-contract scenarios
  • test_rv32(): run a built rv32 contract artifact in the test harness

When a test needs one transaction to see another’s committed changes, call TestEnvironment::advance_block between them. Transactions in the same block read the same committed snapshot; see TestEnvironment::transact.

Typical native client test, with the contract crate calling thruput_sdk::declare_mock_contract!(); in its lib.rs to generate register_mock_contract:

ⓘ
use my_contract::MyContractClient;

thruput_sdk::client_test(
    |env| my_contract::register_mock_contract(env),
    |client: &MyContractClient| {
        // Call methods on `client`
    },
);

Direct environment control:

ⓘ
use thruput_sdk::{ContractAddress, Named, StorageKey, TestEnvironment};

let env = TestEnvironment::no_cost();
let addr = ContractAddress::named("my_test");

env.transact(|tx| {
    tx.call(&addr).run(|| {
        let key = StorageKey::default();
        thruput_sdk::bytestring_set(&key, b"hello");
    })
})
.assert_success();

Use the full env.transact form when a test needs multiple transactions, asserts on aborts or faults, or decodes typed results.

The chain settings an environment runs under – the storage cost model, the network hash, the genesis root, and the network config parameters – come from TestEnvironment::builder() when a test wants something other than the defaults. It is entirely optional; the constructors above are unaffected by it.

ⓘ
// A contract's behavior at the chain's live-hasher cap, without needing a
// chain configured that way. Every unset parameter keeps its stock value.
let env = TestEnvironment::builder()
    .no_cost()
    .with_max_sha256_buffers(2)
    .build();

Advanced helpers are available when you need lower-level control:

Re-exports§

pub use thruput_contract_spec as contract_spec;
pub use thruput_u256 as u256;
pub use block::*;
pub use event::*;
pub use exn::*;
pub use signer::*;
pub use types::*;

Modules§

base58
Allocation-free base58 conversion for public identifiers. Allocation-free Bitcoin/Solana base58 conversion for identifier bytes.
block
crypto
System functions: hash and signature
event
exn
Exceptions (part of the SDK’s call-wrapper)
interface_table
The interface table: which interfaces this contract implements, collected by the linker from its #[contract] impl blocks.
network_config
The chain’s execution parameters, and a builder for non-default ones.
read_xdr
Reading XDR data into Rust types.
remote
Off-chain invocation through generated <Iface>Remote proxies. Invoking a deployed contract from off-chain code.
signer
stats
storage
Datatypes backed by the key-value store.
sys_result
Primitive interfaces for system functions that return Result.
types
Types
write_xdr
Writing Rust values as XDR data.
xdr

Macros§

contract_local
Use this macro to wrap static definitions in order to make them work correctly in the test environment. The statics are placed in thread-local storage so that concurrently-run tests don’t bash each other.
contract_test
Run some code in the test environment, as a single auto-committed transaction at a deterministic per-test address.
debug_log
declare_mock_contract
export_interface_spec
Anchor a #[contract] trait’s spec for inclusion. Spec shaking drops a trait’s (candidate) interface spec unless something anchors it — normally a #[contract] impl. Use this in an interface crate’s spec-carrier main.rs so building that crate on its own emits the interface’s full spec:
hash_ident
hash_to_array
Compute a [u8; 32] at compile time: sha256 of the literal’s value (quotes stripped, escapes resolved). Accepts string and byte-string literals: hash_to_array!("foo") == sha256 of the 3 bytes foo and agrees with thruput_sdk::crypto::sha256(b"foo") at runtime and with sha256_static!/static_key! for the same string.
implements
True if this contract carries a #[contract] impl of the interface identified by the given InterfaceId.
match_exn
Match a caught exception against any exception type, whatever the called interface declared it throws.
sha256_array_ident
Like sha256_ident! (sha256 of the bare identifier’s text), but expands to a [u8; 32] array instead of a SHA256Hash.
sha256_ident
Compute a SHA256Hash at compile time: sha256 of the bare identifier’s text (no quotes — sha256_ident!(foo) hashes the 3 bytes foo).
sha256_static
Compute a SHA256Hash at compile time: sha256 of the string literal’s value (quotes stripped, escapes resolved).
static_key
Compute a StorageKey at compile time: sha256 of the string literal’s value (quotes stripped, escapes resolved).
storage_domain_uniqueness_test
Declare a native test asserting that no two contract state roots linked into this binary share a storage domain.
with_call_tracking
with_debug_context

Structs§

AuthTokenPreimage
Base58
Borrowed fixed-size bytes formatted as unprefixed base58.
ContinuableFrame
A frame that is still open after run_continuable returned FrameAction::Continue. Supports chaining additional run_continuable() calls or finishing.
ContractCell
A wrapped core::cell::Cell that implements Sync so it can be used in statics. Methods of the inner Cell are available via this wrapper’s Deref implementation. The wrapper adds no costs to Cell.
ContractRefCell
A wrapped core::cell::RefCell that implements Sync so it can be used in statics — the by-reference companion to ContractCell for state that must be borrowed in place (e.g. the SDK’s fixed buffers, which would cost a stack copy if moved through Cell). Declare via contract_local!; the SDK accesses it through a crate-private checkout trait that works identically against the guest static and the test env’s thread-local.
DbConflictCode
Reason a storage delta could not be applied during two-phase commit. These are the nondeterministic failures of try_push_new_subtransaction: any of them causes ExecResultTxNonDeterministicError, and the transaction is excluded from the block. Codes are intentionally coarse; finer-grained detail may be added later behind a debug-only extension.
DbConflictDiagnostic
One conflicting storage op. Fixed-size: ContractAddress[32] plus a fixed-size StorageKey plus the code — no heap allocation.
Duration
A span of time, for arithmetic on TimePoint.
FrameBuilder
Builder for configuring and executing a single invocation frame.
FrameHandle
Handle to the current frame, available inside run_continuable closures. Provides child_call() for opening nested frames.
FrameResult
Result of executing a single invocation frame. Wraps InvocationFrameOutput + optional trace + per-frame events.
Hasher
An incremental hasher, implemented by the VM.
Hex
HostFnErrorCode
I256
A 256-bit signed integer.
InvokeConfig
InvokeError
Panic payload classifying how an invocation frame terminated; downcast at the frame’s catch site and mapped to the frame outcome.
InvokeErrorCode
InvokeFlag
Flags that modify the behavior of a contract invocation.
MockContract
Handle to a mock contract registered in a TestEnvironment: a contract whose entrypoints are native closures instead of rv32 code.
MockTransactionConfig
Configuration for a mocked transaction, applied when the handler is created. Build one with TestEnvironment::transaction, or use MockTransactionConfig::default for the standard setup.
MockTransactionHandler
A mocked transaction context: runs one, and only one, transaction, with exactly one root frame (call / open_root_frame panic on a second invocation). Nest further calls as child frames, or use a second transaction.
NetworkConfigBuilder
Builder for a NetworkConfig stating non-default execution parameters.
PanicLocation
Where a contract body panicked.
PanicRecord
What the harness could see of a contract body’s panic.
Rv32StackUsage
What an rv32 guest did with its stack pointer over one invocation.
Stats
StorageCostModel
SystemErrorCode
TestEnvironment
An in-process Thruput instance for testing contracts natively.
TestEnvironmentBuilder
Builder for a TestEnvironment that needs something other than the stock chain settings.
TransactResult
Result of a full transaction: root frame result + commit outcome. Events are accessed via the root frame’s per-frame events.
TransactionBuilder
Builder for configuring a mocked transaction before executing it.
TryFromIntError
Returned when an integer conversion in this crate does not fit.
U256
A 256-bit unsigned integer.

Enums§

DbConflictResult
Conflict diagnostics attached to a failed try_push_new_subtransaction. The discriminant is the DbDiagnosticLevel the database selected from the block’s execution mode, so the variable-length arm is only ever constructed in kDbDiagnosticAll mode (debug-build proposals); prod levels are allocation-free by construction.
FrameAction
What an execute closure tells the harness to do with its frame.
RawCallError
The raw, untyped error from a contract call.
ReadError
Errors that can occur when reading XDR data.
Rounding
The rounding direction of an inexact result.
TryCommitResult
Outcome of a two-phase commit (try_commit_transaction).
WriteError
Errors that can occur when writing XDR data.

Constants§

SP_UNWRITTEN
The value Rv32StackUsage::sp_initial and Rv32StackUsage::sp_min hold when the guest never wrote sp.

Traits§

CollectAuthHandles
Extract the auth-token handles of every Signed value nested in self, in declaration order, so they can travel alongside the XDR payload of a contract call (Signed encodes to zero bytes; the handles are passed out-of-band).
Context
ContractClient
ContractTest
ContractTypeName
Provides the spec-visible name for a contract type.
Hash
SHA-256 of a value’s CXS encoding.
MapExceptions
Classify a borrowed exception during a generated call.
Mintable
MintableType
Marker trait for types that have a pre-signing (preimage) representation.
Named
Create deterministic test addresses from human-readable names.
OrReThrow
Extension trait for transparently propagating a contract error.
OrSyscallThrow
Extension trait for turning a failed raw syscall into the SDK’s syscall exception. A SysErr is only the error code, so the caller names the syscall; the exception carries both (see SyscallExn).
OrThrow
Extension trait for replacing an error with a contract exception.
ReThrow
A type that can re-throw itself as a contract exception or fault.
ReadXDR
Types that can be constructed by reading XDR-encoded data, possibly sharing data from the input.
ReadXDROwned
Types that can be constructed by reading XDR data of any lifetime.
Reader
A reader that can produce XDR values, some borrowed with lifetime 'r.
ReceiveAuthHandles
Re-attach auth-token handles to every Signed value nested in self, drawing them from handles in declaration order. Signed decodes from zero XDR bytes with a sentinel handle; this trait fills in the real handles delivered out-of-band.
TestRegisterFn
WriteXDR
Types that can be written as XDR data.
Writer
Something that can write XDR values to a serialization format.

Functions§

add_address_public_key
Register public_key at pk_index. ML-DSA-65 keys need a runtime with ML-DSA-65 support; an older runtime, like any runtime given a scheme it does not know, rejects the key with InvalidSyscallInput.
base58_encode
Wrap fixed-size identifier bytes for allocation-free base58 formatting.
bytestring_exists
Reports whether a bytestring exists at the given key.
bytestring_get
bytestring_get_len
Returns the length of the bytestring stored at the given key.
bytestring_get_sized
Returns the bytestring contents in a statically-sized array.
bytestring_set
Sets the value at the given key to the given bytestring.
bytestring_set_exclusive
Sets the value at the given key to the given bytestring, then requests ExclusiveLock for the key.
bytestring_try_get
Read the bytestring at key, reporting failure as Err instead of aborting (the try_ law; see the exn module docs). A missing key is a LibraryExn::Syscall for which is_storage_missing is true; a value of another storage type or any other syscall failure is a LibraryExn::Syscall as well.
checked_mul_div_u128
Computes a * b / d exactly, returning None if d is zero or the quotient does not fit in a u128.
clear_storage_flags
Removes every flag the current transaction requests for key. Does nothing if no write to key is pending.
client_test
contract_abort
contract_abort_encoded
contract_revert
Terminate the current call frame immediately, reverting it.
delete
Delete anything stored at the given key.
delete_exclusive
delete_shared
deploy_address
deploy_contract
encode_xdr
encode_xdr_into
ensure
get_auth_claim
get_calldata_len
get_caller
get_current_address
get_deploy_address
get_deploy_address_for_other
get_source_transaction_hash
The hash of the transaction that initiated the current execution.
hex_encode
into_root_call_result
Decode a TransactResult’s root-frame outcome into the same Result<T, RawCallError> shape that contract clients produce. Use this when a test asserts on typed exceptions/selectors rather than raw buffers.
load_rv32_contract
log
log_str
mul_div_u128
Computes a * b / d exactly, without the intermediate product needing to fit in 128 bits.
non_negative_int_get
Get the current value.
non_negative_int_inc
Increment the value.
non_negative_int_set
Set the value.
non_negative_int_set_exclusive
Set the value exclusively.
non_negative_int_strict_inc
Increment the value.
non_negative_int_try_get
Get the current value, reporting failure as Err instead of aborting (the try_ law; see the exn module docs).
non_negative_int_try_strict_inc
Increment the value, like non_negative_int_strict_inc, but report failure to the caller instead of throwing (the try_ law; see the exn module docs), so a contract can raise a domain-specific exception (e.g. an ERC20 “amount too large”).
read_xdr
Reads an XDR value of type T from the reader r.
receive_auth_handles_from_iter
register_mock_package
remove_address_public_key
retrocausal_queue_consume
retrocausal_queue_consume_sized
retrocausal_queue_insert
retrocausal_queue_peek
retrocausal_queue_peek_sized
retrocausal_queue_try_consume
Consume the next queue entry into a boxed slice, reporting failure as Err instead of aborting (the try_ law). An empty queue is a LibraryExn::Syscall for which is_storage_missing is true.
retrocausal_queue_try_consume_sized
Consume the next queue entry as an N-byte array, reporting failure as Err instead of aborting (the try_ law; see the exn module docs).
retrocausal_queue_try_peek
Peek at the next queue entry as a boxed slice; the try_-law counterpart of retrocausal_queue_peek. Same error contract as retrocausal_queue_try_consume.
retrocausal_queue_try_peek_sized
Peek at the next queue entry as an N-byte array; the try_-law counterpart of retrocausal_queue_peek_sized. Same error contract as retrocausal_queue_try_consume_sized.
set_address_required_weight
set_storage_flags
Adds flags (a bitwise OR) to the flags the current transaction requests for key.
storage_flags
Returns the flags the current transaction requests for key, as seen by the current call frame. A key with no pending write has none.
test_network_hash
The NetworkHash that TestEnvironments are created with: sha256(TEST_NETWORK_NAME).
test_rv32
throw
trap
Abort the current invocation with a deterministic error.
try_get_calldata_len
with_debug_context
Add to the stack of debugging-context values.
write_xdr
Writes an XDR value to the writer.

Type Aliases§

AuthHandleBuf
BitMap
A bitmap representing a set of key IDs.
CallError
The error type of ordinary generated try_* client methods: a call failure that may carry a caught exception, kept untyped.
Calldata
The calldata buffer — the SDK’s single ScratchBuf. With the alloc feature this is a heap Vec sized exactly to the calldata (any length); without it, a fixed SCRATCH_MAX-byte buffer.
InvokeFlagSet
A bitset of InvokeFlag values.
ReadResult
A result type for reader operations.
TestEnvironmentHandle
Shared handle to a TestEnvironment; returned by its constructors.
Weight
Represents the weight of a signature key in multi-signature schemes.
WriteResult
A result type for writer operations.

Attribute Macros§

contract
Expose methods for cross-contract calls.
contract_exception
#[contract_exception] or #[contract_exception(version = "1.0.0", name = "...")] — full convenience macro: derives + #[repr(i32)] + impl Exn + impl ContractTypeName.
contract_type
Make a struct or enum usable as a contract argument, return value, or auth-token payload: derives XDR codecs, spec registration, auth-handle walkers, and the Mintable preimage machinery.
exn
#[exn] or #[exn(version = "1.0.0")] — emits impl Exn with a computed selector. Use this when you handle your own derives. For the full convenience macro, use #[contract_exception] instead.
storage
Storage macros and traits for the key-value store.

Derive Macros§

ContractTypeSpec
Derive ContractTypeSpec (plus ContractTypeRefSpec, a linker anchor, and the raw typedef link-section fragment) for a struct or enum.
Deletable
Error
Event
Derive event encoding, signature and spec metadata.
ReadXDR
Derives the ReadXDR trait for a struct or enum.
Storage
WriteXDR
Derives the WriteXDR trait for a struct or enum.