From a2dac9afbd2c06f83ebec7e2f6ba64f8d80a1781 Mon Sep 17 00:00:00 2001 From: casweeney Date: Sat, 14 Dec 2024 12:09:10 +0100 Subject: [PATCH 01/10] FEAT: added inspector_lands() in ILandRegistry interface --- land_registry/src/interface/land_register.cairo | 1 + land_registry/src/land_register.cairo | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/land_registry/src/interface/land_register.cairo b/land_registry/src/interface/land_register.cairo index 9c275ef8..721586a4 100644 --- a/land_registry/src/interface/land_register.cairo +++ b/land_registry/src/interface/land_register.cairo @@ -93,6 +93,7 @@ pub trait ILandRegistry { fn add_inspector(ref self: TContractState, inspector: ContractAddress); fn remove_inspector(ref self: TContractState, inspector: ContractAddress); fn get_all_inspectors(self: @TContractState) -> Array; + fn inspector_lands(self: @TContractState, inspector: ContractAddress) -> Array; fn get_user_type(self: @TContractState, userAddress: ContractAddress) -> felt252; diff --git a/land_registry/src/land_register.cairo b/land_registry/src/land_register.cairo index 1e4a2a09..b9266baa 100644 --- a/land_registry/src/land_register.cairo +++ b/land_registry/src/land_register.cairo @@ -432,6 +432,10 @@ pub mod LandRegistryContract { inspectors } + fn inspector_lands(self: @ContractState, inspector: ContractAddress) -> Array { + + } + fn create_listing(ref self: ContractState, land_id: u256, price: u256) -> u256 { let caller = get_caller_address(); From 1974f4da505a978b1e27e0ac07195b60a6f29094 Mon Sep 17 00:00:00 2001 From: casweeney Date: Sat, 14 Dec 2024 13:04:34 +0100 Subject: [PATCH 02/10] FEAT: implemented inspector_lands() function --- land_registry/src/land_register.cairo | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/land_registry/src/land_register.cairo b/land_registry/src/land_register.cairo index b9266baa..21ebdc90 100644 --- a/land_registry/src/land_register.cairo +++ b/land_registry/src/land_register.cairo @@ -1,6 +1,7 @@ #[starknet::contract] pub mod LandRegistryContract { - use OwnableComponent::InternalTrait; + use starknet::storage::StoragePathEntry; +use OwnableComponent::InternalTrait; use starknet::SyscallResultTrait; use starknet::{ get_caller_address, get_contract_address, get_block_timestamp, ContractAddress, syscalls, @@ -433,7 +434,24 @@ pub mod LandRegistryContract { } fn inspector_lands(self: @ContractState, inspector: ContractAddress) -> Array { + assert(self.registered_inspectors.entry(inspector).read(), 'unregistered inspector'); + let mut inspector_lands: Array = array![]; + + let land_count = self.land_count.read(); + let mut i: u256 = 1; + + while i < land_count + 1 { + let land = self.lands_registry.read(i); + + if land.inspector == inspector { + inspector_lands.append(land); + } + + i += 1; + }; + + inspector_lands } fn create_listing(ref self: ContractState, land_id: u256, price: u256) -> u256 { From 60a53da11fdf6bfbd293d9a23060adcbee748a27 Mon Sep 17 00:00:00 2001 From: casweeney Date: Sat, 14 Dec 2024 13:27:52 +0100 Subject: [PATCH 03/10] UPDATE: updated update_land() to accept land_status --- land_registry/src/interface/land_register.cairo | 2 +- land_registry/src/land_register.cairo | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/land_registry/src/interface/land_register.cairo b/land_registry/src/interface/land_register.cairo index 721586a4..23ec7135 100644 --- a/land_registry/src/interface/land_register.cairo +++ b/land_registry/src/interface/land_register.cairo @@ -75,7 +75,7 @@ pub trait ILandRegistry { fn get_land_count(self: @TContractState) -> u256; fn get_lands_by_owner(self: @TContractState, owner: ContractAddress) -> Span; fn get_all_lands(self: @TContractState) -> Span; - fn update_land(ref self: TContractState, land_id: u256, area: u256, land_use: LandUse); + fn update_land(ref self: TContractState, land_id: u256, area: u256, land_use: LandUse, land_status: LandStatus); fn approve_land(ref self: TContractState, land_id: u256); fn reject_land(ref self: TContractState, land_id: u256); fn is_inspector(self: @TContractState, inspector: ContractAddress) -> bool; diff --git a/land_registry/src/land_register.cairo b/land_registry/src/land_register.cairo index 21ebdc90..d1fbc333 100644 --- a/land_registry/src/land_register.cairo +++ b/land_registry/src/land_register.cairo @@ -227,11 +227,12 @@ use OwnableComponent::InternalTrait; lands.span() } - fn update_land(ref self: ContractState, land_id: u256, area: u256, land_use: LandUse) { + fn update_land(ref self: ContractState, land_id: u256, area: u256, land_use: LandUse, land_status: LandStatus) { assert(InternalFunctions::only_owner(@self, land_id), Errors::UPDATE_BY_LAND); let mut land = self.lands.read(land_id); land.area = area; land.land_use = land_use; + land.status = land_status; self.lands.write(land_id, land); self.emit(LandUpdated { land_id: land_id, area: area, land_use: land_use.into() }); From 89d36be8f0d347507b56f06fc1e35283248d57a7 Mon Sep 17 00:00:00 2001 From: casweeney Date: Sat, 14 Dec 2024 13:30:04 +0100 Subject: [PATCH 04/10] MOD: modified LandUpdate event --- land_registry/src/interface/land_register.cairo | 3 ++- land_registry/src/land_register.cairo | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/land_registry/src/interface/land_register.cairo b/land_registry/src/interface/land_register.cairo index 23ec7135..3de7d5d4 100644 --- a/land_registry/src/interface/land_register.cairo +++ b/land_registry/src/interface/land_register.cairo @@ -134,7 +134,8 @@ pub struct LandVerified { pub struct LandUpdated { pub land_id: u256, pub land_use: Option, - pub area: u256 + pub area: u256, + pub status: LandStatus } diff --git a/land_registry/src/land_register.cairo b/land_registry/src/land_register.cairo index d1fbc333..77e2a749 100644 --- a/land_registry/src/land_register.cairo +++ b/land_registry/src/land_register.cairo @@ -235,7 +235,7 @@ use OwnableComponent::InternalTrait; land.status = land_status; self.lands.write(land_id, land); - self.emit(LandUpdated { land_id: land_id, area: area, land_use: land_use.into() }); + self.emit(LandUpdated { land_id: land_id, area: area, land_use: land_use.into(), status: land_status }); } // Transfers land ownership to a new owner From 433ef620cd6f4f4f0d40c4bb7dd77b1d585f2092 Mon Sep 17 00:00:00 2001 From: casweeney Date: Sat, 14 Dec 2024 13:38:02 +0100 Subject: [PATCH 05/10] MOD: removed redundant assertion --- land_registry/src/land_register.cairo | 2 -- 1 file changed, 2 deletions(-) diff --git a/land_registry/src/land_register.cairo b/land_registry/src/land_register.cairo index 77e2a749..1c4d0aff 100644 --- a/land_registry/src/land_register.cairo +++ b/land_registry/src/land_register.cairo @@ -435,8 +435,6 @@ use OwnableComponent::InternalTrait; } fn inspector_lands(self: @ContractState, inspector: ContractAddress) -> Array { - assert(self.registered_inspectors.entry(inspector).read(), 'unregistered inspector'); - let mut inspector_lands: Array = array![]; let land_count = self.land_count.read(); From 3983cff1cf0fbb35153eafdaa2b3932f89957b1a Mon Sep 17 00:00:00 2001 From: casweeney Date: Sat, 14 Dec 2024 14:11:37 +0100 Subject: [PATCH 06/10] FIXES: fixed test errors due to update_land() modification --- ...t_integration_land_registry_and_land_nft.cairo | 15 ++++++++++----- land_registry/tests/test_land_register.cairo | 6 ++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/land_registry/tests/test_integration_land_registry_and_land_nft.cairo b/land_registry/tests/test_integration_land_registry_and_land_nft.cairo index 488d1d76..5896e499 100644 --- a/land_registry/tests/test_integration_land_registry_and_land_nft.cairo +++ b/land_registry/tests/test_integration_land_registry_and_land_nft.cairo @@ -213,6 +213,7 @@ fn test_register_update_approve_and_transfer() { let location: Location = Location { latitude: 1, longitude: 2 }; let area: u256 = 1000; let land_use = LandUse::Residential; + let land_status = LandStatus::Pending; // register and add inspector start_cheat_caller_address(contract_address, owner); @@ -222,7 +223,7 @@ fn test_register_update_approve_and_transfer() { // update land let new_area: u256 = 1000; let new_land_use = LandUse::Residential; - land_register_dispatcher.update_land(land_id, new_area, new_land_use); + land_register_dispatcher.update_land(land_id, new_area, new_land_use, land_status); stop_cheat_caller_address(contract_address); @@ -278,7 +279,8 @@ fn test_register_approve_update_and_transfer() { start_cheat_caller_address(contract_address, owner); let new_area: u256 = 1000; let new_land_use = LandUse::Residential; - land_register_dispatcher.update_land(land_id, new_area, new_land_use); + let land_status = LandStatus::Approved; + land_register_dispatcher.update_land(land_id, new_area, new_land_use, land_status); stop_cheat_caller_address(contract_address); let mut spy = spy_events(); @@ -312,6 +314,7 @@ fn test_register_approve_transfer_and_update_by_new_owner() { let location: Location = Location { latitude: 1, longitude: 2 }; let area: u256 = 1000; let land_use = LandUse::Residential; + let land_status = LandStatus::Approved; // register and add inspector start_cheat_caller_address(contract_address, owner); @@ -333,7 +336,7 @@ fn test_register_approve_transfer_and_update_by_new_owner() { start_cheat_caller_address(contract_address, new_owner); let new_area: u256 = 2000; let new_land_use = LandUse::Commercial; - land_register_dispatcher.update_land(land_id, new_area, new_land_use); + land_register_dispatcher.update_land(land_id, new_area, new_land_use, land_status); } #[test] @@ -369,6 +372,7 @@ fn previous_owner_tries_to_update_after_transfer_should_fail() { let location: Location = Location { latitude: 1, longitude: 2 }; let area: u256 = 1000; let land_use = LandUse::Residential; + let land_status = LandStatus::Approved; // register and add inspector start_cheat_caller_address(contract_address, owner); @@ -389,7 +393,7 @@ fn previous_owner_tries_to_update_after_transfer_should_fail() { // update land let new_area: u256 = 2000; let new_land_use = LandUse::Commercial; - land_register_dispatcher.update_land(land_id, new_area, new_land_use); + land_register_dispatcher.update_land(land_id, new_area, new_land_use, land_status); } #[test] @@ -449,6 +453,7 @@ fn test_try_to_update_a_not_existant_land_should_fail() { let location: Location = Location { latitude: 1, longitude: 2 }; let area: u256 = 1000; let land_use = LandUse::Residential; + let land_status = LandStatus::Approved; // register and add inspector start_cheat_caller_address(contract_address, owner); @@ -457,5 +462,5 @@ fn test_try_to_update_a_not_existant_land_should_fail() { start_cheat_caller_address(contract_address, not_owner); let new_area = 2000; let new_land_use = LandUse::Commercial; - land_register_dispatcher.update_land(land_id, new_area, new_land_use); + land_register_dispatcher.update_land(land_id, new_area, new_land_use, land_status); } diff --git a/land_registry/tests/test_land_register.cairo b/land_registry/tests/test_land_register.cairo index 87da0871..7ce75109 100644 --- a/land_registry/tests/test_land_register.cairo +++ b/land_registry/tests/test_land_register.cairo @@ -424,6 +424,7 @@ fn test_can_update_land() { let location = Location { latitude: 1, longitude: 2 }; let initial_area = 1000; let initial_land_use = LandUse::Residential; + let land_status = LandStatus::Approved; // Register land as owner start_cheat_caller_address(contract_address, owner_address); @@ -434,12 +435,13 @@ fn test_can_update_land() { let new_land_use = LandUse::Commercial; // Update land - land_register_dispatcher.update_land(land_id, new_area, new_land_use); + land_register_dispatcher.update_land(land_id, new_area, new_land_use, land_status); // Verify updates let updated_land = land_register_dispatcher.get_land(land_id); assert(updated_land.area == new_area, 'Area not updated correctly'); assert(updated_land.land_use == new_land_use, 'Land use not updated correctly'); + assert(updated_land.status == land_status, 'Land status not updated'); stop_cheat_caller_address(contract_address); } @@ -464,7 +466,7 @@ fn test_update_land_by_unauthorized_user_will_fail() { // Attempt to update land as unauthorized user start_cheat_caller_address(contract_address, unauthorized_address); - land_register_dispatcher.update_land(land_id, 1500, LandUse::Commercial); // This should panic + land_register_dispatcher.update_land(land_id, 1500, LandUse::Commercial, LandStatus::Approved); // This should panic stop_cheat_caller_address(contract_address); } From ec48a3f4dab5752e6bd011ef480b9741cec56dc7 Mon Sep 17 00:00:00 2001 From: casweeney Date: Sat, 14 Dec 2024 15:46:59 +0100 Subject: [PATCH 07/10] TEST: implemented test_inspector_lands() --- land_registry/src/land_register.cairo | 47 +++++++++++--------- land_registry/tests/test_land_register.cairo | 41 +++++++++++++++++ 2 files changed, 66 insertions(+), 22 deletions(-) diff --git a/land_registry/src/land_register.cairo b/land_registry/src/land_register.cairo index 1c4d0aff..03633140 100644 --- a/land_registry/src/land_register.cairo +++ b/land_registry/src/land_register.cairo @@ -1,7 +1,6 @@ #[starknet::contract] pub mod LandRegistryContract { - use starknet::storage::StoragePathEntry; -use OwnableComponent::InternalTrait; + use OwnableComponent::InternalTrait; use starknet::SyscallResultTrait; use starknet::{ get_caller_address, get_contract_address, get_block_timestamp, ContractAddress, syscalls, @@ -379,8 +378,10 @@ use OwnableComponent::InternalTrait; } fn set_land_inspector(ref self: ContractState, land_id: u256, inspector: ContractAddress) { - assert(InternalFunctions::only_owner(@self, land_id), Errors::OWNER_MK_INSPECTOR); + assert(self.only_owner(land_id), Errors::OWNER_MK_INSPECTOR); + let prev_land_count = self.lands_assigned_to_inspector.read(inspector); + self.land_inspectors.write(land_id, inspector); self.lands_assigned_to_inspector.write(inspector, prev_land_count + 1); @@ -391,6 +392,27 @@ use OwnableComponent::InternalTrait; self.emit(LandInspectorSet { land_id, inspector }); } + fn inspector_lands(self: @ContractState, inspector: ContractAddress) -> Array { + let mut inspector_lands: Array = array![]; + + let land_count = self.land_count.read(); + let mut i: u256 = 1; + + while i < land_count + 1 { + let land_registry: Land = self.lands_registry.read(i); + let land_inspector = self.land_inspectors.read(land_registry.land_id); + + if land_inspector == inspector { + let land = self.lands.read(land_registry.land_id); + inspector_lands.append(land); + } + + i += 1; + }; + + inspector_lands + } + fn get_land_inspector(self: @ContractState, land_id: u256) -> ContractAddress { self.land_inspectors.read(land_id) } @@ -434,25 +456,6 @@ use OwnableComponent::InternalTrait; inspectors } - fn inspector_lands(self: @ContractState, inspector: ContractAddress) -> Array { - let mut inspector_lands: Array = array![]; - - let land_count = self.land_count.read(); - let mut i: u256 = 1; - - while i < land_count + 1 { - let land = self.lands_registry.read(i); - - if land.inspector == inspector { - inspector_lands.append(land); - } - - i += 1; - }; - - inspector_lands - } - fn create_listing(ref self: ContractState, land_id: u256, price: u256) -> u256 { let caller = get_caller_address(); diff --git a/land_registry/tests/test_land_register.cairo b/land_registry/tests/test_land_register.cairo index 7ce75109..d63ec690 100644 --- a/land_registry/tests/test_land_register.cairo +++ b/land_registry/tests/test_land_register.cairo @@ -1246,3 +1246,44 @@ fn test_set_land_inspector() { ); stop_cheat_caller_address(contract_address); } + +#[test] +fn test_inspector_lands() { + let contract_address = deploy("LandRegistryContract"); + + // Instance of LandRegistryContract + let land_register_dispatcher = ILandRegistryDispatcher { contract_address }; + + start_cheat_max_fee(contract_address, 10000000000000000000); + + // Set up test data + let owner_address = starknet::contract_address_const::<0x123>(); + let inspector_address = starknet::contract_address_const::<0x456>(); + let location = Location { latitude: 1, longitude: 2 }; + let area = 1000; + let land_use = LandUse::Residential; + + // Register land as owner + start_cheat_caller_address(contract_address, owner_address); + let land_id = land_register_dispatcher.register_land(location, area, land_use); + stop_cheat_caller_address(contract_address); + + // Get the registered land + let registered_land = land_register_dispatcher.get_land(land_id); + + // Assert land details are correct + assert(registered_land.owner == owner_address, 'Wrong owner'); + assert(registered_land.location == location, 'Wrong location'); + assert(registered_land.area == area, 'Wrong area'); + + // Set inspector as owner address + start_cheat_caller_address(contract_address, owner_address); + land_register_dispatcher.set_land_inspector(land_id, inspector_address); + stop_cheat_caller_address(contract_address); + + let inspector_lands = land_register_dispatcher.inspector_lands(inspector_address); + + println!("Inspector land: {}", inspector_lands.len()); + + assert(inspector_lands.len() == 1, 'Wrong inspector land count'); +} From 1d4309253bf87c4909181d3eda41da914cbe4bea Mon Sep 17 00:00:00 2001 From: casweeney Date: Sat, 14 Dec 2024 15:51:40 +0100 Subject: [PATCH 08/10] LINTING: scarb fmt --- .../src/interface/land_register.cairo | 8 +++++++- land_registry/src/land_register.cairo | 19 +++++++++++++++---- land_registry/tests/test_land_register.cairo | 3 ++- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/land_registry/src/interface/land_register.cairo b/land_registry/src/interface/land_register.cairo index 3de7d5d4..1b89023b 100644 --- a/land_registry/src/interface/land_register.cairo +++ b/land_registry/src/interface/land_register.cairo @@ -75,7 +75,13 @@ pub trait ILandRegistry { fn get_land_count(self: @TContractState) -> u256; fn get_lands_by_owner(self: @TContractState, owner: ContractAddress) -> Span; fn get_all_lands(self: @TContractState) -> Span; - fn update_land(ref self: TContractState, land_id: u256, area: u256, land_use: LandUse, land_status: LandStatus); + fn update_land( + ref self: TContractState, + land_id: u256, + area: u256, + land_use: LandUse, + land_status: LandStatus + ); fn approve_land(ref self: TContractState, land_id: u256); fn reject_land(ref self: TContractState, land_id: u256); fn is_inspector(self: @TContractState, inspector: ContractAddress) -> bool; diff --git a/land_registry/src/land_register.cairo b/land_registry/src/land_register.cairo index 03633140..57d80bd5 100644 --- a/land_registry/src/land_register.cairo +++ b/land_registry/src/land_register.cairo @@ -226,7 +226,13 @@ pub mod LandRegistryContract { lands.span() } - fn update_land(ref self: ContractState, land_id: u256, area: u256, land_use: LandUse, land_status: LandStatus) { + fn update_land( + ref self: ContractState, + land_id: u256, + area: u256, + land_use: LandUse, + land_status: LandStatus + ) { assert(InternalFunctions::only_owner(@self, land_id), Errors::UPDATE_BY_LAND); let mut land = self.lands.read(land_id); land.area = area; @@ -234,7 +240,12 @@ pub mod LandRegistryContract { land.status = land_status; self.lands.write(land_id, land); - self.emit(LandUpdated { land_id: land_id, area: area, land_use: land_use.into(), status: land_status }); + self + .emit( + LandUpdated { + land_id: land_id, area: area, land_use: land_use.into(), status: land_status + } + ); } // Transfers land ownership to a new owner @@ -403,13 +414,13 @@ pub mod LandRegistryContract { let land_inspector = self.land_inspectors.read(land_registry.land_id); if land_inspector == inspector { - let land = self.lands.read(land_registry.land_id); + let land = self.lands.read(land_registry.land_id); inspector_lands.append(land); } i += 1; }; - + inspector_lands } diff --git a/land_registry/tests/test_land_register.cairo b/land_registry/tests/test_land_register.cairo index d63ec690..4c314e42 100644 --- a/land_registry/tests/test_land_register.cairo +++ b/land_registry/tests/test_land_register.cairo @@ -466,7 +466,8 @@ fn test_update_land_by_unauthorized_user_will_fail() { // Attempt to update land as unauthorized user start_cheat_caller_address(contract_address, unauthorized_address); - land_register_dispatcher.update_land(land_id, 1500, LandUse::Commercial, LandStatus::Approved); // This should panic + land_register_dispatcher + .update_land(land_id, 1500, LandUse::Commercial, LandStatus::Approved); // This should panic stop_cheat_caller_address(contract_address); } From e8da8232001ae759df6fac6d023ed13cc53085a9 Mon Sep 17 00:00:00 2001 From: casweeney Date: Sat, 14 Dec 2024 16:09:39 +0100 Subject: [PATCH 09/10] Removed redundant assertions --- land_registry/tests/test_land_register.cairo | 8 -------- 1 file changed, 8 deletions(-) diff --git a/land_registry/tests/test_land_register.cairo b/land_registry/tests/test_land_register.cairo index 4c314e42..d15eaca9 100644 --- a/land_registry/tests/test_land_register.cairo +++ b/land_registry/tests/test_land_register.cairo @@ -1269,14 +1269,6 @@ fn test_inspector_lands() { let land_id = land_register_dispatcher.register_land(location, area, land_use); stop_cheat_caller_address(contract_address); - // Get the registered land - let registered_land = land_register_dispatcher.get_land(land_id); - - // Assert land details are correct - assert(registered_land.owner == owner_address, 'Wrong owner'); - assert(registered_land.location == location, 'Wrong location'); - assert(registered_land.area == area, 'Wrong area'); - // Set inspector as owner address start_cheat_caller_address(contract_address, owner_address); land_register_dispatcher.set_land_inspector(land_id, inspector_address); From d6cf38764239a6f1434c7df3a0d7d0ab543f9d33 Mon Sep 17 00:00:00 2001 From: casweeney Date: Sat, 14 Dec 2024 16:12:55 +0100 Subject: [PATCH 10/10] Removed unused print --- land_registry/tests/test_land_register.cairo | 2 -- 1 file changed, 2 deletions(-) diff --git a/land_registry/tests/test_land_register.cairo b/land_registry/tests/test_land_register.cairo index d15eaca9..64977010 100644 --- a/land_registry/tests/test_land_register.cairo +++ b/land_registry/tests/test_land_register.cairo @@ -1276,7 +1276,5 @@ fn test_inspector_lands() { let inspector_lands = land_register_dispatcher.inspector_lands(inspector_address); - println!("Inspector land: {}", inspector_lands.len()); - assert(inspector_lands.len() == 1, 'Wrong inspector land count'); }