V0.7 to V0.8 Migration

Covenant V0.8 is fully backward compatible at the source level. Existing .cov files from V0.7 compile unchanged. This guide documents the optional enhancements you can adopt to get the performance and auditability improvements V0.8 ships.

Breaking changes

None. V0.8 is strictly additive relative to V0.7.0 GA. Every V0.7.x public API remains stable. OMEGA V4 audit findings remain resolved; V0.8 introduces no new critical or high findings.

New features you can adopt

1. Compile to WebAssembly

covenant build contract.cov --target-chain wasm
#   → contract.wasm (deterministic, `wasmparser::validate`-clean)
#   → contract.metadata.json (ABI, imports, exports, storage layout)

No source-level changes required. The same .cov file compiles to EVM, Aster Chain, and WASM targets. See the targets reference for the host-import ABI.

2. Optimization annotations

@batch_up_to(N) — bounded-loop hint

-- V0.7: standard loop (no hint)
action process_batch(items: [amount; 32]) {
    for i in 0..32 { process_item(items[i]) }
}

-- V0.8: annotated
@batch_up_to(32)
action process_batch(items: [amount; 32]) {
    for i in 0..32 { process_item(items[i]) }
}

In V0.8 the annotation drives the batch_unrolling analysis pass. If the annotated function contains nothing that benefits from batching, or if N > 64, the compiler emits W406 (batch_not_actionable) so mis-applied annotations are surfaced early. True loop unrolling is planned for V0.8.x once the generic Loop opcode lands.

@precompute(expr) — compile-time evaluation

-- V0.7: hash computed at runtime every time DOMAIN is read
field DOMAIN: hash = keccak(b"MyContract:v1")

-- V0.8: hash computed at compile time, embedded in bytecode
@precompute(keccak(b"MyContract:v1"))
field DOMAIN: hash

V0.8 enables this for Keccak and Blake2 over compile-time-constant byte inputs (text / integer / bytes operands, encoded abi.encodePacked-style). Typical savings: ~100 gas per field access.

3. Bridge construct (now functional)

If you declared bridge X anchored_on [...] in V0.7, the construct parsed but synthesized no runtime logic (W606). V0.8 synthesizes four canonical functions per bridge artifact:

bridge TokenBridge anchored_on [chain_ethereum, chain_arbitrum] {
    field balances: map<address, encrypted amount>

    action transfer(
        to: address,
        value: encrypted amount,
        dest_chain: uint256,
        nonce: uint256,
    ) {
        -- anti-replay via synthesized mark_processed(src, dst, nonce)
        assert mark_processed(local_chain(), dest_chain, nonce)
        -- … your bridge payload logic …
    }
}

Synthesized functions:

  • local_chain() -> uint256
  • nonce_for(uint256 src, uint256 dst) -> uint256
  • mark_processed(uint256 src, uint256 dst, uint256 nonce) -> bool
  • is_processed(uint256 src, uint256 dst, uint256 nonce) -> bool

compile_bridge_for_chain(module, config, chain, diags) emits one artifact per chain listed in anchored_on [...] with the correct local_chain() constant baked in.

4. Amnesia ceremonies (now fully functional)

If you declared ceremony / destroy(field) blocks in V0.7, they compile-passed but the EVM lowering for ShamirSplit / ShamirReconstruct / VdfLock / VdfUnlock emitted a hard E516 + REVERT-stub (KSR-CVN-022).

V0.8 lowers all four opcodes to dedicated precompiles at 0x124–0x127:

ceremony KeyDestructor {
    admin_key: encrypted bytes

    action destroy_admin_key() when phase == finalized {
        destroy(admin_key)  -- zeroes storage, emits VDF-bound proof
        phase = destroyed   -- terminal state
    }
}

5. Aggregate operators

The IR-level lowering plan is reusable today via covenant-stdlib::aggregates::lower_aggregate_plan(op, receiver):

OperatorPlaintext mapEncrypted mapPlaintext listEncrypted list
.sum✅ (tree-reduce)✅ (tree-reduce)
.count
.max / .min✅ (bootstrap)✅ (bootstrap)
.argmax_by_address✅ (bootstrap)

Surface-syntax wiring (parser / typecheck) lands in V0.8.x.

6. Noise-budget warnings

The compiler now tracks a symbolic FHE noise level per encrypted value and warns when it approaches or exceeds the budget:

W701: FHE noise at %0 exceeds budget (105.3 / 100.0).
   help: insert an explicit bootstrap(…) before this use.

W702: FHE noise at %17 approaching budget (87.2 / 100.0).
   help: consider scheduling a bootstrap before further encrypted ops.

Caps are configurable via OptimizerConfig::{noise_budget_cap, noise_budget_soft_cap} if the defaults (100.0 / 80.0) do not match your target precompile.

Gas changes to expect

Contract profileV0.7 → V0.8 delta
FHE-heavy (encrypted arith)−15 % to −30 % (coalescing)
Hash-constant-heavy≈ −100 gas / field (precompute)
ERC-20 / basic vaults±2 % (metadata-level variation)
@batch_up_to(N) + aggregatesgroundwork only in V0.8

If your contract is deployed behind a proxy and you need byte-identical bytecode to an existing V0.7 deployment, compile with --opt-level=0 to match V0.7.0 behavior (identity pass set).

Deprecation warnings

V0.8 introduces no deprecations. Planned deprecations for V0.8.x:

  • None currently.

Testing your migration

Build check

# V0.7 contract should compile clean under V0.8 (may surface new W701/W702)
covenant build my_contract.cov

Gas comparison

# Seed a baseline against the V0.7 compiler (if you still have it installed)
covenant-0.7 bench --update --baseline /tmp/v07.json my_contract.cov

# Compare V0.8 against it
covenant bench --baseline /tmp/v07.json my_contract.cov
# Exits 1 if any benchmark regresses > 5 %.

Bytecode comparison

covenant-0.7 build my_contract.cov --output v07/
covenant     build my_contract.cov --output v08/
cmp v07/MyContract.bin v08/MyContract.bin
# Expected: differ (optimizer improvements). Use --opt-level=0 on V0.8
# if you require identical bytecode.

Support