Pure-book hybrid: require belief_price or minimum_receive — directions 2 & 3 (GitLab #273 follow-up) #334

Closed
opened 2026-06-05 13:44:35 +00:00 by PlasticDigits · 37 comments
PlasticDigits commented 2026-06-05 13:44:35 +00:00 (Migrated from gitlab.com)

Parent

Follow-up to GitLab #273 (hybrid no-belief slippage — open, direction 1 merged) and #307 (material pool leg — closed). Issue discussion (Brouie 2026-06-04) deferred directions 2 & 3 as frontend-coordinated work. User note: pure-book hybrid (declared_pool_input = 0) still unguarded on no-belief path.

Current codebase

Shipped (#273 + #307)

  • Book shortfall metric: dex_common::max_spread no-belief branch folds book_shortfall vs pool net rate when both pool_input > 0 and book_input > 0.
  • Material pool leg (#307): validate_declared_hybrid_pool_leg_for_no_belief requires declared_pool_input ≥ 10% of offer and pool_net > 0 when book leg present without belief_price.
  • Pure-book carve-out: When declared_pool_input == 0, #307 guard skipped; max_spread comment: metric cannot bound book — requires belief_price or minimum_receive (docs/integrators.md, docs/contracts-security-audit.md L9).

Gaps (directions 2 & 3 — not shipped)

Direction Description Status
2 Pair-level min_return on Swap hook — hard floor independent of belief_price Not implemented; inert until frontend adopts
3 Require belief_price or minimum_receive when book_input > 0 (includes pure-book) Breaking until dapp + router send floors

Router / frontend today

  • Router builds per-hop swaps with belief_price: None (smartcontracts/contracts/router/src/contract.rs).
  • Final-hop minimum_receive is optional on ExecuteSwapOperations.
  • Dapp Swap/Trade may omit belief_price on hybrid book legs — pure-book swaps can execute with only max_spread (unbounded for book leg).

Why this is needed

  • Pure-book hybrid (pool_input = 0, full size to book) has no no-belief slippage floor — toxic book fills pass if user omits belief_price and minimum_receive.
  • Direction 1 + #307 close the split-manipulation footgun but explicitly leave pure-book to user-supplied guards.
  • "Default settings" hybrid book trading should not be safe only when callers remember optional params — contract should enforce floor or frontend must always send one (coordinated rollout per #273 comment).

Constraints / guardrails

  • Coordinated release: Direction 3 is breaking for router + dapp until all submit paths send belief_price or minimum_receive on book hops.
  • Pool-only unchanged: book_input == 0 paths unaffected.
  • belief_price path: Existing behavior preserved when set.
  • Router: Must set per-hop floor or belief_price before contract enforces direction 3.
  • Frontend: swapMaxSpread.ts preflight must align with new revert reasons.
  • Integrators: Document migration — pure-book without floor will revert after upgrade.
  • Direction 2 (min_return on pair Swap) can ship as schema addition but remains optional until frontend passes it.

Relevant files

Area Path
Max spread smartcontracts/packages/dex-common/src/max_spread.rs
Pair execute smartcontracts/contracts/pair/src/contract.rs — execute_swap, hybrid validation
Pair msgs smartcontracts/packages/dex-common/src/pair.rs — Swap, Cw20HookMsg
Router smartcontracts/contracts/router/src/contract.rs — hop build, minimum_receive
Tests smartcontracts/tests/src/limit_order_tests.rs, max_spread.rs, lib.rs router tests
Frontend preflight frontend-dapp/src/utils/swapMaxSpread.ts, swapMaxSpread.test.ts
Submit paths SwapPage.tsx, TradeMarketOrderPanel.tsx, transactions.ts
Docs docs/integrators.md, docs/contracts-security-audit.md (L9), docs/swap-max-spread-ux.md

Phase 1 — Frontend + router floors (unblock direction 3)

  1. Dapp: compute and send belief_price or ensure router minimum_receive on every hybrid submit with book_input > 0 (including pure-book UI path).
  2. Router: set minimum_receive on final hop from slippage tolerance; consider per-hop min for multihop book legs.
  3. Indexer quotes: surface expected min receive for display.

Phase 2 — Contract enforcement (direction 3)

  1. In pair execute_swap (no belief_price): when hybrid.book_input > 0, require belief_price.is_some() OR caller proves router-level minimum_receive covers book leg (router-only path) — or simpler: require belief_price on pair hook when book_input > 0 and no router min.
  2. Pure-book (pool_input = 0): same requirement — no carve-out.

Phase 3 — Direction 2 (optional, same release)

  1. Add optional min_return to pair Swap / CW20 hook msg.
  2. Enforce on execute when set; frontend sets from slippage calc.

Tests

  • Pure-book hybrid without belief/min → revert with clear error.
  • Pure-book with belief_price → pass.
  • Router multihop with minimum_receive → pass.
  • Pool-only / zero-book → unchanged.

Acceptance criteria

  • Pure-book hybrid without belief_price or minimum_receive reverts on-chain.
  • Dapp + router updated in same release as contract enforcement.
  • make test-contracts + frontend preflight tests green.
  • docs/integrators.md and L9 audit row updated.
  • #273 can close after directions 2/3 land (or document explicit wont-fix with mandatory frontend-only guards).

Test plan — all paths

Path Expected
Pool-only, no belief Unchanged
Hybrid book=0 Unchanged
Hybrid material pool + book, no belief #307 + shortfall metric
Pure-book, no belief, no min Reject (new)
Pure-book + belief_price Pass
Pure-book + router minimum_receive Pass
Router multihop book hop Per-hop floor enforced
belief_price path Unchanged

Test plan — attack / abuse / hack vectors

Vector Expected
Pure-book toxic fill, no belief Revert — no silent bad fill
Omit minimum_receive on router Revert on book hop
Dust pool bypass (#307) Still rejected — orthogonal
belief_price set too loose User responsibility — still bounded by belief check

Verification criteria

  • cargo test -p cl8y-dex-tests hybrid pure-book reject + accept cases pass.
  • make test-frontend swap submit tests pass with new params.
  • LocalTerra pure-book swap from dapp succeeds with slippage floor attached.
  • Integrator doc migration note published.
## Parent Follow-up to GitLab **#273** (hybrid no-belief slippage — **open**, direction 1 merged) and **#307** (material pool leg — **closed**). Issue discussion (Brouie 2026-06-04) deferred **directions 2 & 3** as frontend-coordinated work. User note: pure-book hybrid (`declared_pool_input = 0`) still unguarded on no-belief path. ## Current codebase ### Shipped (#273 + #307) - **Book shortfall metric:** `dex_common::max_spread` no-belief branch folds `book_shortfall` vs pool **net** rate when both `pool_input > 0` and `book_input > 0`. - **Material pool leg (#307):** `validate_declared_hybrid_pool_leg_for_no_belief` requires `declared_pool_input ≥ 10%` of offer and `pool_net > 0` when book leg present without `belief_price`. - **Pure-book carve-out:** When `declared_pool_input == 0`, #307 guard skipped; max_spread comment: metric cannot bound book — **requires `belief_price` or `minimum_receive`** (`docs/integrators.md`, `docs/contracts-security-audit.md` L9). ### Gaps (directions 2 & 3 — not shipped) | Direction | Description | Status | |-----------|-------------|--------| | **2** | Pair-level `min_return` on Swap hook — hard floor independent of `belief_price` | Not implemented; inert until frontend adopts | | **3** | Require `belief_price` or `minimum_receive` when `book_input > 0` (includes pure-book) | **Breaking** until dapp + router send floors | ### Router / frontend today - Router builds per-hop swaps with `belief_price: None` (`smartcontracts/contracts/router/src/contract.rs`). - Final-hop `minimum_receive` is optional on `ExecuteSwapOperations`. - Dapp Swap/Trade may omit `belief_price` on hybrid book legs — pure-book swaps can execute with only `max_spread` (unbounded for book leg). ## Why this is needed - **Pure-book hybrid** (`pool_input = 0`, full size to book) has **no** no-belief slippage floor — toxic book fills pass if user omits `belief_price` and `minimum_receive`. - Direction 1 + #307 close the split-manipulation footgun but explicitly leave pure-book to user-supplied guards. - "Default settings" hybrid book trading should not be safe only when callers remember optional params — contract should enforce floor **or** frontend must always send one (coordinated rollout per #273 comment). ## Constraints / guardrails - **Coordinated release:** Direction 3 is breaking for router + dapp until all submit paths send `belief_price` or `minimum_receive` on book hops. - **Pool-only unchanged:** `book_input == 0` paths unaffected. - **belief_price path:** Existing behavior preserved when set. - **Router:** Must set per-hop floor or `belief_price` before contract enforces direction 3. - **Frontend:** `swapMaxSpread.ts` preflight must align with new revert reasons. - **Integrators:** Document migration — pure-book without floor will revert after upgrade. - Direction 2 (`min_return` on pair Swap) can ship as schema addition but remains optional until frontend passes it. ## Relevant files | Area | Path | |------|------| | Max spread | `smartcontracts/packages/dex-common/src/max_spread.rs` | | Pair execute | `smartcontracts/contracts/pair/src/contract.rs` — `execute_swap`, hybrid validation | | Pair msgs | `smartcontracts/packages/dex-common/src/pair.rs` — `Swap`, `Cw20HookMsg` | | Router | `smartcontracts/contracts/router/src/contract.rs` — hop build, `minimum_receive` | | Tests | `smartcontracts/tests/src/limit_order_tests.rs`, `max_spread.rs`, `lib.rs` router tests | | Frontend preflight | `frontend-dapp/src/utils/swapMaxSpread.ts`, `swapMaxSpread.test.ts` | | Submit paths | `SwapPage.tsx`, `TradeMarketOrderPanel.tsx`, `transactions.ts` | | Docs | `docs/integrators.md`, `docs/contracts-security-audit.md` (L9), `docs/swap-max-spread-ux.md` | ## Recommended direction ### Phase 1 — Frontend + router floors (unblock direction 3) 1. Dapp: compute and send `belief_price` or ensure router `minimum_receive` on every hybrid submit with `book_input > 0` (including pure-book UI path). 2. Router: set `minimum_receive` on final hop from slippage tolerance; consider per-hop min for multihop book legs. 3. Indexer quotes: surface expected min receive for display. ### Phase 2 — Contract enforcement (direction 3) 1. In pair `execute_swap` (no `belief_price`): when `hybrid.book_input > 0`, require `belief_price.is_some()` **OR** caller proves router-level `minimum_receive` covers book leg (router-only path) — **or** simpler: require `belief_price` on pair hook when `book_input > 0` and no router min. 2. Pure-book (`pool_input = 0`): same requirement — no carve-out. ### Phase 3 — Direction 2 (optional, same release) 1. Add optional `min_return` to pair `Swap` / CW20 hook msg. 2. Enforce on execute when set; frontend sets from slippage calc. ### Tests - Pure-book hybrid without belief/min → revert with clear error. - Pure-book with `belief_price` → pass. - Router multihop with `minimum_receive` → pass. - Pool-only / zero-book → unchanged. ## Acceptance criteria - [ ] Pure-book hybrid without `belief_price` or `minimum_receive` reverts on-chain. - [ ] Dapp + router updated in **same release** as contract enforcement. - [ ] `make test-contracts` + frontend preflight tests green. - [ ] `docs/integrators.md` and L9 audit row updated. - [ ] #273 can close after directions 2/3 land (or document explicit wont-fix with mandatory frontend-only guards). ## Test plan — all paths | Path | Expected | |------|----------| | Pool-only, no belief | Unchanged | | Hybrid book=0 | Unchanged | | Hybrid material pool + book, no belief | #307 + shortfall metric | | Pure-book, no belief, no min | **Reject** (new) | | Pure-book + belief_price | Pass | | Pure-book + router minimum_receive | Pass | | Router multihop book hop | Per-hop floor enforced | | belief_price path | Unchanged | ## Test plan — attack / abuse / hack vectors | Vector | Expected | |--------|----------| | Pure-book toxic fill, no belief | Revert — no silent bad fill | | Omit minimum_receive on router | Revert on book hop | | Dust pool bypass (#307) | Still rejected — orthogonal | | belief_price set too loose | User responsibility — still bounded by belief check | ## Verification criteria - [ ] `cargo test -p cl8y-dex-tests` hybrid pure-book reject + accept cases pass. - [ ] `make test-frontend` swap submit tests pass with new params. - [ ] LocalTerra pure-book swap from dapp succeeds with slippage floor attached. - [ ] Integrator doc migration note published.
PlasticDigits commented 2026-06-05 13:44:36 +00:00 (Migrated from gitlab.com)

marked as related to #273

marked as related to #273
ghost1 commented 2026-06-05 14:08:42 +00:00 (Migrated from gitlab.com)

mentioned in commit ce83a11750

mentioned in commit ce83a11750602ecae8ba1789e5dac77fcb55a64b
PlasticDigits commented 2026-06-05 14:09:13 +00:00 (Migrated from gitlab.com)

mentioned in merge request !819

mentioned in merge request !819
PlasticDigits commented 2026-06-05 14:09:15 +00:00 (Migrated from gitlab.com)

Implementation opened as !819 (branch cursor/gitlab-issue-workflow-dd14).

Verification run locally: make test-contracts (375 tests), make test-frontend (852 tests), new hybrid_pure_book_requires_slippage_floor_without_belief.

Removed agent:implement / agent:verify labels.

Implementation opened as [!819](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/101) (branch `cursor/gitlab-issue-workflow-dd14`). **Verification run locally:** `make test-contracts` (375 tests), `make test-frontend` (852 tests), new `hybrid_pure_book_requires_slippage_floor_without_belief`. Removed `agent:implement` / `agent:verify` labels.
ghost1 commented 2026-06-05 14:12:33 +00:00 (Migrated from gitlab.com)

mentioned in commit 1fbca4fba6

mentioned in commit 1fbca4fba664d39667dec3b5414f6878809a966e
ghost1 commented 2026-06-05 14:20:01 +00:00 (Migrated from gitlab.com)

mentioned in commit 2f6fd97095

mentioned in commit 2f6fd97095385acd5bd1bae54daefab3678f56be
PlasticDigits commented 2026-06-05 14:27:53 +00:00 (Migrated from gitlab.com)

mentioned in commit 6e2ebbe1d0

mentioned in commit 6e2ebbe1d05d0bb30969ebada1b1275e8fc77b29
Brouie commented 2026-06-06 01:56:51 +00:00 (Migrated from gitlab.com)

#334 verified at the contract + router + docs layers on current main (merged via !819, commits ce83a11 / 1fbca4f / 2f6fd97). The frontend half — make test-frontend + the dapp-driven live swap — is the browser layer; I did not run that here (flagged at the bottom). The headline, pure-book reverting without a floor, I proved on-chain.

On-chain revert proof (the security criterion):

  • Pure-book hybrid on the live EMBER/CORAL pair (CW20 send EMBER, hybrid pool_input=0 book_input=10000000, belief_price=null, min_return=null) -> REVERTS:
    "failed to execute message; message index: 0: Hybrid swap with book_input 10000000 requires belief_price or min_return without belief_price"
  • Same swap with min_return=19000000 -> code 0, fills the book (actions send,swap,transfer x3). So the floor is enforced and a floored pure-book swap still executes.

Acceptance criteria:

  • Pure-book without belief/min reverts on-chain: PROVEN live (above) + non-vacuous unit test hybrid_pure_book_requires_slippage_floor_without_belief (negative: pool_input=0 / book_input=5000 / belief=None / min_return=None -> is_err, root cause contains "belief_price"/"min_return"; positive: min_return=Some(1) -> succeeds).
  • Dapp + router same release: router (router/src/contract.rs) extracts per-hop min_return from each SwapOperation and threads it into the per-hop Cw20HookMsg::Swap on the first hop and every intermediate hop, calling validate_hybrid_hop_execute_slippage_floor before each — so router-driven book hops carry the floor. Dapp changes (SwapPage / TradeMarketOrderPanel / swapRoutePreflight / router.ts / pair.ts) shipped in the same MR. Live dapp behavior = laptop.
  • make test-contracts + frontend preflight green: make test-contracts 375/0 (incl the #334 test). Frontend preflight (swapMaxSpread) via make test-frontend = laptop.
  • integrators.md + L9 updated: integrators.md:118 (pure-book needs belief_price or pair min_return; router per-hop min_return when book_input>0), contracts-security-audit.md L9 (#334 + the test ref), swap-max-spread-ux.md (#334 revert + enrichSwapOperationsWithHopMinReturns).
  • #273 closeable after directions 2/3: direction 2 (pair min_return) + direction 3 (require belief/min_return when book_input>0, incl pure-book) are landed and enforced. Your call on closing #273.

Verification criteria:

  • cargo test pure-book reject + accept: the #334 test covers both paths; live accept also shown (CASE 2).
  • make test-frontend swap submit tests: laptop.
  • LocalTerra pure-book swap with floor succeeds: proved the contract-layer equivalent via terrad (CASE 2, min_return floor -> fills). The dapp-driven version is laptop.
  • Integrator doc migration note: integrators.md:118 published.

So contract enforcement + router forwarding + docs are solid and the on-chain revert is proven. What remains is purely the browser layer: make test-frontend (swap submit + swapMaxSpread preflight) and the dapp-driven pure-book swap on LocalTerra — that is my laptop pass, I will run it there. @PlasticDigits — contract side is good; flagging the frontend layer as the remaining laptop check before close.

#334 verified at the contract + router + docs layers on current main (merged via !819, commits ce83a11 / 1fbca4f / 2f6fd97). The frontend half — make test-frontend + the dapp-driven live swap — is the browser layer; I did not run that here (flagged at the bottom). The headline, pure-book reverting without a floor, I proved on-chain. On-chain revert proof (the security criterion): - Pure-book hybrid on the live EMBER/CORAL pair (CW20 send EMBER, hybrid pool_input=0 book_input=10000000, belief_price=null, min_return=null) -> REVERTS: "failed to execute message; message index: 0: Hybrid swap with book_input 10000000 requires belief_price or min_return without belief_price" - Same swap with min_return=19000000 -> code 0, fills the book (actions send,swap,transfer x3). So the floor is enforced and a floored pure-book swap still executes. Acceptance criteria: - Pure-book without belief/min reverts on-chain: PROVEN live (above) + non-vacuous unit test hybrid_pure_book_requires_slippage_floor_without_belief (negative: pool_input=0 / book_input=5000 / belief=None / min_return=None -> is_err, root cause contains "belief_price"/"min_return"; positive: min_return=Some(1) -> succeeds). - Dapp + router same release: router (router/src/contract.rs) extracts per-hop min_return from each SwapOperation and threads it into the per-hop Cw20HookMsg::Swap on the first hop and every intermediate hop, calling validate_hybrid_hop_execute_slippage_floor before each — so router-driven book hops carry the floor. Dapp changes (SwapPage / TradeMarketOrderPanel / swapRoutePreflight / router.ts / pair.ts) shipped in the same MR. Live dapp behavior = laptop. - make test-contracts + frontend preflight green: make test-contracts 375/0 (incl the #334 test). Frontend preflight (swapMaxSpread) via make test-frontend = laptop. - integrators.md + L9 updated: integrators.md:118 (pure-book needs belief_price or pair min_return; router per-hop min_return when book_input>0), contracts-security-audit.md L9 (#334 + the test ref), swap-max-spread-ux.md (#334 revert + enrichSwapOperationsWithHopMinReturns). - #273 closeable after directions 2/3: direction 2 (pair min_return) + direction 3 (require belief/min_return when book_input>0, incl pure-book) are landed and enforced. Your call on closing #273. Verification criteria: - cargo test pure-book reject + accept: the #334 test covers both paths; live accept also shown (CASE 2). - make test-frontend swap submit tests: laptop. - LocalTerra pure-book swap with floor succeeds: proved the contract-layer equivalent via terrad (CASE 2, min_return floor -> fills). The dapp-driven version is laptop. - Integrator doc migration note: integrators.md:118 published. So contract enforcement + router forwarding + docs are solid and the on-chain revert is proven. What remains is purely the browser layer: make test-frontend (swap submit + swapMaxSpread preflight) and the dapp-driven pure-book swap on LocalTerra — that is my laptop pass, I will run it there. @PlasticDigits — contract side is good; flagging the frontend layer as the remaining laptop check before close.
PlasticDigits commented 2026-06-06 06:49:50 +00:00 (Migrated from gitlab.com)

Frontend layer needs verification

Frontend layer needs verification
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-06 07:31:50 +00:00
PlasticDigits commented 2026-06-06 07:32:01 +00:00 (Migrated from gitlab.com)

Verification complete — GitLab #334

Issue: https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/334
Branch verified: main (implementation merged via !819)

Acceptance criteria

Criterion Result Evidence
Pure-book hybrid without belief_price or minimum_receive reverts on-chain PASS cargo test -p cl8y-dex-tests hybrid_pure_book_requires_slippage_floor_without_belief — negative path is_err with belief_price/min_return in root cause. Live LocalTerra CW20 send (EMBER→EMBER/CORAL pair, pool_input=0, book_input=10000000, no floor) reverts: Hybrid swap with book_input 10000000 requires belief_price or min_return without belief_price.
Dapp + router updated in same release as contract enforcement PASS SwapPage.tsx / TradeMarketOrderPanel.tsx call computeDirectHybridMinReturn + enrichSwapOperationsWithHopMinReturns; pair.ts emits min_return; router/src/contract.rs threads per-hop min_return via validate_hybrid_hop_execute_slippage_floor. Shipped in !819.
make test-contracts + frontend preflight tests green PASS make test-contracts → 375/0 (cl8y-dex-tests). make test-frontend (Node 24) → 871/0 incl. swapMaxSpread.test.ts #334 hybridBookRequiresSlippageFloor + targeted SwapPage.test.tsx / pair.test.ts / swapRoutePreflight.test.ts (41/0).
docs/integrators.md + L9 audit row updated PASS integrators.md § Slippage (pure-book execute floor + router per-hop min_return); contracts-security-audit.md L9 cites #334 + hybrid_pure_book_requires_slippage_floor_without_belief; swap-max-spread-ux.md documents #334 revert + enrichSwapOperationsWithHopMinReturns.
#273 closeable after directions 2/3 PASS (for #334 scope) Direction 2 (min_return on pair hook) + direction 3 (require floor when book_input > 0, incl. pure-book) enforced on-chain and in dapp/router submit paths. Closing #273 is a separate maintainer decision.

Verification criteria

Check Result Command / output
cargo test hybrid pure-book reject + accept PASS cargo test -p cl8y-dex-tests hybrid_pure_book → 1 passed
make test-frontend swap submit + preflight PASS make test-frontend → 871 passed
LocalTerra pure-book with slippage floor PASS Terrad: same pure-book msg + min_return=1 → tx 238FE88D… code 0 (send,swap,transfer×3). Dapp: npx playwright test e2e/hybrid-swap.spec.ts --project=e2e-tx -g "hybrid swap emits" → 1 passed (14.4s) — Simulated Wallet hybrid submit with auto min_return fills book (limit_order_fill, book_return_amount > 0).
Integrator migration note PASS docs/integrators.md documents pure-book execute requirement

Test-plan spot checks

Path Expected Result
Pool-only / zero-book Unchanged Covered by existing regression suite (375 contract tests)
Pure-book, no floor Reject PASS (on-chain + unit test)
Pure-book + min_return Pass PASS (LocalTerra terrad)
Hybrid material pool + book, no belief #307 + shortfall Existing tests (hybrid_no_belief_*) in suite
Router multihop book hop floor Per-hop enforced Router validate_hybrid_hop_execute_slippage_floor on first + intermediate hops

Environment

  • LocalTerra + Postgres + indexer via make setup-cloud-localterra
  • scripts/e2e-seed-hybrid-book.sh for resting bid
  • Playwright headless shell installed for E2E (chromium_headless_shell-1208)

All acceptance and verification items PASS. No repo changes required from this verification run.

## Verification complete — GitLab #334 Issue: https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/334 Branch verified: `main` (implementation merged via !819) ### Acceptance criteria | Criterion | Result | Evidence | |-----------|--------|----------| | Pure-book hybrid without `belief_price` or `minimum_receive` reverts on-chain | **PASS** | `cargo test -p cl8y-dex-tests hybrid_pure_book_requires_slippage_floor_without_belief` — negative path `is_err` with `belief_price`/`min_return` in root cause. Live LocalTerra CW20 send (EMBER→EMBER/CORAL pair, `pool_input=0`, `book_input=10000000`, no floor) reverts: `Hybrid swap with book_input 10000000 requires belief_price or min_return without belief_price`. | | Dapp + router updated in same release as contract enforcement | **PASS** | `SwapPage.tsx` / `TradeMarketOrderPanel.tsx` call `computeDirectHybridMinReturn` + `enrichSwapOperationsWithHopMinReturns`; `pair.ts` emits `min_return`; `router/src/contract.rs` threads per-hop `min_return` via `validate_hybrid_hop_execute_slippage_floor`. Shipped in !819. | | `make test-contracts` + frontend preflight tests green | **PASS** | `make test-contracts` → **375/0** (`cl8y-dex-tests`). `make test-frontend` (Node 24) → **871/0** incl. `swapMaxSpread.test.ts` #334 `hybridBookRequiresSlippageFloor` + targeted `SwapPage.test.tsx` / `pair.test.ts` / `swapRoutePreflight.test.ts` (41/0). | | `docs/integrators.md` + L9 audit row updated | **PASS** | `integrators.md` § Slippage (pure-book execute floor + router per-hop `min_return`); `contracts-security-audit.md` L9 cites #334 + `hybrid_pure_book_requires_slippage_floor_without_belief`; `swap-max-spread-ux.md` documents #334 revert + `enrichSwapOperationsWithHopMinReturns`. | | #273 closeable after directions 2/3 | **PASS** (for #334 scope) | Direction 2 (`min_return` on pair hook) + direction 3 (require floor when `book_input > 0`, incl. pure-book) enforced on-chain and in dapp/router submit paths. Closing #273 is a separate maintainer decision. | ### Verification criteria | Check | Result | Command / output | |-------|--------|------------------| | `cargo test` hybrid pure-book reject + accept | **PASS** | `cargo test -p cl8y-dex-tests hybrid_pure_book` → 1 passed | | `make test-frontend` swap submit + preflight | **PASS** | `make test-frontend` → 871 passed | | LocalTerra pure-book with slippage floor | **PASS** | Terrad: same pure-book msg + `min_return=1` → tx `238FE88D…` code **0** (`send,swap,transfer×3`). Dapp: `npx playwright test e2e/hybrid-swap.spec.ts --project=e2e-tx -g "hybrid swap emits"` → **1 passed** (14.4s) — Simulated Wallet hybrid submit with auto `min_return` fills book (`limit_order_fill`, `book_return_amount > 0`). | | Integrator migration note | **PASS** | `docs/integrators.md` documents pure-book execute requirement | ### Test-plan spot checks | Path | Expected | Result | |------|----------|--------| | Pool-only / zero-book | Unchanged | Covered by existing regression suite (375 contract tests) | | Pure-book, no floor | Reject | **PASS** (on-chain + unit test) | | Pure-book + `min_return` | Pass | **PASS** (LocalTerra terrad) | | Hybrid material pool + book, no belief | #307 + shortfall | Existing tests (`hybrid_no_belief_*`) in suite | | Router multihop book hop floor | Per-hop enforced | Router `validate_hybrid_hop_execute_slippage_floor` on first + intermediate hops | ### Environment - LocalTerra + Postgres + indexer via `make setup-cloud-localterra` - `scripts/e2e-seed-hybrid-book.sh` for resting bid - Playwright headless shell installed for E2E (`chromium_headless_shell-1208`) All acceptance and verification items **PASS**. No repo changes required from this verification run.
Brouie commented 2026-06-08 00:20:37 +00:00 (Migrated from gitlab.com)

mentioned in merge request !835

mentioned in merge request !835
Brouie commented 2026-06-08 00:32:39 +00:00 (Migrated from gitlab.com)

mentioned in issue #337

mentioned in issue #337
ghost1 commented 2026-06-08 05:24:40 +00:00 (Migrated from gitlab.com)

mentioned in commit 06eb2d8bb5

mentioned in commit 06eb2d8bb5bd7a30fa9d33e87c5d319082f06e1f
PlasticDigits commented 2026-06-08 05:29:55 +00:00 (Migrated from gitlab.com)

mentioned in commit 737f47e0cc

mentioned in commit 737f47e0cc5db17172fa33ee94297c654f6694bf
PlasticDigits commented 2026-06-08 08:14:17 +00:00 (Migrated from gitlab.com)

mentioned in issue #339

mentioned in issue #339
PlasticDigits commented 2026-06-08 08:14:37 +00:00 (Migrated from gitlab.com)

mentioned in issue #292

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

mentioned in commit 7a64050001

mentioned in commit 7a64050001be44217108d182f377a2e4ba67f296
PlasticDigits commented 2026-06-08 08:43:13 +00:00 (Migrated from gitlab.com)

mentioned in commit 606a0f0d1d

mentioned in commit 606a0f0d1d14fd956db572033ffdab4b4a619971
PlasticDigits commented 2026-06-08 08:43:13 +00:00 (Migrated from gitlab.com)

mentioned in commit d5d0c6a8bc

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

mentioned in commit 807480f30f

mentioned in commit 807480f30ff95f196ff399b642ffcc0cc9deebcf
PlasticDigits commented 2026-06-08 08:43:13 +00:00 (Migrated from gitlab.com)

mentioned in commit 53b8658c58

mentioned in commit 53b8658c5850c50e45fdd163758ea9978315fc56
PlasticDigits commented 2026-06-08 08:43:13 +00:00 (Migrated from gitlab.com)

mentioned in commit ff12f65dbf

mentioned in commit ff12f65dbf64bdfcbd8540bab6e3e48427a41f5e
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:27 +00:00 (Migrated from gitlab.com)

mentioned in commit 5f27d35187

mentioned in commit 5f27d351876909ddfec7dff975efb45c59501000
PlasticDigits commented 2026-06-08 13:42:27 +00:00 (Migrated from gitlab.com)

mentioned in commit 06c3610eff

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

mentioned in commit 4bc07345b1

mentioned in commit 4bc07345b1926cf3a538b4b4d22bb16566b5b823
PlasticDigits commented 2026-06-08 13:42:27 +00:00 (Migrated from gitlab.com)

mentioned in commit 05ee14db17

mentioned in commit 05ee14db17272ba4b982f75df859491565454067
PlasticDigits commented 2026-06-08 13:42:28 +00:00 (Migrated from gitlab.com)

mentioned in commit 8f0ca4009d

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

mentioned in commit e6e71f29e7

mentioned in commit e6e71f29e7db6a520ee4da25b84f9c1bbcc736d1
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:51 +00:00 (Migrated from gitlab.com)

mentioned in merge request !841

mentioned in merge request !841
Brouie commented 2026-06-09 02:14:35 +00:00 (Migrated from gitlab.com)

mentioned in merge request !842

mentioned in merge request !842
ghost1 commented 2026-06-09 06:53:50 +00:00 (Migrated from gitlab.com)

mentioned in merge request !849

mentioned in merge request !849
PlasticDigits commented 2026-06-13 07:09:04 +00:00 (Migrated from gitlab.com)

mentioned in issue #376

mentioned in issue #376
PlasticDigits commented 2026-06-25 14:12:56 +00:00 (Migrated from gitlab.com)

mentioned in issue #418

mentioned in issue #418
Brouie commented 2026-06-29 15:30:19 +00:00 (Migrated from gitlab.com)

mentioned in issue #428

mentioned in issue #428
PlasticDigits commented 2026-08-30 05:24:16 +00:00 (Migrated from gitlab.com)

mentioned in issue #708

mentioned in issue #708
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#334
No description provided.