From 32219757bd12bcd99da841fe94ce08c0012c68db Mon Sep 17 00:00:00 2001 From: saimeunt Date: Mon, 9 Dec 2024 01:11:02 +0100 Subject: [PATCH] WIP --- .tool-versions | 1 + Scarb.toml | 22 +- src/interface.cairo | 2 +- src/interface/resolver.cairo | 4 +- src/resolver.cairo | 100 ++--- src/tests/resolver/erc20.cairo | 29 +- src/tests/resolver/test_hash.cairo | 6 - src/tests/resolver/test_resolver.cairo | 481 ++++++++++++------------- src/tests/utils.cairo | 11 +- 9 files changed, 309 insertions(+), 347 deletions(-) create mode 100644 .tool-versions diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..3efd1f4 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +scarb 2.9.1 diff --git a/Scarb.toml b/Scarb.toml index b7fa650..074cbaf 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,13 +1,25 @@ [package] name = "resolver" version = "0.1.0" +edition = "2024_07" +cairo-version = "2.9.1" +scarb-version = "2.9.1" +authors = ["LFG Labs"] +description = "Resolver CCIP" +documentation = "https://github.com/lfglabs-dev/resolver_ccip" +readme = "README.md" +repository = "https://github.com/lfglabs-dev/resolver_ccip" [dependencies] -starknet = "2.3.1" -naming = { git = "https://github.com/starknet-id/naming.git", rev = "6e45f7fc2bc9e8e9d874a1d2c2d46e3226a96f6d" } -openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", rev = "f3e2a5f0547a429c716f32471b06df729cbdfb9f" } -identity = { git = "https://github.com/starknet-id/identity.git", rev = "eb37846330b78e1410cf5e3e17a5dcca5652f921" } -storage_read = { git = "https://github.com/starknet-id/storage_read_component.git", rev = "c6c69e15d34abfc39ac51dc21b96724e2e19ff31" } +starknet = "2.9.1" +openzeppelin_access = "0.20.0" +openzeppelin_token = "0.20.0" +#naming = { git = "https://github.com/starknet-id/naming.git", rev = "7fa861a7a6e56c96ba3b508c66d7587d2597385a" } +#identity = { git = "https://github.com/starknet-id/identity.git", rev = "5ae7fafdd20abf4b1e789b83af5db7e23ad39a7c" } + +[dev-dependencies] +cairo_test = "2.9.1" +openzeppelin_utils = "0.20.0" [[target.starknet-contract]] # Enable Sierra codegen. diff --git a/src/interface.cairo b/src/interface.cairo index c2a4126..e755804 100644 --- a/src/interface.cairo +++ b/src/interface.cairo @@ -1 +1 @@ -mod resolver; +pub mod resolver; diff --git a/src/interface/resolver.cairo b/src/interface/resolver.cairo index d9a310b..a79e398 100644 --- a/src/interface/resolver.cairo +++ b/src/interface/resolver.cairo @@ -1,7 +1,5 @@ -use starknet::ContractAddress; - #[starknet::interface] -trait IResolver { +pub trait IResolver { fn resolve( self: @TContractState, domain: Span, field: felt252, hint: Span ) -> felt252; diff --git a/src/resolver.cairo b/src/resolver.cairo index 38c9602..28a9dda 100644 --- a/src/resolver.cairo +++ b/src/resolver.cairo @@ -1,19 +1,17 @@ #[starknet::contract] -mod Resolver { - use core::option::OptionTrait; - use core::traits::TryInto; - use core::array::SpanTrait; +pub mod Resolver { + use core::hash::HashStateTrait; + use core::pedersen::PedersenTrait; + use core::ecdsa::check_ecdsa_signature; use starknet::{ContractAddress, get_block_timestamp}; - use ecdsa::check_ecdsa_signature; - use resolver::interface::resolver::{IResolver, IResolverDispatcher, IResolverDispatcherTrait}; - use storage_read::{main::storage_read_component, interface::IStorageRead}; - use openzeppelin::access::ownable::OwnableComponent; + use starknet::storage::{ + Map, StoragePathEntry, StoragePointerReadAccess, StoragePointerWriteAccess + }; + use openzeppelin_access::ownable::OwnableComponent; + use resolver::interface::resolver::IResolver; - component!(path: storage_read_component, storage: storage_read, event: StorageReadEvent); component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); - #[abi(embed_v0)] - impl StorageReadImpl = storage_read_component::StorageRead; #[abi(embed_v0)] impl OwnableImpl = OwnableComponent::OwnableImpl; impl OwnableInternalImpl = OwnableComponent::InternalImpl; @@ -21,9 +19,7 @@ mod Resolver { #[storage] struct Storage { public_key: felt252, - uri: LegacyMap<(felt252, felt252), felt252>, - #[substorage(v0)] - storage_read: storage_read_component::Storage, + uris: Map>, #[substorage(v0)] ownable: OwnableComponent::Storage, } @@ -33,8 +29,6 @@ mod Resolver { enum Event { StarknetIDOffChainResolverUpdate: StarknetIDOffChainResolverUpdate, #[flat] - StorageReadEvent: storage_read_component::Event, - #[flat] OwnableEvent: OwnableComponent::Event, } @@ -44,6 +38,7 @@ mod Resolver { uri_removed: Span, } + const REMOVED_URI_VALUE: felt252 = 'this call was removed'; #[constructor] fn constructor(ref self: ContractState, owner: ContractAddress, _public_key: felt252) { @@ -51,7 +46,7 @@ mod Resolver { self.public_key.write(_public_key); } - #[external(v0)] + #[abi(embed_v0)] impl ResolverImpl of IResolver { fn resolve( self: @ContractState, domain: Span, field: felt252, hint: Span @@ -64,15 +59,12 @@ mod Resolver { assert(get_block_timestamp() < max_validity.try_into().unwrap(), 'Signature expired'); let hashed_domain = self.hash_domain(domain); - let message_hash: felt252 = hash::LegacyHash::hash( - hash::LegacyHash::hash( - hash::LegacyHash::hash( - hash::LegacyHash::hash('ccip_demo resolving', max_validity), hashed_domain - ), - field - ), - *hint.at(0) - ); + let message_hash = PedersenTrait::new('ccip_demo resolving') + .update(max_validity) + .update(hashed_domain) + .update(field) + .update(*hint.at(0)) + .finalize(); let public_key = self.public_key.read(); let is_valid = check_ecdsa_signature( @@ -84,13 +76,13 @@ mod Resolver { } fn get_uris(self: @ContractState) -> Array { - let mut res: Array = array![]; - let mut i: felt252 = 0; + let mut res = array![]; + let mut i = 0; loop { - if self.uri.read((i, 0)) == 0 { + if self.uris.entry(i).entry(0).read() == 0 { break; } - if self.uri.read((i, 0)) != 'this call was removed' { + if self.uris.entry(i).entry(0).read() != REMOVED_URI_VALUE { // we get the next uri at index i let mut new_uri = self.get_uri_at_index(i); res.append(new_uri.len().into()); @@ -108,17 +100,10 @@ mod Resolver { fn add_uri(ref self: ContractState, new_uri: Span) { self.ownable.assert_only_owner(); - let mut i: felt252 = 0; + let mut i = 0; loop { - if self.uri.read((i, 0)) == 0 { - self - .emit( - StarknetIDOffChainResolverUpdate { - uri_added: new_uri, uri_removed: array![].span() - } - ); + if self.uris.entry(i).entry(0).read() == 0 { self.store_uri(new_uri, i); - break; } i += 1; @@ -129,17 +114,17 @@ mod Resolver { self.ownable.assert_only_owner(); let uri_removed = self.get_uri_at_index(index).span(); self.emit(StarknetIDOffChainResolverUpdate { uri_added: array![].span(), uri_removed }); - self.uri.write((index, 0), 'this call was removed'); + self.uris.entry(index).entry(0).write(REMOVED_URI_VALUE); } } #[generate_trait] - impl InternalImpl of InternalTrait { + pub impl InternalImpl of InternalTrait { fn get_uri_at_index(self: @ContractState, index: felt252) -> Array { let mut res = array![]; - let mut j: felt252 = 0; + let mut j = 0; loop { - let value = self.uri.read((index, j)); + let value = self.uris.entry(index).entry(j).read(); if value == 0 { break; } @@ -154,7 +139,7 @@ mod Resolver { loop { match uri.pop_front() { Option::Some(value) => { - self.uri.write((index, j), *value); + self.uris.entry(index).entry(j).write(*value); j += 1; }, Option::None => { break; } @@ -174,27 +159,9 @@ mod Resolver { } }; // append uris to error array - self.append_uris(res) - } - - fn append_uris(self: @ContractState, mut res: Array) -> Array { - let mut i: felt252 = 0; - loop { - if self.uri.read((i, 0)) == 0 { - break; - } - if self.uri.read((i, 0)) != 'this call was removed' { - // we get the next uri at index i - let mut new_uri = self.get_uri_at_index(i); - res.append(new_uri.len().into()); - loop { - match new_uri.pop_front() { - Option::Some(value) => { res.append(value); }, - Option::None => { break; } - } - }; - } - i += 1; + let uris = self.get_uris(); + for uri in uris { + res.append(uri); }; res } @@ -206,8 +173,7 @@ mod Resolver { let new_len = domain.len() - 1; let x = *domain[new_len]; let y = self.hash_domain(domain.slice(0, new_len)); - let hashed_domain = pedersen::pedersen(x, y); - return hashed_domain; + PedersenTrait::new(x).update(y).finalize() } } } diff --git a/src/tests/resolver/erc20.cairo b/src/tests/resolver/erc20.cairo index bce873b..cf185bd 100644 --- a/src/tests/resolver/erc20.cairo +++ b/src/tests/resolver/erc20.cairo @@ -1,32 +1,31 @@ #[starknet::contract] -mod ERC20 { - use openzeppelin::token::erc20::erc20::ERC20Component::InternalTrait; - use openzeppelin::{token::erc20::{ERC20Component, dual20::DualCaseERC20Impl}}; +pub mod ERC20 { + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); + // ERC20 Mixin #[abi(embed_v0)] - impl ERC20Impl = ERC20Component::ERC20Impl; - #[abi(embed_v0)] - impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; - - #[constructor] - fn constructor(ref self: ContractState) { - self.erc20.initializer('ether', 'ETH'); - let target = starknet::contract_address_const::<0x123>(); - self.erc20._mint(target, 0x100000000000000000000000000000000); - } + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl; + impl ERC20InternalImpl = ERC20Component::InternalImpl; #[storage] struct Storage { #[substorage(v0)] - erc20: ERC20Component::Storage, + erc20: ERC20Component::Storage } #[event] #[derive(Drop, starknet::Event)] enum Event { #[flat] - ERC20Event: ERC20Component::Event, + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, initial_supply: u256, recipient: ContractAddress) { + self.erc20.initializer("ether", "ETH"); + self.erc20.mint(recipient, initial_supply); } } diff --git a/src/tests/resolver/test_hash.cairo b/src/tests/resolver/test_hash.cairo index 6ffdd72..b7fa1eb 100644 --- a/src/tests/resolver/test_hash.cairo +++ b/src/tests/resolver/test_hash.cairo @@ -1,9 +1,3 @@ -use array::ArrayTrait; -use debug::PrintTrait; - -use starknet::ContractAddress; -use starknet::testing; -use resolver::interface::resolver::{IResolver, IResolverDispatcher, IResolverDispatcherTrait}; use resolver::resolver::Resolver; use resolver::resolver::Resolver::InternalImpl; diff --git a/src/tests/resolver/test_resolver.cairo b/src/tests/resolver/test_resolver.cairo index 948c31a..a3875d0 100644 --- a/src/tests/resolver/test_resolver.cairo +++ b/src/tests/resolver/test_resolver.cairo @@ -1,60 +1,52 @@ -use array::ArrayTrait; -use debug::PrintTrait; -use core::option::OptionTrait; -use zeroable::Zeroable; -use traits::Into; - use starknet::ContractAddress; -use starknet::testing; -use starknet::contract_address::ContractAddressZeroable; +// use starknet::contract_address::ContractAddressZeroable; use starknet::contract_address_const; use starknet::testing::{set_contract_address, set_block_timestamp}; -use super::super::utils; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_token::erc20::interface::{IERC20, IERC20Dispatcher}; -use openzeppelin::token::erc20::{ - interface::{IERC20Camel, IERC20CamelDispatcher, IERC20CamelDispatcherTrait} -}; +use super::super::utils; use super::erc20::ERC20; -use identity::{ - identity::main::Identity, interface::identity::{IIdentityDispatcher, IIdentityDispatcherTrait} -}; -use naming::interface::naming::{INamingDispatcher, INamingDispatcherTrait}; -use naming::interface::pricing::{IPricingDispatcher, IPricingDispatcherTrait}; -use naming::naming::main::Naming; -use naming::pricing::Pricing; -use resolver::interface::resolver::{IResolver, IResolverDispatcher, IResolverDispatcherTrait}; +// use identity::{ +// identity::main::Identity, interface::identity::{IIdentityDispatcher, +// IIdentityDispatcherTrait} +// }; +// use naming::interface::naming::{INamingDispatcher, INamingDispatcherTrait}; +// use naming::interface::pricing::{IPricingDispatcher, IPricingDispatcherTrait}; +// use naming::naming::main::Naming; +// use naming::pricing::Pricing; +use resolver::interface::resolver::{IResolverDispatcher, IResolverDispatcherTrait}; use resolver::resolver::Resolver; -fn deploy( - pub_key: felt252 -) -> ( - IERC20CamelDispatcher, - IPricingDispatcher, - IIdentityDispatcher, - INamingDispatcher, - IResolverDispatcher -) { +fn deploy(pub_key: felt252) -> (IERC20Dispatcher, // IPricingDispatcher, + // IIdentityDispatcher, +// INamingDispatcher, +IResolverDispatcher) { let admin = 0x123; - //erc20 - let eth = utils::deploy(ERC20::TEST_CLASS_HASH, array![]); + // erc20 + let mut erc20_calldata = array![]; + erc20_calldata.append_serde(contract_address_const::<0x123>()); + erc20_calldata.append_serde(0x100000000000000000000000000000000_u256); + let eth = utils::deploy(ERC20::TEST_CLASS_HASH, erc20_calldata); - // pricing - let pricing = utils::deploy(Pricing::TEST_CLASS_HASH, array![eth.into()]); + // // pricing + // let pricing = utils::deploy(Pricing::TEST_CLASS_HASH, array![eth.into()]); - // identity - let identity = utils::deploy(Identity::TEST_CLASS_HASH, array![admin, 0]); + // // identity + // let identity = utils::deploy(Identity::TEST_CLASS_HASH, array![admin, 0]); - // naming - let address = utils::deploy( - Naming::TEST_CLASS_HASH, array![identity.into(), pricing.into(), 0, admin] - ); + // // naming + // let address = utils::deploy( + // Naming::TEST_CLASS_HASH, array![identity.into(), pricing.into(), 0, admin] + // ); let resolver = utils::deploy(Resolver::TEST_CLASS_HASH, array![admin, pub_key]); ( - IERC20CamelDispatcher { contract_address: eth }, - IPricingDispatcher { contract_address: pricing }, - IIdentityDispatcher { contract_address: identity }, - INamingDispatcher { contract_address: address }, + IERC20Dispatcher { + contract_address: eth + }, // IPricingDispatcher { contract_address: pricing }, + // IIdentityDispatcher { contract_address: identity }, + // INamingDispatcher { contract_address: address }, IResolverDispatcher { contract_address: resolver } ) } @@ -62,19 +54,20 @@ fn deploy( #[test] #[available_gas(20000000000)] fn test_uri() { - let (eth, pricing, identity, naming, resolver) = deploy( - 0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4 - ); + // let (eth, pricing, identity, naming, resolver) = deploy( + // 0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4 + // ); + let (_, resolver) = deploy(0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4); let caller = contract_address_const::<0x123>(); set_contract_address(caller); - // add a some uris + // add some uris resolver.add_uri(array!['http://0.0.0.0:8090/resolve?dom', 'ain='].span()); resolver.add_uri(array!['http://sepolia.starknet.id/reso', 'lve?domain='].span()); resolver.add_uri(array!['http://sepolia_2.starknet.id/re', 'solve?domain='].span()); - let mut uris = resolver.get_uris(); + let uris = resolver.get_uris(); assert(uris.len() == 9, 'wrong length'); assert(uris.at(0) == @2, 'wrong nb of arg'); assert(uris.at(1) == @'http://0.0.0.0:8090/resolve?dom', 'wrong uri'); @@ -85,10 +78,9 @@ fn test_uri() { assert(uris.at(6) == @2, 'wrong nb of arg'); assert(uris.at(7) == @'http://sepolia_2.starknet.id/re', 'wrong 2nd uri'); assert(uris.at(8) == @'solve?domain=', 'wrong 2nd uri'); - // remove the uri at index 1 resolver.remove_uri(1); - let mut uris = resolver.get_uris(); + let uris = resolver.get_uris(); assert(uris.len() == 6, 'wrong length'); assert(uris.at(0) == @2, 'wrong nb of arg'); assert(uris.at(1) == @'http://0.0.0.0:8090/resolve?dom', 'wrong uri'); @@ -97,198 +89,201 @@ fn test_uri() { assert(uris.at(4) == @'http://sepolia_2.starknet.id/re', 'wrong 2nd uri'); assert(uris.at(5) == @'solve?domain=', 'wrong 2nd uri'); } +// #[test] +// #[available_gas(20000000000)] +// #[should_panic( +// expected: ( +// 'offchain_resolving', +// 1, +// 999902, +// 1, +// 'http://0.0.0.0:8090', +// 2, +// 'http://0.0.0.0:8090/resolve?dom', +// 'ain=', +// 'ENTRYPOINT_FAILED', +// 'ENTRYPOINT_FAILED' +// ) +// )] +// fn test_offchain_resolving_no_hint() { +// // setup +// let (eth, pricing, identity, naming, resolver) = deploy( +// 0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4 +// ); +// let caller = contract_address_const::<0x123>(); +// set_contract_address(caller); +// let id1: u128 = 1; +// let iris: felt252 = 999902; +// let notion: felt252 = 1059716045; + +// // add uri +// resolver.add_uri(array!['http://0.0.0.0:8090'].span()); +// resolver.add_uri(array!['http://0.0.0.0:8090/resolve?dom', 'ain='].span()); + +// //we mint an identity +// identity.mint(id1); + +// // we check how much a domain costs +// let (_, price) = pricing.compute_buy_price(6, 365); + +// // we allow the naming to take our money +// eth.approve(naming.contract_address, price); + +// // we buy with a resolver, no sponsor, no discount and empty metadata +// naming.buy(id1, notion, 365, resolver.contract_address, ContractAddressZeroable::zero(), 0, +// 0); + +// // we call resolve on the naming contract for subdomain iris.notion.stark +// // It should panic with 'offchain_resolving' and the external uri to call +// let result = naming +// .resolve(array![999902, 1059716045].span(), 121424973492078, array![].span()); +// } +// #[test] +// #[available_gas(20000000000)] +// fn test_offchain_resolving_with_hint() { +// // setup +// let (eth, pricing, identity, naming, resolver) = deploy( +// 0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4 +// ); +// let caller = contract_address_const::<0x123>(); +// set_contract_address(caller); +// let id1: u128 = 1; +// let notion: felt252 = 1059716045; +// let iris: felt252 = 999902; + +// // add uri +// resolver.add_uri(array!['http://0.0.0.0:8090'].span()); +// resolver.add_uri(array!['http://0.0.0.0:8090/resolve?dom', 'ain='].span()); + +// let max_validity: felt252 = 1701167467; +// let timestamp: u64 = 1701167467 - 1800; // max_validity - 30 minutes +// set_block_timestamp(timestamp); + +// //we mint an identity +// identity.mint(id1); + +// // we check how much a domain costs +// let (_, price) = pricing.compute_buy_price(6, 365); + +// // we allow the naming to take our money +// eth.approve(naming.contract_address, price); + +// // we buy with a resolver, no sponsor, no discount and empty metadata +// naming.buy(id1, notion, 365, resolver.contract_address, ContractAddressZeroable::zero(), 0, +// 0); + +// // we call resolve on the naming contract for subdomain iris.notion.stark +// // It should return the address of the user +// let result = naming +// .resolve( +// array![999902, 1059716045].span(), +// 'starknet', +// array![ +// 0x04a8173e2F008282aC9793FB929974Cc7CEd6cEb76c79A0A9e0D163e60d08b6f, +// 245371453901460459147748049728129673559137408586661778136962765820508164010, +// 3537788104880290368328032579969034182821490439553457951875836525032598257669, +// max_validity, +// ] +// .span() +// ); +// assert( +// result == 0x04a8173e2F008282aC9793FB929974Cc7CEd6cEb76c79A0A9e0D163e60d08b6f, +// 'wrong address' +// ); +// } + +// #[test] +// #[available_gas(20000000000)] +// #[should_panic(expected: ('Signature expired', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED'))] +// fn test_offchain_resolving_with_hint_expired_sig() { +// // setup +// let (eth, pricing, identity, naming, resolver) = deploy( +// 0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4 +// ); +// let caller = contract_address_const::<0x123>(); +// set_contract_address(caller); +// let id1: u128 = 1; +// let notion: felt252 = 1059716045; +// let iris: felt252 = 999902; + +// let max_validity: felt252 = 1701167467; +// let timestamp: u64 = 1701167467 + 1800; // max_validity + 30 minutes +// set_block_timestamp(timestamp); + +// //we mint an identity +// identity.mint(id1); + +// // we check how much a domain costs +// let (_, price) = pricing.compute_buy_price(6, 365); + +// // we allow the naming to take our money +// eth.approve(naming.contract_address, price); + +// // we buy with a resolver, no sponsor, no discount and empty metadata +// naming.buy(id1, notion, 365, resolver.contract_address, ContractAddressZeroable::zero(), 0, +// 0); + +// // we call resolve on the naming contract for subdomain iris.notion.stark +// // It should panic as signature is invalid +// let result = naming +// .resolve( +// array![999902, 1059716045].span(), +// 'starknet', +// array![ +// 0x04a8173e2F008282aC9793FB929974Cc7CEd6cEb76c79A0A9e0D163e60d08b6f, +// 1, +// 2, +// max_validity +// ] +// .span() +// ); +// } + +// #[test] +// #[available_gas(20000000000)] +// #[should_panic(expected: ('Invalid signature', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED'))] +// fn test_offchain_resolving_with_hint_invalid_sig() { +// // setup +// let (eth, pricing, identity, naming, resolver) = deploy( +// 0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4 +// ); +// let caller = contract_address_const::<0x123>(); +// set_contract_address(caller); +// let id1: u128 = 1; +// let notion: felt252 = 1059716045; +// let iris: felt252 = 999902; + +// let max_validity: felt252 = 1701167467; +// let timestamp: u64 = 1701167467 - 1800; // max_validity - 30 minutes +// set_block_timestamp(timestamp); + +// //we mint an identity +// identity.mint(id1); + +// // we check how much a domain costs +// let (_, price) = pricing.compute_buy_price(6, 365); + +// // we allow the naming to take our money +// eth.approve(naming.contract_address, price); + +// // we buy with a resolver, no sponsor, no discount and empty metadata +// naming.buy(id1, notion, 365, resolver.contract_address, ContractAddressZeroable::zero(), 0, +// 0); + +// // we call resolve on the naming contract for subdomain iris.notion.stark +// // It should panic as signature is invalid +// let result = naming +// .resolve( +// array![999902, 1059716045].span(), +// 'starknet', +// array![ +// 0x04a8173e2F008282aC9793FB929974Cc7CEd6cEb76c79A0A9e0D163e60d08b6f, +// 1, +// 2, +// max_validity +// ] +// .span() +// ); +// } -#[test] -#[available_gas(20000000000)] -#[should_panic( - expected: ( - 'offchain_resolving', - 1, - 999902, - 1, - 'http://0.0.0.0:8090', - 2, - 'http://0.0.0.0:8090/resolve?dom', - 'ain=', - 'ENTRYPOINT_FAILED', - 'ENTRYPOINT_FAILED' - ) -)] -fn test_offchain_resolving_no_hint() { - // setup - let (eth, pricing, identity, naming, resolver) = deploy( - 0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4 - ); - let caller = contract_address_const::<0x123>(); - set_contract_address(caller); - let id1: u128 = 1; - let iris: felt252 = 999902; - let notion: felt252 = 1059716045; - - // add uri - resolver.add_uri(array!['http://0.0.0.0:8090'].span()); - resolver.add_uri(array!['http://0.0.0.0:8090/resolve?dom', 'ain='].span()); - - //we mint an identity - identity.mint(id1); - - // we check how much a domain costs - let (_, price) = pricing.compute_buy_price(6, 365); - - // we allow the naming to take our money - eth.approve(naming.contract_address, price); - - // we buy with a resolver, no sponsor, no discount and empty metadata - naming.buy(id1, notion, 365, resolver.contract_address, ContractAddressZeroable::zero(), 0, 0); - - // we call resolve on the naming contract for subdomain iris.notion.stark - // It should panic with 'offchain_resolving' and the external uri to call - let result = naming - .resolve(array![999902, 1059716045].span(), 121424973492078, array![].span()); -} - -#[test] -#[available_gas(20000000000)] -fn test_offchain_resolving_with_hint() { - // setup - let (eth, pricing, identity, naming, resolver) = deploy( - 0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4 - ); - let caller = contract_address_const::<0x123>(); - set_contract_address(caller); - let id1: u128 = 1; - let notion: felt252 = 1059716045; - let iris: felt252 = 999902; - - // add uri - resolver.add_uri(array!['http://0.0.0.0:8090'].span()); - resolver.add_uri(array!['http://0.0.0.0:8090/resolve?dom', 'ain='].span()); - - let max_validity: felt252 = 1701167467; - let timestamp: u64 = 1701167467 - 1800; // max_validity - 30 minutes - set_block_timestamp(timestamp); - - //we mint an identity - identity.mint(id1); - - // we check how much a domain costs - let (_, price) = pricing.compute_buy_price(6, 365); - - // we allow the naming to take our money - eth.approve(naming.contract_address, price); - - // we buy with a resolver, no sponsor, no discount and empty metadata - naming.buy(id1, notion, 365, resolver.contract_address, ContractAddressZeroable::zero(), 0, 0); - - // we call resolve on the naming contract for subdomain iris.notion.stark - // It should return the address of the user - let result = naming - .resolve( - array![999902, 1059716045].span(), - 'starknet', - array![ - 0x04a8173e2F008282aC9793FB929974Cc7CEd6cEb76c79A0A9e0D163e60d08b6f, - 245371453901460459147748049728129673559137408586661778136962765820508164010, - 3537788104880290368328032579969034182821490439553457951875836525032598257669, - max_validity, - ] - .span() - ); - assert( - result == 0x04a8173e2F008282aC9793FB929974Cc7CEd6cEb76c79A0A9e0D163e60d08b6f, - 'wrong address' - ); -} - -#[test] -#[available_gas(20000000000)] -#[should_panic(expected: ('Signature expired', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED'))] -fn test_offchain_resolving_with_hint_expired_sig() { - // setup - let (eth, pricing, identity, naming, resolver) = deploy( - 0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4 - ); - let caller = contract_address_const::<0x123>(); - set_contract_address(caller); - let id1: u128 = 1; - let notion: felt252 = 1059716045; - let iris: felt252 = 999902; - - let max_validity: felt252 = 1701167467; - let timestamp: u64 = 1701167467 + 1800; // max_validity + 30 minutes - set_block_timestamp(timestamp); - - //we mint an identity - identity.mint(id1); - - // we check how much a domain costs - let (_, price) = pricing.compute_buy_price(6, 365); - - // we allow the naming to take our money - eth.approve(naming.contract_address, price); - - // we buy with a resolver, no sponsor, no discount and empty metadata - naming.buy(id1, notion, 365, resolver.contract_address, ContractAddressZeroable::zero(), 0, 0); - - // we call resolve on the naming contract for subdomain iris.notion.stark - // It should panic as signature is invalid - let result = naming - .resolve( - array![999902, 1059716045].span(), - 'starknet', - array![ - 0x04a8173e2F008282aC9793FB929974Cc7CEd6cEb76c79A0A9e0D163e60d08b6f, - 1, - 2, - max_validity - ] - .span() - ); -} - -#[test] -#[available_gas(20000000000)] -#[should_panic(expected: ('Invalid signature', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED'))] -fn test_offchain_resolving_with_hint_invalid_sig() { - // setup - let (eth, pricing, identity, naming, resolver) = deploy( - 0x64018d8ea7829641419aff38ea79efd3eafedf3a5c1fe001d35339b889d48f4 - ); - let caller = contract_address_const::<0x123>(); - set_contract_address(caller); - let id1: u128 = 1; - let notion: felt252 = 1059716045; - let iris: felt252 = 999902; - - let max_validity: felt252 = 1701167467; - let timestamp: u64 = 1701167467 - 1800; // max_validity - 30 minutes - set_block_timestamp(timestamp); - - //we mint an identity - identity.mint(id1); - - // we check how much a domain costs - let (_, price) = pricing.compute_buy_price(6, 365); - - // we allow the naming to take our money - eth.approve(naming.contract_address, price); - - // we buy with a resolver, no sponsor, no discount and empty metadata - naming.buy(id1, notion, 365, resolver.contract_address, ContractAddressZeroable::zero(), 0, 0); - - // we call resolve on the naming contract for subdomain iris.notion.stark - // It should panic as signature is invalid - let result = naming - .resolve( - array![999902, 1059716045].span(), - 'starknet', - array![ - 0x04a8173e2F008282aC9793FB929974Cc7CEd6cEb76c79A0A9e0D163e60d08b6f, - 1, - 2, - max_validity - ] - .span() - ); -} diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo index 4c518dd..227fc91 100644 --- a/src/tests/utils.cairo +++ b/src/tests/utils.cairo @@ -1,11 +1,8 @@ -use array::ArrayTrait; -use core::result::ResultTrait; -use option::OptionTrait; -use starknet::{class_hash::Felt252TryIntoClassHash, ContractAddress, SyscallResultTrait}; -use traits::TryInto; +use starknet::{ContractAddress, SyscallResultTrait}; +use starknet::syscalls::deploy_syscall; -fn deploy(contract_class_hash: felt252, calldata: Array) -> ContractAddress { - let (address, _) = starknet::deploy_syscall( +pub fn deploy(contract_class_hash: felt252, calldata: Array) -> ContractAddress { + let (address, _) = deploy_syscall( contract_class_hash.try_into().unwrap(), 0, calldata.span(), false ) .unwrap_syscall();