# Security Considerations for WASM Contracts on Amadeus: A Complete Technical Guide

> Explore WASM contract security on Amadeus. Learn about defense-in-depth validation, sandboxing, gas metering, and import whitelists for robust smart contract development.

- Repository: [Amadeus Protocol/node](https://github.com/amadeusprotocol/node)
- Tags: deep-dive
- Published: 2026-08-20

---

**Amadeus executes WASM smart contracts inside a sandboxed Wasmer runtime with defense-in-depth validation that enforces binary size limits, structural constraints, gas metering, and a strict two-function import whitelist.**

The Amadeus blockchain relies on WebAssembly (WASM) as its smart contract execution format, running inside a carefully hardened environment. Every contract undergoes rigorous static and dynamic checks before and during execution, ensuring that malicious or buggy code cannot compromise the network. This guide examines the **security considerations for WASM contracts on Amadeus** as implemented in the `amadeusprotocol/node` repository.

## Core Security Architecture

The Amadeus execution model follows a **defense-in-depth** strategy with three interconnected layers: static validation intercepts malformed modules before instantiation; runtime metering bounds computational cost; and import isolation prevents sandbox escape.

### The Wasmer Sandbox Foundation

Amadeus builds its execution environment on the **Wasmer** WebAssembly runtime. This provides memory-safe execution, but the node adds substantial hardening through custom middleware and validation logic concentrated in [`ex/native/rdb/src/consensus/bic/wasm.rs`](https://github.com/amadeusprotocol/node/blob/main/ex/native/rdb/src/consensus/bic/wasm.rs).

## Static Module Validation

Every WASM binary passes through `check_module_limits` (lines 648–709 in [`wasm.rs`](https://github.com/amadeusprotocol/node/blob/main/wasm.rs)) before execution. This function implements nine distinct security checks that reject malformed or malicious modules with explicit error strings.

### Binary Size and Complexity Limits

| Limit | Constant | Purpose | Location |
|-------|----------|---------|----------|
| Maximum binary size | `protocol::WASM_MAX_BINARY_SIZE` | Prevents DoS from oversized uploads | Lines 648–652 |
| Function count | Internal limit | Stops parser exhaustion attacks | Lines 658–665 |
| Global count | Internal limit | Limits module complexity | Lines 665–670 |
| Export count | Internal limit | Restricts exposed interface surface | Lines 670–676 |
| Import count | Internal limit | Enforces minimal dependency surface | Lines 676–682 |
| Code body count | Internal limit | Prevents excessive function bodies | Lines 682–686 |

Violating any of these triggers immediate rejection with identifiers like `wasmparser_function_count_exceeds_limit`.

### Memory Layout Protections

The data section validator (lines 686–709) enforces four critical constraints:

- **Offset must be `i32.const`** — No dynamic or complex offset calculations
- **Offset must be non-negative** — Prevents wrapping to high memory addresses
- **No overlap with reserved memory** — Protects the node's internal region
- **First 65 KB reserved** — The VM environment occupies this region; contracts cannot write here

These rules block out-of-bounds writes that could corrupt host state or escape the sandbox.

### Start Section Prohibition

Amadeus explicitly disallows WASM start sections (line 709). This prevents contracts from defining implicit entry points that execute before the intended call frame, ensuring all execution flows through the contract's declared public interface.

## Runtime Security Mechanisms

Once validated, contracts execute under continuous monitoring with hard resource boundaries.

### Gas Metering via Wasmer Middleware

Every WASM operation consumes gas through Wasmer's `metering` middleware. The configuration appears in [`wasm.rs`](https://github.com/amadeusprotocol/node/blob/main/wasm.rs) (lines 22–24, 52–55):

```rust
// wasm.rs lines 22-24
use wasmer::Middleware;
use wasmer_compiler_singlepass::Singlepass;
use wasmer_middlewares::Metering;

// Cost per WASM operation
const COST_PER_OP_WASM: u64 = 1;

```

The metering state synchronizes with the transaction budget through `budget_sync_in` (lines 52–60). When gas exhausts, the VM aborts immediately—no partial state commits, no resource exhaustion.

### Pointer and Return Value Limits

Two additional bounds protect against memory abuse:

- **`WASM_MAX_PTR_LEN`** (~1 MiB): Enforced in `import_log_implementation` and `import_return_implementation` (lines 172–194). Prevents oversized copies that could overflow the gas meter or exhaust memory.
- **`WASM_MAX_PANIC_MSG_SIZE`**: Enforced in `set_return_value` (lines 45–48). Stops contracts from flooding logs with arbitrarily large panic messages.

Exceeding `WASM_MAX_PTR_LEN` yields the explicit error `exec_ptr_term_too_long`.

### Artifact Cache Protections

Compiled modules are cached with a 4 GiB limit (`ARTIFACT_CACHE_MAX_BYTES`). The `ArtifactCache` implementation (lines 45–98) prevents cache-filling attacks that could exhaust node memory through repeated deployments of distinct contracts.

## Host Import Isolation

The contract's only bridge to the outside world is a **strict whitelist of two functions**:

| Function | Purpose | Location |
|----------|---------|----------|
| `log` | Emit structured log messages | `import_log_implementation` |
| `return` | Return execution results | `import_return_implementation` |

No filesystem access. No networking. No OS syscalls. The `HostEnv` struct (lines 39–44) and `setup_wasm_instance` configuration establish this minimal surface.

```rust
// Conceptual structure from wasm.rs analysis
struct HostEnv {
    // Only log and return capabilities exposed
    log_fn: fn(*const u8, usize),
    return_fn: fn(*const u8, usize) -> !,
}

```

This isolation guarantees that **contract code cannot escape the sandbox** regardless of logic errors or intentional attacks.

## Practical Secure Contract Development

The following patterns demonstrate compliance with Amadeus security constraints.

### Minimal Compliant Contract

```rust
// contract_samples/rust/examples/counter.rs
use amadeus_sdk::wasm::{log, return_};

#[no_mangle]
pub extern "C" fn increment(state: *mut u64) {
    // SAFELY read/write within contract linear memory
    unsafe {
        let value = state.read_unaligned();
        state.write_unaligned(value.wrapping_add(1));
    }
    log(b"counter incremented");
    // Empty payload return—respects ptr/len limits
    return_(b"", 0);
}

```

**Security characteristics:**
- Uses only whitelisted host functions (`log`, `return_`)
- Operates exclusively on contract-owned linear memory
- No dynamic allocation, keeping binary size minimal
- No external pointers or host memory references

### Safe Logging Pattern

```rust
use amadeus_sdk::wasm::log;

#[no_mangle]
pub extern "C" fn operation(state: *mut u8) {
    // Fixed-size message guaranteed under WASM_MAX_PTR_LEN
    let msg = b"operation completed";
    log(msg);  // ~19 bytes, well under ~1 MiB limit
}

```

Attempting to log a buffer exceeding `WASM_MAX_PTR_LEN` triggers runtime abortion with `exec_ptr_term_too_long`.

### Deployment Validation Flow

```bash

# Compile to WASM target

cargo build --target wasm32-unknown-unknown --release

# Deploy via CLI—triggers full validation pipeline

amadeus-node contract deploy \
  --binary target/wasm32-unknown-unknown/release/counter.wasm \
  --init-function "increment" \
  --init-args ""

```

The CLI invokes `contract_validate` ([`lib.rs`](https://github.com/amadeusprotocol/node/blob/main/lib.rs) line 819), which chains to `validate_contract` and `check_module_limits`. Any limit violation aborts deployment with a specific error code before the transaction reaches consensus.

## Critical Source Files

| Path | Responsibility | Key Functions |
|------|---------------|-------------|
| [`ex/native/rdb/src/consensus/bic/wasm.rs`](https://github.com/amadeusprotocol/node/blob/main/ex/native/rdb/src/consensus/bic/wasm.rs) | Core WASM security | `check_module_limits`, `setup_wasm_instance`, `budget_sync_in`, `ArtifactCache` |
| [`ex/native/rdb/src/consensus/consensus_apply.rs`](https://github.com/amadeusprotocol/node/blob/main/ex/native/rdb/src/consensus/consensus_apply.rs) | Execution entry point | `call_wasmvm` |
| [`ex/native/rdb/src/lib.rs`](https://github.com/amadeusprotocol/node/blob/main/ex/native/rdb/src/lib.rs) | High-level validation | `contract_validate` (line 819) |
| [`contract_samples/rust/examples/counter.rs`](https://github.com/amadeusprotocol/node/blob/main/contract_samples/rust/examples/counter.rs) | Reference implementation | Compliant minimal contract |
| [`contract_samples/rust/examples/nft.rs`](https://github.com/amadeusprotocol/node/blob/main/contract_samples/rust/examples/nft.rs) | Advanced patterns | Storage-safe complex contract |

## Summary

- **Static validation** in `check_module_limits` rejects malformed modules before execution through nine structural checks
- **Gas metering** via Wasmer middleware bounds computation with per-operation costs and budget synchronization
- **Memory safety** is enforced through data offset validation, reserved region protection, and pointer length limits
- **Import isolation** restricts contracts to exactly two host functions: `log` and `return`
- **Cache limits** prevent memory exhaustion through the 4 GiB `ArtifactCache` bound
- **Deployment validation** runs the full security pipeline via `contract_validate` before any contract persists

## Frequently Asked Questions

### What happens if a WASM contract exceeds the binary size limit?

The `check_module_limits` function rejects the deployment immediately with error code `wasmparser_binary_size_exceeds_limit`. The transaction fails before the contract is stored or executed, protecting the network from denial-of-service through oversized uploads.

### Can Amadeus WASM contracts perform network I/O or file system operations?

No. The import whitelist in `setup_wasm_instance` exposes only `log` and `return`. No networking, filesystem, or OS interfaces are available. This is enforced at the Wasmer runtime level—attempting to import forbidden functions causes instantiation failure.

### How does Amadeus prevent infinite loops in WASM contracts?

Through **gas metering**. Every WASM operation consumes `COST_PER_OP_WASM` units from the transaction budget. The `Metering` middleware tracks consumption synchronously; exhaustion triggers immediate VM termination via `budget_sync_in`. This bounds execution regardless of control flow structure.

### What error occurs when a contract tries to log an oversized message?

The `import_log_implementation` function checks buffer length against `WASM_MAX_PTR_LEN` (approximately 1 MiB). Exceeding this limit aborts execution with error `exec_ptr_term_too_long`, preventing log flooding attacks.