From df498e0b340f5edbe8fa7b14bfc8aa6f05645d5c Mon Sep 17 00:00:00 2001 From: afurious <120628710+afurious@users.noreply.github.com> Date: Wed, 27 May 2026 14:30:27 +0000 Subject: [PATCH] Add tests for issue #8, #12, and timeout access control - test_pending_match_appears_in_get_active_matches: pending match (no deposits) must be present in get_active_matches index (#8) - test_create_match_with_contract_address_as_player1_returns_invalid_players: contract address as player1 returns InvalidPlayers (#12) - test_set_match_timeout_from_non_admin_returns_unauthorized: non-admin caller to set_match_timeout returns Unauthorized - Add contract-address-as-player guard in create_match (lib.rs) --- contracts/escrow/src/lib.rs | 5 +++ contracts/escrow/src/tests.rs | 72 +++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/contracts/escrow/src/lib.rs b/contracts/escrow/src/lib.rs index 47b793d..5bb6d15 100644 --- a/contracts/escrow/src/lib.rs +++ b/contracts/escrow/src/lib.rs @@ -146,6 +146,11 @@ impl EscrowContract { return Err(Error::InvalidPlayers); } + let self_addr = env.current_contract_address(); + if player1 == self_addr || player2 == self_addr { + return Err(Error::InvalidPlayers); + } + if game_id.is_empty() { return Err(Error::InvalidGameId); } diff --git a/contracts/escrow/src/tests.rs b/contracts/escrow/src/tests.rs index 1ae8522..f1d8b8e 100644 --- a/contracts/escrow/src/tests.rs +++ b/contracts/escrow/src/tests.rs @@ -2681,3 +2681,75 @@ fn test_expire_match_refunds_both_players_when_both_deposited_but_still_pending( assert_eq!(token_client.balance(&player1) - p1_balance_before, 100); assert_eq!(token_client.balance(&player2) - p2_balance_before, 100); } + +// ── Issue #8 — pending match (no deposits) appears in get_active_matches ───── +// +// `create_match` appends to the `ActiveMatches` index immediately, so a match +// in `Pending` state (before any deposits) must be visible in the list. +#[test] +fn test_pending_match_appears_in_get_active_matches() { + let (env, contract_id, _oracle, player1, player2, token, _admin) = setup(); + let client = EscrowContractClient::new(&env, &contract_id); + + let id = client.create_match( + &player1, + &player2, + &100, + &token, + &String::from_str(&env, "active_index_pending"), + &Platform::Lichess, + ); + + // No deposits made — match is still Pending + assert_eq!(client.get_match(&id).state, MatchState::Pending); + + let active = client.get_active_matches(); + assert!( + active.contains(id), + "pending match must appear in get_active_matches immediately after creation" + ); +} + +// ── Issue #12 (first half) — contract address as player1 returns InvalidPlayers +// +// Passing the escrow contract's own address as player1 must be rejected so the +// contract cannot authorize its own deposits. +#[test] +fn test_create_match_with_contract_address_as_player1_returns_invalid_players() { + let (env, contract_id, _oracle, _player1, player2, token, _admin) = setup(); + let client = EscrowContractClient::new(&env, &contract_id); + + let result = client.try_create_match( + &contract_id, + &player2, + &100, + &token, + &String::from_str(&env, "contract_as_player1"), + &Platform::Lichess, + ); + assert_eq!(result, Err(Ok(Error::InvalidPlayers))); +} + +// ── Admin-only access for set_match_timeout ─────────────────────────────────── +// +// A non-admin caller must receive `Unauthorized` when attempting to change the +// match timeout, regardless of what value they supply. +#[test] +fn test_set_match_timeout_from_non_admin_returns_unauthorized() { + let (env, contract_id, _oracle, _player1, _player2, _token, _admin) = setup(); + let client = EscrowContractClient::new(&env, &contract_id); + + let non_admin = Address::generate(&env); + env.mock_auths(&[MockAuth { + address: &non_admin, + invoke: &MockAuthInvoke { + contract: &contract_id, + fn_name: "set_match_timeout", + args: (1000u32,).into_val(&env), + sub_invokes: &[], + }, + }]); + + let result = client.try_set_match_timeout(&1000u32); + assert_eq!(result, Err(Ok(Error::Unauthorized))); +}