From 2b3ca17eb736ed56d94630268eb1564363d63ab5 Mon Sep 17 00:00:00 2001 From: kamaldeen Aliyu Date: Wed, 25 Mar 2026 17:08:34 +0100 Subject: [PATCH 1/4] Implemented the Identity Verification --- .../payment-vault-contract/src/contract.rs | 16 ++- contracts/payment-vault-contract/src/error.rs | 1 + contracts/payment-vault-contract/src/lib.rs | 5 +- .../payment-vault-contract/src/storage.rs | 10 ++ contracts/payment-vault-contract/src/test.rs | 112 +++++++++++++----- 5 files changed, 111 insertions(+), 33 deletions(-) diff --git a/contracts/payment-vault-contract/src/contract.rs b/contracts/payment-vault-contract/src/contract.rs index 544b62f..0b6436d 100644 --- a/contracts/payment-vault-contract/src/contract.rs +++ b/contracts/payment-vault-contract/src/contract.rs @@ -2,13 +2,14 @@ use crate::error::VaultError; use crate::events; use crate::storage; use crate::types::{BookingRecord, BookingStatus}; -use soroban_sdk::{token, Address, Env}; +use soroban_sdk::{token, Address, Env, Symbol}; pub fn initialize_vault( env: &Env, admin: &Address, token: &Address, oracle: &Address, + registry: &Address, ) -> Result<(), VaultError> { // 1. Check if already initialized if storage::has_admin(env) { @@ -19,6 +20,7 @@ pub fn initialize_vault( storage::set_admin(env, admin); storage::set_token(env, token); storage::set_oracle(env, oracle); + storage::set_registry_address(env, registry); Ok(()) } @@ -65,6 +67,18 @@ pub fn book_session( // Require authorization from the user creating the booking user.require_auth(); + // Verify expert is verified via Identity Registry cross-contract call + let registry_address = storage::get_registry_address(env).ok_or(VaultError::NotInitialized)?; + let is_verified: bool = env.invoke_contract( + ®istry_address, + &Symbol::new(env, "is_verified"), + soroban_sdk::vec![env, expert.to_val()], + ); + + if !is_verified { + return Err(VaultError::ExpertNotVerified); + } + // Fetch the expert's rate let rate_per_second = storage::get_expert_rate(env, expert).ok_or(VaultError::ExpertRateNotSet)?; diff --git a/contracts/payment-vault-contract/src/error.rs b/contracts/payment-vault-contract/src/error.rs index c746040..ce3ef13 100644 --- a/contracts/payment-vault-contract/src/error.rs +++ b/contracts/payment-vault-contract/src/error.rs @@ -13,4 +13,5 @@ pub enum VaultError { ReclaimTooEarly = 7, ContractPaused = 8, ExpertRateNotSet = 9, + ExpertNotVerified = 10, } diff --git a/contracts/payment-vault-contract/src/lib.rs b/contracts/payment-vault-contract/src/lib.rs index 651c2c4..66c28a4 100644 --- a/contracts/payment-vault-contract/src/lib.rs +++ b/contracts/payment-vault-contract/src/lib.rs @@ -17,14 +17,15 @@ pub struct PaymentVaultContract; #[contractimpl] impl PaymentVaultContract { - /// Initialize the vault with the Admin, the Payment Token, and the Oracle (Backend) + /// Initialize the vault with the Admin, the Payment Token, the Oracle (Backend), and the Identity Registry pub fn init( env: Env, admin: Address, token: Address, oracle: Address, + registry: Address, ) -> Result<(), VaultError> { - contract::initialize_vault(&env, &admin, &token, &oracle) + contract::initialize_vault(&env, &admin, &token, &oracle, ®istry) } /// Pause the contract (Admin-only) diff --git a/contracts/payment-vault-contract/src/storage.rs b/contracts/payment-vault-contract/src/storage.rs index e82c4b9..50ca6c8 100644 --- a/contracts/payment-vault-contract/src/storage.rs +++ b/contracts/payment-vault-contract/src/storage.rs @@ -7,6 +7,7 @@ pub enum DataKey { Admin, Token, Oracle, + RegistryAddress, // Identity Registry contract address Booking(u64), // Booking ID -> BookingRecord BookingCounter, // Counter for generating unique booking IDs UserBookings(Address), // User Address -> Vec of booking IDs @@ -47,6 +48,15 @@ pub fn get_oracle(env: &Env) -> Address { env.storage().instance().get(&DataKey::Oracle).unwrap() } +// --- Registry (Identity) --- +pub fn set_registry_address(env: &Env, registry: &Address) { + env.storage().instance().set(&DataKey::RegistryAddress, registry); +} + +pub fn get_registry_address(env: &Env) -> Option
{ + env.storage().instance().get(&DataKey::RegistryAddress) +} + // --- Pause (Circuit Breaker) --- pub fn set_paused(env: &Env, paused: bool) { env.storage().instance().set(&DataKey::IsPaused, &paused); diff --git a/contracts/payment-vault-contract/src/test.rs b/contracts/payment-vault-contract/src/test.rs index ea0e77d..750fef0 100644 --- a/contracts/payment-vault-contract/src/test.rs +++ b/contracts/payment-vault-contract/src/test.rs @@ -2,7 +2,7 @@ use crate::{PaymentVaultContract, PaymentVaultContractClient}; use soroban_sdk::{ testutils::{Address as _, Ledger}, - token, Address, Env, + token, Address, Env, Symbol, }; extern crate std; @@ -17,6 +17,28 @@ fn create_token_contract<'a>(env: &'a Env, admin: &Address) -> token::StellarAss token::StellarAssetClient::new(env, &contract.address()) } +// Mock Identity Registry contract that returns true for is_verified +mod mock_registry { + use soroban_sdk::{contract, contractimpl, Address, Env, Symbol}; + + #[contract] + pub struct MockRegistry; + + #[contractimpl] + impl MockRegistry { + pub fn is_verified(env: Env, expert: Address) -> bool { + // Always return true for mock + true + } + } +} + +// Create a mock registry contract that returns true for is_verified +fn create_mock_registry<'a>(env: &'a Env) -> Address { + let contract_id = env.register(mock_registry::MockRegistry, ()); + contract_id +} + #[test] fn test_initialization() { let env = Env::default(); @@ -25,13 +47,15 @@ fn test_initialization() { let admin = Address::generate(&env); let token = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); + let registry = create_mock_registry(&env); // 1. Successful Init - let res = client.try_init(&admin, &token, &oracle); + let res = client.try_init(&admin, &token, &oracle, ®istry); assert!(res.is_ok()); // 2. Double Init (Should Fail) - let res_duplicate = client.try_init(&admin, &token, &oracle); + let res_duplicate = client.try_init(&admin, &token, &oracle, ®istry); assert!(res_duplicate.is_err()); } @@ -44,6 +68,8 @@ fn test_partial_duration_scenario() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); + let registry = create_mock_registry(&env); // Create token contract and mint tokens to user let token_admin = Address::generate(&env); @@ -52,7 +78,7 @@ fn test_partial_duration_scenario() { // Initialize vault let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Book session: rate = 10 tokens/second, max_duration = 100 seconds // Total deposit = 10 * 100 = 1000 tokens @@ -86,13 +112,14 @@ fn test_full_duration_no_refund() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Book session let rate_per_second = 10_i128; @@ -121,13 +148,14 @@ fn test_double_finalization_protection() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); let rate_per_second = 10_i128; let max_duration = 100_u64; @@ -155,13 +183,14 @@ fn test_oracle_authorization_enforcement() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); let rate_per_second = 10_i128; let max_duration = 100_u64; @@ -194,13 +223,14 @@ fn test_zero_duration_finalization() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); let rate_per_second = 10_i128; let max_duration = 100_u64; @@ -226,10 +256,11 @@ fn test_booking_not_found() { let admin = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token = Address::generate(&env); let client = create_client(&env); - client.init(&admin, &token, &oracle); + client.init(&admin, &token, &oracle, ®istry); // Try to finalize non-existent booking let result = client.try_finalize_session(&999, &50); @@ -249,6 +280,7 @@ fn test_book_session_balance_transfer() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); @@ -258,7 +290,7 @@ fn test_book_session_balance_transfer() { token.mint(&user, &initial_balance); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Book session with specific deposit let rate_per_second = 5_i128; @@ -306,13 +338,14 @@ fn test_get_user_and_expert_bookings() { let expert1 = Address::generate(&env); let expert2 = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &100_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Create 2 bookings for the same user with different experts let rate_per_second = 10_i128; @@ -365,13 +398,14 @@ fn test_reclaim_stale_session_too_early() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Create booking let rate_per_second = 10_i128; @@ -399,13 +433,14 @@ fn test_reclaim_stale_session_success() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Create booking let rate_per_second = 10_i128; @@ -439,13 +474,14 @@ fn test_reclaim_stale_session_wrong_user() { let other_user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Create booking let rate_per_second = 10_i128; @@ -476,13 +512,14 @@ fn test_reclaim_already_finalized() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Create booking let rate_per_second = 10_i128; @@ -513,13 +550,14 @@ fn test_expert_rejects_pending_session() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Create booking let rate_per_second = 10_i128; @@ -557,13 +595,14 @@ fn test_user_cannot_reject_session() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); let rate_per_second = 10_i128; let max_duration = 100_u64; @@ -589,13 +628,14 @@ fn test_reject_already_complete_session() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); let rate_per_second = 10_i128; let max_duration = 100_u64; @@ -621,13 +661,14 @@ fn test_reject_already_reclaimed_session() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); let rate_per_second = 10_i128; let max_duration = 100_u64; @@ -656,13 +697,14 @@ fn test_wrong_expert_cannot_reject() { let expert = Address::generate(&env); let wrong_expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); let rate_per_second = 10_i128; let max_duration = 100_u64; @@ -688,9 +730,10 @@ fn test_reject_nonexistent_booking() { let expert = Address::generate(&env); let token = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let client = create_client(&env); - client.init(&admin, &token, &oracle); + client.init(&admin, &token, &oracle, ®istry); // Expert tries to reject non-existent booking (should fail - not found) let result = client.try_reject_session(&expert, &999); @@ -707,10 +750,11 @@ fn test_expert_can_set_and_update_rate() { let admin = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token = Address::generate(&env); let client = create_client(&env); - client.init(&admin, &token, &oracle); + client.init(&admin, &token, &oracle, ®istry); // Initial set let res1 = client.try_set_my_rate(&expert, &10_i128); @@ -734,6 +778,7 @@ fn test_book_session_calculates_correct_deposit() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); @@ -741,7 +786,7 @@ fn test_book_session_calculates_correct_deposit() { token.mint(&user, &initial_balance); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Set expert rate let stored_rate = 15_i128; @@ -767,13 +812,14 @@ fn test_book_session_fails_if_expert_rate_not_set() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &5_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Expert has NOT set rate @@ -795,13 +841,14 @@ fn test_pause_blocks_book_session() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Set expert rate before pausing client.set_my_rate(&expert, &10_i128); @@ -827,13 +874,14 @@ fn test_pause_blocks_finalize_session() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Book session while unpaused let booking_id = { @@ -858,13 +906,14 @@ fn test_pause_blocks_reclaim_stale_session() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Book session while unpaused let booking_id = { @@ -893,13 +942,14 @@ fn test_pause_blocks_reject_session() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Book session while unpaused let booking_id = { @@ -924,13 +974,14 @@ fn test_unpause_resumes_operations() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Set expert rate client.set_my_rate(&expert, &10_i128); @@ -962,13 +1013,14 @@ fn test_read_only_functions_work_while_paused() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); token.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Book a session before pausing let booking_id = { From d9ade7b3c418961b1eb074027eebd59dad582afc Mon Sep 17 00:00:00 2001 From: kamaldeen Aliyu Date: Wed, 25 Mar 2026 19:16:49 +0100 Subject: [PATCH 2/4] fixed test --- contracts/payment-vault-contract/src/test.rs | 50 +++++++++++++++++--- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/contracts/payment-vault-contract/src/test.rs b/contracts/payment-vault-contract/src/test.rs index 750fef0..e560e70 100644 --- a/contracts/payment-vault-contract/src/test.rs +++ b/contracts/payment-vault-contract/src/test.rs @@ -2,7 +2,7 @@ use crate::{PaymentVaultContract, PaymentVaultContractClient}; use soroban_sdk::{ testutils::{Address as _, Ledger}, - token, Address, Env, Symbol, + token, Address, Env, }; extern crate std; @@ -17,7 +17,7 @@ fn create_token_contract<'a>(env: &'a Env, admin: &Address) -> token::StellarAss token::StellarAssetClient::new(env, &contract.address()) } -// Mock Identity Registry contract that returns true for is_verified +// Mock Identity Registry contract that returns configurable value for is_verified mod mock_registry { use soroban_sdk::{contract, contractimpl, Address, Env, Symbol}; @@ -26,9 +26,16 @@ mod mock_registry { #[contractimpl] impl MockRegistry { - pub fn is_verified(env: Env, expert: Address) -> bool { - // Always return true for mock - true + pub fn is_verified(env: Env, _expert: Address) -> bool { + // Read the verification state from the registry's storage + // For simplicity, we'll use an internal storage key + let key = Symbol::new(&env, "is_verified"); + env.storage().instance().get(&key).unwrap_or(true) + } + + pub fn set_verified(env: Env, verified: bool) { + let key = Symbol::new(&env, "is_verified"); + env.storage().instance().set(&key, &verified); } } } @@ -48,7 +55,6 @@ fn test_initialization() { let token = Address::generate(&env); let oracle = Address::generate(&env); let registry = create_mock_registry(&env); - let registry = create_mock_registry(&env); // 1. Successful Init let res = client.try_init(&admin, &token, &oracle, ®istry); @@ -69,7 +75,6 @@ fn test_partial_duration_scenario() { let expert = Address::generate(&env); let oracle = Address::generate(&env); let registry = create_mock_registry(&env); - let registry = create_mock_registry(&env); // Create token contract and mint tokens to user let token_admin = Address::generate(&env); @@ -830,6 +835,37 @@ fn test_book_session_fails_if_expert_rate_not_set() { assert!(res.is_err()); } +#[test] +fn test_book_session_fails_if_expert_not_verified() { + let env = Env::default(); + env.mock_all_auths(); + + let admin = Address::generate(&env); + let user = Address::generate(&env); + let expert = Address::generate(&env); + let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); + + // Set the mock registry to return false (expert not verified) + mock_registry::MockRegistryClient::new(&env, ®istry).set_verified(&false); + + let token_admin = Address::generate(&env); + let token = create_token_contract(&env, &token_admin); + token.mint(&user, &5_000); + + let client = create_client(&env); + client.init(&admin, &token.address, &oracle, ®istry); + + // Set expert's rate + client.set_my_rate(&expert, &10_i128); + + // Book session should fail with ExpertNotVerified error + let max_duration = 100_u64; + let res = client.try_book_session(&user, &expert, &max_duration); + + assert!(res.is_err()); +} + // ==================== Pausability (Circuit Breaker) Tests ==================== #[test] From d2436a4bfaa22b6d826d022ae8c2ef16a0db851f Mon Sep 17 00:00:00 2001 From: kamaldeen Aliyu Date: Thu, 26 Mar 2026 09:44:54 +0100 Subject: [PATCH 3/4] fixed errors --- contracts/payment-vault-contract/src/storage.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/payment-vault-contract/src/storage.rs b/contracts/payment-vault-contract/src/storage.rs index 50ca6c8..fa877af 100644 --- a/contracts/payment-vault-contract/src/storage.rs +++ b/contracts/payment-vault-contract/src/storage.rs @@ -7,7 +7,7 @@ pub enum DataKey { Admin, Token, Oracle, - RegistryAddress, // Identity Registry contract address + RegistryAddress, Booking(u64), // Booking ID -> BookingRecord BookingCounter, // Counter for generating unique booking IDs UserBookings(Address), // User Address -> Vec of booking IDs From 6feb09b43526eeeca0f0f7d62b272f43fad187d4 Mon Sep 17 00:00:00 2001 From: kamaldeen Aliyu Date: Thu, 26 Mar 2026 10:05:47 +0100 Subject: [PATCH 4/4] fixed all build errors --- .../payment-vault-contract/src/storage.rs | 6 +---- contracts/payment-vault-contract/src/test.rs | 27 ++++++++++++------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/contracts/payment-vault-contract/src/storage.rs b/contracts/payment-vault-contract/src/storage.rs index 8d98a14..5a8bc47 100644 --- a/contracts/payment-vault-contract/src/storage.rs +++ b/contracts/payment-vault-contract/src/storage.rs @@ -13,9 +13,6 @@ pub enum DataKey { UserBookings(Address), // User Address -> Vec of booking IDs ExpertBookings(Address), // Expert Address -> Vec of booking IDs IsPaused, // Circuit breaker flag - ExpertRate(Address), // Expert Address -> rate per second (i128) - Booking(u64), // Booking ID -> BookingRecord - BookingCounter, // Counter for generating unique booking IDs // ── Indexed User Booking List ────────────────────────────────────────── // Replaces the old Vec approach with O(1) per-write composite keys. UserBooking(Address, u32), // (user, index) -> booking_id @@ -23,8 +20,7 @@ pub enum DataKey { // ── Indexed Expert Booking List ──────────────────────────────────────── ExpertBooking(Address, u32), // (expert, index) -> booking_id ExpertBookingCount(Address), // expert -> total count (u32) - IsPaused, // Circuit breaker flag - ExpertRate(Address), // Expert Address -> rate per second (i128) + ExpertRate(Address), // Expert Address -> rate per second (i128) } // --- Admin --- diff --git a/contracts/payment-vault-contract/src/test.rs b/contracts/payment-vault-contract/src/test.rs index dab2917..a3581e8 100644 --- a/contracts/payment-vault-contract/src/test.rs +++ b/contracts/payment-vault-contract/src/test.rs @@ -696,9 +696,10 @@ fn test_transfer_admin_success() { let admin_b = Address::generate(&env); let token = Address::generate(&env); let oracle = Address::generate(&env); + let registry = Address::generate(&env); let client = create_client(&env); - client.init(&admin_a, &token, &oracle); + client.init(&admin_a, &token, &oracle, ®istry); // Admin A transfers to Admin B let result = client.try_transfer_admin(&admin_b); @@ -714,9 +715,10 @@ fn test_new_admin_can_pause_after_transfer() { let admin_b = Address::generate(&env); let token = Address::generate(&env); let oracle = Address::generate(&env); + let registry = Address::generate(&env); let client = create_client(&env); - client.init(&admin_a, &token, &oracle); + client.init(&admin_a, &token, &oracle, ®istry); client.transfer_admin(&admin_b); // New admin B can pause and unpause @@ -733,9 +735,10 @@ fn test_old_admin_loses_privileges_after_transfer() { let admin_b = Address::generate(&env); let token = Address::generate(&env); let oracle = Address::generate(&env); + let registry = Address::generate(&env); let client = create_client(&env); - client.init(&admin_a, &token, &oracle); + client.init(&admin_a, &token, &oracle, ®istry); client.transfer_admin(&admin_b); // Remove all mocked auths — now only explicit auth will pass @@ -756,6 +759,7 @@ fn test_set_oracle_success() { let token = Address::generate(&env); let oracle_old = Address::generate(&env); let oracle_new = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token_contract = create_token_contract(&env, &token_admin); @@ -764,7 +768,7 @@ fn test_set_oracle_success() { token_contract.mint(&user, &10_000); let client = create_client(&env); - client.init(&admin, &token_contract.address, &oracle_old); + client.init(&admin, &token_contract.address, &oracle_old, ®istry); // Book a session client.set_my_rate(&expert, &10_i128); @@ -788,9 +792,10 @@ fn test_non_admin_cannot_transfer_admin() { let attacker = Address::generate(&env); let token = Address::generate(&env); let oracle = Address::generate(&env); + let registry = Address::generate(&env); let client = create_client(&env); - client.init(&admin, &token, &oracle); + client.init(&admin, &token, &oracle, ®istry); // Clear auths so attacker has no authorization env.set_auths(&[]); @@ -808,9 +813,10 @@ fn test_non_admin_cannot_set_oracle() { let attacker = Address::generate(&env); let token = Address::generate(&env); let oracle = Address::generate(&env); + let registry = Address::generate(&env); let client = create_client(&env); - client.init(&admin, &token, &oracle); + client.init(&admin, &token, &oracle, ®istry); env.set_auths(&[]); @@ -1137,6 +1143,7 @@ fn test_scale_50_bookings_single_user_with_pagination() { let user = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); @@ -1145,7 +1152,7 @@ fn test_scale_50_bookings_single_user_with_pagination() { token.mint(&user, &50_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); // Expert sets rate let rate_per_second = 1_i128; @@ -1202,6 +1209,7 @@ fn test_pagination_isolation_between_users() { let user_b = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); @@ -1209,7 +1217,7 @@ fn test_pagination_isolation_between_users() { token.mint(&user_b, &25_000); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); client.set_my_rate(&expert, &1_i128); @@ -1250,12 +1258,13 @@ fn test_expert_pagination_50_bookings() { let admin = Address::generate(&env); let expert = Address::generate(&env); let oracle = Address::generate(&env); + let registry = create_mock_registry(&env); let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); let client = create_client(&env); - client.init(&admin, &token.address, &oracle); + client.init(&admin, &token.address, &oracle, ®istry); client.set_my_rate(&expert, &1_i128); // 50 different users each book 1 session with the same expert