> subsystem-summary-of-soroban-env
read this skill for a token-efficient summary of the soroban-env subsystem
curl "https://skillshub.wtf/stellar/stellar-core/subsystem-summary-of-soroban-env?format=md"Soroban Env Subsystem (p26) — Technical Summary
Overview
The Soroban environment subsystem is split into two crates: soroban-env-common and soroban-env-host. Together they define the host-guest interface for Soroban smart contracts. soroban-env-common defines the ABI types and trait interfaces shared between guest (Wasm) and host code. soroban-env-host provides the concrete Host implementation that executes contracts, manages storage, budgets, authorization, events, and the Wasm VM.
The p26 host only supports protocol version 26 and later (MIN_LEDGER_PROTOCOL_VERSION = 26).
soroban-env-common
Val — The Universal 64-bit Value Type
Val (val.rs) is a 64-bit (u64) union type that is the fundamental ABI type crossing the host-guest boundary. It uses bit-packing:
- Low 8 bits:
Tagenum indicating the type. - Upper 56 bits:
body, optionally subdivided into a 32-bitmajorand 24-bitminor.
Tag categories:
- Small tags (0–14): Values packed entirely within the 56-bit body —
False,True,Void,Error,U32Val,I32Val,U64Small,I64Small,TimepointSmall,DurationSmall,U128Small,I128Small,U256Small,I256Small,SymbolSmall. - Object tags (64–78): Reference host-side objects via a 32-bit handle in the
majorfield —U64Object,I64Object,TimepointObject,DurationObject,U128Object,I128Object,U256Object,I256Object,BytesObject,StringObject,SymbolObject,VecObject,MapObject,AddressObject,MuxedAddressObject. Tag::Bad (0x7f): Sentinel for mis-tagged values.
Small values (numbers that fit in 56 bits, symbols ≤9 chars) avoid host object allocation. Larger values overflow to host objects transparently.
Wrapper Types
Type-safe wrappers around Val that statically guarantee the tag:
Object— any object-tagged Val; carries a 32-bit handle.Symbol/SymbolSmall/SymbolObject— identifiers restricted to[a-zA-Z0-9_].SymbolSmallpacks up to 9 chars into 54 bits using 6-bit codes.SymbolStris a fixed-size buffer for extracting symbol bytes.Error— tag=3, encodes(ScErrorType: 24-bit minor, ScErrorCode: 32-bit major).- Numeric wrappers:
U32Val,I32Val,U64Val/U64Small/U64Object,I64Val,U128Val,I128Val,U256Val,I256Val,TimepointVal,DurationVal, plus their Small/Object variants. Bool,Void— singleton-like wrappers.BytesObject,StringObject,MapObject,VecObject,AddressObject,MuxedAddressObject.
Env and VmCallerEnv Traits
EnvBase (env.rs) — base trait with associated Error type, integrity checks, tracing hooks, and slice-passing helper methods (bytes_copy_from_slice, bytes_new_from_slice, map_new_from_slices, vec_new_from_slice, etc.). These bypass the Wasm ABI for trusted callers.
Env — generated via the call_macro_with_all_host_functions! x-macro from env.json. Declares all host functions that guest contracts can call. Each method takes and returns only 64-bit values (Val and wrappers). The x-macro allows the same function list to be reflected in multiple contexts (trait declaration, dispatch, function info tables).
VmCallerEnv (vmcaller_env.rs) — variant of Env where each method takes an additional &mut VmCaller<Self::VmUserState> parameter, allowing host function implementations to access the Wasm Caller context (e.g., for linear memory access). A blanket impl Env for T where T: VmCallerEnv passes VmCaller::none() automatically, so native callers don't need to deal with VmCaller.
Convert and Compare Traits
Convert<F, T> — generic fallible conversion trait. TryFromVal<E, V> / TryIntoVal<E, V> — Env-aware conversion traits used to convert between Rust types and Val (e.g., i64 <-> Val goes through small-or-object path via the Env). Compare<T> — Env-aware ordering trait (needed because comparing objects requires host access).
ConversionError
Minimal uninformative error for ubiquitous tag/number conversions in Wasm, converting to Error(ScErrorType::Value, ScErrorCode::UnexpectedType).
ScValObject / ScValObjRef
Helper types that classify which ScVal variants require host-side object storage vs. fitting into a small Val.
soroban-env-host
Host — The Core Runtime
Host (host.rs) is a newtype around Rc<HostImpl> implementing VmCallerEnv (and thus Env). It is the concrete environment that executes Soroban contracts. HostImpl is a #[derive(Clone, Default)] struct containing all mutable state behind RefCells:
objects: Vec<HostObject>— the host object table (indexed by absolute handles).storage: Storage— ledger entry access.context_stack: Vec<Context>— call stack of frames.budget: Budget— CPU/memory metering (Rc-shared, not deep-cloned).events: InternalEventsBuffer— contract and diagnostic events.authorization_manager: AuthorizationManager— auth tracking.module_cache: Option<ModuleCache>— cached parsed Wasm modules.ledger: Option<LedgerInfo>— current ledger metadata.source_account: Option<AccountId>— transaction source account.base_prng: Option<Prng>— seeded PRNG for deterministic randomness.diagnostic_level: DiagnosticLevel— controls debug event emission.trace_hook: Option<TraceHook>— lifecycle tracing callback.
Construction: Host::with_storage_and_budget(storage, budget) or Host::default().
Finalization: Host::try_finish() consumes the host (requires refcount=1) and returns (Storage, Events).
HostObject — The Object Table
HostObject (host_object.rs) is an enum of all host-side object types:
Vec(HostVec), Map(HostMap), U64(u64), I64(i64), TimePoint, Duration, U128, I128, U256, I256, Bytes(ScBytes), String(ScString), Symbol(ScSymbol), Address(ScAddress), MuxedAddress(MuxedScAddress).
HostObjectType trait: inject(self, host) -> HostObject, try_extract(&HostObject) -> Option<&Self>, new_from_handle(u32) -> Wrapper.
Object handles have two flavors:
- Absolute (odd low bit): index into
Host.objects. Used by host code and stored in host objects. - Relative (even low bit): per-frame indirection table index. Used by Wasm guest code. Translation happens at the VM boundary during dispatch.
Key methods:
add_host_object<HOT>(hot) -> HOT::Wrapper— pushes into the object vec, returns handle.visit_obj<HOT, F>(obj, f) -> U— looks up object by handle, chargesVisitObject, calls closure with&HOT.relative_to_absolute(val)/absolute_to_relative(val)— handle translation at VM boundary.
Frame and Context — Call Stack
Frame (host/frame.rs) — enum of invocation types:
ContractVM { vm, fn_name, args, instance, relative_objects }— Wasm contract call.HostFunction(HostFunctionType)— top-level host function invocation.StellarAssetContract(ContractId, Symbol, Vec<Val>, ScContractInstance)— built-in SAC.TestContract(TestContractFrame)— test-only.
Context wraps a Frame with optional per-frame Prng and InstanceStorageMap.
RollbackPoint captures (StorageMap, events_len, AuthorizationManagerSnapshot) for sub-transaction rollback.
Host::with_frame(frame, f) — the central frame lifecycle method. Pushes a context (capturing rollback point), runs closure, pops context. On error, rolls back storage and events. Handles Ok(Error) returns from contracts (converts to Err), distinguishing contract errors from spoofed system errors. Enforces depth limit (DEFAULT_HOST_DEPTH_LIMIT).
ContractReentryMode: Prohibited, SelfAllowed, Allowed.
Storage — Ledger Access
Storage (storage.rs) mediates all ledger entry access with two modes:
FootprintMode::Recording(SnapshotSource)— preflight mode, records accessed keys.FootprintMode::Enforcing— production mode, rejects accesses outside declared footprint.
Components:
Footprint(FootprintMap)—MeteredOrdMap<Rc<LedgerKey>, AccessType, Budget>mapping keys toReadOnly/ReadWrite.StorageMap—MeteredOrdMap<Rc<LedgerKey>, Option<EntryWithLiveUntil>, Budget>holding actual entries.InstanceStorageMap— in-memory per-contract instance storage (fromScContractInstance.storage), withis_modifiedflag.
Key operations: get, try_get, put, del, has, get_with_live_until_ledger. Each checks footprint first and delegates to the underlying map. TTL extension methods handle extend_ttl and restore.
Supported ledger entry types: Account, Trustline, ContractData, ContractCode.
Budget — Metering System
Budget (budget.rs) is an Rc<RefCell<BudgetImpl>> tracking CPU instructions and memory bytes consumption. It uses a cost model based on ContractCostType enum variants.
BudgetImpl contains:
cpu_insns: BudgetDimension— CPU budget with per-cost-type linear models (const_term + lin_term * input).mem_bytes: BudgetDimension— memory budget.tracker: BudgetTracker— per-cost-type iteration/input/cpu/mem counters.is_in_shadow_mode: bool— when true, charges are tracked but don't fail on exceeding limits (used for debug/diagnostic work).fuel_costs: wasmi::FuelCosts— calibrated Wasm fuel costs for wasmi.depth_limit: u32— recursion depth limit.
Budget::charge(ty, input) is the core metering call, invoked pervasively. It updates tracking, charges both CPU and memory dimensions, and checks limits. In shadow mode, limits aren't enforced.
AsBudget trait allows both Budget and Host to be used as budget references.
Fuel bridge: get_wasmi_fuel_remaining() converts remaining CPU budget to wasmi fuel units. Fuel is transferred to/from wasmi at host function call boundaries.
Metered Data Structures
MeteredOrdMap<K, V, Ctx>(host/metered_map.rs) — sortedVec<(K, V)>with binary search. All operations (insert, get, delete) charge budget based onDeclaredSizeForMetering. Used forHostMap,FootprintMap,StorageMap.MeteredVector<A>(host/metered_vector.rs) —Vec<A>wrapper with metered insert/append/remove. Used forHostVec.MeteredClonetrait (host/metered_clone.rs) — chargesMemCpybudget for cloning, withDeclaredSizeForMeteringproviding stable size constants (notsize_ofwhich may vary).charge_shallow_copyandcharge_heap_allocare the underlying charging functions.MeteredHash(host/metered_hash.rs) — metered hashing.
VM — Wasm Execution
Vm (vm.rs) wraps a wasmi::Instance for a single Wasm module:
contract_id: ContractIdmodule: Arc<ParsedModule>wasmi_store: RefCell<wasmi::Store<Host>>wasmi_instance: wasmi::Instancewasmi_memory: Option<wasmi::Memory>
Rejects modules with floating point or start functions.
ParsedModule (vm/parsed_module.rs) — pre-parsed, validated Wasm module. Stores wasmi::Module, VersionedContractCodeCostInputs (V0 = just byte length, V1 = detailed instruction/function/global counts), and imported symbol set. Charges parsing and instantiation costs separately.
ModuleCache (vm/module_cache.rs) — caches Arc<ParsedModule> keyed by code hash, shared across invocations within a host. Can be installed externally or built from host storage.
Dispatch — Host Function Routing
dispatch.rs uses the call_macro_with_all_host_functions! x-macro to generate one dispatch function per host function. Each dispatch function:
- Transfers wasmi fuel to host CPU budget (
FuelRefillable). - Charges
DispatchHostFunctioncost. - Converts wasmi
i64args toVal/wrappers (with relative-to-absolute object translation viaRelativeObjectConversion). - Calls the
VmCallerEnvmethod on Host. - Converts result back (absolute-to-relative).
- Transfers residual CPU budget back to wasmi fuel.
func_info.rs — static HOST_FUNCTIONS array of HostFuncInfo structs (mod name, fn name, arity, wrap function, protocol bounds). Used by linker setup and introspection.
Protocol gating: each host function can have optional min_proto/max_proto bounds checked at dispatch time.
Events
events/mod.rs — HostEvent wraps ContractEvent XDR with failed_call flag. InternalEventsBuffer (events/internal.rs) stores events during execution. Events are rolled back on frame failure. system_events.rs emits system events for contract lifecycle operations.
Event types: Contract (user-emitted), System (host-emitted lifecycle), Diagnostic (debug-only, guarded by DiagnosticLevel::Debug and shadow budget).
Authorization
AuthorizationManager (auth.rs) handles both authorization (is action allowed?) and authentication (is credential authentic?). Operates in two modes:
- Enforcing: validates
SorobanAuthorizationEntrytrees against actual invocation patterns. - Recording: captures auth requirements during preflight.
Address types for auth:
- Invoker contract — implicit auth from call chain.
- Stellar account with credentials — classic multisig to medium threshold.
- Transaction source account — pre-authenticated by transaction signatures.
- Custom account contract — delegates to
__check_authexport.
require_auth(Address) is the main entrypoint. Matches AuthorizedInvocation trees against execution context. Each pattern node matches at most once per transaction.
Contract Lifecycle
host/lifecycle.rs — create_contract_internal orchestrates:
- Compute contract ID from preimage.
- Verify Wasm code exists.
- Store
ScContractInstanceentry. - Initialize SAC if asset-derived.
- Call
__constructor(protocol ≥22; missing constructor OK if 0 args).
Conversion
host/conversion.rs — methods on Host for converting between ScVal/XDR types and Val/host objects. Includes to_valid_host_val, from_host_val, address/hash extraction helpers, and ScMap↔HostMap conversions. All operations are metered.
Error Handling
HostError (host/error.rs) wraps an Error (the 64-bit Val-encoded error) plus optional DebugInfo (event log + backtrace). ErrorHandler trait provides map_err for wasmi error conversion. Errors are augmented with context via augment_err_result.
Recoverable vs non-recoverable: ScErrorType::Contract errors are recoverable (can be caught by try_call). All others (Budget, Internal, etc.) are non-recoverable and propagate up.
e2e_invoke — Embedder Integration
e2e_invoke.rs provides the top-level entry point for executing Soroban host functions from embedders (stellar-core, RPC). Key types:
InvokeHostFunctionResult— result, ledger changes, encoded events.LedgerEntryChange— per-entry diff with TTL change info.get_ledger_changes()— computes diff between post-execution storage and initial snapshot.
Fees
fees.rs — fee computation protocol for Soroban, shared between stellar-core and RPC. Defines TransactionResources, FeeConfiguration, RentWriteFeeConfiguration, LedgerEntryRentChange. Computes resource fees (CPU, read/write entries/bytes, events, transaction size) and rent fees (based on state size target and TTL extension).
Crypto
crypto/mod.rs — Ed25519 (sign/verify), ECDSA secp256k1/secp256r1, SHA-256, Keccak-256, BLS12-381 (crypto/bls12_381.rs), BN254 (crypto/bn254.rs), Poseidon/Poseidon2 hashes (crypto/poseidon/). All operations charge appropriate ContractCostType budget entries.
Built-in Contracts
builtin_contracts.rs — BuiltinContract trait with fn call(&self, func, host, args) -> Result<Val, HostError>.
Key built-ins:
- Stellar Asset Contract (SAC) (
stellar_asset_contract/) — wraps classic Stellar assets as Soroban contracts. Modules:contract.rs(main dispatch),balance.rs,allowance.rs,admin.rs,event.rs,metadata.rs,storage_types.rs,asset_info.rs,public_types.rs. - Account Contract (
account_contract.rs) — implements__check_authfor classic Stellar accounts. invoker_contract_auth.rs— handles invoker-contract auth entries.storage_utils.rs,base_types.rs,common_types.rs— shared utilities.
LedgerInfo
LedgerInfo (ledger_info.rs) — protocol version, sequence number, timestamp, network ID, base reserve, TTL bounds. Methods: min_live_until_ledger_checked, max_live_until_ledger_checked.
PRNG
host/prng.rs — Prng wraps ChaCha20Rng with metered byte-drawing. Base PRNG seeds per-frame sub-PRNGs deterministically. Separate unmetered PRNGs exist for recording-auth nonces and test data.
Tracing
host/trace.rs — TraceHook, TraceEvent, TraceRecord, TraceState for lifecycle observation. Events include PushCtx, PopCtx, EnvCall, EnvRet. Used for debugging and testing only; disabled during debug-mode operations to avoid observation leaks.
Key Control Flows
Contract Invocation
- Embedder calls
e2e_invokewithHostFunction, footprint, auth entries. - Host is constructed with
StorageandBudgetfrom network config. ModuleCacheis populated or provided externally.Host::with_frame(Frame::HostFunction, ..)pushes top-level frame.- For
InvokeContract: resolves contract instance, loads Wasm, instantiatesVm. Host::with_frame(Frame::ContractVM, ..)pushes contract frame with rollback point.- VM calls exported function. Wasm instructions consume wasmi fuel.
- Host functions called from Wasm go through dispatch: fuel→budget, args relative→absolute, call
VmCallerEnvmethod, result absolute→relative, budget→fuel. - On return, frame pops. On error, storage/events roll back to rollback point.
Host::try_finish()extracts final(Storage, Events).
Object Lifecycle
- Host code calls
add_host_object(value)→ pushes toobjectsvec, returns absolute handle. - When returning to Wasm,
absolute_to_relativeadds to per-frame relative table, returns relative handle. - When Wasm calls host,
relative_to_absolutelooks up in relative table, returns absolute handle. visit_obj(handle, closure)indexes into objects vec, calls closure with typed reference.- Objects are immutable once created. No garbage collection; lifetime is the host's lifetime.
Budget Flow
- Budget initialized from network config cost params + CPU/mem limits.
- Every host operation calls
Budget::charge(CostType, input). chargecomputescost = const_term + lin_term * input, adds to dimension total, checks limit.- Wasm execution uses wasmi fuel; fuel is derived from remaining CPU budget and transferred at host function boundaries.
- Shadow mode (debug/diagnostic work) tracks but doesn't enforce limits.
> related_skills --same-repo
> validating-a-change
comprehensive validation of a change to ensure it is correct and ready for a pull request
> regenerating a technical summary of stellar-core
Instructions for regenerating the full set of subsystem and whole-system technical summary skill documents for stellar-core
> subsystem-summary-of-work
read this skill for a token-efficient summary of the work subsystem
> subsystem-summary-of-util
read this skill for a token-efficient summary of the util subsystem