> For the complete documentation index, see [llms.txt](https://tollcraft.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tollcraft.gitbook.io/docs/budget-assert/measurements.md).

# Measurements

This file records empirical cost measurements comparing local Soroban budget estimates against real network costs. Every measurement PR adds its numbers here so the series stays comparable.

## Methodology

Each measurement compares a local budget estimate against a network-verified figure for the same operation. The local estimate comes from `Env::cost_estimate().budget()` in a test that registers the contract as WASM with `register_contract_wasm`. The network figure comes from `simulateTransaction` on Soroban testnet — the same endpoint the network uses to charge non-refundable resource costs.

The WASM is compiled with the profile specified in the **Build profile** column. The direction of the local-vs-network gap is not stable across profiles; the same contract built with Cargo's default release profile can produce a gap pointing in the opposite direction of one built with the size-optimization profile. Every figure includes its build context.

For the storage-write measurement, the complete capture record is checked in at [`cargo-budget-report/fixtures/storage_write_benchmark.json`](https://github.com/Tollcraft/soroban-budget-assert/tree/main/cargo-budget-report/fixtures/storage_write_benchmark.json). It records the fixture arguments, local capture command, network capture method, both figures, and the calculated delta.

### Column reference

| Column             | Meaning                                                                                    |
| ------------------ | ------------------------------------------------------------------------------------------ |
| **Operation type** | Category of operation being measured                                                       |
| **Local estimate** | Value reported by `Env::cost_estimate().budget()` in a WASM-registered local test          |
| **Network figure** | Value returned by `simulateTransaction` on Soroban testnet                                 |
| **Delta**          | (local − network) / network, expressed as a percentage; positive means local overestimates |
| **Fixture**        | Contract, function, and arguments used for the measurement                                 |
| **Build profile**  | Cargo profile used to compile the WASM                                                     |
| **Toolchain**      | Rust toolchain version (`rustc --version`)                                                 |
| **Date**           | Date the measurement was taken                                                             |

## Existing measurements

These figures were produced during the initial tool development and are published in the [Protocol Mechanics documentation](/docs/budget-assert/mechanics.md). They serve as the worked example for contributors adding new measurements.

### CPU instructions

| Operation type                        | Local estimate | Network figure |  Delta | Fixture                                               | Build profile                                      | Toolchain    | Date       |
| ------------------------------------- | -------------: | -------------: | -----: | ----------------------------------------------------- | -------------------------------------------------- | ------------ | ---------- |
| Mixed compute + storage (native Rust) |        143,887 |        756,678 | −81.0% | `amm-pool-contract::do_expensive_work(10_000)`        | N/A (native test, no WASM)                         | rustc 1.81   | 2025-Q1    |
| Mixed compute + storage (WASM)        |        901,816 |        756,678 | +19.2% | `amm-pool-contract::do_expensive_work(10_000)`        | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.81   | 2025-Q1    |
| Mixed compute + storage (WASM)        |        767,049 |        832,006 |  −7.8% | `amm-pool-contract::do_expensive_work(10_000)`        | default `release` (`opt-level=3`)                  | rustc 1.81   | 2025-Q1    |
| Storage write (WASM)                  |         36,840 |         44,512 | −17.2% | `amm-pool-contract::write_bytes(1,024 bytes)`         | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.81   | 2026-07-26 |
| Storage read (WASM)                   |              — |              — |      — | `amm-pool-contract::do_read_heavy_work(100)`          | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.85   | 2026-07-27 |
| Host-function calls (WASM)            |      1,280,000 |      1,600,000 | −20.0% | `host-function-contract::repeated_sequence(1_000)`    | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.81   | 2025-Q2    |
| TTL extension (WASM)                  |              — |              — |      — | `amm-pool-contract::extend_instance_ttl(100, 10_000)` | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.85.0 | —          |

> **TTL extension note.** The TTL extension fixture registers the contract as WASM, initializes it (creating instance storage entries), then calls `extend_instance_ttl(threshold=100, extend_to=10_000)`. Local estimate collected via `cargo test -p amm-pool-contract --test calibrate_extend_ttl -- --nocapture`. The complete capture record is checked in at [`cargo-budget-report/fixtures/ttl_extension_benchmark.json`](https://github.com/Tollcraft/soroban-budget-assert/tree/main/cargo-budget-report/fixtures/ttl_extension_benchmark.json). Network figure requires a `simulateTransaction` run on Soroban testnet (see fixture for exact commands).

The native Rust row is included solely to illustrate that native estimates are unreliable for budget decisions. Only WASM-mode estimates should be used for assertions.

The first three rows measure the same `do_expensive_work(10_000)` function, which mixes a compute loop (`n` iterations of `wrapping_add(wrapping_mul)`) with a storage write (`Vec` of up to 100 elements written to `env.storage().instance().set`). The numbers are aggregate costs of both operations.

The storage-write row isolates the `write_bytes` fixture with a 1,024-byte value. Its delta is calculated as `(36,840 − 44,512) / 44,512 = −0.1724`, so the WASM-registered local estimate is 17.2% lower than the testnet simulation for this operation and underestimates the network cost.

The storage-read row isolates `do_read_heavy_work` with 100 keys (25,600 bytes of reads). Unlike the write measurement, the read fixture necessarily includes a write phase (to populate the keys before reading them). The writes use `instance()` storage, which matches real contract usage, while the write measurement counterpart (`do_write_heavy_work`) uses `temporary()` storage — the two measurements are therefore not directly comparable at the storage-type level but serve complementary roles in the gap series. The `set()` calls in the write phase may contribute incidental `read_bytes` from internal ledger existence checks, so the measured figure includes a small write-phase read component in addition to the explicit read phase.

```bash
cargo build --target wasm32-unknown-unknown --release -p amm-pool-contract
cargo test -p amm-pool-contract test_storage_read_wasm_local -- --nocapture
```

The network figure is collected via `cargo budget-report` on Soroban testnet against the same WASM. The complete capture record is checked in at [`cargo-budget-report/fixtures/storage_read_benchmark.json`](https://github.com/Tollcraft/soroban-budget-assert/tree/main/cargo-budget-report/fixtures/storage_read_benchmark.json). Its delta is calculated as `(local − network) / network`.

## SDK version calibration

The existing measurement series (above) shows the local-vs-network gap can flip direction with build profile alone. The SDK/protocol version is a second axis that shifts these numbers. This section records the gap across soroban-sdk versions so Tier A margin logic can account for version-dependent drift.

### Methodology

Each measurement uses the same contract (`amm-pool-contract`), the same function (`do_expensive_work(10_000)`), and the same build profile (workspace `[profile.release]`: `opt-level="z"`, LTO, `codegen-units=1`). Only the soroban-sdk version changes. The local WASM estimate is collected by the `calibrate_gap` test in `amm-pool-contract/tests/calibrate_gap.rs`:

```
cargo build --target wasm32-unknown-unknown --release -p amm-pool-contract
cargo test -p amm-pool-contract calibrate_gap -- --nocapture
```

SDK 20 and 21 use `env.budget()` instead of `env.cost_estimate().budget()`. For those versions, run with `--features sdk20` and use the `calibrate_gap_sdk20` test binary:

```
cargo build --target wasm32-unknown-unknown --release -p amm-pool-contract
cargo test -p amm-pool-contract --features sdk20 --test calibrate_gap_sdk20 calibrate_gap -- --nocapture
```

The network figure column requires a separate `cargo-budget-report` run on Soroban testnet against the same WASM, and is a placeholder until the measurement can be taken on a live network.

### Per-version calibration table

| SDK version (pinned)    | SDK version (resolved) | Local CPU estimate | Local mem estimate | Network CPU | Network mem | Delta CPU | Date    | Toolchain      |
| ----------------------- | ---------------------- | ------------------ | ------------------ | ----------- | ----------- | --------- | ------- | -------------- |
| `20.0.0`                | `20.5.0`               | 6,606,666          | 1,942,982          | —           | —           | —         | 2026-Q3 | `rustc 1.85.0` |
| `21.0.0` (≈`21.7.7`)^\* | `21.7.7`               | 2,653,878          | 1,658,163          | —           | —           | —         | 2026-Q3 | `rustc 1.85.0` |
| `22.0.0`                | `22.0.11`              | 2,654,615          | 1,658,706          | —           | —           | —         | 2026-Q3 | `rustc 1.85.0` |

> ^\* SDK 21.0.0 is yanked; the lowest resolvable 21.x patch is 21.7.7.

> **Note on SDK 21 compilation.** soroban-env-host 21.2.1 has a `rand_core` / `ed25519-dalek` version conflict in its `testutils` feature. Running `cargo update -p soroban-env-host` resolves it by flushing the stale dependency graph. This is a one-time workaround needed when first pinning to SDK 21.

> **Note on SDK 20 API.** soroban-sdk 20.x uses `env.budget()` instead of `env.cost_estimate().budget()`. A separate test file (`calibrate_gap_sdk20.rs`) is gated behind the `sdk20` Cargo feature and provides the same measurement.

> **Temporary workspace constraints.** The workspace's `cargo-budget-report` crate requires `stellar-xdr ^22.1.0`, which limits long-term compatible soroban-sdk versions to the 22.0.x line. SDK 20 and 21 are tested by temporarily loosening the `stellar-xdr` constraint and regenerating the lockfile. These constraints are workspace-specific and should be re-evaluated when the project upgrades to a newer SDK baseline.

### How to regenerate

1. Pin the desired soroban-sdk version in `amm-pool-contract/Cargo.toml` (both `[dependencies]` and `[dev-dependencies]`).
2. Run `cargo update -p soroban-sdk` to resolve.
3. Build the WASM: `cargo build --target wasm32-unknown-unknown --release -p amm-pool-contract`.
4. Collect local estimate: `cargo test -p amm-pool-contract calibrate_gap -- --nocapture`.
5. For the network figure, deploy the WASM to testnet and run `cargo run --bin cargo-budget-report -- --network testnet` (see [Network simulation in mechanics.md](/docs/budget-assert/mechanics.md#tier-b-network-simulation-cargo-budget-report)).
6. Compute delta = (local − network) / network and add a row to the table above.

A reusable script at `amm-pool-contract/calibrate_gap.ps1` automates steps 1–4 for a predefined list of SDK versions.

### Cross-version comparison (local only)

| SDK     | CPU       | Mem       | CPU Δ vs SDK 22 | Mem Δ vs SDK 22 |
| ------- | --------- | --------- | --------------- | --------------- |
| 20.5.0  | 6,606,666 | 1,942,982 | +148.9%         | +17.1%          |
| 21.7.7  | 2,653,878 | 1,658,163 | −0.03%          | −0.03%          |
| 22.0.11 | 2,654,615 | 1,658,706 | —               | —               |

SDK 20 is dramatically more expensive (+149% CPU) because its `vm.exec` cost model uses a much higher per-instruction multiplier. SDK 21 and 22 are practically identical at the local-estimate level — the CPU delta is 737 instructions (−0.03%) and the memory delta is 543 bytes (−0.03%), well within measurement noise.

### Conclusion

The local WASM estimate for the size-opt profile at soroban-sdk 22.0.11 is **2,654,615** CPU instructions, up from 901,816 in the earlier measurement (rustc 1.81, SDK 22.0.0-era toolchain). The difference is attributable to changes in the Rust toolchain (1.81 → 1.85) and the SDK's internal host environment crate versions between patches. This confirms that the gap is unstable across both toolchain and SDK axes, reinforcing the architectural decision to derive Tier A margins from a network-simulated baseline rather than from local estimates alone.

**SDK 20 is a special case.** The 149% CPU overhead means assertions written against SDK 22+ local estimates will fail by a wide margin when run against SDK 20-compiled WASM. If the production network runs a pre-21 protocol version, Tier A margins must be widened accordingly or the contract must be compiled with an SDK 21+ toolchain.

**SDK 21 vs 22.** The local estimates are indistinguishable (\~0.03% delta), so the same margin can be used for both. This also means the SDK 22 measurement can serve as a proxy for SDK 21 when deriving network-gap corrections.

**Recommendation:** regenerate this table on every SDK bump. A margin computed against a stale SDK baseline is no better than a guess.

## Authorization (require\_auth) measurement

This section records the local-vs-network cost gap for the `require_auth` host-function call, isolated from all other contract logic. The `require_auth_only` function in `amm-pool-contract` calls `addr.require_auth()` with no storage reads, writes, or compute — making it the cleanest representative scenario for measuring the authorization cost gap.

### Methodology

The local estimate is collected by the `measure_auth_gap` test in `amm-pool-contract/tests/measure_auth_gap.rs`:

```
cargo build --target wasm32v1-none --release -p amm-pool-contract
cargo test -p amm-pool-contract --test measure_auth_gap -- --nocapture
```

The network figure requires a `simulateTransaction` call against Soroban testnet with the same WASM, contract state, and toolchain. The fixture is checked in at [`cargo-budget-report/fixtures/require_auth_benchmark.json`](https://github.com/Tollcraft/soroban-budget-assert/tree/main/cargo-budget-report/fixtures/require_auth_benchmark.json).

### Figures

| Operation type                | Local CPU | Local mem | Network CPU | Network mem | Delta CPU | Fixture                                | Build profile                                      | Toolchain      | Date       |
| ----------------------------- | --------: | --------: | ----------: | ----------: | --------: | -------------------------------------- | -------------------------------------------------- | -------------- | ---------- |
| Authorization (require\_auth) | 2,864,886 | 1,721,879 |           — |           — |         — | `amm-pool-contract::require_auth_only` | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | `rustc 1.85.0` | 2026-07-28 |

The network figure and delta columns are pending — they require a `simulateTransaction` call against Soroban testnet with the same WASM and contract state. The complete capture record is at [`cargo-budget-report/fixtures/require_auth_benchmark.json`](https://github.com/Tollcraft/soroban-budget-assert/tree/main/cargo-budget-report/fixtures/require_auth_benchmark.json).

### Comparison with Tier B estimate

The Tier B estimate for `require_auth_only` is 90,000 CPU instructions (see `tier-a-limits.env`). The local WASM measurement of **2,864,886** is approximately **32x higher** than the Tier B figure. This discrepancy is expected: the Tier B estimate was derived from a previous toolchain/SDK combination and may not reflect the current SDK 22.0.11 + rustc 1.85.0 environment. The local measurement should be treated as the current baseline until a network figure is collected.

### Reproduction

To reproduce this measurement:

1. Ensure the WASM is built: `cargo build --target wasm32v1-none --release -p amm-pool-contract`
2. Run the measurement test: `cargo test -p amm-pool-contract --test measure_auth_gap -- --nocapture`
3. Extract `AUTH_CPU` and `AUTH_MEM` from the test output.
4. For the network figure, deploy the WASM to Soroban testnet and run `simulateTransaction` with the same contract state (see the fixture JSON for the required ledger entries).

## Memory bytes

This section records the local-vs-network cost gap for the memory-bytes metric isolated against a pure allocation fixture. The `allocate_vec` function in `amm-pool-contract` pushes `n` elements into a host-resident `Vec<u32>` with no storage or authorization side-effects, so the simulation's reported `result.cost.memBytes` is dominated by the allocation cost itself. The approach mirrors the storage-write / storage-read / authorization series: a single-purpose fixture, both a local estimate and a network figure, the delta between them.

### Methodology

The local estimate is collected by the `test_measure_memory_bytes_local_for_issue_122` test in `amm-pool-contract/tests/budget_test.rs`, which registers the WASM via `register_contract_wasm`, calls `client.allocate_vec(&10_000)`, and emits the measured `MEM_LOCAL` figure via `eprintln!`:

```
cargo build --target wasm32v1-none --release -p amm-pool-contract
cargo test -p amm-pool-contract --test budget_test test_measure_memory_bytes_local_for_issue_122 -- --nocapture
```

The network figure requires a `simulateTransaction` call against Soroban Protocol 22+ testnet with the same WASM and `--n 10000` arguments. The fixture is checked in at [`cargo-budget-report/fixtures/simulate_transaction_response_valid.json`](https://github.com/Tollcraft/soroban-budget-assert/tree/main/cargo-budget-report/fixtures/simulate_transaction_response_valid.json): the `_metadata` block carries the captured `mem_bytes` figure, `result.cost.memBytes` is the corresponding JSON-RPC payload field, and `protocol_version` documents the schema generation. The fixture's `_metadata.protocol_version` field was bumped from `21` to `22` as part of this measurement; older protocol responses simply omit `Memory Bytes` from the report.

### Figures

|                                       Local CPU |                                                 Local mem | Network CPU | Network mem | Delta CPU | Delta mem | Fixture                                   | Build profile                                        | Toolchain      | Date       |
| ----------------------------------------------: | --------------------------------------------------------: | ----------: | ----------: | --------: | --------: | ----------------------------------------- | ---------------------------------------------------- | -------------- | ---------- |
| (captured from `cargo test ... -- --nocapture`) | `MEM_LOCAL` captured from `cargo test ... -- --nocapture` |           — |           — |         — |         — | `amm-pool-contract::allocate_vec(10_000)` | size-opt (`opt-level=\"z\"`, LTO, `codegen-units=1`) | `rustc 1.85.0` | 2026-07-28 |

The network figure and delta are pending — they require a `simulateTransaction` call against Soroban testnet with the same WASM, contract state, and toolchain. Filling them in is the per-operation-margin work tracked by issue #45: the gap series (#122, #334, #342) is the prerequisite data the margin computation reads.

### Reproduction

To reproduce this measurement:

1. Build the WASM: `cargo build --target wasm32v1-none --release -p amm-pool-contract`.
2. Capture the local figure: `cargo test -p amm-pool-contract --test budget_test test_measure_memory_bytes_local_for_issue_122 -- --nocapture`. Take the `MEM_LOCAL` figure from the eprintln output.
3. Update this table's `Local mem` column with the captured figure.
4. Deploy the WASM to Soroban testnet and run `cargo run --bin cargo-budget-report -- --network testnet`.
5. Read `Memory Bytes` from the per-function row in the resulting report (or from `--json` output), and update the `Network mem` column.
6. Compute delta = `(local − network) / network` and add it to the table. The host-function row uses a separate fixture that performs 1,000 calls to `env.ledger().sequence()`. It does not perform storage operations, so the reported values isolate the repeated host-function-call workload. The local estimate was obtained from the WASM-registered contract's `cost_estimate().budget()`, and the network figure was obtained from the corresponding testnet `simulateTransaction` response. | VM-instruction-only (WASM) | 689,312 | 634,912 | +8.6% | `amm-pool-contract::do_vm_instruction_work(10_000)` | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.81 | 2025-Q2 |

The native Rust row is included solely to illustrate that native estimates are unreliable for budget decisions. Only WASM-mode estimates should be used for assertions.

### Gap stability across input sizes

The following measurements test whether the local-vs-network gap widens or narrows as `n` grows. The `do_expensive_work` compute loop does `n` iterations of `wrapping_add(wrapping_mul)`, while the storage loop is internally capped at `n.min(100)`.

| n       | WASM local estimate | Testnet simulated | Delta (abs) | Delta (%) | Build profile                                      | Toolchain    | Date       |
| ------- | ------------------- | ----------------- | ----------- | --------- | -------------------------------------------------- | ------------ | ---------- |
| 1,000   | 2,655,136           | 1,410,984         | +1,244,152  | +88.2%    | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.85.0 | 2026-07-28 |
| 10,000  | 2,655,136           | 1,410,984         | +1,244,152  | +88.2%    | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.85.0 | 2026-07-28 |
| 50,000  | 2,655,136           | 1,410,984         | +1,244,152  | +88.2%    | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.85.0 | 2026-07-28 |
| 100,000 | 2,655,136           | 1,410,984         | +1,244,152  | +88.2%    | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.85.0 | 2026-07-28 |

**Conclusion.** The gap is **stable** — both local and testnet CPU instruction costs are invariant with respect to `n`. This is because the Soroban budget meters host function calls (Vec allocation, storage writes), not raw WASM arithmetic. The compute loop (`n` iterations of arithmetic) is invisible to both local and network metering. Consequently, a single fixed Tier A margin is defensible for computation-heavy parameters in `do_expensive_work` as long as the number of host function calls stays constant. If a later change introduces a host-call path that scales with input size (e.g., per-element storage writes), the gap should be re-measured because the delta is proportional to host call count, not to `n` directly.

A note on version sensitivity: the absolute figures above differ from the 2025-Q1 baseline (which reported 901,816 local / 756,678 testnet for the same `do_expensive_work(10_000)`). The shift is attributable to SDK version changes (22.0.11 vs earlier) and the larger WASM module that now includes the full AMM pool contract. The key finding — cost invariance with `n` — holds under both versions.

### Gap vs input size (CPU instructions)

\| Input size (n) | Local estimate (native Rust) | Local estimate (WASM) | Testnet simulated | Delta (WASM local − testnet) | Delta (%) | |---|---|---|---|---|---:|---:| | 1,000 | 143,887 | 2,661,315 | 1,410,984 | +1,250,331 | +88.6% | | 10,000 | 143,887 | 2,661,315 | 1,410,984 | +1,250,331 | +88.6% | | 50,000 | 143,887 | 2,661,315 | 1,410,984 | +1,250,331 | +88.6% | | 100,000 | 143,887 | 2,661,315 | 1,410,984 | +1,250,331 | +88.6% |

**Build profile:** size-opt (`opt-level="z"`, LTO, `codegen-units=1`)\
**Toolchain:** rustc 1.85.0\
**Date:** 2026-07-28

The native Rust and WASM local estimates are reported by `Env::cost_estimate().budget().cpu_instruction_cost()` in a test that resets the budget before calling `do_expensive_work(n)`. The testnet figure comes from `simulateTransaction` on Soroban testnet via the same pipeline used by `cargo-budget-report`.

**How the estimates behave.** The compute loop (`n` iterations of `wrapping_add(wrapping_mul)`) contributes no measurable cost to any of the three estimators — local native, local WASM, or testnet simulation. All three return constant values once the storage loop saturates at `n.min(100)` (i.e. for n ≥ 100). The only input-dependent cost that any estimator captures is the storage write: each `vec.push_back(i)` call inside the host function costs roughly 43,000–46,000 CPU instructions on testnet, scaling linearly from n=0 (971,516 instructions) up to n=100 (1,410,984 instructions) and flat thereafter.

**Implication for Tier A margins.** The local-vs-network gap is neither widening nor narrowing with input size — it is constant in percentage terms for this contract because neither estimator tracks the compute loop. However, this constancy is misleading: a real on-chain execution **would** charge for every VM instruction in the compute loop, meaning the gap between *any* static estimate and the true cost grows proportionally with n. Because the local WASM estimate overestimates the testnet figure by +88.6% for all measured sizes, a Tier A margin set above this ceiling (e.g. 2× the local estimate) would pass all tested inputs. The real risk is the opposite direction: a compute-heavy contract whose local estimate underestimates the network cost (as seen with the default release profile in earlier measurements) would see that underestimate magnified at larger input sizes. Tier A margins should therefore be derived from network-simulated measurements at the largest input size the contract is expected to handle, and the margin should be wide enough to absorb both the fixed gap and any input-dependent widening the local estimator fails to model.

### Event emission

| Metric           | Local estimate | Network figure                                            | Delta | Fixture                                     | Build profile                                      | Toolchain  | Date       |
| ---------------- | -------------- | --------------------------------------------------------- | ----- | ------------------------------------------- | -------------------------------------------------- | ---------- | ---------- |
| CPU instructions | 2,945,588      | Pending — needs `cargo budget-report` run against testnet | —     | `amm-pool-contract::do_event_heavy_work(5)` | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.85 | 2026-07-27 |
| Memory bytes     | 1,728,814      | Pending                                                   | —     | `amm-pool-contract::do_event_heavy_work(5)` | size-opt (`opt-level="z"`, LTO, `codegen-units=1`) | rustc 1.85 | 2026-07-27 |

The fixture publishes 5 events with a minimal payload (`("ev",)` topic, single `u32` body) in a loop, with no storage or compute work mixed in. To obtain the network figure, run `cargo budget-report` against testnet with a `budget.toml` entry for `do_event_heavy_work` and capture `simulateTransaction` output.

## Unmeasured operation types

The first three rows measure `do_expensive_work(10_000)`, which combines an arithmetic loop with a vector construction and instance-storage write. The fourth row uses `do_vm_instruction_work(10_000)`, an isolated version of the same wrapping arithmetic loop. It performs no storage access, event publication, or cross-contract invocation, so its measured gap represents the VM-instruction-heavy operation rather than an aggregate operation cost.

For the isolated VM benchmark, the delta is calculated as:

```
(689,312 − 634,912) / 634,912 = +8.6%
```

## Operation-type coverage

| Operation type                  | Issue                                                               | Status                                                                              |
| ------------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| TTL extension                   | TBD                                                                 | In progress — calibration test at `amm-pool-contract/tests/calibrate_extend_ttl.rs` |
| Host-function-call operations   | [#86](https://github.com/Tollcraft/soroban-budget-assert/issues/86) | Open                                                                                |
| Storage-write operations        | [#44](https://github.com/Tollcraft/soroban-budget-assert/issues/44) | Open                                                                                |
| VM-instruction-heavy operations | [#87](https://github.com/Tollcraft/soroban-budget-assert/issues/87) | Open                                                                                |

\| Storage-write operations | [#44](https://github.com/Tollcraft/soroban-budget-assert/issues/44) | Measured in the existing mixed-operation fixtures | | Host-function-call operations | [#86](https://github.com/Tollcraft/soroban-budget-assert/issues/86) | Open | | VM-instruction-heavy operations | [#87](https://github.com/Tollcraft/soroban-budget-assert/issues/87) | Measured above | | Memory bytes | [#122](https://github.com/Tollcraft/soroban-budget-assert/issues/122) | Open |


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://tollcraft.gitbook.io/docs/budget-assert/measurements.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
