Skip to content

Commit

Permalink
Merge pull request #19 from starknet-id/fix/assert_is_owner
Browse files Browse the repository at this point in the history
Fix/assert is owner
  • Loading branch information
Th0rgal authored Jan 10, 2024
2 parents eb9648f + cfa4acc commit b327ec1
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 32 deletions.
51 changes: 27 additions & 24 deletions src/naming/asserts.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::traits::TryInto;
use core::array::SpanTrait;
use naming::{
interface::{
naming::{INaming, INamingDispatcher, INamingDispatcherTrait},
Expand Down Expand Up @@ -28,7 +30,6 @@ use openzeppelin::token::erc20::interface::{
use integer::{u256_safe_divmod, u256_as_non_zero};
use naming::naming::utils::UtilsTrait;


#[generate_trait]
impl AssertionsImpl of AssertionsTrait {
fn assert_purchase_is_possible(
Expand Down Expand Up @@ -61,36 +62,38 @@ impl AssertionsImpl of AssertionsTrait {
assert(get_block_timestamp() <= root_domain_data.expiry, 'this domain has expired');
}

// ensures you own a domain or one of its parents
fn assert_is_owner(
self: @Naming::ContractState, domain: Span<felt252>, account: ContractAddress
) -> u32 {
let hashed_domain = self.hash_domain(domain);
let data = self._domain_data.read(hashed_domain);
) {
let mut i: felt252 = 1;
let stop = (domain.len() + 1).into();
let mut parent_key = 0;
loop {
assert(i != stop, 'you don\'t own this domain');
let i_gas_saver = i.try_into().unwrap();
let active_domain = domain.slice(domain.len() - i_gas_saver, i_gas_saver);
let hashed_domain = self.hash_domain(active_domain);
let data = self._domain_data.read(hashed_domain);

// because erc721 crashes on zero
let owner = if data.owner == 0 {
ContractAddressZeroable::zero()
} else {
IIdentityDispatcher { contract_address: self.starknetid_contract.read() }
.owner_from_id(data.owner)
};
assert(data.parent_key == parent_key, 'a parent domain was reset');

// if caller owns the starknet id, he owns the domain, we return the key
if owner == account {
return data.key;
};
// because erc721 crashes on zero
let owner = if data.owner == 0 {
ContractAddressZeroable::zero()
} else {
IIdentityDispatcher { contract_address: self.starknetid_contract.read() }
.owner_from_id(data.owner)
};

// otherwise, if it is a root domain, he doesn't own it
assert(domain.len() != 1 && domain.len() != 0, 'you don\'t own this domain');
// if caller owns the identity, he controls the domain and its children
if owner == account {
break;
};

// if he doesn't own the starknet id, and doesn't own the domain, he might own the parent domain
let parent_key = self.assert_is_owner(domain.slice(1, domain.len() - 1), account);
// we ensure that the key is the same as the parent key
// this is to allow to revoke all subdomains in o(1) writes, by juste updating the key of the parent
if (data.parent_key != 0) {
assert(parent_key == data.parent_key, 'you no longer own this domain');
parent_key = data.key;
i += 1;
};
data.key
}

// this ensures a non expired domain is not already written on this identity
Expand Down
1 change: 0 additions & 1 deletion src/tests/naming/common.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use array::ArrayTrait;
use array::SpanTrait;
use debug::PrintTrait;
use option::OptionTrait;
use zeroable::Zeroable;
use traits::Into;
Expand Down
59 changes: 57 additions & 2 deletions src/tests/naming/test_abuses.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use array::ArrayTrait;
use array::SpanTrait;
use debug::PrintTrait;
use option::OptionTrait;
use zeroable::Zeroable;
use traits::Into;
Expand All @@ -22,7 +21,6 @@ use naming::naming::main::Naming;
use naming::pricing::Pricing;
use super::common::deploy;


#[test]
#[available_gas(2000000000)]
#[should_panic(expected: ('u256_sub Overflow', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED'))]
Expand Down Expand Up @@ -243,3 +241,60 @@ fn test_non_admin_cannot_claim_balance() {
naming.claim_balance(eth.contract_address);
}

#[test]
#[available_gas(2000000000)]
#[should_panic(expected: ('a parent domain was reset', 'ENTRYPOINT_FAILED'))]
fn test_use_reset_subdomains() {
// setup
let (eth, pricing, identity, naming) = deploy();
let alpha = contract_address_const::<0x123>();
let bravo = contract_address_const::<0x456>();

// we mint the ids

set_contract_address(alpha);
identity.mint(1);
set_contract_address(bravo);
identity.mint(2);

set_contract_address(alpha);
let aller: felt252 = 35683102;

// we check how much a domain costs
let (_, price) = pricing.compute_buy_price(5, 365);

// we allow the naming to take our money
eth.approve(naming.contract_address, price);

// we buy with no resolver, no sponsor, no discount and empty metadata
naming
.buy(1, aller, 365, ContractAddressZeroable::zero(), ContractAddressZeroable::zero(), 0, 0);

let root_domain = array![aller].span();
let subdomain = array![aller, aller].span();

// we transfer aller.aller.stark to id2
naming.transfer_domain(subdomain, 2);

// and make sure the owner has been updated
assert(naming.domain_to_id(subdomain) == 2, 'owner not updated correctly');

// now bravo should be able to create a subsubdomain (charlie.aller.aller.stark):
set_contract_address(bravo);
let subsubdomain = array!['charlie', aller, aller].span();
naming.transfer_domain(subsubdomain, 3);

// alpha resets subdomains of aller.stark
set_contract_address(alpha);
naming.reset_subdomains(root_domain);

// ensure aller.stark still resolves
assert(naming.domain_to_id(root_domain) == 1, 'owner not updated correctly');
// ensure the subdomain was reset
assert(naming.domain_to_id(subdomain) == 0, 'owner not updated correctly');

set_contract_address(bravo);
let subsubdomain2 = array!['delta', aller, aller].span();
naming.transfer_domain(subsubdomain2, 4);
}

2 changes: 0 additions & 2 deletions src/tests/naming/test_custom_resolver.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use array::ArrayTrait;
use array::SpanTrait;
use debug::PrintTrait;
use option::OptionTrait;
use zeroable::Zeroable;
use traits::Into;
Expand Down Expand Up @@ -28,7 +27,6 @@ use naming::interface::resolver::IResolver;
mod CustomResolver {
use core::array::SpanTrait;
use naming::interface::resolver::IResolver;
use debug::PrintTrait;

#[storage]
struct Storage {}
Expand Down
1 change: 0 additions & 1 deletion src/tests/naming/test_features.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use array::ArrayTrait;
use array::SpanTrait;
use debug::PrintTrait;
use option::OptionTrait;
use zeroable::Zeroable;
use traits::Into;
Expand Down
1 change: 0 additions & 1 deletion src/tests/naming/test_usecases.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use array::ArrayTrait;
use array::SpanTrait;
use debug::PrintTrait;
use option::OptionTrait;
use zeroable::Zeroable;
use traits::Into;
Expand Down
1 change: 0 additions & 1 deletion src/tests/test_pricing.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use array::ArrayTrait;
use debug::PrintTrait;
use zeroable::Zeroable;
use traits::Into;

Expand Down

0 comments on commit b327ec1

Please sign in to comment.