Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 90 additions & 116 deletions contracts/compliance/src/lib.rs

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions contracts/compliance/tests/address_index_full_boundary_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! `ComplianceContract::track_address` (see `contracts/compliance/src/lib.rs`) only
//! grows `DataKey::AddressIndex` when the address being tracked is *new* to the
//! index. It rejects growth with `ContractError::AddressIndexFull` once
//! index. It rejects growth with `ComplianceError::AddressIndexFull` once
//! `index.len() >= MAX_TRACKED_ADDRESSES`, but never rejects an operation on an
//! address that is already present in the index — that address's entry is a
//! no-op with respect to `track_address`, regardless of how full the index is.
Expand All @@ -13,7 +13,7 @@
//! 1. Filling the index to exactly `MAX_TRACKED_ADDRESSES` distinct addresses
//! must succeed for every single one (no off-by-one rejecting the last slot).
//! 2. The next *new*, distinct address beyond the cap must be rejected with
//! `ContractError::AddressIndexFull`, not silently accepted or rejected with
//! `ComplianceError::AddressIndexFull`, not silently accepted or rejected with
//! some other error.
//! 3. Operations on addresses that are already tracked — re-blocking an
//! already-blocked address, re-allowing an already-allowed address, and
Expand All @@ -25,7 +25,7 @@
//! suite asserts against the real value rather than a hand-mirrored copy.

use compliance::{
ComplianceContract, ComplianceContractClient, ContractError, BULK_OP_COOLDOWN_SECS,
ComplianceContract, ComplianceContractClient, ComplianceError, BULK_OP_COOLDOWN_SECS,
MAX_BATCH_SIZE, MAX_TRACKED_ADDRESSES,
};
use soroban_sdk::{
Expand Down Expand Up @@ -103,7 +103,7 @@ fn new_distinct_address_beyond_cap_is_rejected_with_address_index_full() {
let result = client.try_allow_address(&admin, &overflow_address);
assert_eq!(
result,
Err(Ok(ContractError::AddressIndexFull)),
Err(Ok(ComplianceError::AddressIndexFull)),
"the (MAX_TRACKED_ADDRESSES + 1)th distinct address must be rejected"
);

Expand All @@ -115,12 +115,12 @@ fn new_distinct_address_beyond_cap_is_rejected_with_address_index_full() {
// `track_address` with a new address, not just `allow_address`.
let overflow_address_2 = Address::generate(&env);
let block_result = client.try_block_address(&admin, &overflow_address_2, &None);
assert_eq!(block_result, Err(Ok(ContractError::AddressIndexFull)));
assert_eq!(block_result, Err(Ok(ComplianceError::AddressIndexFull)));

let overflow_address_3 = Address::generate(&env);
let allow_until_result =
client.try_allow_address_until(&admin, &overflow_address_3, &1_000_000);
assert_eq!(allow_until_result, Err(Ok(ContractError::AddressIndexFull)));
assert_eq!(allow_until_result, Err(Ok(ComplianceError::AddressIndexFull)));
}

#[test]
Expand Down Expand Up @@ -167,7 +167,7 @@ fn already_tracked_address_operations_succeed_while_index_is_full() {
// already-tracked operations grew it.
let overflow_address = Address::generate(&env);
let result = client.try_allow_address(&admin, &overflow_address);
assert_eq!(result, Err(Ok(ContractError::AddressIndexFull)));
assert_eq!(result, Err(Ok(ComplianceError::AddressIndexFull)));
}

#[test]
Expand Down
14 changes: 7 additions & 7 deletions contracts/compliance/tests/bulk_ops_batch_limit_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! Each bulk entrypoint must:
//! 1. Accept a list of exactly `MAX_BATCH_SIZE` addresses without error.
//! 2. Reject a list of `MAX_BATCH_SIZE + 1` addresses with the typed error
//! `ContractError::BatchTooLarge` before performing *any* state mutations.
//! `ComplianceError::BatchTooLarge` before performing *any* state mutations.
//!
//! Testing both boundaries (cap and cap + 1) means the limit is explicitly
//! documented in the test suite and cannot silently change — a future refactor
Expand All @@ -23,7 +23,7 @@
//! `address_index_full_boundary_test.rs`.

use compliance::{
ComplianceContract, ComplianceContractClient, ContractError, BULK_OP_COOLDOWN_SECS,
ComplianceContract, ComplianceContractClient, ComplianceError, BULK_OP_COOLDOWN_SECS,
MAX_BATCH_SIZE,
};
use soroban_sdk::{
Expand Down Expand Up @@ -92,7 +92,7 @@ fn bulk_allow_one_over_max_batch_size_is_rejected() {
let result = client.try_bulk_allow_addresses(&admin, &addresses);
assert_eq!(
result,
Err(Ok(ContractError::BatchTooLarge)),
Err(Ok(ComplianceError::BatchTooLarge)),
"bulk_allow_addresses with MAX_BATCH_SIZE + 1 addresses must return BatchTooLarge"
);

Expand Down Expand Up @@ -139,7 +139,7 @@ fn bulk_block_one_over_max_batch_size_is_rejected() {
let result = client.try_bulk_block_addresses(&admin, &addresses);
assert_eq!(
result,
Err(Ok(ContractError::BatchTooLarge)),
Err(Ok(ComplianceError::BatchTooLarge)),
"bulk_block_addresses with MAX_BATCH_SIZE + 1 addresses must return BatchTooLarge"
);

Expand Down Expand Up @@ -206,7 +206,7 @@ fn bulk_check_one_over_max_batch_size_is_rejected() {
let result = client.try_bulk_check_addresses(&addresses);
assert_eq!(
result,
Err(Ok(ContractError::BatchTooLarge)),
Err(Ok(ComplianceError::BatchTooLarge)),
"bulk_check_addresses with MAX_BATCH_SIZE + 1 addresses must return BatchTooLarge"
);
}
Expand All @@ -222,12 +222,12 @@ fn bulk_allow_and_bulk_block_share_the_same_cap() {

let allow_batch = gen_addresses(&env, MAX_BATCH_SIZE + 1);
let allow_result = client.try_bulk_allow_addresses(&admin, &allow_batch);
assert_eq!(allow_result, Err(Ok(ContractError::BatchTooLarge)));
assert_eq!(allow_result, Err(Ok(ComplianceError::BatchTooLarge)));

// Advance clock so the block call is not rejected by the cooldown instead.
advance_past_cooldown(&env);

let block_batch = gen_addresses(&env, MAX_BATCH_SIZE + 1);
let block_result = client.try_bulk_block_addresses(&admin, &block_batch);
assert_eq!(block_result, Err(Ok(ContractError::BatchTooLarge)));
assert_eq!(block_result, Err(Ok(ComplianceError::BatchTooLarge)));
}
46 changes: 23 additions & 23 deletions contracts/compliance/tests/compliance_test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use compliance::{BlockReason, ComplianceContract, ComplianceContractClient, ContractError};
use compliance::{BlockReason, ComplianceContract, ComplianceContractClient, ComplianceError};
use soroban_sdk::{
symbol_short,
testutils::{Address as _, Events, Ledger},
Expand Down Expand Up @@ -186,7 +186,7 @@ fn revoke_allow_returns_unauthorized_for_non_admin() {
client.initialize(&admin);

let result = client.try_revoke_allow(&non_admin, &address);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
Expand All @@ -201,7 +201,7 @@ fn revoke_allow_returns_contract_paused_when_paused() {
client.pause_with_reason(&admin, &soroban_sdk::symbol_short!("maint"));

let result = client.try_revoke_allow(&admin, &address);
assert_eq!(result, Err(Ok(ContractError::ContractPaused)));
assert_eq!(result, Err(Ok(ComplianceError::ContractPaused)));
}

#[test]
Expand Down Expand Up @@ -250,7 +250,7 @@ fn reinitialize_is_rejected() {
let (env, _admin, _subject, client) = setup();
let attacker = Address::generate(&env);
let result = client.try_initialize(&attacker);
assert_eq!(result, Err(Ok(ContractError::AlreadyInitialized)));
assert_eq!(result, Err(Ok(ComplianceError::AlreadyInitialized)));
}

// Verification: address_allowed event schema
Expand Down Expand Up @@ -568,7 +568,7 @@ fn cancel_admin_transfer_rejects_non_admin() {
client.transfer_admin(&admin, &new_admin);
assert_eq!(
client.try_cancel_admin_transfer(&new_admin),
Err(Ok(ContractError::Unauthorized))
Err(Ok(ComplianceError::Unauthorized))
);
client.accept_admin(&new_admin);
}
Expand All @@ -585,7 +585,7 @@ fn allow_address_returns_unauthorized_for_non_admin() {
client.initialize(&admin);

let result = client.try_allow_address(&non_admin, &address);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
Expand All @@ -600,7 +600,7 @@ fn allow_address_returns_contract_paused_when_paused() {
client.pause_with_reason(&admin, &soroban_sdk::symbol_short!("maint"));

let result = client.try_allow_address(&admin, &address);
assert_eq!(result, Err(Ok(ContractError::ContractPaused)));
assert_eq!(result, Err(Ok(ComplianceError::ContractPaused)));
}

// ── #73 bulk_check_addresses tests ────────────────────────────────────────────
Expand Down Expand Up @@ -650,23 +650,23 @@ fn non_admin_cannot_call_allow_address() {
let (env, _admin, subject, client) = setup();
let non_admin = Address::generate(&env);
let result = client.try_allow_address(&non_admin, &subject);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
fn non_admin_cannot_call_block_address() {
let (env, _admin, subject, client) = setup();
let non_admin = Address::generate(&env);
let result = client.try_block_address(&non_admin, &subject, &None);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
fn non_admin_cannot_call_clear_address() {
let (env, _admin, subject, client) = setup();
let non_admin = Address::generate(&env);
let result = client.try_clear_address(&non_admin, &subject);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
Expand All @@ -675,7 +675,7 @@ fn non_admin_cannot_call_allow_address_until() {
let non_admin = Address::generate(&env);
let expires_at = env.ledger().timestamp() + 1000;
let result = client.try_allow_address_until(&non_admin, &subject, &expires_at);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
Expand All @@ -684,7 +684,7 @@ fn non_admin_cannot_call_transfer_admin() {
let non_admin = Address::generate(&env);
let new_admin = Address::generate(&env);
let result = client.try_transfer_admin(&non_admin, &new_admin);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

// ── #80 export_snapshot tests ─────────────────────────────────────────────────
Expand Down Expand Up @@ -774,7 +774,7 @@ fn paused_contract_rejects_allow_address() {
let (_env, admin, subject, client) = setup();
client.pause_with_reason(&admin, &soroban_sdk::symbol_short!("maint"));
let result = client.try_allow_address(&admin, &subject);
assert_eq!(result, Err(Ok(ContractError::ContractPaused)));
assert_eq!(result, Err(Ok(ComplianceError::ContractPaused)));
}

#[test]
Expand All @@ -783,7 +783,7 @@ fn paused_contract_rejects_allow_address_until() {
let expires_at = env.ledger().timestamp() + 1000;
client.pause_with_reason(&admin, &soroban_sdk::symbol_short!("maint"));
let result = client.try_allow_address_until(&admin, &subject, &expires_at);
assert_eq!(result, Err(Ok(ContractError::ContractPaused)));
assert_eq!(result, Err(Ok(ComplianceError::ContractPaused)));
}

#[test]
Expand Down Expand Up @@ -841,7 +841,7 @@ fn old_admin_allow_address_returns_unauthorized_after_transfer() {
client.transfer_admin(&admin, &new_admin);
client.accept_admin(&new_admin);
let result = client.try_allow_address(&admin, &subject);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
Expand All @@ -851,7 +851,7 @@ fn old_admin_block_address_returns_unauthorized_after_transfer() {
client.transfer_admin(&admin, &new_admin);
client.accept_admin(&new_admin);
let result = client.try_block_address(&admin, &subject, &None);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
Expand All @@ -861,7 +861,7 @@ fn old_admin_pause_returns_unauthorized_after_transfer() {
client.transfer_admin(&admin, &new_admin);
client.accept_admin(&new_admin);
let result = client.try_pause_with_reason(&admin, &soroban_sdk::symbol_short!("maint"));
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

// ── #64 allow_address_until expiry boundary conditions ────────────────────────
Expand Down Expand Up @@ -957,7 +957,7 @@ fn bulk_allow_addresses_over_cap_is_rejected() {
addrs.push_back(Address::generate(&env));
}
let result = client.try_bulk_allow_addresses(&admin, &addrs);
assert_eq!(result, Err(Ok(ContractError::BatchTooLarge)));
assert_eq!(result, Err(Ok(ComplianceError::BatchTooLarge)));
}

// ── #57 clear_address key-clearing completeness ───────────────────────────────
Expand All @@ -976,7 +976,7 @@ fn accept_admin_rejects_non_pending_admin_caller() {
client.transfer_admin(&admin, &new_admin);

let result = client.try_accept_admin(&unrelated);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
Expand All @@ -988,7 +988,7 @@ fn accept_admin_rejects_current_admin_self_accepting_others_transfer() {
// The current admin is not the pending admin, so it must not be able to
// accept a transfer that was nominated for someone else.
let result = client.try_accept_admin(&admin);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
Expand Down Expand Up @@ -1043,7 +1043,7 @@ fn bulk_block_addresses_over_cap_is_rejected() {
addrs.push_back(Address::generate(&env));
}
let result = client.try_bulk_block_addresses(&admin, &addrs);
assert_eq!(result, Err(Ok(ContractError::BatchTooLarge)));
assert_eq!(result, Err(Ok(ComplianceError::BatchTooLarge)));
}

// ── #49 sweep_expired tests ─────────────────────────────────
Expand Down Expand Up @@ -1135,7 +1135,7 @@ fn sweep_expired_returns_unauthorized_for_non_admin() {
client.initialize(&admin);

let result = client.try_sweep_expired(&non_admin, &0);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
Expand Down Expand Up @@ -1179,7 +1179,7 @@ fn set_tier_limit_unauthorized_for_non_admin() {
client.initialize(&admin);

let result = client.try_set_tier_limit(&non_admin, &0, &1_000_000);
assert_eq!(result, Err(Ok(ContractError::Unauthorized)));
assert_eq!(result, Err(Ok(ComplianceError::Unauthorized)));
}

#[test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// the later pages that cover its index slot.

use compliance::{
AddressState, ComplianceContract, ComplianceContractClient, ContractError,
AddressState, ComplianceContract, ComplianceContractClient, ComplianceError,
BULK_OP_COOLDOWN_SECS, MAX_BATCH_SIZE, MAX_TRACKED_ADDRESSES,
};
use soroban_sdk::{
Expand Down Expand Up @@ -89,7 +89,7 @@ fn index_filled_to_cap_rejects_further_growth() {
// address must be rejected with AddressIndexFull.
let one_more = Address::generate(&env);
let result = client.try_allow_address(&admin, &one_more);
assert_eq!(result, Err(Ok(ContractError::AddressIndexFull)));
assert_eq!(result, Err(Ok(ComplianceError::AddressIndexFull)));
}

#[test]
Expand Down
Loading