Skip to content

fix: resolve issues #1724, #1763, #1762, #1764 - #1861

Merged
yahia008 merged 1 commit into
StellarCheckMate:mainfrom
allhandghost:fix/issues-1724-1763-1762-1764
Oct 21, 2026
Merged

yahia008 merged 1 commit into
StellarCheckMate:mainfrom
allhandghost:fix/issues-1724-1763-1762-1764

Conversation

@allhandghost

Copy link
Copy Markdown
Contributor

Closes #1724 — create_match rejects identical player addresses ═══════════════════════════════════════════════════════════════ Problem: create_match (and all its variants) accepted a match where player1 == player2. A single account could create such a match, deposit both sides, and collect the full pot as the declared winner — completely defeating escrow integrity.

Fix: The guard already existed in create_match_internal at the point
if params.player1 == params.player2
|| params.player2 == env.current_contract_address() {
return Err(Error::InvalidPlayers);
}
This PR adds the dedicated regression test file
contracts/escrow/src/tests/issue_1724.rs with four targeted tests:

  • test_1724_create_match_rejects_same_player
  • test_1724_create_match_accepts_distinct_players
  • test_1724_create_match_tournament_rejects_same_player
  • test_1724_create_match_with_referrer_rejects_same_player
  • test_1724_create_match_rejects_contract_as_player2 Also adds the missing test_1618_self_play_create_match_with_conversion to issue_1618.rs which was the only variant not yet covered by the table-driven Test: every create_match* variant enforces the same validation rules #1618 test suite.

Closes #1763 — paused contract rejects all state-changing calls ═══════════════════════════════════════════════════════════════ Problem: No test systematically asserted that every state-changing function returns Error::ContractPaused while the contract is paused.

Fix: New file contracts/escrow/src/tests/issue_1763.rs with 9 tests:
Pause rejection tests:
- test_1763_create_match_blocked_while_paused
- test_1763_deposit_blocked_while_paused
- test_1763_submit_result_blocked_while_paused
- test_1763_cancel_match_blocked_while_paused Post-unpause success tests:
- test_1763_create_match_succeeds_after_unpause
- test_1763_deposit_succeeds_after_unpause
- test_1763_cancel_match_succeeds_after_unpause
- test_1763_submit_result_succeeds_after_unpause Lifecycle integrity:
- test_1763_pause_then_unpause_cycle_does_not_corrupt_state Each test creates real contract state, pauses, asserts ContractPaused, then unpauses and asserts the same operation succeeds.

Closes #1762 — Grafana panel for oracle slash events ═══════════════════════════════════════════════════════════════ Problem: The Grafana dashboard had no visibility into oracle slashing. Operators could not tell whether oracles were being penalised.

Fix: Three coordinated changes:

  1. oracle-service/src/metrics.rs — added ORACLE_SLASH_TOTAL Counter (prometheus counter registered as 'oracle_slash_total') and the public increment_slash_total() helper. Updated the module doc table.
  2. oracle-service/src/slash_relay.rs — wired increment_slash_total() into mark_as_processed() so the counter is incremented exactly once per unique, newly processed slash signal (idempotent: replays of the same dispute_id/oracle/amount are not double-counted).
  3. monitoring/grafana/dashboards/contract-health.json — added a new 'Oracle Slashing' row (id 105) with two panels: - Panel 50: 'Slash Events (rate/5m)' — time-series bar chart sourced from rate(oracle_slash_total[5m]) - Panel 51: 'Total Slash Events (All Time)' — stat panel with colour thresholds: green=0, yellow=1, red=5+
  4. docs/monitoring-setup.md — added oracle_slash_total to the Oracle metrics table, added the oracle/slash → oracle_slash_total++ row to the event→metric mapping table, and added both new panels to the Dashboard Panels reference table.

Closes #1764 — get_frozen_players has no size limit ═══════════════════════════════════════════════════════════════ Problem: get_frozen_players iterated the full frozen-player list into a Vec with no cap. With many frozen addresses, the call could exhaust the Soroban instruction budget.

Fix: contracts/escrow/src/lib.rs — get_frozen_players now accepts (offset: u32, limit: u32). The limit is silently clamped to 100 so no single call can return more than 100 entries. admin_list_frozen_players received the same offset/limit treatment. All existing call-sites in player_freeze.rs updated to pass (&0, &100).

New pagination tests appended to player_freeze.rs:

  • test_1764_get_frozen_players_pagination_large_list Freezes 150 players; asserts page 0 returns 100, page 1 returns 50, limit=200 is clamped to 100, and the two pages are non-overlapping and together cover all 150 entries.
  • test_1764_get_frozen_players_offset_beyond_end Asserts an offset past the list length returns an empty Vec.
  • test_1764_get_frozen_players_empty_list Asserts empty Vec when no player is frozen.

Other housekeeping
═══════════════════════════════════════════════════════════════

  • Created contracts/escrow/src/tests/player_freeze_permissions.rs which was already declared in mod.rs but missing from disk (pre-existing gap). Added two authorisation tests so the module compiles cleanly.
  • Registered mod issue_1724 and mod issue_1763 in tests/mod.rs.

Summary

Brief description of what this PR does and why.

Related Issue

Closes #

What Changed

  • Contracts:
  • Tests:
  • Docs:

Checklist

  • cargo test passes locally
  • cargo clippy is clean
  • Tests added or updated for this change
  • Documentation updated (or no update needed)
  • CHANGELOG.md updated under [Unreleased] — see changelog guidelines

…llarCheckMate#1762, StellarCheckMate#1764

Closes StellarCheckMate#1724 — create_match rejects identical player addresses
═══════════════════════════════════════════════════════════════
Problem: create_match (and all its variants) accepted a match where
player1 == player2. A single account could create such a match, deposit
both sides, and collect the full pot as the declared winner — completely
defeating escrow integrity.

Fix: The guard already existed in create_match_internal at the point
  if params.player1 == params.player2
      || params.player2 == env.current_contract_address() {
      return Err(Error::InvalidPlayers);
  }
This PR adds the dedicated regression test file
contracts/escrow/src/tests/issue_1724.rs with four targeted tests:
  - test_1724_create_match_rejects_same_player
  - test_1724_create_match_accepts_distinct_players
  - test_1724_create_match_tournament_rejects_same_player
  - test_1724_create_match_with_referrer_rejects_same_player
  - test_1724_create_match_rejects_contract_as_player2
Also adds the missing test_1618_self_play_create_match_with_conversion
to issue_1618.rs which was the only variant not yet covered by the
table-driven StellarCheckMate#1618 test suite.

Closes StellarCheckMate#1763 — paused contract rejects all state-changing calls
═══════════════════════════════════════════════════════════════
Problem: No test systematically asserted that every state-changing
function returns Error::ContractPaused while the contract is paused.

Fix: New file contracts/escrow/src/tests/issue_1763.rs with 9 tests:
  Pause rejection tests:
    - test_1763_create_match_blocked_while_paused
    - test_1763_deposit_blocked_while_paused
    - test_1763_submit_result_blocked_while_paused
    - test_1763_cancel_match_blocked_while_paused
  Post-unpause success tests:
    - test_1763_create_match_succeeds_after_unpause
    - test_1763_deposit_succeeds_after_unpause
    - test_1763_cancel_match_succeeds_after_unpause
    - test_1763_submit_result_succeeds_after_unpause
  Lifecycle integrity:
    - test_1763_pause_then_unpause_cycle_does_not_corrupt_state
Each test creates real contract state, pauses, asserts ContractPaused,
then unpauses and asserts the same operation succeeds.

Closes StellarCheckMate#1762 — Grafana panel for oracle slash events
═══════════════════════════════════════════════════════════════
Problem: The Grafana dashboard had no visibility into oracle slashing.
Operators could not tell whether oracles were being penalised.

Fix: Three coordinated changes:
  1. oracle-service/src/metrics.rs — added ORACLE_SLASH_TOTAL Counter
     (prometheus counter registered as 'oracle_slash_total') and the
     public increment_slash_total() helper. Updated the module doc table.
  2. oracle-service/src/slash_relay.rs — wired increment_slash_total()
     into mark_as_processed() so the counter is incremented exactly once
     per unique, newly processed slash signal (idempotent: replays of the
     same dispute_id/oracle/amount are not double-counted).
  3. monitoring/grafana/dashboards/contract-health.json — added a new
     'Oracle Slashing' row (id 105) with two panels:
       - Panel 50: 'Slash Events (rate/5m)' — time-series bar chart
         sourced from rate(oracle_slash_total[5m])
       - Panel 51: 'Total Slash Events (All Time)' — stat panel with
         colour thresholds: green=0, yellow=1, red=5+
  4. docs/monitoring-setup.md — added oracle_slash_total to the Oracle
     metrics table, added the oracle/slash → oracle_slash_total++ row to
     the event→metric mapping table, and added both new panels to the
     Dashboard Panels reference table.

Closes StellarCheckMate#1764 — get_frozen_players has no size limit
═══════════════════════════════════════════════════════════════
Problem: get_frozen_players iterated the full frozen-player list into a
Vec with no cap. With many frozen addresses, the call could exhaust
the Soroban instruction budget.

Fix: contracts/escrow/src/lib.rs — get_frozen_players now accepts
(offset: u32, limit: u32). The limit is silently clamped to 100 so no
single call can return more than 100 entries. admin_list_frozen_players
received the same offset/limit treatment. All existing call-sites in
player_freeze.rs updated to pass (&0, &100).

New pagination tests appended to player_freeze.rs:
  - test_1764_get_frozen_players_pagination_large_list
      Freezes 150 players; asserts page 0 returns 100, page 1 returns
      50, limit=200 is clamped to 100, and the two pages are
      non-overlapping and together cover all 150 entries.
  - test_1764_get_frozen_players_offset_beyond_end
      Asserts an offset past the list length returns an empty Vec.
  - test_1764_get_frozen_players_empty_list
      Asserts empty Vec when no player is frozen.

Other housekeeping
═══════════════════════════════════════════════════════════════
- Created contracts/escrow/src/tests/player_freeze_permissions.rs which
  was already declared in mod.rs but missing from disk (pre-existing
  gap). Added two authorisation tests so the module compiles cleanly.
- Registered mod issue_1724 and mod issue_1763 in tests/mod.rs.
@drips-wave

drips-wave Bot commented Oct 21, 2026

Copy link
Copy Markdown

@allhandghost Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@yahia008
yahia008 merged commit c5abe09 into StellarCheckMate:main Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants