Rotifer claims that genes are portable — compile once to IR, run in any binding environment. Until v0.6.5, that was a specification promise with zero proof. This release changes that.
The Problem: One Binding, Zero Validation
The IR specification declared:
IR 1.0 release condition: at least two binding environments pass cross-binding interoperability tests.
We had exactly one binding (Local/Cloud) and zero cross-binding tests. The most important section of the IR spec — §10, Cross-Binding Interoperability — had never been exercised against real code.
The Solution: Abstract, Mock, Validate
Rather than spending months building a full Web3 Binding (Solidity contracts, Arbitrum deployment, token economics), we took a minimal approach: build a mock that’s different enough to trigger every negotiation path.
RotiferBinding Trait
A new RotiferBinding trait abstracts what it means to be an execution environment:
pub trait RotiferBinding: Send + Sync { fn binding_id(&self) -> &str; fn metering_unit(&self) -> MeteringUnit; fn capabilities(&self) -> &BindingCapabilities; fn execute_ir(&self, ir_bytes: &[u8], context: &Context, input: Value, phenotype: &Phenotype) -> Result<GeneResult>; fn negotiate(&self, requirements: &IrRequirements) -> NegotiationResult;}Every binding declares its identity, metering unit (Fuel vs Gas vs WallClock), available host functions, and resource ceilings. The existing wasmtime sandbox was refactored into LocalBinding without changing any behavior — all 224 existing tests pass unchanged.
Web3MockBinding
A second binding simulates on-chain constraints:
| Dimension | LocalBinding | Web3MockBinding |
|---|---|---|
| Metering | Fuel (1M cap) | Gas = Fuel × price (500K cap) |
| Memory | 64 MB | 16 MB |
| Timeout | 30s | 5s |
| Filesystem | Allowed | Forbidden |
| Extension functions | None | getBlockNumber, getChainId |
Same wasmtime engine, radically different constraints. These differences are sufficient to exercise every path in the Capability Negotiation protocol.
Capability Negotiation: Three Outcomes
When a gene’s IR is transferred to a new binding, the protocol negotiates compatibility:
- Compatible — all required host functions and resources are available. Execute normally.
- PartiallyCompatible — some optional functions are missing. Gene can run with degraded functionality.
- Incompatible — required functions or resources are missing. Transfer is rejected with structured reasons.
The negotiation checks required host functions, optional host functions, memory requirements, and resource budgets. Six typed IncompatibilityReason variants provide precise diagnostics — not string errors.
9 Cross-Binding Tests
We planned 6 tests and shipped 9:
- Basic interop — echo gene compiled in Local, transferred and executed in Web3Mock
- Resource overrun — gene requiring 32 MB rejected by Web3Mock (16 MB cap)
- Optional function degradation — gene using
getBlockNumbergetsPartiallyCompatiblein Local - Required function rejection — gene requiring
chainCallgetsIncompatiblein Local - Gas metering validation — same IR, same computation, different metering units reported
- No-IR fallback — Wrapped gene (no
irHash) returnsERROR_NO_IR_AVAILABLE7-9. Bidirectional transfer — Web3Mock → Local transfers (reverse direction validation)
254 total Rust tests pass (224 original + 30 binding tests).
What We Found: 7 Spec Recommendations
The validation produced a formal IR Cross-Binding Validation Report with 7 recommendations for IR 0.2.0:
| Priority | Recommendation |
|---|---|
| High | Formalize Capability Negotiation as an explicit sub-protocol (§10.5) |
| High | Clarify compile-time interception vs runtime degradation for extension functions |
| Medium | Separate “core interop protocol” (steps 3-5) from “full propagation flow” (steps 1-7) |
| Medium | Define cross-binding resource metering semantics |
| Medium | Auto-extract IrRequirements from WASM custom sections |
| Low | Clarify extension function naming convention |
| Low | Add version check placeholder in negotiation |
IR 1.0 Progress
With v0.6.5, the IR version can advance from 0.1.0 → 0.2.0. The core interop path is validated. But IR 1.0 still requires a real (non-mock) Web3 Binding and external developer RFC feedback.
What’s Next
v0.6.5 is infrastructure — no new CLI commands, no UI changes, no user-facing features. But it unblocks everything that comes after:
- v0.7 uses
BindingCapabilitiesto declare Hybrid Gene network access requirements - A real Web3 Binding can implement
RotiferBindingdirectly, no abstraction redesign needed - The IR spec has concrete validation data to evolve toward 1.0
Upgrade: npm i -g @rotifer/playground@latest
Docs: rotifer.dev/docs