Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: reverse resolving #9

Merged
merged 2 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/interface/naming.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ trait INaming<TContractState> {

fn domain_to_address(self: @TContractState, domain: Span<felt252>) -> ContractAddress;

fn address_to_domain(self: @TContractState, address: ContractAddress) -> Array<felt252>;
fn address_to_domain(self: @TContractState, address: ContractAddress) -> Span<felt252>;

// external
fn buy(
Expand All @@ -39,6 +39,10 @@ trait INaming<TContractState> {

fn reset_subdomains(ref self: TContractState, domain: Span<felt252>);

fn set_address_to_domain(ref self: TContractState, domain: Span<felt252>);

fn reset_address_to_domain(ref self: TContractState);

// admin
fn set_admin(ref self: TContractState, new_admin: ContractAddress);

Expand Down
65 changes: 53 additions & 12 deletions src/naming/main.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ mod Naming {
enum Event {
DomainMint: DomainMint,
DomainRenewal: DomainRenewal,
DomainToResolver: DomainToResolver,
DomainResolverUpdate: DomainResolverUpdate,
AddressToDomainUpdate: AddressToDomainUpdate,
DomainTransfer: DomainTransfer,
SubdomainsReset: SubdomainsReset,
SaleMetadata: SaleMetadata,
Expand All @@ -51,12 +52,19 @@ mod Naming {
}

#[derive(Drop, starknet::Event)]
struct DomainToResolver {
struct DomainResolverUpdate {
#[key]
domain: Span<felt252>,
resolver: ContractAddress
}

#[derive(Drop, starknet::Event)]
struct AddressToDomainUpdate {
#[key]
address: ContractAddress,
domain: Span<felt252>,
}

#[derive(Drop, starknet::Event)]
struct DomainTransfer {
#[key]
Expand Down Expand Up @@ -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<felt252> {
fn address_to_domain(self: @ContractState, address: ContractAddress) -> Span<felt252> {
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()
Expand All @@ -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
}
}
Expand Down Expand Up @@ -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<felt252>) {
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) {
Expand Down Expand Up @@ -412,7 +438,7 @@ mod Naming {
return hashed_domain;
}

fn unhash_domain(self: @ContractState, domain_hash: felt252) -> Array<felt252> {
fn unhash_domain(self: @ContractState, domain_hash: felt252) -> Span<felt252> {
let mut i = 0;
let mut domain = ArrayTrait::new();
loop {
Expand All @@ -421,8 +447,9 @@ mod Naming {
break;
}
domain.append(domain_part);
i += 1;
};
domain
domain.span()
}

fn assert_purchase_is_possible(
Expand Down Expand Up @@ -512,6 +539,20 @@ mod Naming {
}
}

fn set_address_to_domain_util(
ref self: ContractState, address: ContractAddress, mut domain: Span<felt252>
) {
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<felt252>, parent_start_id: u32
) -> (ContractAddress, u32) {
Expand Down Expand Up @@ -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 }));

Expand All @@ -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 }
)
);
}
Expand Down
65 changes: 65 additions & 0 deletions src/tests/naming/test_usecases.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}