From e5bf9ce112563aee1a54baf41daeadef6563bcf5 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 9 Oct 2023 16:32:33 +0200 Subject: [PATCH 1/5] feat: add hint parameter --- src/interface/naming.cairo | 8 ++++++-- src/interface/resolver.cairo | 4 +++- src/naming/main.cairo | 18 ++++++++++++------ src/tests/naming/test_features.cairo | 7 +++++-- src/tests/naming/test_usecases.cairo | 11 +++++++---- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/interface/naming.cairo b/src/interface/naming.cairo index f28046b..00c24ab 100644 --- a/src/interface/naming.cairo +++ b/src/interface/naming.cairo @@ -4,13 +4,17 @@ use naming::naming::main::Naming::{Discount, DomainData}; #[starknet::interface] trait INaming { // view - fn resolve(self: @TContractState, domain: Span, field: felt252) -> felt252; + fn resolve( + self: @TContractState, domain: Span, field: felt252, hint: Span + ) -> felt252; fn domain_to_data(self: @TContractState, domain: Span) -> DomainData; fn domain_to_id(self: @TContractState, domain: Span) -> u128; - fn domain_to_address(self: @TContractState, domain: Span) -> ContractAddress; + fn domain_to_address( + self: @TContractState, domain: Span, hint: Span + ) -> ContractAddress; fn address_to_domain(self: @TContractState, address: ContractAddress) -> Array; diff --git a/src/interface/resolver.cairo b/src/interface/resolver.cairo index 37eaf01..ef719c6 100644 --- a/src/interface/resolver.cairo +++ b/src/interface/resolver.cairo @@ -2,5 +2,7 @@ use starknet::ContractAddress; #[starknet::interface] trait IResolver { - fn resolve(self: @TContractState, domain: Span, field: felt252) -> felt252; + fn resolve( + self: @TContractState, domain: Span, field: felt252, hint: Span + ) -> felt252; } diff --git a/src/naming/main.cairo b/src/naming/main.cairo index 101d4ad..e1dffd8 100644 --- a/src/naming/main.cairo +++ b/src/naming/main.cairo @@ -130,11 +130,13 @@ mod Naming { // For example, it allows to find the Bitcoin address of Alice.stark by calling // naming.resolve(['alice'], 'bitcoin') // Use it with caution in smartcontracts as it can call untrusted contracts - fn resolve(self: @ContractState, domain: Span, field: felt252) -> felt252 { + fn resolve( + self: @ContractState, domain: Span, field: felt252, hint: Span + ) -> felt252 { let (resolver, parent_start) = self.domain_to_resolver(domain, 0); if (resolver != ContractAddressZeroable::zero()) { IResolverDispatcher { contract_address: resolver } - .resolve(domain.slice(parent_start, domain.len() - parent_start), field) + .resolve(domain.slice(parent_start, domain.len() - parent_start), field, hint) } else { let domain_data = self._domain_data.read(self.hash_domain(domain)); // circuit breaker for root domain @@ -162,9 +164,11 @@ mod Naming { // This functions allows to resolve a domain to a native address. Its output is designed // to be used as a parameter for other functions (for example if you want to send ERC20 // to a .stark) - fn domain_to_address(self: @ContractState, domain: Span) -> ContractAddress { + fn domain_to_address( + self: @ContractState, domain: Span, hint: Span + ) -> ContractAddress { // resolve must be performed first because it calls untrusted resolving contracts - let resolve_result = self.resolve(domain, 'starknet'); + let resolve_result = self.resolve(domain, 'starknet', hint); if resolve_result != 0 { let addr: Option = resolve_result.try_into(); return addr.unwrap(); @@ -210,7 +214,8 @@ mod Naming { fn address_to_domain(self: @ContractState, address: ContractAddress) -> Array { let mut domain = ArrayTrait::new(); self._address_to_domain_util(address, ref domain); - if domain.len() != 0 && self.domain_to_address(domain.span()) == address { + if domain.len() != 0 + && self.domain_to_address(domain.span(), array![].span()) == address { domain } else { let identity = IIdentityDispatcher { @@ -222,7 +227,8 @@ mod Naming { .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' + self.domain_to_address(domain.span(), array![].span()) == address, + 'domain not pointing back' ); domain } diff --git a/src/tests/naming/test_features.cairo b/src/tests/naming/test_features.cairo index 870fdd7..92e49ad 100644 --- a/src/tests/naming/test_features.cairo +++ b/src/tests/naming/test_features.cairo @@ -62,7 +62,10 @@ fn test_subdomains() { // we transfer hello.th0rgal.stark to id2 naming.transfer_domain(subdomain, id2); - assert(naming.domain_to_address(subdomain) == caller, 'wrong subdomain initial target'); + assert( + naming.domain_to_address(subdomain, array![].span()) == caller, + 'wrong subdomain initial target' + ); // and make sure the owner has been updated assert(naming.domain_to_id(subdomain) == id2, 'owner not updated correctly'); @@ -77,7 +80,7 @@ fn test_subdomains() { // ensure the subdomain was reset assert( - naming.domain_to_address(subdomain) == ContractAddressZeroable::zero(), + naming.domain_to_address(subdomain, array![].span()) == ContractAddressZeroable::zero(), 'target not updated correctly' ); } diff --git a/src/tests/naming/test_usecases.cairo b/src/tests/naming/test_usecases.cairo index 7411448..b0f5edb 100644 --- a/src/tests/naming/test_usecases.cairo +++ b/src/tests/naming/test_usecases.cairo @@ -51,9 +51,9 @@ fn test_basic_usage() { // let's try the resolving let domain = array![th0rgal].span(); // by default we should have nothing written - assert(naming.resolve(domain, 'starknet') == 0, 'non empty starknet field'); + assert(naming.resolve(domain, 'starknet', array![].span()) == 0, 'non empty starknet field'); // so it should resolve to the starknetid owner - assert(naming.domain_to_address(domain) == caller, 'wrong domain target'); + assert(naming.domain_to_address(domain, array![].span()) == caller, 'wrong domain target'); // let's try reverse resolving identity.set_main_id(id); @@ -65,9 +65,12 @@ fn test_basic_usage() { identity.set_user_data(id, 'starknet', new_target.into(), 0); // now we should have nothing written - assert(naming.resolve(domain, 'starknet') == new_target.into(), 'wrong starknet field'); + assert( + naming.resolve(domain, 'starknet', array![].span()) == new_target.into(), + 'wrong starknet field' + ); // and it should resolve to the new domain target - assert(naming.domain_to_address(domain) == new_target, 'wrong domain target'); + assert(naming.domain_to_address(domain, array![].span()) == new_target, 'wrong domain target'); // testing ownership transfer let new_id = 2; From eb8c583cac038eb4502a5b85ec36e904723ba6f0 Mon Sep 17 00:00:00 2001 From: Iris Date: Thu, 2 Nov 2023 14:43:38 +0100 Subject: [PATCH 2/5] feat: add set_domain_to_resolver function --- src/interface/naming.cairo | 2 ++ src/naming/main.cairo | 20 +++++++++++++++++++ src/tests/naming/test_usecases.cairo | 29 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/src/interface/naming.cairo b/src/interface/naming.cairo index 7f3cc42..73d2d64 100644 --- a/src/interface/naming.cairo +++ b/src/interface/naming.cairo @@ -47,6 +47,8 @@ trait INaming { fn reset_address_to_domain(ref self: TContractState); + fn set_domain_to_resolver(ref self: TContractState, domain: Span, resolver: ContractAddress); + // admin fn set_admin(ref self: TContractState, new_admin: ContractAddress); diff --git a/src/naming/main.cairo b/src/naming/main.cairo index 23e2659..b090e30 100644 --- a/src/naming/main.cairo +++ b/src/naming/main.cairo @@ -376,6 +376,26 @@ mod Naming { self.set_address_to_domain_util(address, array![0].span()); } + fn set_domain_to_resolver( + ref self: ContractState, domain: Span, resolver: ContractAddress + ) { + self.assert_control_domain(domain, get_caller_address()); + + // Write domain owner + let hashed_domain = self.hash_domain(domain); + let current_domain_data = self._domain_data.read(hashed_domain); + let new_domain_data = DomainData { + owner: current_domain_data.owner, + resolver, + address: current_domain_data.address, + expiry: current_domain_data.expiry, + key: current_domain_data.key, + parent_key: current_domain_data.parent_key, + }; + self._domain_data.write(hashed_domain, new_domain_data); + self.emit(Event::DomainResolverUpdate(DomainResolverUpdate { domain, resolver })); + } + // ADMIN fn set_admin(ref self: ContractState, new_admin: ContractAddress) { diff --git a/src/tests/naming/test_usecases.cairo b/src/tests/naming/test_usecases.cairo index 15b76c7..f063cb7 100644 --- a/src/tests/naming/test_usecases.cairo +++ b/src/tests/naming/test_usecases.cairo @@ -272,3 +272,32 @@ fn test_set_address_to_domain() { let expect_domain1 = naming.address_to_domain(caller); assert(expect_domain1 == first_domain, 'wrong rev resolving b'); } + +#[test] +#[available_gas(2000000000)] +fn test_set_domain_to_resolver() { + // setup + let (eth, pricing, identity, naming) = deploy(); + let caller = contract_address_const::<0x123>(); + set_contract_address(caller); + let id1: u128 = 1; + let domain: felt252 = 82939898252385817; + + //we mint the id + identity.mint(id1); + + // buy the domain + let (_, price1) = pricing.compute_buy_price(11, 365); + eth.approve(naming.contract_address, price1); + naming + .buy( + id1, domain, 365, ContractAddressZeroable::zero(), ContractAddressZeroable::zero(), 0, 0 + ); + + // set resolver + let resolver = contract_address_const::<0x456>(); + naming.set_domain_to_resolver(array![domain].span(), resolver); + + let data = naming.domain_to_data(array![domain].span()); + assert(data.resolver == resolver, 'wrong resolver'); +} From 2591df15b2cf5958be3a1c5399ffbdb4879d0b78 Mon Sep 17 00:00:00 2001 From: Iris Date: Thu, 2 Nov 2023 15:41:21 +0100 Subject: [PATCH 3/5] fix: tests errors --- src/tests/naming/common.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/naming/common.cairo b/src/tests/naming/common.cairo index 1e42475..5c55de0 100644 --- a/src/tests/naming/common.cairo +++ b/src/tests/naming/common.cairo @@ -30,7 +30,7 @@ fn deploy() -> (IERC20CamelDispatcher, IPricingDispatcher, IIdentityDispatcher, let pricing = utils::deploy(Pricing::TEST_CLASS_HASH, array![eth.into()]); // identity - let identity = utils::deploy(Identity::TEST_CLASS_HASH, ArrayTrait::::new()); + let identity = utils::deploy(Identity::TEST_CLASS_HASH, array![0]); // naming let admin = 0x123; From 8e7109d6f2352a06ea5b4e3349d23a5073c2a758 Mon Sep 17 00:00:00 2001 From: Iris Date: Fri, 3 Nov 2023 10:29:13 +0100 Subject: [PATCH 4/5] fix: dependency --- Scarb.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scarb.toml b/Scarb.toml index afe2dba..01b9534 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -7,7 +7,7 @@ version = "0.1.0" [dependencies] starknet = "2.3.0" openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.8.0-beta.0" } -identity = { git = "https://github.com/starknet-id/identity.git", branch = "master" } +identity = { git = "https://github.com/starknet-id/identity.git", rev = "2e8fecab0d9a971710e8efb21abc25fb7825ee09" } [[target.starknet-contract]] # Enable Sierra codegen. From 2522e2019eeed7d9950e735bfb6f06249a6a79ef Mon Sep 17 00:00:00 2001 From: Iris Date: Fri, 3 Nov 2023 10:36:13 +0100 Subject: [PATCH 5/5] fix: tests --- src/tests/naming/test_custom_resolver.cairo | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/tests/naming/test_custom_resolver.cairo b/src/tests/naming/test_custom_resolver.cairo index d86a04d..a0b43e3 100644 --- a/src/tests/naming/test_custom_resolver.cairo +++ b/src/tests/naming/test_custom_resolver.cairo @@ -36,7 +36,9 @@ mod CustomResolver { #[external(v0)] impl AdditionResolveImpl of IResolver { - fn resolve(self: @ContractState, mut domain: Span, field: felt252) -> felt252 { + fn resolve( + self: @ContractState, mut domain: Span, field: felt252, hint: Span + ) -> felt252 { let mut output = 0; loop { match domain.pop_front() { @@ -88,12 +90,12 @@ fn test_custom_resolver() { let domain = array![th0rgal].span(); // by default we should have nothing written - assert(naming.resolve(domain, 'starknet') == 0, 'non empty starknet field'); + assert(naming.resolve(domain, 'starknet', array![].span()) == 0, 'non empty starknet field'); // so it should resolve to the starknetid owner - assert(naming.domain_to_address(domain) == caller, 'wrong domain target'); + assert(naming.domain_to_address(domain, array![].span()) == caller, 'wrong domain target'); let domain = array![1, 2, 3, th0rgal].span(); // let's try the resolving - assert(naming.resolve(domain, 'starknet') == 1 + 2 + 3, 'wrong target'); + assert(naming.resolve(domain, 'starknet', array![].span()) == 1 + 2 + 3, 'wrong target'); }