Fix e2e-seed-expired-parked-claim-all.sh: hybrid park swap missing min_return (#334) #339

Closed
opened 2026-06-08 08:14:16 +00:00 by PlasticDigits · 11 comments
PlasticDigits commented 2026-06-08 08:14:16 +00:00 (Migrated from gitlab.com)

Summary

Terrad harness scripts/e2e-seed-expired-parked-claim-all.sh fails when parking expired limits via pure-book hybrid swap because the swap hook omits belief_price and min_return, violating pair invariant L9 / GitLab #334. This breaks limit-orders-claim-all-tx.spec.ts and blocks #292 strict make test-e2e tx phase.


Current codebase

Seed harness

  • scripts/e2e-seed-expired-parked-claim-all.sh:
    1. Loads frontend-dapp/.env.local (VITE_FACTORY_ADDRESS, LCD).
    2. Picks first dual-CW20 unpaused factory pair.
    3. Places 2 short-lived bids via place_limit_order_batch (dev wallet / terrad_tx).
    4. Waits until block_time >= expires_at.
    5. Executes hybrid swap with pool_input: "0" (book-only leg):
      {"swap":{"max_spread":"1","hybrid":{"pool_input":"0","book_input":"5000","max_maker_fills":8}}}
      
      — no belief_price, no min_return, no trader.
    6. Intended outcome: wasm limit_order_expired_parked ×2 → indexer parked_expired for dev wallet.

Playwright consumer

On-chain rule (GitLab #334)

Similar harness (may need same fix)


Why this is needed

Gap Impact
Execute revert Step 5 of seed script fails on current wasm — no parked rows → claim-all E2E cannot run.
#292 criterion 3 Cloud Agent verification: e2e-tx 33/38 with this harness called out explicitly.
False confidence #259 UI shipped; without working harness, batch claim path is unverified in CI.

Constraints / guardrails

  • Do not relax #334 on-chain — fix the harness hook, not the pair contract.
  • Conservative min_return — use a small floor (e.g. 1 raw unit) only to satisfy execute; parking behavior depends on book walk, not output amount.
  • Alternative: belief_price — acceptable if set from pair pool/book context; prefer min_return for scripted terrd paths (no price oracle in bash).
  • Park cap — respect MAX_EXPIRED_PARKS_PER_SWAP (15); script places only 2 orders.
  • Paused pair (L6) — script already exits if pair paused; preserve.
  • Indexer lag — Playwright helper already polls 180s; seed script should echo pair addr + tx hints on success.
  • Env parity — must work after make deploy-local + e2e-start-indexer.sh + dev-wallet provision (LT11 order).
  • Single worker — e2e-tx project; no parallel claim tests on same wallet.

Relevant files

Area Files
Harness scripts/e2e-seed-expired-parked-claim-all.sh
Terrad helper scripts/lib/e2e-terrad-tx.sh
E2E frontend-dapp/e2e/limit-orders-claim-all-tx.spec.ts, e2e/helpers/limit-expiry-park-e2e.ts
Contract reference smartcontracts/tests/src/limit_order_tests.rs, dex-common/src/max_spread.rs
QA script scripts/qa/verify-issue-309.sh (related)
Docs / skills skills/AGENTS_E2E_LIMIT_ORDERS_TX.md, skills/AGENTS_FRONTEND_LIMIT_PARKED_EXPIRED.md, docs/testing.md, frontend-dapp/e2e/README.md

  1. Update SWAP_HOOK JSON in seed script to include full swap envelope:
    {
      "swap": {
        "belief_price": null,
        "max_spread": "1",
        "min_return": "1",
        "to": null,
        "deadline": null,
        "hybrid": { "pool_input": "0", "book_input": "<amt>", "max_maker_fills": 8, "book_start_hint": null },
        "trader": null
      }
    }
    
  2. Manually run bash scripts/e2e-seed-expired-parked-claim-all.sh — confirm terrd tx succeeds and LCD events include limit_order_expired_parked.
  3. Re-run limit-orders-claim-all-tx.spec.ts end-to-end.
  4. Optionally align verify-issue-309.sh hybrid_swap_book_only in same MR if QA script is broken on main.
  5. Document min_return rationale in e2e/README.md (one line cross-link #334).

Acceptance criteria

  • bash scripts/e2e-seed-expired-parked-claim-all.sh exits 0 on fresh LocalTerra deploy with indexer syncing.
  • Hybrid park tx succeeds (no belief_price / min_return revert).
  • Indexer shows ≥ 2 parked_expired placements for dev wallet on seeded pair within poll window.
  • limit-orders-claim-all-tx.spec.ts passes under --project=e2e-tx.
  • No change to claim-all UI or contract semantics.

Test plan — functional paths

  • Harness only: place 2 bids → wait expiry → hybrid swap → script prints success line with pair + expires_at.
  • LCD: park tx contains wasm limit_order_expired_parked (or batch park events).
  • Indexer GET .../limit-placements?status=parked_expired returns dev-wallet rows.
  • Full E2E: seed → /limits → Claim all parked → confirm (LUNC gas copy) → batch claim tx → rows cleared.
  • Re-run harness twice on same volumes — idempotent or documented if not (may need pair rotation).

Test plan — attack / hack / abuse vectors

  • min_return: 1 must not enable value extraction — floor is minimal; verify taker still pays full book_input escrow; no free mint path.
  • Cannot park without expiry — script waits for block_time; attempting early swap should not create parked_expired (harness should fail loudly, not claim success).
  • Paused pair — script aborts before burning gas on doomed park/claim path (L6).
  • Wrong pair selection — dual-CW20 filter prevents native/wrap-only pairs that lack bid escrow token.
  • Over-park — placing >15 expired orders in one swap is out of scope; document 2-order design stays under cap.

Verification criteria

  • bash scripts/e2e-seed-expired-parked-claim-all.sh — exit 0, stderr clean.
  • bash scripts/with-node.sh --cwd frontend-dapp -- npx playwright test e2e/limit-orders-claim-all-tx.spec.ts --project=e2e-tx — pass.
  • CI=1 make test-e2e tx phase includes claim-all green.
  • Optional: make test-contracts — no regressions (harness-only change).

## Summary Terrad harness [`scripts/e2e-seed-expired-parked-claim-all.sh`](scripts/e2e-seed-expired-parked-claim-all.sh) fails when parking expired limits via **pure-book hybrid swap** because the swap hook omits **`belief_price`** and **`min_return`**, violating pair invariant **L9 / GitLab #334**. This breaks `limit-orders-claim-all-tx.spec.ts` and blocks **#292** strict `make test-e2e` tx phase. --- ## Current codebase ### Seed harness - [`scripts/e2e-seed-expired-parked-claim-all.sh`](scripts/e2e-seed-expired-parked-claim-all.sh): 1. Loads `frontend-dapp/.env.local` (`VITE_FACTORY_ADDRESS`, LCD). 2. Picks first dual-CW20 unpaused factory pair. 3. Places **2** short-lived bids via `place_limit_order_batch` (dev wallet / `terrad_tx`). 4. Waits until `block_time >= expires_at`. 5. Executes hybrid swap with **`pool_input: "0"`** (book-only leg): ```json {"swap":{"max_spread":"1","hybrid":{"pool_input":"0","book_input":"5000","max_maker_fills":8}}} ``` — **no** `belief_price`, **no** `min_return`, **no** `trader`. 6. Intended outcome: wasm `limit_order_expired_parked` ×2 → indexer `parked_expired` for dev wallet. ### Playwright consumer - [`frontend-dapp/e2e/limit-orders-claim-all-tx.spec.ts`](frontend-dapp/e2e/limit-orders-claim-all-tx.spec.ts) — calls [`seedExpiredParkedLimitsForClaimAllE2e()`](frontend-dapp/e2e/helpers/limit-expiry-park-e2e.ts) then drives **Claim all parked** UI ([#259](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/259)). - Helper polls indexer `limit-placements?status=parked_expired` for **≥ 2** rows. ### On-chain rule (GitLab #334) - [`smartcontracts/packages/dex-common/src/max_spread.rs`](smartcontracts/packages/dex-common/src/max_spread.rs) — pure-book hybrid (`pool_input = 0`, `book_input > 0`) on **execute** requires `belief_price` **or** `min_return`. - Contract test: `hybrid_pure_book_requires_slippage_floor_without_belief` in [`limit_order_tests.rs`](smartcontracts/tests/src/limit_order_tests.rs) — passes with `min_return: Some(Uint128::one())`. - Docs: [`docs/integrators.md`](docs/integrators.md) § Slippage; skill [`skills/AGENTS_MAX_SPREAD_HYBRID.md`](skills/AGENTS_MAX_SPREAD_HYBRID.md). ### Similar harness (may need same fix) - [`scripts/qa/verify-issue-309.sh`](scripts/qa/verify-issue-309.sh) — `hybrid_swap_book_only()` also uses `belief_price: null` without `min_return` (audit when fixing seed script). --- ## Why this is needed | Gap | Impact | |-----|--------| | **Execute revert** | Step 5 of seed script fails on current wasm — no parked rows → claim-all E2E cannot run. | | **#292 criterion 3** | Cloud Agent verification: `e2e-tx` **33/38** with this harness called out explicitly. | | **False confidence** | [#259](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/259) UI shipped; without working harness, batch claim path is unverified in CI. | --- ## Constraints / guardrails - **Do not relax #334 on-chain** — fix the harness hook, not the pair contract. - **Conservative `min_return`** — use a small floor (e.g. `1` raw unit) only to satisfy execute; parking behavior depends on book walk, not output amount. - **Alternative: `belief_price`** — acceptable if set from pair pool/book context; prefer `min_return` for scripted terrd paths (no price oracle in bash). - **Park cap** — respect `MAX_EXPIRED_PARKS_PER_SWAP` (15); script places only 2 orders. - **Paused pair (L6)** — script already exits if pair paused; preserve. - **Indexer lag** — Playwright helper already polls 180s; seed script should `echo` pair addr + tx hints on success. - **Env parity** — must work after `make deploy-local` + `e2e-start-indexer.sh` + dev-wallet provision (LT11 order). - **Single worker** — `e2e-tx` project; no parallel claim tests on same wallet. --- ## Relevant files | Area | Files | |------|-------| | Harness | `scripts/e2e-seed-expired-parked-claim-all.sh` | | Terrad helper | `scripts/lib/e2e-terrad-tx.sh` | | E2E | `frontend-dapp/e2e/limit-orders-claim-all-tx.spec.ts`, `e2e/helpers/limit-expiry-park-e2e.ts` | | Contract reference | `smartcontracts/tests/src/limit_order_tests.rs`, `dex-common/src/max_spread.rs` | | QA script | `scripts/qa/verify-issue-309.sh` (related) | | Docs / skills | `skills/AGENTS_E2E_LIMIT_ORDERS_TX.md`, `skills/AGENTS_FRONTEND_LIMIT_PARKED_EXPIRED.md`, `docs/testing.md`, `frontend-dapp/e2e/README.md` | --- ## Recommended solution direction 1. Update `SWAP_HOOK` JSON in seed script to include full swap envelope: ```json { "swap": { "belief_price": null, "max_spread": "1", "min_return": "1", "to": null, "deadline": null, "hybrid": { "pool_input": "0", "book_input": "<amt>", "max_maker_fills": 8, "book_start_hint": null }, "trader": null } } ``` 2. Manually run `bash scripts/e2e-seed-expired-parked-claim-all.sh` — confirm terrd tx succeeds and LCD events include `limit_order_expired_parked`. 3. Re-run `limit-orders-claim-all-tx.spec.ts` end-to-end. 4. Optionally align `verify-issue-309.sh` `hybrid_swap_book_only` in same MR if QA script is broken on main. 5. Document `min_return` rationale in `e2e/README.md` (one line cross-link #334). --- ## Acceptance criteria - [ ] `bash scripts/e2e-seed-expired-parked-claim-all.sh` exits 0 on fresh LocalTerra deploy with indexer syncing. - [ ] Hybrid park tx succeeds (no `belief_price` / `min_return` revert). - [ ] Indexer shows **≥ 2** `parked_expired` placements for dev wallet on seeded pair within poll window. - [ ] `limit-orders-claim-all-tx.spec.ts` passes under `--project=e2e-tx`. - [ ] No change to claim-all UI or contract semantics. --- ## Test plan — functional paths - [ ] Harness only: place 2 bids → wait expiry → hybrid swap → script prints success line with pair + `expires_at`. - [ ] LCD: park tx contains wasm `limit_order_expired_parked` (or batch park events). - [ ] Indexer GET `.../limit-placements?status=parked_expired` returns dev-wallet rows. - [ ] Full E2E: seed → `/limits` → Claim all parked → confirm (LUNC gas copy) → batch claim tx → rows cleared. - [ ] Re-run harness twice on same volumes — idempotent or documented if not (may need pair rotation). --- ## Test plan — attack / hack / abuse vectors - [ ] **`min_return: 1` must not enable value extraction** — floor is minimal; verify taker still pays full `book_input` escrow; no free mint path. - [ ] **Cannot park without expiry** — script waits for `block_time`; attempting early swap should not create `parked_expired` (harness should fail loudly, not claim success). - [ ] **Paused pair** — script aborts before burning gas on doomed park/claim path (L6). - [ ] **Wrong pair selection** — dual-CW20 filter prevents native/wrap-only pairs that lack bid escrow token. - [ ] **Over-park** — placing >15 expired orders in one swap is out of scope; document 2-order design stays under cap. --- ## Verification criteria - [ ] `bash scripts/e2e-seed-expired-parked-claim-all.sh` — exit 0, stderr clean. - [ ] `bash scripts/with-node.sh --cwd frontend-dapp -- npx playwright test e2e/limit-orders-claim-all-tx.spec.ts --project=e2e-tx` — pass. - [ ] `CI=1 make test-e2e` tx phase includes claim-all green. - [ ] Optional: `make test-contracts` — no regressions (harness-only change). --- ## Related - Parent umbrella: [GitLab #292](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/292) - Claim-all feature: [GitLab #259](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/259) (closed — harness gap remains) - Slippage floor: [GitLab #334](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/334) - Park lifecycle: [#120](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/120), [#142](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/142)
PlasticDigits commented 2026-06-08 08:14:37 +00:00 (Migrated from gitlab.com)

mentioned in issue #292

mentioned in issue #292
ghost1 commented 2026-06-08 13:30:53 +00:00 (Migrated from gitlab.com)

mentioned in commit 81b1b85c16807e7b5e68e36b517cbf6502746ecf

mentioned in commit 81b1b85c16807e7b5e68e36b517cbf6502746ecf
PlasticDigits commented 2026-06-08 13:42:33 +00:00 (Migrated from gitlab.com)

mentioned in commit a0cccd0456

mentioned in commit a0cccd0456ff5dd9788fa378982b06a3f9ac2dde
PlasticDigits commented 2026-06-08 13:54:29 +00:00 (Migrated from gitlab.com)

Verification complete — #339

All acceptance criteria PASS after harness fix. MR: !841

Pre-fix (baseline)

bash scripts/e2e-seed-expired-parked-claim-all.sh failed at hybrid park step:

Hybrid swap with book_input 5000 requires belief_price or min_return without belief_price

Post-fix verification

Item Result Command / evidence
Seed harness exits 0 PASS bash scripts/e2e-seed-expired-parked-claim-all.sh → seeded pair=terra146y… owner=terra1x46… expires_at=…
Hybrid park tx (no #334 revert) PASS Terrad execute succeeds
Indexer ≥ 2 parked_expired PASS GET /api/v1/pairs/{pair}/limit-placements?status=parked_expired
limit-orders-claim-all-tx.spec.ts PASS npx playwright test … --project=e2e-tx — 1 passed (60s)
No UI/contract change PASS Harness + QA script + docs only
verify-issue-309.sh book-only helper PASS Aligned with min_return: "1"

Changes in MR

  • scripts/e2e-seed-expired-parked-claim-all.sh — min_return: "1" on pure-book park swap
  • scripts/qa/verify-issue-309.sh — same floor
  • frontend-dapp/e2e/README.md, skills/AGENTS_E2E_LIMIT_ORDERS_TX.md — #334 cross-links

Issue left open pending MR merge.

## Verification complete — [#339](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/339) All acceptance criteria **PASS** after harness fix. MR: [!841](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/123) ### Pre-fix (baseline) `bash scripts/e2e-seed-expired-parked-claim-all.sh` failed at hybrid park step: ``` Hybrid swap with book_input 5000 requires belief_price or min_return without belief_price ``` ### Post-fix verification | Item | Result | Command / evidence | |------|--------|-------------------| | Seed harness exits 0 | **PASS** | `bash scripts/e2e-seed-expired-parked-claim-all.sh` → `seeded pair=terra146y… owner=terra1x46… expires_at=…` | | Hybrid park tx (no #334 revert) | **PASS** | Terrad execute succeeds | | Indexer ≥ 2 `parked_expired` | **PASS** | `GET /api/v1/pairs/{pair}/limit-placements?status=parked_expired` | | `limit-orders-claim-all-tx.spec.ts` | **PASS** | `npx playwright test … --project=e2e-tx` — 1 passed (60s) | | No UI/contract change | **PASS** | Harness + QA script + docs only | | `verify-issue-309.sh` book-only helper | **PASS** | Aligned with `min_return: "1"` | ### Changes in MR - `scripts/e2e-seed-expired-parked-claim-all.sh` — `min_return: "1"` on pure-book park swap - `scripts/qa/verify-issue-309.sh` — same floor - `frontend-dapp/e2e/README.md`, `skills/AGENTS_E2E_LIMIT_ORDERS_TX.md` — #334 cross-links Issue left open pending MR merge.
PlasticDigits commented 2026-06-08 13:54:48 +00:00 (Migrated from gitlab.com)

mentioned in merge request !841

mentioned in merge request !841
PlasticDigits commented 2026-06-09 02:04:42 +00:00 (Migrated from gitlab.com)

mentioned in commit d07ba09bed

mentioned in commit d07ba09bed9bc2155c317726d81c01d0d31256b4
Brouie commented 2026-06-09 02:14:35 +00:00 (Migrated from gitlab.com)

mentioned in merge request !842

mentioned in merge request !842
Brouie commented 2026-06-09 02:17:28 +00:00 (Migrated from gitlab.com)

Took this — same min_return floor I added to verify-issue-285.sh, so I knew the shape.

scripts/e2e-seed-expired-parked-claim-all.sh: the pure-book park swap (pool_input:"0", book_input>0) now sets min_return:"1" on the Cw20HookMsg::Swap, clearing the L9/#334 guard on execute. Kept max_spread:"1", left belief_price null — min_return is the right floor for a scripted terrad path with no oracle, exactly the guardrail you spelled out.

Also patched scripts/qa/verify-issue-309.sh — same belief_price:null / no-min_return shape, gave it the same floor (not re-run in full; identical contract path).

Verified live, not just the edit:

  • Ran the seed end to end. The park swap that used to revert executes clean, and both expired bids land at lifecycle_status=parked_expired in one tx — so the claim-all helper gets its >=2-row precondition back and the #292 e2e-tx phase isn't blocked.
  • Then drove the dapp's "Claim all parked (2)" against fresh parked orders: one claim_expired_limit_orders batch, batch_count=2, single combined CW20 refund, both flip to refunded. Single-claim path also clean (one tx + one transfer each).

#334 untouched on-chain — harness-only, both scripts. MR !842 (fork→main). Needs your merge — @PlasticDigits.

Took this — same min_return floor I added to verify-issue-285.sh, so I knew the shape. scripts/e2e-seed-expired-parked-claim-all.sh: the pure-book park swap (pool_input:"0", book_input>0) now sets min_return:"1" on the Cw20HookMsg::Swap, clearing the L9/#334 guard on execute. Kept max_spread:"1", left belief_price null — min_return is the right floor for a scripted terrad path with no oracle, exactly the guardrail you spelled out. Also patched scripts/qa/verify-issue-309.sh — same belief_price:null / no-min_return shape, gave it the same floor (not re-run in full; identical contract path). Verified live, not just the edit: - Ran the seed end to end. The park swap that used to revert executes clean, and both expired bids land at lifecycle_status=parked_expired in one tx — so the claim-all helper gets its >=2-row precondition back and the #292 e2e-tx phase isn't blocked. - Then drove the dapp's "Claim all parked (2)" against fresh parked orders: one claim_expired_limit_orders batch, batch_count=2, single combined CW20 refund, both flip to refunded. Single-claim path also clean (one tx + one transfer each). #334 untouched on-chain — harness-only, both scripts. MR !842 (fork→main). Needs your merge — @PlasticDigits.
Brouie commented 2026-06-09 02:17:30 +00:00 (Migrated from gitlab.com)

mentioned in issue #337

mentioned in issue #337
Brouie commented 2026-06-09 02:27:17 +00:00 (Migrated from gitlab.com)

Update — !841 (a0cccd0) already merged the same min_return floor while I was on this, so my !842 was a duplicate. Closed it and dropped the branch.

The merged fix matches what I shipped (min_return:"1" on the pure-book swap hook, both the seed and verify-309), so my live run stands as verification of the merged version: the seed parks both expired bids in one tx (lifecycle_status=parked_expired), and I drove the dapp's "Claim all parked (2)" against fresh parked orders — one claim_expired_limit_orders batch, single combined refund, both flip to refunded. Merged harness fix is good end to end.

Update — !841 (a0cccd0) already merged the same min_return floor while I was on this, so my !842 was a duplicate. Closed it and dropped the branch. The merged fix matches what I shipped (min_return:"1" on the pure-book swap hook, both the seed and verify-309), so my live run stands as verification of the merged version: the seed parks both expired bids in one tx (lifecycle_status=parked_expired), and I drove the dapp's "Claim all parked (2)" against fresh parked orders — one claim_expired_limit_orders batch, single combined refund, both flip to refunded. Merged harness fix is good end to end.
PlasticDigits commented 2026-06-09 08:17:11 +00:00 (Migrated from gitlab.com)

Verification complete — #339

All acceptance and verification criteria PASS on main (83dc192).

Results

Criterion Result Evidence
Seed harness exit 0 PASS bash scripts/e2e-seed-expired-parked-claim-all.sh — hybrid park tx succeeds
No L9/#334 revert PASS min_return:"1" on pure-book swap hook
limit-orders-claim-all-tx.spec.ts PASS npx playwright test … --project=e2e-tx — 1/1 (68s)
verify-issue-309.sh aligned PASS Same min_return:"1" floor present

Merged fix: !841.

Re-verify checklist

  • bash scripts/e2e-seed-expired-parked-claim-all.sh — exit 0
  • npx playwright test e2e/limit-orders-claim-all-tx.spec.ts --project=e2e-tx — pass
## Verification complete — #339 All acceptance and verification criteria **PASS** on `main` (`83dc192`). ### Results | Criterion | Result | Evidence | |-----------|--------|----------| | Seed harness exit 0 | **PASS** | `bash scripts/e2e-seed-expired-parked-claim-all.sh` — hybrid park tx succeeds | | No L9/#334 revert | **PASS** | `min_return:"1"` on pure-book swap hook | | `limit-orders-claim-all-tx.spec.ts` | **PASS** | `npx playwright test … --project=e2e-tx` — 1/1 (68s) | | `verify-issue-309.sh` aligned | **PASS** | Same `min_return:"1"` floor present | Merged fix: !841. ### Re-verify checklist - [ ] `bash scripts/e2e-seed-expired-parked-claim-all.sh` — exit 0 - [ ] `npx playwright test e2e/limit-orders-claim-all-tx.spec.ts --project=e2e-tx` — pass
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-09 08:17:13 +00:00
Sign in to join this conversation.
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#339
No description provided.