> For the complete documentation index, see [llms.txt](https://quantumwing.gitbook.io/quantumwing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://quantumwing.gitbook.io/quantumwing/smart-contracts/wasm-gas-metering.md).

# WASM Gas Metering

Deterministic WASM gas instrumentation at every basic-block boundary (E-4)

QWVM v1 originally relied on a wall-clock watchdog (5 seconds, then trap) to bound contract execution. Wall-clock metering is non-deterministic across nodes — the same contract could complete on a fast validator and timeout on a slow one, producing divergent state.

Tier E-4 replaces the watchdog with **bytecode instrumentation**: the QWVM walks every WASM module before execution and injects deterministic charge points at every basic-block boundary. Gas consumption is now a pure function of the bytecode, not the host's CPU speed.

Reference commit: `fd4ecd486`.

## Algorithm

```
1. parse module                        (sections: type, function, code, ...)
2. for each function body:
     identify basic blocks
       boundaries = { entry, branch targets, calls, returns,
                      memory.grow, table.grow, host_call }
3. for each basic block:
     compute static cost = sum(GasPerInstruction[op] for op in block)
     prepend instructions to charge that cost:
         global.get  $gas_remaining
         i64.const   <static cost>
         i64.lt_u
         if           ;; trap if not enough gas
             unreachable
         end
         global.get  $gas_remaining
         i64.const   <static cost>
         i64.sub
         global.set  $gas_remaining
4. add $gas_remaining as imported global, initialised by host per call
5. re-emit instrumented module
```

The instrumented module is cached in BadgerDB keyed by `keccak256(originalBytes)` so the rewrite happens once per unique contract.

## Determinism guarantees

* Two nodes running the same instrumented bytecode against the same input consume **exactly** the same gas.
* A contract that runs out of gas traps at a deterministic instruction boundary; the trap is reflected in the receipt as `status: 0x0`.
* `memory.grow` and `table.grow` carry per-page surcharges (see `GasPerInstruction` table below) so a quadratic memory exploit cannot bypass the bound.

## Verification

The instrumenter ships with a linear-scaling test:

```
n=10        →   97 gas
n=100       →  907 gas
n=1000      → 9007 gas
```

Linear in `n` confirms charges fire on every iteration of a loop body, not just once per call. Trap latency is \~544µs (the cost of the `global.get; const; lt_u; if; unreachable` injection) versus the old 5s watchdog.

## GasPerInstruction (excerpt)

| Op                                                   |              Cost |
| ---------------------------------------------------- | ----------------: |
| `i32.const`, `i64.const`, `local.get`, `local.set`   |                 1 |
| `i32.add`, `i32.sub`, `i32.mul`, `i32.and`, `i32.or` |                 2 |
| `i64.add`, `i64.sub`, `i64.mul`                      |                 3 |
| `i32.div_u`, `i64.div_u`, `i32.rem_u`, `i64.rem_u`   |                 8 |
| `i32.load`, `i64.load`, `i32.store`, `i64.store`     |                 3 |
| `memory.grow`                                        | 100 + 10 per page |
| `call`                                               |                 4 |
| `call_indirect`                                      |                 8 |
| `host_call` (varies — see host fn table)             | 100 + per-fn cost |

Tuning the table is post-launch work — current values are conservative and deliberately err high. Final calibration against benchmark contracts is tracked under E-4 follow-up.

## Host function pricing

Each host function carries a fixed minimum charge plus a payload-size term:

```
storage_get        : 200 + 0.1 * value_len
storage_set        : 5000 + 1.0 * value_len    (refund if slot was nonzero before)
emit_event         : 375 + 8 * topic_count + 0.1 * data_len
get_random_bytes   : 200
get_block_hash     : 100
blockchain_transfer: 9000
get_balance        : 700
get_timestamp      : 50
```

The QRC-20 reference contract's `transfer` consumes \~22,500 gas under this table — comparable to Ethereum's ERC-20 (\~46,000). The Solidity tax goes into things QWVM doesn't pay for: dynamic stack management, ECDSA signature recovery in the runtime, etc.

## Migration

All 11 reference contracts in `contracts/` were re-deployed clean after the instrumentation landed. Existing on-chain contracts pre-E-4 continue to run; the host applies instrumentation lazily on first call after the activation height (set in genesis via `wasm_metering_activation_height`).

A contract that **fails** instrumentation (malformed module, unsupported op) is rejected at activation; the deployer must redeploy. None of the 11 reference contracts hit this path.

## Code paths

* `qwvm/instrument.go` — bytecode walker + injector
* `qwvm/runtime.go` — host function table + per-call gas counter
* `qwvm/cache.go` — instrumented-module cache keyed by source hash

## Related

* [QWVM Overview](/quantumwing/smart-contracts/qwvm.md) — host function table + WASM module surface
* [Gas & Fees](/quantumwing/transactions/gas-fees.md) — block-level gas accounting
* [EIP-1559 Fee Market](/quantumwing/transactions/eip1559.md) — base fee + tip split


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://quantumwing.gitbook.io/quantumwing/smart-contracts/wasm-gas-metering.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
