WASM Runtime Environment in Amadeus Protocol: How Smart Contracts Execute on Wasmer 7.1.0

The Amadeus Protocol WASM runtime environment is a Wasmer 7.1.0-based execution engine that uses single-pass compilation, deterministic metering, and an LRU artifact cache to run WebAssembly smart contracts with gas-bounded execution.

The Amadeus node executes smart-contract logic by embedding a purpose-built WebAssembly runtime. Built on Wasmer 7.1.0, the system combines fast compilation, execution metering, and host-function injection to provide deterministic, metered contract execution. This article examines the runtime's architecture, tracing actual implementation paths in the amadeusprotocol/node repository.


Core Architecture of the WASM Runtime

The runtime environment consists of six integrated components that handle everything from initial validation to gas accounting during execution.

Wasmer Engine with Single-Pass Compilation

At the heart of the system is the Wasmer Engine, configured with Wasmer's single-pass compiler for predictable compilation times. In ex/native/rdb/src/consensus/bic/wasm.rs, the engine initializes via EngineBuilder with Singlepass as the backend:

// ENGINE_VERSION_TAG identifies the runtime version for cache invalidation
const ENGINE_VERSION_TAG: &str = "wasmer-7.1.0-singlepass";

The compile_and_cache_module function transforms raw Wasm bytes into an executable Module, then serializes it for storage in the ArtifactCache. This design prioritizes fast compilation over optimization, ensuring consistent latency across contract deployments.

Artifact Cache for Compiled Modules

The runtime maintains an LRU cache with a 4 GiB maximum size to eliminate redundant compilation. The cache keys modules by SHA-256(ENGINE_VERSION_TAG || wasm_bytes), automatically invalidating entries when the runtime version changes.

This caching layer proves critical for throughput: after first compilation, subsequent contract invocations reuse the serialized artifact without re-invoking the compiler.

Metering Middleware for Gas Accounting

Deterministic execution cost requires operation-level metering. The runtime injects wasmer_middlewares::metering during module compilation, with COST_PER_OP_WASM set to 1 execution point per Wasm operation in protocol.rs:

pub const COST_PER_OP_WASM: i128 = 1;

Two functions in wasm.rs synchronize the metered state with the transaction's budget:

  • budget_sync_in — initializes metering points from applyenv.exec_left
  • set_remaining_points — writes updated gas back after host function calls

When gas exhaustion occurs, the VM panics with "exec_invalid_module" or "exec_return_value_too_large" depending on the failure context.

Host Environment and Imported Functions

The HostEnv struct exposes controlled interfaces for contracts to interact with the Amadeus state machine. Only two host functions are currently available:

Function Implementation Purpose
log import_log_implementation Emit structured logs from contract execution
return import_return_implementation Return a byte vector to the caller

These imports are injected during setup_wasm_instance, which prepares a new Instance with accessible linear memory and the metered execution context.

ApplyEnv: Transaction Context Container

The ApplyEnv struct (defined in consensus_apply.rs) carries mutable execution state across the contract lifecycle:

// Fields tracked during contract execution
- exec_left: remaining execution budget
- storage_left: remaining storage budget  
- logs: accumulated contract logs
- caller: transaction initiator address

The runtime updates these fields throughout execution, ensuring atomic budget consumption across storage operations and Wasm opcodes.

Validation Layer

Before any compilation occurs, validate_contract enforces structural constraints using wasmparser:

// Size limits enforced via protocol constants
protocol::WASM_MAX_BINARY_SIZE  // maximum contract binary size

This validation prevents resource exhaustion attacks through malformed Wasm and guarantees that only well-formed modules reach the compiler.


Contract Execution Flow: From Bytes to Result

The Amadeus Protocol WASM runtime follows a six-stage pipeline for every contract interaction:

  1. Contract submission — Wasm binary stored via the contract BIC (binary interface contract)

  2. Validation — validate_contract parses with wasmparser, enforces protocol::WASM_MAX_BINARY_SIZE

  3. Caching — compiled module serialized and cached; cache key derived from version-tagged hash

  4. Instance creation — setup_wasm_instance creates Instance, injects HostEnv, syncs metering

  5. Function call — call_contract (exposed as call_wasmvm) executes entry point with provided arguments

  6. Budget accounting — remaining gas read from middleware and written to applyenv.exec_left

The entire pipeline executes within the native RDB crate, which serves as the Amadeus node's execution layer.


Runtime Configuration and Constants

Protocol-level parameters governing execution are centralized in ex/native/rdb/src/consensus/bic/protocol.rs:

pub const COST_PER_OP_WASM: i128 = 1;                    // execution cost per Wasm op
pub const WASM_MAX_BINARY_SIZE: usize = /* ... */;       // maximum allowed Wasm size
pub const WASM_MAX_PTR_LEN: usize = /* ... */;           // max host-pointer buffer length
pub const WASM_MAX_PANIC_MSG_SIZE: usize = /* ... */;    // max panic message size

These constants ensure deterministic fees across all nodes in the network.


Code Examples: Deployment and Execution

Validating a New Contract Deployment

use rdb::consensus::bic::{wasm, protocol};

// Initialize execution environment with caller and budgets
let mut env = ApplyEnv::new(caller_address, exec_budget, storage_budget);

// Extract Wasm payload from deployment transaction
let wasm_bytes: Vec<u8> = tx.payload.clone();

// Validate before storing (parses, checks limits, tests compilation)
wasm::validate_contract(&mut env, &wasm_bytes)?;

Calling a Contract Function

use rdb::consensus::bic::wasm;

// Execute contract entry point with arguments
let result: Vec<u8> = wasm::call_contract(
    &mut env,                          // mutable ApplyEnv for budget/log tracking
    &wasm_bytes,                       // compiled or raw Wasm bytes
    "transfer".to_string(),            // exported function name
    vec![                              // function arguments
        b"sender_addr".to_vec(),
        b"recipient_addr".to_vec(),
        b"100".to_vec(),
    ],
)?;

println!("Contract returned: {:?}", result);

These entry points — validate_contract and call_contract — constitute the primary interface between the node's consensus layer and the Wasm runtime.


Dependencies and Build Configuration

The runtime's capabilities are declared in ex/native/rdb/Cargo.toml:

[dependencies]
wasmer = "7.1.0"
wasmer-compiler-singlepass = "7.1.0"
wasmer-middlewares = "7.1.0"
wasmparser = "0.x"

This dependency set pins the Wasmer 7.1.0 stack with single-pass compilation and metering support.


Summary

  • The Amadeus Protocol WASM runtime embeds Wasmer 7.1.0 with single-pass compilation for predictable performance
  • Metering middleware charges COST_PER_OP_WASM = 1 per operation, synchronized via budget_sync_in and set_remaining_points
  • A 4 GiB LRU artifact cache eliminates redundant compilation using SHA-256 keyed by engine version and Wasm bytes
  • HostEnv exposes minimal host functions (log, return) with linear memory access
  • ApplyEnv tracks mutable execution state including gas budgets, storage limits, and emitted logs
  • All execution paths reside in ex/native/rdb/src/consensus/bic/wasm.rs and consensus_apply.rs

Frequently Asked Questions

What compiler does the Amadeus WASM runtime use?

The runtime uses Wasmer's single-pass compiler via wasmer-compiler-singlepass version 7.1.0. This compiler prioritizes fast, predictable compilation times over optimization depth, ensuring consistent latency for contract deployment and execution across the network.

How does Amadeus Protocol prevent infinite loops in smart contracts?

The runtime injects metering middleware that decrements execution points for every Wasm operation. When applyenv.exec_left reaches zero, the VM panics with "exec_invalid_module". This deterministic gas model guarantees that all executions terminate within bounded resource consumption.

Where are compiled Wasm modules cached in the Amadeus node?

Compiled modules are stored in an LRU artifact cache with a 4 GiB maximum size, implemented in wasm.rs. The cache uses keys derived from SHA-256(ENGINE_VERSION_TAG || wasm_bytes), automatically invalidating entries when the runtime version changes to prevent stale code execution.

What host functions are available to Amadeus smart contracts?

Contracts can access exactly two host functions: log for emitting structured logs and return for returning a byte vector to the caller. These are implemented as import_log_implementation and import_return_implementation in wasm.rs, with all other system interactions prohibited for determinism and security.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →