Skip to content

Security

Security model

Wasichain does not rely on a custom VM for contract isolation. It runs standard wasm32-wasip2 components in Wasmtime, then constrains what those components are allowed to import and do.

The security boundary comes from three layers working together:

  • deterministic admission checks before activation
  • Wasmtime sandboxing plus a capability-free WASI context
  • runtime limits on fuel, time, storage mutation, and call structure

Sandboxing

Contracts execute inside Wasmtime with a minimal WASI context that grants no ambient capabilities.

In practice, contracts do not get access to:

  • filesystem APIs
  • sockets or arbitrary network access
  • clocks, timers, or wall-clock time
  • randomness
  • process spawning or environment access

The only useful host surface is the Wasichain WIT: storage, events, sender/origin identity, deferred dispatch, and read-only contract queries.

Determinism

Determinism is enforced at both admission time and execution time.

Before activation, the admission pipeline validates that uploaded code:

  • is valid Wasm/component data
  • stays within the maximum blob size
  • exports the required contract ABI
  • imports only the allowed namespaces

At runtime, determinism comes from the absence of nondeterministic host capabilities and from consensus over:

  • the raw Wasm code_hash
  • the VM version string
  • the activation lifecycle recorded on-chain

Validators do not need identical native machine code. Consensus is over the raw Wasm blob and the activation fact, not over serialized native artifacts.

Code admission and compilation-bomb resistance

Untrusted contract compilation is kept off the consensus hot path.

The flow is:

  1. upload the raw Wasm blob
  2. validate and compile it in admissiond
  3. have validators attest readiness with PreparedCodeVote
  4. activate only after quorum

This avoids forcing validators to compile attacker-supplied code while executing transactions in consensus.

Current concrete defenses include:

  • maximum blob-size enforcement
  • deterministic structural validation before compilation
  • isolated admission-sidecar compilation instead of in-transaction compilation
  • compiled-artifact cache verification before execution

Fuel and denial-of-service resistance

Execution is metered with Wasmtime fuel.

  • ExecContract pre-charges against the declared fuel_limit
  • execution stops on OutOfFuel
  • the block proposer also enforces a block-wide fuel cap

Wasichain also enforces a wall-clock execution limit using Wasmtime epoch interruption. This protects against cases where fuel alone is not enough to bound execution cost.

See Fees & Fuel for pricing details.

Re-entrancy resistance

Mutable cross-contract calls use an actor-style dispatch/reply model rather than synchronous re-entrant execution.

That means:

  • contract A finishes before contract B begins
  • sub-message effects are isolated in nested overlays
  • failures roll back the failing frame instead of partially mutating shared state

This removes classic synchronous re-entrancy from the mutable call path by construction.

Read-only contract queries are allowed synchronously because they cannot commit writes.

State isolation and atomicity

Each contract has its own key-value namespace.

  • reads see committed state plus the current transactional overlay
  • writes go to an overlay first
  • failed execution discards the overlay
  • successful execution commits atomically

Sub-messages get nested overlay frames, so partial failures can be rolled back cleanly.

Query safety

Queries run in read-only mode.

During a query:

  • kv-set
  • kv-delete
  • emit-event
  • dispatch

are rejected. Query execution can inspect state, but it cannot persist mutations.

Additional structural limits

Wasichain also enforces:

  • a maximum blob size for uploaded code
  • a maximum fuel budget per transaction
  • a maximum total fuel budget per block
  • a maximum sub-message depth

Together, these keep both execution and host-side bookkeeping bounded.