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() -> uint256nonce_for(uint256 src, uint256 dst) -> uint256mark_processed(uint256 src, uint256 dst, uint256 nonce) -> boolis_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):
| Operator | Plaintext map | Encrypted map | Plaintext list | Encrypted 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 profile | V0.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) + aggregates | groundwork 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
- GitHub issues: https://github.com/Valisthea/covenant/issues
- Security (private disclosure): security@kairos-lab.org