fix(swarm): bootstrap tx parsing + verify #293 OE-1 guardrail #807

Merged
PlasticDigits merged 4 commits from cursor/gitlab-issue-verification-7f54 into main 2026-06-05 13:24:32 +00:00
PlasticDigits commented 2026-06-05 13:09:03 +00:00 (Migrated from gitlab.com)

Summary

Verification QA for https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/293 (MR !783 swarm liquidity landed on main).

Findings: Not a Swap UI decimal bug. Global GET /api/v1/route/solve picks different best routes per direction (multi-hop arb vs direct pool) on LocalTerra's lopsided factory topology — matching Brouie's analysis. Direct-pool quotes (pool_only=true) are near-inverse (~96% after fees). Swap UI renders human-scaled amounts correctly (36.12K CORAL, not raw micro-units).

This MR fixes two regressions in scripts/bots/swarm.py that blocked the !783 bootstrap/LP path from confirming on-chain:

  1. Strip gas estimate: prefix before parsing terrad JSON stdout.
  2. Use terrad query tx (not terrad tx query) for inclusion polling.

Also adds make verify-issue-293 guardrail script and doc cross-links.

Merge conflict resolution (2026-06-05): Rebased onto latest main; resolved Makefile .PHONY conflict by keeping both verify-issue-293 (this MR) and new main targets (deploy-local-no-build, build-indexer-release, fetch-qa-ci-artifacts, test-qa-redeploy-decision).

Acceptance checklist

Criterion Command / method Result
Merge conflicts with main git merge origin/main on MR branch PASS (Makefile .PHONY only)
Python liquidity sizing unit tests make test-swarm-liquidity PASS (5 tests)
TS swarm profile weights cd packages/localnet-trading-swarm && npm run test:run PASS (14 tests)
Bootstrap hub deepen (EMBER/CORAL, ONYX/TOPAZ) make swarm-bootstrap-liquidity PASS (after tx poll fixes)
Swarm launch (33 workers incl. 3 LP) make swarm-launch PASS
OE-1 global inverse quotes (1-unit, swarm running) make verify-issue-293 step [3] / indexer route/solve FAIL — EMBER/CORAL fwd≈36K rev≈1.0 (36300× off reciprocal); TOPAZ/ONYX ≈69×; ONYX/CORAL ≈2.2M×
OE-1 direct-pool inverse quotes indexer route/solve?pool_only=true PASS (~96% reciprocal all three pairs)
Swap UI human-scaled display Chrome / Simulated Wallet: 1 EMBER→36.12K CORAL; flip 1 CORAL→1.006 EMBER PASS (decimals OK; rates still asymmetric due to routing)

Follow-ups

  • Product/UX: If OE-1 expects near-inverse global quotes, consider route UX (show hop count / warn when forward vs reverse paths differ) or deepen intermediate pools in deploy-dex-local.sh — hub LP deepen alone does not make global solver pick the same pool both ways.
  • Issue stays open until stakeholders accept routing-asymmetric global quotes or scope changes.

Note

Low Risk
Changes are limited to localnet bot tooling and optional QA verification scripts; no production swap, auth, or indexer routing logic is modified.

Overview
Fixes Python QA swarm regressions that blocked bootstrap/LP txs from confirming on-chain: _json_from_terrad_output strips a leading gas estimate: prefix before JSON parse, and inclusion polling uses docker exec … terrad query tx via a new _terrad_query helper instead of the broken terrad tx query shape.

Adds make verify-issue-293 / scripts/qa/verify-issue-293.sh: runs make test-swarm-liquidity, TypeScript localnet-trading-swarm tests, and (when LocalTerra + indexer are up) bootstrap + swarm launch + indexer GET /api/v1/route/solve checks that OE-1 hub pairs EMBER/CORAL, TOPAZ/ONYX, ONYX/CORAL are near-inverse within ≤5% deviation. Docs in docs/testing.md and skills/AGENTS_LOCALNET_TRADING_SWARM.md cross-link the target.

Reviewed by Cursor Bugbot for commit 784cf4f5f1. Bugbot is set up for automated code reviews on this repo. Configure here.

## Summary Verification QA for https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/293 (MR !783 swarm liquidity landed on `main`). **Findings:** Not a Swap UI decimal bug. Global `GET /api/v1/route/solve` picks **different best routes per direction** (multi-hop arb vs direct pool) on LocalTerra's lopsided factory topology — matching Brouie's analysis. **Direct-pool** quotes (`pool_only=true`) are near-inverse (~96% after fees). Swap UI renders human-scaled amounts correctly (36.12K CORAL, not raw micro-units). **This MR fixes two regressions in `scripts/bots/swarm.py` that blocked the !783 bootstrap/LP path from confirming on-chain:** 1. Strip `gas estimate:` prefix before parsing terrad JSON stdout. 2. Use `terrad query tx` (not `terrad tx query`) for inclusion polling. Also adds `make verify-issue-293` guardrail script and doc cross-links. **Merge conflict resolution (2026-06-05):** Rebased onto latest `main`; resolved `Makefile` `.PHONY` conflict by keeping both `verify-issue-293` (this MR) and new main targets (`deploy-local-no-build`, `build-indexer-release`, `fetch-qa-ci-artifacts`, `test-qa-redeploy-decision`). ## Acceptance checklist | Criterion | Command / method | Result | |-----------|------------------|--------| | Merge conflicts with `main` | `git merge origin/main` on MR branch | **PASS** (Makefile `.PHONY` only) | | Python liquidity sizing unit tests | `make test-swarm-liquidity` | **PASS** (5 tests) | | TS swarm profile weights | `cd packages/localnet-trading-swarm && npm run test:run` | **PASS** (14 tests) | | Bootstrap hub deepen (EMBER/CORAL, ONYX/TOPAZ) | `make swarm-bootstrap-liquidity` | **PASS** (after tx poll fixes) | | Swarm launch (33 workers incl. 3 LP) | `make swarm-launch` | **PASS** | | OE-1 global inverse quotes (1-unit, swarm running) | `make verify-issue-293` step [3] / indexer `route/solve` | **FAIL** — EMBER/CORAL fwd≈36K rev≈1.0 (36300× off reciprocal); TOPAZ/ONYX ≈69×; ONYX/CORAL ≈2.2M× | | OE-1 direct-pool inverse quotes | indexer `route/solve?pool_only=true` | **PASS** (~96% reciprocal all three pairs) | | Swap UI human-scaled display | Chrome `/` Simulated Wallet: 1 EMBER→`36.12K` CORAL; flip 1 CORAL→`1.006` EMBER | **PASS** (decimals OK; rates still asymmetric due to routing) | ## Follow-ups - **Product/UX:** If OE-1 expects near-inverse *global* quotes, consider route UX (show hop count / warn when forward vs reverse paths differ) or deepen intermediate pools in `deploy-dex-local.sh` — hub LP deepen alone does not make global solver pick the same pool both ways. - **Issue stays open** until stakeholders accept routing-asymmetric global quotes or scope changes. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Changes are limited to localnet bot tooling and optional QA verification scripts; no production swap, auth, or indexer routing logic is modified. > > **Overview** > Fixes **Python QA swarm** regressions that blocked bootstrap/LP txs from confirming on-chain: **`_json_from_terrad_output`** strips a leading **`gas estimate:`** prefix before JSON parse, and inclusion polling uses **`docker exec … terrad query tx`** via a new **`_terrad_query`** helper instead of the broken **`terrad tx query`** shape. > > Adds **`make verify-issue-293`** / **`scripts/qa/verify-issue-293.sh`**: runs **`make test-swarm-liquidity`**, TypeScript **`localnet-trading-swarm`** tests, and (when LocalTerra + indexer are up) bootstrap + swarm launch + indexer **`GET /api/v1/route/solve`** checks that OE-1 hub pairs **EMBER/CORAL**, **TOPAZ/ONYX**, **ONYX/CORAL** are near-inverse within **≤5%** deviation. Docs in **`docs/testing.md`** and **`skills/AGENTS_LOCALNET_TRADING_SWARM.md`** cross-link the target. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 784cf4f5f12c3e630138d91a47bb84f082ea8515. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
ghost1 commented 2026-06-05 13:09:12 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-05 13:09:18 +00:00 (Migrated from gitlab.com)

mentioned in issue #293

mentioned in issue #293
ghost1 commented 2026-06-05 13:09:20 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-05 13:09:35 +00:00 (Migrated from gitlab.com)

added 1 commit

  • 319fa5b5 - chore: make verify-issue-293.sh executable

Compare with previous version

added 1 commit <ul><li>319fa5b5 - chore: make verify-issue-293.sh executable</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/89/diffs?diff_id=1836749384&start_sha=14497eb112c0d233247202756d6ef1f11815b182)
ghost1 commented 2026-06-05 13:09:47 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-05 13:10:36 +00:00 (Migrated from gitlab.com)

Security review (automated)

Reviewed commit: 319fa5b52835bb9b188b8c2aa3145809512c8841
Diff scope (vs 856f024): scripts/bots/swarm.py, scripts/qa/verify-issue-293.sh, Makefile, docs/testing.md, skills/AGENTS_LOCALNET_TRADING_SWARM.md

Outcome: FINDINGS: 0 medium+ — no inline threads opened.

Summary

This MR is limited to localnet QA tooling: terrad stdout JSON normalization (_json_from_terrad_output), switching tx inclusion polling to terrad query tx, and a new make verify-issue-293 guardrail. There are no changes to production services, on-chain contracts, indexer HTTP handlers, or frontend auth paths.

Areas checked

Area Result
Command injection (docker exec / terrad) OK — asyncio.create_subprocess_exec with argv lists; container from compose; txhash from parsed terrad JSON (not shell-expanded).
Unsafe JSON / deserialization OK — json.loads on dict-only terrad output; no eval/pickle. Prefix strip before { only affects local bot confirmation.
SSRF / open redirect (verify-issue-293.sh) N/A (local dev) — VERIFY293_INDEXER_URL defaults to 127.0.0.1:3001; script is operator-run QA, not an exposed service.
Secret leakage / logging OK — no new credentials; existing warn logs truncate tx output.
Authn/authz / permission boundaries N/A — no production auth surface touched.

Prior MR discussion threads: none to re-validate.


Cursor security review automation

## Security review (automated) **Reviewed commit:** `319fa5b52835bb9b188b8c2aa3145809512c8841` **Diff scope (vs `856f024`):** `scripts/bots/swarm.py`, `scripts/qa/verify-issue-293.sh`, `Makefile`, `docs/testing.md`, `skills/AGENTS_LOCALNET_TRADING_SWARM.md` **Outcome:** `FINDINGS: 0` medium+ — no inline threads opened. ### Summary This MR is limited to **localnet QA tooling**: terrad stdout JSON normalization (`_json_from_terrad_output`), switching tx inclusion polling to `terrad query tx`, and a new `make verify-issue-293` guardrail. There are no changes to production services, on-chain contracts, indexer HTTP handlers, or frontend auth paths. ### Areas checked | Area | Result | |------|--------| | Command injection (`docker exec` / `terrad`) | **OK** — `asyncio.create_subprocess_exec` with argv lists; `container` from compose; `txhash` from parsed terrad JSON (not shell-expanded). | | Unsafe JSON / deserialization | **OK** — `json.loads` on dict-only terrad output; no `eval`/pickle. Prefix strip before `{` only affects local bot confirmation. | | SSRF / open redirect (`verify-issue-293.sh`) | **N/A (local dev)** — `VERIFY293_INDEXER_URL` defaults to `127.0.0.1:3001`; script is operator-run QA, not an exposed service. | | Secret leakage / logging | **OK** — no new credentials; existing warn logs truncate tx output. | | Authn/authz / permission boundaries | **N/A** — no production auth surface touched. | Prior MR discussion threads: none to re-validate. --- *Cursor security review automation*
PlasticDigits commented 2026-06-05 13:10:56 +00:00 (Migrated from gitlab.com)

Security review

Commit reviewed: 319fa5b52835bb9b188b8c2aa3145809512c8841
Scope: 5 files — scripts/bots/swarm.py (terrad JSON parsing + query tx polling fix), new scripts/qa/verify-issue-293.sh, Makefile target, and doc cross-links in docs/testing.md / skills/AGENTS_LOCALNET_TRADING_SWARM.md.

Outcome: FINDINGS: 0 medium+

Inline threads: none (no medium+ issues on this diff)


Summary

Reviewed added/modified code for injection, auth bypass, secret leakage, SSRF, unsafe deserialization, and supply-chain risk. All changes are confined to localnet QA tooling (Python swarm bot + verification shell script); no production contracts, indexer API, frontend, or auth paths are touched.

Paths traced

Area Attacker-controlled input? Sink Verdict
_terrad_query / _poll_tx_inclusion txhash comes from local terrad broadcast JSON, not external callers; container from docker compose ps -q localterra asyncio.create_subprocess_exec (argv list, no shell) No command injection; local dev trust boundary
_json_from_terrad_output Output of local terrad inside Docker json.loads Parsing helper only; no auth or network exposure
verify-issue-293.sh Optional env vars (VERIFY293_INDEXER_URL, etc.) set by operator/CI curl + urllib.request.urlopen to indexer Local QA script; operator already controls shell env — not an exploitable remote SSRF surface
Docs / Makefile N/A N/A Documentation only

No new dependencies, secrets, or production runtime behavior introduced.

Security review: no medium+ findings on this diff.

## Security review **Commit reviewed:** `319fa5b52835bb9b188b8c2aa3145809512c8841` **Scope:** 5 files — `scripts/bots/swarm.py` (terrad JSON parsing + `query tx` polling fix), new `scripts/qa/verify-issue-293.sh`, `Makefile` target, and doc cross-links in `docs/testing.md` / `skills/AGENTS_LOCALNET_TRADING_SWARM.md`. **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none (no medium+ issues on this diff) --- ### Summary Reviewed added/modified code for injection, auth bypass, secret leakage, SSRF, unsafe deserialization, and supply-chain risk. All changes are confined to **localnet QA tooling** (Python swarm bot + verification shell script); no production contracts, indexer API, frontend, or auth paths are touched. ### Paths traced | Area | Attacker-controlled input? | Sink | Verdict | |------|---------------------------|------|---------| | `_terrad_query` / `_poll_tx_inclusion` | `txhash` comes from local `terrad` broadcast JSON, not external callers; `container` from `docker compose ps -q localterra` | `asyncio.create_subprocess_exec` (argv list, no shell) | No command injection; local dev trust boundary | | `_json_from_terrad_output` | Output of local `terrad` inside Docker | `json.loads` | Parsing helper only; no auth or network exposure | | `verify-issue-293.sh` | Optional env vars (`VERIFY293_INDEXER_URL`, etc.) set by operator/CI | `curl` + `urllib.request.urlopen` to indexer | Local QA script; operator already controls shell env — not an exploitable remote SSRF surface | | Docs / Makefile | N/A | N/A | Documentation only | No new dependencies, secrets, or production runtime behavior introduced. **Security review: no medium+ findings on this diff.**
ghost1 commented 2026-06-05 13:22:59 +00:00 (Migrated from gitlab.com)

added 42 commits

  • 319fa5b5...c0dd1104 - 41 commits from branch main
  • 784cf4f5 - merge: resolve Makefile .PHONY conflict with main (keep verify-issue-293 + main targets)

Compare with previous version

added 42 commits <ul><li>319fa5b5...c0dd1104 - 41 commits from branch <code>main</code></li><li>784cf4f5 - merge: resolve Makefile .PHONY conflict with main (keep verify-issue-293 + main targets)</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/89/diffs?diff_id=1836779078&start_sha=319fa5b52835bb9b188b8c2aa3145809512c8841)
PlasticDigits commented 2026-06-05 13:23:12 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-05 13:23:13 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-05 13:24:09 +00:00 (Migrated from gitlab.com)

Security review (automated)

Reviewed commit: 784cf4f5f12c3e630138d91a47bb84f082ea8515
Diff scope (vs c0dd110, MR !807): scripts/bots/swarm.py, scripts/qa/verify-issue-293.sh, Makefile, docs/testing.md, skills/AGENTS_LOCALNET_TRADING_SWARM.md

Outcome: FINDINGS: 0 medium+ — no inline threads opened.

Summary

Re-reviewed after the merge commit that resolved the Makefile .PHONY conflict with main. Security posture is unchanged from the prior review on 319fa5b: all changes remain confined to localnet QA tooling (Python swarm bot terrad stdout parsing / query tx polling fix, plus optional make verify-issue-293 guardrail). No production contracts, indexer HTTP handlers, frontend auth paths, or new dependencies are touched.

Paths traced

Area Attacker-controlled input? Sink Verdict
_terrad_query / _poll_tx_inclusion txhash from local terrad broadcast JSON; container from docker compose ps -q localterra asyncio.create_subprocess_exec (argv list, no shell) No command injection; local dev trust boundary
_json_from_terrad_output Output of local terrad inside Docker json.loads on dict-only payload after { prefix strip Parsing helper only; no network or auth exposure
verify-issue-293.sh Optional operator env (VERIFY293_INDEXER_URL, etc.) curl + embedded Python urllib.request.urlopen Local QA script; operator controls shell env — not a remote SSRF surface
Docs / Makefile N/A N/A Documentation / build target only

Prior inline threads: none. Prior top-level security reviews on 319fa5b remain valid; no new medium+ issues introduced by 784cf4f.

Security review: no medium+ findings on this diff.


Cursor security review automation

## Security review (automated) **Reviewed commit:** `784cf4f5f12c3e630138d91a47bb84f082ea8515` **Diff scope (vs `c0dd110`, MR !807):** `scripts/bots/swarm.py`, `scripts/qa/verify-issue-293.sh`, `Makefile`, `docs/testing.md`, `skills/AGENTS_LOCALNET_TRADING_SWARM.md` **Outcome:** `FINDINGS: 0` medium+ — no inline threads opened. ### Summary Re-reviewed after the merge commit that resolved the `Makefile` `.PHONY` conflict with `main`. Security posture is unchanged from the prior review on `319fa5b`: all changes remain confined to **localnet QA tooling** (Python swarm bot terrad stdout parsing / `query tx` polling fix, plus optional `make verify-issue-293` guardrail). No production contracts, indexer HTTP handlers, frontend auth paths, or new dependencies are touched. ### Paths traced | Area | Attacker-controlled input? | Sink | Verdict | |------|---------------------------|------|---------| | `_terrad_query` / `_poll_tx_inclusion` | `txhash` from local `terrad` broadcast JSON; `container` from `docker compose ps -q localterra` | `asyncio.create_subprocess_exec` (argv list, no shell) | No command injection; local dev trust boundary | | `_json_from_terrad_output` | Output of local `terrad` inside Docker | `json.loads` on dict-only payload after `{` prefix strip | Parsing helper only; no network or auth exposure | | `verify-issue-293.sh` | Optional operator env (`VERIFY293_INDEXER_URL`, etc.) | `curl` + embedded Python `urllib.request.urlopen` | Local QA script; operator controls shell env — not a remote SSRF surface | | Docs / Makefile | N/A | N/A | Documentation / build target only | Prior inline threads: none. Prior top-level security reviews on `319fa5b` remain valid; no new medium+ issues introduced by `784cf4f`. **Security review: no medium+ findings on this diff.** --- *Cursor security review automation*
PlasticDigits commented 2026-06-05 13:24:32 +00:00 (Migrated from gitlab.com)

mentioned in commit 9d7331cd66

mentioned in commit 9d7331cd6672e66320a7b585bc37c41f41732fab
PlasticDigits (Migrated from gitlab.com) merged commit 9d7331cd66 into main 2026-06-05 13:24:32 +00:00
PlasticDigits commented 2026-06-08 08:43:13 +00:00 (Migrated from gitlab.com)

mentioned in commit 33488c2acd

mentioned in commit 33488c2acdfa6bb8dd329dd5618691cfe4ad471e
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic!807
No description provided.