From 269e490287d02b7be9fe307b57b7892beaeb20c5 Mon Sep 17 00:00:00 2001 From: Thomas Marchand Date: Tue, 10 Oct 2023 15:09:24 +0700 Subject: [PATCH] feature: reverse resolving (#9) * feat: add set_address_to_domain to override reverse resolving * feat: add reverse resolving --- src/interface/naming.cairo | 6 ++- src/naming/main.cairo | 65 +++++++++++++++++++++++----- src/tests/naming/test_usecases.cairo | 65 ++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 13 deletions(-) diff --git a/src/interface/naming.cairo b/src/interface/naming.cairo index f28046b..7e6194b 100644 --- a/src/interface/naming.cairo +++ b/src/interface/naming.cairo @@ -12,7 +12,7 @@ trait INaming { fn domain_to_address(self: @TContractState, domain: Span) -> ContractAddress; - fn address_to_domain(self: @TContractState, address: ContractAddress) -> Array; + fn address_to_domain(self: @TContractState, address: ContractAddress) -> Span; // external fn buy( @@ -39,6 +39,10 @@ trait INaming { fn reset_subdomains(ref self: TContractState, domain: Span); + fn set_address_to_domain(ref self: TContractState, domain: Span); + + fn reset_address_to_domain(ref self: TContractState); + // admin fn set_admin(ref self: TContractState, new_admin: ContractAddress); diff --git a/src/naming/main.cairo b/src/naming/main.cairo index 101d4ad..2a02efa 100644 --- a/src/naming/main.cairo +++ b/src/naming/main.cairo @@ -29,7 +29,8 @@ mod Naming { enum Event { DomainMint: DomainMint, DomainRenewal: DomainRenewal, - DomainToResolver: DomainToResolver, + DomainResolverUpdate: DomainResolverUpdate, + AddressToDomainUpdate: AddressToDomainUpdate, DomainTransfer: DomainTransfer, SubdomainsReset: SubdomainsReset, SaleMetadata: SaleMetadata, @@ -51,12 +52,19 @@ mod Naming { } #[derive(Drop, starknet::Event)] - struct DomainToResolver { + struct DomainResolverUpdate { #[key] domain: Span, resolver: ContractAddress } + #[derive(Drop, starknet::Event)] + struct AddressToDomainUpdate { + #[key] + address: ContractAddress, + domain: Span, + } + #[derive(Drop, starknet::Event)] struct DomainTransfer { #[key] @@ -207,11 +215,11 @@ mod Naming { } // This function allows to find which domain to use to display an account - fn address_to_domain(self: @ContractState, address: ContractAddress) -> Array { + fn address_to_domain(self: @ContractState, address: ContractAddress) -> Span { let mut domain = ArrayTrait::new(); self._address_to_domain_util(address, ref domain); if domain.len() != 0 && self.domain_to_address(domain.span()) == address { - domain + domain.span() } else { let identity = IIdentityDispatcher { contract_address: self.starknetid_contract.read() @@ -221,9 +229,7 @@ mod Naming { let id_hashed_domain = identity .get_verifier_data(id, 'name', get_contract_address(), 0); let domain = self.unhash_domain(id_hashed_domain); - assert( - self.domain_to_address(domain.span()) == address, 'domain not pointing back' - ); + assert(self.domain_to_address(domain) == address, 'domain not pointing back'); domain } } @@ -360,6 +366,26 @@ mod Naming { self.emit(Event::SubdomainsReset(SubdomainsReset { domain: domain, })); } + + // will override your main id + fn set_address_to_domain(ref self: ContractState, domain: Span) { + let address = get_caller_address(); + assert(self.domain_to_address(domain) == address, 'domain not pointing back'); + self.emit(Event::AddressToDomainUpdate(AddressToDomainUpdate { address, domain })); + self.set_address_to_domain_util(address, domain); + } + + fn reset_address_to_domain(ref self: ContractState) { + let address = get_caller_address(); + self + .emit( + Event::AddressToDomainUpdate( + AddressToDomainUpdate { address, domain: array![].span() } + ) + ); + self.set_address_to_domain_util(address, array![0].span()); + } + // ADMIN fn set_admin(ref self: ContractState, new_admin: ContractAddress) { @@ -412,7 +438,7 @@ mod Naming { return hashed_domain; } - fn unhash_domain(self: @ContractState, domain_hash: felt252) -> Array { + fn unhash_domain(self: @ContractState, domain_hash: felt252) -> Span { let mut i = 0; let mut domain = ArrayTrait::new(); loop { @@ -421,8 +447,9 @@ mod Naming { break; } domain.append(domain_part); + i += 1; }; - domain + domain.span() } fn assert_purchase_is_possible( @@ -512,6 +539,20 @@ mod Naming { } } + fn set_address_to_domain_util( + ref self: ContractState, address: ContractAddress, mut domain: Span + ) { + match domain.pop_back() { + Option::Some(domain_part) => { + self._address_to_domain.write((address, domain.len()), *domain_part); + return self.set_address_to_domain_util(address, domain); + }, + Option::None => { + return; + } + } + } + fn domain_to_resolver( self: @ContractState, domain: Span, parent_start_id: u32 ) -> (ContractAddress, u32) { @@ -588,7 +629,7 @@ mod Naming { key: 1, parent_key: 0, }; - self._hash_to_domain.write((hashed_domain, 0), hashed_domain); + self._hash_to_domain.write((hashed_domain, 0), domain); self._domain_data.write(hashed_domain, data); self.emit(Event::DomainMint(DomainMint { domain, owner: id, expiry })); @@ -597,8 +638,8 @@ mod Naming { if (resolver.into() != 0) { self .emit( - Event::DomainToResolver( - DomainToResolver { domain: array![domain].span(), resolver } + Event::DomainResolverUpdate( + DomainResolverUpdate { domain: array![domain].span(), resolver } ) ); } diff --git a/src/tests/naming/test_usecases.cairo b/src/tests/naming/test_usecases.cairo index 7411448..1211cd5 100644 --- a/src/tests/naming/test_usecases.cairo +++ b/src/tests/naming/test_usecases.cairo @@ -202,3 +202,68 @@ fn test_non_owner_can_renew_domain() { eth.approve(naming.contract_address, price); naming.renew(domain_name, 365, ContractAddressZeroable::zero(), 0, 0); } + + +#[test] +#[available_gas(2000000000)] +fn test_set_address_to_domain() { + // setup + let (eth, pricing, identity, naming) = deploy(); + let caller = contract_address_const::<0x123>(); + set_contract_address(caller); + let id1: u128 = 1; + let id2: u128 = 2; + let first_domain_top: felt252 = 82939898252385817; + let second_domain_top: felt252 = 3151716132312299378; + + //we mint the ids + identity.mint(id1); + identity.mint(id2); + + // buy the domains + let (_, price1) = pricing.compute_buy_price(11, 365); + eth.approve(naming.contract_address, price1); + naming + .buy( + id1, + first_domain_top, + 365, + ContractAddressZeroable::zero(), + ContractAddressZeroable::zero(), + 0, + 0 + ); + + let (_, price2) = pricing.compute_buy_price(12, 365); + eth.approve(naming.contract_address, price2); + naming + .buy( + id2, + second_domain_top, + 365, + ContractAddressZeroable::zero(), + ContractAddressZeroable::zero(), + 0, + 0 + ); + + // let's try the resolving + let first_domain = array![first_domain_top].span(); + assert(naming.domain_to_address(first_domain) == caller, 'wrong domain target'); + + // set reverse resolving + identity.set_main_id(id1); + let expect_domain1 = naming.address_to_domain(caller); + assert(expect_domain1 == first_domain, 'wrong rev resolving 1'); + + // override reverse resolving + let second_domain = array![second_domain_top].span(); + naming.set_address_to_domain(second_domain); + let expect_domain2 = naming.address_to_domain(caller); + assert(expect_domain2 == second_domain, 'wrong rev resolving 2'); + + // remove override + naming.reset_address_to_domain(); + let expect_domain1 = naming.address_to_domain(caller); + assert(expect_domain1 == first_domain, 'wrong rev resolving b'); +}