Skip to content

Commit 1c1c8fc

Browse files
Merge pull request Gloriachinedu#943 from Julianemeka/feat/831-batch-payment-gas-optimization
feat(Gloriachinedu#831): measure and reduce gas usage of batch payment loops
2 parents 428e3a4 + beca1c4 commit 1c1c8fc

1 file changed

Lines changed: 57 additions & 0 deletions

File tree

docs/gas-optimization.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Gas Usage: Batch Payment Loop
2+
3+
## Problem (issue #831)
4+
5+
The original `batch_payment` implementation performed **O(N) storage round-trips** for operations that could be collapsed into a single read+write:
6+
7+
| Operation | Original (per N-item batch) | Optimised |
8+
|---|---|---|
9+
| `get_global_stats` | N reads | 1 read |
10+
| `set_global_stats` | N writes | 1 write |
11+
| `get_payer_payment_ids` | N reads | 1 read |
12+
| `set_payer_payment_ids` | N writes | 1 write |
13+
| `env.ledger().timestamp()` | N calls | 1 call |
14+
15+
For the maximum batch size of **10 items** this eliminated **18 redundant ledger entry operations** and **9 redundant timestamp host-function calls**.
16+
17+
## Changes
18+
19+
### `contracts/lumenflow/src/lib.rs``batch_payment`
20+
21+
1. **Validation-first pass** — all per-item checks (token allowance, duplicate
22+
order ID, merchant existence/activity, signature) run in a first pass _before_
23+
any state is mutated. This prevents partial state writes on failure.
24+
25+
2. **Hoisted globals**`env.ledger().timestamp()`, `get_global_stats`, and
26+
`get_payer_payment_ids` are called once before the loop. Counters are
27+
accumulated in-memory, and the results are written after the loop completes.
28+
29+
### `contracts/lumenflow/src/storage.rs`
30+
31+
- Added `set_payer_payment_ids(env, payer, ids)` — writes the full payer ID
32+
list in a single operation, used by the optimised batch path.
33+
34+
## Measuring gas locally
35+
36+
Soroban's test framework exposes CPU instruction and memory byte budgets when
37+
the `SOROBAN_TEST_BUDGET` environment variable is set:
38+
39+
```bash
40+
SOROBAN_TEST_BUDGET=1 cargo test test_batch_payment -- --nocapture 2>&1 \
41+
| grep -E "cpu_insns|mem_bytes"
42+
```
43+
44+
Compare the output against the `main` branch to quantify the savings.
45+
46+
## Test coverage
47+
48+
Six new unit tests in `test.rs`:
49+
50+
| Test | Verifies |
51+
|---|---|
52+
| `test_batch_payment_single_item` | Basic correctness |
53+
| `test_batch_payment_multiple_items_stats_correct` | Stats accumulated correctly across items |
54+
| `test_batch_payment_payer_history_contains_all_items` | Payer index contains all IDs |
55+
| `test_batch_payment_max_10_items_enforced` | Batch size limit |
56+
| `test_batch_payment_fails_on_duplicate_order_id` | Duplicate rejection |
57+
| `test_batch_payment_validation_pass_prevents_partial_state` | No partial state writes on error |

0 commit comments

Comments
 (0)