Verify #377: Harden CosmWasm hooks and CW20/hook ops policy #907

Merged
PlasticDigits merged 2 commits from verify/issue-377-hook-hardening into main 2026-06-14 06:53:26 +00:00
PlasticDigits commented 2026-06-14 03:03:41 +00:00 (Migrated from gitlab.com)

Summary

Implements GitLab #377 remediation for security findings H-01, H-02, H-03, and I-02:

  • H-01: docs/runbooks/cw20-whitelist-ops.md forbids fee-on-transfer CW20 templates; launch checklist cross-links; scripts/qa/verify-cw20-code-ids.sh for pre-whitelist LCD CodeInfo checks.
  • H-02: docs/runbooks/hook-registration.md — audit requirement, allowlist hygiene, intentional swap-blocking policy.
  • H-03: lp-burn-hook requires pair == info.sender and on-chain LP token validation; adversarial spoof test now expects rejection.
  • I-02: Pair queries HookQueryMsg::ComputeSwapFee and deducts tax/burn fees from swap output before AfterSwap; tax hook collects with zero hook treasury balance.

Verification checklist

Acceptance item Command / result
Fee-on-transfer prohibition + GDEX/TerraPort checklist docs/runbooks/cw20-whitelist-ops.md; bash scripts/qa/verify-cw20-code-ids.sh --lcd <lcd> <code_id>
Hook registration playbook docs/runbooks/hook-registration.md; linked from docs/security-model.md and launch checklist
LP burn hook rejects spoofed pair cd smartcontracts && cargo test lp_burn_hook_rejects_spoofed → PASS
Tax/burn charge from swap I/O cd smartcontracts && cargo test test_tax_hook_collects_from_swap_with_zero_hook_balance → PASS
cargo test adversarial PASS (7 tests)
Hook unit/integration tests cargo test tax_hook, cargo test burn_hook, cargo test lp_burn_hook → PASS
Full contract suite make test-contracts → PASS
fee_on_transfer_creates_reserve_imbalance still demonstrates risk PASS
lp_burn_hook_accepts_spoofed_pair renamed → must fail lp_burn_hook_rejects_spoofed_pair_when_spoofer_allowlisted → PASS
swap_fails_atomically_when_allowlisted_hook_reverts PASS
Docs cross-linked security-model.md, contracts-security-audit.md, hooks/README.md, launch checklist

Test plan

  • cd smartcontracts && cargo test adversarial
  • cd smartcontracts && cargo test -p cl8y-dex-lp-burn-hook (0 unit; integration via cl8y-dex-tests)
  • cd smartcontracts && cargo test tax_hook burn_hook lp_burn_hook
  • make test-contracts
  • Manual review: docs/runbooks/hook-registration.md, docs/runbooks/cw20-whitelist-ops.md, docs/security-model.md

Follow-ups

  • Rebuild optimized wasm and bump artifact checksums before mainnet hook/pair upgrades (pair settlement change is a wasm migration).
  • Add make verify-issue-377 wrapper script if CI should gate this bundle explicitly.

Note

High Risk
Changes pair swap settlement and requires optimized wasm migration; incorrect rollout could alter user receive amounts or break swaps with registered fee hooks.

Overview
GitLab #377 closes audit items H-01–H-03 and I-02 with operator runbooks, pair settlement changes, and stricter LP-burn hook checks.

Operations (H-01, H-02): Documents forbid fee-on-transfer CW20 templates and tie launch checklist to scripts/verify-cw20-code-ids.sh LCD CodeInfo checks. New docs/runbooks/hook-registration.md covers hook audit, allowlist hygiene, and intentional swap-blocking when an allowlisted hook reverts; cross-links land in security-model.md, contracts-security-audit.md, and the hooks README.

Pair settlement (I-02): Swap flow now uses shared dex-common::hook_settlement: at execute time the pair queries tax/burn hooks via GetConfig, deducts bps from ask-token output, emits CW20 transfers (tax → recipient, burn → hook), and pays the trader net return before AfterSwap — so fees no longer depend on pre-funded hook treasuries. This is a pair wasm migration before mainnet upgrade.

LP-burn hook (H-03): AfterSwap requires pair == info.sender, on-chain Pair {} validation, and matching liquidity_token; UpdateAllowedPairs only accepts real pair contracts. Adversarial coverage flips from accepting spoofed pair to lp_burn_hook_rejects_spoofed_pair_when_spoofer_allowlisted.

Regression tests cover tax collection with zero hook balance, adversarial hook suites, and updated audit matrix rows H2 / I2.

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

## Summary Implements GitLab #377 remediation for security findings H-01, H-02, H-03, and I-02: - **H-01:** `docs/runbooks/cw20-whitelist-ops.md` forbids fee-on-transfer CW20 templates; launch checklist cross-links; `scripts/qa/verify-cw20-code-ids.sh` for pre-whitelist LCD `CodeInfo` checks. - **H-02:** `docs/runbooks/hook-registration.md` — audit requirement, allowlist hygiene, intentional swap-blocking policy. - **H-03:** lp-burn-hook requires `pair == info.sender` and on-chain LP token validation; adversarial spoof test now expects rejection. - **I-02:** Pair queries `HookQueryMsg::ComputeSwapFee` and deducts tax/burn fees from swap output before `AfterSwap`; tax hook collects with zero hook treasury balance. ## Verification checklist | Acceptance item | Command / result | |-----------------|------------------| | Fee-on-transfer prohibition + GDEX/TerraPort checklist | `docs/runbooks/cw20-whitelist-ops.md`; `bash scripts/qa/verify-cw20-code-ids.sh --lcd <lcd> <code_id>` | | Hook registration playbook | `docs/runbooks/hook-registration.md`; linked from `docs/security-model.md` and launch checklist | | LP burn hook rejects spoofed `pair` | `cd smartcontracts && cargo test lp_burn_hook_rejects_spoofed` → PASS | | Tax/burn charge from swap I/O | `cd smartcontracts && cargo test test_tax_hook_collects_from_swap_with_zero_hook_balance` → PASS | | `cargo test adversarial` | PASS (7 tests) | | Hook unit/integration tests | `cargo test tax_hook`, `cargo test burn_hook`, `cargo test lp_burn_hook` → PASS | | Full contract suite | `make test-contracts` → PASS | | `fee_on_transfer_creates_reserve_imbalance` still demonstrates risk | PASS | | `lp_burn_hook_accepts_spoofed_pair` renamed → must fail | `lp_burn_hook_rejects_spoofed_pair_when_spoofer_allowlisted` → PASS | | `swap_fails_atomically_when_allowlisted_hook_reverts` | PASS | | Docs cross-linked | `security-model.md`, `contracts-security-audit.md`, `hooks/README.md`, launch checklist | ## Test plan - [x] `cd smartcontracts && cargo test adversarial` - [x] `cd smartcontracts && cargo test -p cl8y-dex-lp-burn-hook` (0 unit; integration via cl8y-dex-tests) - [x] `cd smartcontracts && cargo test tax_hook burn_hook lp_burn_hook` - [x] `make test-contracts` - [x] Manual review: `docs/runbooks/hook-registration.md`, `docs/runbooks/cw20-whitelist-ops.md`, `docs/security-model.md` ## Follow-ups - Rebuild optimized wasm and bump artifact checksums before mainnet hook/pair upgrades (pair settlement change is a wasm migration). - Add `make verify-issue-377` wrapper script if CI should gate this bundle explicitly. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Changes pair swap settlement and requires optimized wasm migration; incorrect rollout could alter user receive amounts or break swaps with registered fee hooks. > > **Overview** > **GitLab #377** closes audit items **H-01–H-03** and **I-02** with operator runbooks, pair settlement changes, and stricter LP-burn hook checks. > > **Operations (H-01, H-02):** Documents forbid fee-on-transfer CW20 templates and tie launch checklist to **`scripts/verify-cw20-code-ids.sh`** LCD `CodeInfo` checks. New **`docs/runbooks/hook-registration.md`** covers hook audit, allowlist hygiene, and intentional swap-blocking when an allowlisted hook reverts; cross-links land in **`security-model.md`**, **`contracts-security-audit.md`**, and the hooks README. > > **Pair settlement (I-02):** Swap flow now uses shared **`dex-common::hook_settlement`**: at execute time the pair queries tax/burn hooks via **`GetConfig`**, deducts bps from **ask-token output**, emits CW20 transfers (tax → recipient, burn → hook), and pays the trader **net return** before **`AfterSwap`** — so fees no longer depend on pre-funded hook treasuries. This is a **pair wasm migration** before mainnet upgrade. > > **LP-burn hook (H-03):** **`AfterSwap`** requires **`pair == info.sender`**, on-chain **`Pair {}`** validation, and matching **`liquidity_token`**; **`UpdateAllowedPairs`** only accepts real pair contracts. Adversarial coverage flips from accepting spoofed **`pair`** to **`lp_burn_hook_rejects_spoofed_pair_when_spoofer_allowlisted`**. > > Regression tests cover tax collection with zero hook balance, adversarial hook suites, and updated audit matrix rows **H2** / **I2**. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5154e7bed725c0b5ddcc6d4715212a0f07fb236b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
ghost1 commented 2026-06-14 03:03:50 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-14 03:03:59 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
ghost1 commented 2026-06-14 03:04:57 +00:00 (Migrated from gitlab.com)

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fb7dad99ab. Configure here.

<!-- BUGBOT_REVIEW --> Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues. <!-- BUGBOT_FIX_ALL --> <a href="https://cursor.com/open?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9BTExfSU5fQ1VSU09SIiwiZGF0YSI6eyJyZWRpc0tleSI6ImJ1Z2JvdC1tdWx0aToxYWJhZjcyMC03ZmVkLTRiMjYtOTYwZi1mMmExYjJkODg1NmEiLCJlbmNyeXB0aW9uS2V5IjoiN1VXNGliaE1fWVpXT1BhQWJxVk9aX2g5SFJwcVRnS3VHeWVvODQyR1Y2byIsImJyYW5jaCI6InZlcmlmeS9pc3N1ZS0zNzctaG9vay1oYXJkZW5pbmciLCJyZXBvT3duZXIiOiJQbGFzdGljRGlnaXRzIiwicmVwb05hbWUiOiJjbDh5LWRleC10ZXJyYWNsYXNzaWMifX0" 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 OFF. To automatically fix reported issues with cloud agents, enable autofix in the [Cursor dashboard](https://www.cursor.com/dashboard/bugbot).</sup> <!-- BUGBOT_AUTOFIX_REVIEW_FOOTNOTE_END --> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit fb7dad99ab88e7989185698cd5b4060a7c1ab428. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
ghost1 commented 2026-06-14 03:04:58 +00:00 (Migrated from gitlab.com)

Simulation omits hook fees

Medium Severity

HybridSimulation still returns return_amount as the full book-plus-pool net (total_out) and never queries registered hooks for ComputeSwapFee. Off-chain quotes and UIs using simulation will overstate what traders actually receive after pair settlement deducts tax/burn hook fees.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit fb7dad99ab. Configure here.

### Simulation omits hook fees **Medium Severity** <!-- DESCRIPTION START --> `HybridSimulation` still returns `return_amount` as the full book-plus-pool net (`total_out`) and never queries registered hooks for `ComputeSwapFee`. Off-chain quotes and UIs using simulation will overstate what traders actually receive after pair settlement deducts tax/burn hook fees. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: 5d4d726c-a81f-4ebd-83d4-3d9d36e2d082 --> <!-- LOCATIONS START smartcontracts/contracts/pair/src/contract.rs#L2402-L2406 LOCATIONS END --> <div><a href="https://cursor.com/open?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OmM2MzlhYjEwLTc4NDktNGFmNy1hNGVmLTA3MzhlOTBkNGRjNCIsImVuY3J5cHRpb25LZXkiOiJkdE9XUkZtdXVYajNCXzlhaXhUTWhHdkxrTlVaLUtseldEVE5zSlBNbkowIiwiYnJhbmNoIjoidmVyaWZ5L2lzc3VlLTM3Ny1ob29rLWhhcmRlbmluZyIsInJlcG9Pd25lciI6IlBsYXN0aWNEaWdpdHMiLCJyZXBvTmFtZSI6ImNsOHktZGV4LXRlcnJhY2xhc3NpYyJ9fQ" 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=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OmM2MzlhYjEwLTc4NDktNGFmNy1hNGVmLTA3MzhlOTBkNGRjNCIsImVuY3J5cHRpb25LZXkiOiJkdE9XUkZtdXVYajNCXzlhaXhUTWhHdkxrTlVaLUtseldEVE5zSlBNbkowIiwiYnJhbmNoIjoidmVyaWZ5L2lzc3VlLTM3Ny1ob29rLWhhcmRlbmluZyIsInJlcG9Pd25lciI6IlBsYXN0aWNEaWdpdHMiLCJyZXBvTmFtZSI6ImNsOHktZGV4LXRlcnJhY2xhc3NpYyIsInByTnVtYmVyIjoxODksImNvbW1pdFNoYSI6ImZiN2RhZDk5YWI4OGU3OTg5MTg1Njk4Y2Q1YjQwNjBhN2MxYWI0MjgiLCJwcm92aWRlciI6ImdpdGxhYiIsImhvc3RuYW1lIjoiZ2l0bGFiLmNvbSJ9fQ" 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 fb7dad99ab88e7989185698cd5b4060a7c1ab428. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
ghost1 commented 2026-06-14 03:04:58 +00:00 (Migrated from gitlab.com)

Min return ignores hook fees

Medium Severity

min_return is enforced against total_return before hook settlement, while the receiver’s CW20 transfer uses user_return (total_return minus hook fees). A swap can succeed when gross output meets the floor but the trader receives less than min_return. The swap return_amount wasm attribute still reports the gross total, not the net credited amount.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit fb7dad99ab. Configure here.

### Min return ignores hook fees **Medium Severity** <!-- DESCRIPTION START --> `min_return` is enforced against `total_return` before hook settlement, while the receiver’s CW20 transfer uses `user_return` (`total_return` minus hook fees). A swap can succeed when gross output meets the floor but the trader receives less than `min_return`. The swap `return_amount` wasm attribute still reports the gross total, not the net credited amount. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: ee635640-dd15-4e03-a25a-0ea5694640ae --> <!-- LOCATIONS START smartcontracts/contracts/pair/src/contract.rs#L1147-L1155 smartcontracts/contracts/pair/src/contract.rs#L1267-L1268 LOCATIONS END --> <details> <summary>Additional Locations (1)</summary> - [`smartcontracts/contracts/pair/src/contract.rs#L1267-L1268`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-//blob/fb7dad99ab88e7989185698cd5b4060a7c1ab428/smartcontracts/contracts/pair/src/contract.rs#L1267-L1268) </details> <div><a href="https://cursor.com/open?link=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjE5ZTFiZTcyLWU4ODEtNGE1MC1hNzY4LTgyZmYzMzU4MTE4ZiIsImVuY3J5cHRpb25LZXkiOiJTNmJjMFRRSXp6NmpQNHk5R09STFVjUklLUzFWV3hqTGR4QUN2WTk5NzFRIiwiYnJhbmNoIjoidmVyaWZ5L2lzc3VlLTM3Ny1ob29rLWhhcmRlbmluZyIsInJlcG9Pd25lciI6IlBsYXN0aWNEaWdpdHMiLCJyZXBvTmFtZSI6ImNsOHktZGV4LXRlcnJhY2xhc3NpYyJ9fQ" 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=eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjE5ZTFiZTcyLWU4ODEtNGE1MC1hNzY4LTgyZmYzMzU4MTE4ZiIsImVuY3J5cHRpb25LZXkiOiJTNmJjMFRRSXp6NmpQNHk5R09STFVjUklLUzFWV3hqTGR4QUN2WTk5NzFRIiwiYnJhbmNoIjoidmVyaWZ5L2lzc3VlLTM3Ny1ob29rLWhhcmRlbmluZyIsInJlcG9Pd25lciI6IlBsYXN0aWNEaWdpdHMiLCJyZXBvTmFtZSI6ImNsOHktZGV4LXRlcnJhY2xhc3NpYyIsInByTnVtYmVyIjoxODksImNvbW1pdFNoYSI6ImZiN2RhZDk5YWI4OGU3OTg5MTg1Njk4Y2Q1YjQwNjBhN2MxYWI0MjgiLCJwcm92aWRlciI6ImdpdGxhYiIsImhvc3RuYW1lIjoiZ2l0bGFiLmNvbSJ9fQ" 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 fb7dad99ab88e7989185698cd5b4060a7c1ab428. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
PlasticDigits commented 2026-06-14 03:06:11 +00:00 (Migrated from gitlab.com)

Security review — MR !907

Commit reviewed: fb7dad99ab88e7989185698cd5b4060a7c1ab428

Scope: Pair swap settlement (ComputeSwapFee / hook fee transfers), tax/burn/lp-burn hook hardening, adversarial spoof tests, ops runbooks (cw20-whitelist-ops.md, hook-registration.md), verify-cw20-code-ids.sh.

Outcome: FINDINGS: 0 medium+ — Security review: no medium+ findings on this diff.

Inline threads: none

Summary

Reviewed attacker-controlled inputs through real sinks on the modified paths:

Area Result
lp-burn-hook H-03 pair == info.sender plus on-chain Pair LP-token validation closes the allowlisted-spoofer AfterSwap.pair forgery path; spoof tests now expect rejection.
Pair ComputeSwapFee settlement Fees summed with checked_add; user_return = total_return - total_hook_fees uses checked_sub (reverts if hooks over-claim). settlement_recipient required when fee_amount > 0. Hook registration remains factory-governance-only (SetPairHooks → UpdateHooks).
Tax/burn hooks ComputeSwapFee and settlement math are consistent; pair transfers fees before AfterSwap, removing pre-funded treasury subsidy (I-02).
Ops scripts / docs Operator tooling only; no production attack surface.

Note (below medium): min_return is still asserted against gross total_return before hook-fee deduction, so direct pair swaps on hooked pools may deliver user_return < min_return when fees are non-zero. This is a slippage-floor correctness gap for integrators, not an unprivileged theft path (hooks are governance-registered; fee rates are hook-configured).

No block:security label applied.

## Security review — MR !907 **Commit reviewed:** `fb7dad99ab88e7989185698cd5b4060a7c1ab428` **Scope:** Pair swap settlement (`ComputeSwapFee` / hook fee transfers), tax/burn/lp-burn hook hardening, adversarial spoof tests, ops runbooks (`cw20-whitelist-ops.md`, `hook-registration.md`), `verify-cw20-code-ids.sh`. **Outcome:** `FINDINGS: 0` medium+ — **Security review: no medium+ findings on this diff.** **Inline threads:** none ### Summary Reviewed attacker-controlled inputs through real sinks on the modified paths: | Area | Result | |------|--------| | **lp-burn-hook H-03** | `pair == info.sender` plus on-chain `Pair` LP-token validation closes the allowlisted-spoofer `AfterSwap.pair` forgery path; spoof tests now expect rejection. | | **Pair `ComputeSwapFee` settlement** | Fees summed with `checked_add`; `user_return = total_return - total_hook_fees` uses `checked_sub` (reverts if hooks over-claim). `settlement_recipient` required when `fee_amount > 0`. Hook registration remains factory-governance-only (`SetPairHooks` → `UpdateHooks`). | | **Tax/burn hooks** | `ComputeSwapFee` and settlement math are consistent; pair transfers fees before `AfterSwap`, removing pre-funded treasury subsidy (I-02). | | **Ops scripts / docs** | Operator tooling only; no production attack surface. | **Note (below medium):** `min_return` is still asserted against gross `total_return` before hook-fee deduction, so direct pair swaps on hooked pools may deliver `user_return < min_return` when fees are non-zero. This is a slippage-floor correctness gap for integrators, not an unprivileged theft path (hooks are governance-registered; fee rates are hook-configured). No `block:security` label applied.
PlasticDigits commented 2026-06-14 05:42:09 +00:00 (Migrated from gitlab.com)

changed this line in version 1 of the diff

changed this line in version 1 of the diff
PlasticDigits commented 2026-06-14 05:42:09 +00:00 (Migrated from gitlab.com)

changed this line in version 1 of the diff

changed this line in version 1 of the diff
PlasticDigits commented 2026-06-14 05:42:09 +00:00 (Migrated from gitlab.com)

added 30 commits

  • fb7dad99...171aa60b - 29 commits from branch main
  • 5154e7be - Merge main into verify/issue-377-hook-hardening.

Compare with previous version

added 30 commits <ul><li>fb7dad99...171aa60b - 29 commits from branch <code>main</code></li><li>5154e7be - Merge main into verify/issue-377-hook-hardening.</li></ul> [Compare with previous version](/PlasticDigits/cl8y-dex-terraclassic/-/merge_requests/189/diffs?diff_id=1850595861&start_sha=fb7dad99ab88e7989185698cd5b4060a7c1ab428)
PlasticDigits commented 2026-06-14 05:42:11 +00:00 (Migrated from gitlab.com)

Conflict resolution

Merged main into verify/issue-377-hook-hardening and resolved 11 conflicted files.

Approach: main already landed #377 via hook_settlement (collect_fee_hook_deductions / GetConfig), cw20-whitelist-policy.md, and the main hook-registration.md playbook. Conflicts were resolved by taking main for all overlapping code and docs.

Dropped MR-only duplicates: ComputeSwapFee query path (pair + hook msg/query), docs/runbooks/cw20-whitelist-ops.md, and scripts/qa/verify-cw20-code-ids.sh (superseded by scripts/verify-cw20-code-ids.sh on main).

Sanity checks: cargo test adversarial and hook-related tests pass locally.

## Conflict resolution Merged `main` into `verify/issue-377-hook-hardening` and resolved 11 conflicted files. **Approach:** `main` already landed #377 via `hook_settlement` (`collect_fee_hook_deductions` / `GetConfig`), `cw20-whitelist-policy.md`, and the main `hook-registration.md` playbook. Conflicts were resolved by taking `main` for all overlapping code and docs. **Dropped MR-only duplicates:** `ComputeSwapFee` query path (pair + hook msg/query), `docs/runbooks/cw20-whitelist-ops.md`, and `scripts/qa/verify-cw20-code-ids.sh` (superseded by `scripts/verify-cw20-code-ids.sh` on `main`). **Sanity checks:** `cargo test adversarial` and hook-related tests pass locally.
ghost1 commented 2026-06-14 05:42:23 +00:00 (Migrated from gitlab.com)

resolved all threads

resolved all threads
ghost1 commented 2026-06-14 05:42:29 +00:00 (Migrated from gitlab.com)

changed the description

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

Security review — MR !907

Commit reviewed: 5154e7bed725c0b5ddcc6d4715212a0f07fb236b

Scope: Post-merge verification of #377 hook/CW20 hardening (pair hook_settlement fee deductions, tax/burn/lp-burn hooks, adversarial spoof tests, ops runbooks/scripts). Latest MR diff version has 0 changed files (branch tree matches main after conflict resolution per !907 discussion).

Outcome: FINDINGS: 0 medium+ — Security review: no medium+ findings on this diff.

Inline threads: none (empty MR diff; prior Bugbot threads on min_return / HybridSimulation resolved or below threshold)

Summary

Re-traced attacker-controlled inputs on the security-relevant paths now on main (identical to this MR head):

Area Result
lp-burn-hook (H-03) pair == info.sender, on-chain Pair {} query, and LP-token match block allowlisted-spoofer AfterSwap.pair forgery; UpdateAllowedPairs rejects non-pair contracts (lp_burn_hook_rejects_spoofed_pair_when_spoofer_allowlisted).
Pair hook settlement (I-02) collect_fee_hook_deductions queries hook GetConfig; fees summed with checked_add; net_return = total_return - hook_fee_total with HookFeeExceedsReturn guard; user transfer uses net_return. Hook registration remains factory-governance-only (SetPairHooks → UpdateHooks).
min_return (prior Bugbot) Fixed on main: slippage floor enforced against net_return after hook-fee deduction (pair/src/contract.rs ~L1180–L1186), not gross total_return.
Tax/burn hooks Pair forwards ask-token fee slice before AfterSwap; tax hook callback is event-only; burn hook burns transferred settlement balance. tax_hook_collects_from_swap_flow_with_zero_treasury_balance passes.
Ops scripts / docs Operator LCD CodeInfo tooling only; no production attack surface.

Below medium (not reported): HybridSimulation / router multi-hop simulation still quote gross return_amount without hook-fee deduction. This can mislead off-chain quotes when governance-registered fee hooks are active, but there is no unprivileged fund-extraction path (hooks are governance-gated; execute-time min_return uses net output).

No block:security label applied.

## Security review — MR !907 **Commit reviewed:** `5154e7bed725c0b5ddcc6d4715212a0f07fb236b` **Scope:** Post-merge verification of #377 hook/CW20 hardening (pair `hook_settlement` fee deductions, tax/burn/lp-burn hooks, adversarial spoof tests, ops runbooks/scripts). Latest MR diff version has **0 changed files** (branch tree matches `main` after conflict resolution per !907 discussion). **Outcome:** `FINDINGS: 0` medium+ — **Security review: no medium+ findings on this diff.** **Inline threads:** none (empty MR diff; prior Bugbot threads on `min_return` / `HybridSimulation` resolved or below threshold) ### Summary Re-traced attacker-controlled inputs on the security-relevant paths now on `main` (identical to this MR head): | Area | Result | |------|--------| | **lp-burn-hook (H-03)** | `pair == info.sender`, on-chain `Pair {}` query, and LP-token match block allowlisted-spoofer `AfterSwap.pair` forgery; `UpdateAllowedPairs` rejects non-pair contracts (`lp_burn_hook_rejects_spoofed_pair_when_spoofer_allowlisted`). | | **Pair hook settlement (I-02)** | `collect_fee_hook_deductions` queries hook `GetConfig`; fees summed with `checked_add`; `net_return = total_return - hook_fee_total` with `HookFeeExceedsReturn` guard; user transfer uses `net_return`. Hook registration remains factory-governance-only (`SetPairHooks` → `UpdateHooks`). | | **`min_return` (prior Bugbot)** | **Fixed on `main`:** slippage floor enforced against `net_return` after hook-fee deduction (`pair/src/contract.rs` ~L1180–L1186), not gross `total_return`. | | **Tax/burn hooks** | Pair forwards ask-token fee slice before `AfterSwap`; tax hook callback is event-only; burn hook burns transferred settlement balance. `tax_hook_collects_from_swap_flow_with_zero_treasury_balance` passes. | | **Ops scripts / docs** | Operator LCD `CodeInfo` tooling only; no production attack surface. | **Below medium (not reported):** `HybridSimulation` / router multi-hop simulation still quote gross `return_amount` without hook-fee deduction. This can mislead off-chain quotes when governance-registered fee hooks are active, but there is no unprivileged fund-extraction path (hooks are governance-gated; execute-time `min_return` uses net output). No `block:security` label applied.
PlasticDigits commented 2026-06-14 06:53:26 +00:00 (Migrated from gitlab.com)

mentioned in commit a7f2691ee7

mentioned in commit a7f2691ee7b1ff4e1a4462c2dcd9e1c25b42c082
PlasticDigits (Migrated from gitlab.com) merged commit a7f2691ee7 into main 2026-06-14 06:53:26 +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!907
No description provided.