Contracts: unify assert_max_spread for pool-only and hybrid swaps #197

Closed
opened 2026-05-26 08:00:00 +00:00 by PlasticDigits · 8 comments
PlasticDigits commented 2026-05-26 08:00:00 +00:00 (Migrated from gitlab.com)

Problem statement

assert_max_spread / slippage checks are validated primarily against pool path inputs; combined hybrid return (book + pool) may not match product intent for belief_price / max_spread guards.

Evidence / context

Proposed solution

  1. Product decision: spread checked on total output (book + pool) vs pool-only.
  2. Implement unified check; add integration tests for hybrid with non-zero book leg and edge beliefs.

Acceptance criteria

  • Documented spread semantics in docs/integrators.md or security audit.
  • Tests: hybrid swap respects max_spread per chosen rule; pool-only unchanged.

Priority

P2

## Problem statement `assert_max_spread` / slippage checks are validated primarily against **pool path** inputs; combined **hybrid** return (book + pool) may not match product intent for `belief_price` / `max_spread` guards. ## Evidence / context - Backlog **#81** / DEX-P2-011; [`smartcontracts/contracts/pair/src/contract.rs`](smartcontracts/contracts/pair/src/contract.rs). ## Proposed solution 1. Product decision: spread checked on **total output** (book + pool) vs pool-only. 2. Implement unified check; add integration tests for hybrid with non-zero book leg and edge beliefs. ## Acceptance criteria - [ ] Documented spread semantics in [`docs/integrators.md`](docs/integrators.md) or security audit. - [ ] Tests: hybrid swap respects `max_spread` per chosen rule; pool-only unchanged. ## Priority **P2**
PlasticDigits commented 2026-05-26 09:44:05 +00:00 (Migrated from gitlab.com)

mentioned in commit be40461810

mentioned in commit be4046181087784a13ca7e30fae05505e17a3dd0
PlasticDigits commented 2026-05-26 09:44:36 +00:00 (Migrated from gitlab.com)

Implementation summary (GitLab #197)

Unified pool-only and hybrid max_spread / belief_price slippage checks behind a single shared module and documented the product rule as invariant L9.

What changed

  • Shared logic: dex_common::max_spread — pool-only is book_net_return = 0; hybrid uses the same code path.
  • Pair contract: assert_max_spread delegates to dex_common::max_spread::check_max_spread.
  • Product rule (no belief_price): min(pool_spread, pool_gross) / (pool_gross + book_net) must not strictly exceed max_spread.
  • Product rule (belief_price): shortfall vs offer / belief_price using book_net + pool_net + pool_commission as actual output.
  • Tests added:
    • hybrid_max_spread_exact_tolerance_succeeds
    • hybrid_max_spread_tighter_than_simulation_rejected
    • hybrid_belief_price_max_spread_rejects_shortfall_on_total_output
    • Pool-only regression unchanged: test_swap_max_spread
  • Docs / agent skills: invariant L9 in docs/contracts-security-audit.md, docs/integrators.md, ADR 0001, docs/swap-max-spread-ux.md, new skills/AGENTS_MAX_SPREAD_HYBRID.md; cross-links in AGENTS_HYBRID_QUOTING.md and AGENTS_TESTING_MULTIHOP_HYBRID.md.

Merged to main in commit be40461.

Verification checklist

  • cd smartcontracts && cargo test -p dex-common max_spread
  • cd smartcontracts && cargo test -p cl8y-dex-tests hybrid_max_spread
  • cd smartcontracts && cargo test -p cl8y-dex-tests hybrid_belief_price_max_spread
  • cd smartcontracts && cargo test -p cl8y-dex-tests test_swap_max_spread (pool-only unchanged)
  • Confirm docs/integrators.md slippage section matches integrator expectations
  • Confirm frontend preflight in swapMaxSpread.ts still mirrors L9 for retail swaps (no belief_price)

@brouie — please verify the hybrid slippage semantics and test checklist above. Leaving this issue open until sign-off.

## Implementation summary (GitLab #197) Unified pool-only and hybrid `max_spread` / `belief_price` slippage checks behind a single shared module and documented the product rule as invariant **L9**. ### What changed - **Shared logic:** `dex_common::max_spread` — pool-only is `book_net_return = 0`; hybrid uses the same code path. - **Pair contract:** `assert_max_spread` delegates to `dex_common::max_spread::check_max_spread`. - **Product rule (no `belief_price`):** `min(pool_spread, pool_gross) / (pool_gross + book_net)` must not strictly exceed `max_spread`. - **Product rule (`belief_price`):** shortfall vs `offer / belief_price` using `book_net + pool_net + pool_commission` as actual output. - **Tests added:** - `hybrid_max_spread_exact_tolerance_succeeds` - `hybrid_max_spread_tighter_than_simulation_rejected` - `hybrid_belief_price_max_spread_rejects_shortfall_on_total_output` - Pool-only regression unchanged: `test_swap_max_spread` - **Docs / agent skills:** invariant **L9** in `docs/contracts-security-audit.md`, `docs/integrators.md`, ADR 0001, `docs/swap-max-spread-ux.md`, new `skills/AGENTS_MAX_SPREAD_HYBRID.md`; cross-links in `AGENTS_HYBRID_QUOTING.md` and `AGENTS_TESTING_MULTIHOP_HYBRID.md`. Merged to `main` in commit `be40461`. ### Verification checklist - [ ] `cd smartcontracts && cargo test -p dex-common max_spread` - [ ] `cd smartcontracts && cargo test -p cl8y-dex-tests hybrid_max_spread` - [ ] `cd smartcontracts && cargo test -p cl8y-dex-tests hybrid_belief_price_max_spread` - [ ] `cd smartcontracts && cargo test -p cl8y-dex-tests test_swap_max_spread` (pool-only unchanged) - [ ] Confirm `docs/integrators.md` slippage section matches integrator expectations - [ ] Confirm frontend preflight in `swapMaxSpread.ts` still mirrors L9 for retail swaps (no `belief_price`) @brouie — please verify the hybrid slippage semantics and test checklist above. Leaving this issue **open** until sign-off.
PlasticDigits commented 2026-05-26 09:45:42 +00:00 (Migrated from gitlab.com)

mentioned in commit f31fa823f7

mentioned in commit f31fa823f7ff9fc28f7b911f5660666297f45c0c
PlasticDigits commented 2026-05-26 09:45:49 +00:00 (Migrated from gitlab.com)

mentioned in issue #196

mentioned in issue #196
PlasticDigits commented 2026-05-27 06:59:42 +00:00 (Migrated from gitlab.com)

Verification sign-off (@brouie agent, 2026-05-27)

Verified GitLab #197 on main (commits be40461, f31fa82). No additional code changes were required.

Verification checklist

  • cd smartcontracts && cargo test -p dex-common max_spread — 5/5 passed
  • cd smartcontracts && cargo test -p cl8y-dex-tests hybrid_max_spread — 2/2 passed
  • cd smartcontracts && cargo test -p cl8y-dex-tests hybrid_belief_price_max_spread — 1/1 passed
  • cd smartcontracts && cargo test -p cl8y-dex-tests test_swap_max_spread — pool-only regression passed
  • docs/integrators.md slippage section matches invariant L9 (dex_common::max_spread, total-gross denominator for hybrid)
  • Frontend swapMaxSpread.ts + vitest (swapMaxSpread.test.ts) — 5/5 passed; mirrors no-belief L9 formula
  • Browser: Swap page at http://127.0.0.1:5175 — EMBER→CORAL 100-unit quote shows Price impact 0.10%, slippage 0.5%, min received (preflight path live against indexer :3001)

Infra used

  • LocalTerra healthy (127.0.0.1:26657)
  • Host Postgres :5432 accepting connections
  • Indexer healthy (http://127.0.0.1:3001/health)
  • Bot swarm workers running on localnet

Worktree fix/issue-197-verify was used for isolated verification; merged state is already on origin/main (no delta to push).

## Verification sign-off (@brouie agent, 2026-05-27) Verified GitLab #197 on `main` (commits `be40461`, `f31fa82`). No additional code changes were required. ### Verification checklist - [x] `cd smartcontracts && cargo test -p dex-common max_spread` — 5/5 passed - [x] `cd smartcontracts && cargo test -p cl8y-dex-tests hybrid_max_spread` — 2/2 passed - [x] `cd smartcontracts && cargo test -p cl8y-dex-tests hybrid_belief_price_max_spread` — 1/1 passed - [x] `cd smartcontracts && cargo test -p cl8y-dex-tests test_swap_max_spread` — pool-only regression passed - [x] `docs/integrators.md` slippage section matches invariant **L9** (`dex_common::max_spread`, total-gross denominator for hybrid) - [x] Frontend `swapMaxSpread.ts` + vitest (`swapMaxSpread.test.ts`) — 5/5 passed; mirrors no-belief L9 formula - [x] Browser: Swap page at `http://127.0.0.1:5175` — EMBER→CORAL 100-unit quote shows **Price impact 0.10%**, slippage 0.5%, min received (preflight path live against indexer :3001) ### Infra used - LocalTerra healthy (`127.0.0.1:26657`) - Host Postgres `:5432` accepting connections - Indexer healthy (`http://127.0.0.1:3001/health`) - Bot swarm workers running on localnet Worktree `fix/issue-197-verify` was used for isolated verification; merged state is already on `origin/main` (no delta to push).
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-05-27 06:59:47 +00:00
Brouie commented 2026-06-04 06:10:10 +00:00 (Migrated from gitlab.com)

mentioned in issue #273

mentioned in issue #273
Brouie commented 2026-06-04 06:10:13 +00:00 (Migrated from gitlab.com)

mentioned in merge request !746

mentioned in merge request !746
PlasticDigits commented 2026-06-05 04:08:28 +00:00 (Migrated from gitlab.com)

mentioned in issue #307

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