From 86d3cc454032c33c3d2c4b210a0a7b1d67d6d3bf Mon Sep 17 00:00:00 2001 From: Hallab Date: Sun, 22 Feb 2026 12:53:39 +0100 Subject: [PATCH 1/2] feat: Add comprehensive test suite for Soroban smart contracts --- contracts/assetsup/src/tests/admin.rs | 105 ++++ contracts/assetsup/src/tests/asset.rs | 340 +++++++++++++ .../assetsup/src/tests/detokenization.rs | 235 +++++++++ contracts/assetsup/src/tests/dividends.rs | 245 +++++++++ contracts/assetsup/src/tests/helpers.rs | 151 ++++++ .../assetsup/src/tests/initialization.rs | 81 +++ contracts/assetsup/src/tests/insurance.rs | 338 +++++++++++++ .../assetsup/src/tests/integration_full.rs | 255 ++++++++++ contracts/assetsup/src/tests/mod.rs | 28 +- contracts/assetsup/src/tests/tokenization.rs | 463 ++++++++++++++++++ .../src/tests/transfer_restrictions.rs | 198 ++++++++ contracts/assetsup/src/tests/voting.rs | 187 +++++++ 12 files changed, 2620 insertions(+), 6 deletions(-) create mode 100644 contracts/assetsup/src/tests/admin.rs create mode 100644 contracts/assetsup/src/tests/asset.rs create mode 100644 contracts/assetsup/src/tests/detokenization.rs create mode 100644 contracts/assetsup/src/tests/dividends.rs create mode 100644 contracts/assetsup/src/tests/helpers.rs create mode 100644 contracts/assetsup/src/tests/initialization.rs create mode 100644 contracts/assetsup/src/tests/insurance.rs create mode 100644 contracts/assetsup/src/tests/integration_full.rs create mode 100644 contracts/assetsup/src/tests/tokenization.rs create mode 100644 contracts/assetsup/src/tests/transfer_restrictions.rs create mode 100644 contracts/assetsup/src/tests/voting.rs diff --git a/contracts/assetsup/src/tests/admin.rs b/contracts/assetsup/src/tests/admin.rs new file mode 100644 index 0000000..fecd7f4 --- /dev/null +++ b/contracts/assetsup/src/tests/admin.rs @@ -0,0 +1,105 @@ +use crate::tests::helpers::*; +use soroban_sdk::{testutils::Address as _, Address, String}; + +#[test] +fn test_update_admin_success() { + let env = create_env(); + let (admin, new_admin, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + client.update_admin(&new_admin); + + // Verify admin was updated + assert_eq!(client.get_admin(), new_admin); + + // Verify new admin is authorized registrar + assert_eq!(client.is_authorized_registrar(&new_admin), true); + + // Verify old admin is no longer authorized registrar + assert_eq!(client.is_authorized_registrar(&admin), false); +} + +#[test] +#[should_panic(expected = "Error(Contract, #39)")] +fn test_update_admin_zero_address() { + let env = create_env(); + let admin = Address::generate(&env); + let client = initialize_contract(&env, &admin); + + let zero_address = Address::from_string(&soroban_sdk::String::from_str( + &env, + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF", + )); + + env.mock_all_auths(); + + // Should panic with InvalidOwnerAddress error + client.update_admin(&zero_address); +} + +#[test] +fn test_pause_unpause_contract() { + let env = create_env(); + let admin = Address::generate(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Initially not paused + assert_eq!(client.is_paused(), false); + + // Pause contract + client.pause_contract(); + assert_eq!(client.is_paused(), true); + + // Unpause contract + client.unpause_contract(); + assert_eq!(client.is_paused(), false); +} + +#[test] +fn test_add_authorized_registrar() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Initially user1 is not authorized + assert_eq!(client.is_authorized_registrar(&user1), false); + + // Add user1 as authorized registrar + client.add_authorized_registrar(&user1); + assert_eq!(client.is_authorized_registrar(&user1), true); +} + +#[test] +fn test_remove_authorized_registrar() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Add user1 as authorized registrar + client.add_authorized_registrar(&user1); + assert_eq!(client.is_authorized_registrar(&user1), true); + + // Remove user1 from authorized registrars + client.remove_authorized_registrar(&user1); + assert_eq!(client.is_authorized_registrar(&user1), false); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_remove_admin_from_registrars() { + let env = create_env(); + let admin = Address::generate(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Should panic with Unauthorized error - cannot remove admin + client.remove_authorized_registrar(&admin); +} diff --git a/contracts/assetsup/src/tests/asset.rs b/contracts/assetsup/src/tests/asset.rs new file mode 100644 index 0000000..d464867 --- /dev/null +++ b/contracts/assetsup/src/tests/asset.rs @@ -0,0 +1,340 @@ +use crate::tests::helpers::*; +use crate::types::AssetStatus; +use soroban_sdk::{String, Vec, Address, testutils::Address as _}; + +#[test] +fn test_register_asset_success() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id.clone()); + + env.mock_all_auths(); + client.register_asset(&asset, &admin); + + // Verify asset was registered + let stored_asset = client.get_asset(&asset_id); + assert_eq!(stored_asset.id, asset_id); + assert_eq!(stored_asset.owner, user1); + + // Verify total asset count increased + assert_eq!(client.get_total_asset_count(), 1); + + // Verify asset is in owner's registry + let owner_assets = client.get_assets_by_owner(&user1); + assert_eq!(owner_assets.len(), 1); + assert_eq!(owner_assets.get(0).unwrap(), asset_id); +} + +#[test] +#[should_panic(expected = "Error(Contract, #3)")] +fn test_register_asset_already_exists() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id.clone()); + + env.mock_all_auths(); + client.register_asset(&asset, &admin); + + // Try to register same asset again - should panic with AssetAlreadyExists + client.register_asset(&asset, &admin); +} + +#[test] +#[should_panic(expected = "Error(Contract, #34)")] +fn test_register_asset_when_paused() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Pause contract + client.pause_contract(); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id); + + // Should panic with ContractPaused error + client.register_asset(&asset, &admin); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_register_asset_unauthorized() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id); + + env.mock_all_auths(); + + // user2 is not authorized registrar - should panic with Unauthorized + client.register_asset(&asset, &user2); +} + +#[test] +#[should_panic(expected = "Error(Contract, #36)")] +fn test_register_asset_invalid_name_too_short() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let mut asset = create_test_asset(&env, &user1, asset_id); + asset.name = String::from_str(&env, "AB"); // Too short (< 3 chars) + + env.mock_all_auths(); + + // Should panic with InvalidAssetName error + client.register_asset(&asset, &admin); +} + +#[test] +#[should_panic(expected = "Error(Contract, #37)")] +fn test_register_asset_invalid_purchase_value() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let mut asset = create_test_asset(&env, &user1, asset_id); + asset.purchase_value = -100; // Negative value + + env.mock_all_auths(); + + // Should panic with InvalidPurchaseValue error + client.register_asset(&asset, &admin); +} + +#[test] +#[should_panic(expected = "Error(Contract, #39)")] +fn test_register_asset_zero_owner() { + let env = create_env(); + let admin = Address::generate(&env); + let client = initialize_contract(&env, &admin); + + let zero_address = Address::from_string(&String::from_str( + &env, + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF", + )); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &zero_address, asset_id); + + env.mock_all_auths(); + + // Should panic with InvalidOwnerAddress error + client.register_asset(&asset, &admin); +} + +#[test] +fn test_update_asset_metadata_success() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id.clone()); + + env.mock_all_auths(); + client.register_asset(&asset, &admin); + + // Update metadata + let new_description = Some(String::from_str(&env, "Updated description")); + let new_uri = Some(String::from_str(&env, "ipfs://QmUpdated123")); + + client.update_asset_metadata(&asset_id, &new_description, &new_uri, &None, &user1); + + // Verify metadata was updated (just check it doesn't error) + let updated_asset = client.get_asset(&asset_id); + assert!(updated_asset.description.len() > 0); + assert!(updated_asset.metadata_uri.len() > 0); +} + +#[test] +#[should_panic(expected = "Error(Contract, #4)")] +fn test_update_asset_metadata_not_found() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 999); + let new_description = Some(String::from_str(&env, "Updated")); + + env.mock_all_auths(); + + // Should panic with AssetNotFound error + client.update_asset_metadata(&asset_id, &new_description, &None, &None, &user1); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_update_asset_metadata_unauthorized() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id.clone()); + + env.mock_all_auths(); + client.register_asset(&asset, &admin); + + let new_description = Some(String::from_str(&env, "Hacked")); + + // user2 is not owner or admin - should panic with Unauthorized + client.update_asset_metadata(&asset_id, &new_description, &None, &None, &user2); +} + +#[test] +fn test_transfer_asset_ownership_success() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id.clone()); + + env.mock_all_auths(); + client.register_asset(&asset, &admin); + + // Transfer ownership + client.transfer_asset_ownership(&asset_id, &user2, &user1); + + // Verify ownership was transferred + let transferred_asset = client.get_asset(&asset_id); + assert_eq!(transferred_asset.owner, user2); + assert_eq!(transferred_asset.status, AssetStatus::Transferred); + + // Verify asset is in new owner's registry + let user2_assets = client.get_assets_by_owner(&user2); + assert_eq!(user2_assets.len(), 1); + + // Verify asset is removed from old owner's registry + let user1_assets = client.get_assets_by_owner(&user1); + assert_eq!(user1_assets.len(), 0); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_transfer_asset_ownership_unauthorized() { + let env = create_env(); + let (admin, user1, user2, user3) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id.clone()); + + env.mock_all_auths(); + client.register_asset(&asset, &admin); + + // user3 is not owner - should panic with Unauthorized + client.transfer_asset_ownership(&asset_id, &user2, &user3); +} + +#[test] +fn test_retire_asset_success() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id.clone()); + + env.mock_all_auths(); + client.register_asset(&asset, &admin); + + // Retire asset + client.retire_asset(&asset_id, &user1); + + // Verify asset was retired + let retired_asset = client.get_asset(&asset_id); + assert_eq!(retired_asset.status, AssetStatus::Retired); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_retire_asset_unauthorized() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id.clone()); + + env.mock_all_auths(); + client.register_asset(&asset, &admin); + + // user2 is not owner or admin - should panic with Unauthorized + client.retire_asset(&asset_id, &user2); +} + +#[test] +fn test_check_asset_exists() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id.clone()); + + env.mock_all_auths(); + + // Asset doesn't exist yet + assert_eq!(client.check_asset_exists(&asset_id), false); + + // Register asset + client.register_asset(&asset, &admin); + + // Asset now exists + assert_eq!(client.check_asset_exists(&asset_id), true); +} + +#[test] +fn test_get_asset_info() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &user1, asset_id.clone()); + + env.mock_all_auths(); + client.register_asset(&asset, &admin); + + let info = client.get_asset_info(&asset_id); + assert_eq!(info.id, asset_id); + assert_eq!(info.owner, user1); + assert_eq!(info.status, AssetStatus::Active); +} + +#[test] +fn test_batch_get_asset_info() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id1 = generate_asset_id(&env, 1); + let asset_id2 = generate_asset_id(&env, 2); + let asset1 = create_test_asset(&env, &user1, asset_id1.clone()); + let asset2 = create_test_asset(&env, &user1, asset_id2.clone()); + + env.mock_all_auths(); + client.register_asset(&asset1, &admin); + client.register_asset(&asset2, &admin); + + let mut ids = Vec::new(&env); + ids.push_back(asset_id1.clone()); + ids.push_back(asset_id2.clone()); + + let infos = client.batch_get_asset_info(&ids); + assert_eq!(infos.len(), 2); +} diff --git a/contracts/assetsup/src/tests/detokenization.rs b/contracts/assetsup/src/tests/detokenization.rs new file mode 100644 index 0000000..d9e3e9d --- /dev/null +++ b/contracts/assetsup/src/tests/detokenization.rs @@ -0,0 +1,235 @@ +use crate::tests::helpers::*; +use crate::types::{AssetType, DetokenizationProposal}; +use soroban_sdk::String; + +#[test] +fn test_propose_detokenization_success() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Propose detokenization + let proposal_id = client.propose_detokenization(&1u64, &user1); + + assert_eq!(proposal_id, 1); + + // Verify proposal is active + assert_eq!(client.is_detokenization_active(&1u64), true); +} + +#[test] +#[should_panic(expected = "Error(Contract, #29)")] +fn test_propose_detokenization_already_proposed() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + client.propose_detokenization(&1u64, &user1); + + // Try to propose again - should panic with DetokenizationAlreadyProposed + client.propose_detokenization(&1u64, &user1); +} + +#[test] +#[should_panic(expected = "Error(Contract, #11)")] +fn test_propose_detokenization_not_tokenized() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Should panic with AssetNotTokenized error + client.propose_detokenization(&999u64, &user1); +} + +#[test] +fn test_execute_detokenization_success() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Transfer 60% to user2 + client.transfer_tokens(&1u64, &user1, &user2, &600000i128); + + // Propose detokenization + let proposal_id = client.propose_detokenization(&1u64, &user1); + + // Vote with majority + client.cast_vote(&1u64, &proposal_id, &user2); + + // Execute detokenization + client.execute_detokenization(&1u64, &proposal_id); + + // Verify asset is no longer tokenized + assert_eq!(client.is_detokenization_active(&1u64), false); +} + +#[test] +#[should_panic(expected = "Error(Contract, #28)")] +fn test_execute_detokenization_not_approved() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Transfer 30% to user2 (not enough for majority) + client.transfer_tokens(&1u64, &user1, &user2, &300000i128); + + // Propose detokenization + let proposal_id = client.propose_detokenization(&1u64, &user1); + + // Vote with minority + client.cast_vote(&1u64, &proposal_id, &user2); + + // Should panic with DetokenizationNotApproved error + client.execute_detokenization(&1u64, &proposal_id); +} + +#[test] +#[should_panic(expected = "Error(Contract, #24)")] +fn test_execute_detokenization_no_proposal() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Should panic with InvalidProposal error + client.execute_detokenization(&1u64, &1u64); +} + +#[test] +fn test_get_detokenization_proposal() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + let proposal_id = client.propose_detokenization(&1u64, &user1); + + let proposal = client.get_detokenization_proposal(&1u64); + + match proposal { + DetokenizationProposal::Active(active) => { + assert_eq!(active.proposal_id, proposal_id); + assert_eq!(active.proposer, user1); + } + _ => panic!("Expected Active proposal"), + } +} + +#[test] +fn test_detokenization_clears_all_data() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Set up some data + client.transfer_tokens(&1u64, &user1, &user2, &600000i128); + client.add_to_whitelist(&1u64, &user2); + client.enable_revenue_sharing(&1u64); + + // Propose and execute detokenization + let proposal_id = client.propose_detokenization(&1u64, &user1); + client.cast_vote(&1u64, &proposal_id, &user2); + client.execute_detokenization(&1u64, &proposal_id); + + // Verify whitelist is cleared + let whitelist = client.get_whitelist(&1u64); + assert_eq!(whitelist.len(), 0); +} diff --git a/contracts/assetsup/src/tests/dividends.rs b/contracts/assetsup/src/tests/dividends.rs new file mode 100644 index 0000000..821ec28 --- /dev/null +++ b/contracts/assetsup/src/tests/dividends.rs @@ -0,0 +1,245 @@ +use crate::tests::helpers::*; +use crate::types::AssetType; +use soroban_sdk::String; + +#[test] +fn test_enable_revenue_sharing() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Initially disabled + let asset = client.get_tokenized_asset(&1u64); + assert_eq!(asset.revenue_sharing_enabled, false); + + // Enable revenue sharing + client.enable_revenue_sharing(&1u64); + + let asset = client.get_tokenized_asset(&1u64); + assert_eq!(asset.revenue_sharing_enabled, true); +} + +#[test] +fn test_disable_revenue_sharing() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + client.enable_revenue_sharing(&1u64); + client.disable_revenue_sharing(&1u64); + + let asset = client.get_tokenized_asset(&1u64); + assert_eq!(asset.revenue_sharing_enabled, false); +} + +#[test] +fn test_distribute_dividends_success() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Enable revenue sharing + client.enable_revenue_sharing(&1u64); + + // Transfer 30% to user2 + client.transfer_tokens(&1u64, &user1, &user2, &300000i128); + + // Distribute 10000 in dividends + client.distribute_dividends(&1u64, &10000i128); + + // Check unclaimed dividends + let unclaimed1 = client.get_unclaimed_dividends(&1u64, &user1); + let unclaimed2 = client.get_unclaimed_dividends(&1u64, &user2); + + assert_eq!(unclaimed1, 7000); // 70% of 10000 + assert_eq!(unclaimed2, 3000); // 30% of 10000 +} + +#[test] +#[should_panic(expected = "Error(Contract, #27)")] +fn test_distribute_dividends_invalid_amount() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + client.enable_revenue_sharing(&1u64); + + // Should panic with InvalidDividendAmount error + client.distribute_dividends(&1u64, &0i128); +} + +#[test] +#[should_panic(expected = "Error(Contract, #27)")] +fn test_distribute_dividends_not_enabled() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Revenue sharing not enabled - should panic with InvalidDividendAmount + client.distribute_dividends(&1u64, &10000i128); +} + +#[test] +fn test_claim_dividends_success() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + client.enable_revenue_sharing(&1u64); + client.transfer_tokens(&1u64, &user1, &user2, &300000i128); + client.distribute_dividends(&1u64, &10000i128); + + // Claim dividends + let claimed = client.claim_dividends(&1u64, &user2); + assert_eq!(claimed, 3000); + + // After claiming, unclaimed should be 0 + let unclaimed = client.get_unclaimed_dividends(&1u64, &user2); + assert_eq!(unclaimed, 0); +} + +#[test] +#[should_panic(expected = "Error(Contract, #26)")] +fn test_claim_dividends_none_to_claim() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Should panic with NoDividendsToClaim error + client.claim_dividends(&1u64, &user1); +} + +#[test] +fn test_multiple_dividend_distributions() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + client.enable_revenue_sharing(&1u64); + client.transfer_tokens(&1u64, &user1, &user2, &500000i128); + + // First distribution + client.distribute_dividends(&1u64, &10000i128); + + // Second distribution + client.distribute_dividends(&1u64, &5000i128); + + // Total unclaimed should be sum of both distributions + let unclaimed1 = client.get_unclaimed_dividends(&1u64, &user1); + let unclaimed2 = client.get_unclaimed_dividends(&1u64, &user2); + + assert_eq!(unclaimed1, 7500); // 50% of 15000 + assert_eq!(unclaimed2, 7500); // 50% of 15000 +} diff --git a/contracts/assetsup/src/tests/helpers.rs b/contracts/assetsup/src/tests/helpers.rs new file mode 100644 index 0000000..20ed151 --- /dev/null +++ b/contracts/assetsup/src/tests/helpers.rs @@ -0,0 +1,151 @@ +use crate::asset::Asset; +use crate::insurance::{InsuranceClaim, InsurancePolicy, PolicyStatus, PolicyType, ClaimStatus}; +use crate::types::{AssetStatus, CustomAttribute, TokenMetadata, AssetType}; +use crate::{AssetUpContract, AssetUpContractClient}; +use soroban_sdk::{testutils::Address as _, Address, BytesN, Env, String, Vec}; + +/// Create a fresh test environment +pub fn create_env() -> Env { + Env::default() +} + +/// Create mock addresses for testing +pub fn create_mock_addresses(env: &Env) -> (Address, Address, Address, Address) { + let admin = Address::generate(env); + let user1 = Address::generate(env); + let user2 = Address::generate(env); + let user3 = Address::generate(env); + (admin, user1, user2, user3) +} + +/// Initialize contract with admin +pub fn initialize_contract<'a>(env: &'a Env, admin: &Address) -> AssetUpContractClient<'a> { + let contract_id = env.register(AssetUpContract, ()); + let client = AssetUpContractClient::new(env, &contract_id); + + env.mock_all_auths(); + client.initialize(admin); + client +} + +/// Create a test asset +pub fn create_test_asset(env: &Env, owner: &Address, id: BytesN<32>) -> Asset { + let timestamp = env.ledger().timestamp(); + + Asset { + id, + name: String::from_str(env, "Test Asset"), + description: String::from_str(env, "A test asset for unit testing"), + category: String::from_str(env, "Electronics"), + owner: owner.clone(), + registration_timestamp: timestamp, + last_transfer_timestamp: timestamp, + status: AssetStatus::Active, + metadata_uri: String::from_str(env, "ipfs://QmTest123456789"), + purchase_value: 1000, + custom_attributes: Vec::new(env), + } +} + +/// Create a test asset with custom attributes +pub fn create_test_asset_with_attributes( + env: &Env, + owner: &Address, + id: BytesN<32>, + name: &str, + value: i128, +) -> Asset { + let timestamp = env.ledger().timestamp(); + let mut attributes = Vec::new(env); + attributes.push_back(CustomAttribute { + key: String::from_str(env, "serial_number"), + value: String::from_str(env, "SN123456"), + }); + + Asset { + id, + name: String::from_str(env, name), + description: String::from_str(env, "Test asset with attributes"), + category: String::from_str(env, "Equipment"), + owner: owner.clone(), + registration_timestamp: timestamp, + last_transfer_timestamp: timestamp, + status: AssetStatus::Active, + metadata_uri: String::from_str(env, "ipfs://QmTestWithAttrs"), + purchase_value: value, + custom_attributes: attributes, + } +} + +/// Generate a unique asset ID +pub fn generate_asset_id(env: &Env, seed: u32) -> BytesN<32> { + let mut bytes = [0u8; 32]; + bytes[0] = (seed >> 24) as u8; + bytes[1] = (seed >> 16) as u8; + bytes[2] = (seed >> 8) as u8; + bytes[3] = seed as u8; + BytesN::from_array(env, &bytes) +} + +/// Create token metadata for testing +pub fn create_test_token_metadata(env: &Env) -> TokenMetadata { + TokenMetadata { + name: String::from_str(env, "Test Token"), + description: String::from_str(env, "Test tokenized asset"), + asset_type: AssetType::Physical, + ipfs_uri: Some(String::from_str(env, "ipfs://QmTokenMetadata")), + legal_docs_hash: None, + valuation_report_hash: None, + accredited_investor_required: false, + geographic_restrictions: Vec::new(env), + } +} + +/// Create a test insurance policy +pub fn create_test_policy( + env: &Env, + policy_id: BytesN<32>, + holder: &Address, + insurer: &Address, + asset_id: BytesN<32>, +) -> InsurancePolicy { + let current_time = env.ledger().timestamp(); + + InsurancePolicy { + policy_id, + holder: holder.clone(), + insurer: insurer.clone(), + asset_id, + policy_type: PolicyType::Property, + coverage_amount: 10000, + deductible: 500, + premium: 100, + start_date: current_time, + end_date: current_time + 31536000, // 1 year + status: PolicyStatus::Active, + auto_renew: false, + last_payment: current_time, + } +} + +/// Create a test insurance claim +pub fn create_test_claim( + env: &Env, + claim_id: BytesN<32>, + policy_id: BytesN<32>, + asset_id: BytesN<32>, + claimant: &Address, +) -> InsuranceClaim { + let current_time = env.ledger().timestamp(); + + InsuranceClaim { + claim_id, + policy_id, + asset_id, + claimant: claimant.clone(), + amount: 5000, + status: ClaimStatus::Submitted, + filed_at: current_time, + approved_amount: 0, + } +} diff --git a/contracts/assetsup/src/tests/initialization.rs b/contracts/assetsup/src/tests/initialization.rs new file mode 100644 index 0000000..d2fc549 --- /dev/null +++ b/contracts/assetsup/src/tests/initialization.rs @@ -0,0 +1,81 @@ +use crate::error::Error; +use crate::tests::helpers::*; +use crate::{AssetUpContract, AssetUpContractClient}; +use soroban_sdk::{testutils::Address as _, Address, Env}; + +#[test] +fn test_initialize_success() { + let env = create_env(); + let admin = Address::generate(&env); + + let contract_id = env.register(AssetUpContract, ()); + let client = AssetUpContractClient::new(&env, &contract_id); + + env.mock_all_auths(); + client.initialize(&admin); + + // Verify admin is set + let stored_admin = client.get_admin(); + assert_eq!(stored_admin, admin); + + // Verify contract is not paused + assert_eq!(client.is_paused(), false); + + // Verify total asset count is 0 + assert_eq!(client.get_total_asset_count(), 0); + + // Verify admin is authorized registrar + assert_eq!(client.is_authorized_registrar(&admin), true); +} + +#[test] +#[should_panic(expected = "Error(Contract, #1)")] +fn test_initialize_already_initialized() { + let env = create_env(); + let admin = Address::generate(&env); + + let contract_id = env.register(AssetUpContract, ()); + let client = AssetUpContractClient::new(&env, &contract_id); + + env.mock_all_auths(); + client.initialize(&admin); + + // Try to initialize again - should panic with AlreadyInitialized error + client.initialize(&admin); +} + +#[test] +fn test_get_contract_metadata() { + let env = create_env(); + let admin = Address::generate(&env); + let client = initialize_contract(&env, &admin); + + let metadata = client.get_contract_metadata(); + // Just verify metadata exists and has expected structure + assert!(metadata.version.len() > 0); + assert!(metadata.name.len() > 0); +} + +#[test] +#[should_panic(expected = "Error(Contract, #35)")] +fn test_get_contract_metadata_not_initialized() { + let env = create_env(); + + let contract_id = env.register(AssetUpContract, ()); + let client = AssetUpContractClient::new(&env, &contract_id); + + // Should panic with ContractNotInitialized error + client.get_contract_metadata(); +} + +#[test] +#[should_panic(expected = "Error(Contract, #2)")] +fn test_get_admin_not_found() { + let env = create_env(); + + let contract_id = env.register(AssetUpContract, ()); + let client = AssetUpContractClient::new(&env, &contract_id); + + // Should panic with AdminNotFound error + client.get_admin(); +} diff --git a/contracts/assetsup/src/tests/insurance.rs b/contracts/assetsup/src/tests/insurance.rs new file mode 100644 index 0000000..6a1eb2f --- /dev/null +++ b/contracts/assetsup/src/tests/insurance.rs @@ -0,0 +1,338 @@ +use crate::insurance::{ClaimStatus, PolicyStatus}; +use crate::tests::helpers::*; +use soroban_sdk::testutils::Ledger; + +#[test] +fn test_create_insurance_policy_success() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + // Verify policy was created + let stored_policy = client.get_insurance_policy(&policy_id); + assert!(stored_policy.is_some()); + + let stored = stored_policy.unwrap(); + assert_eq!(stored.policy_id, policy_id); + assert_eq!(stored.holder, user1); + assert_eq!(stored.status, PolicyStatus::Active); +} + +#[test] +#[should_panic(expected = "Error(Contract, #3)")] +fn test_create_insurance_policy_already_exists() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + // Try to create again - should panic with AssetAlreadyExists + client.create_insurance_policy(&policy); +} + +#[test] +#[should_panic(expected = "Error(Contract, #9)")] +fn test_create_insurance_policy_invalid_coverage() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let mut policy = create_test_policy(&env, policy_id, &user1, &insurer, asset_id); + + // Invalid: deductible >= coverage_amount + policy.deductible = 10000; + policy.coverage_amount = 10000; + + env.mock_all_auths(); + + // Should panic with InvalidPayment error + client.create_insurance_policy(&policy); +} + +#[test] +#[should_panic(expected = "Error(Contract, #9)")] +fn test_create_insurance_policy_invalid_dates() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let mut policy = create_test_policy(&env, policy_id, &user1, &insurer, asset_id); + + // Invalid: start_date >= end_date + policy.start_date = 1000; + policy.end_date = 1000; + + env.mock_all_auths(); + + // Should panic with InvalidPayment error + client.create_insurance_policy(&policy); +} + +#[test] +fn test_cancel_insurance_policy_by_holder() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + // Cancel by holder + client.cancel_insurance_policy(&policy_id, &user1); + + // Verify policy was cancelled + let stored_policy = client.get_insurance_policy(&policy_id).unwrap(); + assert_eq!(stored_policy.status, PolicyStatus::Cancelled); +} + +#[test] +fn test_cancel_insurance_policy_by_insurer() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + // Cancel by insurer + client.cancel_insurance_policy(&policy_id, &insurer); + + // Verify policy was cancelled + let stored_policy = client.get_insurance_policy(&policy_id).unwrap(); + assert_eq!(stored_policy.status, PolicyStatus::Cancelled); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_cancel_insurance_policy_unauthorized() { + let env = create_env(); + let (admin, user1, insurer, user3) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + // user3 is neither holder nor insurer - should panic with Unauthorized + client.cancel_insurance_policy(&policy_id, &user3); +} + +#[test] +fn test_suspend_insurance_policy() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + // Suspend policy + client.suspend_insurance_policy(&policy_id, &insurer); + + // Verify policy was suspended + let stored_policy = client.get_insurance_policy(&policy_id).unwrap(); + assert_eq!(stored_policy.status, PolicyStatus::Suspended); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_suspend_insurance_policy_unauthorized() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + // Holder cannot suspend - should panic with Unauthorized + client.suspend_insurance_policy(&policy_id, &user1); +} + +#[test] +fn test_expire_insurance_policy() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let mut policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + // Set current time to 5000 + env.ledger().with_mut(|li| li.timestamp = 5000); + + // Set dates: start now, end in 1000 seconds + policy.start_date = 5000; + policy.end_date = 6000; + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + // Advance time past end_date + env.ledger().with_mut(|li| li.timestamp = 7000); + + // Expire policy (permissionless) + client.expire_insurance_policy(&policy_id); + + // Verify policy was expired + let stored_policy = client.get_insurance_policy(&policy_id).unwrap(); + assert_eq!(stored_policy.status, PolicyStatus::Expired); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_expire_insurance_policy_not_yet_expired() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + // Should panic with Unauthorized error - end date hasn't passed + client.expire_insurance_policy(&policy_id); +} + +#[test] +fn test_renew_insurance_policy() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + // Renew policy + let new_end_date = env.ledger().timestamp() + 63072000; // 2 years + let new_premium = 150i128; + + client.renew_insurance_policy(&policy_id, &new_end_date, &new_premium, &insurer); + + // Verify policy was renewed + let stored_policy = client.get_insurance_policy(&policy_id).unwrap(); + assert_eq!(stored_policy.end_date, new_end_date); + assert_eq!(stored_policy.premium, new_premium); + assert_eq!(stored_policy.status, PolicyStatus::Active); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_renew_insurance_policy_unauthorized() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + client.create_insurance_policy(&policy); + + let new_end_date = env.ledger().timestamp() + 63072000; + let new_premium = 150i128; + + // Holder cannot renew - should panic with Unauthorized + client.renew_insurance_policy(&policy_id, &new_end_date, &new_premium, &user1); +} + +#[test] +fn test_get_asset_insurance_policies() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let asset_id = generate_asset_id(&env, 100); + let policy_id1 = generate_asset_id(&env, 1); + let policy_id2 = generate_asset_id(&env, 2); + + let policy1 = create_test_policy(&env, policy_id1.clone(), &user1, &insurer, asset_id.clone()); + let policy2 = create_test_policy(&env, policy_id2.clone(), &user1, &insurer, asset_id.clone()); + + env.mock_all_auths(); + client.create_insurance_policy(&policy1); + client.create_insurance_policy(&policy2); + + // Get all policies for asset + let policies = client.get_asset_insurance_policies(&asset_id); + assert_eq!(policies.len(), 2); +} + +#[test] +fn test_policy_lifecycle_full() { + let env = create_env(); + let (admin, user1, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + let policy_id = generate_asset_id(&env, 1); + let asset_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); + + env.mock_all_auths(); + + // Create + client.create_insurance_policy(&policy); + let stored = client.get_insurance_policy(&policy_id).unwrap(); + assert_eq!(stored.status, PolicyStatus::Active); + + // Renew while active + let new_end_date = env.ledger().timestamp() + 63072000; + client.renew_insurance_policy(&policy_id, &new_end_date, &150i128, &insurer); + let stored = client.get_insurance_policy(&policy_id).unwrap(); + assert_eq!(stored.status, PolicyStatus::Active); + assert_eq!(stored.premium, 150); + + // Suspend + client.suspend_insurance_policy(&policy_id, &insurer); + let stored = client.get_insurance_policy(&policy_id).unwrap(); + assert_eq!(stored.status, PolicyStatus::Suspended); + + // Cancel from suspended state + client.cancel_insurance_policy(&policy_id, &user1); + let stored = client.get_insurance_policy(&policy_id).unwrap(); + assert_eq!(stored.status, PolicyStatus::Cancelled); +} diff --git a/contracts/assetsup/src/tests/integration_full.rs b/contracts/assetsup/src/tests/integration_full.rs new file mode 100644 index 0000000..65cb932 --- /dev/null +++ b/contracts/assetsup/src/tests/integration_full.rs @@ -0,0 +1,255 @@ +use crate::tests::helpers::*; +use crate::types::AssetType; +use soroban_sdk::String; + +#[test] +fn test_full_asset_tokenization_workflow() { + let env = create_env(); + let (admin, owner, investor1, investor2) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Step 1: Register asset + let asset_id_bytes = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &owner, asset_id_bytes.clone()); + client.register_asset(&asset, &admin); + + // Step 2: Tokenize asset + let asset_id = 1u64; + client.tokenize_asset( + &asset_id, + &String::from_str(&env, "PROP"), + &1000000i128, + &6u32, + &1000i128, + &owner, + &String::from_str(&env, "Property Token"), + &String::from_str(&env, "Tokenized real estate"), + &AssetType::Physical, + ); + + // Step 3: Distribute tokens to investors + client.transfer_tokens(&asset_id, &owner, &investor1, &400000i128); + client.transfer_tokens(&asset_id, &owner, &investor2, &300000i128); + + // Verify ownership distribution + assert_eq!(client.get_token_balance(&asset_id, &owner), 300000); + assert_eq!(client.get_token_balance(&asset_id, &investor1), 400000); + assert_eq!(client.get_token_balance(&asset_id, &investor2), 300000); + + // Step 4: Enable revenue sharing and distribute dividends + client.enable_revenue_sharing(&asset_id); + client.distribute_dividends(&asset_id, &10000i128); + + // Verify dividend distribution + assert_eq!(client.get_unclaimed_dividends(&asset_id, &owner), 3000); + assert_eq!(client.get_unclaimed_dividends(&asset_id, &investor1), 4000); + assert_eq!(client.get_unclaimed_dividends(&asset_id, &investor2), 3000); + + // Step 5: Claim dividends + let claimed = client.claim_dividends(&asset_id, &investor1); + assert_eq!(claimed, 4000); + assert_eq!(client.get_unclaimed_dividends(&asset_id, &investor1), 0); +} + +#[test] +fn test_governance_and_detokenization_workflow() { + let env = create_env(); + let (admin, owner, investor1, investor2) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Setup: Tokenize asset + let asset_id = 1u64; + client.tokenize_asset( + &asset_id, + &String::from_str(&env, "GOV"), + &1000000i128, + &6u32, + &1000i128, + &owner, + &String::from_str(&env, "Governance Token"), + &String::from_str(&env, "Token with voting"), + &AssetType::Physical, + ); + + // Distribute tokens + client.transfer_tokens(&asset_id, &owner, &investor1, &600000i128); + client.transfer_tokens(&asset_id, &owner, &investor2, &200000i128); + + // Propose detokenization + let proposal_id = client.propose_detokenization(&asset_id, &owner); + + // Vote on proposal + client.cast_vote(&asset_id, &proposal_id, &investor1); + + // Check if proposal passed + assert_eq!(client.proposal_passed(&asset_id, &proposal_id), true); + + // Execute detokenization + client.execute_detokenization(&asset_id, &proposal_id); + + // Verify asset is detokenized + assert_eq!(client.is_detokenization_active(&asset_id), false); +} + +#[test] +fn test_transfer_restrictions_workflow() { + let env = create_env(); + let (admin, owner, investor1, investor2) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Setup: Tokenize asset + let asset_id = 1u64; + client.tokenize_asset( + &asset_id, + &String::from_str(&env, "REST"), + &1000000i128, + &6u32, + &1000i128, + &owner, + &String::from_str(&env, "Restricted Token"), + &String::from_str(&env, "Token with restrictions"), + &AssetType::Physical, + ); + + // Set transfer restrictions + client.set_transfer_restriction(&asset_id, &true); + + // Add investor1 to whitelist + client.add_to_whitelist(&asset_id, &investor1); + + // Transfer to whitelisted address should succeed + client.transfer_tokens(&asset_id, &owner, &investor1, &100000i128); + assert_eq!(client.get_token_balance(&asset_id, &investor1), 100000); + + // Verify whitelist + assert_eq!(client.is_whitelisted(&asset_id, &investor1), true); + assert_eq!(client.is_whitelisted(&asset_id, &investor2), false); +} + +#[test] +fn test_multi_asset_management() { + let env = create_env(); + let (admin, owner, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Register multiple assets + for i in 1..=5 { + let asset_id = generate_asset_id(&env, i); + let asset = create_test_asset(&env, &owner, asset_id); + client.register_asset(&asset, &admin); + } + + // Verify total count + assert_eq!(client.get_total_asset_count(), 5); + + // Verify owner has all assets + let owner_assets = client.get_assets_by_owner(&owner); + assert_eq!(owner_assets.len(), 5); +} + +#[test] +fn test_token_locking_workflow() { + let env = create_env(); + let (admin, owner, investor, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Setup: Tokenize and transfer + let asset_id = 1u64; + client.tokenize_asset( + &asset_id, + &String::from_str(&env, "LOCK"), + &1000000i128, + &6u32, + &1000i128, + &owner, + &String::from_str(&env, "Lockable Token"), + &String::from_str(&env, "Token with locking"), + &AssetType::Physical, + ); + + client.transfer_tokens(&asset_id, &owner, &investor, &500000i128); + + // Lock investor's tokens + let lock_until = env.ledger().timestamp() + 1000; + client.lock_tokens(&asset_id, &investor, &lock_until, &owner); + + // Verify tokens are locked + assert_eq!(client.is_tokens_locked(&asset_id, &investor), true); + + // Unlock tokens + client.unlock_tokens(&asset_id, &investor); + + // Verify tokens are unlocked + assert_eq!(client.is_tokens_locked(&asset_id, &investor), false); + + // Transfer should now succeed + client.transfer_tokens(&asset_id, &investor, &owner, &100000i128); +} + +#[test] +fn test_insurance_and_asset_integration() { + let env = create_env(); + let (admin, owner, insurer, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Register asset + let asset_id = generate_asset_id(&env, 1); + let asset = create_test_asset(&env, &owner, asset_id.clone()); + client.register_asset(&asset, &admin); + + // Create insurance policy for asset + let policy_id = generate_asset_id(&env, 100); + let policy = create_test_policy(&env, policy_id.clone(), &owner, &insurer, asset_id.clone()); + client.create_insurance_policy(&policy); + + // Verify policy exists + let stored_policy = client.get_insurance_policy(&policy_id); + assert!(stored_policy.is_some()); + + // Verify asset has policy + let asset_policies = client.get_asset_insurance_policies(&asset_id); + assert_eq!(asset_policies.len(), 1); +} + +#[test] +fn test_admin_operations_workflow() { + let env = create_env(); + let (admin, new_admin, registrar, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Add authorized registrar + client.add_authorized_registrar(®istrar); + assert_eq!(client.is_authorized_registrar(®istrar), true); + + // Pause contract + client.pause_contract(); + assert_eq!(client.is_paused(), true); + + // Unpause contract + client.unpause_contract(); + assert_eq!(client.is_paused(), false); + + // Update admin + client.update_admin(&new_admin); + assert_eq!(client.get_admin(), new_admin); + + // Verify old admin is no longer authorized registrar + assert_eq!(client.is_authorized_registrar(&admin), false); + + // Verify new admin is authorized registrar + assert_eq!(client.is_authorized_registrar(&new_admin), true); +} diff --git a/contracts/assetsup/src/tests/mod.rs b/contracts/assetsup/src/tests/mod.rs index fd8a933..3eaf435 100644 --- a/contracts/assetsup/src/tests/mod.rs +++ b/contracts/assetsup/src/tests/mod.rs @@ -1,3 +1,25 @@ +// Test helper functions and utilities +mod helpers; + +// Core contract tests +mod initialization; +mod admin; +mod asset; + +// Tokenization and ownership tests +mod tokenization; +mod voting; +mod dividends; +mod transfer_restrictions; +mod detokenization; + +// Insurance tests +mod insurance; + +// Integration tests +mod integration_full; + +// Legacy test modules (if still needed) mod detokenization_new; mod dividends_new; mod insurance_new; @@ -5,9 +27,3 @@ mod integration; mod tokenization_new; mod transfer_restrictions_new; mod voting_new; -// mod access_control; -// mod asset; -// mod branch; -// mod initialize; -// mod transfer; -// mod types; diff --git a/contracts/assetsup/src/tests/tokenization.rs b/contracts/assetsup/src/tests/tokenization.rs new file mode 100644 index 0000000..18d7bfa --- /dev/null +++ b/contracts/assetsup/src/tests/tokenization.rs @@ -0,0 +1,463 @@ +use crate::tests::helpers::*; +use crate::types::AssetType; +use soroban_sdk::String; + +#[test] +fn test_tokenize_asset_success() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + let result = client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + assert_eq!(result.asset_id, 1); + assert_eq!(result.total_supply, 1000000); + assert_eq!(result.tokenizer, user1); + assert_eq!(result.tokens_in_circulation, 1000000); +} + +#[test] +#[should_panic(expected = "Error(Contract, #10)")] +fn test_tokenize_asset_already_tokenized() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Try to tokenize again - should panic with AssetAlreadyTokenized + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST2"), + &500000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token 2"), + &String::from_str(&env, "Another test"), + &AssetType::Physical, + ); +} + +#[test] +#[should_panic(expected = "Error(Contract, #12)")] +fn test_tokenize_asset_invalid_supply() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Should panic with InvalidTokenSupply error + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &0i128, // Invalid: zero supply + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); +} + +#[test] +fn test_mint_tokens_success() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + let result = client.mint_tokens(&1u64, &500000i128, &user1); + + assert_eq!(result.total_supply, 1500000); + assert_eq!(result.tokens_in_circulation, 1500000); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_mint_tokens_unauthorized() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // user2 is not tokenizer - should panic with Unauthorized + client.mint_tokens(&1u64, &500000i128, &user2); +} + +#[test] +#[should_panic(expected = "Error(Contract, #11)")] +fn test_mint_tokens_not_tokenized() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Should panic with AssetNotTokenized error + client.mint_tokens(&999u64, &500000i128, &user1); +} + +#[test] +fn test_burn_tokens_success() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + let result = client.burn_tokens(&1u64, &200000i128, &user1); + + assert_eq!(result.total_supply, 800000); + assert_eq!(result.tokens_in_circulation, 800000); +} + +#[test] +#[should_panic(expected = "Error(Contract, #14)")] +fn test_burn_tokens_insufficient_balance() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Should panic with InsufficientBalance error + client.burn_tokens(&1u64, &2000000i128, &user1); +} + +#[test] +fn test_transfer_tokens_success() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + client.transfer_tokens(&1u64, &user1, &user2, &300000i128); + + // Verify balances + let balance1 = client.get_token_balance(&1u64, &user1); + let balance2 = client.get_token_balance(&1u64, &user2); + + assert_eq!(balance1, 700000); + assert_eq!(balance2, 300000); +} + +#[test] +#[should_panic(expected = "Error(Contract, #14)")] +fn test_transfer_tokens_insufficient_balance() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Should panic with InsufficientBalance error + client.transfer_tokens(&1u64, &user1, &user2, &2000000i128); +} + +#[test] +#[should_panic(expected = "Error(Contract, #16)")] +fn test_transfer_tokens_locked() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Lock tokens + let future_time = env.ledger().timestamp() + 1000; + client.lock_tokens(&1u64, &user1, &future_time, &user1); + + // Should panic with TokensAreLocked error + client.transfer_tokens(&1u64, &user1, &user2, &100000i128); +} + +#[test] +fn test_lock_unlock_tokens() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Initially not locked + assert_eq!(client.is_tokens_locked(&1u64, &user1), false); + + // Lock tokens + let future_time = env.ledger().timestamp() + 1000; + client.lock_tokens(&1u64, &user1, &future_time, &user1); + + assert_eq!(client.is_tokens_locked(&1u64, &user1), true); + + // Unlock tokens + client.unlock_tokens(&1u64, &user1); + + assert_eq!(client.is_tokens_locked(&1u64, &user1), false); +} + +#[test] +#[should_panic(expected = "Error(Contract, #8)")] +fn test_lock_tokens_unauthorized() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + let future_time = env.ledger().timestamp() + 1000; + + // user2 is not tokenizer - should panic with Unauthorized + client.lock_tokens(&1u64, &user1, &future_time, &user2); +} + +#[test] +fn test_get_ownership_percentage() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Transfer 30% to user2 + client.transfer_tokens(&1u64, &user1, &user2, &300000i128); + + // Check ownership percentages (in basis points) + let percentage1 = client.get_ownership_percentage(&1u64, &user1); + let percentage2 = client.get_ownership_percentage(&1u64, &user2); + + assert_eq!(percentage1, 7000); // 70% + assert_eq!(percentage2, 3000); // 30% +} + +#[test] +fn test_get_token_holders() { + let env = create_env(); + let (admin, user1, user2, user3) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Initially only user1 + let holders = client.get_token_holders(&1u64); + assert_eq!(holders.len(), 1); + + // Transfer to user2 and user3 + client.transfer_tokens(&1u64, &user1, &user2, &300000i128); + client.transfer_tokens(&1u64, &user1, &user3, &200000i128); + + // Now should have 3 holders + let holders = client.get_token_holders(&1u64); + assert_eq!(holders.len(), 3); +} + +#[test] +fn test_update_valuation() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + client.update_valuation(&1u64, &2000000i128); + + let asset = client.get_tokenized_asset(&1u64); + assert_eq!(asset.valuation, 2000000); +} + +#[test] +#[should_panic(expected = "Error(Contract, #30)")] +fn test_update_valuation_invalid() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Should panic with InvalidValuation error + client.update_valuation(&1u64, &0i128); +} diff --git a/contracts/assetsup/src/tests/transfer_restrictions.rs b/contracts/assetsup/src/tests/transfer_restrictions.rs new file mode 100644 index 0000000..2973cdf --- /dev/null +++ b/contracts/assetsup/src/tests/transfer_restrictions.rs @@ -0,0 +1,198 @@ +use crate::tests::helpers::*; +use crate::types::AssetType; +use soroban_sdk::{String, Vec}; + +#[test] +fn test_add_to_whitelist() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Initially not whitelisted + assert_eq!(client.is_whitelisted(&1u64, &user2), false); + + // Add to whitelist + client.add_to_whitelist(&1u64, &user2); + + assert_eq!(client.is_whitelisted(&1u64, &user2), true); +} + +#[test] +fn test_remove_from_whitelist() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Add to whitelist + client.add_to_whitelist(&1u64, &user2); + assert_eq!(client.is_whitelisted(&1u64, &user2), true); + + // Remove from whitelist + client.remove_from_whitelist(&1u64, &user2); + assert_eq!(client.is_whitelisted(&1u64, &user2), false); +} + +#[test] +fn test_get_whitelist() { + let env = create_env(); + let (admin, user1, user2, user3) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Add multiple addresses to whitelist + client.add_to_whitelist(&1u64, &user2); + client.add_to_whitelist(&1u64, &user3); + + let whitelist = client.get_whitelist(&1u64); + assert_eq!(whitelist.len(), 2); +} + +#[test] +fn test_add_duplicate_to_whitelist() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Add to whitelist twice + client.add_to_whitelist(&1u64, &user2); + client.add_to_whitelist(&1u64, &user2); + + // Should still only have one entry + let whitelist = client.get_whitelist(&1u64); + assert_eq!(whitelist.len(), 1); +} + +#[test] +fn test_set_transfer_restriction() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Set transfer restriction + client.set_transfer_restriction(&1u64, &true); + + // Restriction should be set (no error means success) +} + +#[test] +fn test_transfer_with_whitelist() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Add user2 to whitelist + client.add_to_whitelist(&1u64, &user2); + + // Transfer should succeed + client.transfer_tokens(&1u64, &user1, &user2, &100000i128); + + let balance = client.get_token_balance(&1u64, &user2); + assert_eq!(balance, 100000); +} + +#[test] +fn test_empty_whitelist() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + let whitelist = client.get_whitelist(&1u64); + assert_eq!(whitelist.len(), 0); +} diff --git a/contracts/assetsup/src/tests/voting.rs b/contracts/assetsup/src/tests/voting.rs new file mode 100644 index 0000000..b072bfc --- /dev/null +++ b/contracts/assetsup/src/tests/voting.rs @@ -0,0 +1,187 @@ +use crate::tests::helpers::*; +use crate::types::AssetType; +use soroban_sdk::String; + +#[test] +fn test_cast_vote_success() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Tokenize asset + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Cast vote + client.cast_vote(&1u64, &1u64, &user1); + + // Verify vote was recorded + assert_eq!(client.has_voted(&1u64, &1u64, &user1), true); + + // Verify vote tally + let tally = client.get_vote_tally(&1u64, &1u64); + assert_eq!(tally, 1000000); // Full balance +} + +#[test] +#[should_panic(expected = "Error(Contract, #22)")] +fn test_cast_vote_already_voted() { + let env = create_env(); + let (admin, user1, _, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + client.cast_vote(&1u64, &1u64, &user1); + + // Try to vote again - should panic with AlreadyVoted + client.cast_vote(&1u64, &1u64, &user1); +} + +#[test] +#[should_panic(expected = "Error(Contract, #21)")] +fn test_cast_vote_insufficient_voting_power() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + // Tokenize with high voting threshold + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &500000i128, // 50% threshold + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Transfer small amount to user2 + client.transfer_tokens(&1u64, &user1, &user2, &10000i128); + + // user2 doesn't have enough tokens - should panic with InsufficientVotingPower + client.cast_vote(&1u64, &1u64, &user2); +} + +#[test] +fn test_proposal_passed() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Transfer 60% to user2 + client.transfer_tokens(&1u64, &user1, &user2, &600000i128); + + // user2 votes (60% of supply) + client.cast_vote(&1u64, &1u64, &user2); + + // Proposal should pass (>50% threshold) + assert_eq!(client.proposal_passed(&1u64, &1u64), true); +} + +#[test] +fn test_proposal_not_passed() { + let env = create_env(); + let (admin, user1, user2, _) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Transfer 40% to user2 + client.transfer_tokens(&1u64, &user1, &user2, &400000i128); + + // user2 votes (40% of supply) + client.cast_vote(&1u64, &1u64, &user2); + + // Proposal should not pass (<50% threshold) + assert_eq!(client.proposal_passed(&1u64, &1u64), false); +} + +#[test] +fn test_multiple_voters() { + let env = create_env(); + let (admin, user1, user2, user3) = create_mock_addresses(&env); + let client = initialize_contract(&env, &admin); + + env.mock_all_auths(); + + client.tokenize_asset( + &1u64, + &String::from_str(&env, "TST"), + &1000000i128, + &6u32, + &100i128, + &user1, + &String::from_str(&env, "Test Token"), + &String::from_str(&env, "A test tokenized asset"), + &AssetType::Physical, + ); + + // Distribute tokens + client.transfer_tokens(&1u64, &user1, &user2, &300000i128); + client.transfer_tokens(&1u64, &user1, &user3, &200000i128); + + // Multiple users vote + client.cast_vote(&1u64, &1u64, &user1); // 500000 + client.cast_vote(&1u64, &1u64, &user2); // 300000 + + // Total tally should be 800000 + let tally = client.get_vote_tally(&1u64, &1u64); + assert_eq!(tally, 800000); + + // Proposal should pass (80% > 50%) + assert_eq!(client.proposal_passed(&1u64, &1u64), true); +} From a407befc944787ffd1bb0d4bca0da4e022b412b1 Mon Sep 17 00:00:00 2001 From: Hallab Date: Sun, 22 Feb 2026 13:13:55 +0100 Subject: [PATCH 2/2] fix CI error --- contracts/assetsup/src/detokenization.rs | 3 +- contracts/assetsup/src/lib.rs | 5 +- contracts/assetsup/src/tests/admin.rs | 58 ++++---- contracts/assetsup/src/tests/asset.rs | 140 +++++++++--------- .../assetsup/src/tests/detokenization.rs | 78 +++++----- .../assetsup/src/tests/detokenization_new.rs | 7 +- contracts/assetsup/src/tests/dividends.rs | 82 +++++----- contracts/assetsup/src/tests/helpers.rs | 17 ++- .../assetsup/src/tests/initialization.rs | 39 +++-- contracts/assetsup/src/tests/insurance.rs | 126 ++++++++-------- contracts/assetsup/src/tests/insurance_new.rs | 23 +-- .../assetsup/src/tests/integration_full.rs | 114 +++++++------- contracts/assetsup/src/tests/mod.rs | 8 +- contracts/assetsup/src/tests/tokenization.rs | 134 ++++++++--------- .../src/tests/transfer_restrictions.rs | 68 ++++----- contracts/assetsup/src/tests/voting.rs | 66 ++++----- 16 files changed, 490 insertions(+), 478 deletions(-) diff --git a/contracts/assetsup/src/detokenization.rs b/contracts/assetsup/src/detokenization.rs index c6f2078..d297ce5 100644 --- a/contracts/assetsup/src/detokenization.rs +++ b/contracts/assetsup/src/detokenization.rs @@ -73,7 +73,8 @@ pub fn execute_detokenization(env: &Env, asset_id: u64, proposal_id: u64) -> Res // Get list of all token holders before clearing let holders_list_key = TokenDataKey::TokenHoldersList(asset_id); - let holders = store.get::<_, soroban_sdk::Vec
>(&holders_list_key) + let holders = store + .get::<_, soroban_sdk::Vec
>(&holders_list_key) .ok_or(Error::AssetNotTokenized)?; // Remove all token holder records diff --git a/contracts/assetsup/src/lib.rs b/contracts/assetsup/src/lib.rs index 8639201..f65ef03 100644 --- a/contracts/assetsup/src/lib.rs +++ b/contracts/assetsup/src/lib.rs @@ -822,7 +822,10 @@ impl AssetUpContract { } /// Get a specific policy - pub fn get_insurance_policy(env: Env, policy_id: BytesN<32>) -> Option { + pub fn get_insurance_policy( + env: Env, + policy_id: BytesN<32>, + ) -> Option { insurance::get_policy(env, policy_id) } diff --git a/contracts/assetsup/src/tests/admin.rs b/contracts/assetsup/src/tests/admin.rs index fecd7f4..e6cbd37 100644 --- a/contracts/assetsup/src/tests/admin.rs +++ b/contracts/assetsup/src/tests/admin.rs @@ -1,23 +1,23 @@ use crate::tests::helpers::*; -use soroban_sdk::{testutils::Address as _, Address, String}; +use soroban_sdk::{testutils::Address as _, Address}; #[test] fn test_update_admin_success() { let env = create_env(); let (admin, new_admin, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); client.update_admin(&new_admin); - + // Verify admin was updated assert_eq!(client.get_admin(), new_admin); - + // Verify new admin is authorized registrar - assert_eq!(client.is_authorized_registrar(&new_admin), true); - + assert!(client.is_authorized_registrar(&new_admin)); + // Verify old admin is no longer authorized registrar - assert_eq!(client.is_authorized_registrar(&admin), false); + assert!(!client.is_authorized_registrar(&admin)); } #[test] @@ -26,14 +26,14 @@ fn test_update_admin_zero_address() { let env = create_env(); let admin = Address::generate(&env); let client = initialize_contract(&env, &admin); - + let zero_address = Address::from_string(&soroban_sdk::String::from_str( &env, "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF", )); - + env.mock_all_auths(); - + // Should panic with InvalidOwnerAddress error client.update_admin(&zero_address); } @@ -43,19 +43,19 @@ fn test_pause_unpause_contract() { let env = create_env(); let admin = Address::generate(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Initially not paused - assert_eq!(client.is_paused(), false); - + assert!(!client.is_paused()); + // Pause contract client.pause_contract(); - assert_eq!(client.is_paused(), true); - + assert!(client.is_paused()); + // Unpause contract client.unpause_contract(); - assert_eq!(client.is_paused(), false); + assert!(!client.is_paused()); } #[test] @@ -63,15 +63,15 @@ fn test_add_authorized_registrar() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Initially user1 is not authorized - assert_eq!(client.is_authorized_registrar(&user1), false); - + assert!(!client.is_authorized_registrar(&user1)); + // Add user1 as authorized registrar client.add_authorized_registrar(&user1); - assert_eq!(client.is_authorized_registrar(&user1), true); + assert!(client.is_authorized_registrar(&user1)); } #[test] @@ -79,16 +79,16 @@ fn test_remove_authorized_registrar() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Add user1 as authorized registrar client.add_authorized_registrar(&user1); - assert_eq!(client.is_authorized_registrar(&user1), true); - + assert!(client.is_authorized_registrar(&user1)); + // Remove user1 from authorized registrars client.remove_authorized_registrar(&user1); - assert_eq!(client.is_authorized_registrar(&user1), false); + assert!(!client.is_authorized_registrar(&user1)); } #[test] @@ -97,9 +97,9 @@ fn test_remove_admin_from_registrars() { let env = create_env(); let admin = Address::generate(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Should panic with Unauthorized error - cannot remove admin client.remove_authorized_registrar(&admin); } diff --git a/contracts/assetsup/src/tests/asset.rs b/contracts/assetsup/src/tests/asset.rs index d464867..79872cb 100644 --- a/contracts/assetsup/src/tests/asset.rs +++ b/contracts/assetsup/src/tests/asset.rs @@ -1,27 +1,27 @@ use crate::tests::helpers::*; use crate::types::AssetStatus; -use soroban_sdk::{String, Vec, Address, testutils::Address as _}; +use soroban_sdk::{testutils::Address as _, Address, String, Vec}; #[test] fn test_register_asset_success() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id.clone()); - + env.mock_all_auths(); client.register_asset(&asset, &admin); - + // Verify asset was registered let stored_asset = client.get_asset(&asset_id); assert_eq!(stored_asset.id, asset_id); assert_eq!(stored_asset.owner, user1); - + // Verify total asset count increased assert_eq!(client.get_total_asset_count(), 1); - + // Verify asset is in owner's registry let owner_assets = client.get_assets_by_owner(&user1); assert_eq!(owner_assets.len(), 1); @@ -34,13 +34,13 @@ fn test_register_asset_already_exists() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id.clone()); - + env.mock_all_auths(); client.register_asset(&asset, &admin); - + // Try to register same asset again - should panic with AssetAlreadyExists client.register_asset(&asset, &admin); } @@ -51,15 +51,15 @@ fn test_register_asset_when_paused() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Pause contract client.pause_contract(); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id); - + // Should panic with ContractPaused error client.register_asset(&asset, &admin); } @@ -70,12 +70,12 @@ fn test_register_asset_unauthorized() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id); - + env.mock_all_auths(); - + // user2 is not authorized registrar - should panic with Unauthorized client.register_asset(&asset, &user2); } @@ -86,13 +86,13 @@ fn test_register_asset_invalid_name_too_short() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let mut asset = create_test_asset(&env, &user1, asset_id); asset.name = String::from_str(&env, "AB"); // Too short (< 3 chars) - + env.mock_all_auths(); - + // Should panic with InvalidAssetName error client.register_asset(&asset, &admin); } @@ -103,13 +103,13 @@ fn test_register_asset_invalid_purchase_value() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let mut asset = create_test_asset(&env, &user1, asset_id); asset.purchase_value = -100; // Negative value - + env.mock_all_auths(); - + // Should panic with InvalidPurchaseValue error client.register_asset(&asset, &admin); } @@ -120,17 +120,17 @@ fn test_register_asset_zero_owner() { let env = create_env(); let admin = Address::generate(&env); let client = initialize_contract(&env, &admin); - + let zero_address = Address::from_string(&String::from_str( &env, "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF", )); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &zero_address, asset_id); - + env.mock_all_auths(); - + // Should panic with InvalidOwnerAddress error client.register_asset(&asset, &admin); } @@ -140,23 +140,23 @@ fn test_update_asset_metadata_success() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id.clone()); - + env.mock_all_auths(); client.register_asset(&asset, &admin); - + // Update metadata let new_description = Some(String::from_str(&env, "Updated description")); let new_uri = Some(String::from_str(&env, "ipfs://QmUpdated123")); - + client.update_asset_metadata(&asset_id, &new_description, &new_uri, &None, &user1); - + // Verify metadata was updated (just check it doesn't error) let updated_asset = client.get_asset(&asset_id); - assert!(updated_asset.description.len() > 0); - assert!(updated_asset.metadata_uri.len() > 0); + assert!(!updated_asset.description.is_empty()); + assert!(!updated_asset.metadata_uri.is_empty()); } #[test] @@ -165,12 +165,12 @@ fn test_update_asset_metadata_not_found() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 999); let new_description = Some(String::from_str(&env, "Updated")); - + env.mock_all_auths(); - + // Should panic with AssetNotFound error client.update_asset_metadata(&asset_id, &new_description, &None, &None, &user1); } @@ -181,15 +181,15 @@ fn test_update_asset_metadata_unauthorized() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id.clone()); - + env.mock_all_auths(); client.register_asset(&asset, &admin); - + let new_description = Some(String::from_str(&env, "Hacked")); - + // user2 is not owner or admin - should panic with Unauthorized client.update_asset_metadata(&asset_id, &new_description, &None, &None, &user2); } @@ -199,25 +199,25 @@ fn test_transfer_asset_ownership_success() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id.clone()); - + env.mock_all_auths(); client.register_asset(&asset, &admin); - + // Transfer ownership client.transfer_asset_ownership(&asset_id, &user2, &user1); - + // Verify ownership was transferred let transferred_asset = client.get_asset(&asset_id); assert_eq!(transferred_asset.owner, user2); assert_eq!(transferred_asset.status, AssetStatus::Transferred); - + // Verify asset is in new owner's registry let user2_assets = client.get_assets_by_owner(&user2); assert_eq!(user2_assets.len(), 1); - + // Verify asset is removed from old owner's registry let user1_assets = client.get_assets_by_owner(&user1); assert_eq!(user1_assets.len(), 0); @@ -229,13 +229,13 @@ fn test_transfer_asset_ownership_unauthorized() { let env = create_env(); let (admin, user1, user2, user3) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id.clone()); - + env.mock_all_auths(); client.register_asset(&asset, &admin); - + // user3 is not owner - should panic with Unauthorized client.transfer_asset_ownership(&asset_id, &user2, &user3); } @@ -245,16 +245,16 @@ fn test_retire_asset_success() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id.clone()); - + env.mock_all_auths(); client.register_asset(&asset, &admin); - + // Retire asset client.retire_asset(&asset_id, &user1); - + // Verify asset was retired let retired_asset = client.get_asset(&asset_id); assert_eq!(retired_asset.status, AssetStatus::Retired); @@ -266,13 +266,13 @@ fn test_retire_asset_unauthorized() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id.clone()); - + env.mock_all_auths(); client.register_asset(&asset, &admin); - + // user2 is not owner or admin - should panic with Unauthorized client.retire_asset(&asset_id, &user2); } @@ -282,20 +282,20 @@ fn test_check_asset_exists() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id.clone()); - + env.mock_all_auths(); - + // Asset doesn't exist yet - assert_eq!(client.check_asset_exists(&asset_id), false); - + assert!(!client.check_asset_exists(&asset_id)); + // Register asset client.register_asset(&asset, &admin); - + // Asset now exists - assert_eq!(client.check_asset_exists(&asset_id), true); + assert!(client.check_asset_exists(&asset_id)); } #[test] @@ -303,13 +303,13 @@ fn test_get_asset_info() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &user1, asset_id.clone()); - + env.mock_all_auths(); client.register_asset(&asset, &admin); - + let info = client.get_asset_info(&asset_id); assert_eq!(info.id, asset_id); assert_eq!(info.owner, user1); @@ -321,20 +321,20 @@ fn test_batch_get_asset_info() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id1 = generate_asset_id(&env, 1); let asset_id2 = generate_asset_id(&env, 2); let asset1 = create_test_asset(&env, &user1, asset_id1.clone()); let asset2 = create_test_asset(&env, &user1, asset_id2.clone()); - + env.mock_all_auths(); client.register_asset(&asset1, &admin); client.register_asset(&asset2, &admin); - + let mut ids = Vec::new(&env); ids.push_back(asset_id1.clone()); ids.push_back(asset_id2.clone()); - + let infos = client.batch_get_asset_info(&ids); assert_eq!(infos.len(), 2); } diff --git a/contracts/assetsup/src/tests/detokenization.rs b/contracts/assetsup/src/tests/detokenization.rs index d9e3e9d..0657603 100644 --- a/contracts/assetsup/src/tests/detokenization.rs +++ b/contracts/assetsup/src/tests/detokenization.rs @@ -7,9 +7,9 @@ fn test_propose_detokenization_success() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -21,14 +21,14 @@ fn test_propose_detokenization_success() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Propose detokenization let proposal_id = client.propose_detokenization(&1u64, &user1); - + assert_eq!(proposal_id, 1); - + // Verify proposal is active - assert_eq!(client.is_detokenization_active(&1u64), true); + assert!(client.is_detokenization_active(&1u64)); } #[test] @@ -37,9 +37,9 @@ fn test_propose_detokenization_already_proposed() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -51,9 +51,9 @@ fn test_propose_detokenization_already_proposed() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + client.propose_detokenization(&1u64, &user1); - + // Try to propose again - should panic with DetokenizationAlreadyProposed client.propose_detokenization(&1u64, &user1); } @@ -64,9 +64,9 @@ fn test_propose_detokenization_not_tokenized() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Should panic with AssetNotTokenized error client.propose_detokenization(&999u64, &user1); } @@ -76,9 +76,9 @@ fn test_execute_detokenization_success() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -90,21 +90,21 @@ fn test_execute_detokenization_success() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Transfer 60% to user2 client.transfer_tokens(&1u64, &user1, &user2, &600000i128); - + // Propose detokenization let proposal_id = client.propose_detokenization(&1u64, &user1); - + // Vote with majority client.cast_vote(&1u64, &proposal_id, &user2); - + // Execute detokenization client.execute_detokenization(&1u64, &proposal_id); - + // Verify asset is no longer tokenized - assert_eq!(client.is_detokenization_active(&1u64), false); + assert!(!client.is_detokenization_active(&1u64)); } #[test] @@ -113,9 +113,9 @@ fn test_execute_detokenization_not_approved() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -127,16 +127,16 @@ fn test_execute_detokenization_not_approved() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Transfer 30% to user2 (not enough for majority) client.transfer_tokens(&1u64, &user1, &user2, &300000i128); - + // Propose detokenization let proposal_id = client.propose_detokenization(&1u64, &user1); - + // Vote with minority client.cast_vote(&1u64, &proposal_id, &user2); - + // Should panic with DetokenizationNotApproved error client.execute_detokenization(&1u64, &proposal_id); } @@ -147,9 +147,9 @@ fn test_execute_detokenization_no_proposal() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -161,7 +161,7 @@ fn test_execute_detokenization_no_proposal() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Should panic with InvalidProposal error client.execute_detokenization(&1u64, &1u64); } @@ -171,9 +171,9 @@ fn test_get_detokenization_proposal() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -185,11 +185,11 @@ fn test_get_detokenization_proposal() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + let proposal_id = client.propose_detokenization(&1u64, &user1); - + let proposal = client.get_detokenization_proposal(&1u64); - + match proposal { DetokenizationProposal::Active(active) => { assert_eq!(active.proposal_id, proposal_id); @@ -204,9 +204,9 @@ fn test_detokenization_clears_all_data() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -218,17 +218,17 @@ fn test_detokenization_clears_all_data() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Set up some data client.transfer_tokens(&1u64, &user1, &user2, &600000i128); client.add_to_whitelist(&1u64, &user2); client.enable_revenue_sharing(&1u64); - + // Propose and execute detokenization let proposal_id = client.propose_detokenization(&1u64, &user1); client.cast_vote(&1u64, &proposal_id, &user2); client.execute_detokenization(&1u64, &proposal_id); - + // Verify whitelist is cleared let whitelist = client.get_whitelist(&1u64); assert_eq!(whitelist.len(), 0); diff --git a/contracts/assetsup/src/tests/detokenization_new.rs b/contracts/assetsup/src/tests/detokenization_new.rs index ba7a0b9..cea89e1 100644 --- a/contracts/assetsup/src/tests/detokenization_new.rs +++ b/contracts/assetsup/src/tests/detokenization_new.rs @@ -232,7 +232,12 @@ fn test_token_elimination_on_execution() { let holders_result = tokenization::get_token_holders(&env, asset_id); let holders_cleared = holders_result.is_err(); - (before_exists, after_exists, balance_cleared, holders_cleared) + ( + before_exists, + after_exists, + balance_cleared, + holders_cleared, + ) }); // Assert asset existed before diff --git a/contracts/assetsup/src/tests/dividends.rs b/contracts/assetsup/src/tests/dividends.rs index 821ec28..dae3f9e 100644 --- a/contracts/assetsup/src/tests/dividends.rs +++ b/contracts/assetsup/src/tests/dividends.rs @@ -7,9 +7,9 @@ fn test_enable_revenue_sharing() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -21,16 +21,16 @@ fn test_enable_revenue_sharing() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Initially disabled let asset = client.get_tokenized_asset(&1u64); - assert_eq!(asset.revenue_sharing_enabled, false); - + assert!(!asset.revenue_sharing_enabled); + // Enable revenue sharing client.enable_revenue_sharing(&1u64); - + let asset = client.get_tokenized_asset(&1u64); - assert_eq!(asset.revenue_sharing_enabled, true); + assert!(asset.revenue_sharing_enabled); } #[test] @@ -38,9 +38,9 @@ fn test_disable_revenue_sharing() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -52,12 +52,12 @@ fn test_disable_revenue_sharing() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + client.enable_revenue_sharing(&1u64); client.disable_revenue_sharing(&1u64); - + let asset = client.get_tokenized_asset(&1u64); - assert_eq!(asset.revenue_sharing_enabled, false); + assert!(!asset.revenue_sharing_enabled); } #[test] @@ -65,9 +65,9 @@ fn test_distribute_dividends_success() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -79,20 +79,20 @@ fn test_distribute_dividends_success() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Enable revenue sharing client.enable_revenue_sharing(&1u64); - + // Transfer 30% to user2 client.transfer_tokens(&1u64, &user1, &user2, &300000i128); - + // Distribute 10000 in dividends client.distribute_dividends(&1u64, &10000i128); - + // Check unclaimed dividends let unclaimed1 = client.get_unclaimed_dividends(&1u64, &user1); let unclaimed2 = client.get_unclaimed_dividends(&1u64, &user2); - + assert_eq!(unclaimed1, 7000); // 70% of 10000 assert_eq!(unclaimed2, 3000); // 30% of 10000 } @@ -103,9 +103,9 @@ fn test_distribute_dividends_invalid_amount() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -117,9 +117,9 @@ fn test_distribute_dividends_invalid_amount() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + client.enable_revenue_sharing(&1u64); - + // Should panic with InvalidDividendAmount error client.distribute_dividends(&1u64, &0i128); } @@ -130,9 +130,9 @@ fn test_distribute_dividends_not_enabled() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -144,7 +144,7 @@ fn test_distribute_dividends_not_enabled() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Revenue sharing not enabled - should panic with InvalidDividendAmount client.distribute_dividends(&1u64, &10000i128); } @@ -154,9 +154,9 @@ fn test_claim_dividends_success() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -168,15 +168,15 @@ fn test_claim_dividends_success() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + client.enable_revenue_sharing(&1u64); client.transfer_tokens(&1u64, &user1, &user2, &300000i128); client.distribute_dividends(&1u64, &10000i128); - + // Claim dividends let claimed = client.claim_dividends(&1u64, &user2); assert_eq!(claimed, 3000); - + // After claiming, unclaimed should be 0 let unclaimed = client.get_unclaimed_dividends(&1u64, &user2); assert_eq!(unclaimed, 0); @@ -188,9 +188,9 @@ fn test_claim_dividends_none_to_claim() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -202,7 +202,7 @@ fn test_claim_dividends_none_to_claim() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Should panic with NoDividendsToClaim error client.claim_dividends(&1u64, &user1); } @@ -212,9 +212,9 @@ fn test_multiple_dividend_distributions() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -226,20 +226,20 @@ fn test_multiple_dividend_distributions() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + client.enable_revenue_sharing(&1u64); client.transfer_tokens(&1u64, &user1, &user2, &500000i128); - + // First distribution client.distribute_dividends(&1u64, &10000i128); - + // Second distribution client.distribute_dividends(&1u64, &5000i128); - + // Total unclaimed should be sum of both distributions let unclaimed1 = client.get_unclaimed_dividends(&1u64, &user1); let unclaimed2 = client.get_unclaimed_dividends(&1u64, &user2); - + assert_eq!(unclaimed1, 7500); // 50% of 15000 assert_eq!(unclaimed2, 7500); // 50% of 15000 } diff --git a/contracts/assetsup/src/tests/helpers.rs b/contracts/assetsup/src/tests/helpers.rs index 20ed151..66ad205 100644 --- a/contracts/assetsup/src/tests/helpers.rs +++ b/contracts/assetsup/src/tests/helpers.rs @@ -1,6 +1,6 @@ use crate::asset::Asset; -use crate::insurance::{InsuranceClaim, InsurancePolicy, PolicyStatus, PolicyType, ClaimStatus}; -use crate::types::{AssetStatus, CustomAttribute, TokenMetadata, AssetType}; +use crate::insurance::{ClaimStatus, InsuranceClaim, InsurancePolicy, PolicyStatus, PolicyType}; +use crate::types::{AssetStatus, AssetType, CustomAttribute, TokenMetadata}; use crate::{AssetUpContract, AssetUpContractClient}; use soroban_sdk::{testutils::Address as _, Address, BytesN, Env, String, Vec}; @@ -22,7 +22,7 @@ pub fn create_mock_addresses(env: &Env) -> (Address, Address, Address, Address) pub fn initialize_contract<'a>(env: &'a Env, admin: &Address) -> AssetUpContractClient<'a> { let contract_id = env.register(AssetUpContract, ()); let client = AssetUpContractClient::new(env, &contract_id); - + env.mock_all_auths(); client.initialize(admin); client @@ -31,7 +31,7 @@ pub fn initialize_contract<'a>(env: &'a Env, admin: &Address) -> AssetUpContract /// Create a test asset pub fn create_test_asset(env: &Env, owner: &Address, id: BytesN<32>) -> Asset { let timestamp = env.ledger().timestamp(); - + Asset { id, name: String::from_str(env, "Test Asset"), @@ -48,6 +48,7 @@ pub fn create_test_asset(env: &Env, owner: &Address, id: BytesN<32>) -> Asset { } /// Create a test asset with custom attributes +#[allow(dead_code)] pub fn create_test_asset_with_attributes( env: &Env, owner: &Address, @@ -61,7 +62,7 @@ pub fn create_test_asset_with_attributes( key: String::from_str(env, "serial_number"), value: String::from_str(env, "SN123456"), }); - + Asset { id, name: String::from_str(env, name), @@ -88,6 +89,7 @@ pub fn generate_asset_id(env: &Env, seed: u32) -> BytesN<32> { } /// Create token metadata for testing +#[allow(dead_code)] pub fn create_test_token_metadata(env: &Env) -> TokenMetadata { TokenMetadata { name: String::from_str(env, "Test Token"), @@ -110,7 +112,7 @@ pub fn create_test_policy( asset_id: BytesN<32>, ) -> InsurancePolicy { let current_time = env.ledger().timestamp(); - + InsurancePolicy { policy_id, holder: holder.clone(), @@ -129,6 +131,7 @@ pub fn create_test_policy( } /// Create a test insurance claim +#[allow(dead_code)] pub fn create_test_claim( env: &Env, claim_id: BytesN<32>, @@ -137,7 +140,7 @@ pub fn create_test_claim( claimant: &Address, ) -> InsuranceClaim { let current_time = env.ledger().timestamp(); - + InsuranceClaim { claim_id, policy_id, diff --git a/contracts/assetsup/src/tests/initialization.rs b/contracts/assetsup/src/tests/initialization.rs index d2fc549..4430527 100644 --- a/contracts/assetsup/src/tests/initialization.rs +++ b/contracts/assetsup/src/tests/initialization.rs @@ -1,31 +1,30 @@ -use crate::error::Error; use crate::tests::helpers::*; use crate::{AssetUpContract, AssetUpContractClient}; -use soroban_sdk::{testutils::Address as _, Address, Env}; +use soroban_sdk::{testutils::Address as _, Address}; #[test] fn test_initialize_success() { let env = create_env(); let admin = Address::generate(&env); - + let contract_id = env.register(AssetUpContract, ()); let client = AssetUpContractClient::new(&env, &contract_id); - + env.mock_all_auths(); client.initialize(&admin); - + // Verify admin is set let stored_admin = client.get_admin(); assert_eq!(stored_admin, admin); - + // Verify contract is not paused - assert_eq!(client.is_paused(), false); - + assert!(!client.is_paused()); + // Verify total asset count is 0 assert_eq!(client.get_total_asset_count(), 0); - + // Verify admin is authorized registrar - assert_eq!(client.is_authorized_registrar(&admin), true); + assert!(client.is_authorized_registrar(&admin)); } #[test] @@ -33,13 +32,13 @@ fn test_initialize_success() { fn test_initialize_already_initialized() { let env = create_env(); let admin = Address::generate(&env); - + let contract_id = env.register(AssetUpContract, ()); let client = AssetUpContractClient::new(&env, &contract_id); - + env.mock_all_auths(); client.initialize(&admin); - + // Try to initialize again - should panic with AlreadyInitialized error client.initialize(&admin); } @@ -49,21 +48,21 @@ fn test_get_contract_metadata() { let env = create_env(); let admin = Address::generate(&env); let client = initialize_contract(&env, &admin); - + let metadata = client.get_contract_metadata(); // Just verify metadata exists and has expected structure - assert!(metadata.version.len() > 0); - assert!(metadata.name.len() > 0); + assert!(!metadata.version.is_empty()); + assert!(!metadata.name.is_empty()); } #[test] #[should_panic(expected = "Error(Contract, #35)")] fn test_get_contract_metadata_not_initialized() { let env = create_env(); - + let contract_id = env.register(AssetUpContract, ()); let client = AssetUpContractClient::new(&env, &contract_id); - + // Should panic with ContractNotInitialized error client.get_contract_metadata(); } @@ -72,10 +71,10 @@ fn test_get_contract_metadata_not_initialized() { #[should_panic(expected = "Error(Contract, #2)")] fn test_get_admin_not_found() { let env = create_env(); - + let contract_id = env.register(AssetUpContract, ()); let client = AssetUpContractClient::new(&env, &contract_id); - + // Should panic with AdminNotFound error client.get_admin(); } diff --git a/contracts/assetsup/src/tests/insurance.rs b/contracts/assetsup/src/tests/insurance.rs index 6a1eb2f..677982b 100644 --- a/contracts/assetsup/src/tests/insurance.rs +++ b/contracts/assetsup/src/tests/insurance.rs @@ -1,4 +1,4 @@ -use crate::insurance::{ClaimStatus, PolicyStatus}; +use crate::insurance::PolicyStatus; use crate::tests::helpers::*; use soroban_sdk::testutils::Ledger; @@ -7,18 +7,18 @@ fn test_create_insurance_policy_success() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + // Verify policy was created let stored_policy = client.get_insurance_policy(&policy_id); assert!(stored_policy.is_some()); - + let stored = stored_policy.unwrap(); assert_eq!(stored.policy_id, policy_id); assert_eq!(stored.holder, user1); @@ -31,14 +31,14 @@ fn test_create_insurance_policy_already_exists() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + // Try to create again - should panic with AssetAlreadyExists client.create_insurance_policy(&policy); } @@ -49,17 +49,17 @@ fn test_create_insurance_policy_invalid_coverage() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let mut policy = create_test_policy(&env, policy_id, &user1, &insurer, asset_id); - + // Invalid: deductible >= coverage_amount policy.deductible = 10000; policy.coverage_amount = 10000; - + env.mock_all_auths(); - + // Should panic with InvalidPayment error client.create_insurance_policy(&policy); } @@ -70,17 +70,17 @@ fn test_create_insurance_policy_invalid_dates() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let mut policy = create_test_policy(&env, policy_id, &user1, &insurer, asset_id); - + // Invalid: start_date >= end_date policy.start_date = 1000; policy.end_date = 1000; - + env.mock_all_auths(); - + // Should panic with InvalidPayment error client.create_insurance_policy(&policy); } @@ -90,17 +90,17 @@ fn test_cancel_insurance_policy_by_holder() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + // Cancel by holder client.cancel_insurance_policy(&policy_id, &user1); - + // Verify policy was cancelled let stored_policy = client.get_insurance_policy(&policy_id).unwrap(); assert_eq!(stored_policy.status, PolicyStatus::Cancelled); @@ -111,17 +111,17 @@ fn test_cancel_insurance_policy_by_insurer() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + // Cancel by insurer client.cancel_insurance_policy(&policy_id, &insurer); - + // Verify policy was cancelled let stored_policy = client.get_insurance_policy(&policy_id).unwrap(); assert_eq!(stored_policy.status, PolicyStatus::Cancelled); @@ -133,14 +133,14 @@ fn test_cancel_insurance_policy_unauthorized() { let env = create_env(); let (admin, user1, insurer, user3) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + // user3 is neither holder nor insurer - should panic with Unauthorized client.cancel_insurance_policy(&policy_id, &user3); } @@ -150,17 +150,17 @@ fn test_suspend_insurance_policy() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + // Suspend policy client.suspend_insurance_policy(&policy_id, &insurer); - + // Verify policy was suspended let stored_policy = client.get_insurance_policy(&policy_id).unwrap(); assert_eq!(stored_policy.status, PolicyStatus::Suspended); @@ -172,14 +172,14 @@ fn test_suspend_insurance_policy_unauthorized() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + // Holder cannot suspend - should panic with Unauthorized client.suspend_insurance_policy(&policy_id, &user1); } @@ -189,27 +189,27 @@ fn test_expire_insurance_policy() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let mut policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + // Set current time to 5000 env.ledger().with_mut(|li| li.timestamp = 5000); - + // Set dates: start now, end in 1000 seconds policy.start_date = 5000; policy.end_date = 6000; - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + // Advance time past end_date env.ledger().with_mut(|li| li.timestamp = 7000); - + // Expire policy (permissionless) client.expire_insurance_policy(&policy_id); - + // Verify policy was expired let stored_policy = client.get_insurance_policy(&policy_id).unwrap(); assert_eq!(stored_policy.status, PolicyStatus::Expired); @@ -221,14 +221,14 @@ fn test_expire_insurance_policy_not_yet_expired() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + // Should panic with Unauthorized error - end date hasn't passed client.expire_insurance_policy(&policy_id); } @@ -238,20 +238,20 @@ fn test_renew_insurance_policy() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + // Renew policy let new_end_date = env.ledger().timestamp() + 63072000; // 2 years let new_premium = 150i128; - + client.renew_insurance_policy(&policy_id, &new_end_date, &new_premium, &insurer); - + // Verify policy was renewed let stored_policy = client.get_insurance_policy(&policy_id).unwrap(); assert_eq!(stored_policy.end_date, new_end_date); @@ -265,17 +265,17 @@ fn test_renew_insurance_policy_unauthorized() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); client.create_insurance_policy(&policy); - + let new_end_date = env.ledger().timestamp() + 63072000; let new_premium = 150i128; - + // Holder cannot renew - should panic with Unauthorized client.renew_insurance_policy(&policy_id, &new_end_date, &new_premium, &user1); } @@ -285,18 +285,18 @@ fn test_get_asset_insurance_policies() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let asset_id = generate_asset_id(&env, 100); let policy_id1 = generate_asset_id(&env, 1); let policy_id2 = generate_asset_id(&env, 2); - + let policy1 = create_test_policy(&env, policy_id1.clone(), &user1, &insurer, asset_id.clone()); let policy2 = create_test_policy(&env, policy_id2.clone(), &user1, &insurer, asset_id.clone()); - + env.mock_all_auths(); client.create_insurance_policy(&policy1); client.create_insurance_policy(&policy2); - + // Get all policies for asset let policies = client.get_asset_insurance_policies(&asset_id); assert_eq!(policies.len(), 2); @@ -307,30 +307,30 @@ fn test_policy_lifecycle_full() { let env = create_env(); let (admin, user1, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + let policy_id = generate_asset_id(&env, 1); let asset_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &user1, &insurer, asset_id); - + env.mock_all_auths(); - + // Create client.create_insurance_policy(&policy); let stored = client.get_insurance_policy(&policy_id).unwrap(); assert_eq!(stored.status, PolicyStatus::Active); - + // Renew while active let new_end_date = env.ledger().timestamp() + 63072000; client.renew_insurance_policy(&policy_id, &new_end_date, &150i128, &insurer); let stored = client.get_insurance_policy(&policy_id).unwrap(); assert_eq!(stored.status, PolicyStatus::Active); assert_eq!(stored.premium, 150); - + // Suspend client.suspend_insurance_policy(&policy_id, &insurer); let stored = client.get_insurance_policy(&policy_id).unwrap(); assert_eq!(stored.status, PolicyStatus::Suspended); - + // Cancel from suspended state client.cancel_insurance_policy(&policy_id, &user1); let stored = client.get_insurance_policy(&policy_id).unwrap(); diff --git a/contracts/assetsup/src/tests/insurance_new.rs b/contracts/assetsup/src/tests/insurance_new.rs index 6f98605..d2f3b9a 100644 --- a/contracts/assetsup/src/tests/insurance_new.rs +++ b/contracts/assetsup/src/tests/insurance_new.rs @@ -328,7 +328,8 @@ fn test_renew_expired_policy() { li.timestamp = 1000; }); - let mut policy = create_test_policy(&env, policy_id.clone(), holder, insurer.clone(), asset_id); + let mut policy = + create_test_policy(&env, policy_id.clone(), holder, insurer.clone(), asset_id); // Set policy to expire at timestamp 2000 policy.start_date = 1000; policy.end_date = 2000; @@ -343,14 +344,9 @@ fn test_renew_expired_policy() { insurance::expire_policy(env.clone(), policy_id.clone()).unwrap(); // Now renew it to timestamp 3500 - let renew_result = insurance::renew_policy( - env.clone(), - policy_id.clone(), - 3500, - 1500, - insurer.clone(), - ) - .is_ok(); + let renew_result = + insurance::renew_policy(env.clone(), policy_id.clone(), 3500, 1500, insurer.clone()) + .is_ok(); let final_policy = insurance::get_policy(env.clone(), policy_id.clone()).unwrap(); @@ -409,8 +405,13 @@ fn test_status_transition_validation() { let (suspend_ok, cancel_after_suspend_ok, suspend_cancelled_err) = env.as_contract(&contract_id, || { - let policy = - create_test_policy(&env, policy_id.clone(), holder.clone(), insurer.clone(), asset_id); + let policy = create_test_policy( + &env, + policy_id.clone(), + holder.clone(), + insurer.clone(), + asset_id, + ); insurance::create_policy(env.clone(), policy).unwrap(); // Active -> Suspended (should work) diff --git a/contracts/assetsup/src/tests/integration_full.rs b/contracts/assetsup/src/tests/integration_full.rs index 65cb932..a3527da 100644 --- a/contracts/assetsup/src/tests/integration_full.rs +++ b/contracts/assetsup/src/tests/integration_full.rs @@ -7,14 +7,14 @@ fn test_full_asset_tokenization_workflow() { let env = create_env(); let (admin, owner, investor1, investor2) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Step 1: Register asset let asset_id_bytes = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &owner, asset_id_bytes.clone()); client.register_asset(&asset, &admin); - + // Step 2: Tokenize asset let asset_id = 1u64; client.tokenize_asset( @@ -28,25 +28,25 @@ fn test_full_asset_tokenization_workflow() { &String::from_str(&env, "Tokenized real estate"), &AssetType::Physical, ); - + // Step 3: Distribute tokens to investors client.transfer_tokens(&asset_id, &owner, &investor1, &400000i128); client.transfer_tokens(&asset_id, &owner, &investor2, &300000i128); - + // Verify ownership distribution assert_eq!(client.get_token_balance(&asset_id, &owner), 300000); assert_eq!(client.get_token_balance(&asset_id, &investor1), 400000); assert_eq!(client.get_token_balance(&asset_id, &investor2), 300000); - + // Step 4: Enable revenue sharing and distribute dividends client.enable_revenue_sharing(&asset_id); client.distribute_dividends(&asset_id, &10000i128); - + // Verify dividend distribution assert_eq!(client.get_unclaimed_dividends(&asset_id, &owner), 3000); assert_eq!(client.get_unclaimed_dividends(&asset_id, &investor1), 4000); assert_eq!(client.get_unclaimed_dividends(&asset_id, &investor2), 3000); - + // Step 5: Claim dividends let claimed = client.claim_dividends(&asset_id, &investor1); assert_eq!(claimed, 4000); @@ -58,9 +58,9 @@ fn test_governance_and_detokenization_workflow() { let env = create_env(); let (admin, owner, investor1, investor2) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Setup: Tokenize asset let asset_id = 1u64; client.tokenize_asset( @@ -74,25 +74,25 @@ fn test_governance_and_detokenization_workflow() { &String::from_str(&env, "Token with voting"), &AssetType::Physical, ); - + // Distribute tokens client.transfer_tokens(&asset_id, &owner, &investor1, &600000i128); client.transfer_tokens(&asset_id, &owner, &investor2, &200000i128); - + // Propose detokenization let proposal_id = client.propose_detokenization(&asset_id, &owner); - + // Vote on proposal client.cast_vote(&asset_id, &proposal_id, &investor1); - + // Check if proposal passed - assert_eq!(client.proposal_passed(&asset_id, &proposal_id), true); - + assert!(client.proposal_passed(&asset_id, &proposal_id)); + // Execute detokenization client.execute_detokenization(&asset_id, &proposal_id); - + // Verify asset is detokenized - assert_eq!(client.is_detokenization_active(&asset_id), false); + assert!(!client.is_detokenization_active(&asset_id)); } #[test] @@ -100,9 +100,9 @@ fn test_transfer_restrictions_workflow() { let env = create_env(); let (admin, owner, investor1, investor2) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Setup: Tokenize asset let asset_id = 1u64; client.tokenize_asset( @@ -116,20 +116,20 @@ fn test_transfer_restrictions_workflow() { &String::from_str(&env, "Token with restrictions"), &AssetType::Physical, ); - + // Set transfer restrictions client.set_transfer_restriction(&asset_id, &true); - + // Add investor1 to whitelist client.add_to_whitelist(&asset_id, &investor1); - + // Transfer to whitelisted address should succeed client.transfer_tokens(&asset_id, &owner, &investor1, &100000i128); assert_eq!(client.get_token_balance(&asset_id, &investor1), 100000); - + // Verify whitelist - assert_eq!(client.is_whitelisted(&asset_id, &investor1), true); - assert_eq!(client.is_whitelisted(&asset_id, &investor2), false); + assert!(client.is_whitelisted(&asset_id, &investor1)); + assert!(!client.is_whitelisted(&asset_id, &investor2)); } #[test] @@ -137,19 +137,19 @@ fn test_multi_asset_management() { let env = create_env(); let (admin, owner, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Register multiple assets for i in 1..=5 { let asset_id = generate_asset_id(&env, i); let asset = create_test_asset(&env, &owner, asset_id); client.register_asset(&asset, &admin); } - + // Verify total count assert_eq!(client.get_total_asset_count(), 5); - + // Verify owner has all assets let owner_assets = client.get_assets_by_owner(&owner); assert_eq!(owner_assets.len(), 5); @@ -160,9 +160,9 @@ fn test_token_locking_workflow() { let env = create_env(); let (admin, owner, investor, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Setup: Tokenize and transfer let asset_id = 1u64; client.tokenize_asset( @@ -176,22 +176,22 @@ fn test_token_locking_workflow() { &String::from_str(&env, "Token with locking"), &AssetType::Physical, ); - + client.transfer_tokens(&asset_id, &owner, &investor, &500000i128); - + // Lock investor's tokens let lock_until = env.ledger().timestamp() + 1000; client.lock_tokens(&asset_id, &investor, &lock_until, &owner); - + // Verify tokens are locked - assert_eq!(client.is_tokens_locked(&asset_id, &investor), true); - + assert!(client.is_tokens_locked(&asset_id, &investor)); + // Unlock tokens client.unlock_tokens(&asset_id, &investor); - + // Verify tokens are unlocked - assert_eq!(client.is_tokens_locked(&asset_id, &investor), false); - + assert!(!client.is_tokens_locked(&asset_id, &investor)); + // Transfer should now succeed client.transfer_tokens(&asset_id, &investor, &owner, &100000i128); } @@ -201,23 +201,23 @@ fn test_insurance_and_asset_integration() { let env = create_env(); let (admin, owner, insurer, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Register asset let asset_id = generate_asset_id(&env, 1); let asset = create_test_asset(&env, &owner, asset_id.clone()); client.register_asset(&asset, &admin); - + // Create insurance policy for asset let policy_id = generate_asset_id(&env, 100); let policy = create_test_policy(&env, policy_id.clone(), &owner, &insurer, asset_id.clone()); client.create_insurance_policy(&policy); - + // Verify policy exists let stored_policy = client.get_insurance_policy(&policy_id); assert!(stored_policy.is_some()); - + // Verify asset has policy let asset_policies = client.get_asset_insurance_policies(&asset_id); assert_eq!(asset_policies.len(), 1); @@ -228,28 +228,28 @@ fn test_admin_operations_workflow() { let env = create_env(); let (admin, new_admin, registrar, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Add authorized registrar client.add_authorized_registrar(®istrar); - assert_eq!(client.is_authorized_registrar(®istrar), true); - + assert!(client.is_authorized_registrar(®istrar)); + // Pause contract client.pause_contract(); - assert_eq!(client.is_paused(), true); - + assert!(client.is_paused()); + // Unpause contract client.unpause_contract(); - assert_eq!(client.is_paused(), false); - + assert!(!client.is_paused()); + // Update admin client.update_admin(&new_admin); assert_eq!(client.get_admin(), new_admin); - + // Verify old admin is no longer authorized registrar - assert_eq!(client.is_authorized_registrar(&admin), false); - + assert!(!client.is_authorized_registrar(&admin)); + // Verify new admin is authorized registrar - assert_eq!(client.is_authorized_registrar(&new_admin), true); + assert!(client.is_authorized_registrar(&new_admin)); } diff --git a/contracts/assetsup/src/tests/mod.rs b/contracts/assetsup/src/tests/mod.rs index 3eaf435..0cded02 100644 --- a/contracts/assetsup/src/tests/mod.rs +++ b/contracts/assetsup/src/tests/mod.rs @@ -2,16 +2,16 @@ mod helpers; // Core contract tests -mod initialization; mod admin; mod asset; +mod initialization; // Tokenization and ownership tests -mod tokenization; -mod voting; +mod detokenization; mod dividends; +mod tokenization; mod transfer_restrictions; -mod detokenization; +mod voting; // Insurance tests mod insurance; diff --git a/contracts/assetsup/src/tests/tokenization.rs b/contracts/assetsup/src/tests/tokenization.rs index 18d7bfa..bc1a024 100644 --- a/contracts/assetsup/src/tests/tokenization.rs +++ b/contracts/assetsup/src/tests/tokenization.rs @@ -7,9 +7,9 @@ fn test_tokenize_asset_success() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + let result = client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -21,7 +21,7 @@ fn test_tokenize_asset_success() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + assert_eq!(result.asset_id, 1); assert_eq!(result.total_supply, 1000000); assert_eq!(result.tokenizer, user1); @@ -34,9 +34,9 @@ fn test_tokenize_asset_already_tokenized() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -48,7 +48,7 @@ fn test_tokenize_asset_already_tokenized() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Try to tokenize again - should panic with AssetAlreadyTokenized client.tokenize_asset( &1u64, @@ -69,9 +69,9 @@ fn test_tokenize_asset_invalid_supply() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Should panic with InvalidTokenSupply error client.tokenize_asset( &1u64, @@ -91,9 +91,9 @@ fn test_mint_tokens_success() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -105,9 +105,9 @@ fn test_mint_tokens_success() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + let result = client.mint_tokens(&1u64, &500000i128, &user1); - + assert_eq!(result.total_supply, 1500000); assert_eq!(result.tokens_in_circulation, 1500000); } @@ -118,9 +118,9 @@ fn test_mint_tokens_unauthorized() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -132,7 +132,7 @@ fn test_mint_tokens_unauthorized() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // user2 is not tokenizer - should panic with Unauthorized client.mint_tokens(&1u64, &500000i128, &user2); } @@ -143,9 +143,9 @@ fn test_mint_tokens_not_tokenized() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Should panic with AssetNotTokenized error client.mint_tokens(&999u64, &500000i128, &user1); } @@ -155,9 +155,9 @@ fn test_burn_tokens_success() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -169,9 +169,9 @@ fn test_burn_tokens_success() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + let result = client.burn_tokens(&1u64, &200000i128, &user1); - + assert_eq!(result.total_supply, 800000); assert_eq!(result.tokens_in_circulation, 800000); } @@ -182,9 +182,9 @@ fn test_burn_tokens_insufficient_balance() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -196,7 +196,7 @@ fn test_burn_tokens_insufficient_balance() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Should panic with InsufficientBalance error client.burn_tokens(&1u64, &2000000i128, &user1); } @@ -206,9 +206,9 @@ fn test_transfer_tokens_success() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -220,13 +220,13 @@ fn test_transfer_tokens_success() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + client.transfer_tokens(&1u64, &user1, &user2, &300000i128); - + // Verify balances let balance1 = client.get_token_balance(&1u64, &user1); let balance2 = client.get_token_balance(&1u64, &user2); - + assert_eq!(balance1, 700000); assert_eq!(balance2, 300000); } @@ -237,9 +237,9 @@ fn test_transfer_tokens_insufficient_balance() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -251,7 +251,7 @@ fn test_transfer_tokens_insufficient_balance() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Should panic with InsufficientBalance error client.transfer_tokens(&1u64, &user1, &user2, &2000000i128); } @@ -262,9 +262,9 @@ fn test_transfer_tokens_locked() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -276,11 +276,11 @@ fn test_transfer_tokens_locked() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Lock tokens let future_time = env.ledger().timestamp() + 1000; client.lock_tokens(&1u64, &user1, &future_time, &user1); - + // Should panic with TokensAreLocked error client.transfer_tokens(&1u64, &user1, &user2, &100000i128); } @@ -290,9 +290,9 @@ fn test_lock_unlock_tokens() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -304,20 +304,20 @@ fn test_lock_unlock_tokens() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Initially not locked - assert_eq!(client.is_tokens_locked(&1u64, &user1), false); - + assert!(!client.is_tokens_locked(&1u64, &user1)); + // Lock tokens let future_time = env.ledger().timestamp() + 1000; client.lock_tokens(&1u64, &user1, &future_time, &user1); - - assert_eq!(client.is_tokens_locked(&1u64, &user1), true); - + + assert!(client.is_tokens_locked(&1u64, &user1)); + // Unlock tokens client.unlock_tokens(&1u64, &user1); - - assert_eq!(client.is_tokens_locked(&1u64, &user1), false); + + assert!(!client.is_tokens_locked(&1u64, &user1)); } #[test] @@ -326,9 +326,9 @@ fn test_lock_tokens_unauthorized() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -340,9 +340,9 @@ fn test_lock_tokens_unauthorized() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + let future_time = env.ledger().timestamp() + 1000; - + // user2 is not tokenizer - should panic with Unauthorized client.lock_tokens(&1u64, &user1, &future_time, &user2); } @@ -352,9 +352,9 @@ fn test_get_ownership_percentage() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -366,14 +366,14 @@ fn test_get_ownership_percentage() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Transfer 30% to user2 client.transfer_tokens(&1u64, &user1, &user2, &300000i128); - + // Check ownership percentages (in basis points) let percentage1 = client.get_ownership_percentage(&1u64, &user1); let percentage2 = client.get_ownership_percentage(&1u64, &user2); - + assert_eq!(percentage1, 7000); // 70% assert_eq!(percentage2, 3000); // 30% } @@ -383,9 +383,9 @@ fn test_get_token_holders() { let env = create_env(); let (admin, user1, user2, user3) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -397,15 +397,15 @@ fn test_get_token_holders() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Initially only user1 let holders = client.get_token_holders(&1u64); assert_eq!(holders.len(), 1); - + // Transfer to user2 and user3 client.transfer_tokens(&1u64, &user1, &user2, &300000i128); client.transfer_tokens(&1u64, &user1, &user3, &200000i128); - + // Now should have 3 holders let holders = client.get_token_holders(&1u64); assert_eq!(holders.len(), 3); @@ -416,9 +416,9 @@ fn test_update_valuation() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -430,9 +430,9 @@ fn test_update_valuation() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + client.update_valuation(&1u64, &2000000i128); - + let asset = client.get_tokenized_asset(&1u64); assert_eq!(asset.valuation, 2000000); } @@ -443,9 +443,9 @@ fn test_update_valuation_invalid() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -457,7 +457,7 @@ fn test_update_valuation_invalid() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Should panic with InvalidValuation error client.update_valuation(&1u64, &0i128); } diff --git a/contracts/assetsup/src/tests/transfer_restrictions.rs b/contracts/assetsup/src/tests/transfer_restrictions.rs index 2973cdf..8cc39c2 100644 --- a/contracts/assetsup/src/tests/transfer_restrictions.rs +++ b/contracts/assetsup/src/tests/transfer_restrictions.rs @@ -1,15 +1,15 @@ use crate::tests::helpers::*; use crate::types::AssetType; -use soroban_sdk::{String, Vec}; +use soroban_sdk::String; #[test] fn test_add_to_whitelist() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -21,14 +21,14 @@ fn test_add_to_whitelist() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Initially not whitelisted - assert_eq!(client.is_whitelisted(&1u64, &user2), false); - + assert!(!client.is_whitelisted(&1u64, &user2)); + // Add to whitelist client.add_to_whitelist(&1u64, &user2); - - assert_eq!(client.is_whitelisted(&1u64, &user2), true); + + assert!(client.is_whitelisted(&1u64, &user2)); } #[test] @@ -36,9 +36,9 @@ fn test_remove_from_whitelist() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -50,14 +50,14 @@ fn test_remove_from_whitelist() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Add to whitelist client.add_to_whitelist(&1u64, &user2); - assert_eq!(client.is_whitelisted(&1u64, &user2), true); - + assert!(client.is_whitelisted(&1u64, &user2)); + // Remove from whitelist client.remove_from_whitelist(&1u64, &user2); - assert_eq!(client.is_whitelisted(&1u64, &user2), false); + assert!(!client.is_whitelisted(&1u64, &user2)); } #[test] @@ -65,9 +65,9 @@ fn test_get_whitelist() { let env = create_env(); let (admin, user1, user2, user3) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -79,11 +79,11 @@ fn test_get_whitelist() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Add multiple addresses to whitelist client.add_to_whitelist(&1u64, &user2); client.add_to_whitelist(&1u64, &user3); - + let whitelist = client.get_whitelist(&1u64); assert_eq!(whitelist.len(), 2); } @@ -93,9 +93,9 @@ fn test_add_duplicate_to_whitelist() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -107,11 +107,11 @@ fn test_add_duplicate_to_whitelist() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Add to whitelist twice client.add_to_whitelist(&1u64, &user2); client.add_to_whitelist(&1u64, &user2); - + // Should still only have one entry let whitelist = client.get_whitelist(&1u64); assert_eq!(whitelist.len(), 1); @@ -122,9 +122,9 @@ fn test_set_transfer_restriction() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -136,10 +136,10 @@ fn test_set_transfer_restriction() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Set transfer restriction client.set_transfer_restriction(&1u64, &true); - + // Restriction should be set (no error means success) } @@ -148,9 +148,9 @@ fn test_transfer_with_whitelist() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -162,13 +162,13 @@ fn test_transfer_with_whitelist() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Add user2 to whitelist client.add_to_whitelist(&1u64, &user2); - + // Transfer should succeed client.transfer_tokens(&1u64, &user1, &user2, &100000i128); - + let balance = client.get_token_balance(&1u64, &user2); assert_eq!(balance, 100000); } @@ -178,9 +178,9 @@ fn test_empty_whitelist() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -192,7 +192,7 @@ fn test_empty_whitelist() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + let whitelist = client.get_whitelist(&1u64); assert_eq!(whitelist.len(), 0); } diff --git a/contracts/assetsup/src/tests/voting.rs b/contracts/assetsup/src/tests/voting.rs index b072bfc..0856870 100644 --- a/contracts/assetsup/src/tests/voting.rs +++ b/contracts/assetsup/src/tests/voting.rs @@ -7,9 +7,9 @@ fn test_cast_vote_success() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Tokenize asset client.tokenize_asset( &1u64, @@ -22,13 +22,13 @@ fn test_cast_vote_success() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Cast vote client.cast_vote(&1u64, &1u64, &user1); - + // Verify vote was recorded - assert_eq!(client.has_voted(&1u64, &1u64, &user1), true); - + assert!(client.has_voted(&1u64, &1u64, &user1)); + // Verify vote tally let tally = client.get_vote_tally(&1u64, &1u64); assert_eq!(tally, 1000000); // Full balance @@ -40,9 +40,9 @@ fn test_cast_vote_already_voted() { let env = create_env(); let (admin, user1, _, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -54,9 +54,9 @@ fn test_cast_vote_already_voted() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + client.cast_vote(&1u64, &1u64, &user1); - + // Try to vote again - should panic with AlreadyVoted client.cast_vote(&1u64, &1u64, &user1); } @@ -67,9 +67,9 @@ fn test_cast_vote_insufficient_voting_power() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + // Tokenize with high voting threshold client.tokenize_asset( &1u64, @@ -82,10 +82,10 @@ fn test_cast_vote_insufficient_voting_power() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Transfer small amount to user2 client.transfer_tokens(&1u64, &user1, &user2, &10000i128); - + // user2 doesn't have enough tokens - should panic with InsufficientVotingPower client.cast_vote(&1u64, &1u64, &user2); } @@ -95,9 +95,9 @@ fn test_proposal_passed() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -109,15 +109,15 @@ fn test_proposal_passed() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Transfer 60% to user2 client.transfer_tokens(&1u64, &user1, &user2, &600000i128); - + // user2 votes (60% of supply) client.cast_vote(&1u64, &1u64, &user2); - + // Proposal should pass (>50% threshold) - assert_eq!(client.proposal_passed(&1u64, &1u64), true); + assert!(client.proposal_passed(&1u64, &1u64)); } #[test] @@ -125,9 +125,9 @@ fn test_proposal_not_passed() { let env = create_env(); let (admin, user1, user2, _) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -139,15 +139,15 @@ fn test_proposal_not_passed() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Transfer 40% to user2 client.transfer_tokens(&1u64, &user1, &user2, &400000i128); - + // user2 votes (40% of supply) client.cast_vote(&1u64, &1u64, &user2); - + // Proposal should not pass (<50% threshold) - assert_eq!(client.proposal_passed(&1u64, &1u64), false); + assert!(!client.proposal_passed(&1u64, &1u64)); } #[test] @@ -155,9 +155,9 @@ fn test_multiple_voters() { let env = create_env(); let (admin, user1, user2, user3) = create_mock_addresses(&env); let client = initialize_contract(&env, &admin); - + env.mock_all_auths(); - + client.tokenize_asset( &1u64, &String::from_str(&env, "TST"), @@ -169,19 +169,19 @@ fn test_multiple_voters() { &String::from_str(&env, "A test tokenized asset"), &AssetType::Physical, ); - + // Distribute tokens client.transfer_tokens(&1u64, &user1, &user2, &300000i128); client.transfer_tokens(&1u64, &user1, &user3, &200000i128); - + // Multiple users vote client.cast_vote(&1u64, &1u64, &user1); // 500000 client.cast_vote(&1u64, &1u64, &user2); // 300000 - + // Total tally should be 800000 let tally = client.get_vote_tally(&1u64, &1u64); assert_eq!(tally, 800000); - + // Proposal should pass (80% > 50%) - assert_eq!(client.proposal_passed(&1u64, &1u64), true); + assert!(client.proposal_passed(&1u64, &1u64)); }