fix(contracts): material pool leg for no-belief hybrid max_spread (#307) #785

Merged
PlasticDigits merged 6 commits from cursor/gitlab-issue-workflow-dc06 into main 2026-06-05 10:54:19 +00:00
PlasticDigits commented 2026-06-05 09:59:15 +00:00 (Migrated from gitlab.com)

Summary

Closes https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/307 (follow-up to #273).

When a hybrid swap routes to the limit book without belief_price, the declared pool_input must be at least 10% of offer_amount (minimum 1 raw unit) and the pool leg must produce non-zero net output before the #273 book-shortfall term runs. Pure-book hybrids (declared_pool_input = 0) are unchanged.

Acceptance checklist

Criterion Verification Result
Dust pool + book rejected cargo test -p cl8y-dex-tests hybrid_no_belief_dust_pool_leg_rejected PASS
Material-pool hybrid passes cargo test -p cl8y-dex-tests hybrid_max_spread_exact_tolerance_succeeds PASS
Pool-only unchanged cargo test -p dex-common pool_only_matches_hybrid_with_zero_book PASS
Clear contract errors InsufficientPoolLegForHybrid in pair PASS
Security audit doc docs/contracts-security-audit.md L9 PASS
#273 PoC rejects toxic book hybrid_no_belief_book_far_below_pool_rejected PASS
Frontend preflight npm test -- src/utils/swapMaxSpread.test.ts PASS
Full suite make test-contracts PASS

Issue left open until merge.


Note

Medium Risk
Changes core swap slippage rejection on hybrid execute and router paths (user-facing trading), but scope is bounded to no-belief hybrid splits with regression tests and pure-book behavior preserved.

Overview
Extends invariant L9 so no-belief hybrid swaps with both pool and book legs must declare pool_input ≥ 10% of the offer (minimum 1 raw unit) and get non-zero pool net output before the existing #273 book-shortfall slippage math runs. Pure-book intent (declared_pool_input = 0) is unchanged and can still roll remainder to the pool.

On-chain: dex_common::max_spread gains CheckMaxSpreadError, validate_declared_hybrid_pool_leg_for_no_belief, and declared_pool_input on spread inputs. The pair validates declared splits early on swap and hybrid sim (skipped when belief_price is set), maps failures to InsufficientPoolLegForHybrid / ZeroPoolNetForHybrid, and exposes optional belief_price on hybrid sim queries plus limit_book_offer_consumed on sim responses. The router applies the same declared-split guard before multi-hop swaps and simulation.

Off-chain: swapMaxSpread.ts mirrors #273 shortfall and #307 floors; route preflight uses realized legs and material-pool checks; tx errors get user-facing copy for these rejections. Docs, agent skill, and integration/unit tests updated accordingly.

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

## Summary Closes https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/307 (follow-up to #273). When a hybrid swap routes to the limit book without belief_price, the declared pool_input must be at least 10% of offer_amount (minimum 1 raw unit) and the pool leg must produce non-zero net output before the #273 book-shortfall term runs. Pure-book hybrids (declared_pool_input = 0) are unchanged. ## Acceptance checklist | Criterion | Verification | Result | |-----------|--------------|--------| | Dust pool + book rejected | cargo test -p cl8y-dex-tests hybrid_no_belief_dust_pool_leg_rejected | PASS | | Material-pool hybrid passes | cargo test -p cl8y-dex-tests hybrid_max_spread_exact_tolerance_succeeds | PASS | | Pool-only unchanged | cargo test -p dex-common pool_only_matches_hybrid_with_zero_book | PASS | | Clear contract errors | InsufficientPoolLegForHybrid in pair | PASS | | Security audit doc | docs/contracts-security-audit.md L9 | PASS | | #273 PoC rejects toxic book | hybrid_no_belief_book_far_below_pool_rejected | PASS | | Frontend preflight | npm test -- src/utils/swapMaxSpread.test.ts | PASS | | Full suite | make test-contracts | PASS | Issue left open until merge. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes core swap slippage rejection on hybrid execute and router paths (user-facing trading), but scope is bounded to no-belief hybrid splits with regression tests and pure-book behavior preserved. > > **Overview** > Extends **invariant L9** so no-belief hybrid swaps with **both** pool and book legs must declare **`pool_input ≥ 10%`** of the offer (minimum 1 raw unit) and get **non-zero pool net output** before the existing **#273** book-shortfall slippage math runs. **Pure-book** intent (`declared_pool_input = 0`) is unchanged and can still roll remainder to the pool. > > **On-chain:** `dex_common::max_spread` gains **`CheckMaxSpreadError`**, **`validate_declared_hybrid_pool_leg_for_no_belief`**, and **`declared_pool_input`** on spread inputs. The **pair** validates declared splits early on swap and hybrid sim (skipped when **`belief_price`** is set), maps failures to **`InsufficientPoolLegForHybrid`** / **`ZeroPoolNetForHybrid`**, and exposes optional **`belief_price`** on hybrid sim queries plus **`limit_book_offer_consumed`** on sim responses. The **router** applies the same declared-split guard before multi-hop swaps and simulation. > > **Off-chain:** **`swapMaxSpread.ts`** mirrors #273 shortfall and #307 floors; **route preflight** uses realized legs and material-pool checks; **tx errors** get user-facing copy for these rejections. Docs, agent skill, and integration/unit tests updated accordingly. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 72dcd5625011f188387e5a329270221cc8d69a2a. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
PlasticDigits commented 2026-06-05 09:59:22 +00:00 (Migrated from gitlab.com)

mentioned in issue #307

mentioned in issue #307
ghost1 commented 2026-06-05 09:59:24 +00:00 (Migrated from gitlab.com)

changed the description

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

changed the description

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

Security review (automated)

Commit reviewed: 6cf3d7a4dd4fe2e25826578186103539e7b59651
Scope: MR !785 diff vs main (contracts max_spread / pair / router #307, factory #276/#277, indexer rate-limit #282 / limit clamps / resting-book mirror, frontend preflight, QA scripts). Prior MR discussions contained no security-review threads to re-validate.

Outcome: FINDINGS: 0 medium+

Inline threads: none


Summary

This MR closes the no-belief hybrid slippage bypass tracked in #307 (dust declared pool_input destabilizing the #273 book-shortfall reference). Changes are defensive and align on-chain checks, router prechecks, frontend preflight, and audit invariant L9.

Contract path (#307 / L9) — reviewed, no new bypass

  • Early reject: validate_declared_hybrid_pool_leg_for_no_belief in pair execute_swap and router validate_hybrid_declared_split_for_no_belief when belief_price is unset and both pool_input and book_input are non-zero.
  • Post-settlement reject: check_max_spread uses declared_pool_input for the 10% floor and requires pool_net_return > 0 before applying the #273 book-shortfall term.
  • Attacker-controlled inputs (pool_input, book_input, max_spread, book fills) are bounded by existing L4 split equality, L5 scan/maker caps, and the updated spread math; integration tests (hybrid_no_belief_dust_pool_leg_rejected, hybrid_no_belief_book_far_below_pool_rejected) cover the PoC shapes.
  • Intentional residual (documented, not introduced): pure-book hybrids (declared_pool_input = 0) remain outside the #273/#307 no-belief metric; unfilled book remainder may still hit the pool. Documented in max_spread.rs, L9, and tests (pure_book_hybrid_skips_material_pool_floor). Users must rely on belief_price / router minimum_receive — pre-existing product boundary, not a regression in this diff.

Other security-relevant diff hunks

Area Assessment
Factory #276 (CreatePair uluna refund when fee = 0) Reduces stuck-funds risk; no authz change.
Factory #277 (decouple SetLpAdmin from UpdateConfig; bounded SetLpAdminAll / SetLpAdminBatch) Reduces governance-tx DoS / gas blow-up; governance-only.
Indexer #282 (IPv6 /64 rate-limit keys via ConnectInfo, no X-Forwarded-For) Hardens rate limiting; avoids spoofable forwarded headers.
Indexer #317 limit lower-bound clamps Prevents negative LIMIT SQL errors (availability), not authz.
resting_orders SQL ORDER BY price_dir derived only from internal "bid" / "ask" — no caller-controlled SQL injection.
Keplr setup scripts Dev/QA VM tooling only; not in production attack surface.

Not reported (per policy)

  • Governance-trusted operations, stylistic issues, and pre-existing pure-book / optional-belief_price slippage models unrelated to the #307 fix.

Security review: no medium+ findings on this diff.

## Security review (automated) **Commit reviewed:** `6cf3d7a4dd4fe2e25826578186103539e7b59651` **Scope:** MR !785 diff vs `main` (contracts `max_spread` / pair / router #307, factory #276/#277, indexer rate-limit #282 / limit clamps / resting-book mirror, frontend preflight, QA scripts). Prior MR discussions contained no security-review threads to re-validate. **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none --- ### Summary This MR **closes** the no-belief hybrid slippage bypass tracked in #307 (dust declared `pool_input` destabilizing the #273 book-shortfall reference). Changes are defensive and align on-chain checks, router prechecks, frontend preflight, and audit invariant **L9**. ### Contract path (#307 / L9) — reviewed, no new bypass - **Early reject:** `validate_declared_hybrid_pool_leg_for_no_belief` in pair `execute_swap` and router `validate_hybrid_declared_split_for_no_belief` when `belief_price` is unset and both `pool_input` and `book_input` are non-zero. - **Post-settlement reject:** `check_max_spread` uses `declared_pool_input` for the 10% floor and requires `pool_net_return > 0` before applying the #273 book-shortfall term. - **Attacker-controlled inputs** (`pool_input`, `book_input`, `max_spread`, book fills) are bounded by existing **L4** split equality, **L5** scan/maker caps, and the updated spread math; integration tests (`hybrid_no_belief_dust_pool_leg_rejected`, `hybrid_no_belief_book_far_below_pool_rejected`) cover the PoC shapes. - **Intentional residual (documented, not introduced):** pure-book hybrids (`declared_pool_input = 0`) remain outside the #273/#307 no-belief metric; unfilled book remainder may still hit the pool. Documented in `max_spread.rs`, **L9**, and tests (`pure_book_hybrid_skips_material_pool_floor`). Users must rely on `belief_price` / router `minimum_receive` — pre-existing product boundary, not a regression in this diff. ### Other security-relevant diff hunks | Area | Assessment | |------|------------| | Factory **#276** (`CreatePair` uluna refund when fee = 0) | Reduces stuck-funds risk; no authz change. | | Factory **#277** (decouple `SetLpAdmin` from `UpdateConfig`; bounded `SetLpAdminAll` / `SetLpAdminBatch`) | Reduces governance-tx DoS / gas blow-up; governance-only. | | Indexer **#282** (IPv6 `/64` rate-limit keys via `ConnectInfo`, no `X-Forwarded-For`) | Hardens rate limiting; avoids spoofable forwarded headers. | | Indexer **#317** limit lower-bound clamps | Prevents negative `LIMIT` SQL errors (availability), not authz. | | `resting_orders` SQL `ORDER BY` | `price_dir` derived only from internal `"bid"` / `"ask"` — no caller-controlled SQL injection. | | Keplr setup scripts | Dev/QA VM tooling only; not in production attack surface. | ### Not reported (per policy) - Governance-trusted operations, stylistic issues, and pre-existing pure-book / optional-`belief_price` slippage models unrelated to the #307 fix. --- Security review: **no medium+ findings** on this diff.
ghost1 commented 2026-06-05 10:01:19 +00:00 (Migrated from gitlab.com)
Stale Security Review comment
Stale Security Review comment
Stale Security Review comment
Stale Security Review comment
Stale Security Review comment

Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Reviewed by Cursor Bugbot for commit 6cf3d7a4dd. Configure here.

<details> <summary>Stale Security Review comment</summary> <details> <summary>Stale Security Review comment</summary> <details> <summary>Stale Security Review comment</summary> <details> <summary>Stale Security Review comment</summary> <details> <summary>Stale Security Review comment</summary> <!-- BUGBOT_REVIEW --> Cursor Bugbot has reviewed your changes and found 1 potential issue.<!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_BEGIN --> <sup>Bugbot Autofix is [ON](https://www.cursor.com/dashboard/bugbot). A cloud agent has been kicked off to fix the reported issue. <!-- BUGBOT_AUTOFIX_AGENT_LINK --></sup> <!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_END --> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6cf3d7a4dd4fe2e25826578186103539e7b59651. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> </details> </details> </details> </details> </details>
ghost1 commented 2026-06-05 10:01:20 +00:00 (Migrated from gitlab.com)

Preflight shortfall ignores empty book

Medium Severity

hybridSpreadCmpAndTotal folds in #273 book shortfall whenever declared pool_input and book_input are both positive, but on-chain check_max_spread only applies that term when the book actually consumed offer (book_input / book_return non-zero). A hybrid with a declared book leg that simulates to zero book output can pass execute yet fail route preflight spread gating.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6cf3d7a4dd. Configure here.

### Preflight shortfall ignores empty book **Medium Severity** <!-- DESCRIPTION START --> `hybridSpreadCmpAndTotal` folds in #273 book shortfall whenever declared `pool_input` and `book_input` are both positive, but on-chain `check_max_spread` only applies that term when the book actually consumed offer (`book_input` / `book_return` non-zero). A hybrid with a declared book leg that simulates to zero book output can pass execute yet fail route preflight spread gating. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: 7e14db6d-d0da-45d6-a491-068212e97b16 --> <!-- LOCATIONS START frontend-dapp/src/utils/swapMaxSpread.ts#L90-L94 frontend-dapp/src/services/terraclassic/swapRoutePreflight.ts#L62-L65 LOCATIONS END --> <details> <summary>Additional Locations (1)</summary> - [`frontend-dapp/src/services/terraclassic/swapRoutePreflight.ts#L62-L65`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-//blob/6cf3d7a4dd4fe2e25826578186103539e7b59651/frontend-dapp/src/services/terraclassic/swapRoutePreflight.ts#L62-L65) </details> <div><a href="https://cursor.com/open?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OmQ5NmRlYmE2LWUyMjMtNGRlOC05NDdhLWI2YzBhMDhkNDgyMiIsImVuY3J5cHRpb25LZXkiOiJ4RTFhMjlUM0xEaWpEdmhNaU05M1lXZi1FNHZMNmRYU29KbTRhWlVLMGlvIiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIn19" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OmQ5NmRlYmE2LWUyMjMtNGRlOC05NDdhLWI2YzBhMDhkNDgyMiIsImVuY3J5cHRpb25LZXkiOiJ4RTFhMjlUM0xEaWpEdmhNaU05M1lXZi1FNHZMNmRYU29KbTRhWlVLMGlvIiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIiwicHJOdW1iZXIiOjY3LCJjb21taXRTaGEiOiI2Y2YzZDdhNGRkNGZlMmUyNTgyNjU3ODE4NjEwMzUzOWU3YjU5NjUxIiwicHJvdmlkZXIiOiJnaXRsYWIiLCJob3N0bmFtZSI6ImdpdGxhYi5jb20ifX0" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></div> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6cf3d7a4dd4fe2e25826578186103539e7b59651. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
ghost1 commented 2026-06-05 10:02:57 +00:00 (Migrated from gitlab.com)

added 1 commit

  • 9ac09ab1 - fix: skip book shortfall in preflight when book leg fills nothing

Compare with previous version

added 1 commit <ul><li>9ac09ab1 - fix: skip book shortfall in preflight when book leg fills nothing</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/67/diffs?diff_id=1836399041&start_sha=6cf3d7a4dd4fe2e25826578186103539e7b59651)
ghost1 commented 2026-06-05 10:03:12 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-05 10:03:20 +00:00 (Migrated from gitlab.com)

resolved all threads

resolved all threads
ghost1 commented 2026-06-05 10:05:54 +00:00 (Migrated from gitlab.com)
Stale Security Review comment
Stale Security Review comment
Stale Security Review comment
Stale Security Review comment

Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Reviewed by Cursor Bugbot for commit 9ac09ab1c1. Configure here.

<details> <summary>Stale Security Review comment</summary> <details> <summary>Stale Security Review comment</summary> <details> <summary>Stale Security Review comment</summary> <details> <summary>Stale Security Review comment</summary> <!-- BUGBOT_REVIEW --> Cursor Bugbot has reviewed your changes and found 1 potential issue.<!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_BEGIN --> <sup>Bugbot Autofix is [ON](https://www.cursor.com/dashboard/bugbot). A cloud agent has been kicked off to fix the reported issue. <!-- BUGBOT_AUTOFIX_AGENT_LINK --></sup> <!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_END --> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 9ac09ab1c178c6c808b27eb60241189c84df642d. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> </details> </details> </details> </details>
ghost1 commented 2026-06-05 10:05:55 +00:00 (Migrated from gitlab.com)

Hybrid sim skips pool leg

Medium Severity

HybridSimulation still quotes dust-pool hybrids after execute began rejecting them via validate_declared_hybrid_pool_leg_for_no_belief when belief_price is unset. Router simulation was updated, but the pair forward sim path was not, so LCD quotes and indexer grid search can overstate output for splits that fail on submit.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9ac09ab1c1. Configure here.

### Hybrid sim skips pool leg **Medium Severity** <!-- DESCRIPTION START --> `HybridSimulation` still quotes dust-pool hybrids after execute began rejecting them via `validate_declared_hybrid_pool_leg_for_no_belief` when `belief_price` is unset. Router simulation was updated, but the pair forward sim path was not, so LCD quotes and indexer grid search can overstate output for splits that fail on submit. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: c8571e37-9efe-402c-9b2d-24fcd400e841 --> <!-- LOCATIONS START smartcontracts/contracts/pair/src/contract.rs#L2136-L2148 LOCATIONS END --> <div><a href="https://cursor.com/open?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OmViNWNhMjVkLTNjNGUtNDEzNy05YTQzLTdkYmFjNzIwZmViNiIsImVuY3J5cHRpb25LZXkiOiJzOXdwRGhWblFWNGp6RkVlTHdudklmVU1Hc1JBbThsRWdvUzJlMjAxQjJ3IiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIn19" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OmViNWNhMjVkLTNjNGUtNDEzNy05YTQzLTdkYmFjNzIwZmViNiIsImVuY3J5cHRpb25LZXkiOiJzOXdwRGhWblFWNGp6RkVlTHdudklmVU1Hc1JBbThsRWdvUzJlMjAxQjJ3IiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIiwicHJOdW1iZXIiOjY3LCJjb21taXRTaGEiOiI5YWMwOWFiMWMxNzhjNmM4MDhiMjdlYjYwMjQxMTg5Yzg0ZGY2NDJkIiwicHJvdmlkZXIiOiJnaXRsYWIiLCJob3N0bmFtZSI6ImdpdGxhYi5jb20ifX0" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></div> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 9ac09ab1c178c6c808b27eb60241189c84df642d. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
PlasticDigits commented 2026-06-05 10:05:59 +00:00 (Migrated from gitlab.com)

Security review (automated)

Commit reviewed: 9ac09ab1c178c6c808b27eb60241189c84df642d
Scope: MR !785 diff vs main — dex_common::max_spread (#273 book shortfall, #307 material pool leg), pair execute_swap / assert_max_spread, router declared-split precheck + SimulateSwapOperations, frontend swapMaxSpread / route preflight, audit doc L9, integration tests.

Outcome: FINDINGS: 0 medium+

Inline threads: none


Re-validation of prior threads

  • Prior automated review (6cf3d7a): FINDINGS: 0 — still holds on the updated head; no new bypass identified.
  • Bugbot inline (resolved): preflight #273 shortfall gated on declared legs while on-chain gates on realized offer_consumed_by_book. Fixed in 9ac09ab (bookNet > 0n in hybridSpreadCmpAndTotal); contract parity confirmed at max_spread.rs (book_input.is_zero() uses realized consumption). This was a preflight false-positive (UX), not an on-chain slippage bypass — no open medium+ item.

Contract path (#307 / L9) — reviewed, no exploitable bypass

Control Location Attacker input Result
Early declared-split reject validate_declared_hybrid_pool_leg_for_no_belief in pair execute_swap (no belief_price) and router validate_hybrid_declared_split_for_no_belief pool_input, book_input Rejects when both legs non-zero and pool_input < 10% of offer (min 1 raw unit)
Post-settlement floor check_max_spread on declared_pool_input + pool_net_return same + execution outcome InsufficientPoolLegForBookHybrid / ZeroPoolNetForBookHybrid before #273 shortfall
Book degradation term #273 book_shortfall using realized pool_input / book_input book fill quality Toxic book PoC rejected (hybrid_no_belief_book_far_below_pool_rejected)

Intentional residual (documented, pre-existing): pure-book hybrids (declared_pool_input = 0) skip #307/#273 no-belief metrics; unfilled book remainder may roll to the pool. Documented in L9, pure_book_hybrid_skips_material_pool_floor, and skill docs. Mitigation remains belief_price / router minimum_receive — product boundary, not a regression in this diff.

Frontend / preflight

  • Material-pool and spread helpers mirror on-chain rules; 9ac09ab aligns #273 shortfall gating with realized book output.
  • humanizeTerraTxError additions are static copy only (no XSS / injection surface).

Verification run on review VM

  • cargo test -p dex-common max_spread — pass
  • cargo test -p cl8y-dex-tests hybrid_no_belief — pass
  • npm test -- src/utils/swapMaxSpread.test.ts — pass

Security review: no medium+ findings on this diff.

## Security review (automated) **Commit reviewed:** `9ac09ab1c178c6c808b27eb60241189c84df642d` **Scope:** MR !785 diff vs `main` — `dex_common::max_spread` (#273 book shortfall, #307 material pool leg), pair `execute_swap` / `assert_max_spread`, router declared-split precheck + `SimulateSwapOperations`, frontend `swapMaxSpread` / route preflight, audit doc L9, integration tests. **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none --- ### Re-validation of prior threads - **Prior automated review** (`6cf3d7a`): `FINDINGS: 0` — still holds on the updated head; no new bypass identified. - **Bugbot inline (resolved):** preflight #273 shortfall gated on declared legs while on-chain gates on realized `offer_consumed_by_book`. Fixed in `9ac09ab` (`bookNet > 0n` in `hybridSpreadCmpAndTotal`); contract parity confirmed at `max_spread.rs` (`book_input.is_zero()` uses realized consumption). This was a **preflight false-positive** (UX), not an on-chain slippage bypass — no open medium+ item. ### Contract path (#307 / L9) — reviewed, no exploitable bypass | Control | Location | Attacker input | Result | |---------|----------|----------------|--------| | Early declared-split reject | `validate_declared_hybrid_pool_leg_for_no_belief` in pair `execute_swap` (no `belief_price`) and router `validate_hybrid_declared_split_for_no_belief` | `pool_input`, `book_input` | Rejects when both legs non-zero and `pool_input < 10%` of offer (min 1 raw unit) | | Post-settlement floor | `check_max_spread` on `declared_pool_input` + `pool_net_return` | same + execution outcome | `InsufficientPoolLegForBookHybrid` / `ZeroPoolNetForBookHybrid` before #273 shortfall | | Book degradation term | #273 `book_shortfall` using realized `pool_input` / `book_input` | book fill quality | Toxic book PoC rejected (`hybrid_no_belief_book_far_below_pool_rejected`) | **Intentional residual (documented, pre-existing):** pure-book hybrids (`declared_pool_input = 0`) skip #307/#273 no-belief metrics; unfilled book remainder may roll to the pool. Documented in L9, `pure_book_hybrid_skips_material_pool_floor`, and skill docs. Mitigation remains `belief_price` / router `minimum_receive` — product boundary, not a regression in this diff. ### Frontend / preflight - Material-pool and spread helpers mirror on-chain rules; `9ac09ab` aligns #273 shortfall gating with realized book output. - `humanizeTerraTxError` additions are static copy only (no XSS / injection surface). ### Verification run on review VM - `cargo test -p dex-common max_spread` — pass - `cargo test -p cl8y-dex-tests hybrid_no_belief` — pass - `npm test -- src/utils/swapMaxSpread.test.ts` — pass **Security review: no medium+ findings on this diff.**
ghost1 commented 2026-06-05 10:08:35 +00:00 (Migrated from gitlab.com)

added 1 commit

  • 365e61fb - fix(pair): reject dust pool leg in HybridSimulation quotes

Compare with previous version

added 1 commit <ul><li>365e61fb - fix(pair): reject dust pool leg in HybridSimulation quotes</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/67/diffs?diff_id=1836410293&start_sha=9ac09ab1c178c6c808b27eb60241189c84df642d)
ghost1 commented 2026-06-05 10:08:48 +00:00 (Migrated from gitlab.com)

changed the description

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

Security review (automated)

Commit reviewed: 365e61fbe566b36b6923b199657d40c21243dd27
Scope: MR !785 diff vs main — dex_common::max_spread (#273 book shortfall, #307 material pool leg), pair execute_swap / assert_max_spread / simulate_hybrid_swap_with_fee, router declared-split precheck + SimulateSwapOperations, frontend swapMaxSpread / route preflight / tx error humanization, audit doc L9, integration tests.

Outcome: FINDINGS: 0 medium+

Inline threads: none


Re-validation of prior threads

  • Prior automated review (9ac09ab): FINDINGS: 0 — still holds on updated head.
  • Bugbot inline (resolved): preflight #273 shortfall gated on declared legs while on-chain gates on realized offer_consumed_by_book. Fixed in 9ac09ab (bookNet > 0n in hybridSpreadCmpAndTotal). Preflight false-positive only (UX), not an on-chain slippage bypass — no open medium+ item.
  • Bugbot inline (resolved in this head): HybridSimulation quoted dust-pool hybrids after execute began rejecting them. Fixed in 365e61f by mirroring validate_declared_hybrid_pool_leg_for_no_belief in simulate_hybrid_swap_with_fee (pair contract.rs ~L2145). Sim/execute parity restored for the #307 declared-split floor; quote inflation for reject-on-submit splits is closed.

Contract path (#307 / L9) — reviewed, no exploitable bypass

Control Location Attacker input Result
Early declared-split reject validate_declared_hybrid_pool_leg_for_no_belief in pair execute_swap (no belief_price) and router validate_hybrid_declared_split_for_no_belief pool_input, book_input Rejects when both legs non-zero and pool_input < 10% of offer (min 1 raw unit)
Sim parity (#307 floor) simulate_hybrid_swap_with_fee (same validator) hybrid params on LCD queries Dust declared splits error consistently with execute
Post-settlement floor check_max_spread via declared_pool_input realized + declared legs Requires material declared pool + pool_net_return > 0 before #273 book-shortfall term
#273 book bound check_max_spread no-belief branch pool_input, book_input, fills Shortfall folded into numerator; pure-book (declared_pool_input = 0) unchanged by design (belief / min_receive)

Attacker-controlled swap params remain bounded by L4 split equality, L5 scan/maker caps, and the updated spread math. Integration tests (hybrid_no_belief_dust_pool_leg_rejected, hybrid_no_belief_book_far_below_pool_rejected, hybrid_max_spread_exact_tolerance_succeeds) cover PoC shapes.

Frontend — reviewed, no authz / injection surface

  • swapMaxSpread.ts / swapRoutePreflight.ts mirror on-chain guards; preflight may block more aggressively than chain (conservative).
  • humanizeTerraTxError.ts maps new revert strings to static copy (no HTML injection).

Security review: no medium+ findings on this diff.

## Security review (automated) **Commit reviewed:** `365e61fbe566b36b6923b199657d40c21243dd27` **Scope:** MR !785 diff vs `main` — `dex_common::max_spread` (#273 book shortfall, #307 material pool leg), pair `execute_swap` / `assert_max_spread` / `simulate_hybrid_swap_with_fee`, router declared-split precheck + `SimulateSwapOperations`, frontend `swapMaxSpread` / route preflight / tx error humanization, audit doc L9, integration tests. **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none --- ### Re-validation of prior threads - **Prior automated review** (`9ac09ab`): `FINDINGS: 0` — still holds on updated head. - **Bugbot inline (resolved):** preflight #273 shortfall gated on declared legs while on-chain gates on realized `offer_consumed_by_book`. Fixed in `9ac09ab` (`bookNet > 0n` in `hybridSpreadCmpAndTotal`). Preflight false-positive only (UX), not an on-chain slippage bypass — no open medium+ item. - **Bugbot inline (resolved in this head):** `HybridSimulation` quoted dust-pool hybrids after execute began rejecting them. Fixed in `365e61f` by mirroring `validate_declared_hybrid_pool_leg_for_no_belief` in `simulate_hybrid_swap_with_fee` (pair `contract.rs` ~L2145). Sim/execute parity restored for the #307 declared-split floor; quote inflation for reject-on-submit splits is closed. ### Contract path (#307 / L9) — reviewed, no exploitable bypass | Control | Location | Attacker input | Result | |---------|----------|----------------|--------| | Early declared-split reject | `validate_declared_hybrid_pool_leg_for_no_belief` in pair `execute_swap` (no `belief_price`) and router `validate_hybrid_declared_split_for_no_belief` | `pool_input`, `book_input` | Rejects when both legs non-zero and `pool_input < 10%` of offer (min 1 raw unit) | | Sim parity (#307 floor) | `simulate_hybrid_swap_with_fee` (same validator) | hybrid params on LCD queries | Dust declared splits error consistently with execute | | Post-settlement floor | `check_max_spread` via `declared_pool_input` | realized + declared legs | Requires material declared pool + `pool_net_return > 0` before #273 book-shortfall term | | #273 book bound | `check_max_spread` no-belief branch | `pool_input`, `book_input`, fills | Shortfall folded into numerator; pure-book (`declared_pool_input = 0`) unchanged by design (belief / min_receive) | Attacker-controlled swap params remain bounded by **L4** split equality, **L5** scan/maker caps, and the updated spread math. Integration tests (`hybrid_no_belief_dust_pool_leg_rejected`, `hybrid_no_belief_book_far_below_pool_rejected`, `hybrid_max_spread_exact_tolerance_succeeds`) cover PoC shapes. ### Frontend — reviewed, no authz / injection surface - `swapMaxSpread.ts` / `swapRoutePreflight.ts` mirror on-chain guards; preflight may block more aggressively than chain (conservative). - `humanizeTerraTxError.ts` maps new revert strings to static copy (no HTML injection). **Security review: no medium+ findings on this diff.**
ghost1 commented 2026-06-05 10:11:12 +00:00 (Migrated from gitlab.com)
Stale Security Review comment
Stale Security Review comment
Stale Security Review comment

Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Reviewed by Cursor Bugbot for commit 365e61fbe5. Configure here.

<details> <summary>Stale Security Review comment</summary> <details> <summary>Stale Security Review comment</summary> <details> <summary>Stale Security Review comment</summary> <!-- BUGBOT_REVIEW --> Cursor Bugbot has reviewed your changes and found 1 potential issue.<!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_BEGIN --> <sup>Bugbot Autofix is [ON](https://www.cursor.com/dashboard/bugbot). A cloud agent has been kicked off to fix the reported issue. <!-- BUGBOT_AUTOFIX_AGENT_LINK --></sup> <!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_END --> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 365e61fbe566b36b6923b199657d40c21243dd27. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> </details> </details> </details>
ghost1 commented 2026-06-05 10:11:13 +00:00 (Migrated from gitlab.com)

Hybrid sim ignores belief bypass

Medium Severity

HybridSimulation always runs the no-belief material pool-leg check, while execute_swap skips that validation when belief_price is set. A hybrid with a sub-10% declared pool_input and a book leg can execute on-chain but HybridSimulation / reverse sim queries error, breaking quote parity for belief-guarded swaps.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 365e61fbe5. Configure here.

### Hybrid sim ignores belief bypass **Medium Severity** <!-- DESCRIPTION START --> `HybridSimulation` always runs the no-belief material pool-leg check, while `execute_swap` skips that validation when `belief_price` is set. A hybrid with a sub-10% declared `pool_input` and a book leg can execute on-chain but `HybridSimulation` / reverse sim queries error, breaking quote parity for belief-guarded swaps. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: a79c19cc-96c0-4200-a0d4-32998d59e783 --> <!-- LOCATIONS START smartcontracts/contracts/pair/src/contract.rs#L2144-L2161 smartcontracts/contracts/pair/src/contract.rs#L840-L861 LOCATIONS END --> <details> <summary>Additional Locations (1)</summary> - [`smartcontracts/contracts/pair/src/contract.rs#L840-L861`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-//blob/365e61fbe566b36b6923b199657d40c21243dd27/smartcontracts/contracts/pair/src/contract.rs#L840-L861) </details> <div><a href="https://cursor.com/open?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjlhYjEwYWI1LTAyZjYtNDZjMS04YzA0LWY0ZGU4MWRjMzE0OSIsImVuY3J5cHRpb25LZXkiOiI2Q3k2aUpWcUVHeXpQR0w4NWxPbkdqVl9YYWlTXzlnUHlDazNHM184OTZJIiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIn19" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjlhYjEwYWI1LTAyZjYtNDZjMS04YzA0LWY0ZGU4MWRjMzE0OSIsImVuY3J5cHRpb25LZXkiOiI2Q3k2aUpWcUVHeXpQR0w4NWxPbkdqVl9YYWlTXzlnUHlDazNHM184OTZJIiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIiwicHJOdW1iZXIiOjY3LCJjb21taXRTaGEiOiIzNjVlNjFmYmU1NjZiMzZiNjkyM2IxOTk2NTdkNDBjMjEyNDNkZDI3IiwicHJvdmlkZXIiOiJnaXRsYWIiLCJob3N0bmFtZSI6ImdpdGxhYi5jb20ifX0" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></div> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 365e61fbe566b36b6923b199657d40c21243dd27. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
ghost1 commented 2026-06-05 10:15:46 +00:00 (Migrated from gitlab.com)

changed this line in version 4 of the diff

changed this line in [version 4 of the diff](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/67/diffs?diff_id=1836425202&start_sha=365e61fbe566b36b6923b199657d40c21243dd27#1802471b43a600c2c68314bfa68b35a80c30dd1e_2161_2155)
ghost1 commented 2026-06-05 10:15:46 +00:00 (Migrated from gitlab.com)

added 1 commit

  • f51bf936 - fix(pair): skip no-belief pool-leg guard in hybrid sim when belief_price is set

Compare with previous version

added 1 commit <ul><li>f51bf936 - fix(pair): skip no-belief pool-leg guard in hybrid sim when belief_price is set</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/67/diffs?diff_id=1836425202&start_sha=365e61fbe566b36b6923b199657d40c21243dd27)
ghost1 commented 2026-06-05 10:16:00 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-05 10:18:06 +00:00 (Migrated from gitlab.com)
Stale Security Review comment
Stale Security Review comment

Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Reviewed by Cursor Bugbot for commit f51bf9364e. Configure here.

<details> <summary>Stale Security Review comment</summary> <details> <summary>Stale Security Review comment</summary> <!-- BUGBOT_REVIEW --> Cursor Bugbot has reviewed your changes and found 1 potential issue.<!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_BEGIN --> <sup>Bugbot Autofix is [ON](https://www.cursor.com/dashboard/bugbot). A cloud agent has been kicked off to fix the reported issue. <!-- BUGBOT_AUTOFIX_AGENT_LINK --></sup> <!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_END --> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f51bf9364ee5a6b95425c806af759edb5fabb43d. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> </details> </details>
ghost1 commented 2026-06-05 10:18:07 +00:00 (Migrated from gitlab.com)

Frontend book shortfall misaligned

Medium Severity

Route preflight folds in #273 book shortfall using declared pool_input and book_input, and only when simulated book_return_amount is positive. On-chain check_max_spread uses realized pool offer (pool_leg plus unfilled book) and offer actually consumed by the book, and still adds shortfall when book net is zero. Preflight can understate spread and allow submit when the pair rejects on max_spread.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f51bf9364e. Configure here.

### Frontend book shortfall misaligned **Medium Severity** <!-- DESCRIPTION START --> Route preflight folds in #273 book shortfall using declared `pool_input` and `book_input`, and only when simulated `book_return_amount` is positive. On-chain `check_max_spread` uses realized pool offer (`pool_leg` plus unfilled book) and offer actually consumed by the book, and still adds shortfall when book net is zero. Preflight can understate spread and allow submit when the pair rejects on `max_spread`. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: 767b1804-f8b0-47f3-bdbd-375d7cbb505c --> <!-- LOCATIONS START frontend-dapp/src/utils/swapMaxSpread.ts#L90-L95 frontend-dapp/src/services/terraclassic/swapRoutePreflight.ts#L62-L65 LOCATIONS END --> <details> <summary>Additional Locations (1)</summary> - [`frontend-dapp/src/services/terraclassic/swapRoutePreflight.ts#L62-L65`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-//blob/f51bf9364ee5a6b95425c806af759edb5fabb43d/frontend-dapp/src/services/terraclassic/swapRoutePreflight.ts#L62-L65) </details> <div><a href="https://cursor.com/open?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjcyZWIzM2M1LTM5OTktNDUxYS05YTUwLWY3NDY0YzJhNjg2YyIsImVuY3J5cHRpb25LZXkiOiJ2YzJCTFc4N0JJeGtlbDUxSklkQjJPbTBLajFCZkpjSWpTSnhERmFoQ1JvIiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIn19" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjcyZWIzM2M1LTM5OTktNDUxYS05YTUwLWY3NDY0YzJhNjg2YyIsImVuY3J5cHRpb25LZXkiOiJ2YzJCTFc4N0JJeGtlbDUxSklkQjJPbTBLajFCZkpjSWpTSnhERmFoQ1JvIiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIiwicHJOdW1iZXIiOjY3LCJjb21taXRTaGEiOiJmNTFiZjkzNjRlZTVhNmI5NTQyNWM4MDZhZjc1OWVkYjVmYWJiNDNkIiwicHJvdmlkZXIiOiJnaXRsYWIiLCJob3N0bmFtZSI6ImdpdGxhYi5jb20ifX0" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></div> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f51bf9364ee5a6b95425c806af759edb5fabb43d. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
PlasticDigits commented 2026-06-05 10:18:34 +00:00 (Migrated from gitlab.com)

Security review (automated)

Commit reviewed: f51bf9364ee5a6b95425c806af759edb5fabb43d
Scope: MR !785 diff vs main — dex_common::max_spread (#273 book shortfall, #307 material pool leg), pair execute_swap / assert_max_spread / simulate_hybrid_swap_with_fee (incl. optional query belief_price), router declared-split precheck + SimulateSwapOperations, frontend swapMaxSpread / route preflight, factory #276/#277, indexer IPv6 rate-limit #282, audit doc L9, integration tests.

Outcome: FINDINGS: 0 medium+

Inline threads: none (new). Prior Bugbot threads on this MR are resolved on this SHA — see re-validation below.


Re-validation of prior threads

Prior finding Status on f51bf93
Preflight #273 shortfall used declared book_input when sim returned zero book net Fixed — hybridSpreadCmpAndTotal gates shortfall on bookNet > 0n (9ac09ab).
HybridSimulation quoted dust-pool hybrids rejected by execute Fixed — validate_declared_hybrid_pool_leg_for_no_belief in simulate_hybrid_swap_with_fee when belief_price is unset (365e61f).
Sim/execute parity when belief_price skips #307 guard Fixed — query accepts optional belief_price and mirrors execute skip (f51bf93).

Contract path (#307 / L9)

  • Early reject (no belief): validate_declared_hybrid_pool_leg_for_no_belief in pair execute_swap and router validate_hybrid_declared_split_for_no_belief.
  • Post-settlement: check_max_spread enforces declared_pool_input ≥ 10% of offer (min 1 unit) and pool_net > 0 before #273 book-shortfall; uses realized pool_input / offer_consumed_by_book for the shortfall ratio.
  • Attacker-controlled inputs (pool_input, book_input, max_spread, book fills) remain bounded by L4 split equality, L5 scan/maker caps, and updated spread math; PoC shapes covered by hybrid_no_belief_dust_pool_leg_rejected and hybrid_no_belief_book_far_below_pool_rejected.
  • Intentional residual (documented, not introduced): pure-book hybrids (declared_pool_input = 0) stay outside #273/#307 no-belief metric; takers must use belief_price / minimum_receive. Pre-existing product boundary per L9.

Other security-relevant hunks

Area Assessment
Query belief_price on HybridSimulation / reverse sim Read-only; mirrors execute guard skip — no authz or fund-movement impact.
Factory #276 (uluna refund when fee = 0) Reduces stuck-funds risk; no authz change.
Factory #277 (SetLpAdminAll / batch; decouple from UpdateConfig) Governance-only; bounded gas — reduces governance-tx DoS.
Indexer #282 (IPv6 /64 rate-limit key) Hardens rate limiting; no spoofable forwarded-header extractor added.

Security review: no medium+ findings on this diff.

## Security review (automated) **Commit reviewed:** `f51bf9364ee5a6b95425c806af759edb5fabb43d` **Scope:** MR !785 diff vs `main` — `dex_common::max_spread` (#273 book shortfall, #307 material pool leg), pair `execute_swap` / `assert_max_spread` / `simulate_hybrid_swap_with_fee` (incl. optional query `belief_price`), router declared-split precheck + `SimulateSwapOperations`, frontend `swapMaxSpread` / route preflight, factory #276/#277, indexer IPv6 rate-limit #282, audit doc L9, integration tests. **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none (new). Prior Bugbot threads on this MR are **resolved** on this SHA — see re-validation below. --- ### Re-validation of prior threads | Prior finding | Status on `f51bf93` | |---------------|---------------------| | Preflight #273 shortfall used declared `book_input` when sim returned zero book net | **Fixed** — `hybridSpreadCmpAndTotal` gates shortfall on `bookNet > 0n` (`9ac09ab`). | | `HybridSimulation` quoted dust-pool hybrids rejected by execute | **Fixed** — `validate_declared_hybrid_pool_leg_for_no_belief` in `simulate_hybrid_swap_with_fee` when `belief_price` is unset (`365e61f`). | | Sim/execute parity when `belief_price` skips #307 guard | **Fixed** — query accepts optional `belief_price` and mirrors execute skip (`f51bf93`). | ### Contract path (#307 / L9) - **Early reject (no belief):** `validate_declared_hybrid_pool_leg_for_no_belief` in pair `execute_swap` and router `validate_hybrid_declared_split_for_no_belief`. - **Post-settlement:** `check_max_spread` enforces `declared_pool_input ≥ 10%` of offer (min 1 unit) and `pool_net > 0` before #273 book-shortfall; uses realized `pool_input` / `offer_consumed_by_book` for the shortfall ratio. - **Attacker-controlled inputs** (`pool_input`, `book_input`, `max_spread`, book fills) remain bounded by L4 split equality, L5 scan/maker caps, and updated spread math; PoC shapes covered by `hybrid_no_belief_dust_pool_leg_rejected` and `hybrid_no_belief_book_far_below_pool_rejected`. - **Intentional residual (documented, not introduced):** pure-book hybrids (`declared_pool_input = 0`) stay outside #273/#307 no-belief metric; takers must use `belief_price` / `minimum_receive`. Pre-existing product boundary per L9. ### Other security-relevant hunks | Area | Assessment | |------|------------| | Query `belief_price` on `HybridSimulation` / reverse sim | Read-only; mirrors execute guard skip — no authz or fund-movement impact. | | Factory #276 (uluna refund when fee = 0) | Reduces stuck-funds risk; no authz change. | | Factory #277 (`SetLpAdminAll` / batch; decouple from `UpdateConfig`) | Governance-only; bounded gas — reduces governance-tx DoS. | | Indexer #282 (IPv6 /64 rate-limit key) | Hardens rate limiting; no spoofable forwarded-header extractor added. | Security review: **no medium+ findings** on this diff.
ghost1 commented 2026-06-05 10:21:12 +00:00 (Migrated from gitlab.com)

added 1 commit

  • c1f69030 - fix(frontend): align hybrid max-spread preflight with on-chain #273 legs

Compare with previous version

added 1 commit <ul><li>c1f69030 - fix(frontend): align hybrid max-spread preflight with on-chain #273 legs</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/67/diffs?diff_id=1836435779&start_sha=f51bf9364ee5a6b95425c806af759edb5fabb43d)
ghost1 commented 2026-06-05 10:21:26 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-05 10:23:03 +00:00 (Migrated from gitlab.com)
Stale Security Review comment

Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Reviewed by Cursor Bugbot for commit c1f6903039cb226a7550f4397637e7c99ac4e6ac. Configure here.

<details> <summary>Stale Security Review comment</summary> <!-- BUGBOT_REVIEW --> Cursor Bugbot has reviewed your changes and found 1 potential issue.<!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_BEGIN --> <sup>Bugbot Autofix is [ON](https://www.cursor.com/dashboard/bugbot). A cloud agent has been kicked off to fix the reported issue. <!-- BUGBOT_AUTOFIX_AGENT_LINK --></sup> <!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_END --> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c1f6903039cb226a7550f4397637e7c99ac4e6ac. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> </details>
ghost1 commented 2026-06-05 10:23:04 +00:00 (Migrated from gitlab.com)

Preflight miscomputes hybrid book legs

Medium Severity

hybridMaxSpreadRealizedLegs does not match pair assert_max_spread, which uses realized offer_consumed_by_book and pool_leg + (book_leg − consumed) for #273. When the book only partially fills, preflight can omit book shortfall or use the wrong ratio, so route spread preflight may disagree with on-chain max_spread.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c1f6903039cb226a7550f4397637e7c99ac4e6ac. Configure here.

### Preflight miscomputes hybrid book legs **Medium Severity** <!-- DESCRIPTION START --> `hybridMaxSpreadRealizedLegs` does not match pair `assert_max_spread`, which uses realized `offer_consumed_by_book` and `pool_leg + (book_leg − consumed)` for #273. When the book only partially fills, preflight can omit book shortfall or use the wrong ratio, so route spread preflight may disagree with on-chain `max_spread`. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: ccd0d5c2-0c13-4aa7-814f-eb0db34b4ab8 --> <!-- LOCATIONS START frontend-dapp/src/utils/swapMaxSpread.ts#L62-L77 frontend-dapp/src/services/terraclassic/swapRoutePreflight.ts#L64-L67 LOCATIONS END --> <details> <summary>Additional Locations (1)</summary> - [`frontend-dapp/src/services/terraclassic/swapRoutePreflight.ts#L64-L67`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-//blob/c1f6903039cb226a7550f4397637e7c99ac4e6ac/frontend-dapp/src/services/terraclassic/swapRoutePreflight.ts#L64-L67) </details> <div><a href="https://cursor.com/open?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjNkN2VmNDE3LTgyZTYtNGExNi1iMjBjLTNiYTZhZmIzMDBlMyIsImVuY3J5cHRpb25LZXkiOiI4RFBuVjFLQmNsY0FjYVgzd2g3aVpCeVBwYml2dVR5eVhiQW9NNERyOUZvIiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIn19" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjNkN2VmNDE3LTgyZTYtNGExNi1iMjBjLTNiYTZhZmIzMDBlMyIsImVuY3J5cHRpb25LZXkiOiI4RFBuVjFLQmNsY0FjYVgzd2g3aVpCeVBwYml2dVR5eVhiQW9NNERyOUZvIiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIiwicHJOdW1iZXIiOjY3LCJjb21taXRTaGEiOiJjMWY2OTAzMDM5Y2IyMjZhNzU1MGY0Mzk3NjM3ZTdjOTlhYzRlNmFjIiwicHJvdmlkZXIiOiJnaXRsYWIiLCJob3N0bmFtZSI6ImdpdGxhYi5jb20ifX0" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></div> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c1f6903039cb226a7550f4397637e7c99ac4e6ac. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
PlasticDigits commented 2026-06-05 10:24:02 +00:00 (Migrated from gitlab.com)

Security review (automated)

Commit reviewed: c1f6903039cb226a7550f4397637e7c99ac4e6ac
Scope: MR !785 diff vs main — dex_common::max_spread (#273 book shortfall, #307 material pool leg), pair execute_swap / assert_max_spread / HybridSimulation (optional belief_price), router declared-split precheck + SimulateSwapOperations, frontend swapMaxSpread / route preflight, audit doc L9, integration tests.

Outcome: FINDINGS: 0 medium+

Inline threads: none


Re-validation of prior threads

Prior finding Status on c1f6903
Preflight #273 shortfall gated on declared legs / empty book (Bugbot 7e14db6d) Fixed in 9ac09ab; superseded by realized-leg alignment in c1f6903 (hybridMaxSpreadRealizedLegs)
HybridSimulation skipped dust-pool guard (Bugbot c8571e37) Fixed in 365e61f
HybridSimulation ignored belief_price bypass (Bugbot a79c19cc) Fixed in f51bf93
Frontend book shortfall used declared legs / positive book net gate (Bugbot 767b1804) Fixed in c1f6903 — preflight now mirrors on-chain realized pool_input / book_input, including zero book net with unfilled remainder

No remaining exploitable path identified on the latest head.


Contract path (#307 / L9) — reviewed, no bypass

  • Early reject: validate_declared_hybrid_pool_leg_for_no_belief in pair execute_swap (when belief_price unset) and router validate_hybrid_declared_split_for_no_belief on swap start and each hop reply.
  • Post-settlement reject: check_max_spread enforces declared pool ≥10% of offer (min 1 unit) and non-zero pool_net_return before #273 book shortfall; maps to InsufficientPoolLegForHybrid / ZeroPoolNetForHybrid.
  • Attacker-controlled inputs (pool_input, book_input, max_spread, book fills) remain bounded by L4 split equality, L5 scan/maker caps, and the updated spread math. Integration tests hybrid_no_belief_dust_pool_leg_rejected and hybrid_no_belief_book_far_below_pool_rejected pass on this SHA.
  • Intentional residual (documented, not introduced): pure-book hybrids (declared_pool_input = 0) remain outside the #273/#307 no-belief metric; unfilled book remainder may still hit the pool. Documented in max_spread.rs, audit L9, and pure_book_hybrid_skips_material_pool_floor. Users must rely on belief_price / router minimum_receive — pre-existing product boundary.

Frontend / quote parity

  • Route preflight (swapRoutePreflight.ts) applies #307 material-pool guards and #273 shortfall via hybridMaxSpreadRealizedLegs, aligned with pair assert_max_spread inputs after c1f6903.
  • HybridSimulation / reverse sim honor optional belief_price for the material-pool guard, matching execute.

Not reported (per policy)

Governance-trusted operations, stylistic issues, pre-existing pure-book / optional-belief_price slippage model, and indexer route-solver paths outside this diff.


Security review: no medium+ findings on this diff.

## Security review (automated) **Commit reviewed:** `c1f6903039cb226a7550f4397637e7c99ac4e6ac` **Scope:** MR !785 diff vs `main` — `dex_common::max_spread` (#273 book shortfall, #307 material pool leg), pair `execute_swap` / `assert_max_spread` / `HybridSimulation` (optional `belief_price`), router declared-split precheck + `SimulateSwapOperations`, frontend `swapMaxSpread` / route preflight, audit doc L9, integration tests. **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none --- ### Re-validation of prior threads | Prior finding | Status on `c1f6903` | |---------------|---------------------| | Preflight #273 shortfall gated on declared legs / empty book (Bugbot `7e14db6d`) | **Fixed** in `9ac09ab`; superseded by realized-leg alignment in `c1f6903` (`hybridMaxSpreadRealizedLegs`) | | `HybridSimulation` skipped dust-pool guard (Bugbot `c8571e37`) | **Fixed** in `365e61f` | | `HybridSimulation` ignored `belief_price` bypass (Bugbot `a79c19cc`) | **Fixed** in `f51bf93` | | Frontend book shortfall used declared legs / positive book net gate (Bugbot `767b1804`) | **Fixed** in `c1f6903` — preflight now mirrors on-chain realized `pool_input` / `book_input`, including zero book net with unfilled remainder | No remaining exploitable path identified on the latest head. --- ### Contract path (#307 / L9) — reviewed, no bypass - **Early reject:** `validate_declared_hybrid_pool_leg_for_no_belief` in pair `execute_swap` (when `belief_price` unset) and router `validate_hybrid_declared_split_for_no_belief` on swap start and each hop reply. - **Post-settlement reject:** `check_max_spread` enforces declared pool ≥10% of offer (min 1 unit) and non-zero `pool_net_return` before #273 book shortfall; maps to `InsufficientPoolLegForHybrid` / `ZeroPoolNetForHybrid`. - **Attacker-controlled inputs** (`pool_input`, `book_input`, `max_spread`, book fills) remain bounded by **L4** split equality, **L5** scan/maker caps, and the updated spread math. Integration tests `hybrid_no_belief_dust_pool_leg_rejected` and `hybrid_no_belief_book_far_below_pool_rejected` pass on this SHA. - **Intentional residual (documented, not introduced):** pure-book hybrids (`declared_pool_input = 0`) remain outside the #273/#307 no-belief metric; unfilled book remainder may still hit the pool. Documented in `max_spread.rs`, audit **L9**, and `pure_book_hybrid_skips_material_pool_floor`. Users must rely on `belief_price` / router `minimum_receive` — pre-existing product boundary. ### Frontend / quote parity - Route preflight (`swapRoutePreflight.ts`) applies #307 material-pool guards and #273 shortfall via `hybridMaxSpreadRealizedLegs`, aligned with pair `assert_max_spread` inputs after `c1f6903`. - `HybridSimulation` / reverse sim honor optional `belief_price` for the material-pool guard, matching execute. ### Not reported (per policy) Governance-trusted operations, stylistic issues, pre-existing pure-book / optional-`belief_price` slippage model, and indexer route-solver paths outside this diff. --- Security review: **no medium+ findings** on this diff.
ghost1 commented 2026-06-05 10:26:21 +00:00 (Migrated from gitlab.com)

added 1 commit

  • e1ae0596 - fix(frontend): align hybrid max-spread preflight with on-chain #273 legs

Compare with previous version

added 1 commit <ul><li>e1ae0596 - fix(frontend): align hybrid max-spread preflight with on-chain #273 legs</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/67/diffs?diff_id=1836446663&start_sha=c1f6903039cb226a7550f4397637e7c99ac4e6ac)
ghost1 commented 2026-06-05 10:26:40 +00:00 (Migrated from gitlab.com)

changed the description

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

Security review (automated)

Commit reviewed: e1ae059653f509cf6682b3f23101cf6f1e0da4d7
Scope: MR !785 diff vs main — dex_common::max_spread (#273 book shortfall, #307 material pool leg), pair execute_swap / assert_max_spread / HybridSimulation (optional query belief_price, limit_book_offer_consumed), router declared-split precheck + SimulateSwapOperations, frontend swapMaxSpread / swapRoutePreflight, audit doc L9, integration tests. Re-checked prior automated/Bugbot threads on this MR.

Outcome: FINDINGS: 0 medium+

Inline threads: none


Re-validation of prior threads

Prior thread Status on e1ae059
Hybrid sim ignores belief_price bypass Fixed — simulate_hybrid_swap_with_fee / HybridSimulation query accept optional belief_price and skip validate_declared_hybrid_pool_leg_for_no_belief when set (parity with execute_swap).
Hybrid sim skips material-pool guard Fixed — same validation on forward sim path as execute.
Frontend book shortfall / empty-book / realized-leg mismatch Fixed — hybridMaxSpreadRealizedLegs + limit_book_offer_consumed from hybrid sim; preflight uses realized legs for #273; book shortfall when book_net = 0 covered in unit tests.
Preflight miscomputes hybrid book legs (partial fill) Fixed in latest commit — swapRoutePreflight.ts reads limit_book_offer_consumed; fallback to declared book_input only when sim omits the field and book output is non-zero (errs strict vs chain).

Contract path (#307 / L9) — no exploitable bypass found

  • Early reject: validate_declared_hybrid_pool_leg_for_no_belief on pair execute_swap and router validate_hybrid_declared_split_for_no_belief when belief_price is unset and both pool_input and book_input are non-zero.
  • Post-settlement reject: check_max_spread enforces declared 10% pool floor, pool_net_return > 0, then #273 book shortfall using realized pool_input (pool_leg + book_leg − offer_consumed_by_book) and offer_consumed_by_book.
  • Attacker-controlled splits remain bounded by L4 (pool_input + book_input == amount), L5 scan/maker caps, and spread math; integration tests hybrid_no_belief_dust_pool_leg_rejected and hybrid_no_belief_book_far_below_pool_rejected match the historical PoC shapes.
  • Documented residual (pre-existing product boundary, not introduced here): pure-book hybrids (declared_pool_input = 0) are outside the #273/#307 no-belief metric; unfilled book remainder may still route to the pool. Mitigation remains belief_price / router minimum_receive — see L9 in docs/contracts-security-audit.md.

Frontend / indexer

  • Preflight is client-side UX only; mis-estimation cannot weaken on-chain checks. Latest diff aligns spread math with pair assert_max_spread.
  • Indexer IPv6 /64 rate-limit keying (#282) and limit clamps are hardening, not new attack surface.

Other diff hunks (factory #276/#277, broadcast scope, QA scripts)

  • Factory pair-creation fee requires attached uluna ≥ governance fee; governance-only admin unchanged (F2, P8).
  • No secret leakage or authz expansion identified in touched frontend broadcast helpers.

Security review: no medium+ findings on this diff.

## Security review (automated) **Commit reviewed:** `e1ae059653f509cf6682b3f23101cf6f1e0da4d7` **Scope:** MR !785 diff vs `main` — `dex_common::max_spread` (#273 book shortfall, #307 material pool leg), pair `execute_swap` / `assert_max_spread` / `HybridSimulation` (optional query `belief_price`, `limit_book_offer_consumed`), router declared-split precheck + `SimulateSwapOperations`, frontend `swapMaxSpread` / `swapRoutePreflight`, audit doc L9, integration tests. Re-checked prior automated/Bugbot threads on this MR. **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none --- ### Re-validation of prior threads | Prior thread | Status on `e1ae059` | |--------------|---------------------| | Hybrid sim ignores `belief_price` bypass | **Fixed** — `simulate_hybrid_swap_with_fee` / `HybridSimulation` query accept optional `belief_price` and skip `validate_declared_hybrid_pool_leg_for_no_belief` when set (parity with `execute_swap`). | | Hybrid sim skips material-pool guard | **Fixed** — same validation on forward sim path as execute. | | Frontend book shortfall / empty-book / realized-leg mismatch | **Fixed** — `hybridMaxSpreadRealizedLegs` + `limit_book_offer_consumed` from hybrid sim; preflight uses realized legs for #273; book shortfall when `book_net = 0` covered in unit tests. | | Preflight miscomputes hybrid book legs (partial fill) | **Fixed** in latest commit — `swapRoutePreflight.ts` reads `limit_book_offer_consumed`; fallback to declared `book_input` only when sim omits the field and book output is non-zero (errs strict vs chain). | ### Contract path (#307 / L9) — no exploitable bypass found - **Early reject:** `validate_declared_hybrid_pool_leg_for_no_belief` on pair `execute_swap` and router `validate_hybrid_declared_split_for_no_belief` when `belief_price` is unset and both `pool_input` and `book_input` are non-zero. - **Post-settlement reject:** `check_max_spread` enforces declared 10% pool floor, `pool_net_return > 0`, then #273 book shortfall using realized `pool_input` (`pool_leg + book_leg − offer_consumed_by_book`) and `offer_consumed_by_book`. - Attacker-controlled splits remain bounded by **L4** (`pool_input + book_input == amount`), **L5** scan/maker caps, and spread math; integration tests `hybrid_no_belief_dust_pool_leg_rejected` and `hybrid_no_belief_book_far_below_pool_rejected` match the historical PoC shapes. - **Documented residual (pre-existing product boundary, not introduced here):** pure-book hybrids (`declared_pool_input = 0`) are outside the #273/#307 no-belief metric; unfilled book remainder may still route to the pool. Mitigation remains `belief_price` / router `minimum_receive` — see L9 in `docs/contracts-security-audit.md`. ### Frontend / indexer - Preflight is client-side UX only; mis-estimation cannot weaken on-chain checks. Latest diff aligns spread math with pair `assert_max_spread`. - Indexer IPv6 `/64` rate-limit keying (#282) and limit clamps are hardening, not new attack surface. ### Other diff hunks (factory #276/#277, broadcast scope, QA scripts) - Factory pair-creation fee requires attached uluna ≥ governance fee; governance-only admin unchanged (**F2**, **P8**). - No secret leakage or authz expansion identified in touched frontend broadcast helpers. **Security review: no medium+ findings on this diff.**
ghost1 commented 2026-06-05 10:28:36 +00:00 (Migrated from gitlab.com)

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Reviewed by Cursor Bugbot for commit e1ae059653. Configure here.

<!-- BUGBOT_REVIEW --> Cursor Bugbot has reviewed your changes and found 1 potential issue. <!-- BUGBOT_FIX_ALL --> <a href="https://cursor.com/open?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9BTExfSU5fQ1VSU09SIiwiZGF0YSI6eyJyZWRpc0tleSI6ImJ1Z2JvdC1tdWx0aTo2ZjI4YzhlYS0zMjk3LTRhNDYtOWUyYi1lOTZiMzQ1MWYwNzAiLCJlbmNyeXB0aW9uS2V5IjoibVFTOGMxbDFROTQ2b2NZYUlPMTNDR0k1S1RkdkNtVGZQSzNLUWV0ZFRBRSIsImJyYW5jaCI6ImN1cnNvci9naXRsYWItaXNzdWUtd29ya2Zsb3ctZGMwNiIsInJlcG9Pd25lciI6IlBsYXN0aWNEaWdpdHMiLCJyZXBvTmFtZSI6ImNsOHktZGV4LXRlcnJhY2xhc3NpYyJ9fQ" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix All in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a> <!-- /BUGBOT_FIX_ALL --> <!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_BEGIN --> <sup>Bugbot Autofix is [ON](https://www.cursor.com/dashboard/bugbot). A cloud agent has been kicked off to fix the reported issue. <!-- BUGBOT_AUTOFIX_AGENT_LINK --></sup> <!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_END --> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e1ae059653f509cf6682b3f23101cf6f1e0da4d7. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
ghost1 commented 2026-06-05 10:28:37 +00:00 (Migrated from gitlab.com)

Preflight throws on dust pool

Medium Severity

When hybridNoBeliefMaterialPoolReject flags an insufficient declared pool leg, preflight still calls simulateHybridSwap, which now rejects the same split on-chain. The thrown LCD error aborts preflightSwapRouteSpread instead of returning anyHopExceedsMaxSpread: true, so slippage gating and quote flows that expect a structured preflight result break for invalid hybrid routes.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e1ae059653. Configure here.

### Preflight throws on dust pool **Medium Severity** <!-- DESCRIPTION START --> When `hybridNoBeliefMaterialPoolReject` flags an insufficient declared pool leg, preflight still calls `simulateHybridSwap`, which now rejects the same split on-chain. The thrown LCD error aborts `preflightSwapRouteSpread` instead of returning `anyHopExceedsMaxSpread: true`, so slippage gating and quote flows that expect a structured preflight result break for invalid hybrid routes. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: 5d1ac711-f32d-41da-8ed1-e60f0f9e39b5 --> <!-- LOCATIONS START frontend-dapp/src/services/terraclassic/swapRoutePreflight.ts#L49-L54 LOCATIONS END --> <div><a href="https://cursor.com/open?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjIzNjFlY2U0LTRlMzAtNGU5NC05MDBiLWY1Nzc0MzFmNTAyNiIsImVuY3J5cHRpb25LZXkiOiJDdU9QMmNkblhUUHUzcUFZQVhqaEFPT3E3elB6ZS1OMGpvQ0tMdUZNWTNnIiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIn19" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjIzNjFlY2U0LTRlMzAtNGU5NC05MDBiLWY1Nzc0MzFmNTAyNiIsImVuY3J5cHRpb25LZXkiOiJDdU9QMmNkblhUUHUzcUFZQVhqaEFPT3E3elB6ZS1OMGpvQ0tMdUZNWTNnIiwiYnJhbmNoIjoiY3Vyc29yL2dpdGxhYi1pc3N1ZS13b3JrZmxvdy1kYzA2IiwicmVwb093bmVyIjoiUGxhc3RpY0RpZ2l0cyIsInJlcG9OYW1lIjoiY2w4eS1kZXgtdGVycmFjbGFzc2ljIiwicHJOdW1iZXIiOjY3LCJjb21taXRTaGEiOiJlMWFlMDU5NjUzZjUwOWNmNjY4MmIzZjIzMTAxY2Y2ZjFlMGRhNGQ3IiwicHJvdmlkZXIiOiJnaXRsYWIiLCJob3N0bmFtZSI6ImdpdGxhYi5jb20ifX0" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></div> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e1ae059653f509cf6682b3f23101cf6f1e0da4d7. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
ghost1 commented 2026-06-05 10:34:20 +00:00 (Migrated from gitlab.com)

added 1 commit

  • 72dcd562 - fix: skip hybrid simulation when declared pool leg is dust

Compare with previous version

added 1 commit <ul><li>72dcd562 - fix: skip hybrid simulation when declared pool leg is dust</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/67/diffs?diff_id=1836465627&start_sha=e1ae059653f509cf6682b3f23101cf6f1e0da4d7)
ghost1 commented 2026-06-05 10:34:36 +00:00 (Migrated from gitlab.com)

changed the description

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

Security review (automated)

Commit reviewed: 72dcd5625011f188387e5a329270221cc8d69a2a
Scope: MR !785 diff vs main — dex_common::max_spread (#273 book shortfall, #307 material pool leg), pair execute_swap / assert_max_spread / HybridSimulation (optional query belief_price, limit_book_offer_consumed), router declared-split precheck + SimulateSwapOperations, frontend swapMaxSpread / swapRoutePreflight, audit doc L9, integration tests.

Outcome: FINDINGS: 0 medium+

Inline threads: none


Re-validation of prior threads

Prior thread Status on 72dcd56
Preflight #273 shortfall used declared legs / empty-book gate (Bugbot 7e14db6d) Fixed — realized-leg alignment via hybridMaxSpreadRealizedLegs + limit_book_offer_consumed
HybridSimulation quoted dust-pool hybrids rejected by execute (Bugbot c8571e37) Fixed — validate_declared_hybrid_pool_leg_for_no_belief on sim path
Sim/execute parity when belief_price skips #307 guard (Bugbot a79c19cc) Fixed — optional query belief_price mirrors execute skip
Frontend book shortfall / partial-fill leg mismatch (Bugbot 767b1804, ccd0d5c2) Fixed — preflight uses realized pool_input / offer_consumed_by_book
Preflight throws on dust pool instead of structured reject (Bugbot 5d1ac711) Fixed in 72dcd56 — early break before simulateHybridSwap when insufficient_pool_leg

No remaining exploitable on-chain path identified on this head.


Contract path (#307 / L9) — reviewed, no bypass

  • Early reject (no belief): validate_declared_hybrid_pool_leg_for_no_belief in pair execute_swap and router validate_hybrid_declared_split_for_no_belief when both pool_input and book_input are non-zero.
  • Post-settlement reject: check_max_spread enforces declared 10% pool floor and pool_net_return > 0 before #273 book shortfall; uses realized pool_input (pool_leg + book_leg − offer_consumed_by_book) and offer_consumed_by_book.
  • Attacker-controlled inputs (pool_input, book_input, max_spread, book fills) remain bounded by L4 split equality, L5 scan/maker caps, and updated spread math. Integration tests hybrid_no_belief_dust_pool_leg_rejected and hybrid_no_belief_book_far_below_pool_rejected pass on this SHA.
  • Documented residual (pre-existing product boundary, not introduced here): pure-book hybrids (declared_pool_input = 0) stay outside the #273/#307 no-belief metric; unfilled book remainder may still route to the pool. Mitigation remains belief_price / router minimum_receive — see L9 in docs/contracts-security-audit.md.

Frontend / preflight

  • Client-side spread gating only; cannot weaken on-chain checks. Latest commit aligns dust-pool preflight with on-chain rejection without throwing.

Verification run on review VM

  • cargo test -p dex-common max_spread — pass
  • cargo test -p cl8y-dex-tests hybrid_no_belief — pass

Security review: no medium+ findings on this diff.

## Security review (automated) **Commit reviewed:** `72dcd5625011f188387e5a329270221cc8d69a2a` **Scope:** MR !785 diff vs `main` — `dex_common::max_spread` (#273 book shortfall, #307 material pool leg), pair `execute_swap` / `assert_max_spread` / `HybridSimulation` (optional query `belief_price`, `limit_book_offer_consumed`), router declared-split precheck + `SimulateSwapOperations`, frontend `swapMaxSpread` / `swapRoutePreflight`, audit doc L9, integration tests. **Outcome:** `FINDINGS: 0` medium+ **Inline threads:** none --- ### Re-validation of prior threads | Prior thread | Status on `72dcd56` | |--------------|---------------------| | Preflight #273 shortfall used declared legs / empty-book gate (Bugbot `7e14db6d`) | **Fixed** — realized-leg alignment via `hybridMaxSpreadRealizedLegs` + `limit_book_offer_consumed` | | `HybridSimulation` quoted dust-pool hybrids rejected by execute (Bugbot `c8571e37`) | **Fixed** — `validate_declared_hybrid_pool_leg_for_no_belief` on sim path | | Sim/execute parity when `belief_price` skips #307 guard (Bugbot `a79c19cc`) | **Fixed** — optional query `belief_price` mirrors execute skip | | Frontend book shortfall / partial-fill leg mismatch (Bugbot `767b1804`, `ccd0d5c2`) | **Fixed** — preflight uses realized `pool_input` / `offer_consumed_by_book` | | Preflight throws on dust pool instead of structured reject (Bugbot `5d1ac711`) | **Fixed** in `72dcd56` — early `break` before `simulateHybridSwap` when `insufficient_pool_leg` | No remaining exploitable on-chain path identified on this head. --- ### Contract path (#307 / L9) — reviewed, no bypass - **Early reject (no belief):** `validate_declared_hybrid_pool_leg_for_no_belief` in pair `execute_swap` and router `validate_hybrid_declared_split_for_no_belief` when both `pool_input` and `book_input` are non-zero. - **Post-settlement reject:** `check_max_spread` enforces declared 10% pool floor and `pool_net_return > 0` before #273 book shortfall; uses realized `pool_input` (`pool_leg + book_leg − offer_consumed_by_book`) and `offer_consumed_by_book`. - **Attacker-controlled inputs** (`pool_input`, `book_input`, `max_spread`, book fills) remain bounded by **L4** split equality, **L5** scan/maker caps, and updated spread math. Integration tests `hybrid_no_belief_dust_pool_leg_rejected` and `hybrid_no_belief_book_far_below_pool_rejected` pass on this SHA. - **Documented residual (pre-existing product boundary, not introduced here):** pure-book hybrids (`declared_pool_input = 0`) stay outside the #273/#307 no-belief metric; unfilled book remainder may still route to the pool. Mitigation remains `belief_price` / router `minimum_receive` — see L9 in `docs/contracts-security-audit.md`. ### Frontend / preflight - Client-side spread gating only; cannot weaken on-chain checks. Latest commit aligns dust-pool preflight with on-chain rejection without throwing. ### Verification run on review VM - `cargo test -p dex-common max_spread` — pass - `cargo test -p cl8y-dex-tests hybrid_no_belief` — pass **Security review: no medium+ findings on this diff.**
PlasticDigits commented 2026-06-05 10:53:43 +00:00 (Migrated from gitlab.com)

resolved all threads

resolved all threads
PlasticDigits commented 2026-06-05 10:54:19 +00:00 (Migrated from gitlab.com)

mentioned in commit 27e7a61846

mentioned in commit 27e7a6184680327a325ef93a83eb04855c0edce4
PlasticDigits (Migrated from gitlab.com) merged commit 27e7a61846 into main 2026-06-05 10:54:19 +00:00
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!785
No description provided.