From 3cd9ed9d188a58f19e1c77848614674893e11b90 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 28 Jun 2024 11:33:57 +0200 Subject: [PATCH 01/45] Migrate erc20 tests (#1022) * feat: migrate event tests * feat: update workflow * feat: add foundry utils * feat: finish erc20 and erc20votes migration * feat: remove dual case tests * refactor: format files * refactor: variable name * Update src/tests/token.cairo Co-authored-by: Andrew Fleming * Update src/tests/token/erc20.cairo Co-authored-by: Andrew Fleming * Update src/tests/utils/foundry.cairo Co-authored-by: Andrew Fleming * Update src/tests/token/erc20/test_erc20_votes.cairo Co-authored-by: Andrew Fleming * feat: apply review updates --------- Co-authored-by: Andrew Fleming --- .github/workflows/test.yml | 9 +- Scarb.lock | 8 + Scarb.toml | 1 + src/tests.cairo | 29 +- src/tests/token.cairo | 4 +- src/tests/token/erc20.cairo | 1 - src/tests/token/erc20/common.cairo | 54 ++-- src/tests/token/erc20/test_dual20.cairo | 297 ------------------- src/tests/token/erc20/test_erc20.cairo | 105 ++++--- src/tests/token/erc20/test_erc20_votes.cairo | 140 +++++---- src/tests/utils.cairo | 4 + src/tests/utils/foundry.cairo | 24 ++ 12 files changed, 219 insertions(+), 457 deletions(-) delete mode 100644 src/tests/token/erc20/test_dual20.cairo create mode 100644 src/tests/utils/foundry.cairo diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 023569891..9f6fe7888 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,6 +21,13 @@ jobs: - uses: software-mansion/setup-scarb@v1 with: scarb-version: ${{ env.SCARB_VERSION }} + - name: Extract foundry version + run: | + FOUNDRY_VERSION=$(grep 'snforge_std = ' Scarb.toml | sed 's/snforge_std = .\+ tag = "v\(.*\)".*/\1/') + echo "FOUNDRY_VERSION=$FOUNDRY_VERSION" >> $GITHUB_ENV + - uses: foundry-rs/setup-snfoundry@v3 + with: + starknet-foundry-version: ${{ env.FOUNDRY_VERSION }} - name: Markdown lint uses: DavidAnson/markdownlint-cli2-action@5b7c9f74fec47e6b15667b2cc23c63dff11e449e # v9 with: @@ -30,4 +37,4 @@ jobs: - name: Cairo lint run: scarb fmt --check - name: Cairo test - run: scarb test + run: snforge test diff --git a/Scarb.lock b/Scarb.lock index 8e8b73b05..2c67a9112 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -4,3 +4,11 @@ version = 1 [[package]] name = "openzeppelin" version = "0.14.0" +dependencies = [ + "snforge_std", +] + +[[package]] +name = "snforge_std" +version = "0.25.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.25.0#5b366e24821e530fea97f11b211d220e8493fbea" diff --git a/Scarb.toml b/Scarb.toml index a99d0ba14..c51cc402b 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -14,6 +14,7 @@ keywords = ["openzeppelin", "starknet", "cairo", "contracts", "security", "stand [dependencies] starknet = "2.6.4" +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.25.0" } [lib] diff --git a/src/tests.cairo b/src/tests.cairo index 1f53e79de..6b45d6e2c 100644 --- a/src/tests.cairo +++ b/src/tests.cairo @@ -1,20 +1,19 @@ -#[cfg(test)] -mod access; -#[cfg(test)] -mod account; -#[cfg(test)] -mod cryptography; -#[cfg(test)] -mod introspection; -#[cfg(test)] +// #[cfg(test)] +// mod access; +// #[cfg(test)] +// mod account; +// #[cfg(test)] +// mod cryptography; +// #[cfg(test)] +// mod introspection; mod mocks; -#[cfg(test)] -mod presets; -#[cfg(test)] -mod security; +// #[cfg(test)] +// mod presets; +// #[cfg(test)] +// mod security; #[cfg(test)] mod token; -#[cfg(test)] -mod upgrades; +// #[cfg(test)] +// mod upgrades; pub mod utils; diff --git a/src/tests/token.cairo b/src/tests/token.cairo index 04f631ea8..8833c90c3 100644 --- a/src/tests/token.cairo +++ b/src/tests/token.cairo @@ -1,3 +1,3 @@ -pub(crate) mod erc1155; +// pub(crate) mod erc1155; pub(crate) mod erc20; -pub(crate) mod erc721; +// pub(crate) mod erc721; diff --git a/src/tests/token/erc20.cairo b/src/tests/token/erc20.cairo index 8d094274f..6b10a866e 100644 --- a/src/tests/token/erc20.cairo +++ b/src/tests/token/erc20.cairo @@ -1,5 +1,4 @@ pub(crate) mod common; -mod test_dual20; mod test_erc20; mod test_erc20_votes; diff --git a/src/tests/token/erc20/common.cairo b/src/tests/token/erc20/common.cairo index dfd3e7e7d..12c03ce34 100644 --- a/src/tests/token/erc20/common.cairo +++ b/src/tests/token/erc20/common.cairo @@ -1,49 +1,49 @@ -use openzeppelin::tests::utils; use openzeppelin::token::erc20::ERC20Component::{Approval, Transfer}; use openzeppelin::token::erc20::ERC20Component; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::{EventSpy, EventAssertions}; use starknet::ContractAddress; pub(crate) fn assert_event_approval( - contract: ContractAddress, owner: ContractAddress, spender: ContractAddress, value: u256 + ref spy: EventSpy, + contract: ContractAddress, + owner: ContractAddress, + spender: ContractAddress, + value: u256 ) { - let event = utils::pop_log::(contract).unwrap(); let expected = ERC20Component::Event::Approval(Approval { owner, spender, value }); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("Approval")); - indexed_keys.append_serde(owner); - indexed_keys.append_serde(spender); - utils::assert_indexed_keys(event, indexed_keys.span()) + spy.assert_emitted(@array![(contract, expected)]); } pub(crate) fn assert_only_event_approval( - contract: ContractAddress, owner: ContractAddress, spender: ContractAddress, value: u256 + ref spy: EventSpy, + contract: ContractAddress, + owner: ContractAddress, + spender: ContractAddress, + value: u256 ) { - assert_event_approval(contract, owner, spender, value); - utils::assert_no_events_left(contract); + assert_event_approval(ref spy, contract, owner, spender, value); + assert(spy.events.len() == 0, 'Events remaining on queue'); } pub(crate) fn assert_event_transfer( - contract: ContractAddress, from: ContractAddress, to: ContractAddress, value: u256 + ref spy: EventSpy, + contract: ContractAddress, + from: ContractAddress, + to: ContractAddress, + value: u256 ) { - let event = utils::pop_log::(contract).unwrap(); let expected = ERC20Component::Event::Transfer(Transfer { from, to, value }); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("Transfer")); - indexed_keys.append_serde(from); - indexed_keys.append_serde(to); - utils::assert_indexed_keys(event, indexed_keys.span()); + spy.assert_emitted(@array![(contract, expected)]); } pub(crate) fn assert_only_event_transfer( - contract: ContractAddress, from: ContractAddress, to: ContractAddress, value: u256 + ref spy: EventSpy, + contract: ContractAddress, + from: ContractAddress, + to: ContractAddress, + value: u256 ) { - assert_event_transfer(contract, from, to, value); - utils::assert_no_events_left(contract); + assert_event_transfer(ref spy, contract, from, to, value); + assert(spy.events.len() == 0, 'Events remaining on queue'); } diff --git a/src/tests/token/erc20/test_dual20.cairo b/src/tests/token/erc20/test_dual20.cairo deleted file mode 100644 index ba9ba740d..000000000 --- a/src/tests/token/erc20/test_dual20.cairo +++ /dev/null @@ -1,297 +0,0 @@ -use openzeppelin::tests::mocks::erc20_mocks::{CamelERC20Mock, SnakeERC20Mock}; -use openzeppelin::tests::mocks::erc20_mocks::{CamelERC20Panic, SnakeERC20Panic}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::{ - OWNER, RECIPIENT, SPENDER, OPERATOR, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE -}; -use openzeppelin::tests::utils; -use openzeppelin::token::erc20::dual20::{DualCaseERC20, DualCaseERC20Trait}; -use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin::utils::serde::SerializedAppend; -use starknet::testing::set_contract_address; - -// -// Setup -// - -fn setup_snake() -> (DualCaseERC20, IERC20Dispatcher) { - let mut calldata = array![]; - calldata.append_serde(NAME()); - calldata.append_serde(SYMBOL()); - calldata.append_serde(SUPPLY); - calldata.append_serde(OWNER()); - let target = utils::deploy(SnakeERC20Mock::TEST_CLASS_HASH, calldata); - (DualCaseERC20 { contract_address: target }, IERC20Dispatcher { contract_address: target }) -} - -fn setup_camel() -> (DualCaseERC20, IERC20CamelDispatcher) { - let mut calldata = array![]; - calldata.append_serde(NAME()); - calldata.append_serde(SYMBOL()); - calldata.append_serde(SUPPLY); - calldata.append_serde(OWNER()); - let target = utils::deploy(CamelERC20Mock::TEST_CLASS_HASH, calldata); - (DualCaseERC20 { contract_address: target }, IERC20CamelDispatcher { contract_address: target }) -} - -fn setup_non_erc20() -> DualCaseERC20 { - let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); - DualCaseERC20 { contract_address: target } -} - -fn setup_erc20_panic() -> (DualCaseERC20, DualCaseERC20) { - let snake_target = utils::deploy(SnakeERC20Panic::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelERC20Panic::TEST_CLASS_HASH, array![]); - ( - DualCaseERC20 { contract_address: snake_target }, - DualCaseERC20 { contract_address: camel_target } - ) -} - -// -// Case agnostic methods -// - -#[test] -fn test_dual_name() { - let (snake_dispatcher, _) = setup_snake(); - assert_eq!(snake_dispatcher.name(), NAME()); - - let (camel_dispatcher, _) = setup_camel(); - assert_eq!(camel_dispatcher.name(), NAME()); -} - -#[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_name() { - let dispatcher = setup_non_erc20(); - dispatcher.name(); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_name_exists_and_panics() { - let (dispatcher, _) = setup_erc20_panic(); - dispatcher.name(); -} - -#[test] -fn test_dual_symbol() { - let (snake_dispatcher, _) = setup_snake(); - let (camel_dispatcher, _) = setup_camel(); - assert_eq!(snake_dispatcher.symbol(), SYMBOL()); - assert_eq!(camel_dispatcher.symbol(), SYMBOL()); -} - -#[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_symbol() { - let dispatcher = setup_non_erc20(); - dispatcher.symbol(); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_symbol_exists_and_panics() { - let (dispatcher, _) = setup_erc20_panic(); - dispatcher.symbol(); -} - -#[test] -fn test_dual_decimals() { - let (snake_dispatcher, _) = setup_snake(); - let (camel_dispatcher, _) = setup_camel(); - assert_eq!(snake_dispatcher.decimals(), DECIMALS); - assert_eq!(camel_dispatcher.decimals(), DECIMALS); -} - -#[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_decimals() { - let dispatcher = setup_non_erc20(); - dispatcher.decimals(); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_decimals_exists_and_panics() { - let (dispatcher, _) = setup_erc20_panic(); - dispatcher.decimals(); -} - -#[test] -fn test_dual_transfer() { - let (snake_dispatcher, snake_target) = setup_snake(); - set_contract_address(OWNER()); - assert!(snake_dispatcher.transfer(RECIPIENT(), VALUE)); - assert_eq!(snake_target.balance_of(RECIPIENT()), VALUE); - - let (camel_dispatcher, camel_target) = setup_camel(); - set_contract_address(OWNER()); - assert!(camel_dispatcher.transfer(RECIPIENT(), VALUE)); - assert_eq!(camel_target.balanceOf(RECIPIENT()), VALUE); -} - -#[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_transfer() { - let dispatcher = setup_non_erc20(); - dispatcher.transfer(RECIPIENT(), VALUE); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_transfer_exists_and_panics() { - let (dispatcher, _) = setup_erc20_panic(); - dispatcher.transfer(RECIPIENT(), VALUE); -} - -#[test] -fn test_dual_approve() { - let (snake_dispatcher, snake_target) = setup_snake(); - set_contract_address(OWNER()); - assert!(snake_dispatcher.approve(SPENDER(), VALUE)); - - let snake_allowance = snake_target.allowance(OWNER(), SPENDER()); - assert_eq!(snake_allowance, VALUE); - - let (camel_dispatcher, camel_target) = setup_camel(); - set_contract_address(OWNER()); - assert!(camel_dispatcher.approve(SPENDER(), VALUE)); - - let camel_allowance = camel_target.allowance(OWNER(), SPENDER()); - assert_eq!(camel_allowance, VALUE); -} - -#[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_approve() { - let dispatcher = setup_non_erc20(); - dispatcher.approve(SPENDER(), VALUE); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_approve_exists_and_panics() { - let (dispatcher, _) = setup_erc20_panic(); - dispatcher.approve(SPENDER(), VALUE); -} - -// -// snake_case target -// - -#[test] -fn test_dual_total_supply() { - let (dispatcher, _) = setup_snake(); - assert_eq!(dispatcher.total_supply(), SUPPLY); -} - -#[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_total_supply() { - let dispatcher = setup_non_erc20(); - dispatcher.total_supply(); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_total_supply_exists_and_panics() { - let (dispatcher, _) = setup_erc20_panic(); - dispatcher.total_supply(); -} - -#[test] -fn test_dual_balance_of() { - let (dispatcher, _) = setup_snake(); - assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY); -} - -#[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_balance_of() { - let dispatcher = setup_non_erc20(); - dispatcher.balance_of(OWNER()); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_balance_of_exists_and_panics() { - let (dispatcher, _) = setup_erc20_panic(); - dispatcher.balance_of(OWNER()); -} - -#[test] -fn test_dual_transfer_from() { - let (dispatcher, target) = setup_snake(); - set_contract_address(OWNER()); - target.approve(OPERATOR(), VALUE); - - set_contract_address(OPERATOR()); - dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); - assert_eq!(target.balance_of(RECIPIENT()), VALUE); -} - -#[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_transfer_from() { - let dispatcher = setup_non_erc20(); - dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_transfer_from_exists_and_panics() { - let (dispatcher, _) = setup_erc20_panic(); - dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); -} - -// -// camelCase target -// - -#[test] -fn test_dual_totalSupply() { - let (dispatcher, _) = setup_camel(); - assert_eq!(dispatcher.total_supply(), SUPPLY); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_totalSupply_exists_and_panics() { - let (_, dispatcher) = setup_erc20_panic(); - dispatcher.total_supply(); -} - -#[test] -fn test_dual_balanceOf() { - let (dispatcher, _) = setup_camel(); - assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_balanceOf_exists_and_panics() { - let (_, dispatcher) = setup_erc20_panic(); - dispatcher.balance_of(OWNER()); -} - -#[test] -fn test_dual_transferFrom() { - let (dispatcher, target) = setup_camel(); - set_contract_address(OWNER()); - target.approve(OPERATOR(), VALUE); - - set_contract_address(OPERATOR()); - dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); - assert_eq!(target.balanceOf(RECIPIENT()), VALUE); -} - -#[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] -fn test_dual_transferFrom_exists_and_panics() { - let (_, dispatcher) = setup_erc20_panic(); - dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); -} diff --git a/src/tests/token/erc20/test_erc20.cairo b/src/tests/token/erc20/test_erc20.cairo index 2c41a7971..c83e16576 100644 --- a/src/tests/token/erc20/test_erc20.cairo +++ b/src/tests/token/erc20/test_erc20.cairo @@ -4,13 +4,11 @@ use openzeppelin::tests::utils::constants::{ ZERO, OWNER, SPENDER, RECIPIENT, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE }; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::ERC20Component::{Approval, Transfer}; use openzeppelin::token::erc20::ERC20Component::{ERC20CamelOnlyImpl, ERC20Impl}; use openzeppelin::token::erc20::ERC20Component::{ERC20MetadataImpl, InternalImpl}; use openzeppelin::token::erc20::ERC20Component; -use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::{test_address, start_cheat_caller_address}; use starknet::ContractAddress; -use starknet::testing; use super::common::{assert_event_approval, assert_only_event_approval, assert_only_event_transfer}; @@ -28,7 +26,6 @@ fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(NAME(), SYMBOL()); state.mint(OWNER(), SUPPLY); - utils::drop_event(ZERO()); state } @@ -82,7 +79,7 @@ fn test_balanceOf() { #[test] fn test_allowance() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.approve(SPENDER(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); @@ -96,10 +93,13 @@ fn test_allowance() { #[test] fn test_approve() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let contract_address = test_address(); + let mut spy = utils::spy_on(contract_address); + + start_cheat_caller_address(contract_address, OWNER()); assert!(state.approve(SPENDER(), VALUE)); - assert_only_event_approval(ZERO(), OWNER(), SPENDER(), VALUE); + assert_only_event_approval(ref spy, contract_address, OWNER(), SPENDER(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); assert_eq!(allowance, VALUE); @@ -116,17 +116,20 @@ fn test_approve_from_zero() { #[should_panic(expected: ('ERC20: approve to 0',))] fn test_approve_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.approve(ZERO(), VALUE); } #[test] fn test__approve() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let contract_address = test_address(); + let mut spy = utils::spy_on(contract_address); + + start_cheat_caller_address(contract_address, OWNER()); state._approve(OWNER(), SPENDER(), VALUE); - assert_only_event_approval(ZERO(), OWNER(), SPENDER(), VALUE); + assert_only_event_approval(ref spy, contract_address, OWNER(), SPENDER(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); assert_eq!(allowance, VALUE); @@ -143,7 +146,7 @@ fn test__approve_from_zero() { #[should_panic(expected: ('ERC20: approve to 0',))] fn test__approve_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state._approve(OWNER(), ZERO(), VALUE); } @@ -154,10 +157,13 @@ fn test__approve_to_zero() { #[test] fn test_transfer() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let contract_address = test_address(); + let mut spy = utils::spy_on(contract_address); + + start_cheat_caller_address(contract_address, OWNER()); assert!(state.transfer(RECIPIENT(), VALUE)); - assert_only_event_transfer(ZERO(), OWNER(), RECIPIENT(), VALUE); + assert_only_event_transfer(ref spy, contract_address, OWNER(), RECIPIENT(), VALUE); assert_eq!(state.balance_of(RECIPIENT()), VALUE); assert_eq!(state.balance_of(OWNER()), SUPPLY - VALUE); assert_eq!(state.total_supply(), SUPPLY); @@ -167,7 +173,7 @@ fn test_transfer() { #[should_panic(expected: ('ERC20: insufficient balance',))] fn test_transfer_not_enough_balance() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); let balance_plus_one = SUPPLY + 1; state.transfer(RECIPIENT(), balance_plus_one); @@ -184,17 +190,19 @@ fn test_transfer_from_zero() { #[should_panic(expected: ('ERC20: transfer to 0',))] fn test_transfer_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.transfer(ZERO(), VALUE); } #[test] fn test__transfer() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = utils::spy_on(contract_address); state._transfer(OWNER(), RECIPIENT(), VALUE); - assert_only_event_transfer(ZERO(), OWNER(), RECIPIENT(), VALUE); + assert_only_event_transfer(ref spy, contract_address, OWNER(), RECIPIENT(), VALUE); assert_eq!(state.balance_of(RECIPIENT()), VALUE); assert_eq!(state.balance_of(OWNER()), SUPPLY - VALUE); assert_eq!(state.total_supply(), SUPPLY); @@ -204,7 +212,7 @@ fn test__transfer() { #[should_panic(expected: ('ERC20: insufficient balance',))] fn test__transfer_not_enough_balance() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); let balance_plus_one = SUPPLY + 1; state._transfer(OWNER(), RECIPIENT(), balance_plus_one); @@ -231,15 +239,17 @@ fn test__transfer_to_zero() { #[test] fn test_transfer_from() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, OWNER()); state.approve(SPENDER(), VALUE); - utils::drop_event(ZERO()); - testing::set_caller_address(SPENDER()); + let mut spy = utils::spy_on(contract_address); + start_cheat_caller_address(contract_address, SPENDER()); assert!(state.transfer_from(OWNER(), RECIPIENT(), VALUE)); - assert_event_approval(ZERO(), OWNER(), SPENDER(), 0); - assert_only_event_transfer(ZERO(), OWNER(), RECIPIENT(), VALUE); + assert_event_approval(ref spy, contract_address, OWNER(), SPENDER(), 0); + assert_only_event_transfer(ref spy, contract_address, OWNER(), RECIPIENT(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); assert_eq!(allowance, 0); @@ -252,10 +262,10 @@ fn test_transfer_from() { #[test] fn test_transfer_from_doesnt_consume_infinite_allowance() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.approve(SPENDER(), BoundedInt::max()); - testing::set_caller_address(SPENDER()); + start_cheat_caller_address(test_address(), SPENDER()); state.transfer_from(OWNER(), RECIPIENT(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); @@ -266,10 +276,10 @@ fn test_transfer_from_doesnt_consume_infinite_allowance() { #[should_panic(expected: ('ERC20: insufficient allowance',))] fn test_transfer_from_greater_than_allowance() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.approve(SPENDER(), VALUE); - testing::set_caller_address(SPENDER()); + start_cheat_caller_address(test_address(), SPENDER()); let allowance_plus_one = VALUE + 1; state.transfer_from(OWNER(), RECIPIENT(), allowance_plus_one); } @@ -278,10 +288,10 @@ fn test_transfer_from_greater_than_allowance() { #[should_panic(expected: ('ERC20: transfer to 0',))] fn test_transfer_from_to_zero_address() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.approve(SPENDER(), VALUE); - testing::set_caller_address(SPENDER()); + start_cheat_caller_address(test_address(), SPENDER()); state.transfer_from(OWNER(), ZERO(), VALUE); } @@ -295,15 +305,17 @@ fn test_transfer_from_from_zero_address() { #[test] fn test_transferFrom() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, OWNER()); state.approve(SPENDER(), VALUE); - utils::drop_event(ZERO()); - testing::set_caller_address(SPENDER()); + let mut spy = utils::spy_on(contract_address); + start_cheat_caller_address(contract_address, SPENDER()); assert!(state.transferFrom(OWNER(), RECIPIENT(), VALUE)); - assert_event_approval(ZERO(), OWNER(), SPENDER(), 0); - assert_only_event_transfer(ZERO(), OWNER(), RECIPIENT(), VALUE); + assert_event_approval(ref spy, contract_address, OWNER(), SPENDER(), 0); + assert_only_event_transfer(ref spy, contract_address, OWNER(), RECIPIENT(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); assert_eq!(allowance, 0); @@ -317,10 +329,10 @@ fn test_transferFrom() { #[test] fn test_transferFrom_doesnt_consume_infinite_allowance() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.approve(SPENDER(), BoundedInt::max()); - testing::set_caller_address(SPENDER()); + start_cheat_caller_address(test_address(), SPENDER()); state.transferFrom(OWNER(), RECIPIENT(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); @@ -331,10 +343,10 @@ fn test_transferFrom_doesnt_consume_infinite_allowance() { #[should_panic(expected: ('ERC20: insufficient allowance',))] fn test_transferFrom_greater_than_allowance() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.approve(SPENDER(), VALUE); - testing::set_caller_address(SPENDER()); + start_cheat_caller_address(test_address(), SPENDER()); let allowance_plus_one = VALUE + 1; state.transferFrom(OWNER(), RECIPIENT(), allowance_plus_one); } @@ -343,10 +355,10 @@ fn test_transferFrom_greater_than_allowance() { #[should_panic(expected: ('ERC20: transfer to 0',))] fn test_transferFrom_to_zero_address() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.approve(SPENDER(), VALUE); - testing::set_caller_address(SPENDER()); + start_cheat_caller_address(test_address(), SPENDER()); state.transferFrom(OWNER(), ZERO(), VALUE); } @@ -364,13 +376,14 @@ fn test_transferFrom_from_zero_address() { #[test] fn test__spend_allowance_not_unlimited() { let mut state = setup(); + let contract_address = test_address(); state._approve(OWNER(), SPENDER(), SUPPLY); - utils::drop_event(ZERO()); + let mut spy = utils::spy_on(contract_address); state._spend_allowance(OWNER(), SPENDER(), VALUE); - assert_only_event_approval(ZERO(), OWNER(), SPENDER(), SUPPLY - VALUE); + assert_only_event_approval(ref spy, contract_address, OWNER(), SPENDER(), SUPPLY - VALUE); let allowance = state.allowance(OWNER(), SPENDER()); assert_eq!(allowance, SUPPLY - VALUE); @@ -395,9 +408,12 @@ fn test__spend_allowance_unlimited() { #[test] fn test_mint() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); + + let mut spy = utils::spy_on(contract_address); state.mint(OWNER(), VALUE); - assert_only_event_transfer(ZERO(), ZERO(), OWNER(), VALUE); + assert_only_event_transfer(ref spy, contract_address, ZERO(), OWNER(), VALUE); assert_eq!(state.balance_of(OWNER()), VALUE); assert_eq!(state.total_supply(), VALUE); } @@ -416,9 +432,12 @@ fn test_mint_to_zero() { #[test] fn test_burn() { let mut state = setup(); + let contract_address = test_address(); + + let mut spy = utils::spy_on(contract_address); state.burn(OWNER(), VALUE); - assert_only_event_transfer(ZERO(), OWNER(), ZERO(), VALUE); + assert_only_event_transfer(ref spy, contract_address, OWNER(), ZERO(), VALUE); assert_eq!(state.total_supply(), SUPPLY - VALUE); assert_eq!(state.balance_of(OWNER()), SUPPLY - VALUE); } diff --git a/src/tests/token/erc20/test_erc20_votes.cairo b/src/tests/token/erc20/test_erc20_votes.cairo index e241e891c..f8453ebd6 100644 --- a/src/tests/token/erc20/test_erc20_votes.cairo +++ b/src/tests/token/erc20/test_erc20_votes.cairo @@ -1,9 +1,8 @@ use core::integer::BoundedInt; use core::num::traits::Zero; -use openzeppelin::tests::mocks::account_mocks::DualCaseAccountMock; use openzeppelin::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock::SNIP12MetadataImpl; use openzeppelin::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock; -use openzeppelin::tests::utils::constants::{SUPPLY, ZERO, OWNER, PUBKEY, RECIPIENT}; +use openzeppelin::tests::utils::constants::{SUPPLY, ZERO, OWNER, RECIPIENT}; use openzeppelin::tests::utils; use openzeppelin::token::erc20::ERC20Component::InternalImpl as ERC20Impl; use openzeppelin::token::erc20::extensions::ERC20VotesComponent::{ @@ -14,13 +13,16 @@ use openzeppelin::token::erc20::extensions::ERC20VotesComponent; use openzeppelin::token::erc20::extensions::erc20_votes::Delegation; use openzeppelin::utils::cryptography::snip12::OffchainMessageHash; use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::structs::checkpoint::{Checkpoint, Trace, TraceTrait}; +use openzeppelin::utils::structs::checkpoint::{Checkpoint, TraceTrait}; +use snforge_std::signature::KeyPairTrait; +use snforge_std::signature::stark_curve::{StarkCurveKeyPairImpl, StarkCurveSignerImpl}; +use snforge_std::{ + cheat_block_timestamp_global, start_cheat_caller_address, cheat_chain_id_global, test_address +}; +use snforge_std::{EventSpy, EventAssertions}; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; -use starknet::testing; - -use super::common::{assert_event_approval, assert_only_event_approval, assert_only_event_transfer}; // // Setup @@ -41,13 +43,12 @@ fn setup() -> ComponentState { mock_state.erc20.mint(OWNER(), SUPPLY); state.transfer_voting_units(ZERO(), OWNER(), SUPPLY); - utils::drop_event(ZERO()); state } -fn setup_account() -> ContractAddress { - let mut calldata = array![0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7]; - utils::deploy(DualCaseAccountMock::TEST_CLASS_HASH, calldata) +fn setup_account(public_key: felt252) -> ContractAddress { + let mut calldata = array![public_key]; + utils::declare_and_deploy("DualCaseAccountMock", calldata) } // Checkpoints unordered insertion @@ -58,7 +59,7 @@ fn test__delegate_checkpoints_unordered_insertion() { let mut state = setup(); let mut trace = state.ERC20Votes_delegate_checkpoints.read(OWNER()); - testing::set_block_timestamp('ts10'); + cheat_block_timestamp_global('ts10'); trace.push('ts2', 0x222); trace.push('ts1', 0x111); } @@ -69,7 +70,7 @@ fn test__total_checkpoints_unordered_insertion() { let mut state = setup(); let mut trace = state.ERC20Votes_total_checkpoints.read(); - testing::set_block_timestamp('ts10'); + cheat_block_timestamp_global('ts10'); trace.push('ts2', 0x222); trace.push('ts1', 0x111); } @@ -81,8 +82,7 @@ fn test__total_checkpoints_unordered_insertion() { #[test] fn test_get_votes() { let mut state = setup(); - - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.delegate(OWNER()); assert_eq!(state.get_votes(OWNER()), SUPPLY); @@ -94,7 +94,7 @@ fn test_get_past_votes() { let mut trace = state.ERC20Votes_delegate_checkpoints.read(OWNER()); // Future timestamp. - testing::set_block_timestamp('ts10'); + cheat_block_timestamp_global('ts10'); trace.push('ts1', 0x111); trace.push('ts2', 0x222); trace.push('ts3', 0x333); @@ -118,7 +118,7 @@ fn test_get_past_votes_future_lookup() { let state = setup(); // Past timestamp. - testing::set_block_timestamp('ts1'); + cheat_block_timestamp_global('ts1'); state.get_past_votes(OWNER(), 'ts2'); } @@ -128,7 +128,7 @@ fn test_get_past_total_supply() { let mut trace = state.ERC20Votes_total_checkpoints.read(); // Future timestamp. - testing::set_block_timestamp('ts10'); + cheat_block_timestamp_global('ts10'); trace.push('ts1', 0x111); trace.push('ts2', 0x222); trace.push('ts3', 0x333); @@ -152,7 +152,7 @@ fn test_get_past_total_supply_future_lookup() { let state = setup(); // Past timestamp. - testing::set_block_timestamp('ts1'); + cheat_block_timestamp_global('ts1'); state.get_past_total_supply('ts2'); } @@ -163,41 +163,44 @@ fn test_get_past_total_supply_future_lookup() { #[test] fn test_delegate() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let contract_address = test_address(); + let mut spy = utils::spy_on(contract_address); + + start_cheat_caller_address(contract_address, OWNER()); // Delegate from zero state.delegate(OWNER()); - assert_event_delegate_changed(ZERO(), OWNER(), ZERO(), OWNER()); - assert_only_event_delegate_votes_changed(ZERO(), OWNER(), 0, SUPPLY); + assert_event_delegate_changed(ref spy, contract_address, OWNER(), ZERO(), OWNER()); + assert_only_event_delegate_votes_changed(ref spy, contract_address, OWNER(), 0, SUPPLY); assert_eq!(state.get_votes(OWNER()), SUPPLY); // Delegate from non-zero to non-zero state.delegate(RECIPIENT()); - assert_event_delegate_changed(ZERO(), OWNER(), OWNER(), RECIPIENT()); - assert_event_delegate_votes_changed(ZERO(), OWNER(), SUPPLY, 0); - assert_only_event_delegate_votes_changed(ZERO(), RECIPIENT(), 0, SUPPLY); + assert_event_delegate_changed(ref spy, contract_address, OWNER(), OWNER(), RECIPIENT()); + assert_event_delegate_votes_changed(ref spy, contract_address, OWNER(), SUPPLY, 0); + assert_only_event_delegate_votes_changed(ref spy, contract_address, RECIPIENT(), 0, SUPPLY); assert!(state.get_votes(OWNER()).is_zero()); assert_eq!(state.get_votes(RECIPIENT()), SUPPLY); // Delegate to zero state.delegate(ZERO()); - assert_event_delegate_changed(ZERO(), OWNER(), RECIPIENT(), ZERO()); - assert_event_delegate_votes_changed(ZERO(), RECIPIENT(), SUPPLY, 0); + assert_event_delegate_changed(ref spy, contract_address, OWNER(), RECIPIENT(), ZERO()); + assert_event_delegate_votes_changed(ref spy, contract_address, RECIPIENT(), SUPPLY, 0); assert!(state.get_votes(RECIPIENT()).is_zero()); // Delegate from zero to zero state.delegate(ZERO()); - assert_only_event_delegate_changed(ZERO(), OWNER(), ZERO(), ZERO()); + assert_only_event_delegate_changed(ref spy, contract_address, OWNER(), ZERO(), ZERO()); } #[test] fn test_delegates() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.delegate(OWNER()); assert_eq!(state.delegates(OWNER()), OWNER()); @@ -210,12 +213,12 @@ fn test_delegates() { #[test] fn test_delegate_by_sig_hash_generation() { - testing::set_chain_id('SN_TEST'); + cheat_chain_id_global('SN_TEST'); let nonce = 0; let expiry = 'ts2'; let delegator = contract_address_const::< - 0x19dcd9e412145354a3328fb68b5975bded85972893eb42eed11355d4cfbb58a + 0x70b0526a4bfbc9ca717c96aeb5a8afac85181f4585662273668928585a0d628 >(); let delegatee = RECIPIENT(); let delegation = Delegation { delegatee, nonce, expiry }; @@ -226,50 +229,51 @@ fn test_delegate_by_sig_hash_generation() { // - name: 'DAPP_NAME' // - version: 'DAPP_VERSION' // - chainId: 'SN_TEST' - // - account: 0x19dcd9e412145354a3328fb68b5975bded85972893eb42eed11355d4cfbb58a + // - account: 0x70b0526a4bfbc9ca717c96aeb5a8afac85181f4585662273668928585a0d628 // - delegatee: 'RECIPIENT' // - nonce: 0 // - expiry: 'ts2' // - revision: '1' - let expected_hash = 0x5b9e8190392425e06024b1eedfbbe9dd3631ddd07a84154185d39ec1d657511; + let expected_hash = 0x314bd38b22b62d576691d8dafd9f8ea0601329ebe686bc64ca28e4d8821d5a0; assert_eq!(hash, expected_hash); } #[test] fn test_delegate_by_sig() { + cheat_chain_id_global('SN_TEST'); + cheat_block_timestamp_global('ts1'); + let mut state = setup(); - let account = setup_account(); - testing::set_chain_id('SN_TEST'); + let contract_address = test_address(); + let key_pair = KeyPairTrait::::generate(); + let account = setup_account(key_pair.public_key); let nonce = 0; let expiry = 'ts2'; let delegator = account; let delegatee = RECIPIENT(); - // This signature was computed using starknet js sdk from the following values: - // - private_key: '1234' - // - public_key: 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7 - // - msg_hash: 0x5b9e8190392425e06024b1eedfbbe9dd3631ddd07a84154185d39ec1d657511 - let signature = array![ - 0x4b2ca5c3cb47eafc1263db0fb7a1c4ee54eb9cc6605607a072894c0a9ae3b08, - 0x313dc5b5f05ab680db7d51b391fadd52e679c971551f0017a8ceba37bacc5c6 - ]; + let delegation = Delegation { delegatee, nonce, expiry }; + let msg_hash = delegation.get_message_hash(delegator); + let (r, s) = key_pair.sign(msg_hash).unwrap(); - testing::set_block_timestamp('ts1'); - state.delegate_by_sig(delegator, delegatee, nonce, expiry, signature); + let mut spy = utils::spy_on(contract_address); - assert_only_event_delegate_changed(ZERO(), delegator, ZERO(), delegatee); + state.delegate_by_sig(delegator, delegatee, nonce, expiry, array![r, s]); + + assert_only_event_delegate_changed(ref spy, contract_address, delegator, ZERO(), delegatee); assert_eq!(state.delegates(account), delegatee); } #[test] #[should_panic(expected: ('Votes: expired signature',))] fn test_delegate_by_sig_past_expiry() { + cheat_block_timestamp_global('ts5'); + let mut state = setup(); let expiry = 'ts4'; let signature = array![0, 0]; - testing::set_block_timestamp('ts5'); state.delegate_by_sig(OWNER(), RECIPIENT(), 0, expiry, signature); } @@ -286,7 +290,7 @@ fn test_delegate_by_sig_invalid_nonce() { #[should_panic(expected: ('Votes: invalid signature',))] fn test_delegate_by_sig_invalid_signature() { let mut state = setup(); - let account = setup_account(); + let account = setup_account(0x123); let signature = array![0, 0]; state.delegate_by_sig(account, RECIPIENT(), 0, 0, signature); @@ -351,55 +355,49 @@ fn test_get_voting_units() { // fn assert_event_delegate_changed( + ref spy: EventSpy, contract: ContractAddress, delegator: ContractAddress, from_delegate: ContractAddress, to_delegate: ContractAddress ) { - let event = utils::pop_log::(contract).unwrap(); let expected = ERC20VotesComponent::Event::DelegateChanged( DelegateChanged { delegator, from_delegate, to_delegate } ); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("DelegateChanged")); - indexed_keys.append_serde(delegator); - indexed_keys.append_serde(from_delegate); - indexed_keys.append_serde(to_delegate); - utils::assert_indexed_keys(event, indexed_keys.span()) + spy.assert_emitted(@array![(contract, expected)]); } fn assert_only_event_delegate_changed( + ref spy: EventSpy, contract: ContractAddress, delegator: ContractAddress, from_delegate: ContractAddress, to_delegate: ContractAddress ) { - assert_event_delegate_changed(contract, delegator, from_delegate, to_delegate); - utils::assert_no_events_left(contract); + assert_event_delegate_changed(ref spy, contract, delegator, from_delegate, to_delegate); + assert(spy.events.len() == 0, 'Events remaining on queue'); } fn assert_event_delegate_votes_changed( - contract: ContractAddress, delegate: ContractAddress, previous_votes: u256, new_votes: u256 + ref spy: EventSpy, + contract: ContractAddress, + delegate: ContractAddress, + previous_votes: u256, + new_votes: u256 ) { - let event = utils::pop_log::(contract).unwrap(); let expected = ERC20VotesComponent::Event::DelegateVotesChanged( DelegateVotesChanged { delegate, previous_votes, new_votes } ); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("DelegateVotesChanged")); - indexed_keys.append_serde(delegate); - utils::assert_indexed_keys(event, indexed_keys.span()) + spy.assert_emitted(@array![(contract, expected)]); } fn assert_only_event_delegate_votes_changed( - contract: ContractAddress, delegate: ContractAddress, previous_votes: u256, new_votes: u256 + ref spy: EventSpy, + contract: ContractAddress, + delegate: ContractAddress, + previous_votes: u256, + new_votes: u256 ) { - assert_event_delegate_votes_changed(contract, delegate, previous_votes, new_votes); - utils::assert_no_events_left(contract); + assert_event_delegate_votes_changed(ref spy, contract, delegate, previous_votes, new_votes); + assert(spy.events.len() == 0, 'Events remaining on queue'); } diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo index 658b94645..6edad0000 100644 --- a/src/tests/utils.cairo +++ b/src/tests/utils.cairo @@ -1,4 +1,8 @@ pub(crate) mod constants; +pub mod foundry; +pub use foundry::declare_and_deploy; + +pub use foundry::spy_on; use starknet::ContractAddress; use starknet::SyscallResultTrait; diff --git a/src/tests/utils/foundry.cairo b/src/tests/utils/foundry.cairo new file mode 100644 index 000000000..d624d9a79 --- /dev/null +++ b/src/tests/utils/foundry.cairo @@ -0,0 +1,24 @@ +use snforge_std::{declare, ContractClassTrait, spy_events, EventSpy, SpyOn}; +use starknet::ContractAddress; + +pub fn declare_and_deploy(contract_name: ByteArray, calldata: Array) -> ContractAddress { + let contract_class = declare(contract_name).unwrap(); + match contract_class.deploy(@calldata) { + Result::Ok((contract_address, _)) => contract_address, + Result::Err(panic_data) => panic!("Failed to deploy, error: ${:?}", panic_data) + } +} + +pub fn declare_and_deploy_at( + contract_name: ByteArray, target_address: ContractAddress, calldata: Array +) { + let contract_class = declare(contract_name).unwrap(); + if let Result::Err(panic_data) = contract_class.deploy_at(@calldata, target_address) { + panic!("Failed to deploy, error: ${:?}", panic_data) + } +} + +pub fn spy_on(contract_address: ContractAddress) -> EventSpy { + spy_events(SpyOn::One(contract_address)) +} + From a96b50a4b952eaa3fd987e17fe3ecf7440da1870 Mon Sep 17 00:00:00 2001 From: immrsd <103599616+immrsd@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:11:28 +0200 Subject: [PATCH 02/45] Snforge utils and some common changes (#1030) * Update gitignore with snfoundry cache dir * Delete foundry utils file * Add snfoundry-related test utils, comment out previous utils * Update ERC20 event helpers * Update ERC20 tests * Update ERC20Votes tests * Run linter * Add util function to drop single event * Fix review issues * Make Github workflow run on every PR * Fix review issues * Bump snforge version * Support snforge 0.26 in test utils * Update ERC20 tests to support snforge upgrade * Run linter --- .github/workflows/test.yml | 2 - .gitignore | 3 + Scarb.lock | 4 +- Scarb.toml | 2 +- src/tests/token.cairo | 2 +- src/tests/token/erc20/common.cairo | 84 +++++++------ src/tests/token/erc20/test_erc20.cairo | 44 +++---- src/tests/token/erc20/test_erc20_votes.cairo | 123 ++++++++++--------- src/tests/utils.cairo | 76 +----------- src/tests/utils/common.cairo | 34 +++++ src/tests/utils/events.cairo | 62 ++++++++++ src/tests/utils/foundry.cairo | 24 ---- src/tests/utils/signing.cairo | 11 ++ 13 files changed, 249 insertions(+), 222 deletions(-) create mode 100644 src/tests/utils/common.cairo create mode 100644 src/tests/utils/events.cairo delete mode 100644 src/tests/utils/foundry.cairo create mode 100644 src/tests/utils/signing.cairo diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9f6fe7888..1d37a35d6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,8 +2,6 @@ name: Lint and test on: pull_request: - branches: - - main push: branches: - main diff --git a/.gitignore b/.gitignore index 869665ba4..2956e1b18 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ corelib/ # Scarb target/ +# Starknet Foundry +.snfoundry_cache/ + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/Scarb.lock b/Scarb.lock index 2c67a9112..524489827 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -10,5 +10,5 @@ dependencies = [ [[package]] name = "snforge_std" -version = "0.25.0" -source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.25.0#5b366e24821e530fea97f11b211d220e8493fbea" +version = "0.26.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.26.0#50eb589db65e113efe4f09241feb59b574228c7e" diff --git a/Scarb.toml b/Scarb.toml index c51cc402b..935224176 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -14,7 +14,7 @@ keywords = ["openzeppelin", "starknet", "cairo", "contracts", "security", "stand [dependencies] starknet = "2.6.4" -snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.25.0" } +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.26.0" } [lib] diff --git a/src/tests/token.cairo b/src/tests/token.cairo index 8833c90c3..25979f784 100644 --- a/src/tests/token.cairo +++ b/src/tests/token.cairo @@ -1,3 +1,3 @@ // pub(crate) mod erc1155; -pub(crate) mod erc20; // pub(crate) mod erc721; +pub(crate) mod erc20; diff --git a/src/tests/token/erc20/common.cairo b/src/tests/token/erc20/common.cairo index 12c03ce34..be65d0241 100644 --- a/src/tests/token/erc20/common.cairo +++ b/src/tests/token/erc20/common.cairo @@ -1,49 +1,53 @@ +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::token::erc20::ERC20Component::{Approval, Transfer}; use openzeppelin::token::erc20::ERC20Component; use openzeppelin::utils::serde::SerializedAppend; -use snforge_std::{EventSpy, EventAssertions}; +use snforge_std::EventSpy; use starknet::ContractAddress; -pub(crate) fn assert_event_approval( - ref spy: EventSpy, - contract: ContractAddress, - owner: ContractAddress, - spender: ContractAddress, - value: u256 -) { - let expected = ERC20Component::Event::Approval(Approval { owner, spender, value }); - spy.assert_emitted(@array![(contract, expected)]); -} +#[generate_trait] +pub(crate) impl ERC20SpyHelpersImpl of ERC20SpyHelpers { + fn assert_event_approval( + ref self: EventSpy, + contract: ContractAddress, + owner: ContractAddress, + spender: ContractAddress, + value: u256 + ) { + let expected = ERC20Component::Event::Approval(Approval { owner, spender, value }); + self.assert_emitted_single(contract, expected); + } -pub(crate) fn assert_only_event_approval( - ref spy: EventSpy, - contract: ContractAddress, - owner: ContractAddress, - spender: ContractAddress, - value: u256 -) { - assert_event_approval(ref spy, contract, owner, spender, value); - assert(spy.events.len() == 0, 'Events remaining on queue'); -} + fn assert_only_event_approval( + ref self: EventSpy, + contract: ContractAddress, + owner: ContractAddress, + spender: ContractAddress, + value: u256 + ) { + self.assert_event_approval(contract, owner, spender, value); + self.assert_no_events_left_from(contract); + } -pub(crate) fn assert_event_transfer( - ref spy: EventSpy, - contract: ContractAddress, - from: ContractAddress, - to: ContractAddress, - value: u256 -) { - let expected = ERC20Component::Event::Transfer(Transfer { from, to, value }); - spy.assert_emitted(@array![(contract, expected)]); -} + fn assert_event_transfer( + ref self: EventSpy, + contract: ContractAddress, + from: ContractAddress, + to: ContractAddress, + value: u256 + ) { + let expected = ERC20Component::Event::Transfer(Transfer { from, to, value }); + self.assert_emitted_single(contract, expected); + } -pub(crate) fn assert_only_event_transfer( - ref spy: EventSpy, - contract: ContractAddress, - from: ContractAddress, - to: ContractAddress, - value: u256 -) { - assert_event_transfer(ref spy, contract, from, to, value); - assert(spy.events.len() == 0, 'Events remaining on queue'); + fn assert_only_event_transfer( + ref self: EventSpy, + contract: ContractAddress, + from: ContractAddress, + to: ContractAddress, + value: u256 + ) { + self.assert_event_transfer(contract, from, to, value); + self.assert_no_events_left_from(contract); + } } diff --git a/src/tests/token/erc20/test_erc20.cairo b/src/tests/token/erc20/test_erc20.cairo index c83e16576..c3315e8b7 100644 --- a/src/tests/token/erc20/test_erc20.cairo +++ b/src/tests/token/erc20/test_erc20.cairo @@ -7,10 +7,10 @@ use openzeppelin::tests::utils; use openzeppelin::token::erc20::ERC20Component::{ERC20CamelOnlyImpl, ERC20Impl}; use openzeppelin::token::erc20::ERC20Component::{ERC20MetadataImpl, InternalImpl}; use openzeppelin::token::erc20::ERC20Component; -use snforge_std::{test_address, start_cheat_caller_address}; +use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::ContractAddress; -use super::common::{assert_event_approval, assert_only_event_approval, assert_only_event_transfer}; +use super::common::ERC20SpyHelpers; // // Setup @@ -94,12 +94,12 @@ fn test_allowance() { fn test_approve() { let mut state = setup(); let contract_address = test_address(); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); start_cheat_caller_address(contract_address, OWNER()); assert!(state.approve(SPENDER(), VALUE)); - assert_only_event_approval(ref spy, contract_address, OWNER(), SPENDER(), VALUE); + spy.assert_only_event_approval(contract_address, OWNER(), SPENDER(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); assert_eq!(allowance, VALUE); @@ -124,12 +124,12 @@ fn test_approve_to_zero() { fn test__approve() { let mut state = setup(); let contract_address = test_address(); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); start_cheat_caller_address(contract_address, OWNER()); state._approve(OWNER(), SPENDER(), VALUE); - assert_only_event_approval(ref spy, contract_address, OWNER(), SPENDER(), VALUE); + spy.assert_only_event_approval(contract_address, OWNER(), SPENDER(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); assert_eq!(allowance, VALUE); @@ -158,12 +158,12 @@ fn test__approve_to_zero() { fn test_transfer() { let mut state = setup(); let contract_address = test_address(); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); start_cheat_caller_address(contract_address, OWNER()); assert!(state.transfer(RECIPIENT(), VALUE)); - assert_only_event_transfer(ref spy, contract_address, OWNER(), RECIPIENT(), VALUE); + spy.assert_only_event_transfer(contract_address, OWNER(), RECIPIENT(), VALUE); assert_eq!(state.balance_of(RECIPIENT()), VALUE); assert_eq!(state.balance_of(OWNER()), SUPPLY - VALUE); assert_eq!(state.total_supply(), SUPPLY); @@ -198,11 +198,11 @@ fn test_transfer_to_zero() { fn test__transfer() { let mut state = setup(); let contract_address = test_address(); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); state._transfer(OWNER(), RECIPIENT(), VALUE); - assert_only_event_transfer(ref spy, contract_address, OWNER(), RECIPIENT(), VALUE); + spy.assert_only_event_transfer(contract_address, OWNER(), RECIPIENT(), VALUE); assert_eq!(state.balance_of(RECIPIENT()), VALUE); assert_eq!(state.balance_of(OWNER()), SUPPLY - VALUE); assert_eq!(state.total_supply(), SUPPLY); @@ -244,12 +244,12 @@ fn test_transfer_from() { start_cheat_caller_address(contract_address, OWNER()); state.approve(SPENDER(), VALUE); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); start_cheat_caller_address(contract_address, SPENDER()); assert!(state.transfer_from(OWNER(), RECIPIENT(), VALUE)); - assert_event_approval(ref spy, contract_address, OWNER(), SPENDER(), 0); - assert_only_event_transfer(ref spy, contract_address, OWNER(), RECIPIENT(), VALUE); + spy.assert_event_approval(contract_address, OWNER(), SPENDER(), 0); + spy.assert_only_event_transfer(contract_address, OWNER(), RECIPIENT(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); assert_eq!(allowance, 0); @@ -310,12 +310,12 @@ fn test_transferFrom() { start_cheat_caller_address(contract_address, OWNER()); state.approve(SPENDER(), VALUE); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); start_cheat_caller_address(contract_address, SPENDER()); assert!(state.transferFrom(OWNER(), RECIPIENT(), VALUE)); - assert_event_approval(ref spy, contract_address, OWNER(), SPENDER(), 0); - assert_only_event_transfer(ref spy, contract_address, OWNER(), RECIPIENT(), VALUE); + spy.assert_event_approval(contract_address, OWNER(), SPENDER(), 0); + spy.assert_only_event_transfer(contract_address, OWNER(), RECIPIENT(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); assert_eq!(allowance, 0); @@ -380,10 +380,10 @@ fn test__spend_allowance_not_unlimited() { state._approve(OWNER(), SPENDER(), SUPPLY); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); state._spend_allowance(OWNER(), SPENDER(), VALUE); - assert_only_event_approval(ref spy, contract_address, OWNER(), SPENDER(), SUPPLY - VALUE); + spy.assert_only_event_approval(contract_address, OWNER(), SPENDER(), SUPPLY - VALUE); let allowance = state.allowance(OWNER(), SPENDER()); assert_eq!(allowance, SUPPLY - VALUE); @@ -410,10 +410,10 @@ fn test_mint() { let mut state = COMPONENT_STATE(); let contract_address = test_address(); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); state.mint(OWNER(), VALUE); - assert_only_event_transfer(ref spy, contract_address, ZERO(), OWNER(), VALUE); + spy.assert_only_event_transfer(contract_address, ZERO(), OWNER(), VALUE); assert_eq!(state.balance_of(OWNER()), VALUE); assert_eq!(state.total_supply(), VALUE); } @@ -434,10 +434,10 @@ fn test_burn() { let mut state = setup(); let contract_address = test_address(); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); state.burn(OWNER(), VALUE); - assert_only_event_transfer(ref spy, contract_address, OWNER(), ZERO(), VALUE); + spy.assert_only_event_transfer(contract_address, OWNER(), ZERO(), VALUE); assert_eq!(state.total_supply(), SUPPLY - VALUE); assert_eq!(state.balance_of(OWNER()), SUPPLY - VALUE); } diff --git a/src/tests/token/erc20/test_erc20_votes.cairo b/src/tests/token/erc20/test_erc20_votes.cairo index f8453ebd6..269ec1d44 100644 --- a/src/tests/token/erc20/test_erc20_votes.cairo +++ b/src/tests/token/erc20/test_erc20_votes.cairo @@ -3,6 +3,7 @@ use core::num::traits::Zero; use openzeppelin::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock::SNIP12MetadataImpl; use openzeppelin::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock; use openzeppelin::tests::utils::constants::{SUPPLY, ZERO, OWNER, RECIPIENT}; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::tests::utils; use openzeppelin::token::erc20::ERC20Component::InternalImpl as ERC20Impl; use openzeppelin::token::erc20::extensions::ERC20VotesComponent::{ @@ -17,9 +18,10 @@ use openzeppelin::utils::structs::checkpoint::{Checkpoint, TraceTrait}; use snforge_std::signature::KeyPairTrait; use snforge_std::signature::stark_curve::{StarkCurveKeyPairImpl, StarkCurveSignerImpl}; use snforge_std::{ - cheat_block_timestamp_global, start_cheat_caller_address, cheat_chain_id_global, test_address + cheat_block_timestamp_global, start_cheat_caller_address, spy_events, cheat_chain_id_global, + test_address }; -use snforge_std::{EventSpy, EventAssertions}; +use snforge_std::{EventSpy, EventSpyAssertionsTrait}; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; @@ -164,37 +166,37 @@ fn test_get_past_total_supply_future_lookup() { fn test_delegate() { let mut state = setup(); let contract_address = test_address(); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); start_cheat_caller_address(contract_address, OWNER()); // Delegate from zero state.delegate(OWNER()); - assert_event_delegate_changed(ref spy, contract_address, OWNER(), ZERO(), OWNER()); - assert_only_event_delegate_votes_changed(ref spy, contract_address, OWNER(), 0, SUPPLY); + spy.assert_event_delegate_changed(contract_address, OWNER(), ZERO(), OWNER()); + spy.assert_only_event_delegate_votes_changed(contract_address, OWNER(), 0, SUPPLY); assert_eq!(state.get_votes(OWNER()), SUPPLY); // Delegate from non-zero to non-zero state.delegate(RECIPIENT()); - assert_event_delegate_changed(ref spy, contract_address, OWNER(), OWNER(), RECIPIENT()); - assert_event_delegate_votes_changed(ref spy, contract_address, OWNER(), SUPPLY, 0); - assert_only_event_delegate_votes_changed(ref spy, contract_address, RECIPIENT(), 0, SUPPLY); + spy.assert_event_delegate_changed(contract_address, OWNER(), OWNER(), RECIPIENT()); + spy.assert_event_delegate_votes_changed(contract_address, OWNER(), SUPPLY, 0); + spy.assert_only_event_delegate_votes_changed(contract_address, RECIPIENT(), 0, SUPPLY); assert!(state.get_votes(OWNER()).is_zero()); assert_eq!(state.get_votes(RECIPIENT()), SUPPLY); // Delegate to zero state.delegate(ZERO()); - assert_event_delegate_changed(ref spy, contract_address, OWNER(), RECIPIENT(), ZERO()); - assert_event_delegate_votes_changed(ref spy, contract_address, RECIPIENT(), SUPPLY, 0); + spy.assert_event_delegate_changed(contract_address, OWNER(), RECIPIENT(), ZERO()); + spy.assert_event_delegate_votes_changed(contract_address, RECIPIENT(), SUPPLY, 0); assert!(state.get_votes(RECIPIENT()).is_zero()); // Delegate from zero to zero state.delegate(ZERO()); - assert_only_event_delegate_changed(ref spy, contract_address, OWNER(), ZERO(), ZERO()); + spy.assert_only_event_delegate_changed(contract_address, OWNER(), ZERO(), ZERO()); } #[test] @@ -257,11 +259,11 @@ fn test_delegate_by_sig() { let msg_hash = delegation.get_message_hash(delegator); let (r, s) = key_pair.sign(msg_hash).unwrap(); - let mut spy = utils::spy_on(contract_address); + let mut spy = spy_events(); state.delegate_by_sig(delegator, delegatee, nonce, expiry, array![r, s]); - assert_only_event_delegate_changed(ref spy, contract_address, delegator, ZERO(), delegatee); + spy.assert_only_event_delegate_changed(contract_address, delegator, ZERO(), delegatee); assert_eq!(state.delegates(account), delegatee); } @@ -354,50 +356,53 @@ fn test_get_voting_units() { // Helpers // -fn assert_event_delegate_changed( - ref spy: EventSpy, - contract: ContractAddress, - delegator: ContractAddress, - from_delegate: ContractAddress, - to_delegate: ContractAddress -) { - let expected = ERC20VotesComponent::Event::DelegateChanged( - DelegateChanged { delegator, from_delegate, to_delegate } - ); - spy.assert_emitted(@array![(contract, expected)]); -} - -fn assert_only_event_delegate_changed( - ref spy: EventSpy, - contract: ContractAddress, - delegator: ContractAddress, - from_delegate: ContractAddress, - to_delegate: ContractAddress -) { - assert_event_delegate_changed(ref spy, contract, delegator, from_delegate, to_delegate); - assert(spy.events.len() == 0, 'Events remaining on queue'); -} - -fn assert_event_delegate_votes_changed( - ref spy: EventSpy, - contract: ContractAddress, - delegate: ContractAddress, - previous_votes: u256, - new_votes: u256 -) { - let expected = ERC20VotesComponent::Event::DelegateVotesChanged( - DelegateVotesChanged { delegate, previous_votes, new_votes } - ); - spy.assert_emitted(@array![(contract, expected)]); -} - -fn assert_only_event_delegate_votes_changed( - ref spy: EventSpy, - contract: ContractAddress, - delegate: ContractAddress, - previous_votes: u256, - new_votes: u256 -) { - assert_event_delegate_votes_changed(ref spy, contract, delegate, previous_votes, new_votes); - assert(spy.events.len() == 0, 'Events remaining on queue'); +#[generate_trait] +impl VotesSpyHelpersImpl of VotesSpyHelpers { + fn assert_event_delegate_changed( + ref self: EventSpy, + contract: ContractAddress, + delegator: ContractAddress, + from_delegate: ContractAddress, + to_delegate: ContractAddress + ) { + let expected = ERC20VotesComponent::Event::DelegateChanged( + DelegateChanged { delegator, from_delegate, to_delegate } + ); + self.assert_emitted_single(contract, expected); + } + + fn assert_only_event_delegate_changed( + ref self: EventSpy, + contract: ContractAddress, + delegator: ContractAddress, + from_delegate: ContractAddress, + to_delegate: ContractAddress + ) { + self.assert_event_delegate_changed(contract, delegator, from_delegate, to_delegate); + self.assert_no_events_left_from(contract); + } + + fn assert_event_delegate_votes_changed( + ref self: EventSpy, + contract: ContractAddress, + delegate: ContractAddress, + previous_votes: u256, + new_votes: u256 + ) { + let expected = ERC20VotesComponent::Event::DelegateVotesChanged( + DelegateVotesChanged { delegate, previous_votes, new_votes } + ); + self.assert_emitted_single(contract, expected); + } + + fn assert_only_event_delegate_votes_changed( + ref self: EventSpy, + contract: ContractAddress, + delegate: ContractAddress, + previous_votes: u256, + new_votes: u256 + ) { + self.assert_event_delegate_votes_changed(contract, delegate, previous_votes, new_votes); + self.assert_no_events_left_from(contract); + } } diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo index 6edad0000..34b29154d 100644 --- a/src/tests/utils.cairo +++ b/src/tests/utils.cairo @@ -1,73 +1,7 @@ +pub(crate) mod common; pub(crate) mod constants; -pub mod foundry; -pub use foundry::declare_and_deploy; +pub(crate) mod events; +pub(crate) mod signing; +pub use common::{declare_class, declare_and_deploy, declare_and_deploy_at, deploy, deploy_at}; -pub use foundry::spy_on; - -use starknet::ContractAddress; -use starknet::SyscallResultTrait; -use starknet::testing; - -pub fn deploy(contract_class_hash: felt252, calldata: Array) -> ContractAddress { - deploy_with_salt(contract_class_hash, calldata, 0) -} - -pub fn deploy_with_salt( - contract_class_hash: felt252, calldata: Array, salt: felt252 -) -> ContractAddress { - let (address, _) = starknet::syscalls::deploy_syscall( - contract_class_hash.try_into().unwrap(), salt, calldata.span(), false - ) - .unwrap_syscall(); - address -} - -/// Pop the earliest unpopped logged event enum for the contract and checks -/// there's no more keys or data left on the event, preventing unaccounted params. -/// -/// CAUTION: If the event enum contains two `flat` events with the same structure (member types), -/// this function will always match the first event, even when the second one is emitted. -pub fn pop_log, +starknet::Event>(address: ContractAddress) -> Option { - let (mut keys, mut data) = testing::pop_log_raw(address)?; - - let ret = starknet::Event::deserialize(ref keys, ref data); - assert!(data.is_empty(), "Event has extra data"); - assert!(keys.is_empty(), "Event has extra keys"); - ret -} - -/// Asserts that `expected_keys` exactly matches the indexed keys from `event`. -/// -/// `expected_keys` must include all indexed event keys for `event` in the order -/// that they're defined. -/// -/// If the event is not flattened, the first key will be the event member name -/// e.g. selector!("EnumMemberName"). -pub fn assert_indexed_keys, +starknet::Event>( - event: T, expected_keys: Span -) { - let mut keys = array![]; - let mut data = array![]; - - event.append_keys_and_data(ref keys, ref data); - assert!(expected_keys == keys.span()); -} - -pub fn assert_no_events_left(address: ContractAddress) { - assert!(testing::pop_log_raw(address).is_none(), "Events remaining on queue"); -} - -pub fn drop_event(address: ContractAddress) { - let _ = testing::pop_log_raw(address); -} - -pub fn drop_events(address: ContractAddress, n_events: felt252) { - let mut count = n_events; - loop { - if count == 0 { - break; - } - drop_event(address); - count -= 1; - } -} +pub use events::EventSpyExt; diff --git a/src/tests/utils/common.cairo b/src/tests/utils/common.cairo new file mode 100644 index 000000000..27a7698db --- /dev/null +++ b/src/tests/utils/common.cairo @@ -0,0 +1,34 @@ +use snforge_std::{declare, ContractClass, ContractClassTrait}; +use starknet::ContractAddress; + +pub fn deploy(contract_class: ContractClass, calldata: Array) -> ContractAddress { + match contract_class.deploy(@calldata) { + Result::Ok((contract_address, _)) => contract_address, + Result::Err(panic_data) => panic!("Failed to deploy, error: ${:?}", panic_data) + } +} + +pub fn deploy_at( + contract_class: ContractClass, contract_address: ContractAddress, calldata: Array +) { + match contract_class.deploy_at(@calldata, contract_address) { + Result::Ok(_) => (), + Result::Err(panic_data) => panic!("Failed to deploy, error: ${:?}", panic_data) + }; +} + +pub fn declare_class(contract_name: ByteArray) -> ContractClass { + declare(contract_name).unwrap() +} + +pub fn declare_and_deploy(contract_name: ByteArray, calldata: Array) -> ContractAddress { + let contract_class = declare(contract_name).unwrap(); + deploy(contract_class, calldata) +} + +pub fn declare_and_deploy_at( + contract_name: ByteArray, target_address: ContractAddress, calldata: Array +) { + let contract_class = declare(contract_name).expect('Failed to declare contract'); + deploy_at(contract_class, target_address, calldata) +} diff --git a/src/tests/utils/events.cairo b/src/tests/utils/events.cairo new file mode 100644 index 000000000..302d1a917 --- /dev/null +++ b/src/tests/utils/events.cairo @@ -0,0 +1,62 @@ +use snforge_std::{EventSpyTrait, EventSpy, EventSpyAssertionsTrait}; +use starknet::ContractAddress; + +#[generate_trait] +pub impl EventSpyExtImpl of EventSpyExt { + fn assert_only_event, +Drop>( + ref self: EventSpy, from_address: ContractAddress, event: T + ) { + self.assert_emitted_single(from_address, event); + self.assert_no_events_left_from(from_address); + } + + fn assert_emitted_single, +Drop>( + ref self: EventSpy, from_address: ContractAddress, expected_event: T + ) { + self.assert_emitted(@array![(from_address, expected_event)]); + self._event_offset += 1; + } + + fn drop_event(ref self: EventSpy) { + self.drop_n_events(1); + } + + fn drop_n_events(ref self: EventSpy, number_to_drop: u32) { + let events = self.get_events().events; + let len = events.len(); + assert!( + len >= number_to_drop, + "Not enough events to drop. ${len} events, ${number_to_drop} to drop" + ); + self._event_offset += number_to_drop; + } + + fn drop_all_events(ref self: EventSpy) { + let events = self.get_events().events; + self._event_offset += events.len(); + } + + fn assert_no_events_left(ref self: EventSpy) { + let events = self.get_events().events; + assert!(events.len() == 0, "Events remaining on queue"); + } + + fn assert_no_events_left_from(ref self: EventSpy, from_address: ContractAddress) { + assert!(self.count_events_from(from_address) == 0, "Events remaining on queue"); + } + + fn count_events_from(ref self: EventSpy, from_address: ContractAddress) -> u32 { + let mut result = 0; + let mut events = self.get_events().events; + let mut index = 0; + let length = events.len(); + while index < length { + let (from, _) = events.at(index); + if from_address == *from { + result += 1; + } + index += 1; + }; + result + } +} diff --git a/src/tests/utils/foundry.cairo b/src/tests/utils/foundry.cairo deleted file mode 100644 index d624d9a79..000000000 --- a/src/tests/utils/foundry.cairo +++ /dev/null @@ -1,24 +0,0 @@ -use snforge_std::{declare, ContractClassTrait, spy_events, EventSpy, SpyOn}; -use starknet::ContractAddress; - -pub fn declare_and_deploy(contract_name: ByteArray, calldata: Array) -> ContractAddress { - let contract_class = declare(contract_name).unwrap(); - match contract_class.deploy(@calldata) { - Result::Ok((contract_address, _)) => contract_address, - Result::Err(panic_data) => panic!("Failed to deploy, error: ${:?}", panic_data) - } -} - -pub fn declare_and_deploy_at( - contract_name: ByteArray, target_address: ContractAddress, calldata: Array -) { - let contract_class = declare(contract_name).unwrap(); - if let Result::Err(panic_data) = contract_class.deploy_at(@calldata, target_address) { - panic!("Failed to deploy, error: ${:?}", panic_data) - } -} - -pub fn spy_on(contract_address: ContractAddress) -> EventSpy { - spy_events(SpyOn::One(contract_address)) -} - diff --git a/src/tests/utils/signing.cairo b/src/tests/utils/signing.cairo new file mode 100644 index 000000000..90be99ed5 --- /dev/null +++ b/src/tests/utils/signing.cairo @@ -0,0 +1,11 @@ +use snforge_std::signature::stark_curve::{StarkCurveSignerImpl, StarkCurveKeyPairImpl}; +use snforge_std::signature::{KeyPair, KeyPairTrait}; + +pub type StarkKeyPair = KeyPair; + +pub fn KEY_PAIR() -> StarkKeyPair { + KeyPairTrait::from_secret_key('SECRET_KEY') +} +pub fn KEY_PAIR_2() -> StarkKeyPair { + KeyPairTrait::from_secret_key('SECRET_KEY_2') +} From 9b333cc2c56322a4941a8466c3a2a0cd3f5ddbdb Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 4 Jul 2024 12:33:05 +0200 Subject: [PATCH 03/45] Re-add dual20 tests (#1028) * feat: migrate event tests * feat: update workflow * feat: add foundry utils * feat: finish erc20 and erc20votes migration * feat: remove dual case tests * refactor: format files * refactor: variable name * Update src/tests/token.cairo Co-authored-by: Andrew Fleming * Update src/tests/token/erc20.cairo Co-authored-by: Andrew Fleming * Update src/tests/utils/foundry.cairo Co-authored-by: Andrew Fleming * Update src/tests/token/erc20/test_erc20_votes.cairo Co-authored-by: Andrew Fleming * feat: apply review updates * feat: readd dual20 tests * refactor: remove unnecessary import * feat: add dual20 import --------- Co-authored-by: Andrew Fleming --- src/tests/token/erc20.cairo | 1 + src/tests/token/erc20/test_dual20.cairo | 325 ++++++++++++++++++++++++ 2 files changed, 326 insertions(+) create mode 100644 src/tests/token/erc20/test_dual20.cairo diff --git a/src/tests/token/erc20.cairo b/src/tests/token/erc20.cairo index 6b10a866e..8d094274f 100644 --- a/src/tests/token/erc20.cairo +++ b/src/tests/token/erc20.cairo @@ -1,4 +1,5 @@ pub(crate) mod common; +mod test_dual20; mod test_erc20; mod test_erc20_votes; diff --git a/src/tests/token/erc20/test_dual20.cairo b/src/tests/token/erc20/test_dual20.cairo new file mode 100644 index 000000000..dc37ce836 --- /dev/null +++ b/src/tests/token/erc20/test_dual20.cairo @@ -0,0 +1,325 @@ +use openzeppelin::tests::utils::constants::{ + OWNER, RECIPIENT, SPENDER, OPERATOR, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE +}; +use openzeppelin::tests::utils; +use openzeppelin::token::erc20::dual20::{DualCaseERC20, DualCaseERC20Trait}; +use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; +use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::{test_address, start_cheat_caller_address}; + +// +// Setup +// + +fn setup_snake() -> (DualCaseERC20, IERC20Dispatcher) { + let mut calldata = array![]; + calldata.append_serde(NAME()); + calldata.append_serde(SYMBOL()); + calldata.append_serde(SUPPLY); + calldata.append_serde(OWNER()); + let target = utils::declare_and_deploy("SnakeERC20Mock", calldata); + (DualCaseERC20 { contract_address: target }, IERC20Dispatcher { contract_address: target }) +} + +fn setup_camel() -> (DualCaseERC20, IERC20CamelDispatcher) { + let mut calldata = array![]; + calldata.append_serde(NAME()); + calldata.append_serde(SYMBOL()); + calldata.append_serde(SUPPLY); + calldata.append_serde(OWNER()); + let target = utils::declare_and_deploy("CamelERC20Mock", calldata); + (DualCaseERC20 { contract_address: target }, IERC20CamelDispatcher { contract_address: target }) +} + +fn setup_non_erc20() -> DualCaseERC20 { + let calldata = array![]; + let target = utils::declare_and_deploy("NonImplementingMock", calldata); + DualCaseERC20 { contract_address: target } +} + +fn setup_erc20_panic() -> (DualCaseERC20, DualCaseERC20) { + let snake_target = utils::declare_and_deploy("SnakeERC20Panic", array![]); + let camel_target = utils::declare_and_deploy("CamelERC20Panic", array![]); + ( + DualCaseERC20 { contract_address: snake_target }, + DualCaseERC20 { contract_address: camel_target } + ) +} + +// +// Case agnostic methods +// + +#[test] +#[ignore] +fn test_dual_name() { + let (snake_dispatcher, _) = setup_snake(); + assert_eq!(snake_dispatcher.name(), NAME()); + + let (camel_dispatcher, _) = setup_camel(); + assert_eq!(camel_dispatcher.name(), NAME()); +} + +#[test] +#[ignore] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +fn test_dual_no_name() { + let dispatcher = setup_non_erc20(); + dispatcher.name(); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_name_exists_and_panics() { + let (dispatcher, _) = setup_erc20_panic(); + dispatcher.name(); +} + +#[test] +#[ignore] +fn test_dual_symbol() { + let (snake_dispatcher, _) = setup_snake(); + let (camel_dispatcher, _) = setup_camel(); + assert_eq!(snake_dispatcher.symbol(), SYMBOL()); + assert_eq!(camel_dispatcher.symbol(), SYMBOL()); +} + +#[test] +#[ignore] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +fn test_dual_no_symbol() { + let dispatcher = setup_non_erc20(); + dispatcher.symbol(); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_symbol_exists_and_panics() { + let (dispatcher, _) = setup_erc20_panic(); + dispatcher.symbol(); +} + +#[test] +#[ignore] +fn test_dual_decimals() { + let (snake_dispatcher, _) = setup_snake(); + let (camel_dispatcher, _) = setup_camel(); + assert_eq!(snake_dispatcher.decimals(), DECIMALS); + assert_eq!(camel_dispatcher.decimals(), DECIMALS); +} + +#[test] +#[ignore] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +fn test_dual_no_decimals() { + let dispatcher = setup_non_erc20(); + dispatcher.decimals(); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_decimals_exists_and_panics() { + let (dispatcher, _) = setup_erc20_panic(); + dispatcher.decimals(); +} + +#[test] +#[ignore] +fn test_dual_transfer() { + let (snake_dispatcher, snake_target) = setup_snake(); + + start_cheat_caller_address(test_address(), OWNER()); + assert!(snake_dispatcher.transfer(RECIPIENT(), VALUE)); + assert_eq!(snake_target.balance_of(RECIPIENT()), VALUE); + + let (camel_dispatcher, camel_target) = setup_camel(); + start_cheat_caller_address(test_address(), OWNER()); + assert!(camel_dispatcher.transfer(RECIPIENT(), VALUE)); + assert_eq!(camel_target.balanceOf(RECIPIENT()), VALUE); +} + +#[test] +#[ignore] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +fn test_dual_no_transfer() { + let dispatcher = setup_non_erc20(); + dispatcher.transfer(RECIPIENT(), VALUE); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_transfer_exists_and_panics() { + let (dispatcher, _) = setup_erc20_panic(); + dispatcher.transfer(RECIPIENT(), VALUE); +} + +#[test] +#[ignore] +fn test_dual_approve() { + let (snake_dispatcher, snake_target) = setup_snake(); + start_cheat_caller_address(test_address(), OWNER()); + assert!(snake_dispatcher.approve(SPENDER(), VALUE)); + + let snake_allowance = snake_target.allowance(OWNER(), SPENDER()); + assert_eq!(snake_allowance, VALUE); + + let (camel_dispatcher, camel_target) = setup_camel(); + start_cheat_caller_address(test_address(), OWNER()); + assert!(camel_dispatcher.approve(SPENDER(), VALUE)); + + let camel_allowance = camel_target.allowance(OWNER(), SPENDER()); + assert_eq!(camel_allowance, VALUE); +} + +#[test] +#[ignore] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +fn test_dual_no_approve() { + let dispatcher = setup_non_erc20(); + dispatcher.approve(SPENDER(), VALUE); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_approve_exists_and_panics() { + let (dispatcher, _) = setup_erc20_panic(); + dispatcher.approve(SPENDER(), VALUE); +} + +// +// snake_case target +// + +#[test] +#[ignore] +fn test_dual_total_supply() { + let (dispatcher, _) = setup_snake(); + assert_eq!(dispatcher.total_supply(), SUPPLY); +} + +#[test] +#[ignore] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +fn test_dual_no_total_supply() { + let dispatcher = setup_non_erc20(); + dispatcher.total_supply(); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_total_supply_exists_and_panics() { + let (dispatcher, _) = setup_erc20_panic(); + dispatcher.total_supply(); +} + +#[test] +#[ignore] +fn test_dual_balance_of() { + let (dispatcher, _) = setup_snake(); + assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY); +} + +#[test] +#[ignore] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +fn test_dual_no_balance_of() { + let dispatcher = setup_non_erc20(); + dispatcher.balance_of(OWNER()); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_balance_of_exists_and_panics() { + let (dispatcher, _) = setup_erc20_panic(); + dispatcher.balance_of(OWNER()); +} + +#[test] +#[ignore] +fn test_dual_transfer_from() { + let (dispatcher, target) = setup_snake(); + start_cheat_caller_address(test_address(), OWNER()); + target.approve(OPERATOR(), VALUE); + + start_cheat_caller_address(test_address(), OPERATOR()); + dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); + assert_eq!(target.balance_of(RECIPIENT()), VALUE); +} + +#[test] +#[ignore] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +fn test_dual_no_transfer_from() { + let dispatcher = setup_non_erc20(); + dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_transfer_from_exists_and_panics() { + let (dispatcher, _) = setup_erc20_panic(); + dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); +} + +// +// camelCase target +// + +#[test] +#[ignore] +fn test_dual_totalSupply() { + let (dispatcher, _) = setup_camel(); + assert_eq!(dispatcher.total_supply(), SUPPLY); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_totalSupply_exists_and_panics() { + let (_, dispatcher) = setup_erc20_panic(); + dispatcher.total_supply(); +} + +#[test] +#[ignore] +fn test_dual_balanceOf() { + let (dispatcher, _) = setup_camel(); + assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_balanceOf_exists_and_panics() { + let (_, dispatcher) = setup_erc20_panic(); + dispatcher.balance_of(OWNER()); +} + +#[test] +#[ignore] +fn test_dual_transferFrom() { + let (dispatcher, target) = setup_camel(); + start_cheat_caller_address(test_address(), OWNER()); + target.approve(OPERATOR(), VALUE); + + start_cheat_caller_address(test_address(), OPERATOR()); + dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); + assert_eq!(target.balanceOf(RECIPIENT()), VALUE); +} + +#[test] +#[ignore] +#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +fn test_dual_transferFrom_exists_and_panics() { + let (_, dispatcher) = setup_erc20_panic(); + dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); +} From 0d149da76627cff3d132d61a71c156b0f941c92c Mon Sep 17 00:00:00 2001 From: Andrew Fleming Date: Fri, 5 Jul 2024 11:32:21 -0400 Subject: [PATCH 04/45] Migrate security tests (#1034) * migrate pausable and initializable tests * migrate reentrancy guard tests * clean up tests * fix fmt * add event trait to pausable, fix tests * Apply suggestions from code review Co-authored-by: Eric Nordelo * fix fmt --------- Co-authored-by: Eric Nordelo --- src/tests.cairo | 4 +- src/tests/security/test_pausable.cairo | 64 ++++++++++++------- src/tests/security/test_reentrancyguard.cairo | 23 ++----- 3 files changed, 51 insertions(+), 40 deletions(-) diff --git a/src/tests.cairo b/src/tests.cairo index 6b45d6e2c..eceac55c6 100644 --- a/src/tests.cairo +++ b/src/tests.cairo @@ -9,8 +9,8 @@ mod mocks; // #[cfg(test)] // mod presets; -// #[cfg(test)] -// mod security; +#[cfg(test)] +mod security; #[cfg(test)] mod token; // #[cfg(test)] diff --git a/src/tests/security/test_pausable.cairo b/src/tests/security/test_pausable.cairo index 8fd170df0..ea4ff3878 100644 --- a/src/tests/security/test_pausable.cairo +++ b/src/tests/security/test_pausable.cairo @@ -2,11 +2,11 @@ use openzeppelin::security::PausableComponent::{InternalImpl, PausableImpl}; use openzeppelin::security::PausableComponent::{Paused, Unpaused}; use openzeppelin::security::PausableComponent; use openzeppelin::tests::mocks::pausable_mocks::PausableMock; -use openzeppelin::tests::utils::constants::{CALLER, ZERO}; -use openzeppelin::tests::utils; +use openzeppelin::tests::utils::constants::CALLER; +use openzeppelin::tests::utils::events::EventSpyExt; +use snforge_std::EventSpy; +use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::ContractAddress; -use starknet::contract_address_const; -use starknet::testing; type ComponentState = PausableComponent::ComponentState; @@ -73,11 +73,13 @@ fn test_assert_not_paused_when_not_paused() { #[test] fn test_pause_when_unpaused() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(CALLER()); + let contract_address = test_address(); + let mut spy = spy_events(); + start_cheat_caller_address(contract_address, CALLER()); state.pause(); - assert_event_paused(CALLER()); + spy.assert_only_event_paused(contract_address, CALLER()); assert!(state.is_paused()); } @@ -96,14 +98,15 @@ fn test_pause_when_paused() { #[test] fn test_unpause_when_paused() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(CALLER()); + let contract_address = test_address(); + let mut spy = spy_events(); + start_cheat_caller_address(test_address(), CALLER()); state.pause(); - utils::drop_event(ZERO()); - state.unpause(); - assert_event_unpaused(CALLER()); + spy.assert_event_paused(contract_address, CALLER()); + spy.assert_only_event_unpaused(contract_address, CALLER()); assert!(!state.is_paused()); } @@ -119,16 +122,33 @@ fn test_unpause_when_unpaused() { // Helpers // -fn assert_event_paused(account: ContractAddress) { - let event = utils::pop_log::(ZERO()).unwrap(); - let expected = PausableComponent::Event::Paused(Paused { account }); - assert!(event == expected); - utils::assert_no_events_left(ZERO()); -} - -fn assert_event_unpaused(account: ContractAddress) { - let event = utils::pop_log::(ZERO()).unwrap(); - let expected = PausableComponent::Event::Unpaused(Unpaused { account }); - assert!(event == expected); - utils::assert_no_events_left(ZERO()); +#[generate_trait] +impl PausableSpyHelpersImpl of PausableSpyHelpers { + fn assert_event_paused( + ref self: EventSpy, contract: ContractAddress, account: ContractAddress + ) { + let expected = PausableComponent::Event::Paused(Paused { account }); + self.assert_emitted_single(contract, expected); + } + + fn assert_only_event_paused( + ref self: EventSpy, contract: ContractAddress, account: ContractAddress, + ) { + self.assert_event_paused(contract, account); + self.assert_no_events_left_from(contract); + } + + fn assert_event_unpaused( + ref self: EventSpy, contract: ContractAddress, account: ContractAddress + ) { + let expected = PausableComponent::Event::Unpaused(Unpaused { account }); + self.assert_emitted_single(contract, expected); + } + + fn assert_only_event_unpaused( + ref self: EventSpy, contract: ContractAddress, account: ContractAddress, + ) { + self.assert_event_unpaused(contract, account); + self.assert_no_events_left_from(contract); + } } diff --git a/src/tests/security/test_reentrancyguard.cairo b/src/tests/security/test_reentrancyguard.cairo index 327f72fa4..4a12bc918 100644 --- a/src/tests/security/test_reentrancyguard.cairo +++ b/src/tests/security/test_reentrancyguard.cairo @@ -1,7 +1,7 @@ use openzeppelin::security::ReentrancyGuardComponent::InternalImpl; use openzeppelin::security::ReentrancyGuardComponent; use openzeppelin::tests::mocks::reentrancy_mocks::{ - Attacker, ReentrancyMock, IReentrancyMockDispatcher, IReentrancyMockDispatcherTrait + ReentrancyMock, IReentrancyMockDispatcher, IReentrancyMockDispatcherTrait }; use openzeppelin::tests::utils; use starknet::storage::StorageMemberAccessTrait; @@ -14,7 +14,7 @@ fn COMPONENT_STATE() -> ComponentState { fn deploy_mock() -> IReentrancyMockDispatcher { let calldata = array![]; - let address = utils::deploy(ReentrancyMock::TEST_CLASS_HASH, calldata); + let address = utils::declare_and_deploy("ReentrancyMock", calldata); IReentrancyMockDispatcher { contract_address: address } } @@ -64,35 +64,26 @@ fn test_reentrancy_guard_end() { // #[test] -#[should_panic( - expected: ( - 'ReentrancyGuard: reentrant call', - 'ENTRYPOINT_FAILED', - 'ENTRYPOINT_FAILED', - 'ENTRYPOINT_FAILED' - ), -)] +#[should_panic(expected: ('ReentrancyGuard: reentrant call',))] fn test_remote_callback() { let contract = deploy_mock(); // Deploy attacker - let calldata = ArrayTrait::new(); - let attacker_addr = utils::deploy(Attacker::TEST_CLASS_HASH, calldata); + let calldata = array![]; + let attacker_addr = utils::declare_and_deploy("Attacker", calldata); contract.count_and_call(attacker_addr); } #[test] -#[should_panic(expected: ('ReentrancyGuard: reentrant call', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ReentrancyGuard: reentrant call',))] fn test_local_recursion() { let contract = deploy_mock(); contract.count_local_recursive(10); } #[test] -#[should_panic( - expected: ('ReentrancyGuard: reentrant call', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED') -)] +#[should_panic(expected: ('ReentrancyGuard: reentrant call',))] fn test_external_recursion() { let contract = deploy_mock(); contract.count_external_recursive(10); From a9b4eb3755f336aafdb64245756425dd256ba358 Mon Sep 17 00:00:00 2001 From: Alex Metelli Date: Sun, 7 Jul 2024 10:45:52 +0800 Subject: [PATCH 05/45] refacto repo into packages --- README.md | 2 +- Scarb.lock | 60 ++++++++++++++++++- Scarb.toml | 26 ++++++-- docs/modules/ROOT/pages/access.adoc | 22 +++---- docs/modules/ROOT/pages/accounts.adoc | 24 ++++---- docs/modules/ROOT/pages/api/access.adoc | 6 +- docs/modules/ROOT/pages/api/account.adoc | 10 ++-- docs/modules/ROOT/pages/api/erc1155.adoc | 14 ++--- docs/modules/ROOT/pages/api/erc20.adoc | 12 ++-- docs/modules/ROOT/pages/api/erc721.adoc | 14 ++--- docs/modules/ROOT/pages/api/governance.adoc | 2 +- .../modules/ROOT/pages/api/introspection.adoc | 4 +- docs/modules/ROOT/pages/api/security.adoc | 6 +- docs/modules/ROOT/pages/api/udc.adoc | 4 +- docs/modules/ROOT/pages/api/upgrades.adoc | 4 +- docs/modules/ROOT/pages/api/utilities.adoc | 44 +++++++------- docs/modules/ROOT/pages/components.adoc | 26 ++++---- docs/modules/ROOT/pages/erc1155.adoc | 8 +-- docs/modules/ROOT/pages/erc20.adoc | 4 +- docs/modules/ROOT/pages/erc721.adoc | 8 +-- .../ROOT/pages/guides/erc20-supply.adoc | 4 +- docs/modules/ROOT/pages/guides/snip12.adoc | 20 +++---- .../ROOT/pages/guides/src5-migration.adoc | 6 +- docs/modules/ROOT/pages/index.adoc | 2 +- docs/modules/ROOT/pages/interfaces.adoc | 4 +- docs/modules/ROOT/pages/introspection.adoc | 12 ++-- docs/modules/ROOT/pages/presets.adoc | 8 +-- docs/modules/ROOT/pages/security.adoc | 10 ++-- docs/modules/ROOT/pages/udc.adoc | 2 +- docs/modules/ROOT/pages/upgrades.adoc | 6 +- packages/access/README.md | 0 packages/access/Scarb.toml | 15 +++++ .../access/src}/accesscontrol.cairo | 0 .../src}/accesscontrol/accesscontrol.cairo | 8 +-- .../accesscontrol/dual_accesscontrol.cairo | 8 +-- .../access/src}/accesscontrol/interface.cairo | 0 .../access/src/lib.cairo | 0 .../access/src}/ownable.cairo | 0 .../access/src}/ownable/dual_ownable.cairo | 8 +-- .../access/src}/ownable/interface.cairo | 0 .../access/src}/ownable/ownable.cairo | 4 +- packages/account/README.md | 0 packages/account/Scarb.toml | 15 +++++ .../account/src}/account.cairo | 12 ++-- .../account/src}/dual_account.cairo | 8 +-- .../account/src}/dual_eth_account.cairo | 12 ++-- .../account/src}/eth_account.cairo | 16 ++--- .../account/src}/interface.cairo | 2 +- .../account/src/lib.cairo | 0 .../account/src}/utils.cairo | 0 .../account/src}/utils/secp256k1.cairo | 0 .../account/src}/utils/signature.cairo | 2 +- packages/governance/README.md | 0 packages/governance/Scarb.toml | 15 +++++ .../governance/src/lib.cairo | 0 .../governance/src}/utils.cairo | 0 .../governance/src}/utils/interfaces.cairo | 0 .../src}/utils/interfaces/votes.cairo | 0 packages/introspection/README.md | 0 packages/introspection/Scarb.toml | 13 ++++ .../introspection/src}/interface.cairo | 0 .../introspection/src/lib.cairo | 2 +- .../introspection/src}/src5.cairo | 2 +- packages/presets/README.md | 0 packages/presets/Scarb.toml | 18 ++++++ .../presets/src}/account.cairo | 8 +-- .../presets/src}/erc1155.cairo | 10 ++-- .../presets/src}/erc20.cairo | 8 +-- .../presets/src}/erc721.cairo | 10 ++-- .../presets/src}/eth_account.cairo | 12 ++-- .../presets/src}/interfaces.cairo | 0 .../presets/src}/interfaces/account.cairo | 0 .../presets/src}/interfaces/erc1155.cairo | 0 .../presets/src}/interfaces/erc20.cairo | 0 .../presets/src}/interfaces/erc721.cairo | 0 .../presets/src}/interfaces/eth_account.cairo | 4 +- .../presets/src/lib.cairo | 0 .../presets/src}/universal_deployer.cairo | 2 +- packages/security/README.md | 0 packages/security/Scarb.toml | 13 ++++ .../security/src}/initializable.cairo | 2 +- .../security/src}/interface.cairo | 0 .../security/src/lib.cairo | 0 .../security/src}/pausable.cairo | 2 +- .../security/src}/reentrancyguard.cairo | 0 packages/token/README.md | 0 packages/token/Scarb.toml | 16 +++++ .../token/src}/erc1155.cairo | 0 .../token/src}/erc1155/dual1155.cairo | 8 +-- .../src}/erc1155/dual1155_receiver.cairo | 8 +-- .../token/src}/erc1155/erc1155.cairo | 17 +++--- .../token/src}/erc1155/erc1155_receiver.cairo | 10 ++-- .../token/src}/erc1155/interface.cairo | 0 {src/token => packages/token/src}/erc20.cairo | 0 .../token/src}/erc20/dual20.cairo | 8 +-- .../token/src}/erc20/erc20.cairo | 2 +- .../token/src}/erc20/extensions.cairo | 0 .../src}/erc20/extensions/erc20_votes.cairo | 16 ++--- .../token/src}/erc20/interface.cairo | 2 +- .../token => packages/token/src}/erc721.cairo | 0 .../token/src}/erc721/dual721.cairo | 8 +-- .../token/src}/erc721/dual721_receiver.cairo | 8 +-- .../token/src}/erc721/erc721.cairo | 15 +++-- .../token/src}/erc721/erc721_receiver.cairo | 12 ++-- .../token/src}/erc721/interface.cairo | 0 .../token/src/lib.cairo | 0 packages/upgrades/README.md | 0 packages/upgrades/Scarb.toml | 13 ++++ .../upgrades/src}/interface.cairo | 0 .../upgrades/src/lib.cairo | 0 .../upgrades/src}/upgradeable.cairo | 0 packages/utils/README.md | 0 packages/utils/Scarb.toml | 13 ++++ .../utils/src}/cryptography.cairo | 0 .../utils/src}/cryptography/interface.cairo | 0 .../utils/src}/cryptography/nonces.cairo | 2 +- .../utils/src}/cryptography/snip12.cairo | 0 .../utils/src}/deployments.cairo | 2 +- .../utils/src}/deployments/interface.cairo | 0 .../utils/src}/interfaces.cairo | 4 +- .../utils/src/lib.cairo | 0 {src/utils => packages/utils/src}/math.cairo | 0 .../utils/src}/selectors.cairo | 0 {src/utils => packages/utils/src}/serde.cairo | 0 .../utils/src}/structs.cairo | 0 .../utils/src}/structs/checkpoint.cairo | 2 +- .../utils/src}/structs/storage_array.cairo | 0 .../utils/src}/unwrap_and_cast.cairo | 0 src/lib.cairo | 2 +- src/tests/access/common.cairo | 6 +- src/tests/access/test_accesscontrol.cairo | 18 +++--- .../access/test_dual_accesscontrol.cairo | 18 +++--- src/tests/access/test_dual_ownable.cairo | 12 ++-- src/tests/access/test_ownable.cairo | 6 +- src/tests/access/test_ownable_twostep.cairo | 10 ++-- src/tests/account/ethereum/common.cairo | 12 ++-- .../ethereum/test_dual_eth_account.cairo | 12 ++-- .../account/ethereum/test_eth_account.cairo | 24 ++++---- src/tests/account/starknet/common.cairo | 8 +-- src/tests/account/starknet/test_account.cairo | 18 +++--- .../account/starknet/test_dual_account.cairo | 6 +- src/tests/account/test_secp256k1.cairo | 2 +- src/tests/account/test_signature.cairo | 2 +- src/tests/cryptography/test_nonces.cairo | 6 +- src/tests/cryptography/test_snip12.cairo | 2 +- src/tests/introspection/test_src5.cairo | 6 +- src/tests/mocks/accesscontrol_mocks.cairo | 18 +++--- src/tests/mocks/account_mocks.cairo | 12 ++-- src/tests/mocks/erc1155_mocks.cairo | 12 ++-- src/tests/mocks/erc1155_receiver_mocks.cairo | 12 ++-- src/tests/mocks/erc20_mocks.cairo | 6 +- src/tests/mocks/erc20_votes_mocks.cairo | 10 ++-- src/tests/mocks/erc721_mocks.cairo | 14 ++--- src/tests/mocks/erc721_receiver_mocks.cairo | 12 ++-- src/tests/mocks/eth_account_mocks.cairo | 32 +++++----- src/tests/mocks/initializable_mocks.cairo | 2 +- src/tests/mocks/nonces_mocks.cairo | 2 +- src/tests/mocks/ownable_mocks.cairo | 8 +-- src/tests/mocks/pausable_mocks.cairo | 2 +- src/tests/mocks/reentrancy_mocks.cairo | 2 +- src/tests/mocks/src5_mocks.cairo | 2 +- src/tests/mocks/upgrades_mocks.cairo | 4 +- src/tests/presets/test_account.cairo | 16 ++--- src/tests/presets/test_erc1155.cairo | 16 +++-- src/tests/presets/test_erc20.cairo | 12 ++-- src/tests/presets/test_erc721.cairo | 20 +++---- src/tests/presets/test_eth_account.cairo | 18 +++--- .../presets/test_universal_deployer.cairo | 12 ++-- src/tests/security/test_initializable.cairo | 4 +- src/tests/security/test_pausable.cairo | 6 +- src/tests/security/test_reentrancyguard.cairo | 4 +- src/tests/token/erc1155/common.cairo | 6 +- src/tests/token/erc1155/test_dual1155.cairo | 10 ++-- .../erc1155/test_dual1155_receiver.cairo | 8 +-- src/tests/token/erc1155/test_erc1155.cairo | 16 ++--- .../token/erc1155/test_erc1155_receiver.cairo | 8 +-- src/tests/token/erc20/common.cairo | 6 +- src/tests/token/erc20/test_dual20.cairo | 8 +-- src/tests/token/erc20/test_erc20.cairo | 10 ++-- src/tests/token/erc20/test_erc20_votes.cairo | 16 ++--- src/tests/token/erc721/common.cairo | 6 +- src/tests/token/erc721/test_dual721.cairo | 10 ++-- .../token/erc721/test_dual721_receiver.cairo | 8 +-- src/tests/token/erc721/test_erc721.cairo | 20 +++---- .../token/erc721/test_erc721_receiver.cairo | 8 +-- src/tests/upgrades/common.cairo | 4 +- src/tests/upgrades/test_upgradeable.cairo | 2 +- src/tests/utils/constants.cairo | 2 +- 188 files changed, 773 insertions(+), 574 deletions(-) create mode 100644 packages/access/README.md create mode 100644 packages/access/Scarb.toml rename {src/access => packages/access/src}/accesscontrol.cairo (100%) rename {src/access => packages/access/src}/accesscontrol/accesscontrol.cairo (97%) rename {src/access => packages/access/src}/accesscontrol/dual_accesscontrol.cairo (94%) rename {src/access => packages/access/src}/accesscontrol/interface.cairo (100%) rename src/access.cairo => packages/access/src/lib.cairo (100%) rename {src/access => packages/access/src}/ownable.cairo (100%) rename {src/access => packages/access/src}/ownable/dual_ownable.cairo (89%) rename {src/access => packages/access/src}/ownable/interface.cairo (100%) rename {src/access => packages/access/src}/ownable/ownable.cairo (99%) create mode 100644 packages/account/README.md create mode 100644 packages/account/Scarb.toml rename {src/account => packages/account/src}/account.cairo (96%) rename {src/account => packages/account/src}/dual_account.cairo (92%) rename {src/account => packages/account/src}/dual_eth_account.cairo (88%) rename {src/account => packages/account/src}/eth_account.cairo (96%) rename {src/account => packages/account/src}/interface.cairo (98%) rename src/account.cairo => packages/account/src/lib.cairo (100%) rename {src/account => packages/account/src}/utils.cairo (100%) rename {src/account => packages/account/src}/utils/secp256k1.cairo (100%) rename {src/account => packages/account/src}/utils/signature.cairo (96%) create mode 100644 packages/governance/README.md create mode 100644 packages/governance/Scarb.toml rename src/governance.cairo => packages/governance/src/lib.cairo (100%) rename {src/governance => packages/governance/src}/utils.cairo (100%) rename {src/governance => packages/governance/src}/utils/interfaces.cairo (100%) rename {src/governance => packages/governance/src}/utils/interfaces/votes.cairo (100%) create mode 100644 packages/introspection/README.md create mode 100644 packages/introspection/Scarb.toml rename {src/introspection => packages/introspection/src}/interface.cairo (100%) rename src/introspection.cairo => packages/introspection/src/lib.cairo (57%) rename {src/introspection => packages/introspection/src}/src5.cairo (97%) create mode 100644 packages/presets/README.md create mode 100644 packages/presets/Scarb.toml rename {src/presets => packages/presets/src}/account.cairo (89%) rename {src/presets => packages/presets/src}/erc1155.cairo (91%) rename {src/presets => packages/presets/src}/erc20.cairo (91%) rename {src/presets => packages/presets/src}/erc721.cairo (91%) rename {src/presets => packages/presets/src}/eth_account.cairo (84%) rename {src/presets => packages/presets/src}/interfaces.cairo (100%) rename {src/presets => packages/presets/src}/interfaces/account.cairo (100%) rename {src/presets => packages/presets/src}/interfaces/erc1155.cairo (100%) rename {src/presets => packages/presets/src}/interfaces/erc20.cairo (100%) rename {src/presets => packages/presets/src}/interfaces/erc721.cairo (100%) rename {src/presets => packages/presets/src}/interfaces/eth_account.cairo (91%) rename src/presets.cairo => packages/presets/src/lib.cairo (100%) rename {src/presets => packages/presets/src}/universal_deployer.cairo (97%) create mode 100644 packages/security/README.md create mode 100644 packages/security/Scarb.toml rename {src/security => packages/security/src}/initializable.cairo (96%) rename {src/security => packages/security/src}/interface.cairo (100%) rename src/security.cairo => packages/security/src/lib.cairo (100%) rename {src/security => packages/security/src}/pausable.cairo (98%) rename {src/security => packages/security/src}/reentrancyguard.cairo (100%) create mode 100644 packages/token/README.md create mode 100644 packages/token/Scarb.toml rename {src/token => packages/token/src}/erc1155.cairo (100%) rename {src/token => packages/token/src}/erc1155/dual1155.cairo (96%) rename {src/token => packages/token/src}/erc1155/dual1155_receiver.cairo (92%) rename {src/token => packages/token/src}/erc1155/erc1155.cairo (97%) rename {src/token => packages/token/src}/erc1155/erc1155_receiver.cairo (94%) rename {src/token => packages/token/src}/erc1155/interface.cairo (100%) rename {src/token => packages/token/src}/erc20.cairo (100%) rename {src/token => packages/token/src}/erc20/dual20.cairo (95%) rename {src/token => packages/token/src}/erc20/erc20.cairo (99%) rename {src/token => packages/token/src}/erc20/extensions.cairo (100%) rename {src/token => packages/token/src}/erc20/extensions/erc20_votes.cairo (95%) rename {src/token => packages/token/src}/erc20/interface.cairo (98%) rename {src/token => packages/token/src}/erc721.cairo (100%) rename {src/token => packages/token/src}/erc721/dual721.cairo (96%) rename {src/token => packages/token/src}/erc721/dual721_receiver.cairo (86%) rename {src/token => packages/token/src}/erc721/erc721.cairo (98%) rename {src/token => packages/token/src}/erc721/erc721_receiver.cairo (89%) rename {src/token => packages/token/src}/erc721/interface.cairo (100%) rename src/token.cairo => packages/token/src/lib.cairo (100%) create mode 100644 packages/upgrades/README.md create mode 100644 packages/upgrades/Scarb.toml rename {src/upgrades => packages/upgrades/src}/interface.cairo (100%) rename src/upgrades.cairo => packages/upgrades/src/lib.cairo (100%) rename {src/upgrades => packages/upgrades/src}/upgradeable.cairo (100%) create mode 100644 packages/utils/README.md create mode 100644 packages/utils/Scarb.toml rename {src/utils => packages/utils/src}/cryptography.cairo (100%) rename {src/utils => packages/utils/src}/cryptography/interface.cairo (100%) rename {src/utils => packages/utils/src}/cryptography/nonces.cairo (97%) rename {src/utils => packages/utils/src}/cryptography/snip12.cairo (100%) rename {src/utils => packages/utils/src}/deployments.cairo (98%) rename {src/utils => packages/utils/src}/deployments/interface.cairo (100%) rename {src/utils => packages/utils/src}/interfaces.cairo (57%) rename src/utils.cairo => packages/utils/src/lib.cairo (100%) rename {src/utils => packages/utils/src}/math.cairo (100%) rename {src/utils => packages/utils/src}/selectors.cairo (100%) rename {src/utils => packages/utils/src}/serde.cairo (100%) rename {src/utils => packages/utils/src}/structs.cairo (100%) rename {src/utils => packages/utils/src}/structs/checkpoint.cairo (99%) rename {src/utils => packages/utils/src}/structs/storage_array.cairo (100%) rename {src/utils => packages/utils/src}/unwrap_and_cast.cairo (100%) diff --git a/README.md b/README.md index b5750a91e..2f0c53698 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ For example, this is how to write an ERC20-compliant contract: ```cairo #[starknet::contract] mod MyToken { - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); diff --git a/Scarb.lock b/Scarb.lock index 8e8b73b05..1327fcc71 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -2,5 +2,61 @@ version = 1 [[package]] -name = "openzeppelin" -version = "0.14.0" +name = "openzeppelin_access" +version = "0.1.0" +dependencies = [ + "openzeppelin_introspection", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_account" +version = "0.1.0" +dependencies = [ + "openzeppelin_introspection", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_governance" +version = "0.1.0" +dependencies = [ + "openzeppelin_introspection", + "openzeppelin_utils", +] + +[[package]] +name = "openzeppelin_introspection" +version = "0.1.0" + +[[package]] +name = "openzeppelin_presets" +version = "0.1.0" +dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_introspection", + "openzeppelin_token", + "openzeppelin_upgrades", +] + +[[package]] +name = "openzeppelin_security" +version = "0.1.0" + +[[package]] +name = "openzeppelin_token" +version = "0.1.0" +dependencies = [ + "openzeppelin_account", + "openzeppelin_governance", + "openzeppelin_introspection", +] + +[[package]] +name = "openzeppelin_upgrades" +version = "0.1.0" + +[[package]] +name = "openzeppelin_utils" +version = "0.1.0" diff --git a/Scarb.toml b/Scarb.toml index a99d0ba14..dd4169056 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,4 +1,15 @@ -[package] +[workspace] +members = [ + "packages/access", + "packages/account", + "packages/governance", + "packages/introspection", + "packages/presets", + "packages/security", + "packages/token", + "packages/upgrades", + "packages/utils", +] name = "openzeppelin" version = "0.14.0" edition = "2023_11" @@ -10,9 +21,16 @@ documentation = "https://docs.openzeppelin.com/contracts-cairo" readme = "README.md" repository = "https://github.com/OpenZeppelin/cairo-contracts" license-file = "LICENSE" -keywords = ["openzeppelin", "starknet", "cairo", "contracts", "security", "standards"] +keywords = [ + "openzeppelin", + "starknet", + "cairo", + "contracts", + "security", + "standards", +] -[dependencies] +[workspace.dependencies] starknet = "2.6.4" [lib] @@ -22,5 +40,5 @@ allowed-libfuncs-list.name = "experimental" sierra = true casm = false -[tool.fmt] +[workspace.tool.fmt] sort-module-level-items = true diff --git a/docs/modules/ROOT/pages/access.adoc b/docs/modules/ROOT/pages/access.adoc index dbd987a1e..28f8fa8be 100644 --- a/docs/modules/ROOT/pages/access.adoc +++ b/docs/modules/ROOT/pages/access.adoc @@ -26,7 +26,7 @@ xref:/api/access.adoc#OwnableComponent-initializer[`initializer`] like this: ---- #[starknet::contract] mod MyContract { - use openzeppelin::access::ownable::OwnableComponent; + use openzeppelin_access::ownable::OwnableComponent; use starknet::ContractAddress; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); @@ -174,9 +174,9 @@ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE"); #[starknet::contract] mod MyContract { - use openzeppelin::access::accesscontrol::AccessControlComponent; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; use super::MINTER_ROLE; @@ -265,9 +265,9 @@ const BURNER_ROLE: felt252 = selector!("BURNER_ROLE"); #[starknet::contract] mod MyContract { - use openzeppelin::access::accesscontrol::AccessControlComponent; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; use super::{MINTER_ROLE, BURNER_ROLE}; @@ -387,10 +387,10 @@ const BURNER_ROLE: felt252 = selector!("BURNER_ROLE"); #[starknet::contract] mod MyContract { - use openzeppelin::access::accesscontrol::AccessControlComponent; - use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; use super::{MINTER_ROLE, BURNER_ROLE}; diff --git a/docs/modules/ROOT/pages/accounts.adoc b/docs/modules/ROOT/pages/accounts.adoc index b6aaa2e48..68d93e161 100644 --- a/docs/modules/ROOT/pages/accounts.adoc +++ b/docs/modules/ROOT/pages/accounts.adoc @@ -112,8 +112,8 @@ Constructing an account contract requires integrating both {account-component} a ---- #[starknet::contract(account)] mod MyAccount { - use openzeppelin::account::AccountComponent; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; component!(path: AccountComponent, storage: account, event: AccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -202,10 +202,10 @@ Here’s an example of a basic contract: ---- #[starknet::contract(account)] mod MyEthAccount { - use openzeppelin::account::EthAccountComponent; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; + use openzeppelin_introspection::src5::SRC5Component; use starknet::ClassHash; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); @@ -304,8 +304,8 @@ First, let's take the example account we created before and deploy it: ```[,cairo] #[starknet::contract(account)] mod MyAccount { - use openzeppelin::account::AccountComponent; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; component!(path: AccountComponent, storage: account, event: AccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -387,10 +387,10 @@ First, let's take the example account we created before and deploy it: ```[,cairo] #[starknet::contract(account)] mod MyEthAccount { - use openzeppelin::account::EthAccountComponent; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; + use openzeppelin_introspection::src5::SRC5Component; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); diff --git a/docs/modules/ROOT/pages/api/access.adoc b/docs/modules/ROOT/pages/api/access.adoc index 5338692ce..1c8dc4e76 100644 --- a/docs/modules/ROOT/pages/api/access.adoc +++ b/docs/modules/ROOT/pages/api/access.adoc @@ -23,7 +23,7 @@ assigned each to multiple accounts. === `++OwnableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/access/ownable/ownable.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::access::ownable::OwnableComponent; +use openzeppelin_access::ownable::OwnableComponent; ``` `Ownable` provides a basic access control mechanism where an account @@ -276,7 +276,7 @@ Emitted when the ownership is transferred. :RoleAdminChanged: xref:#IAccessControl-RoleAdminChanged[RoleAdminChanged] ```cairo -use openzeppelin::access::accesscontrol::interface::IAccessControl; +use openzeppelin_access::accesscontrol::interface::IAccessControl; ``` External interface of AccessControl. @@ -407,7 +407,7 @@ Emitted when `account` is revoked `role`. :revoke_role: xref:#AccessControlComponent-revoke_role[revoke_role] ```cairo -use openzeppelin::access::accesscontrol::AccessControlComponent; +use openzeppelin_access::accesscontrol::AccessControlComponent; ``` Component that allows contracts to implement role-based access control mechanisms. diff --git a/docs/modules/ROOT/pages/api/account.adoc b/docs/modules/ROOT/pages/api/account.adoc index 04cd5e9f4..866e09900 100644 --- a/docs/modules/ROOT/pages/api/account.adoc +++ b/docs/modules/ROOT/pages/api/account.adoc @@ -15,7 +15,7 @@ include::../utils/_common.adoc[] === `++ISRC6++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/account/interface.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::account::interface::ISRC6; +use openzeppelin_account::interface::ISRC6; ``` Interface of the SRC6 Standard Account as defined in the {snip6}. @@ -72,7 +72,7 @@ Returns the short string `'VALID'` if valid, otherwise it reverts. :starknet-curve: https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/stark-curve/[Starknet curve] ```cairo -use openzeppelin::account::AccountComponent; +use openzeppelin_account::AccountComponent; ``` Account component implementing xref:ISRC6[`ISRC6`] for signatures over the {starknet-curve}. @@ -322,7 +322,7 @@ Emitted when a `public_key` is removed. :secp256k1-curve: https://en.bitcoin.it/wiki/Secp256k1[Secp256k1 curve] ```cairo -use openzeppelin::account::eth_account::EthAccountComponent; +use openzeppelin_account::eth_account::EthAccountComponent; ``` Account component implementing xref:ISRC6[`ISRC6`] for signatures over the {secp256k1-curve}. @@ -573,7 +573,7 @@ Emitted when a `public_key` is removed. === `++AccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets/account.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::presets::AccountUpgradeable; +use openzeppelin_presets::AccountUpgradeable; ``` Upgradeable account contract leveraging xref:#AccountComponent[AccountComponent]. @@ -634,7 +634,7 @@ Requirements: === `++EthAccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets/eth_account.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::presets::EthAccountUpgradeable; +use openzeppelin_presets::EthAccountUpgradeable; ``` Upgradeable account contract leveraging xref:#EthAccountComponent[EthAccountComponent]. diff --git a/docs/modules/ROOT/pages/api/erc1155.adoc b/docs/modules/ROOT/pages/api/erc1155.adoc index 029cf84e3..16e4fb99d 100644 --- a/docs/modules/ROOT/pages/api/erc1155.adoc +++ b/docs/modules/ROOT/pages/api/erc1155.adoc @@ -20,7 +20,7 @@ TIP: For an overview of ERC1155, read our xref:erc1155.adoc[ERC1155 guide]. [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc1155::interface::IERC1155; +use openzeppelin_token::erc1155::interface::IERC1155; ``` Interface of the IERC1155 standard as defined in {eip1155}. @@ -130,7 +130,7 @@ Emitted when the token URI is updated to `value` for the `id` token. [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc1155::interface::IERC1155MetadataURI; +use openzeppelin_token::erc1155::interface::IERC1155MetadataURI; ``` Interface for the optional metadata function in {eip1155-metadata}[EIP1155]. @@ -160,7 +160,7 @@ Returns the Uniform Resource Identifier (URI) for the `token_id` token. [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc1155::ERC1155Component; +use openzeppelin_token::erc1155::ERC1155Component; ``` ERC1155 component implementing <> and <>. @@ -246,7 +246,7 @@ Hooks are functions which implementations can extend the functionality of the co using ERC1155Component is expected to provide an implementation of the ERC1155HooksTrait. For basic token contracts, an empty implementation with no logic must be provided. -TIP: You can use `openzeppelin::token::erc1155::ERC1155HooksEmptyImpl` which is already available as part of the library +TIP: You can use `openzeppelin_token::erc1155::ERC1155HooksEmptyImpl` which is already available as part of the library for this purpose. [.contract-item] @@ -547,7 +547,7 @@ See <>. [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc1155::interface::IERC1155Receiver; +use openzeppelin_token::erc1155::interface::IERC1155Receiver; ``` Interface for contracts that support receiving token transfers from `ERC1155` contracts. @@ -587,7 +587,7 @@ via <> by [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc1155::ERC1155ReceiverComponent; +use openzeppelin_token::erc1155::ERC1155ReceiverComponent; ``` ERC1155Receiver component implementing <>. @@ -663,7 +663,7 @@ Registers the `IERC1155Receiver` interface ID as supported through introspection === `++ERC1155Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets/erc1155.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::presets::ERC1155; +use openzeppelin_presets::ERC1155; ``` Upgradeable ERC1155 contract leveraging xref:#ERC1155Component[ERC1155Component]. diff --git a/docs/modules/ROOT/pages/api/erc20.adoc b/docs/modules/ROOT/pages/api/erc20.adoc index 48e2f7349..378548f61 100644 --- a/docs/modules/ROOT/pages/api/erc20.adoc +++ b/docs/modules/ROOT/pages/api/erc20.adoc @@ -20,7 +20,7 @@ TIP: For an overview of ERC20, read our {erc20-guide}. [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc20::interface::IERC20; +use openzeppelin_token::erc20::interface::IERC20; ``` Interface of the IERC20 standard as defined in {eip20}. @@ -118,7 +118,7 @@ Emitted when the allowance of a `spender` for an `owner` is set. [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc20::interface::IERC20Metadata; +use openzeppelin_token::erc20::interface::IERC20Metadata; ``` Interface for the optional metadata functions in {eip20}. @@ -166,7 +166,7 @@ NOTE: This information is only used for _display_ purposes: it in no way affects [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc20::ERC20Component; +use openzeppelin_token::erc20::ERC20Component; ``` ERC20 component extending <> and <>. @@ -242,7 +242,7 @@ Hooks are functions which implementations can extend the functionality of the co using ERC20Component is expected to provide an implementation of the ERC20HooksTrait. For basic token contracts, an empty implementation with no logic must be provided. -TIP: You can use `openzeppelin::token::erc20::ERC20HooksEmptyImpl` which is already available as part of the library +TIP: You can use `openzeppelin_token::erc20::ERC20HooksEmptyImpl` which is already available as part of the library for this purpose. [.contract-item] @@ -463,7 +463,7 @@ See <>. === `++ERC20VotesComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc20/extensions/erc20_votes.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::token::extensions::ERC20VotesComponent; +use openzeppelin_token::extensions::ERC20VotesComponent; ``` :DelegateChanged: xref:ERC20VotesComponent-DelegateChanged[DelegateChanged] @@ -657,7 +657,7 @@ Emitted when `delegate` votes are updated from `previous_votes` to `new_votes`. === `++ERC20Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets/erc20.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::presets::ERC20Upgradeable; +use openzeppelin_presets::ERC20Upgradeable; ``` Upgradeable ERC20 contract leveraging xref:#ERC20Component[ERC20Component] with a fixed-supply mechanism for token distribution. diff --git a/docs/modules/ROOT/pages/api/erc721.adoc b/docs/modules/ROOT/pages/api/erc721.adoc index ecf4b7a97..cbbb72e1e 100644 --- a/docs/modules/ROOT/pages/api/erc721.adoc +++ b/docs/modules/ROOT/pages/api/erc721.adoc @@ -20,7 +20,7 @@ TIP: For an overview of ERC721, read our xref:erc721.adoc[ERC721 guide]. [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc721::interface::IERC721; +use openzeppelin_token::erc721::interface::IERC721; ``` Interface of the IERC721 standard as defined in {eip721}. @@ -139,7 +139,7 @@ Emitted when `token_id` token is transferred from `from` to `to`. [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc721::interface::IERC721Metadata; +use openzeppelin_token::erc721::interface::IERC721Metadata; ``` Interface for the optional metadata functions in {eip721}. @@ -185,7 +185,7 @@ If the URI is not set for `token_id`, the return value will be an empty `ByteArr [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc721::ERC721Component; +use openzeppelin_token::erc721::ERC721Component; ``` ERC721 component implementing <> and <>. @@ -292,7 +292,7 @@ Hooks are functions which implementations can extend the functionality of the co using ERC721Component is expected to provide an implementation of the ERC721HooksTrait. For basic token contracts, an empty implementation with no logic must be provided. -TIP: You can use `openzeppelin::token::erc721::ERC721HooksEmptyImpl` which is already available as part of the library +TIP: You can use `openzeppelin_token::erc721::ERC721HooksEmptyImpl` which is already available as part of the library for this purpose. [.contract-item] @@ -697,7 +697,7 @@ See <>. [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc721::interface::IERC721Receiver; +use openzeppelin_token::erc721::interface::IERC721Receiver; ``` Interface for contracts that support receiving `safe_transfer_from` transfers. @@ -728,7 +728,7 @@ Whenever an IERC721 `token_id` token is transferred to this non-account contract [.hljs-theme-dark] ```cairo -use openzeppelin::token::erc721::ERC721ReceiverComponent; +use openzeppelin_token::erc721::ERC721ReceiverComponent; ``` ERC721Receiver component implementing <>. @@ -793,7 +793,7 @@ Registers the `IERC721Receiver` interface ID as supported through introspection. === `++ERC721Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets/erc721.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::presets::ERC721Upgradeable; +use openzeppelin_presets::ERC721Upgradeable; ``` Upgradeable ERC721 contract leveraging xref:#ERC721Component[ERC721Component]. diff --git a/docs/modules/ROOT/pages/api/governance.adoc b/docs/modules/ROOT/pages/api/governance.adoc index 1d2451eb2..ea2b47c2c 100644 --- a/docs/modules/ROOT/pages/api/governance.adoc +++ b/docs/modules/ROOT/pages/api/governance.adoc @@ -12,7 +12,7 @@ Reference of interfaces and utilities related to Governance. [.hljs-theme-dark] ```cairo -use openzeppelin::governance::utils::interfaces::IVotes; +use openzeppelin_governance::utils::interfaces::IVotes; ``` Common interface for Votes-enabled contracts. For an implementation example see diff --git a/docs/modules/ROOT/pages/api/introspection.adoc b/docs/modules/ROOT/pages/api/introspection.adoc index c1e35dcba..ebf94e41e 100644 --- a/docs/modules/ROOT/pages/api/introspection.adoc +++ b/docs/modules/ROOT/pages/api/introspection.adoc @@ -13,7 +13,7 @@ Reference of interfaces and utilities related to https://en.wikipedia.org/wiki/T === `++ISRC5++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/introspection/interface.cairo#L7[{github-icon},role=heading-link] ```cairo -use openzeppelin::introspection::interface::ISRC5; +use openzeppelin_introspection::interface::ISRC5; ``` Interface of the SRC5 Introspection Standard as defined in {snip5}. @@ -47,7 +47,7 @@ on how to compute this ID. === `++SRC5Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/introspection/src5.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::introspection::src5::SRC5Component; +use openzeppelin_introspection::src5::SRC5Component; ``` SRC5 component extending xref:ISRC5[`ISRC5`]. diff --git a/docs/modules/ROOT/pages/api/security.adoc b/docs/modules/ROOT/pages/api/security.adoc index 02b137467..fdac26d96 100644 --- a/docs/modules/ROOT/pages/api/security.adoc +++ b/docs/modules/ROOT/pages/api/security.adoc @@ -11,7 +11,7 @@ Reference of components, interfaces and utilities found in the library's `securi === `++InitializableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/security/initializable.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::security::InitializableComponent; +use openzeppelin_security::InitializableComponent; ``` Component enabling one-time initialization for contracts. @@ -64,7 +64,7 @@ Requirements: :Unpaused: xref:PausableComponent-Unpaused[Unpaused] ```cairo -use openzeppelin::security::PausableComponent; +use openzeppelin_security::PausableComponent; ``` Component to implement an emergency stop mechanism. @@ -166,7 +166,7 @@ Emitted when the contract is unpaused by `account`. === `++ReentrancyGuardComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/security/reentrancyguard.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::security::ReentrancyGuardComponent; +use openzeppelin_security::ReentrancyGuardComponent; ``` Component to help prevent reentrant calls. diff --git a/docs/modules/ROOT/pages/api/udc.adoc b/docs/modules/ROOT/pages/api/udc.adoc index 25c68731e..3f61021be 100644 --- a/docs/modules/ROOT/pages/api/udc.adoc +++ b/docs/modules/ROOT/pages/api/udc.adoc @@ -11,7 +11,7 @@ Reference of the Universal Deployer Contract (UDC) interface and preset. === `++IUniversalDeployer++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/utils/universal_deployer/interface.cairo#L7[{github-icon},role=heading-link] ```cairo -use openzeppelin::utils::interfaces::IUniversalDeployer; +use openzeppelin_utils::interfaces::IUniversalDeployer; ``` [.contract-index] @@ -54,7 +54,7 @@ Emitted when `deployer` deploys a contract through the Universal Deployer Contra === `++UniversalDeployer++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/presets/universal_deployer.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::presets::UniversalDeployer; +use openzeppelin_presets::UniversalDeployer; ``` The standard Universal Deployer Contract. diff --git a/docs/modules/ROOT/pages/api/upgrades.adoc b/docs/modules/ROOT/pages/api/upgrades.adoc index c7673fbf2..709d070f4 100644 --- a/docs/modules/ROOT/pages/api/upgrades.adoc +++ b/docs/modules/ROOT/pages/api/upgrades.adoc @@ -14,7 +14,7 @@ Reference of interfaces and utilities related to upgradeability. :Upgraded: xref:UpgradeableComponent-Upgraded[Upgraded] ```cairo -use openzeppelin::upgrades::interface::IUpgradeable; +use openzeppelin_upgrades::interface::IUpgradeable; ``` Interface of an upgradeable contract. @@ -41,7 +41,7 @@ NOTE: This function is usually protected by an xref:access.adoc[Access Control] === `++UpgradeableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/upgrades/upgradeable.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin::upgrades::upgradeable::UpgradeableComponent; +use openzeppelin_upgrades::upgradeable::UpgradeableComponent; ``` Upgradeable component. diff --git a/docs/modules/ROOT/pages/api/utilities.adoc b/docs/modules/ROOT/pages/api/utilities.adoc index 3feaa991f..3a0a3608e 100644 --- a/docs/modules/ROOT/pages/api/utilities.adoc +++ b/docs/modules/ROOT/pages/api/utilities.adoc @@ -2,7 +2,7 @@ :deploy_syscall: link:https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy[deploy_syscall] -The following documentation provides reasoning and examples for functions and constants found in `openzeppelin::utils` +The following documentation provides reasoning and examples for functions and constants found in `openzeppelin_utils` and `openzeppelin::tests::utils`. CAUTION: Expect this module to evolve (as it has already done). @@ -14,7 +14,7 @@ CAUTION: Expect this module to evolve (as it has already done). === `++utils++` ```cairo -use openzeppelin::utils; +use openzeppelin_utils; ``` Module containing core utilities of the library. @@ -77,8 +77,8 @@ casting and unwrapping the result multiple times. Usage example: ```cairo -use openzeppelin::utils::selectors; -use openzeppelin::utils::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::UnwrapAndCast; fn call_and_cast_to_bool(target: ContractAddress, args: Span) -> bool { try_selector_with_fallback( @@ -102,31 +102,31 @@ Note that it can be automatically casted to any type implementing the `Serde` tr [[utils-cryptography]] ==== `[.contract-item-name]#++cryptography++#` [.item-kind]#module# -See xref:#cryptography[`openzeppelin::utils::cryptography`]. +See xref:#cryptography[`openzeppelin_utils::cryptography`]. [.contract-item] [[utils-deployments]] ==== `[.contract-item-name]#++deployments++#` [.item-kind]#module# -See xref:#deployments[`openzeppelin::utils::deployments`]. +See xref:#deployments[`openzeppelin_utils::deployments`]. [.contract-item] [[utils-math]] ==== `[.contract-item-name]#++math++#` [.item-kind]#module# -See xref:#math[`openzeppelin::utils::math`]. +See xref:#math[`openzeppelin_utils::math`]. [.contract-item] [[utils-selectors]] ==== `[.contract-item-name]#++selectors++#` [.item-kind]#module# -See xref:#selectors[`openzeppelin::utils::selectors`]. +See xref:#selectors[`openzeppelin_utils::selectors`]. [.contract-item] [[utils-serde]] ==== `[.contract-item-name]#++serde++#` [.item-kind]#module# -See xref:#serde[`openzeppelin::utils::serde`]. +See xref:#serde[`openzeppelin_utils::serde`]. [.contract] [[cryptography]] @@ -135,7 +135,7 @@ See xref:#serde[`openzeppelin::utils::serde`]. :snip12: https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md[SNIP12] ```cairo -use openzeppelin::utils::cryptography; +use openzeppelin_utils::cryptography; ``` Module containing utilities related to cryptography. @@ -155,13 +155,13 @@ Module containing utilities related to cryptography. [[cryptography-nonces]] ==== `[.contract-item-name]#++nonces++#` [.item-kind]#module# -See xref:#NoncesComponent[`openzeppelin::utils::cryptography::nonces::NoncesComponent`]. +See xref:#NoncesComponent[`openzeppelin_utils::cryptography::nonces::NoncesComponent`]. [.contract-item] [[cryptography-snip12]] ==== `[.contract-item-name]#++snip12++#` [.item-kind]#module# -See xref:#snip12[`openzeppelin::utils::cryptography::snip12`]. +See xref:#snip12[`openzeppelin_utils::cryptography::snip12`]. [.contract] [[deployments]] @@ -170,7 +170,7 @@ See xref:#snip12[`openzeppelin::utils::cryptography::snip12`]. :udc-doc: xref:/udc.adoc[Universal Deployer Contract] ```cairo -use openzeppelin::utils::deployments; +use openzeppelin_utils::deployments; ``` Module containing utility functions for calculating contract addresses through {deploy_syscall} and the {udc-doc} (UDC). @@ -230,7 +230,7 @@ Origin-dependent deployments hash `salt` with `caller_address` (member of {deplo === `++math++` ```cairo -use openzeppelin::utils::math; +use openzeppelin_utils::math; ``` Module containing math utilities. @@ -258,7 +258,7 @@ NOTE: `T` is a generic value matching different numeric implementations. === `++selectors++` ```cairo -use openzeppelin::utils::selectors; +use openzeppelin_utils::selectors; ``` :selectors: https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/utils/selectors.cairo[selectors.cairo] @@ -271,7 +271,7 @@ To see the full list of selectors, see {selectors}. === `++serde++` ```cairo -use openzeppelin::utils::serde; +use openzeppelin_utils::serde; ``` Module containing utilities related to serialization and deserialization of Cairo data structures. @@ -296,7 +296,7 @@ implementing the `Serde` trait to a `felt252` buffer. Usage example: ```cairo -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; fn to_calldata(recipient: ContractAddress, amount: u256) -> Array { @@ -317,7 +317,7 @@ that implements the `Serde` trait. === `++NoncesComponent++` ```cairo -use openzeppelin::utils::cryptography::nonces::NoncesComponent; +use openzeppelin_utils::cryptography::nonces::NoncesComponent; ``` Simple component for managing nonces. @@ -372,7 +372,7 @@ Same as `use_nonce` but checking that `nonce` is the next valid one for `owner`. === `++snip12++` ```cairo -use openzeppelin::utils::snip12; +use openzeppelin_utils::snip12; ``` Supports on-chain generation of message hashes compliant with {snip12}. @@ -419,7 +419,7 @@ The `contract_address_salt` is always set to zero, and `deploy_from_zero` is set Usage example: ```cairo -use openzeppelin::presets::AccountUpgradeable; +use openzeppelin_presets::AccountUpgradeable; use openzeppelin::tests::utils; use starknet::ContractAddress; @@ -460,8 +460,8 @@ Usage example: ```cairo use openzeppelin::tests::utils; -use openzeppelin::token::erc20::ERC20Component; -use openzeppelin::token::erc20::ERC20Component::Transfer; +use openzeppelin_token::erc20::ERC20Component; +use openzeppelin_token::erc20::ERC20Component::Transfer; use starknet::ContractAddress; fn assert_emitted_event( diff --git a/docs/modules/ROOT/pages/components.adoc b/docs/modules/ROOT/pages/components.adoc index 33dbbe539..eb3051414 100644 --- a/docs/modules/ROOT/pages/components.adoc +++ b/docs/modules/ROOT/pages/components.adoc @@ -25,7 +25,7 @@ The contract should first import the component and declare it with the `componen #[starknet::contract] mod MyContract { // Import the component - use openzeppelin::security::InitializableComponent; + use openzeppelin_security::InitializableComponent; // Declare the component component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -40,7 +40,7 @@ Note that even if the component doesn't define any events, the compiler will sti ---- #[starknet::contract] mod MyContract { - use openzeppelin::security::InitializableComponent; + use openzeppelin_security::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -79,7 +79,7 @@ Integrating an implementation looks like this: [,cairo] ---- mod MyContract { - use openzeppelin::security::InitializableComponent; + use openzeppelin_security::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -99,7 +99,7 @@ A function on the contract level can expose it like this: ---- #[starknet::contract] mod MyContract { - use openzeppelin::security::InitializableComponent; + use openzeppelin_security::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -202,8 +202,8 @@ Here's a full example of an account contract that embeds the `AccountMixinImpl`: ---- #[starknet::contract] mod Account { - use openzeppelin::account::AccountComponent; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; component!(path: AccountComponent, storage: account, event: AccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -254,7 +254,7 @@ Let's look at how a contract would integrate {ownable-component}: ---- #[starknet::contract] mod MyContract { - use openzeppelin::access::ownable::OwnableComponent; + use openzeppelinaccess::ownable::OwnableComponent; use starknet::ContractAddress; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); @@ -297,8 +297,8 @@ Creating a contract with `AccessControlComponent` should look like this: ---- #[starknet::contract] mod MyContract { - use openzeppelin::access::accesscontrol::AccessControlComponent; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelinaccess::accesscontrol::AccessControlComponent; + use openzeppelin_introspection::src5::SRC5Component; component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -358,10 +358,10 @@ Here's the setup: ---- #[starknet::contract] mod ERC20Pausable { - use openzeppelin::security::pausable::PausableComponent; - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_security::pausable::PausableComponent; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; // Import the ERC20 interfaces to create custom implementations - use openzeppelin::token::erc20::interface::{IERC20, IERC20CamelOnly}; + use openzeppelin_token::erc20::interface::{IERC20, IERC20CamelOnly}; use starknet::ContractAddress; component!(path: PausableComponent, storage: pausable, event: PausableEvent); @@ -462,7 +462,7 @@ To do so, use the same syntax as calling an implementation method except replace ---- #[starknet::contract] mod MyContract { - use openzeppelin::security::InitializableComponent; + use openzeppelin_security::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); diff --git a/docs/modules/ROOT/pages/erc1155.adoc b/docs/modules/ROOT/pages/erc1155.adoc index 78cdc322b..87f593660 100644 --- a/docs/modules/ROOT/pages/erc1155.adoc +++ b/docs/modules/ROOT/pages/erc1155.adoc @@ -34,8 +34,8 @@ Here's an example of a basic contract: ---- #[starknet::contract] mod MyERC1155 { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); @@ -227,8 +227,8 @@ Here's an example of a simple token receiver contract: ---- #[starknet::contract] mod MyTokenReceiver { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::ERC1155ReceiverComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::ERC1155ReceiverComponent; use starknet::ContractAddress; component!(path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent); diff --git a/docs/modules/ROOT/pages/erc20.adoc b/docs/modules/ROOT/pages/erc20.adoc index 67d100db9..b73124f12 100644 --- a/docs/modules/ROOT/pages/erc20.adoc +++ b/docs/modules/ROOT/pages/erc20.adoc @@ -23,7 +23,7 @@ Here's what that looks like: ---- #[starknet::contract] mod MyToken { - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); @@ -170,7 +170,7 @@ TIP: Note that we are not using the MixinImpl in this case, since we need to cus ---- #[starknet::contract] mod MyToken { - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); diff --git a/docs/modules/ROOT/pages/erc721.adoc b/docs/modules/ROOT/pages/erc721.adoc index 33c250ebf..b4166ae12 100644 --- a/docs/modules/ROOT/pages/erc721.adoc +++ b/docs/modules/ROOT/pages/erc721.adoc @@ -18,8 +18,8 @@ Here's an example of a basic contract: ---- #[starknet::contract] mod MyNFT { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC721Component, storage: erc721, event: ERC721Event); @@ -195,8 +195,8 @@ Here's an example of a simple token receiver contract: ---- #[starknet::contract] mod MyTokenReceiver { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::ERC721ReceiverComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721ReceiverComponent; use starknet::ContractAddress; component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); diff --git a/docs/modules/ROOT/pages/guides/erc20-supply.adoc b/docs/modules/ROOT/pages/guides/erc20-supply.adoc index a1c86340e..71543e19d 100644 --- a/docs/modules/ROOT/pages/guides/erc20-supply.adoc +++ b/docs/modules/ROOT/pages/guides/erc20-supply.adoc @@ -15,7 +15,7 @@ We can achieve this by setting the token supply in the constructor which will ex ---- #[starknet::contract] mod MyToken { - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); @@ -69,7 +69,7 @@ Let's make a few changes to the almighty `MyToken` contract and create a minting ---- #[starknet::contract] mod MyToken { - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); diff --git a/docs/modules/ROOT/pages/guides/snip12.adoc b/docs/modules/ROOT/pages/guides/snip12.adoc index fb919e065..18b8f5181 100644 --- a/docs/modules/ROOT/pages/guides/snip12.adoc +++ b/docs/modules/ROOT/pages/guides/snip12.adoc @@ -26,7 +26,7 @@ Note that some declarations are omitted for brevity. The full example will be av ---- #[starknet::contract] mod CustomERC20 { - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); @@ -117,12 +117,12 @@ NOTE: In practice it's better to compute the type hash off-chain and hardcode it === 3. Implement the `StructHash` trait for the struct. -You can import the trait from: `openzeppelin::utils::snip12::StructHash`. And this implementation +You can import the trait from: `openzeppelin_utils::snip12::StructHash`. And this implementation is nothing more than the encoding of the message as defined in the {snip}. [,cairo] ---- -use openzeppelin::utils::snip12::StructHash; +use openzeppelin_utils::snip12::StructHash; use core::hash::HashStateExTrait; use hash::{HashStateTrait, Hash}; @@ -155,7 +155,7 @@ because the `chain_id` is obtained on-chain, and the `revision` is hardcoded to [,cairo] ---- -use openzeppelin::utils::snip12::SNIP12Metadata; +use openzeppelin_utils::snip12::SNIP12Metadata; impl SNIP12MetadataImpl of SNIP12Metadata { fn name() -> felt252 { 'DAPP_NAME' } @@ -169,7 +169,7 @@ the trait is not bounded to the ContractState, like this: [,cairo] ---- -use openzeppelin::utils::snip12::SNIP12Metadata; +use openzeppelin_utils::snip12::SNIP12Metadata; impl SNIP12MetadataImpl of SNIP12Metadata { fn name() -> felt252 { @@ -190,7 +190,7 @@ using the `get_message_hash` function. The implementation is already available a [,cairo] ---- -use openzeppelin::utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl}; +use openzeppelin_utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl}; use core::hash::HashStateExTrait; use hash::{HashStateTrait, Hash}; @@ -251,7 +251,7 @@ and the {nonces}[`NoncesComponent`] to handle nonces to prevent replay attacks. [,cairo] ---- -use openzeppelin::utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl}; +use openzeppelin_utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl}; use core::hash::HashStateExTrait; use hash::{HashStateTrait, Hash}; @@ -278,9 +278,9 @@ impl StructHashImpl of StructHash { #[starknet::contract] mod CustomERC20 { - use openzeppelin::account::dual_account::{DualCaseAccount, DualCaseAccountABI}; - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use openzeppelin::utils::cryptography::nonces::NoncesComponent; + use openzeppelin_account::dual_account::{DualCaseAccount, DualCaseAccountABI}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_utils::cryptography::nonces::NoncesComponent; use starknet::ContractAddress; use super::{Message, OffchainMessageHashImpl, SNIP12Metadata}; diff --git a/docs/modules/ROOT/pages/guides/src5-migration.adoc b/docs/modules/ROOT/pages/guides/src5-migration.adoc index 5f97d5ee3..b12eb5239 100644 --- a/docs/modules/ROOT/pages/guides/src5-migration.adoc +++ b/docs/modules/ROOT/pages/guides/src5-migration.adoc @@ -36,8 +36,8 @@ Here's the setup: ---- #[starknet::contract] mod MigratingContract { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::security::initializable::InitializableComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_security::initializable::InitializableComponent; component!(path: SRC5Component, storage: src5, event: SRC5Event); component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -84,7 +84,7 @@ The contract should implement an `InternalImpl` and add a function to register t ---- #[starknet::contract] mod MigratingContract { - use openzeppelin::token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID}; + use openzeppelin_token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID}; (...) diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 77a1f138e..29f3e6437 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -71,7 +71,7 @@ Copy the code into `src/lib.cairo`. ---- #[starknet::contract] mod MyERC20Token { - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); diff --git a/docs/modules/ROOT/pages/interfaces.adoc b/docs/modules/ROOT/pages/interfaces.adoc index d6e6a7fc8..36462d458 100644 --- a/docs/modules/ROOT/pages/interfaces.adoc +++ b/docs/modules/ROOT/pages/interfaces.adoc @@ -7,13 +7,13 @@ This section describes the interfaces OpenZeppelin Contracts for Cairo offer, an Interfaces can be found in the module tree under the `interface` submodule, such as `token::erc20::interface`. For example: ```cairo -use openzeppelin::token::erc20::interface::IERC20; +use openzeppelin_token::erc20::interface::IERC20; ``` or ```cairo -use openzeppelin::token::erc20::dual20::DualCaseERC20; +use openzeppelin_token::erc20::dual20::DualCaseERC20; ``` NOTE: For simplicity, we'll use ERC20 as example but the same concepts apply to other modules. diff --git a/docs/modules/ROOT/pages/introspection.adoc b/docs/modules/ROOT/pages/introspection.adoc index d4c9a4170..18a4f0bff 100644 --- a/docs/modules/ROOT/pages/introspection.adoc +++ b/docs/modules/ROOT/pages/introspection.adoc @@ -26,7 +26,7 @@ Here is an example contract: ---- #[starknet::contract] mod MyContract { - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_introspection::src5::SRC5Component; component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -82,8 +82,8 @@ For a contract to declare its support for a given interface, we recommend using ---- #[starknet::contract] mod MyContract { - use openzeppelin::account::interface; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::interface; + use openzeppelin_introspection::src5::SRC5Component; component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -122,9 +122,9 @@ Use the `supports_interface` function to query a contract's support for a given ---- #[starknet::contract] mod MyContract { - use openzeppelin::account::interface; - use openzeppelin::introspection::interface::ISRC5DispatcherTrait; - use openzeppelin::introspection::interface::ISRC5Dispatcher; + use openzeppelin_account::interface; + use openzeppelin_introspection::interface::ISRC5DispatcherTrait; + use openzeppelin_introspection::interface::ISRC5Dispatcher; use starknet::ContractAddress; #[storage] diff --git a/docs/modules/ROOT/pages/presets.adoc b/docs/modules/ROOT/pages/presets.adoc index f0a3f8ce3..feb05c97b 100644 --- a/docs/modules/ROOT/pages/presets.adoc +++ b/docs/modules/ROOT/pages/presets.adoc @@ -76,10 +76,10 @@ Copy the target preset contract from the {presets_dir} and paste it in the new p #[starknet::contract] mod ERC20Upgradeable { - use openzeppelin::access::ownable::OwnableComponent; - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use openzeppelin::upgrades::UpgradeableComponent; - use openzeppelin::upgrades::interface::IUpgradeable; + use openzeppelin_access::ownable::OwnableComponent; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_upgrades::UpgradeableComponent; + use openzeppelin_upgrades::interface::IUpgradeable; use starknet::{ContractAddress, ClassHash}; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); diff --git a/docs/modules/ROOT/pages/security.adoc b/docs/modules/ROOT/pages/security.adoc index 9ccfe9c1a..b3d44c1ae 100644 --- a/docs/modules/ROOT/pages/security.adoc +++ b/docs/modules/ROOT/pages/security.adoc @@ -1,6 +1,6 @@ = Security -The following documentation provides context, reasoning, and examples of modules found under `openzeppelin::security`. +The following documentation provides context, reasoning, and examples of modules found under `openzeppelin_security`. CAUTION: Expect these modules to evolve. @@ -18,7 +18,7 @@ You can use the component in your contracts like this: ---- #[starknet::contract] mod MyInitializableContract { - use openzeppelin::security::InitializableComponent; + use openzeppelin_security::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -82,8 +82,8 @@ For example (using the xref:api/access.adoc#OwnableComponent[Ownable] component ---- #[starknet::contract] mod MyPausableContract { - use openzeppelin::access::ownable::OwnableComponent; - use openzeppelin::security::PausableComponent; + use openzeppelin_access::ownable::OwnableComponent; + use openzeppelin_security::PausableComponent; use starknet::ContractAddress; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); @@ -176,7 +176,7 @@ The protected function must call `start` before the first function statement, an ---- #[starknet::contract] mod MyReentrancyContract { - use openzeppelin::security::ReentrancyGuardComponent; + use openzeppelin_security::ReentrancyGuardComponent; component!( path: ReentrancyGuardComponent, storage: reentrancy_guard, event: ReentrancyGuardEvent diff --git a/docs/modules/ROOT/pages/udc.adoc b/docs/modules/ROOT/pages/udc.adoc index fd30ce729..823ee7c96 100644 --- a/docs/modules/ROOT/pages/udc.adoc +++ b/docs/modules/ROOT/pages/udc.adoc @@ -41,7 +41,7 @@ Here's an implementation example in Cairo: [,cairo] ---- -use openzeppelin::utils::interfaces::{IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait}; +use openzeppelin_utils::interfaces::{IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait}; const UDC_ADDRESS: felt252 = 0x04a64cd09a853868621d94cae9952b106f2c36a3f81260f85de6696c6b050221; diff --git a/docs/modules/ROOT/pages/upgrades.adoc b/docs/modules/ROOT/pages/upgrades.adoc index dff92c758..12d72b3c0 100644 --- a/docs/modules/ROOT/pages/upgrades.adoc +++ b/docs/modules/ROOT/pages/upgrades.adoc @@ -51,9 +51,9 @@ NOTE: We will be using the following module to implement the {i_upgradeable} int ---- #[starknet::contract] mod UpgradeableContract { - use openzeppelin::access::ownable::OwnableComponent; - use openzeppelin::upgrades::UpgradeableComponent; - use openzeppelin::upgrades::interface::IUpgradeable; + use openzeppelin_access::ownable::OwnableComponent; + use openzeppelin_upgrades::UpgradeableComponent; + use openzeppelin_upgrades::interface::IUpgradeable; use starknet::ClassHash; use starknet::ContractAddress; diff --git a/packages/access/README.md b/packages/access/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/access/Scarb.toml b/packages/access/Scarb.toml new file mode 100644 index 000000000..23e831497 --- /dev/null +++ b/packages/access/Scarb.toml @@ -0,0 +1,15 @@ + +[package] +name = "openzeppelin_access" +version = "0.1.0" +description = "" +homepage = "" +edition = "2023_11" + +[tool] +fmt.workspace = true + +[dependencies] +starknet = "2.6.4" +openzeppelin_introspection = { path = "../introspection" } +openzeppelin_utils = { path = "../utils" } diff --git a/src/access/accesscontrol.cairo b/packages/access/src/accesscontrol.cairo similarity index 100% rename from src/access/accesscontrol.cairo rename to packages/access/src/accesscontrol.cairo diff --git a/src/access/accesscontrol/accesscontrol.cairo b/packages/access/src/accesscontrol/accesscontrol.cairo similarity index 97% rename from src/access/accesscontrol/accesscontrol.cairo rename to packages/access/src/accesscontrol/accesscontrol.cairo index 3f320d988..33cedbb94 100644 --- a/src/access/accesscontrol/accesscontrol.cairo +++ b/packages/access/src/accesscontrol/accesscontrol.cairo @@ -7,10 +7,10 @@ /// Roles are referred to by their `felt252` identifier. #[starknet::component] pub mod AccessControlComponent { - use openzeppelin::access::accesscontrol::interface; - use openzeppelin::introspection::src5::SRC5Component::InternalImpl as SRC5InternalImpl; - use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_access::accesscontrol::interface; + use openzeppelin_introspection::src5::SRC5Component::InternalImpl as SRC5InternalImpl; + use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin_introspection::src5::SRC5Component; use starknet::ContractAddress; use starknet::get_caller_address; diff --git a/src/access/accesscontrol/dual_accesscontrol.cairo b/packages/access/src/accesscontrol/dual_accesscontrol.cairo similarity index 94% rename from src/access/accesscontrol/dual_accesscontrol.cairo rename to packages/access/src/accesscontrol/dual_accesscontrol.cairo index b9cca51f9..46d05e00d 100644 --- a/src/access/accesscontrol/dual_accesscontrol.cairo +++ b/packages/access/src/accesscontrol/dual_accesscontrol.cairo @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (access/accesscontrol/dual_accesscontrol.cairo) -use openzeppelin::utils::UnwrapAndCast; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::try_selector_with_fallback; +use openzeppelin_utils::unwrap_and_cast::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::syscalls::call_contract_syscall; diff --git a/src/access/accesscontrol/interface.cairo b/packages/access/src/accesscontrol/interface.cairo similarity index 100% rename from src/access/accesscontrol/interface.cairo rename to packages/access/src/accesscontrol/interface.cairo diff --git a/src/access.cairo b/packages/access/src/lib.cairo similarity index 100% rename from src/access.cairo rename to packages/access/src/lib.cairo diff --git a/src/access/ownable.cairo b/packages/access/src/ownable.cairo similarity index 100% rename from src/access/ownable.cairo rename to packages/access/src/ownable.cairo diff --git a/src/access/ownable/dual_ownable.cairo b/packages/access/src/ownable/dual_ownable.cairo similarity index 89% rename from src/access/ownable/dual_ownable.cairo rename to packages/access/src/ownable/dual_ownable.cairo index 7c3052c81..0022927b9 100644 --- a/src/access/ownable/dual_ownable.cairo +++ b/packages/access/src/ownable/dual_ownable.cairo @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (access/ownable/dual_ownable.cairo) -use openzeppelin::utils::UnwrapAndCast; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::try_selector_with_fallback; +use openzeppelin_utils::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::syscalls::call_contract_syscall; diff --git a/src/access/ownable/interface.cairo b/packages/access/src/ownable/interface.cairo similarity index 100% rename from src/access/ownable/interface.cairo rename to packages/access/src/ownable/interface.cairo diff --git a/src/access/ownable/ownable.cairo b/packages/access/src/ownable/ownable.cairo similarity index 99% rename from src/access/ownable/ownable.cairo rename to packages/access/src/ownable/ownable.cairo index c60b214e1..23f9da501 100644 --- a/src/access/ownable/ownable.cairo +++ b/packages/access/src/ownable/ownable.cairo @@ -16,8 +16,8 @@ #[starknet::component] pub mod OwnableComponent { use core::num::traits::Zero; - use openzeppelin::access::ownable::interface::IOwnableTwoStep; - use openzeppelin::access::ownable::interface; + use openzeppelin_access::ownable::interface::IOwnableTwoStep; + use openzeppelin_access::ownable::interface; use starknet::ContractAddress; use starknet::get_caller_address; diff --git a/packages/account/README.md b/packages/account/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/account/Scarb.toml b/packages/account/Scarb.toml new file mode 100644 index 000000000..04b44efbe --- /dev/null +++ b/packages/account/Scarb.toml @@ -0,0 +1,15 @@ + +[package] +name = "openzeppelin_account" +version = "0.1.0" +description = "" +homepage = "" +edition = "2023_11" + +[tool] +fmt.workspace = true + +[dependencies] +starknet = "2.6.4" +openzeppelin_introspection = { path = "../introspection" } +openzeppelin_utils = { path = "../utils" } diff --git a/src/account/account.cairo b/packages/account/src/account.cairo similarity index 96% rename from src/account/account.cairo rename to packages/account/src/account.cairo index c13192540..9cf7917d8 100644 --- a/src/account/account.cairo +++ b/packages/account/src/account.cairo @@ -9,12 +9,12 @@ pub mod AccountComponent { use core::hash::{HashStateExTrait, HashStateTrait}; use core::num::traits::Zero; use core::poseidon::PoseidonTrait; - use openzeppelin::account::interface; - use openzeppelin::account::utils::{MIN_TRANSACTION_VERSION, QUERY_VERSION, QUERY_OFFSET}; - use openzeppelin::account::utils::{execute_calls, is_valid_stark_signature}; - use openzeppelin::introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; - use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::interface; + use openzeppelin_account::utils::{MIN_TRANSACTION_VERSION, QUERY_VERSION, QUERY_OFFSET}; + use openzeppelin_account::utils::{execute_calls, is_valid_stark_signature}; + use openzeppelin_introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; + use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin_introspection::src5::SRC5Component; use starknet::account::Call; use starknet::get_caller_address; use starknet::get_contract_address; diff --git a/src/account/dual_account.cairo b/packages/account/src/dual_account.cairo similarity index 92% rename from src/account/dual_account.cairo rename to packages/account/src/dual_account.cairo index 3c0d33c14..6badadd21 100644 --- a/src/account/dual_account.cairo +++ b/packages/account/src/dual_account.cairo @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (account/dual_account.cairo) -use openzeppelin::utils::UnwrapAndCast; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::try_selector_with_fallback; +use openzeppelin_utils::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::syscalls::call_contract_syscall; diff --git a/src/account/dual_eth_account.cairo b/packages/account/src/dual_eth_account.cairo similarity index 88% rename from src/account/dual_eth_account.cairo rename to packages/account/src/dual_eth_account.cairo index eee086574..52eadfc30 100644 --- a/src/account/dual_eth_account.cairo +++ b/packages/account/src/dual_eth_account.cairo @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (account/dual_eth_account.cairo) -use openzeppelin::account::interface::EthPublicKey; -use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; -use openzeppelin::utils::UnwrapAndCast; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::try_selector_with_fallback; +use openzeppelin_account::interface::EthPublicKey; +use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; +use openzeppelin_utils::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::syscalls::call_contract_syscall; diff --git a/src/account/eth_account.cairo b/packages/account/src/eth_account.cairo similarity index 96% rename from src/account/eth_account.cairo rename to packages/account/src/eth_account.cairo index cb8082932..94131446a 100644 --- a/src/account/eth_account.cairo +++ b/packages/account/src/eth_account.cairo @@ -10,14 +10,14 @@ pub mod EthAccountComponent { use core::num::traits::Zero; use core::poseidon::{PoseidonTrait, poseidon_hash_span}; use core::starknet::secp256_trait::Secp256PointTrait; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::interface; - use openzeppelin::account::utils::secp256k1::{Secp256k1PointSerde, Secp256k1PointStorePacking}; - use openzeppelin::account::utils::{MIN_TRANSACTION_VERSION, QUERY_VERSION, QUERY_OFFSET}; - use openzeppelin::account::utils::{execute_calls, is_valid_eth_signature}; - use openzeppelin::introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; - use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_account::interface; + use openzeppelin_account::utils::secp256k1::{Secp256k1PointSerde, Secp256k1PointStorePacking}; + use openzeppelin_account::utils::{MIN_TRANSACTION_VERSION, QUERY_VERSION, QUERY_OFFSET}; + use openzeppelin_account::utils::{execute_calls, is_valid_eth_signature}; + use openzeppelin_introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; + use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin_introspection::src5::SRC5Component; use starknet::SyscallResultTrait; use starknet::account::Call; use starknet::get_caller_address; diff --git a/src/account/interface.cairo b/packages/account/src/interface.cairo similarity index 98% rename from src/account/interface.cairo rename to packages/account/src/interface.cairo index 957a0e5e9..75d51f093 100644 --- a/src/account/interface.cairo +++ b/packages/account/src/interface.cairo @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (account/interface.cairo) -use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; +use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; use starknet::ContractAddress; use starknet::account::Call; diff --git a/src/account.cairo b/packages/account/src/lib.cairo similarity index 100% rename from src/account.cairo rename to packages/account/src/lib.cairo diff --git a/src/account/utils.cairo b/packages/account/src/utils.cairo similarity index 100% rename from src/account/utils.cairo rename to packages/account/src/utils.cairo diff --git a/src/account/utils/secp256k1.cairo b/packages/account/src/utils/secp256k1.cairo similarity index 100% rename from src/account/utils/secp256k1.cairo rename to packages/account/src/utils/secp256k1.cairo diff --git a/src/account/utils/signature.cairo b/packages/account/src/utils/signature.cairo similarity index 96% rename from src/account/utils/signature.cairo rename to packages/account/src/utils/signature.cairo index 13caa8391..c11f5f9d4 100644 --- a/src/account/utils/signature.cairo +++ b/packages/account/src/utils/signature.cairo @@ -2,7 +2,7 @@ // OpenZeppelin Contracts for Cairo v0.14.0 (account/utils/signature.cairo) use core::ecdsa::check_ecdsa_signature; -use openzeppelin::account::interface::EthPublicKey; +use openzeppelin_account::interface::EthPublicKey; use starknet::secp256_trait; #[derive(Copy, Drop, Serde)] diff --git a/packages/governance/README.md b/packages/governance/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/governance/Scarb.toml b/packages/governance/Scarb.toml new file mode 100644 index 000000000..d1d505f38 --- /dev/null +++ b/packages/governance/Scarb.toml @@ -0,0 +1,15 @@ + +[package] +name = "openzeppelin_governance" +version = "0.1.0" +description = "" +homepage = "" +edition = "2023_11" + +[tool] +fmt.workspace = true + +[dependencies] +starknet = "2.6.4" +openzeppelin_introspection = { path = "../introspection" } +openzeppelin_utils = { path = "../utils" } diff --git a/src/governance.cairo b/packages/governance/src/lib.cairo similarity index 100% rename from src/governance.cairo rename to packages/governance/src/lib.cairo diff --git a/src/governance/utils.cairo b/packages/governance/src/utils.cairo similarity index 100% rename from src/governance/utils.cairo rename to packages/governance/src/utils.cairo diff --git a/src/governance/utils/interfaces.cairo b/packages/governance/src/utils/interfaces.cairo similarity index 100% rename from src/governance/utils/interfaces.cairo rename to packages/governance/src/utils/interfaces.cairo diff --git a/src/governance/utils/interfaces/votes.cairo b/packages/governance/src/utils/interfaces/votes.cairo similarity index 100% rename from src/governance/utils/interfaces/votes.cairo rename to packages/governance/src/utils/interfaces/votes.cairo diff --git a/packages/introspection/README.md b/packages/introspection/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/introspection/Scarb.toml b/packages/introspection/Scarb.toml new file mode 100644 index 000000000..29ba1d7d4 --- /dev/null +++ b/packages/introspection/Scarb.toml @@ -0,0 +1,13 @@ + +[package] +name = "openzeppelin_introspection" +version = "0.1.0" +description = "" +homepage = "" +edition = "2023_11" + +[tool] +fmt.workspace = true + +[dependencies] +starknet = "2.6.4" diff --git a/src/introspection/interface.cairo b/packages/introspection/src/interface.cairo similarity index 100% rename from src/introspection/interface.cairo rename to packages/introspection/src/interface.cairo diff --git a/src/introspection.cairo b/packages/introspection/src/lib.cairo similarity index 57% rename from src/introspection.cairo rename to packages/introspection/src/lib.cairo index 584b93016..191587449 100644 --- a/src/introspection.cairo +++ b/packages/introspection/src/lib.cairo @@ -1,2 +1,2 @@ pub mod interface; -pub mod src5; +pub mod src5; \ No newline at end of file diff --git a/src/introspection/src5.cairo b/packages/introspection/src/src5.cairo similarity index 97% rename from src/introspection/src5.cairo rename to packages/introspection/src/src5.cairo index 4ac0d4b7e..70ae56386 100644 --- a/src/introspection/src5.cairo +++ b/packages/introspection/src/src5.cairo @@ -6,7 +6,7 @@ /// The SRC5 component allows contracts to expose the interfaces they implement. #[starknet::component] pub mod SRC5Component { - use openzeppelin::introspection::interface; + use openzeppelin_introspection::interface; #[storage] struct Storage { diff --git a/packages/presets/README.md b/packages/presets/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/presets/Scarb.toml b/packages/presets/Scarb.toml new file mode 100644 index 000000000..dd703aa1a --- /dev/null +++ b/packages/presets/Scarb.toml @@ -0,0 +1,18 @@ + +[package] +name = "openzeppelin_presets" +version = "0.1.0" +description = "" +homepage = "" +edition = "2023_11" + +[tool] +fmt.workspace = true + +[dependencies] +starknet = "2.6.4" +openzeppelin_access = { path = "../access" } +openzeppelin_account = { path = "../account" } +openzeppelin_introspection = { path = "../introspection" } +openzeppelin_token = { path = "../token" } +openzeppelin_upgrades = { path = "../upgrades" } diff --git a/src/presets/account.cairo b/packages/presets/src/account.cairo similarity index 89% rename from src/presets/account.cairo rename to packages/presets/src/account.cairo index e9805bf3e..c0b6da1c7 100644 --- a/src/presets/account.cairo +++ b/packages/presets/src/account.cairo @@ -6,10 +6,10 @@ /// OpenZeppelin's upgradeable account which can change its public key and declare, deploy, or call contracts. #[starknet::contract(account)] pub(crate) mod AccountUpgradeable { - use openzeppelin::account::AccountComponent; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::upgrades::UpgradeableComponent; - use openzeppelin::upgrades::interface::IUpgradeable; + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_upgrades::UpgradeableComponent; + use openzeppelin_upgrades::interface::IUpgradeable; use starknet::ClassHash; component!(path: AccountComponent, storage: account, event: AccountEvent); diff --git a/src/presets/erc1155.cairo b/packages/presets/src/erc1155.cairo similarity index 91% rename from src/presets/erc1155.cairo rename to packages/presets/src/erc1155.cairo index 2552e7323..bd2c0354e 100644 --- a/src/presets/erc1155.cairo +++ b/packages/presets/src/erc1155.cairo @@ -10,11 +10,11 @@ /// https://wizard.openzeppelin.com/cairo #[starknet::contract] pub(crate) mod ERC1155Upgradeable { - use openzeppelin::access::ownable::OwnableComponent; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; - use openzeppelin::upgrades::UpgradeableComponent; - use openzeppelin::upgrades::interface::IUpgradeable; + use openzeppelin_access::ownable::OwnableComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use openzeppelin_upgrades::UpgradeableComponent; + use openzeppelin_upgrades::interface::IUpgradeable; use starknet::{ContractAddress, ClassHash}; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); diff --git a/src/presets/erc20.cairo b/packages/presets/src/erc20.cairo similarity index 91% rename from src/presets/erc20.cairo rename to packages/presets/src/erc20.cairo index a12f43d2b..d061ffb5e 100644 --- a/src/presets/erc20.cairo +++ b/packages/presets/src/erc20.cairo @@ -11,10 +11,10 @@ /// https://wizard.openzeppelin.com/cairo #[starknet::contract] pub(crate) mod ERC20Upgradeable { - use openzeppelin::access::ownable::OwnableComponent; - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use openzeppelin::upgrades::UpgradeableComponent; - use openzeppelin::upgrades::interface::IUpgradeable; + use openzeppelin_access::ownable::OwnableComponent; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_upgrades::UpgradeableComponent; + use openzeppelin_upgrades::interface::IUpgradeable; use starknet::{ContractAddress, ClassHash}; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); diff --git a/src/presets/erc721.cairo b/packages/presets/src/erc721.cairo similarity index 91% rename from src/presets/erc721.cairo rename to packages/presets/src/erc721.cairo index 91a469a6f..6e57f7d04 100644 --- a/src/presets/erc721.cairo +++ b/packages/presets/src/erc721.cairo @@ -10,11 +10,11 @@ /// https://wizard.openzeppelin.com/cairo #[starknet::contract] pub(crate) mod ERC721Upgradeable { - use openzeppelin::access::ownable::OwnableComponent; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; - use openzeppelin::upgrades::UpgradeableComponent; - use openzeppelin::upgrades::interface::IUpgradeable; + use openzeppelin_access::ownable::OwnableComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use openzeppelin_upgrades::UpgradeableComponent; + use openzeppelin_upgrades::interface::IUpgradeable; use starknet::{ContractAddress, ClassHash}; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); diff --git a/src/presets/eth_account.cairo b/packages/presets/src/eth_account.cairo similarity index 84% rename from src/presets/eth_account.cairo rename to packages/presets/src/eth_account.cairo index f641904be..42a9e7675 100644 --- a/src/presets/eth_account.cairo +++ b/packages/presets/src/eth_account.cairo @@ -7,12 +7,12 @@ /// deploy, or call contracts, using Ethereum signing keys. #[starknet::contract(account)] pub(crate) mod EthAccountUpgradeable { - use openzeppelin::account::EthAccountComponent; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::upgrades::UpgradeableComponent; - use openzeppelin::upgrades::interface::IUpgradeable; + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_upgrades::UpgradeableComponent; + use openzeppelin_upgrades::interface::IUpgradeable; use starknet::ClassHash; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); diff --git a/src/presets/interfaces.cairo b/packages/presets/src/interfaces.cairo similarity index 100% rename from src/presets/interfaces.cairo rename to packages/presets/src/interfaces.cairo diff --git a/src/presets/interfaces/account.cairo b/packages/presets/src/interfaces/account.cairo similarity index 100% rename from src/presets/interfaces/account.cairo rename to packages/presets/src/interfaces/account.cairo diff --git a/src/presets/interfaces/erc1155.cairo b/packages/presets/src/interfaces/erc1155.cairo similarity index 100% rename from src/presets/interfaces/erc1155.cairo rename to packages/presets/src/interfaces/erc1155.cairo diff --git a/src/presets/interfaces/erc20.cairo b/packages/presets/src/interfaces/erc20.cairo similarity index 100% rename from src/presets/interfaces/erc20.cairo rename to packages/presets/src/interfaces/erc20.cairo diff --git a/src/presets/interfaces/erc721.cairo b/packages/presets/src/interfaces/erc721.cairo similarity index 100% rename from src/presets/interfaces/erc721.cairo rename to packages/presets/src/interfaces/erc721.cairo diff --git a/src/presets/interfaces/eth_account.cairo b/packages/presets/src/interfaces/eth_account.cairo similarity index 91% rename from src/presets/interfaces/eth_account.cairo rename to packages/presets/src/interfaces/eth_account.cairo index 9ee9ad22c..29578af24 100644 --- a/src/presets/interfaces/eth_account.cairo +++ b/packages/presets/src/interfaces/eth_account.cairo @@ -1,5 +1,5 @@ -use openzeppelin::account::interface::EthPublicKey; -use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; +use openzeppelin_account::interface::EthPublicKey; +use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; use starknet::account::Call; use starknet::{ContractAddress, ClassHash}; diff --git a/src/presets.cairo b/packages/presets/src/lib.cairo similarity index 100% rename from src/presets.cairo rename to packages/presets/src/lib.cairo diff --git a/src/presets/universal_deployer.cairo b/packages/presets/src/universal_deployer.cairo similarity index 97% rename from src/presets/universal_deployer.cairo rename to packages/presets/src/universal_deployer.cairo index d4a928ca9..adac6e12a 100644 --- a/src/presets/universal_deployer.cairo +++ b/packages/presets/src/universal_deployer.cairo @@ -8,7 +8,7 @@ pub(crate) mod UniversalDeployer { use core::hash::{HashStateTrait, HashStateExTrait}; use core::poseidon::PoseidonTrait; - use openzeppelin::utils::interfaces::IUniversalDeployer; + use openzeppelin_utils::interfaces::IUniversalDeployer; use starknet::ClassHash; use starknet::ContractAddress; use starknet::SyscallResultTrait; diff --git a/packages/security/README.md b/packages/security/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/security/Scarb.toml b/packages/security/Scarb.toml new file mode 100644 index 000000000..c61dcab09 --- /dev/null +++ b/packages/security/Scarb.toml @@ -0,0 +1,13 @@ + +[package] +name = "openzeppelin_security" +version = "0.1.0" +description = "" +homepage = "" +edition = "2023_11" + +[tool] +fmt.workspace = true + +[dependencies] +starknet = "2.6.4" diff --git a/src/security/initializable.cairo b/packages/security/src/initializable.cairo similarity index 96% rename from src/security/initializable.cairo rename to packages/security/src/initializable.cairo index b265bbc8a..df0f04bae 100644 --- a/src/security/initializable.cairo +++ b/packages/security/src/initializable.cairo @@ -8,7 +8,7 @@ /// initial state in scenarios where a constructor cannot be used. #[starknet::component] pub mod InitializableComponent { - use openzeppelin::security::interface::IInitializable; + use openzeppelin_security::interface::IInitializable; #[storage] struct Storage { diff --git a/src/security/interface.cairo b/packages/security/src/interface.cairo similarity index 100% rename from src/security/interface.cairo rename to packages/security/src/interface.cairo diff --git a/src/security.cairo b/packages/security/src/lib.cairo similarity index 100% rename from src/security.cairo rename to packages/security/src/lib.cairo diff --git a/src/security/pausable.cairo b/packages/security/src/pausable.cairo similarity index 98% rename from src/security/pausable.cairo rename to packages/security/src/pausable.cairo index d10a201a5..25ba7f70a 100644 --- a/src/security/pausable.cairo +++ b/packages/security/src/pausable.cairo @@ -8,7 +8,7 @@ /// or `assert_not_paused` will be affected by this mechanism. #[starknet::component] pub mod PausableComponent { - use openzeppelin::security::interface::IPausable; + use openzeppelin_security::interface::IPausable; use starknet::ContractAddress; use starknet::get_caller_address; diff --git a/src/security/reentrancyguard.cairo b/packages/security/src/reentrancyguard.cairo similarity index 100% rename from src/security/reentrancyguard.cairo rename to packages/security/src/reentrancyguard.cairo diff --git a/packages/token/README.md b/packages/token/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/token/Scarb.toml b/packages/token/Scarb.toml new file mode 100644 index 000000000..3c0bd4f64 --- /dev/null +++ b/packages/token/Scarb.toml @@ -0,0 +1,16 @@ + +[package] +name = "openzeppelin_token" +version = "0.1.0" +description = "" +homepage = "" +edition = "2023_11" + +[tool] +fmt.workspace = true + +[dependencies] +starknet = "2.6.4" +openzeppelin_account = { path = "../account" } +openzeppelin_introspection = { path = "../introspection" } +openzeppelin_governance = { path = "../governance" } diff --git a/src/token/erc1155.cairo b/packages/token/src/erc1155.cairo similarity index 100% rename from src/token/erc1155.cairo rename to packages/token/src/erc1155.cairo diff --git a/src/token/erc1155/dual1155.cairo b/packages/token/src/erc1155/dual1155.cairo similarity index 96% rename from src/token/erc1155/dual1155.cairo rename to packages/token/src/erc1155/dual1155.cairo index b0aac8f8b..333f62b70 100644 --- a/src/token/erc1155/dual1155.cairo +++ b/packages/token/src/erc1155/dual1155.cairo @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (token/erc1155/dual1155.cairo) -use openzeppelin::utils::UnwrapAndCast; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::try_selector_with_fallback; +use openzeppelin_utils::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::syscalls::call_contract_syscall; diff --git a/src/token/erc1155/dual1155_receiver.cairo b/packages/token/src/erc1155/dual1155_receiver.cairo similarity index 92% rename from src/token/erc1155/dual1155_receiver.cairo rename to packages/token/src/erc1155/dual1155_receiver.cairo index 24d35834f..f1319ef9e 100644 --- a/src/token/erc1155/dual1155_receiver.cairo +++ b/packages/token/src/erc1155/dual1155_receiver.cairo @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (token/erc1155/dual1155_receiver.cairo) -use openzeppelin::utils::UnwrapAndCast; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::try_selector_with_fallback; +use openzeppelin_utils::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; #[derive(Copy, Drop)] diff --git a/src/token/erc1155/erc1155.cairo b/packages/token/src/erc1155/erc1155.cairo similarity index 97% rename from src/token/erc1155/erc1155.cairo rename to packages/token/src/erc1155/erc1155.cairo index 493207c40..dd6a60890 100644 --- a/src/token/erc1155/erc1155.cairo +++ b/packages/token/src/erc1155/erc1155.cairo @@ -10,15 +10,14 @@ use starknet::ContractAddress; #[starknet::component] pub mod ERC1155Component { use core::num::traits::Zero; - use openzeppelin::account; - use openzeppelin::introspection::interface::{ISRC5Dispatcher, ISRC5DispatcherTrait}; - use openzeppelin::introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; - use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::dual1155_receiver::{ + use openzeppelin_introspection::interface::{ISRC5Dispatcher, ISRC5DispatcherTrait}; + use openzeppelin_introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; + use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::dual1155_receiver::{ DualCaseERC1155Receiver, DualCaseERC1155ReceiverTrait }; - use openzeppelin::token::erc1155::interface; + use openzeppelin_token::erc1155::interface; use starknet::ContractAddress; use starknet::get_caller_address; @@ -680,7 +679,7 @@ pub mod ERC1155Component { get_caller_address(), from, token_id, value, data ) == interface::IERC1155_RECEIVER_ID } else { - src5_dispatcher.supports_interface(account::interface::ISRC6_ID) + src5_dispatcher.supports_interface(openzeppelin_account::interface::ISRC6_ID) } } @@ -701,7 +700,7 @@ pub mod ERC1155Component { get_caller_address(), from, token_ids, values, data ) == interface::IERC1155_RECEIVER_ID } else { - src5_dispatcher.supports_interface(account::interface::ISRC6_ID) + src5_dispatcher.supports_interface(openzeppelin_account::interface::ISRC6_ID) } } } diff --git a/src/token/erc1155/erc1155_receiver.cairo b/packages/token/src/erc1155/erc1155_receiver.cairo similarity index 94% rename from src/token/erc1155/erc1155_receiver.cairo rename to packages/token/src/erc1155/erc1155_receiver.cairo index 48e7e7361..c7bc98cea 100644 --- a/src/token/erc1155/erc1155_receiver.cairo +++ b/packages/token/src/erc1155/erc1155_receiver.cairo @@ -8,11 +8,11 @@ /// safe transfers. #[starknet::component] pub mod ERC1155ReceiverComponent { - use openzeppelin::introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; - use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::interface::IERC1155_RECEIVER_ID; - use openzeppelin::token::erc1155::interface::{ + use openzeppelin_introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; + use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::interface::IERC1155_RECEIVER_ID; + use openzeppelin_token::erc1155::interface::{ IERC1155Receiver, IERC1155ReceiverCamel, ERC1155ReceiverABI }; use starknet::ContractAddress; diff --git a/src/token/erc1155/interface.cairo b/packages/token/src/erc1155/interface.cairo similarity index 100% rename from src/token/erc1155/interface.cairo rename to packages/token/src/erc1155/interface.cairo diff --git a/src/token/erc20.cairo b/packages/token/src/erc20.cairo similarity index 100% rename from src/token/erc20.cairo rename to packages/token/src/erc20.cairo diff --git a/src/token/erc20/dual20.cairo b/packages/token/src/erc20/dual20.cairo similarity index 95% rename from src/token/erc20/dual20.cairo rename to packages/token/src/erc20/dual20.cairo index 6c0f50628..2fcac722e 100644 --- a/src/token/erc20/dual20.cairo +++ b/packages/token/src/erc20/dual20.cairo @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (token/erc20/dual20.cairo) -use openzeppelin::utils::UnwrapAndCast; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::try_selector_with_fallback; +use openzeppelin_utils::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::syscalls::call_contract_syscall; diff --git a/src/token/erc20/erc20.cairo b/packages/token/src/erc20/erc20.cairo similarity index 99% rename from src/token/erc20/erc20.cairo rename to packages/token/src/erc20/erc20.cairo index 4cd568375..fa6d79988 100644 --- a/src/token/erc20/erc20.cairo +++ b/packages/token/src/erc20/erc20.cairo @@ -15,7 +15,7 @@ use starknet::ContractAddress; pub mod ERC20Component { use core::integer::BoundedInt; use core::num::traits::Zero; - use openzeppelin::token::erc20::interface; + use openzeppelin_token::erc20::interface; use starknet::ContractAddress; use starknet::get_caller_address; diff --git a/src/token/erc20/extensions.cairo b/packages/token/src/erc20/extensions.cairo similarity index 100% rename from src/token/erc20/extensions.cairo rename to packages/token/src/erc20/extensions.cairo diff --git a/src/token/erc20/extensions/erc20_votes.cairo b/packages/token/src/erc20/extensions/erc20_votes.cairo similarity index 95% rename from src/token/erc20/extensions/erc20_votes.cairo rename to packages/token/src/erc20/extensions/erc20_votes.cairo index 069fd626c..f48d5022e 100644 --- a/src/token/erc20/extensions/erc20_votes.cairo +++ b/packages/token/src/erc20/extensions/erc20_votes.cairo @@ -3,7 +3,7 @@ use core::hash::{Hash, HashStateTrait, HashStateExTrait}; use core::poseidon::PoseidonTrait; -use openzeppelin::utils::cryptography::snip12::{OffchainMessageHash, StructHash, SNIP12Metadata}; +use openzeppelin_utils::cryptography::snip12::{OffchainMessageHash, StructHash, SNIP12Metadata}; use starknet::ContractAddress; /// # ERC20Votes Component @@ -16,13 +16,13 @@ use starknet::ContractAddress; #[starknet::component] pub mod ERC20VotesComponent { use core::num::traits::Zero; - use openzeppelin::account::dual_account::{DualCaseAccount, DualCaseAccountABI}; - use openzeppelin::governance::utils::interfaces::IVotes; - use openzeppelin::token::erc20::ERC20Component; - use openzeppelin::token::erc20::interface::IERC20; - use openzeppelin::utils::nonces::NoncesComponent::InternalTrait as NoncesInternalTrait; - use openzeppelin::utils::nonces::NoncesComponent; - use openzeppelin::utils::structs::checkpoint::{Checkpoint, Trace, TraceTrait}; + use openzeppelin_account::dual_account::{DualCaseAccount, DualCaseAccountABI}; + use openzeppelin_governance::utils::interfaces::IVotes; + use openzeppelin_token::erc20::ERC20Component; + use openzeppelin_token::erc20::interface::IERC20; + use openzeppelin_utils::nonces::NoncesComponent::InternalTrait as NoncesInternalTrait; + use openzeppelin_utils::nonces::NoncesComponent; + use openzeppelin_utils::structs::checkpoint::{Checkpoint, Trace, TraceTrait}; use starknet::ContractAddress; use super::{Delegation, OffchainMessageHash, SNIP12Metadata}; diff --git a/src/token/erc20/interface.cairo b/packages/token/src/erc20/interface.cairo similarity index 98% rename from src/token/erc20/interface.cairo rename to packages/token/src/erc20/interface.cairo index 44c61694f..82b865160 100644 --- a/src/token/erc20/interface.cairo +++ b/packages/token/src/erc20/interface.cairo @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (token/erc20/interface.cairo) -use openzeppelin::utils::structs::checkpoint::Checkpoint; +use openzeppelin_utils::structs::checkpoint::Checkpoint; use starknet::ContractAddress; #[starknet::interface] diff --git a/src/token/erc721.cairo b/packages/token/src/erc721.cairo similarity index 100% rename from src/token/erc721.cairo rename to packages/token/src/erc721.cairo diff --git a/src/token/erc721/dual721.cairo b/packages/token/src/erc721/dual721.cairo similarity index 96% rename from src/token/erc721/dual721.cairo rename to packages/token/src/erc721/dual721.cairo index 4c710f588..b1d052d98 100644 --- a/src/token/erc721/dual721.cairo +++ b/packages/token/src/erc721/dual721.cairo @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (token/erc721/dual721.cairo) -use openzeppelin::utils::UnwrapAndCast; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::try_selector_with_fallback; +use openzeppelin_utils::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::syscalls::call_contract_syscall; diff --git a/src/token/erc721/dual721_receiver.cairo b/packages/token/src/erc721/dual721_receiver.cairo similarity index 86% rename from src/token/erc721/dual721_receiver.cairo rename to packages/token/src/erc721/dual721_receiver.cairo index a41f9699b..92d2882fb 100644 --- a/src/token/erc721/dual721_receiver.cairo +++ b/packages/token/src/erc721/dual721_receiver.cairo @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (token/erc721/dual721_receiver.cairo) -use openzeppelin::utils::UnwrapAndCast; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::try_selector_with_fallback; +use openzeppelin_utils::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; #[derive(Copy, Drop)] diff --git a/src/token/erc721/erc721.cairo b/packages/token/src/erc721/erc721.cairo similarity index 98% rename from src/token/erc721/erc721.cairo rename to packages/token/src/erc721/erc721.cairo index 6f838205a..c5a6651f3 100644 --- a/src/token/erc721/erc721.cairo +++ b/packages/token/src/erc721/erc721.cairo @@ -10,15 +10,14 @@ use starknet::ContractAddress; #[starknet::component] pub mod ERC721Component { use core::num::traits::Zero; - use openzeppelin::account; - use openzeppelin::introspection::interface::{ISRC5Dispatcher, ISRC5DispatcherTrait}; - use openzeppelin::introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; - use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::dual721_receiver::{ + use openzeppelin_introspection::interface::{ISRC5Dispatcher, ISRC5DispatcherTrait}; + use openzeppelin_introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; + use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::dual721_receiver::{ DualCaseERC721Receiver, DualCaseERC721ReceiverTrait }; - use openzeppelin::token::erc721::interface; + use openzeppelin_token::erc721::interface; use starknet::ContractAddress; use starknet::get_caller_address; @@ -804,7 +803,7 @@ pub mod ERC721Component { get_caller_address(), from, token_id, data ) == interface::IERC721_RECEIVER_ID } else { - src5_dispatcher.supports_interface(account::interface::ISRC6_ID) + src5_dispatcher.supports_interface(openzeppelin_account::interface::ISRC6_ID) } } } diff --git a/src/token/erc721/erc721_receiver.cairo b/packages/token/src/erc721/erc721_receiver.cairo similarity index 89% rename from src/token/erc721/erc721_receiver.cairo rename to packages/token/src/erc721/erc721_receiver.cairo index bbc8db4ff..b32673512 100644 --- a/src/token/erc721/erc721_receiver.cairo +++ b/packages/token/src/erc721/erc721_receiver.cairo @@ -8,12 +8,12 @@ /// safe transfers. #[starknet::component] pub mod ERC721ReceiverComponent { - use openzeppelin::introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; - use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::interface::IERC721_RECEIVER_ID; - use openzeppelin::token::erc721::interface::{IERC721Receiver, IERC721ReceiverCamel}; - use openzeppelin::token::erc721::interface; + use openzeppelin_introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; + use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::interface::IERC721_RECEIVER_ID; + use openzeppelin_token::erc721::interface::{IERC721Receiver, IERC721ReceiverCamel}; + use openzeppelin_token::erc721::interface; use starknet::ContractAddress; #[storage] diff --git a/src/token/erc721/interface.cairo b/packages/token/src/erc721/interface.cairo similarity index 100% rename from src/token/erc721/interface.cairo rename to packages/token/src/erc721/interface.cairo diff --git a/src/token.cairo b/packages/token/src/lib.cairo similarity index 100% rename from src/token.cairo rename to packages/token/src/lib.cairo diff --git a/packages/upgrades/README.md b/packages/upgrades/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/upgrades/Scarb.toml b/packages/upgrades/Scarb.toml new file mode 100644 index 000000000..754d0f126 --- /dev/null +++ b/packages/upgrades/Scarb.toml @@ -0,0 +1,13 @@ + +[package] +name = "openzeppelin_upgrades" +version = "0.1.0" +description = "" +homepage = "" +edition = "2023_11" + +[tool] +fmt.workspace = true + +[dependencies] +starknet = "2.6.4" diff --git a/src/upgrades/interface.cairo b/packages/upgrades/src/interface.cairo similarity index 100% rename from src/upgrades/interface.cairo rename to packages/upgrades/src/interface.cairo diff --git a/src/upgrades.cairo b/packages/upgrades/src/lib.cairo similarity index 100% rename from src/upgrades.cairo rename to packages/upgrades/src/lib.cairo diff --git a/src/upgrades/upgradeable.cairo b/packages/upgrades/src/upgradeable.cairo similarity index 100% rename from src/upgrades/upgradeable.cairo rename to packages/upgrades/src/upgradeable.cairo diff --git a/packages/utils/README.md b/packages/utils/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/utils/Scarb.toml b/packages/utils/Scarb.toml new file mode 100644 index 000000000..adb37135d --- /dev/null +++ b/packages/utils/Scarb.toml @@ -0,0 +1,13 @@ + +[package] +name = "openzeppelin_utils" +version = "0.1.0" +description = "" +homepage = "" +edition = "2023_11" + +[tool] +fmt.workspace = true + +[dependencies] +starknet = "2.6.4" diff --git a/src/utils/cryptography.cairo b/packages/utils/src/cryptography.cairo similarity index 100% rename from src/utils/cryptography.cairo rename to packages/utils/src/cryptography.cairo diff --git a/src/utils/cryptography/interface.cairo b/packages/utils/src/cryptography/interface.cairo similarity index 100% rename from src/utils/cryptography/interface.cairo rename to packages/utils/src/cryptography/interface.cairo diff --git a/src/utils/cryptography/nonces.cairo b/packages/utils/src/cryptography/nonces.cairo similarity index 97% rename from src/utils/cryptography/nonces.cairo rename to packages/utils/src/cryptography/nonces.cairo index 6358cefe6..b93d6092d 100644 --- a/src/utils/cryptography/nonces.cairo +++ b/packages/utils/src/cryptography/nonces.cairo @@ -3,7 +3,7 @@ #[starknet::component] pub mod NoncesComponent { - use openzeppelin::utils::interfaces::INonces; + use openzeppelin_utils::interfaces::INonces; use starknet::ContractAddress; #[storage] diff --git a/src/utils/cryptography/snip12.cairo b/packages/utils/src/cryptography/snip12.cairo similarity index 100% rename from src/utils/cryptography/snip12.cairo rename to packages/utils/src/cryptography/snip12.cairo diff --git a/src/utils/deployments.cairo b/packages/utils/src/deployments.cairo similarity index 98% rename from src/utils/deployments.cairo rename to packages/utils/src/deployments.cairo index 16a1f0519..80973449b 100644 --- a/src/utils/deployments.cairo +++ b/packages/utils/src/deployments.cairo @@ -5,7 +5,7 @@ use core::num::traits::Zero; use core::pedersen::PedersenTrait; use core::poseidon::PoseidonTrait; use interface::IUniversalDeployer; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ClassHash; use starknet::ContractAddress; diff --git a/src/utils/deployments/interface.cairo b/packages/utils/src/deployments/interface.cairo similarity index 100% rename from src/utils/deployments/interface.cairo rename to packages/utils/src/deployments/interface.cairo diff --git a/src/utils/interfaces.cairo b/packages/utils/src/interfaces.cairo similarity index 57% rename from src/utils/interfaces.cairo rename to packages/utils/src/interfaces.cairo index 4609526a0..90cfbc9ff 100644 --- a/src/utils/interfaces.cairo +++ b/packages/utils/src/interfaces.cairo @@ -1,6 +1,6 @@ -pub use openzeppelin::utils::cryptography::interface::{ +pub use openzeppelin_utils::cryptography::interface::{ INonces, INoncesDispatcher, INoncesDispatcherTrait }; -pub use openzeppelin::utils::deployments::interface::{ +pub use openzeppelin_utils::deployments::interface::{ IUniversalDeployer, IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait }; diff --git a/src/utils.cairo b/packages/utils/src/lib.cairo similarity index 100% rename from src/utils.cairo rename to packages/utils/src/lib.cairo diff --git a/src/utils/math.cairo b/packages/utils/src/math.cairo similarity index 100% rename from src/utils/math.cairo rename to packages/utils/src/math.cairo diff --git a/src/utils/selectors.cairo b/packages/utils/src/selectors.cairo similarity index 100% rename from src/utils/selectors.cairo rename to packages/utils/src/selectors.cairo diff --git a/src/utils/serde.cairo b/packages/utils/src/serde.cairo similarity index 100% rename from src/utils/serde.cairo rename to packages/utils/src/serde.cairo diff --git a/src/utils/structs.cairo b/packages/utils/src/structs.cairo similarity index 100% rename from src/utils/structs.cairo rename to packages/utils/src/structs.cairo diff --git a/src/utils/structs/checkpoint.cairo b/packages/utils/src/structs/checkpoint.cairo similarity index 99% rename from src/utils/structs/checkpoint.cairo rename to packages/utils/src/structs/checkpoint.cairo index 0a55edf9a..94f52b867 100644 --- a/src/utils/structs/checkpoint.cairo +++ b/packages/utils/src/structs/checkpoint.cairo @@ -2,7 +2,7 @@ // OpenZeppelin Contracts for Cairo v0.14.0 (utils/structs/checkpoint.cairo) use core::integer::u32_sqrt; -use openzeppelin::utils::math; +use openzeppelin_utils::math; use starknet::storage_access::StorePacking; use super::storage_array::{StorageArray, StorageArrayTrait}; diff --git a/src/utils/structs/storage_array.cairo b/packages/utils/src/structs/storage_array.cairo similarity index 100% rename from src/utils/structs/storage_array.cairo rename to packages/utils/src/structs/storage_array.cairo diff --git a/src/utils/unwrap_and_cast.cairo b/packages/utils/src/unwrap_and_cast.cairo similarity index 100% rename from src/utils/unwrap_and_cast.cairo rename to packages/utils/src/unwrap_and_cast.cairo diff --git a/src/lib.cairo b/src/lib.cairo index 78bf8b567..182a000c4 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -1,4 +1,4 @@ -pub mod access; +// pub mod access; pub mod account; pub mod governance; pub mod introspection; diff --git a/src/tests/access/common.cairo b/src/tests/access/common.cairo index 752b08584..32697f1d4 100644 --- a/src/tests/access/common.cairo +++ b/src/tests/access/common.cairo @@ -1,7 +1,7 @@ -use openzeppelin::access::ownable::OwnableComponent::OwnershipTransferred; -use openzeppelin::access::ownable::OwnableComponent; +use openzeppelin_access::ownable::OwnableComponent::OwnershipTransferred; +use openzeppelin_access::ownable::OwnableComponent; use openzeppelin::tests::utils; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; pub(crate) fn assert_only_event_ownership_transferred( diff --git a/src/tests/access/test_accesscontrol.cairo b/src/tests/access/test_accesscontrol.cairo index 35a76c136..287fa30e7 100644 --- a/src/tests/access/test_accesscontrol.cairo +++ b/src/tests/access/test_accesscontrol.cairo @@ -1,12 +1,12 @@ -use openzeppelin::access::accesscontrol::AccessControlComponent::InternalImpl; -use openzeppelin::access::accesscontrol::AccessControlComponent::RoleAdminChanged; -use openzeppelin::access::accesscontrol::AccessControlComponent::RoleGranted; -use openzeppelin::access::accesscontrol::AccessControlComponent::RoleRevoked; -use openzeppelin::access::accesscontrol::AccessControlComponent; -use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; -use openzeppelin::access::accesscontrol::interface::IACCESSCONTROL_ID; -use openzeppelin::access::accesscontrol::interface::{IAccessControl, IAccessControlCamel}; -use openzeppelin::introspection::interface::ISRC5; +use openzeppelin_access::accesscontrol::AccessControlComponent::InternalImpl; +use openzeppelin_access::accesscontrol::AccessControlComponent::RoleAdminChanged; +use openzeppelin_access::accesscontrol::AccessControlComponent::RoleGranted; +use openzeppelin_access::accesscontrol::AccessControlComponent::RoleRevoked; +use openzeppelin_access::accesscontrol::AccessControlComponent; +use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; +use openzeppelin_access::accesscontrol::interface::IACCESSCONTROL_ID; +use openzeppelin_access::accesscontrol::interface::{IAccessControl, IAccessControlCamel}; +use openzeppelin_introspection::interface::ISRC5; use openzeppelin::tests::mocks::accesscontrol_mocks::DualCaseAccessControlMock; use openzeppelin::tests::utils::constants::{ ADMIN, AUTHORIZED, OTHER, OTHER_ADMIN, ROLE, OTHER_ROLE, ZERO diff --git a/src/tests/access/test_dual_accesscontrol.cairo b/src/tests/access/test_dual_accesscontrol.cairo index e172384a7..ad6ce6536 100644 --- a/src/tests/access/test_dual_accesscontrol.cairo +++ b/src/tests/access/test_dual_accesscontrol.cairo @@ -1,11 +1,11 @@ -use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; -use openzeppelin::access::accesscontrol::dual_accesscontrol::DualCaseAccessControl; -use openzeppelin::access::accesscontrol::dual_accesscontrol::DualCaseAccessControlTrait; -use openzeppelin::access::accesscontrol::interface::IACCESSCONTROL_ID; -use openzeppelin::access::accesscontrol::interface::IAccessControlCamelDispatcher; -use openzeppelin::access::accesscontrol::interface::IAccessControlCamelDispatcherTrait; -use openzeppelin::access::accesscontrol::interface::IAccessControlDispatcher; -use openzeppelin::access::accesscontrol::interface::IAccessControlDispatcherTrait; +use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; +use openzeppelin_access::accesscontrol::dual_accesscontrol::DualCaseAccessControl; +use openzeppelin_access::accesscontrol::dual_accesscontrol::DualCaseAccessControlTrait; +use openzeppelin_access::accesscontrol::interface::IACCESSCONTROL_ID; +use openzeppelin_access::accesscontrol::interface::IAccessControlCamelDispatcher; +use openzeppelin_access::accesscontrol::interface::IAccessControlCamelDispatcherTrait; +use openzeppelin_access::accesscontrol::interface::IAccessControlDispatcher; +use openzeppelin_access::accesscontrol::interface::IAccessControlDispatcherTrait; use openzeppelin::tests::mocks::accesscontrol_mocks::{ CamelAccessControlMock, SnakeAccessControlMock, CamelAccessControlPanicMock, SnakeAccessControlPanicMock @@ -13,7 +13,7 @@ use openzeppelin::tests::mocks::accesscontrol_mocks::{ use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::utils::constants::{ADMIN, AUTHORIZED, ROLE}; use openzeppelin::tests::utils; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::testing::set_contract_address; diff --git a/src/tests/access/test_dual_ownable.cairo b/src/tests/access/test_dual_ownable.cairo index c29d09fef..d2a6788ee 100644 --- a/src/tests/access/test_dual_ownable.cairo +++ b/src/tests/access/test_dual_ownable.cairo @@ -1,16 +1,16 @@ use core::num::traits::Zero; -use openzeppelin::access::ownable::dual_ownable::DualCaseOwnable; -use openzeppelin::access::ownable::dual_ownable::DualCaseOwnableTrait; -use openzeppelin::access::ownable::interface::IOwnableCamelOnlyDispatcher; -use openzeppelin::access::ownable::interface::IOwnableDispatcher; -use openzeppelin::access::ownable::interface::IOwnableDispatcherTrait; +use openzeppelin_access::ownable::dual_ownable::DualCaseOwnable; +use openzeppelin_access::ownable::dual_ownable::DualCaseOwnableTrait; +use openzeppelin_access::ownable::interface::IOwnableCamelOnlyDispatcher; +use openzeppelin_access::ownable::interface::IOwnableDispatcher; +use openzeppelin_access::ownable::interface::IOwnableDispatcherTrait; use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::mocks::ownable_mocks::{ CamelOwnableMock, CamelOwnablePanicMock, SnakeOwnableMock, SnakeOwnablePanicMock }; use openzeppelin::tests::utils::constants::{OWNER, NEW_OWNER}; use openzeppelin::tests::utils; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_utils::serde::SerializedAppend; use starknet::testing::set_contract_address; // diff --git a/src/tests/access/test_ownable.cairo b/src/tests/access/test_ownable.cairo index ea4b97c74..a07a99494 100644 --- a/src/tests/access/test_ownable.cairo +++ b/src/tests/access/test_ownable.cairo @@ -1,7 +1,7 @@ use core::num::traits::Zero; -use openzeppelin::access::ownable::OwnableComponent::InternalTrait; -use openzeppelin::access::ownable::OwnableComponent; -use openzeppelin::access::ownable::interface::{IOwnable, IOwnableCamelOnly}; +use openzeppelin_access::ownable::OwnableComponent::InternalTrait; +use openzeppelin_access::ownable::OwnableComponent; +use openzeppelin_access::ownable::interface::{IOwnable, IOwnableCamelOnly}; use openzeppelin::tests::mocks::ownable_mocks::DualCaseOwnableMock; use openzeppelin::tests::utils::constants::{ZERO, OTHER, OWNER}; use openzeppelin::tests::utils; diff --git a/src/tests/access/test_ownable_twostep.cairo b/src/tests/access/test_ownable_twostep.cairo index 0b300ddc4..dfa96db0d 100644 --- a/src/tests/access/test_ownable_twostep.cairo +++ b/src/tests/access/test_ownable_twostep.cairo @@ -1,12 +1,12 @@ use core::num::traits::Zero; -use openzeppelin::access::ownable::OwnableComponent::InternalTrait; -use openzeppelin::access::ownable::OwnableComponent::OwnershipTransferStarted; -use openzeppelin::access::ownable::OwnableComponent; -use openzeppelin::access::ownable::interface::{IOwnableTwoStep, IOwnableTwoStepCamelOnly}; +use openzeppelin_access::ownable::OwnableComponent::InternalTrait; +use openzeppelin_access::ownable::OwnableComponent::OwnershipTransferStarted; +use openzeppelin_access::ownable::OwnableComponent; +use openzeppelin_access::ownable::interface::{IOwnableTwoStep, IOwnableTwoStepCamelOnly}; use openzeppelin::tests::mocks::ownable_mocks::DualCaseTwoStepOwnableMock; use openzeppelin::tests::utils::constants::{ZERO, OWNER, OTHER, NEW_OWNER}; use openzeppelin::tests::utils; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; use starknet::storage::StorageMemberAccessTrait; use starknet::testing; diff --git a/src/tests/account/ethereum/common.cairo b/src/tests/account/ethereum/common.cairo index faf88a25c..b307f378e 100644 --- a/src/tests/account/ethereum/common.cairo +++ b/src/tests/account/ethereum/common.cairo @@ -1,14 +1,14 @@ use core::poseidon::poseidon_hash_span; use core::starknet::secp256_trait::Secp256PointTrait; -use openzeppelin::account::EthAccountComponent::{OwnerAdded, OwnerRemoved}; -use openzeppelin::account::EthAccountComponent; -use openzeppelin::account::interface::EthPublicKey; -use openzeppelin::account::utils::signature::EthSignature; +use openzeppelin_account::EthAccountComponent::{OwnerAdded, OwnerRemoved}; +use openzeppelin_account::EthAccountComponent; +use openzeppelin_account::interface::EthPublicKey; +use openzeppelin_account::utils::signature::EthSignature; use openzeppelin::tests::mocks::erc20_mocks::DualCaseERC20Mock; use openzeppelin::tests::utils::constants::{NAME, SYMBOL}; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::secp256_trait::Secp256Trait; diff --git a/src/tests/account/ethereum/test_dual_eth_account.cairo b/src/tests/account/ethereum/test_dual_eth_account.cairo index b627724d5..d2c748535 100644 --- a/src/tests/account/ethereum/test_dual_eth_account.cairo +++ b/src/tests/account/ethereum/test_dual_eth_account.cairo @@ -1,17 +1,17 @@ -use openzeppelin::account::dual_eth_account::{DualCaseEthAccountABI, DualCaseEthAccount}; -use openzeppelin::account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; -use openzeppelin::account::utils::secp256k1::{ +use openzeppelin_account::dual_eth_account::{DualCaseEthAccountABI, DualCaseEthAccount}; +use openzeppelin_account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; +use openzeppelin_account::utils::secp256k1::{ DebugSecp256k1Point, Secp256k1PointPartialEq, Secp256k1PointSerde }; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin::introspection::interface::ISRC5_ID; +use openzeppelin_account::utils::signature::EthSignature; +use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin::tests::mocks::eth_account_mocks::{ CamelEthAccountPanicMock, CamelEthAccountMock, SnakeEthAccountMock, SnakeEthAccountPanicMock }; use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::utils::constants::ETH_PUBKEY; use openzeppelin::tests::utils; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_utils::serde::SerializedAppend; use starknet::testing; use super::common::{NEW_ETH_PUBKEY, SIGNED_TX_DATA}; diff --git a/src/tests/account/ethereum/test_eth_account.cairo b/src/tests/account/ethereum/test_eth_account.cairo index 8c1a8e8d6..ab76b7389 100644 --- a/src/tests/account/ethereum/test_eth_account.cairo +++ b/src/tests/account/ethereum/test_eth_account.cairo @@ -1,22 +1,22 @@ -use openzeppelin::account::EthAccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; -use openzeppelin::account::EthAccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; -use openzeppelin::account::EthAccountComponent; -use openzeppelin::account::interface::EthPublicKey; -use openzeppelin::account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; -use openzeppelin::account::interface::{ISRC6, ISRC6_ID}; -use openzeppelin::account::utils::secp256k1::{ +use openzeppelin_account::EthAccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; +use openzeppelin_account::EthAccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; +use openzeppelin_account::EthAccountComponent; +use openzeppelin_account::interface::EthPublicKey; +use openzeppelin_account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; +use openzeppelin_account::interface::{ISRC6, ISRC6_ID}; +use openzeppelin_account::utils::secp256k1::{ DebugSecp256k1Point, Secp256k1PointPartialEq, Secp256k1PointSerde }; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin::introspection::interface::{ISRC5, ISRC5_ID}; +use openzeppelin_account::utils::signature::EthSignature; +use openzeppelin_introspection::interface::{ISRC5, ISRC5_ID}; use openzeppelin::tests::mocks::eth_account_mocks::DualCaseEthAccountMock; use openzeppelin::tests::utils::constants::{ ETH_PUBKEY, SALT, ZERO, OTHER, RECIPIENT, CALLER, QUERY_VERSION, MIN_TRANSACTION_VERSION }; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; use starknet::account::Call; use starknet::testing; use starknet::{contract_address_const, ContractAddress}; diff --git a/src/tests/account/starknet/common.cairo b/src/tests/account/starknet/common.cairo index 91905d856..755d59ab8 100644 --- a/src/tests/account/starknet/common.cairo +++ b/src/tests/account/starknet/common.cairo @@ -1,10 +1,10 @@ -use openzeppelin::account::AccountComponent::{OwnerAdded, OwnerRemoved}; -use openzeppelin::account::AccountComponent; +use openzeppelin_account::AccountComponent::{OwnerAdded, OwnerRemoved}; +use openzeppelin_account::AccountComponent; use openzeppelin::tests::mocks::erc20_mocks::DualCaseERC20Mock; use openzeppelin::tests::utils::constants::{NAME, SYMBOL, NEW_PUBKEY}; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; #[derive(Drop)] diff --git a/src/tests/account/starknet/test_account.cairo b/src/tests/account/starknet/test_account.cairo index ed4dc81ed..0a54556e8 100644 --- a/src/tests/account/starknet/test_account.cairo +++ b/src/tests/account/starknet/test_account.cairo @@ -1,18 +1,18 @@ use core::num::traits::Zero; -use openzeppelin::account::AccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; -use openzeppelin::account::AccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; -use openzeppelin::account::AccountComponent; -use openzeppelin::account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; -use openzeppelin::account::interface::{ISRC6, ISRC6_ID}; -use openzeppelin::introspection::interface::{ISRC5, ISRC5_ID}; +use openzeppelin_account::AccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; +use openzeppelin_account::AccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; +use openzeppelin_account::AccountComponent; +use openzeppelin_account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; +use openzeppelin_account::interface::{ISRC6, ISRC6_ID}; +use openzeppelin_introspection::interface::{ISRC5, ISRC5_ID}; use openzeppelin::tests::mocks::account_mocks::DualCaseAccountMock; use openzeppelin::tests::utils::constants::{ PUBKEY, NEW_PUBKEY, SALT, ZERO, QUERY_OFFSET, QUERY_VERSION, MIN_TRANSACTION_VERSION }; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; use starknet::account::Call; use starknet::contract_address_const; diff --git a/src/tests/account/starknet/test_dual_account.cairo b/src/tests/account/starknet/test_dual_account.cairo index 003075b1f..bd2d80dc4 100644 --- a/src/tests/account/starknet/test_dual_account.cairo +++ b/src/tests/account/starknet/test_dual_account.cairo @@ -1,6 +1,6 @@ -use openzeppelin::account::dual_account::{DualCaseAccountABI, DualCaseAccount}; -use openzeppelin::account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; -use openzeppelin::introspection::interface::ISRC5_ID; +use openzeppelin_account::dual_account::{DualCaseAccountABI, DualCaseAccount}; +use openzeppelin_account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; +use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin::tests::account::starknet::common::SIGNED_TX_DATA; use openzeppelin::tests::mocks::account_mocks::{ CamelAccountPanicMock, CamelAccountMock, SnakeAccountMock, SnakeAccountPanicMock diff --git a/src/tests/account/test_secp256k1.cairo b/src/tests/account/test_secp256k1.cairo index 5466eee55..af0f414c8 100644 --- a/src/tests/account/test_secp256k1.cairo +++ b/src/tests/account/test_secp256k1.cairo @@ -1,4 +1,4 @@ -use openzeppelin::account::utils::secp256k1::{ +use openzeppelin_account::utils::secp256k1::{ DebugSecp256k1Point, Secp256k1PointSerde, Secp256k1PointPartialEq, Secp256k1PointStorePacking as StorePacking }; diff --git a/src/tests/account/test_signature.cairo b/src/tests/account/test_signature.cairo index ffdb2ce74..05b921f4f 100644 --- a/src/tests/account/test_signature.cairo +++ b/src/tests/account/test_signature.cairo @@ -1,4 +1,4 @@ -use openzeppelin::account::utils::signature::{is_valid_stark_signature, is_valid_eth_signature}; +use openzeppelin_account::utils::signature::{is_valid_stark_signature, is_valid_eth_signature}; use starknet::secp256_trait::Secp256Trait; use starknet::secp256k1::Secp256k1Point; diff --git a/src/tests/cryptography/test_nonces.cairo b/src/tests/cryptography/test_nonces.cairo index 8d46c5fcb..8c5d8fb7a 100644 --- a/src/tests/cryptography/test_nonces.cairo +++ b/src/tests/cryptography/test_nonces.cairo @@ -1,9 +1,9 @@ use core::num::traits::Zero; use openzeppelin::tests::mocks::nonces_mocks::NoncesMock; use openzeppelin::tests::utils::constants::OWNER; -use openzeppelin::utils::cryptography::interface::INonces; -use openzeppelin::utils::cryptography::nonces::NoncesComponent::InternalTrait; -use openzeppelin::utils::cryptography::nonces::NoncesComponent; +use openzeppelin_utils::cryptography::interface::INonces; +use openzeppelin_utils::cryptography::nonces::NoncesComponent::InternalTrait; +use openzeppelin_utils::cryptography::nonces::NoncesComponent; type ComponentState = NoncesComponent::ComponentState; diff --git a/src/tests/cryptography/test_snip12.cairo b/src/tests/cryptography/test_snip12.cairo index e0caeffc1..cedce5fb4 100644 --- a/src/tests/cryptography/test_snip12.cairo +++ b/src/tests/cryptography/test_snip12.cairo @@ -1,7 +1,7 @@ use core::hash::{Hash, HashStateTrait, HashStateExTrait}; use core::poseidon::{PoseidonTrait, poseidon_hash_span}; use openzeppelin::tests::utils::constants::{OWNER, RECIPIENT}; -use openzeppelin::utils::cryptography::snip12::{ +use openzeppelin_utils::cryptography::snip12::{ STARKNET_DOMAIN_TYPE_HASH, StarknetDomain, StructHash, OffchainMessageHashImpl, SNIP12Metadata }; use starknet::ContractAddress; diff --git a/src/tests/introspection/test_src5.cairo b/src/tests/introspection/test_src5.cairo index 7280845de..a46498ae8 100644 --- a/src/tests/introspection/test_src5.cairo +++ b/src/tests/introspection/test_src5.cairo @@ -1,6 +1,6 @@ -use openzeppelin::introspection::interface::{ISRC5_ID, ISRC5}; -use openzeppelin::introspection::src5::SRC5Component::InternalTrait; -use openzeppelin::introspection::src5::SRC5Component; +use openzeppelin_introspection::interface::{ISRC5_ID, ISRC5}; +use openzeppelin_introspection::src5::SRC5Component::InternalTrait; +use openzeppelin_introspection::src5::SRC5Component; use openzeppelin::tests::mocks::src5_mocks::SRC5Mock; const OTHER_ID: felt252 = 0x12345678; diff --git a/src/tests/mocks/accesscontrol_mocks.cairo b/src/tests/mocks/accesscontrol_mocks.cairo index d06e2c3b5..f9ddb0b38 100644 --- a/src/tests/mocks/accesscontrol_mocks.cairo +++ b/src/tests/mocks/accesscontrol_mocks.cairo @@ -1,8 +1,8 @@ #[starknet::contract] pub(crate) mod DualCaseAccessControlMock { - use openzeppelin::access::accesscontrol::AccessControlComponent; - use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; + use openzeppelin_introspection::src5::SRC5Component; use starknet::ContractAddress; component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); @@ -40,9 +40,9 @@ pub(crate) mod DualCaseAccessControlMock { #[starknet::contract] pub(crate) mod SnakeAccessControlMock { - use openzeppelin::access::accesscontrol::AccessControlComponent; - use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; + use openzeppelin_introspection::src5::SRC5Component; use starknet::ContractAddress; component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); @@ -84,9 +84,9 @@ pub(crate) mod SnakeAccessControlMock { #[starknet::contract] pub(crate) mod CamelAccessControlMock { - use openzeppelin::access::accesscontrol::AccessControlComponent; - use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; + use openzeppelin_introspection::src5::SRC5Component; use starknet::ContractAddress; component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); diff --git a/src/tests/mocks/account_mocks.cairo b/src/tests/mocks/account_mocks.cairo index 9f82fb883..c2f7d9f57 100644 --- a/src/tests/mocks/account_mocks.cairo +++ b/src/tests/mocks/account_mocks.cairo @@ -1,7 +1,7 @@ #[starknet::contract(account)] pub(crate) mod DualCaseAccountMock { - use openzeppelin::account::AccountComponent; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; component!(path: AccountComponent, storage: account, event: AccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -46,8 +46,8 @@ pub(crate) mod DualCaseAccountMock { #[starknet::contract(account)] pub(crate) mod SnakeAccountMock { - use openzeppelin::account::AccountComponent; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; component!(path: AccountComponent, storage: account, event: AccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -88,8 +88,8 @@ pub(crate) mod SnakeAccountMock { #[starknet::contract(account)] pub(crate) mod CamelAccountMock { - use openzeppelin::account::AccountComponent; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; use starknet::account::Call; component!(path: AccountComponent, storage: account, event: AccountEvent); diff --git a/src/tests/mocks/erc1155_mocks.cairo b/src/tests/mocks/erc1155_mocks.cairo index 4ea256485..9d8d79181 100644 --- a/src/tests/mocks/erc1155_mocks.cairo +++ b/src/tests/mocks/erc1155_mocks.cairo @@ -1,7 +1,7 @@ #[starknet::contract] pub(crate) mod DualCaseERC1155Mock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); @@ -53,8 +53,8 @@ pub(crate) mod DualCaseERC1155Mock { #[starknet::contract] pub(crate) mod SnakeERC1155Mock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); @@ -104,8 +104,8 @@ pub(crate) mod SnakeERC1155Mock { #[starknet::contract] pub(crate) mod CamelERC1155Mock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); diff --git a/src/tests/mocks/erc1155_receiver_mocks.cairo b/src/tests/mocks/erc1155_receiver_mocks.cairo index 8df4a3963..adbf6bdab 100644 --- a/src/tests/mocks/erc1155_receiver_mocks.cairo +++ b/src/tests/mocks/erc1155_receiver_mocks.cairo @@ -2,8 +2,8 @@ use openzeppelin::tests::utils::constants::SUCCESS; #[starknet::contract] pub(crate) mod DualCaseERC1155ReceiverMock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::ERC1155ReceiverComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::ERC1155ReceiverComponent; use starknet::ContractAddress; component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -42,8 +42,8 @@ pub(crate) mod DualCaseERC1155ReceiverMock { #[starknet::contract] pub(crate) mod SnakeERC1155ReceiverMock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::ERC1155ReceiverComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::ERC1155ReceiverComponent; use starknet::ContractAddress; component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -86,8 +86,8 @@ pub(crate) mod SnakeERC1155ReceiverMock { #[starknet::contract] pub(crate) mod CamelERC1155ReceiverMock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc1155::ERC1155ReceiverComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::ERC1155ReceiverComponent; use starknet::ContractAddress; component!(path: SRC5Component, storage: src5, event: SRC5Event); diff --git a/src/tests/mocks/erc20_mocks.cairo b/src/tests/mocks/erc20_mocks.cairo index 283cd7fdf..80a66d34f 100644 --- a/src/tests/mocks/erc20_mocks.cairo +++ b/src/tests/mocks/erc20_mocks.cairo @@ -1,6 +1,6 @@ #[starknet::contract] pub(crate) mod DualCaseERC20Mock { - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); @@ -41,7 +41,7 @@ pub(crate) mod DualCaseERC20Mock { #[starknet::contract] pub(crate) mod SnakeERC20Mock { - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); @@ -80,7 +80,7 @@ pub(crate) mod SnakeERC20Mock { #[starknet::contract] pub(crate) mod CamelERC20Mock { - use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); diff --git a/src/tests/mocks/erc20_votes_mocks.cairo b/src/tests/mocks/erc20_votes_mocks.cairo index fcc44b16a..a2a79ca18 100644 --- a/src/tests/mocks/erc20_votes_mocks.cairo +++ b/src/tests/mocks/erc20_votes_mocks.cairo @@ -1,10 +1,10 @@ #[starknet::contract] pub(crate) mod DualCaseERC20VotesMock { - use openzeppelin::token::erc20::ERC20Component; - use openzeppelin::token::erc20::extensions::ERC20VotesComponent::InternalTrait as ERC20VotesInternalTrait; - use openzeppelin::token::erc20::extensions::ERC20VotesComponent; - use openzeppelin::utils::cryptography::nonces::NoncesComponent; - use openzeppelin::utils::cryptography::snip12::SNIP12Metadata; + use openzeppelin_token::erc20::ERC20Component; + use openzeppelin_token::erc20::extensions::ERC20VotesComponent::InternalTrait as ERC20VotesInternalTrait; + use openzeppelin_token::erc20::extensions::ERC20VotesComponent; + use openzeppelin_utils::cryptography::nonces::NoncesComponent; + use openzeppelin_utils::cryptography::snip12::SNIP12Metadata; use starknet::ContractAddress; component!(path: ERC20VotesComponent, storage: erc20_votes, event: ERC20VotesEvent); diff --git a/src/tests/mocks/erc721_mocks.cairo b/src/tests/mocks/erc721_mocks.cairo index 770fd8312..05aaf81f2 100644 --- a/src/tests/mocks/erc721_mocks.cairo +++ b/src/tests/mocks/erc721_mocks.cairo @@ -1,7 +1,7 @@ #[starknet::contract] pub(crate) mod DualCaseERC721Mock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC721Component, storage: erc721, event: ERC721Event); @@ -56,8 +56,8 @@ pub(crate) mod DualCaseERC721Mock { #[starknet::contract] pub(crate) mod SnakeERC721Mock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC721Component, storage: erc721, event: ERC721Event); @@ -107,9 +107,9 @@ pub(crate) mod SnakeERC721Mock { #[starknet::contract] pub(crate) mod CamelERC721Mock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::ERC721Component::{ERC721Impl, ERC721MetadataImpl}; - use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721Component::{ERC721Impl, ERC721MetadataImpl}; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC721Component, storage: erc721, event: ERC721Event); diff --git a/src/tests/mocks/erc721_receiver_mocks.cairo b/src/tests/mocks/erc721_receiver_mocks.cairo index f496d0a9c..5c193d67f 100644 --- a/src/tests/mocks/erc721_receiver_mocks.cairo +++ b/src/tests/mocks/erc721_receiver_mocks.cairo @@ -2,8 +2,8 @@ use openzeppelin::tests::utils::constants::SUCCESS; #[starknet::contract] pub(crate) mod DualCaseERC721ReceiverMock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::ERC721ReceiverComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721ReceiverComponent; use starknet::ContractAddress; component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); @@ -72,8 +72,8 @@ pub(crate) mod DualCaseERC721ReceiverMock { #[starknet::contract] pub(crate) mod SnakeERC721ReceiverMock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::ERC721ReceiverComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721ReceiverComponent; use starknet::ContractAddress; component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); @@ -131,8 +131,8 @@ pub(crate) mod SnakeERC721ReceiverMock { #[starknet::contract] pub(crate) mod CamelERC721ReceiverMock { - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::token::erc721::ERC721ReceiverComponent; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721ReceiverComponent; use starknet::ContractAddress; component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); diff --git a/src/tests/mocks/eth_account_mocks.cairo b/src/tests/mocks/eth_account_mocks.cairo index 687e5d68f..792b0cecf 100644 --- a/src/tests/mocks/eth_account_mocks.cairo +++ b/src/tests/mocks/eth_account_mocks.cairo @@ -1,9 +1,9 @@ #[starknet::contract(account)] pub(crate) mod DualCaseEthAccountMock { - use openzeppelin::account::EthAccountComponent; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; + use openzeppelin_introspection::src5::SRC5Component; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -45,10 +45,10 @@ pub(crate) mod DualCaseEthAccountMock { #[starknet::contract(account)] pub(crate) mod SnakeEthAccountMock { - use openzeppelin::account::EthAccountComponent; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; + use openzeppelin_introspection::src5::SRC5Component; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -86,10 +86,10 @@ pub(crate) mod SnakeEthAccountMock { #[starknet::contract(account)] pub(crate) mod CamelEthAccountMock { - use openzeppelin::account::EthAccountComponent; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; + use openzeppelin_introspection::src5::SRC5Component; use starknet::account::Call; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); @@ -150,8 +150,8 @@ pub(crate) mod CamelEthAccountMock { #[starknet::contract] pub(crate) mod SnakeEthAccountPanicMock { - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; use starknet::SyscallResultTrait; use starknet::secp256_trait::Secp256Trait; @@ -192,8 +192,8 @@ pub(crate) mod SnakeEthAccountPanicMock { #[starknet::contract] pub(crate) mod CamelEthAccountPanicMock { - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; use starknet::SyscallResultTrait; use starknet::secp256_trait::Secp256Trait; diff --git a/src/tests/mocks/initializable_mocks.cairo b/src/tests/mocks/initializable_mocks.cairo index 442d1e2b2..92841237d 100644 --- a/src/tests/mocks/initializable_mocks.cairo +++ b/src/tests/mocks/initializable_mocks.cairo @@ -1,6 +1,6 @@ #[starknet::contract] pub(crate) mod InitializableMock { - use openzeppelin::security::initializable::InitializableComponent; + use openzeppelin_security::initializable::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); diff --git a/src/tests/mocks/nonces_mocks.cairo b/src/tests/mocks/nonces_mocks.cairo index 51472eb51..4c68d5f06 100644 --- a/src/tests/mocks/nonces_mocks.cairo +++ b/src/tests/mocks/nonces_mocks.cairo @@ -1,6 +1,6 @@ #[starknet::contract] pub(crate) mod NoncesMock { - use openzeppelin::utils::cryptography::nonces::NoncesComponent; + use openzeppelin_utils::cryptography::nonces::NoncesComponent; component!(path: NoncesComponent, storage: nonces, event: NoncesEvent); diff --git a/src/tests/mocks/ownable_mocks.cairo b/src/tests/mocks/ownable_mocks.cairo index 45d48951f..1448f0cb0 100644 --- a/src/tests/mocks/ownable_mocks.cairo +++ b/src/tests/mocks/ownable_mocks.cairo @@ -1,6 +1,6 @@ #[starknet::contract] pub(crate) mod DualCaseOwnableMock { - use openzeppelin::access::ownable::OwnableComponent; + use openzeppelin_access::ownable::OwnableComponent; use starknet::ContractAddress; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); @@ -30,7 +30,7 @@ pub(crate) mod DualCaseOwnableMock { #[starknet::contract] pub(crate) mod SnakeOwnableMock { - use openzeppelin::access::ownable::OwnableComponent; + use openzeppelin_access::ownable::OwnableComponent; use starknet::ContractAddress; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); @@ -60,7 +60,7 @@ pub(crate) mod SnakeOwnableMock { #[starknet::contract] pub(crate) mod CamelOwnableMock { - use openzeppelin::access::ownable::OwnableComponent; + use openzeppelin_access::ownable::OwnableComponent; use starknet::ContractAddress; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); @@ -158,7 +158,7 @@ pub(crate) mod CamelOwnablePanicMock { #[starknet::contract] pub(crate) mod DualCaseTwoStepOwnableMock { - use openzeppelin::access::ownable::OwnableComponent; + use openzeppelin_access::ownable::OwnableComponent; use starknet::ContractAddress; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); diff --git a/src/tests/mocks/pausable_mocks.cairo b/src/tests/mocks/pausable_mocks.cairo index e737508f9..c37584a24 100644 --- a/src/tests/mocks/pausable_mocks.cairo +++ b/src/tests/mocks/pausable_mocks.cairo @@ -1,6 +1,6 @@ #[starknet::contract] pub(crate) mod PausableMock { - use openzeppelin::security::pausable::PausableComponent; + use openzeppelin_security::pausable::PausableComponent; component!(path: PausableComponent, storage: pausable, event: PausableEvent); diff --git a/src/tests/mocks/reentrancy_mocks.cairo b/src/tests/mocks/reentrancy_mocks.cairo index 44d545d9d..e7768e70f 100644 --- a/src/tests/mocks/reentrancy_mocks.cairo +++ b/src/tests/mocks/reentrancy_mocks.cairo @@ -17,7 +17,7 @@ pub(crate) trait IReentrancyMock { #[starknet::contract] pub(crate) mod ReentrancyMock { - use openzeppelin::security::reentrancyguard::ReentrancyGuardComponent; + use openzeppelin_security::reentrancyguard::ReentrancyGuardComponent; use starknet::ContractAddress; use starknet::get_contract_address; use super::IAttackerDispatcher; diff --git a/src/tests/mocks/src5_mocks.cairo b/src/tests/mocks/src5_mocks.cairo index f6d5f51b5..86e8c5167 100644 --- a/src/tests/mocks/src5_mocks.cairo +++ b/src/tests/mocks/src5_mocks.cairo @@ -1,6 +1,6 @@ #[starknet::contract] pub(crate) mod SRC5Mock { - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_introspection::src5::SRC5Component; component!(path: SRC5Component, storage: src5, event: SRC5Event); diff --git a/src/tests/mocks/upgrades_mocks.cairo b/src/tests/mocks/upgrades_mocks.cairo index 07a7ac620..266680d56 100644 --- a/src/tests/mocks/upgrades_mocks.cairo +++ b/src/tests/mocks/upgrades_mocks.cairo @@ -14,7 +14,7 @@ pub(crate) trait IUpgradesV1 { #[starknet::contract] pub(crate) mod UpgradesV1 { - use openzeppelin::upgrades::UpgradeableComponent; + use openzeppelin_upgrades::UpgradeableComponent; use starknet::ClassHash; component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); @@ -64,7 +64,7 @@ pub(crate) trait IUpgradesV2 { #[starknet::contract] pub(crate) mod UpgradesV2 { - use openzeppelin::upgrades::UpgradeableComponent; + use openzeppelin_upgrades::UpgradeableComponent; use starknet::ClassHash; component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); diff --git a/src/tests/presets/test_account.cairo b/src/tests/presets/test_account.cairo index 61dc1c803..284de0718 100644 --- a/src/tests/presets/test_account.cairo +++ b/src/tests/presets/test_account.cairo @@ -1,9 +1,9 @@ use core::num::traits::Zero; -use openzeppelin::account::AccountComponent::{OwnerAdded, OwnerRemoved}; -use openzeppelin::account::interface::ISRC6_ID; -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::presets::AccountUpgradeable; -use openzeppelin::presets::interfaces::{ +use openzeppelin_account::AccountComponent::{OwnerAdded, OwnerRemoved}; +use openzeppelin_account::interface::ISRC6_ID; +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_presets::AccountUpgradeable; +use openzeppelin_presets::interfaces::{ AccountUpgradeableABIDispatcher, AccountUpgradeableABIDispatcherTrait }; use openzeppelin::tests::account::starknet::common::{ @@ -19,9 +19,9 @@ use openzeppelin::tests::utils::constants::{ MIN_TRANSACTION_VERSION, CLASS_HASH_ZERO }; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; use starknet::account::Call; use starknet::testing; use starknet::{ContractAddress, ClassHash}; diff --git a/src/tests/presets/test_erc1155.cairo b/src/tests/presets/test_erc1155.cairo index ba1b71101..7073c6516 100644 --- a/src/tests/presets/test_erc1155.cairo +++ b/src/tests/presets/test_erc1155.cairo @@ -1,7 +1,7 @@ use core::num::traits::Zero; -use openzeppelin::introspection; -use openzeppelin::presets::ERC1155Upgradeable; -use openzeppelin::presets::interfaces::{ +use openzeppelin_introspection; +use openzeppelin_presets::ERC1155Upgradeable; +use openzeppelin_presets::interfaces::{ ERC1155UpgradeableABIDispatcher, ERC1155UpgradeableABIDispatcherTrait }; use openzeppelin::tests::access::common::assert_event_ownership_transferred; @@ -20,12 +20,10 @@ use openzeppelin::tests::utils::constants::{ TOKEN_VALUE, TOKEN_VALUE_2 }; use openzeppelin::tests::utils; -use openzeppelin::token::erc1155::interface::{ - IERC1155CamelDispatcher, IERC1155CamelDispatcherTrait -}; -use openzeppelin::token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; -use openzeppelin::token::erc1155; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc1155::interface::{IERC1155CamelDispatcher, IERC1155CamelDispatcherTrait}; +use openzeppelin_token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; +use openzeppelin_token::erc1155; +use openzeppelin_utils::serde::SerializedAppend; use starknet::testing; use starknet::{ContractAddress, ClassHash}; diff --git a/src/tests/presets/test_erc20.cairo b/src/tests/presets/test_erc20.cairo index b9d7f8e00..9f39fc240 100644 --- a/src/tests/presets/test_erc20.cairo +++ b/src/tests/presets/test_erc20.cairo @@ -1,8 +1,8 @@ use core::integer::BoundedInt; use core::num::traits::Zero; -use openzeppelin::access::ownable::OwnableComponent::OwnershipTransferred; -use openzeppelin::presets::ERC20Upgradeable; -use openzeppelin::presets::interfaces::{ +use openzeppelin_access::ownable::OwnableComponent::OwnershipTransferred; +use openzeppelin_presets::ERC20Upgradeable; +use openzeppelin_presets::interfaces::{ ERC20UpgradeableABIDispatcher, ERC20UpgradeableABIDispatcherTrait }; use openzeppelin::tests::access::common::assert_event_ownership_transferred; @@ -15,9 +15,9 @@ use openzeppelin::tests::utils::constants::{ ZERO, OWNER, SPENDER, RECIPIENT, OTHER, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE, CLASS_HASH_ZERO }; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; +use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ClassHash; use starknet::testing; diff --git a/src/tests/presets/test_erc721.cairo b/src/tests/presets/test_erc721.cairo index bf1d27d14..3c54e3bd0 100644 --- a/src/tests/presets/test_erc721.cairo +++ b/src/tests/presets/test_erc721.cairo @@ -1,8 +1,8 @@ use core::num::traits::Zero; -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::presets::ERC721Upgradeable::InternalImpl; -use openzeppelin::presets::ERC721Upgradeable; -use openzeppelin::presets::interfaces::{ +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_presets::ERC721Upgradeable::InternalImpl; +use openzeppelin_presets::ERC721Upgradeable; +use openzeppelin_presets::interfaces::{ ERC721UpgradeableABIDispatcher, ERC721UpgradeableABIDispatcherTrait }; use openzeppelin::tests::access::common::assert_event_ownership_transferred; @@ -22,14 +22,14 @@ use openzeppelin::tests::utils::constants::{ BASE_URI }; use openzeppelin::tests::utils; -use openzeppelin::token::erc721::ERC721Component::ERC721Impl; -use openzeppelin::token::erc721::ERC721Component; -use openzeppelin::token::erc721::interface::{ +use openzeppelin_token::erc721::ERC721Component::ERC721Impl; +use openzeppelin_token::erc721::ERC721Component; +use openzeppelin_token::erc721::interface::{ IERC721CamelOnlyDispatcher, IERC721CamelOnlyDispatcherTrait }; -use openzeppelin::token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; -use openzeppelin::token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID}; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; +use openzeppelin_token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID}; +use openzeppelin_utils::serde::SerializedAppend; use starknet::testing; use starknet::{ContractAddress, ClassHash}; diff --git a/src/tests/presets/test_eth_account.cairo b/src/tests/presets/test_eth_account.cairo index b8510958a..1f8488106 100644 --- a/src/tests/presets/test_eth_account.cairo +++ b/src/tests/presets/test_eth_account.cairo @@ -1,12 +1,12 @@ use core::num::traits::Zero; -use openzeppelin::account::interface::ISRC6_ID; -use openzeppelin::account::utils::secp256k1::{ +use openzeppelin_account::interface::ISRC6_ID; +use openzeppelin_account::utils::secp256k1::{ DebugSecp256k1Point, Secp256k1PointSerde, Secp256k1PointPartialEq }; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::presets::EthAccountUpgradeable; -use openzeppelin::presets::interfaces::{ +use openzeppelin_account::utils::signature::EthSignature; +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_presets::EthAccountUpgradeable; +use openzeppelin_presets::interfaces::{ EthAccountUpgradeableABIDispatcher, EthAccountUpgradeableABIDispatcherTrait }; use openzeppelin::tests::account::ethereum::common::{ @@ -21,9 +21,9 @@ use openzeppelin::tests::utils::constants::{ CLASS_HASH_ZERO, ETH_PUBKEY, SALT, ZERO, RECIPIENT, QUERY_VERSION, MIN_TRANSACTION_VERSION }; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc20::interface::IERC20DispatcherTrait; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; use starknet::account::Call; use starknet::contract_address_const; use starknet::testing; diff --git a/src/tests/presets/test_universal_deployer.cairo b/src/tests/presets/test_universal_deployer.cairo index e5247a9ae..e5425ffa8 100644 --- a/src/tests/presets/test_universal_deployer.cairo +++ b/src/tests/presets/test_universal_deployer.cairo @@ -1,14 +1,14 @@ -use openzeppelin::presets::universal_deployer::UniversalDeployer::ContractDeployed; -use openzeppelin::presets::universal_deployer::UniversalDeployer; +use openzeppelin_presets::universal_deployer::UniversalDeployer::ContractDeployed; +use openzeppelin_presets::universal_deployer::UniversalDeployer; use openzeppelin::tests::mocks::erc20_mocks::DualCaseERC20Mock; use openzeppelin::tests::utils::constants::{NAME, SYMBOL, SUPPLY, SALT, CALLER, RECIPIENT}; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin::utils::deployments::{DeployerInfo, calculate_contract_address_from_udc}; -use openzeppelin::utils::interfaces::{ +use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin_utils::deployments::{DeployerInfo, calculate_contract_address_from_udc}; +use openzeppelin_utils::interfaces::{ IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait }; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ClassHash; use starknet::ContractAddress; use starknet::testing; diff --git a/src/tests/security/test_initializable.cairo b/src/tests/security/test_initializable.cairo index 745b34518..37d27debc 100644 --- a/src/tests/security/test_initializable.cairo +++ b/src/tests/security/test_initializable.cairo @@ -1,5 +1,5 @@ -use openzeppelin::security::InitializableComponent::{InitializableImpl, InternalImpl}; -use openzeppelin::security::InitializableComponent; +use openzeppelin_security::InitializableComponent::{InitializableImpl, InternalImpl}; +use openzeppelin_security::InitializableComponent; use openzeppelin::tests::mocks::initializable_mocks::InitializableMock; type ComponentState = InitializableComponent::ComponentState; diff --git a/src/tests/security/test_pausable.cairo b/src/tests/security/test_pausable.cairo index 8fd170df0..b646d820b 100644 --- a/src/tests/security/test_pausable.cairo +++ b/src/tests/security/test_pausable.cairo @@ -1,6 +1,6 @@ -use openzeppelin::security::PausableComponent::{InternalImpl, PausableImpl}; -use openzeppelin::security::PausableComponent::{Paused, Unpaused}; -use openzeppelin::security::PausableComponent; +use openzeppelin_security::PausableComponent::{InternalImpl, PausableImpl}; +use openzeppelin_security::PausableComponent::{Paused, Unpaused}; +use openzeppelin_security::PausableComponent; use openzeppelin::tests::mocks::pausable_mocks::PausableMock; use openzeppelin::tests::utils::constants::{CALLER, ZERO}; use openzeppelin::tests::utils; diff --git a/src/tests/security/test_reentrancyguard.cairo b/src/tests/security/test_reentrancyguard.cairo index b243b4aa4..34df8212b 100644 --- a/src/tests/security/test_reentrancyguard.cairo +++ b/src/tests/security/test_reentrancyguard.cairo @@ -1,5 +1,5 @@ -use openzeppelin::security::ReentrancyGuardComponent::InternalImpl; -use openzeppelin::security::ReentrancyGuardComponent; +use openzeppelin_security::ReentrancyGuardComponent::InternalImpl; +use openzeppelin_security::ReentrancyGuardComponent; use openzeppelin::tests::mocks::reentrancy_mocks::{ Attacker, ReentrancyMock, IReentrancyMockDispatcher, IReentrancyMockDispatcherTrait }; diff --git a/src/tests/token/erc1155/common.cairo b/src/tests/token/erc1155/common.cairo index ba7ca499a..692207bb7 100644 --- a/src/tests/token/erc1155/common.cairo +++ b/src/tests/token/erc1155/common.cairo @@ -7,9 +7,9 @@ use openzeppelin::tests::utils::constants::{ PUBKEY, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 }; use openzeppelin::tests::utils; -use openzeppelin::token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; -use openzeppelin::token::erc1155::ERC1155Component; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; +use openzeppelin_token::erc1155::ERC1155Component; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; diff --git a/src/tests/token/erc1155/test_dual1155.cairo b/src/tests/token/erc1155/test_dual1155.cairo index 16bfe4bfa..3dfe53409 100644 --- a/src/tests/token/erc1155/test_dual1155.cairo +++ b/src/tests/token/erc1155/test_dual1155.cairo @@ -6,13 +6,13 @@ use openzeppelin::tests::utils::constants::{ EMPTY_DATA, OWNER, RECIPIENT, OPERATOR, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE }; use openzeppelin::tests::utils; -use openzeppelin::token::erc1155::dual1155::{DualCaseERC1155, DualCaseERC1155Trait}; -use openzeppelin::token::erc1155::interface::IERC1155_ID; -use openzeppelin::token::erc1155::interface::{ +use openzeppelin_token::erc1155::dual1155::{DualCaseERC1155, DualCaseERC1155Trait}; +use openzeppelin_token::erc1155::interface::IERC1155_ID; +use openzeppelin_token::erc1155::interface::{ IERC1155CamelDispatcher, IERC1155CamelDispatcherTrait }; -use openzeppelin::token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; use starknet::testing; diff --git a/src/tests/token/erc1155/test_dual1155_receiver.cairo b/src/tests/token/erc1155/test_dual1155_receiver.cairo index d62ab277b..b17e3d8fe 100644 --- a/src/tests/token/erc1155/test_dual1155_receiver.cairo +++ b/src/tests/token/erc1155/test_dual1155_receiver.cairo @@ -5,14 +5,14 @@ use openzeppelin::tests::mocks::erc1155_receiver_mocks::{ use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::utils::constants::{EMPTY_DATA, OPERATOR, OWNER, TOKEN_ID, TOKEN_VALUE}; use openzeppelin::tests::utils; -use openzeppelin::token::erc1155::dual1155_receiver::{ +use openzeppelin_token::erc1155::dual1155_receiver::{ DualCaseERC1155Receiver, DualCaseERC1155ReceiverTrait }; -use openzeppelin::token::erc1155::interface::IERC1155_RECEIVER_ID; -use openzeppelin::token::erc1155::interface::{ +use openzeppelin_token::erc1155::interface::IERC1155_RECEIVER_ID; +use openzeppelin_token::erc1155::interface::{ IERC1155ReceiverCamelDispatcher, IERC1155ReceiverCamelDispatcherTrait }; -use openzeppelin::token::erc1155::interface::{ +use openzeppelin_token::erc1155::interface::{ IERC1155ReceiverDispatcher, IERC1155ReceiverDispatcherTrait }; diff --git a/src/tests/token/erc1155/test_erc1155.cairo b/src/tests/token/erc1155/test_erc1155.cairo index 978bc1634..c93bc9f76 100644 --- a/src/tests/token/erc1155/test_erc1155.cairo +++ b/src/tests/token/erc1155/test_erc1155.cairo @@ -1,21 +1,21 @@ use core::num::traits::Zero; use core::starknet::storage::StorageMemberAccessTrait; -use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; -use openzeppelin::introspection; +use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; +use openzeppelin_introspection; use openzeppelin::tests::mocks::erc1155_mocks::DualCaseERC1155Mock; use openzeppelin::tests::utils::constants::{ EMPTY_DATA, ZERO, OWNER, RECIPIENT, OPERATOR, OTHER, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 }; use openzeppelin::tests::utils; -use openzeppelin::token::erc1155::ERC1155Component::ERC1155CamelImpl; -use openzeppelin::token::erc1155::ERC1155Component::{ +use openzeppelin_token::erc1155::ERC1155Component::ERC1155CamelImpl; +use openzeppelin_token::erc1155::ERC1155Component::{ ERC1155Impl, ERC1155MetadataURIImpl, InternalImpl }; -use openzeppelin::token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; -use openzeppelin::token::erc1155::ERC1155Component; -use openzeppelin::token::erc1155; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; +use openzeppelin_token::erc1155::ERC1155Component; +use openzeppelin_token::erc1155; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; use starknet::testing; diff --git a/src/tests/token/erc1155/test_erc1155_receiver.cairo b/src/tests/token/erc1155/test_erc1155_receiver.cairo index 5d3456a52..a7645e941 100644 --- a/src/tests/token/erc1155/test_erc1155_receiver.cairo +++ b/src/tests/token/erc1155/test_erc1155_receiver.cairo @@ -1,11 +1,11 @@ -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; use openzeppelin::tests::mocks::erc1155_receiver_mocks::DualCaseERC1155ReceiverMock; use openzeppelin::tests::utils::constants::{OWNER, OPERATOR, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA}; -use openzeppelin::token::erc1155::ERC1155ReceiverComponent::{ +use openzeppelin_token::erc1155::ERC1155ReceiverComponent::{ ERC1155ReceiverImpl, ERC1155ReceiverCamelImpl, InternalImpl }; -use openzeppelin::token::erc1155::interface::IERC1155_RECEIVER_ID; +use openzeppelin_token::erc1155::interface::IERC1155_RECEIVER_ID; fn STATE() -> DualCaseERC1155ReceiverMock::ContractState { DualCaseERC1155ReceiverMock::contract_state_for_testing() diff --git a/src/tests/token/erc20/common.cairo b/src/tests/token/erc20/common.cairo index dfd3e7e7d..8b39e9b6d 100644 --- a/src/tests/token/erc20/common.cairo +++ b/src/tests/token/erc20/common.cairo @@ -1,7 +1,7 @@ use openzeppelin::tests::utils; -use openzeppelin::token::erc20::ERC20Component::{Approval, Transfer}; -use openzeppelin::token::erc20::ERC20Component; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc20::ERC20Component::{Approval, Transfer}; +use openzeppelin_token::erc20::ERC20Component; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; pub(crate) fn assert_event_approval( diff --git a/src/tests/token/erc20/test_dual20.cairo b/src/tests/token/erc20/test_dual20.cairo index ba9ba740d..ce6fae07e 100644 --- a/src/tests/token/erc20/test_dual20.cairo +++ b/src/tests/token/erc20/test_dual20.cairo @@ -5,10 +5,10 @@ use openzeppelin::tests::utils::constants::{ OWNER, RECIPIENT, SPENDER, OPERATOR, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE }; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::dual20::{DualCaseERC20, DualCaseERC20Trait}; -use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc20::dual20::{DualCaseERC20, DualCaseERC20Trait}; +use openzeppelin_token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; +use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin_utils::serde::SerializedAppend; use starknet::testing::set_contract_address; // diff --git a/src/tests/token/erc20/test_erc20.cairo b/src/tests/token/erc20/test_erc20.cairo index 2c41a7971..9ac361d26 100644 --- a/src/tests/token/erc20/test_erc20.cairo +++ b/src/tests/token/erc20/test_erc20.cairo @@ -4,11 +4,11 @@ use openzeppelin::tests::utils::constants::{ ZERO, OWNER, SPENDER, RECIPIENT, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE }; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::ERC20Component::{Approval, Transfer}; -use openzeppelin::token::erc20::ERC20Component::{ERC20CamelOnlyImpl, ERC20Impl}; -use openzeppelin::token::erc20::ERC20Component::{ERC20MetadataImpl, InternalImpl}; -use openzeppelin::token::erc20::ERC20Component; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc20::ERC20Component::{Approval, Transfer}; +use openzeppelin_token::erc20::ERC20Component::{ERC20CamelOnlyImpl, ERC20Impl}; +use openzeppelin_token::erc20::ERC20Component::{ERC20MetadataImpl, InternalImpl}; +use openzeppelin_token::erc20::ERC20Component; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; use starknet::testing; diff --git a/src/tests/token/erc20/test_erc20_votes.cairo b/src/tests/token/erc20/test_erc20_votes.cairo index e241e891c..bcb83900d 100644 --- a/src/tests/token/erc20/test_erc20_votes.cairo +++ b/src/tests/token/erc20/test_erc20_votes.cairo @@ -5,16 +5,16 @@ use openzeppelin::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock::SNIP1 use openzeppelin::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock; use openzeppelin::tests::utils::constants::{SUPPLY, ZERO, OWNER, PUBKEY, RECIPIENT}; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::ERC20Component::InternalImpl as ERC20Impl; -use openzeppelin::token::erc20::extensions::ERC20VotesComponent::{ +use openzeppelin_token::erc20::ERC20Component::InternalImpl as ERC20Impl; +use openzeppelin_token::erc20::extensions::ERC20VotesComponent::{ DelegateChanged, DelegateVotesChanged }; -use openzeppelin::token::erc20::extensions::ERC20VotesComponent::{ERC20VotesImpl, InternalImpl}; -use openzeppelin::token::erc20::extensions::ERC20VotesComponent; -use openzeppelin::token::erc20::extensions::erc20_votes::Delegation; -use openzeppelin::utils::cryptography::snip12::OffchainMessageHash; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::structs::checkpoint::{Checkpoint, Trace, TraceTrait}; +use openzeppelin_token::erc20::extensions::ERC20VotesComponent::{ERC20VotesImpl, InternalImpl}; +use openzeppelin_token::erc20::extensions::ERC20VotesComponent; +use openzeppelin_token::erc20::extensions::erc20_votes::Delegation; +use openzeppelin_utils::cryptography::snip12::OffchainMessageHash; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::structs::checkpoint::{Checkpoint, Trace, TraceTrait}; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; diff --git a/src/tests/token/erc721/common.cairo b/src/tests/token/erc721/common.cairo index a6601e5e1..d640956bf 100644 --- a/src/tests/token/erc721/common.cairo +++ b/src/tests/token/erc721/common.cairo @@ -1,7 +1,7 @@ use openzeppelin::tests::utils; -use openzeppelin::token::erc721::ERC721Component::{Approval, ApprovalForAll, Transfer}; -use openzeppelin::token::erc721::ERC721Component; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc721::ERC721Component::{Approval, ApprovalForAll, Transfer}; +use openzeppelin_token::erc721::ERC721Component; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; pub(crate) fn assert_event_approval_for_all( diff --git a/src/tests/token/erc721/test_dual721.cairo b/src/tests/token/erc721/test_dual721.cairo index 4cf393bf7..b90962f67 100644 --- a/src/tests/token/erc721/test_dual721.cairo +++ b/src/tests/token/erc721/test_dual721.cairo @@ -6,13 +6,13 @@ use openzeppelin::tests::utils::constants::{ DATA, OWNER, RECIPIENT, SPENDER, OPERATOR, OTHER, NAME, SYMBOL, BASE_URI, TOKEN_ID }; use openzeppelin::tests::utils; -use openzeppelin::token::erc721::dual721::{DualCaseERC721, DualCaseERC721Trait}; -use openzeppelin::token::erc721::interface::IERC721_ID; -use openzeppelin::token::erc721::interface::{ +use openzeppelin_token::erc721::dual721::{DualCaseERC721, DualCaseERC721Trait}; +use openzeppelin_token::erc721::interface::IERC721_ID; +use openzeppelin_token::erc721::interface::{ IERC721CamelOnlyDispatcher, IERC721CamelOnlyDispatcherTrait }; -use openzeppelin::token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; +use openzeppelin_utils::serde::SerializedAppend; use starknet::ContractAddress; use starknet::testing::set_caller_address; use starknet::testing::set_contract_address; diff --git a/src/tests/token/erc721/test_dual721_receiver.cairo b/src/tests/token/erc721/test_dual721_receiver.cairo index d6073197d..44fc3ee8b 100644 --- a/src/tests/token/erc721/test_dual721_receiver.cairo +++ b/src/tests/token/erc721/test_dual721_receiver.cairo @@ -7,14 +7,14 @@ use openzeppelin::tests::mocks::erc721_receiver_mocks::{ use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::utils::constants::{DATA, OPERATOR, OWNER, TOKEN_ID}; use openzeppelin::tests::utils; -use openzeppelin::token::erc721::dual721_receiver::{ +use openzeppelin_token::erc721::dual721_receiver::{ DualCaseERC721Receiver, DualCaseERC721ReceiverTrait }; -use openzeppelin::token::erc721::interface::IERC721_RECEIVER_ID; -use openzeppelin::token::erc721::interface::{ +use openzeppelin_token::erc721::interface::IERC721_RECEIVER_ID; +use openzeppelin_token::erc721::interface::{ IERC721ReceiverCamelDispatcher, IERC721ReceiverCamelDispatcherTrait }; -use openzeppelin::token::erc721::interface::{ +use openzeppelin_token::erc721::interface::{ IERC721ReceiverDispatcher, IERC721ReceiverDispatcherTrait }; diff --git a/src/tests/token/erc721/test_erc721.cairo b/src/tests/token/erc721/test_erc721.cairo index 7dd5ae1bf..b496860f8 100644 --- a/src/tests/token/erc721/test_erc721.cairo +++ b/src/tests/token/erc721/test_erc721.cairo @@ -1,8 +1,8 @@ use core::num::traits::Zero; -use openzeppelin::account::AccountComponent; -use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; -use openzeppelin::introspection::src5; -use openzeppelin::introspection; +use openzeppelin_account::AccountComponent; +use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; +use openzeppelin_introspection::src5; +use openzeppelin_introspection; use openzeppelin::tests::mocks::account_mocks::{DualCaseAccountMock, CamelAccountMock}; use openzeppelin::tests::mocks::erc721_mocks::DualCaseERC721Mock; use openzeppelin::tests::mocks::erc721_receiver_mocks::{ @@ -14,13 +14,11 @@ use openzeppelin::tests::utils::constants::{ TOKEN_ID_2, PUBKEY, BASE_URI, BASE_URI_2 }; use openzeppelin::tests::utils; -use openzeppelin::token::erc721::ERC721Component::{ - ERC721CamelOnlyImpl, ERC721MetadataCamelOnlyImpl -}; -use openzeppelin::token::erc721::ERC721Component::{ERC721Impl, ERC721MetadataImpl, InternalImpl}; -use openzeppelin::token::erc721::ERC721Component; -use openzeppelin::token::erc721::interface::IERC721; -use openzeppelin::token::erc721; +use openzeppelin_token::erc721::ERC721Component::{ERC721CamelOnlyImpl, ERC721MetadataCamelOnlyImpl}; +use openzeppelin_token::erc721::ERC721Component::{ERC721Impl, ERC721MetadataImpl, InternalImpl}; +use openzeppelin_token::erc721::ERC721Component; +use openzeppelin_token::erc721::interface::IERC721; +use openzeppelin_token::erc721; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::storage::StorageMapMemberAccessTrait; diff --git a/src/tests/token/erc721/test_erc721_receiver.cairo b/src/tests/token/erc721/test_erc721_receiver.cairo index 72f8272a2..62315b482 100644 --- a/src/tests/token/erc721/test_erc721_receiver.cairo +++ b/src/tests/token/erc721/test_erc721_receiver.cairo @@ -1,11 +1,11 @@ -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; use openzeppelin::tests::mocks::erc721_receiver_mocks::DualCaseERC721ReceiverMock; use openzeppelin::tests::utils::constants::{OWNER, OPERATOR, TOKEN_ID, DATA}; -use openzeppelin::token::erc721::ERC721ReceiverComponent::{ +use openzeppelin_token::erc721::ERC721ReceiverComponent::{ ERC721ReceiverImpl, ERC721ReceiverCamelImpl, InternalImpl }; -use openzeppelin::token::erc721::interface::IERC721_RECEIVER_ID; +use openzeppelin_token::erc721::interface::IERC721_RECEIVER_ID; fn STATE() -> DualCaseERC721ReceiverMock::ContractState { DualCaseERC721ReceiverMock::contract_state_for_testing() diff --git a/src/tests/upgrades/common.cairo b/src/tests/upgrades/common.cairo index 0308fd45b..ce9b03c0f 100644 --- a/src/tests/upgrades/common.cairo +++ b/src/tests/upgrades/common.cairo @@ -1,7 +1,7 @@ use openzeppelin::tests::utils::constants::ZERO; use openzeppelin::tests::utils; -use openzeppelin::upgrades::UpgradeableComponent::Upgraded; -use openzeppelin::upgrades::UpgradeableComponent; +use openzeppelin_upgrades::UpgradeableComponent::Upgraded; +use openzeppelin_upgrades::UpgradeableComponent; use starknet::{ContractAddress, ClassHash}; pub(crate) fn assert_event_upgraded(contract: ContractAddress, class_hash: ClassHash) { diff --git a/src/tests/upgrades/test_upgradeable.cairo b/src/tests/upgrades/test_upgradeable.cairo index c022e9c85..52e0e26eb 100644 --- a/src/tests/upgrades/test_upgradeable.cairo +++ b/src/tests/upgrades/test_upgradeable.cairo @@ -6,7 +6,7 @@ use openzeppelin::tests::mocks::upgrades_mocks::{ }; use openzeppelin::tests::utils::constants::{CLASS_HASH_ZERO, ZERO}; use openzeppelin::tests::utils; -use openzeppelin::upgrades::UpgradeableComponent; +use openzeppelin_upgrades::UpgradeableComponent; use starknet::ClassHash; use super::common::assert_only_event_upgraded; diff --git a/src/tests/utils/constants.cairo b/src/tests/utils/constants.cairo index 8f29ca4f9..cbdfd16d8 100644 --- a/src/tests/utils/constants.cairo +++ b/src/tests/utils/constants.cairo @@ -1,4 +1,4 @@ -use openzeppelin::account::interface::EthPublicKey; +use openzeppelin_account::interface::EthPublicKey; use starknet::ClassHash; use starknet::ContractAddress; use starknet::SyscallResultTrait; From 890608eb37508ff3369bf52d6f11ae94ab925eba Mon Sep 17 00:00:00 2001 From: Alex Metelli Date: Sun, 7 Jul 2024 11:21:04 +0800 Subject: [PATCH 06/45] fmt --- packages/access/src/accesscontrol/dual_accesscontrol.cairo | 6 +++--- packages/introspection/src/lib.cairo | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/access/src/accesscontrol/dual_accesscontrol.cairo b/packages/access/src/accesscontrol/dual_accesscontrol.cairo index 46d05e00d..1f63852f2 100644 --- a/packages/access/src/accesscontrol/dual_accesscontrol.cairo +++ b/packages/access/src/accesscontrol/dual_accesscontrol.cairo @@ -1,10 +1,10 @@ +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.14.0 (access/accesscontrol/dual_accesscontrol.cairo) use openzeppelin_utils::unwrap_and_cast::UnwrapAndCast; -use openzeppelin_utils::selectors; -use openzeppelin_utils::serde::SerializedAppend; -use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::syscalls::call_contract_syscall; diff --git a/packages/introspection/src/lib.cairo b/packages/introspection/src/lib.cairo index 191587449..584b93016 100644 --- a/packages/introspection/src/lib.cairo +++ b/packages/introspection/src/lib.cairo @@ -1,2 +1,2 @@ pub mod interface; -pub mod src5; \ No newline at end of file +pub mod src5; From c3df2885516b59b4dc3faa11885be34d7334845f Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Wed, 10 Jul 2024 13:52:23 +0200 Subject: [PATCH 07/45] Migrate erc1155 tests (#1037) * feat: update common module * feat: migrate dual modules * feat: finish component test migration * refactor: remove unnecessary imports * feat: apply review updates --- src/tests/token.cairo | 2 +- src/tests/token/erc1155/common.cairo | 205 ++++--- src/tests/token/erc1155/test_dual1155.cairo | 101 ++-- .../erc1155/test_dual1155_receiver.cairo | 43 +- src/tests/token/erc1155/test_erc1155.cairo | 524 ++++++++++++------ src/tests/utils.cairo | 4 +- src/tests/utils/common.cairo | 18 +- 7 files changed, 566 insertions(+), 331 deletions(-) diff --git a/src/tests/token.cairo b/src/tests/token.cairo index 25979f784..2ecd8ae11 100644 --- a/src/tests/token.cairo +++ b/src/tests/token.cairo @@ -1,3 +1,3 @@ -// pub(crate) mod erc1155; +pub(crate) mod erc1155; // pub(crate) mod erc721; pub(crate) mod erc20; diff --git a/src/tests/token/erc1155/common.cairo b/src/tests/token/erc1155/common.cairo index 3230c45b0..579b5931b 100644 --- a/src/tests/token/erc1155/common.cairo +++ b/src/tests/token/erc1155/common.cairo @@ -1,134 +1,36 @@ -use openzeppelin::tests::mocks::account_mocks::SnakeAccountMock; -use openzeppelin::tests::mocks::erc1155_receiver_mocks::{ - CamelERC1155ReceiverMock, SnakeERC1155ReceiverMock -}; -use openzeppelin::tests::mocks::src5_mocks::SRC5Mock; use openzeppelin::tests::utils::constants::{ PUBKEY, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 }; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::tests::utils; use openzeppelin::token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; use openzeppelin::token::erc1155::ERC1155Component; -use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::EventSpy; use starknet::ContractAddress; pub(crate) fn setup_receiver() -> ContractAddress { - utils::deploy(SnakeERC1155ReceiverMock::TEST_CLASS_HASH, array![]) + utils::declare_and_deploy("SnakeERC1155ReceiverMock", array![]) } pub(crate) fn setup_camel_receiver() -> ContractAddress { - utils::deploy(CamelERC1155ReceiverMock::TEST_CLASS_HASH, array![]) + utils::declare_and_deploy("CamelERC1155ReceiverMock", array![]) } pub(crate) fn setup_account() -> ContractAddress { - let mut calldata = array![PUBKEY]; - utils::deploy(SnakeAccountMock::TEST_CLASS_HASH, calldata) -} - -pub(crate) fn setup_account_with_salt(salt: felt252) -> ContractAddress { - let mut calldata = array![PUBKEY]; - utils::deploy_with_salt(SnakeAccountMock::TEST_CLASS_HASH, calldata, salt) + let calldata = array![PUBKEY]; + utils::declare_and_deploy("SnakeAccountMock", calldata) } -pub(crate) fn setup_src5() -> ContractAddress { - utils::deploy(SRC5Mock::TEST_CLASS_HASH, array![]) -} - -pub(crate) fn assert_event_approval_for_all( - contract: ContractAddress, owner: ContractAddress, operator: ContractAddress, approved: bool +pub(crate) fn deploy_another_account_at( + existing: ContractAddress, target_address: ContractAddress ) { - let event = utils::pop_log::(contract).unwrap(); - let expected = ERC1155Component::Event::ApprovalForAll( - ApprovalForAll { owner, operator, approved } - ); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("ApprovalForAll")); - indexed_keys.append_serde(owner); - indexed_keys.append_serde(operator); - utils::assert_indexed_keys(event, indexed_keys.span()); + let calldata = array![PUBKEY]; + utils::deploy_another_at(existing, target_address, calldata); } -pub(crate) fn assert_event_transfer_single( - contract: ContractAddress, - operator: ContractAddress, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - value: u256 -) { - let event = utils::pop_log::(contract).unwrap(); - let id = token_id; - let expected = ERC1155Component::Event::TransferSingle( - TransferSingle { operator, from, to, id, value } - ); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("TransferSingle")); - indexed_keys.append_serde(operator); - indexed_keys.append_serde(from); - indexed_keys.append_serde(to); - utils::assert_indexed_keys(event, indexed_keys.span()); -} - -pub(crate) fn assert_event_transfer_batch( - contract: ContractAddress, - operator: ContractAddress, - from: ContractAddress, - to: ContractAddress, - token_ids: Span, - values: Span -) { - let event = utils::pop_log::(contract).unwrap(); - let ids = token_ids; - let expected = ERC1155Component::Event::TransferBatch( - TransferBatch { operator, from, to, ids, values } - ); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("TransferBatch")); - indexed_keys.append_serde(operator); - indexed_keys.append_serde(from); - indexed_keys.append_serde(to); - utils::assert_indexed_keys(event, indexed_keys.span()); -} - -pub(crate) fn assert_only_event_transfer_single( - contract: ContractAddress, - operator: ContractAddress, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - value: u256 -) { - assert_event_transfer_single(contract, operator, from, to, token_id, value); - utils::assert_no_events_left(contract); -} - -pub(crate) fn assert_only_event_transfer_batch( - contract: ContractAddress, - operator: ContractAddress, - from: ContractAddress, - to: ContractAddress, - token_ids: Span, - values: Span -) { - assert_event_transfer_batch(contract, operator, from, to, token_ids, values); - utils::assert_no_events_left(contract); -} - -pub(crate) fn assert_only_event_approval_for_all( - contract: ContractAddress, owner: ContractAddress, operator: ContractAddress, approved: bool -) { - assert_event_approval_for_all(contract, owner, operator, approved); - utils::assert_no_events_left(contract); +pub(crate) fn setup_src5() -> ContractAddress { + utils::declare_and_deploy("SRC5Mock", array![]) } pub(crate) fn get_ids_and_values() -> (Span, Span) { @@ -142,3 +44,86 @@ pub(crate) fn get_ids_and_split_values(split: u256) -> (Span, Span) let values = array![TOKEN_VALUE - split, split].span(); (ids, values) } + +#[generate_trait] +pub(crate) impl ERC1155SpyHelpersImpl of ERC1155SpyHelpers { + fn assert_event_approval_for_all( + ref self: EventSpy, + contract: ContractAddress, + owner: ContractAddress, + operator: ContractAddress, + approved: bool + ) { + let expected = ERC1155Component::Event::ApprovalForAll( + ApprovalForAll { owner, operator, approved } + ); + self.assert_emitted_single(contract, expected); + } + + fn assert_only_event_approval_for_all( + ref self: EventSpy, + contract: ContractAddress, + owner: ContractAddress, + operator: ContractAddress, + approved: bool + ) { + self.assert_event_approval_for_all(contract, owner, operator, approved); + self.assert_no_events_left_from(contract); + } + + fn assert_event_transfer_single( + ref self: EventSpy, + contract: ContractAddress, + operator: ContractAddress, + from: ContractAddress, + to: ContractAddress, + token_id: u256, + value: u256 + ) { + let expected = ERC1155Component::Event::TransferSingle( + TransferSingle { operator, from, to, id: token_id, value } + ); + self.assert_emitted_single(contract, expected); + } + + fn assert_only_event_transfer_single( + ref self: EventSpy, + contract: ContractAddress, + operator: ContractAddress, + from: ContractAddress, + to: ContractAddress, + token_id: u256, + value: u256 + ) { + self.assert_event_transfer_single(contract, operator, from, to, token_id, value); + self.assert_no_events_left_from(contract); + } + + fn assert_event_transfer_batch( + ref self: EventSpy, + contract: ContractAddress, + operator: ContractAddress, + from: ContractAddress, + to: ContractAddress, + token_ids: Span, + values: Span + ) { + let expected = ERC1155Component::Event::TransferBatch( + TransferBatch { operator, from, to, ids: token_ids, values } + ); + self.assert_emitted_single(contract, expected); + } + + fn assert_only_event_transfer_batch( + ref self: EventSpy, + contract: ContractAddress, + operator: ContractAddress, + from: ContractAddress, + to: ContractAddress, + token_ids: Span, + values: Span + ) { + self.assert_event_transfer_batch(contract, operator, from, to, token_ids, values); + self.assert_no_events_left_from(contract); + } +} diff --git a/src/tests/token/erc1155/test_dual1155.cairo b/src/tests/token/erc1155/test_dual1155.cairo index 16bfe4bfa..4589cd2c1 100644 --- a/src/tests/token/erc1155/test_dual1155.cairo +++ b/src/tests/token/erc1155/test_dual1155.cairo @@ -1,7 +1,4 @@ use core::num::traits::Zero; -use openzeppelin::tests::mocks::erc1155_mocks::{CamelERC1155Mock, SnakeERC1155Mock}; -use openzeppelin::tests::mocks::erc1155_mocks::{CamelERC1155PanicMock, SnakeERC1155PanicMock}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::utils::constants::{ EMPTY_DATA, OWNER, RECIPIENT, OPERATOR, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE }; @@ -13,8 +10,8 @@ use openzeppelin::token::erc1155::interface::{ }; use openzeppelin::token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::start_cheat_caller_address; use starknet::ContractAddress; -use starknet::testing; use super::common::{setup_account, setup_receiver}; @@ -30,7 +27,7 @@ fn setup_snake() -> (DualCaseERC1155, IERC1155Dispatcher, ContractAddress) { calldata.append_serde(owner); calldata.append_serde(TOKEN_ID); calldata.append_serde(TOKEN_VALUE); - let target = utils::deploy(SnakeERC1155Mock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("SnakeERC1155Mock", calldata); ( DualCaseERC1155 { contract_address: target }, IERC1155Dispatcher { contract_address: target }, @@ -46,7 +43,7 @@ fn setup_camel() -> (DualCaseERC1155, IERC1155CamelDispatcher, ContractAddress) calldata.append_serde(owner); calldata.append_serde(TOKEN_ID); calldata.append_serde(TOKEN_VALUE); - let target = utils::deploy(CamelERC1155Mock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("CamelERC1155Mock", calldata); ( DualCaseERC1155 { contract_address: target }, IERC1155CamelDispatcher { contract_address: target }, @@ -56,13 +53,13 @@ fn setup_camel() -> (DualCaseERC1155, IERC1155CamelDispatcher, ContractAddress) fn setup_non_erc1155() -> DualCaseERC1155 { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("NonImplementingMock", calldata); DualCaseERC1155 { contract_address: target } } fn setup_erc1155_panic() -> (DualCaseERC1155, DualCaseERC1155) { - let snake_target = utils::deploy(SnakeERC1155PanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelERC1155PanicMock::TEST_CLASS_HASH, array![]); + let snake_target = utils::declare_and_deploy("SnakeERC1155PanicMock", array![]); + let camel_target = utils::declare_and_deploy("CamelERC1155PanicMock", array![]); ( DualCaseERC1155 { contract_address: snake_target }, DualCaseERC1155 { contract_address: camel_target } @@ -74,6 +71,7 @@ fn setup_erc1155_panic() -> (DualCaseERC1155, DualCaseERC1155) { // #[test] +#[ignore] fn test_dual_uri() { let (snake_dispatcher, _, _) = setup_snake(); let (camel_dispatcher, _, _) = setup_camel(); @@ -82,6 +80,7 @@ fn test_dual_uri() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_uri() { let dispatcher = setup_non_erc1155(); @@ -89,7 +88,8 @@ fn test_dual_no_uri() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_uri_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); dispatcher.uri(TOKEN_ID); @@ -100,12 +100,14 @@ fn test_dual_uri_exists_and_panics() { // #[test] +#[ignore] fn test_dual_balance_of() { let (dispatcher, _, owner) = setup_snake(); assert_eq!(dispatcher.balance_of(owner, TOKEN_ID), TOKEN_VALUE); } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_balance_of() { let dispatcher = setup_non_erc1155(); @@ -113,13 +115,15 @@ fn test_dual_no_balance_of() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_balance_of_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); dispatcher.balance_of(OWNER(), TOKEN_ID); } #[test] +#[ignore] fn test_dual_balance_of_batch() { let (dispatcher, _, owner) = setup_snake(); let accounts = array![owner, RECIPIENT()].span(); @@ -131,6 +135,7 @@ fn test_dual_balance_of_batch() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_balance_of_batch() { let dispatcher = setup_non_erc1155(); @@ -139,7 +144,8 @@ fn test_dual_no_balance_of_batch() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_balance_of_batch_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); let (accounts, token_ids) = get_accounts_and_ids(); @@ -147,15 +153,18 @@ fn test_dual_balance_of_batch_exists_and_panics() { } #[test] +#[ignore] fn test_dual_safe_transfer_from() { let (dispatcher, target, owner) = setup_snake(); let receiver = setup_receiver(); - testing::set_contract_address(owner); + + start_cheat_caller_address(dispatcher.contract_address, owner); dispatcher.safe_transfer_from(owner, receiver, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); assert_eq!(target.balance_of(receiver, TOKEN_ID), TOKEN_VALUE); } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_safe_transfer_from() { let dispatcher = setup_non_erc1155(); @@ -163,26 +172,29 @@ fn test_dual_no_safe_transfer_from() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_safe_transfer_from_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); dispatcher.safe_transfer_from(OWNER(), RECIPIENT(), TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] +#[ignore] fn test_dual_safe_batch_transfer_from() { let (dispatcher, target, owner) = setup_snake(); let token_ids = array![TOKEN_ID, TOKEN_ID_2].span(); let values = array![TOKEN_VALUE, 0].span(); let receiver = setup_receiver(); - testing::set_contract_address(owner); + start_cheat_caller_address(dispatcher.contract_address, owner); dispatcher.safe_batch_transfer_from(owner, receiver, token_ids, values, EMPTY_DATA()); assert_eq!(target.balance_of(receiver, TOKEN_ID), TOKEN_VALUE); assert!(target.balance_of(receiver, TOKEN_ID_2).is_zero()); } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_safe_batch_transfer_from() { let dispatcher = setup_non_erc1155(); @@ -192,7 +204,8 @@ fn test_dual_no_safe_batch_transfer_from() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_safe_batch_transfer_from_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); let token_ids = array![TOKEN_ID, TOKEN_ID_2].span(); @@ -201,9 +214,11 @@ fn test_dual_safe_batch_transfer_from_exists_and_panics() { } #[test] +#[ignore] fn test_dual_is_approved_for_all() { let (dispatcher, target, _) = setup_snake(); - testing::set_contract_address(OWNER()); + + start_cheat_caller_address(dispatcher.contract_address, OWNER()); target.set_approval_for_all(OPERATOR(), true); let is_approved_for_all = dispatcher.is_approved_for_all(OWNER(), OPERATOR()); @@ -211,6 +226,7 @@ fn test_dual_is_approved_for_all() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_is_approved_for_all() { let dispatcher = setup_non_erc1155(); @@ -218,16 +234,19 @@ fn test_dual_no_is_approved_for_all() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_is_approved_for_all_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); dispatcher.is_approved_for_all(OWNER(), OPERATOR()); } #[test] +#[ignore] fn test_dual_set_approval_for_all() { let (dispatcher, target, _) = setup_snake(); - testing::set_contract_address(OWNER()); + + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.set_approval_for_all(OPERATOR(), true); let is_approved_for_all = target.is_approved_for_all(OWNER(), OPERATOR()); @@ -235,6 +254,7 @@ fn test_dual_set_approval_for_all() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_set_approval_for_all() { let dispatcher = setup_non_erc1155(); @@ -242,13 +262,15 @@ fn test_dual_no_set_approval_for_all() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_set_approval_for_all_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); dispatcher.set_approval_for_all(OPERATOR(), true); } #[test] +#[ignore] fn test_dual_supports_interface() { let (dispatcher, _, _) = setup_snake(); let supports_ierc1155 = dispatcher.supports_interface(IERC1155_ID); @@ -256,6 +278,7 @@ fn test_dual_supports_interface() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_supports_interface() { let dispatcher = setup_non_erc1155(); @@ -263,7 +286,8 @@ fn test_dual_no_supports_interface() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_supports_interface_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); dispatcher.supports_interface(IERC1155_ID); @@ -274,19 +298,22 @@ fn test_dual_supports_interface_exists_and_panics() { // #[test] +#[ignore] fn test_dual_balanceOf() { let (dispatcher, _, owner) = setup_camel(); assert_eq!(dispatcher.balance_of(owner, TOKEN_ID), TOKEN_VALUE); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_balanceOf_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); dispatcher.balance_of(OWNER(), TOKEN_ID); } #[test] +#[ignore] fn test_dual_balanceOfBatch() { let (dispatcher, _, owner) = setup_camel(); let accounts = array![owner, RECIPIENT()].span(); @@ -298,7 +325,8 @@ fn test_dual_balanceOfBatch() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_balanceOfBatch_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); let (accounts, token_ids) = get_accounts_and_ids(); @@ -306,36 +334,41 @@ fn test_dual_balanceOfBatch_exists_and_panics() { } #[test] +#[ignore] fn test_dual_safeTransferFrom() { let (dispatcher, target, owner) = setup_camel(); let receiver = setup_receiver(); - testing::set_contract_address(owner); + + start_cheat_caller_address(dispatcher.contract_address, owner); dispatcher.safe_transfer_from(owner, receiver, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); assert_eq!(target.balanceOf(receiver, TOKEN_ID), TOKEN_VALUE); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_safeTransferFrom_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); dispatcher.safe_transfer_from(OWNER(), RECIPIENT(), TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] +#[ignore] fn test_dual_safeBatchTransferFrom() { let (dispatcher, target, owner) = setup_camel(); let token_ids = array![TOKEN_ID, TOKEN_ID_2].span(); let values = array![TOKEN_VALUE, 0].span(); let receiver = setup_receiver(); - testing::set_contract_address(owner); + start_cheat_caller_address(dispatcher.contract_address, owner); dispatcher.safe_batch_transfer_from(owner, receiver, token_ids, values, EMPTY_DATA()); assert_eq!(target.balanceOf(receiver, TOKEN_ID), TOKEN_VALUE); assert!(target.balanceOf(receiver, TOKEN_ID_2).is_zero()); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_safeBatchTransferFrom_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); let token_ids = array![TOKEN_ID, TOKEN_ID_2].span(); @@ -344,9 +377,11 @@ fn test_dual_safeBatchTransferFrom_exists_and_panics() { } #[test] +#[ignore] fn test_dual_isApprovedForAll() { let (dispatcher, target, _) = setup_camel(); - testing::set_contract_address(OWNER()); + + start_cheat_caller_address(dispatcher.contract_address, OWNER()); target.setApprovalForAll(OPERATOR(), true); let is_approved_for_all = dispatcher.is_approved_for_all(OWNER(), OPERATOR()); @@ -354,16 +389,19 @@ fn test_dual_isApprovedForAll() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_isApprovedForAll_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); dispatcher.is_approved_for_all(OWNER(), OPERATOR()); } #[test] +#[ignore] fn test_dual_setApprovalForAll() { let (dispatcher, target, _) = setup_camel(); - testing::set_contract_address(OWNER()); + + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.set_approval_for_all(OPERATOR(), true); let is_approved_for_all = target.isApprovedForAll(OWNER(), OPERATOR()); @@ -371,7 +409,8 @@ fn test_dual_setApprovalForAll() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_setApprovalForAll_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); dispatcher.set_approval_for_all(OPERATOR(), true); diff --git a/src/tests/token/erc1155/test_dual1155_receiver.cairo b/src/tests/token/erc1155/test_dual1155_receiver.cairo index da0b87bba..c207d3e71 100644 --- a/src/tests/token/erc1155/test_dual1155_receiver.cairo +++ b/src/tests/token/erc1155/test_dual1155_receiver.cairo @@ -1,8 +1,3 @@ -use openzeppelin::tests::mocks::erc1155_receiver_mocks::{ - CamelERC1155ReceiverMock, CamelERC1155ReceiverPanicMock, SnakeERC1155ReceiverMock, - SnakeERC1155ReceiverPanicMock -}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::utils::constants::{EMPTY_DATA, OPERATOR, OWNER, TOKEN_ID, TOKEN_VALUE}; use openzeppelin::tests::utils; use openzeppelin::token::erc1155::dual1155_receiver::{ @@ -21,8 +16,8 @@ use openzeppelin::token::erc1155::interface::{ // fn setup_snake() -> (DualCaseERC1155Receiver, IERC1155ReceiverDispatcher) { - let mut calldata = ArrayTrait::new(); - let target = utils::deploy(SnakeERC1155ReceiverMock::TEST_CLASS_HASH, calldata); + let mut calldata = array![]; + let target = utils::declare_and_deploy("SnakeERC1155ReceiverMock", calldata); ( DualCaseERC1155Receiver { contract_address: target }, IERC1155ReceiverDispatcher { contract_address: target } @@ -30,8 +25,8 @@ fn setup_snake() -> (DualCaseERC1155Receiver, IERC1155ReceiverDispatcher) { } fn setup_camel() -> (DualCaseERC1155Receiver, IERC1155ReceiverCamelDispatcher) { - let mut calldata = ArrayTrait::new(); - let target = utils::deploy(CamelERC1155ReceiverMock::TEST_CLASS_HASH, calldata); + let mut calldata = array![]; + let target = utils::declare_and_deploy("CamelERC1155ReceiverMock", calldata); ( DualCaseERC1155Receiver { contract_address: target }, IERC1155ReceiverCamelDispatcher { contract_address: target } @@ -39,18 +34,14 @@ fn setup_camel() -> (DualCaseERC1155Receiver, IERC1155ReceiverCamelDispatcher) { } fn setup_non_erc1155_receiver() -> DualCaseERC1155Receiver { - let calldata = ArrayTrait::new(); - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let calldata = array![]; + let target = utils::declare_and_deploy("NonImplementingMock", calldata); DualCaseERC1155Receiver { contract_address: target } } fn setup_erc1155_receiver_panic() -> (DualCaseERC1155Receiver, DualCaseERC1155Receiver) { - let snake_target = utils::deploy( - SnakeERC1155ReceiverPanicMock::TEST_CLASS_HASH, ArrayTrait::new() - ); - let camel_target = utils::deploy( - CamelERC1155ReceiverPanicMock::TEST_CLASS_HASH, ArrayTrait::new() - ); + let snake_target = utils::declare_and_deploy("SnakeERC1155ReceiverPanicMock", array![]); + let camel_target = utils::declare_and_deploy("CamelERC1155ReceiverPanicMock", array![]); ( DualCaseERC1155Receiver { contract_address: snake_target }, DualCaseERC1155Receiver { contract_address: camel_target } @@ -62,6 +53,7 @@ fn setup_erc1155_receiver_panic() -> (DualCaseERC1155Receiver, DualCaseERC1155Re // #[test] +#[ignore] fn test_dual_on_erc1155_received() { let (dispatcher, _) = setup_snake(); let result = dispatcher @@ -70,6 +62,7 @@ fn test_dual_on_erc1155_received() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_on_erc1155_received() { let dispatcher = setup_non_erc1155_receiver(); @@ -77,13 +70,15 @@ fn test_dual_no_on_erc1155_received() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_on_erc1155_received_exists_and_panics() { let (dispatcher, _) = setup_erc1155_receiver_panic(); dispatcher.on_erc1155_received(OPERATOR(), OWNER(), TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] +#[ignore] fn test_dual_on_erc1155_batch_received() { let (dispatcher, _) = setup_snake(); let (token_ids, values) = get_ids_and_values(); @@ -94,6 +89,7 @@ fn test_dual_on_erc1155_batch_received() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_on_erc1155_batch_received() { let dispatcher = setup_non_erc1155_receiver(); @@ -102,7 +98,8 @@ fn test_dual_no_on_erc1155_batch_received() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_on_erc1155_batch_received_exists_and_panics() { let (dispatcher, _) = setup_erc1155_receiver_panic(); let (token_ids, values) = get_ids_and_values(); @@ -114,6 +111,7 @@ fn test_dual_on_erc1155_batch_received_exists_and_panics() { // #[test] +#[ignore] fn test_dual_onERC1155Received() { let (dispatcher, _) = setup_camel(); let result = dispatcher @@ -122,13 +120,15 @@ fn test_dual_onERC1155Received() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_onERC1155Received_exists_and_panics() { let (_, dispatcher) = setup_erc1155_receiver_panic(); dispatcher.on_erc1155_received(OPERATOR(), OWNER(), TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] +#[ignore] fn test_dual_onERC1155BatchReceived() { let (dispatcher, _) = setup_camel(); let (token_ids, values) = get_ids_and_values(); @@ -139,7 +139,8 @@ fn test_dual_onERC1155BatchReceived() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_onERC1155BatchReceived_exists_and_panics() { let (_, dispatcher) = setup_erc1155_receiver_panic(); let (token_ids, values) = get_ids_and_values(); diff --git a/src/tests/token/erc1155/test_erc1155.cairo b/src/tests/token/erc1155/test_erc1155.cairo index 978bc1634..db07832e5 100644 --- a/src/tests/token/erc1155/test_erc1155.cairo +++ b/src/tests/token/erc1155/test_erc1155.cairo @@ -7,26 +7,17 @@ use openzeppelin::tests::utils::constants::{ EMPTY_DATA, ZERO, OWNER, RECIPIENT, OPERATOR, OTHER, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 }; -use openzeppelin::tests::utils; use openzeppelin::token::erc1155::ERC1155Component::ERC1155CamelImpl; -use openzeppelin::token::erc1155::ERC1155Component::{ - ERC1155Impl, ERC1155MetadataURIImpl, InternalImpl -}; -use openzeppelin::token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; +use openzeppelin::token::erc1155::ERC1155Component::{ERC1155Impl, InternalImpl}; use openzeppelin::token::erc1155::ERC1155Component; use openzeppelin::token::erc1155; -use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::ContractAddress; -use starknet::testing; use super::common::{ - assert_only_event_transfer_single, assert_only_event_transfer_batch, - assert_only_event_approval_for_all -}; -use super::common::{ - setup_account, setup_account_with_salt, setup_src5, setup_receiver, setup_camel_receiver + setup_account, deploy_another_account_at, setup_src5, setup_receiver, setup_camel_receiver }; -use super::common::{get_ids_and_values, get_ids_and_split_values}; +use super::common::{ERC1155SpyHelpers, get_ids_and_values, get_ids_and_split_values}; // // Setup @@ -50,7 +41,6 @@ fn setup() -> (ComponentState, ContractAddress) { let values = array![TOKEN_VALUE, TOKEN_VALUE_2].span(); state.batch_mint_with_acceptance_check(owner, token_ids, values, array![].span()); - utils::drop_events(ZERO(), 2); (state, owner) } @@ -152,26 +142,37 @@ fn test_balanceOfBatch_invalid_inputs() { fn test_safe_transfer_from_owner_to_receiver() { let (mut state, owner) = setup(); let recipient = setup_receiver(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_single(owner, recipient, TOKEN_ID); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_single(owner, recipient, TOKEN_ID); state.safe_transfer_from(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } #[test] +#[ignore] fn test_safe_transfer_from_owner_to_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_single(owner, recipient, TOKEN_ID); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_single(owner, recipient, TOKEN_ID); state.safe_transfer_from(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } @@ -180,26 +181,37 @@ fn test_safe_transfer_from_owner_to_camel_receiver() { fn test_safeTransferFrom_owner_to_receiver() { let (mut state, owner) = setup(); let recipient = setup_receiver(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_single(owner, recipient, TOKEN_ID); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_single(owner, recipient, TOKEN_ID); state.safeTransferFrom(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } #[test] +#[ignore] fn test_safeTransferFrom_owner_to_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_single(owner, recipient, TOKEN_ID); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_single(owner, recipient, TOKEN_ID); state.safeTransferFrom(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } @@ -207,13 +219,19 @@ fn test_safeTransferFrom_owner_to_camel_receiver() { #[test] fn test_safe_transfer_from_owner_to_account() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); - testing::set_caller_address(owner); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_single(owner, recipient, TOKEN_ID); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_single(owner, recipient, TOKEN_ID); state.safe_transfer_from(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } @@ -221,13 +239,19 @@ fn test_safe_transfer_from_owner_to_account() { #[test] fn test_safeTransferFrom_owner_to_account() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); - testing::set_caller_address(owner); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_single(owner, recipient, TOKEN_ID); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_single(owner, recipient, TOKEN_ID); state.safeTransferFrom(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } @@ -235,18 +259,24 @@ fn test_safeTransferFrom_owner_to_account() { #[test] fn test_safe_transfer_from_approved_operator() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); let operator = OPERATOR(); + let mut spy = spy_events(); + let contract_address = test_address(); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.set_approval_for_all(operator, true); - assert_only_event_approval_for_all(ZERO(), owner, operator, true); + spy.assert_only_event_approval_for_all(contract_address, owner, operator, true); assert_state_before_transfer_single(owner, recipient, TOKEN_ID); - testing::set_caller_address(operator); + start_cheat_caller_address(contract_address, operator); state.safe_transfer_from(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), operator, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, operator, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } @@ -254,18 +284,24 @@ fn test_safe_transfer_from_approved_operator() { #[test] fn test_safeTransferFrom_approved_operator() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); let operator = OPERATOR(); + let mut spy = spy_events(); + let contract_address = test_address(); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.set_approval_for_all(operator, true); - assert_only_event_approval_for_all(ZERO(), owner, operator, true); + spy.assert_only_event_approval_for_all(contract_address, owner, operator, true); assert_state_before_transfer_single(owner, recipient, TOKEN_ID); - testing::set_caller_address(operator); + start_cheat_caller_address(contract_address, operator); state.safeTransferFrom(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), operator, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, operator, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } @@ -274,7 +310,7 @@ fn test_safeTransferFrom_approved_operator() { #[should_panic(expected: ('ERC1155: invalid sender',))] fn test_safe_transfer_from_from_zero() { let (mut state, owner) = setup(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_transfer_from(ZERO(), owner, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } @@ -283,7 +319,7 @@ fn test_safe_transfer_from_from_zero() { #[should_panic(expected: ('ERC1155: invalid sender',))] fn test_safeTransferFrom_from_zero() { let (mut state, owner) = setup(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeTransferFrom(ZERO(), owner, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } @@ -292,7 +328,7 @@ fn test_safeTransferFrom_from_zero() { #[should_panic(expected: ('ERC1155: invalid receiver',))] fn test_safe_transfer_from_to_zero() { let (mut state, owner) = setup(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_transfer_from(owner, ZERO(), TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } @@ -301,7 +337,7 @@ fn test_safe_transfer_from_to_zero() { #[should_panic(expected: ('ERC1155: invalid receiver',))] fn test_safeTransferFrom_to_zero() { let (mut state, owner) = setup(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeTransferFrom(owner, ZERO(), TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } @@ -310,7 +346,7 @@ fn test_safeTransferFrom_to_zero() { #[should_panic(expected: ('ERC1155: unauthorized operator',))] fn test_safe_transfer_from_unauthorized() { let (mut state, owner) = setup(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_transfer_from(OTHER(), owner, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } @@ -319,7 +355,7 @@ fn test_safe_transfer_from_unauthorized() { #[should_panic(expected: ('ERC1155: unauthorized operator',))] fn test_safeTransferFrom_unauthorized() { let (mut state, owner) = setup(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeTransferFrom(OTHER(), owner, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } @@ -328,7 +364,7 @@ fn test_safeTransferFrom_unauthorized() { #[should_panic(expected: ('ERC1155: insufficient balance',))] fn test_safe_transfer_from_insufficient_balance() { let (mut state, owner) = setup(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_transfer_from(owner, OTHER(), TOKEN_ID, TOKEN_VALUE + 1, EMPTY_DATA()); } @@ -337,7 +373,7 @@ fn test_safe_transfer_from_insufficient_balance() { #[should_panic(expected: ('ERC1155: insufficient balance',))] fn test_safeTransferFrom_insufficient_balance() { let (mut state, owner) = setup(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeTransferFrom(owner, OTHER(), TOKEN_ID, TOKEN_VALUE + 1, EMPTY_DATA()); } @@ -347,7 +383,7 @@ fn test_safeTransferFrom_insufficient_balance() { fn test_safe_transfer_from_non_account_non_receiver() { let (mut state, owner) = setup(); let non_receiver = setup_src5(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_transfer_from(owner, non_receiver, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } @@ -357,7 +393,7 @@ fn test_safe_transfer_from_non_account_non_receiver() { fn test_safeTransferFrom_non_account_non_receiver() { let (mut state, owner) = setup(); let non_receiver = setup_src5(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeTransferFrom(owner, non_receiver, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } @@ -371,27 +407,38 @@ fn test_safe_batch_transfer_from_owner_to_receiver() { let (mut state, owner) = setup(); let recipient = setup_receiver(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_batch(owner, recipient, token_ids, values); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.safe_batch_transfer_from(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } #[test] +#[ignore] fn test_safe_batch_transfer_from_owner_to_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_batch(owner, recipient, token_ids, values); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.safe_batch_transfer_from(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } @@ -401,27 +448,38 @@ fn test_safeBatchTransferFrom_owner_to_receiver() { let (mut state, owner) = setup(); let recipient = setup_receiver(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_batch(owner, recipient, token_ids, values); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.safeBatchTransferFrom(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } #[test] +#[ignore] fn test_safeBatchTransferFrom_owner_to_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_batch(owner, recipient, token_ids, values); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.safeBatchTransferFrom(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } @@ -429,14 +487,20 @@ fn test_safeBatchTransferFrom_owner_to_camel_receiver() { #[test] fn test_safe_batch_transfer_from_owner_to_account() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_batch(owner, recipient, token_ids, values); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.safe_batch_transfer_from(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } @@ -444,14 +508,20 @@ fn test_safe_batch_transfer_from_owner_to_account() { #[test] fn test_safeBatchTransferFrom_owner_to_account() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_batch(owner, recipient, token_ids, values); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.safeBatchTransferFrom(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } @@ -460,19 +530,25 @@ fn test_safeBatchTransferFrom_owner_to_account() { #[test] fn test_safe_batch_transfer_from_approved_operator() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); let operator = OPERATOR(); let (token_ids, values) = get_ids_and_values(); + let mut spy = spy_events(); + let contract_address = test_address(); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.set_approval_for_all(operator, true); - assert_only_event_approval_for_all(ZERO(), owner, operator, true); + spy.assert_only_event_approval_for_all(contract_address, owner, operator, true); assert_state_before_transfer_batch(owner, recipient, token_ids, values); - testing::set_caller_address(operator); + start_cheat_caller_address(contract_address, operator); state.safe_batch_transfer_from(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), operator, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, operator, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } @@ -480,19 +556,25 @@ fn test_safe_batch_transfer_from_approved_operator() { #[test] fn test_safeBatchTransferFrom_approved_operator() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); let operator = OPERATOR(); let (token_ids, values) = get_ids_and_values(); + let mut spy = spy_events(); + let contract_address = test_address(); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.set_approval_for_all(operator, true); - assert_only_event_approval_for_all(ZERO(), owner, operator, true); + spy.assert_only_event_approval_for_all(contract_address, owner, operator, true); assert_state_before_transfer_batch(owner, recipient, token_ids, values); - testing::set_caller_address(operator); + start_cheat_caller_address(contract_address, operator); state.safeBatchTransferFrom(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), operator, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, operator, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } @@ -502,7 +584,8 @@ fn test_safeBatchTransferFrom_approved_operator() { fn test_safe_batch_transfer_from_from_zero() { let (mut state, owner) = setup(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + + start_cheat_caller_address(test_address(), owner); state.safe_batch_transfer_from(ZERO(), owner, token_ids, values, EMPTY_DATA()); } @@ -512,7 +595,8 @@ fn test_safe_batch_transfer_from_from_zero() { fn test_safeBatchTransferFrom_from_zero() { let (mut state, owner) = setup(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + + start_cheat_caller_address(test_address(), owner); state.safeBatchTransferFrom(ZERO(), owner, token_ids, values, EMPTY_DATA()); } @@ -522,7 +606,7 @@ fn test_safeBatchTransferFrom_from_zero() { fn test_safe_batch_transfer_from_to_zero() { let (mut state, owner) = setup(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_batch_transfer_from(owner, ZERO(), token_ids, values, EMPTY_DATA()); } @@ -532,7 +616,7 @@ fn test_safe_batch_transfer_from_to_zero() { fn test_safeBatchTransferFrom_to_zero() { let (mut state, owner) = setup(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeBatchTransferFrom(owner, ZERO(), token_ids, values, EMPTY_DATA()); } @@ -542,7 +626,7 @@ fn test_safeBatchTransferFrom_to_zero() { fn test_safe_batch_transfer_from_unauthorized() { let (mut state, owner) = setup(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_batch_transfer_from(OTHER(), owner, token_ids, values, EMPTY_DATA()); } @@ -552,7 +636,7 @@ fn test_safe_batch_transfer_from_unauthorized() { fn test_safeBatchTransferFrom_unauthorized() { let (mut state, owner) = setup(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeBatchTransferFrom(OTHER(), owner, token_ids, values, EMPTY_DATA()); } @@ -563,7 +647,7 @@ fn test_safe_batch_transfer_from_insufficient_balance() { let (mut state, owner) = setup(); let token_ids = array![TOKEN_ID, TOKEN_ID_2].span(); let values = array![TOKEN_VALUE + 1, TOKEN_VALUE_2].span(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_batch_transfer_from(owner, OTHER(), token_ids, values, EMPTY_DATA()); } @@ -574,7 +658,7 @@ fn test_safeBatchTransferFrom_insufficient_balance() { let (mut state, owner) = setup(); let token_ids = array![TOKEN_ID, TOKEN_ID_2].span(); let values = array![TOKEN_VALUE + 1, TOKEN_VALUE_2].span(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeBatchTransferFrom(owner, OTHER(), token_ids, values, EMPTY_DATA()); } @@ -585,7 +669,7 @@ fn test_safe_batch_transfer_from_non_account_non_receiver() { let (mut state, owner) = setup(); let (token_ids, values) = get_ids_and_split_values(5); let non_receiver = setup_src5(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_batch_transfer_from(owner, non_receiver, token_ids, values, EMPTY_DATA()); } @@ -596,7 +680,7 @@ fn test_safeBatchTransferFrom_non_account_non_receiver() { let (mut state, owner) = setup(); let (token_ids, values) = get_ids_and_split_values(5); let non_receiver = setup_src5(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeBatchTransferFrom(owner, non_receiver, token_ids, values, EMPTY_DATA()); } @@ -608,19 +692,22 @@ fn test_safeBatchTransferFrom_non_account_non_receiver() { #[test] fn test_set_approval_for_all_and_is_approved_for_all() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, OWNER()); let not_approved_for_all = !state.is_approved_for_all(OWNER(), OPERATOR()); assert!(not_approved_for_all); state.set_approval_for_all(OPERATOR(), true); - assert_only_event_approval_for_all(ZERO(), OWNER(), OPERATOR(), true); + spy.assert_only_event_approval_for_all(contract_address, OWNER(), OPERATOR(), true); let is_approved_for_all = state.is_approved_for_all(OWNER(), OPERATOR()); assert!(is_approved_for_all); state.set_approval_for_all(OPERATOR(), false); - assert_only_event_approval_for_all(ZERO(), OWNER(), OPERATOR(), false); + spy.assert_only_event_approval_for_all(contract_address, OWNER(), OPERATOR(), false); let not_approved_for_all = !state.is_approved_for_all(OWNER(), OPERATOR()); assert!(not_approved_for_all); @@ -630,7 +717,7 @@ fn test_set_approval_for_all_and_is_approved_for_all() { #[should_panic(expected: ('ERC1155: self approval',))] fn test_set_approval_for_all_owner_equal_operator_true() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.set_approval_for_all(OWNER(), true); } @@ -638,7 +725,7 @@ fn test_set_approval_for_all_owner_equal_operator_true() { #[should_panic(expected: ('ERC1155: self approval',))] fn test_set_approval_for_all_owner_equal_operator_false() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.set_approval_for_all(OWNER(), false); } @@ -649,19 +736,22 @@ fn test_set_approval_for_all_owner_equal_operator_false() { #[test] fn test_setApprovalForAll_and_isApprovedForAll() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, OWNER()); let not_approved_for_all = !state.isApprovedForAll(OWNER(), OPERATOR()); assert!(not_approved_for_all); state.setApprovalForAll(OPERATOR(), true); - assert_only_event_approval_for_all(ZERO(), OWNER(), OPERATOR(), true); + spy.assert_only_event_approval_for_all(contract_address, OWNER(), OPERATOR(), true); let is_approved_for_all = state.isApprovedForAll(OWNER(), OPERATOR()); assert!(is_approved_for_all); state.setApprovalForAll(OPERATOR(), false); - assert_only_event_approval_for_all(ZERO(), OWNER(), OPERATOR(), false); + spy.assert_only_event_approval_for_all(contract_address, OWNER(), OPERATOR(), false); let not_approved_for_all = !state.isApprovedForAll(OWNER(), OPERATOR()); assert!(not_approved_for_all); @@ -671,7 +761,7 @@ fn test_setApprovalForAll_and_isApprovedForAll() { #[should_panic(expected: ('ERC1155: self approval',))] fn test_setApprovalForAll_owner_equal_operator_true() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.set_approval_for_all(OWNER(), true); } @@ -679,7 +769,7 @@ fn test_setApprovalForAll_owner_equal_operator_true() { #[should_panic(expected: ('ERC1155: self approval',))] fn test_setApprovalForAll_owner_equal_operator_false() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.setApprovalForAll(OWNER(), false); } @@ -693,12 +783,17 @@ fn test_update_single_from_non_zero_to_non_zero() { let recipient = RECIPIENT(); let token_ids = array![TOKEN_ID].span(); let values = array![TOKEN_VALUE].span(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_single(owner, recipient, TOKEN_ID); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_single(owner, recipient, TOKEN_ID); state.update(owner, recipient, token_ids, values); - assert_only_event_transfer_single(ZERO(), owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } @@ -708,12 +803,17 @@ fn test_update_batch_from_non_zero_to_non_zero() { let (mut state, owner) = setup(); let recipient = RECIPIENT(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_batch(owner, recipient, token_ids, values); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.update(owner, recipient, token_ids, values); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } @@ -723,12 +823,17 @@ fn test_update_from_non_zero_to_zero() { let (mut state, owner) = setup(); let recipient = ZERO(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_batch(owner, recipient, token_ids, values); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.update(owner, recipient, token_ids, values); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_to_zero_batch(owner, recipient, token_ids); } @@ -739,12 +844,17 @@ fn test_update_from_zero_to_non_zero() { let recipient = RECIPIENT(); let sender = ZERO(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_from_zero_batch(sender, recipient, token_ids); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_from_zero_batch(sender, recipient, token_ids); state.update(sender, recipient, token_ids, values); - assert_only_event_transfer_batch(ZERO(), owner, sender, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, sender, recipient, token_ids, values + ); assert_state_after_transfer_from_zero_batch(sender, recipient, token_ids, values); } @@ -793,28 +903,39 @@ fn test_update_wac_single_from_non_zero_to_non_zero() { let recipient = setup_receiver(); let token_ids = array![TOKEN_ID].span(); let values = array![TOKEN_VALUE].span(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_single(owner, recipient, TOKEN_ID); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_single(owner, recipient, TOKEN_ID); state.update_with_acceptance_check(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } #[test] +#[ignore] fn test_update_wac_single_from_non_zero_to_non_zero_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); let token_ids = array![TOKEN_ID].span(); let values = array![TOKEN_VALUE].span(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_single(owner, recipient, TOKEN_ID); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_single(owner, recipient, TOKEN_ID); state.update_with_acceptance_check(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } @@ -822,15 +943,21 @@ fn test_update_wac_single_from_non_zero_to_non_zero_camel_receiver() { #[test] fn test_update_wac_single_from_non_zero_to_non_zero_account() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); let token_ids = array![TOKEN_ID].span(); let values = array![TOKEN_VALUE].span(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_single(owner, recipient, TOKEN_ID); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_single(owner, recipient, TOKEN_ID); state.update_with_acceptance_check(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(owner, recipient, TOKEN_ID); } @@ -840,27 +967,38 @@ fn test_update_wac_batch_from_non_zero_to_non_zero() { let (mut state, owner) = setup(); let recipient = setup_receiver(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_batch(owner, recipient, token_ids, values); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.update_with_acceptance_check(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } #[test] +#[ignore] fn test_update_wac_batch_from_non_zero_to_non_zero_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_batch(owner, recipient, token_ids, values); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.update_with_acceptance_check(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } @@ -868,25 +1006,35 @@ fn test_update_wac_batch_from_non_zero_to_non_zero_camel_receiver() { #[test] fn test_update_wac_batch_from_non_zero_to_non_zero_account() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, owner); assert_state_before_transfer_batch(owner, recipient, token_ids, values); state.update_with_acceptance_check(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, owner, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, owner, recipient, token_ids, values + ); assert_state_after_transfer_batch(owner, recipient, token_ids, values); } #[test] -#[should_panic(expected: ('CONTRACT_NOT_DEPLOYED',))] +#[should_panic( + expected: ( + "Contract not deployed at address: 0x0000000000000000000000000000000000000000000000000000000000000000", + ) +)] fn test_update_wac_from_non_zero_to_zero() { let (mut state, owner) = setup(); let recipient = ZERO(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.update_with_acceptance_check(owner, recipient, token_ids, values, EMPTY_DATA()); } @@ -897,28 +1045,39 @@ fn test_update_wac_from_zero_to_non_zero() { let recipient = setup_receiver(); let sender = ZERO(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_from_zero_batch(sender, recipient, token_ids); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_from_zero_batch(sender, recipient, token_ids); state.update_with_acceptance_check(sender, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, sender, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, sender, recipient, token_ids, values + ); assert_state_after_transfer_from_zero_batch(sender, recipient, token_ids, values); } #[test] +#[ignore] fn test_update_wac_from_zero_to_non_zero_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); let sender = ZERO(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_from_zero_batch(sender, recipient, token_ids); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_from_zero_batch(sender, recipient, token_ids); state.update_with_acceptance_check(sender, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, sender, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, sender, recipient, token_ids, values + ); assert_state_after_transfer_from_zero_batch(sender, recipient, token_ids, values); } @@ -926,15 +1085,21 @@ fn test_update_wac_from_zero_to_non_zero_camel_receiver() { #[test] fn test_update_wac_from_zero_to_non_zero_account() { let (mut state, owner) = setup(); - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); let sender = ZERO(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); - assert_state_before_transfer_from_zero_batch(sender, recipient, token_ids); + start_cheat_caller_address(contract_address, owner); + assert_state_before_transfer_from_zero_batch(sender, recipient, token_ids); state.update_with_acceptance_check(sender, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), owner, sender, recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, owner, sender, recipient, token_ids, values + ); assert_state_after_transfer_from_zero_batch(sender, recipient, token_ids, values); } @@ -979,7 +1144,7 @@ fn test_update_wac_single_to_non_receiver() { let recipient = setup_src5(); let token_ids = array![TOKEN_ID].span(); let values = array![TOKEN_VALUE].span(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.update_with_acceptance_check(owner, recipient, token_ids, values, EMPTY_DATA()); } @@ -990,7 +1155,7 @@ fn test_update_wac_batch_to_non_receiver() { let (mut state, owner) = setup(); let recipient = setup_src5(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.update_with_acceptance_check(owner, recipient, token_ids, values, EMPTY_DATA()); } @@ -1003,13 +1168,19 @@ fn test_update_wac_batch_to_non_receiver() { fn test_mint_wac_to_receiver() { let mut state = COMPONENT_STATE(); let recipient = setup_receiver(); - testing::set_caller_address(OTHER()); + let mut spy = spy_events(); + let contract_address = test_address(); + + start_cheat_caller_address(test_address(), OTHER()); let balance_of_recipient = state.balance_of(recipient, TOKEN_ID); assert!(balance_of_recipient.is_zero()); state.mint_with_acceptance_check(recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), OTHER(), ZERO(), recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, OTHER(), ZERO(), recipient, TOKEN_ID, TOKEN_VALUE + ); let balance_of_recipient = state.balance_of(recipient, TOKEN_ID); assert_eq!(balance_of_recipient, TOKEN_VALUE); @@ -1018,14 +1189,20 @@ fn test_mint_wac_to_receiver() { #[test] fn test_mint_wac_to_account() { let mut state = COMPONENT_STATE(); - let recipient = setup_account_with_salt(1); - testing::set_caller_address(OTHER()); + let recipient = setup_account(); + let mut spy = spy_events(); + let contract_address = test_address(); + + start_cheat_caller_address(test_address(), OTHER()); let balance_of_recipient = state.balance_of(recipient, TOKEN_ID); assert!(balance_of_recipient.is_zero()); state.mint_with_acceptance_check(recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(ZERO(), OTHER(), ZERO(), recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, OTHER(), ZERO(), recipient, TOKEN_ID, TOKEN_VALUE + ); let balance_of_recipient = state.balance_of(recipient, TOKEN_ID); assert_eq!(balance_of_recipient, TOKEN_VALUE); @@ -1058,7 +1235,10 @@ fn test_batch_mint_wac_to_receiver() { let mut state = COMPONENT_STATE(); let recipient = setup_receiver(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(OTHER()); + let mut spy = spy_events(); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, OTHER()); let balance_of_recipient_token_1_before = state.balance_of(recipient, TOKEN_ID); assert!(balance_of_recipient_token_1_before.is_zero()); @@ -1066,7 +1246,10 @@ fn test_batch_mint_wac_to_receiver() { assert!(balance_of_recipient_token_2_before.is_zero()); state.batch_mint_with_acceptance_check(recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), OTHER(), ZERO(), recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, OTHER(), ZERO(), recipient, token_ids, values + ); let balance_of_recipient_token_1_after = state.balance_of(recipient, TOKEN_ID); assert_eq!(balance_of_recipient_token_1_after, TOKEN_VALUE); @@ -1077,9 +1260,12 @@ fn test_batch_mint_wac_to_receiver() { #[test] fn test_batch_mint_wac_to_account() { let mut state = COMPONENT_STATE(); - let recipient = setup_account_with_salt(1); + let recipient = setup_account(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(OTHER()); + let mut spy = spy_events(); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, OTHER()); let balance_of_recipient_token_1_before = state.balance_of(recipient, TOKEN_ID); assert!(balance_of_recipient_token_1_before.is_zero()); @@ -1087,7 +1273,10 @@ fn test_batch_mint_wac_to_account() { assert!(balance_of_recipient_token_2_before.is_zero()); state.batch_mint_with_acceptance_check(recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(ZERO(), OTHER(), ZERO(), recipient, token_ids, values); + spy + .assert_only_event_transfer_batch( + contract_address, OTHER(), ZERO(), recipient, token_ids, values + ); let balance_of_recipient_token_1_after = state.balance_of(recipient, TOKEN_ID); assert_eq!(balance_of_recipient_token_1_after, TOKEN_VALUE); @@ -1122,13 +1311,19 @@ fn test_batch_mint_wac_to_non_receiver() { #[test] fn test_burn() { let (mut state, owner) = setup(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, owner); let balance_of_owner = state.balance_of(owner, TOKEN_ID); assert_eq!(balance_of_owner, TOKEN_VALUE); state.burn(owner, TOKEN_ID, TOKEN_VALUE); - assert_only_event_transfer_single(ZERO(), owner, owner, ZERO(), TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract_address, owner, owner, ZERO(), TOKEN_ID, TOKEN_VALUE + ); let balance_of_owner = state.balance_of(owner, TOKEN_ID); assert!(balance_of_owner.is_zero()); @@ -1146,7 +1341,10 @@ fn test_burn_from_zero() { fn test_batch_burn() { let (mut state, owner) = setup(); let (token_ids, values) = get_ids_and_values(); - testing::set_caller_address(owner); + let mut spy = spy_events(); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, owner); let balance_of_owner_token_1_before = state.balance_of(owner, TOKEN_ID); assert_eq!(balance_of_owner_token_1_before, TOKEN_VALUE); @@ -1154,7 +1352,7 @@ fn test_batch_burn() { assert_eq!(balance_of_owner_token_2_before, TOKEN_VALUE_2); state.batch_burn(owner, token_ids, values); - assert_only_event_transfer_batch(ZERO(), owner, owner, ZERO(), token_ids, values); + spy.assert_only_event_transfer_batch(contract_address, owner, owner, ZERO(), token_ids, values); let balance_of_owner_token_1_after = state.balance_of(owner, TOKEN_ID); assert!(balance_of_owner_token_1_after.is_zero()); diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo index 34b29154d..64abc3023 100644 --- a/src/tests/utils.cairo +++ b/src/tests/utils.cairo @@ -2,6 +2,8 @@ pub(crate) mod common; pub(crate) mod constants; pub(crate) mod events; pub(crate) mod signing; -pub use common::{declare_class, declare_and_deploy, declare_and_deploy_at, deploy, deploy_at}; +pub use common::{ + declare_class, declare_and_deploy, declare_and_deploy_at, deploy, deploy_at, deploy_another_at +}; pub use events::EventSpyExt; diff --git a/src/tests/utils/common.cairo b/src/tests/utils/common.cairo index 27a7698db..88c443cfb 100644 --- a/src/tests/utils/common.cairo +++ b/src/tests/utils/common.cairo @@ -1,4 +1,5 @@ -use snforge_std::{declare, ContractClass, ContractClassTrait}; +use core::starknet::SyscallResultTrait; +use snforge_std::{declare, get_class_hash, ContractClass, ContractClassTrait}; use starknet::ContractAddress; pub fn deploy(contract_class: ContractClass, calldata: Array) -> ContractAddress { @@ -17,18 +18,27 @@ pub fn deploy_at( }; } +/// Deploys a contract from the class hash of another contract which is already deployed. +pub fn deploy_another_at( + existing: ContractAddress, target_address: ContractAddress, calldata: Array +) { + let class_hash = get_class_hash(existing); + let contract_class = ContractClassTrait::new(class_hash); + deploy_at(contract_class, target_address, calldata) +} + pub fn declare_class(contract_name: ByteArray) -> ContractClass { - declare(contract_name).unwrap() + declare(contract_name).unwrap_syscall() } pub fn declare_and_deploy(contract_name: ByteArray, calldata: Array) -> ContractAddress { - let contract_class = declare(contract_name).unwrap(); + let contract_class = declare(contract_name).unwrap_syscall(); deploy(contract_class, calldata) } pub fn declare_and_deploy_at( contract_name: ByteArray, target_address: ContractAddress, calldata: Array ) { - let contract_class = declare(contract_name).expect('Failed to declare contract'); + let contract_class = declare(contract_name).unwrap_syscall(); deploy_at(contract_class, target_address, calldata) } From ef89fb273f1dbe5353000c6440b42a95078c269d Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 11 Jul 2024 13:25:17 +0200 Subject: [PATCH 08/45] Migrate erc721 tests (#1027) * feat: migrate event tests * feat: update workflow * feat: add foundry utils * feat: finish erc20 and erc20votes migration * feat: remove dual case tests * refactor: format files * refactor: variable name * Update src/tests/token.cairo Co-authored-by: Andrew Fleming * Update src/tests/token/erc20.cairo Co-authored-by: Andrew Fleming * Update src/tests/utils/foundry.cairo Co-authored-by: Andrew Fleming * Update src/tests/token/erc20/test_erc20_votes.cairo Co-authored-by: Andrew Fleming * feat: apply review updates * feat: migrate erc721 components tests * refactor: remove extra line * feat: apply review updates * feat: update utilities * feat: apply review updates * fix: ignore tests --------- Co-authored-by: Andrew Fleming --- src/tests/token.cairo | 2 +- src/tests/token/erc20/common.cairo | 1 - src/tests/token/erc721.cairo | 1 + src/tests/token/erc721/common.cairo | 131 ++--- src/tests/token/erc721/test_dual721.cairo | 135 +++-- .../token/erc721/test_dual721_receiver.cairo | 35 +- src/tests/token/erc721/test_erc721.cairo | 480 +++++++++++------- .../token/erc721/test_erc721_receiver.cairo | 2 +- 8 files changed, 473 insertions(+), 314 deletions(-) diff --git a/src/tests/token.cairo b/src/tests/token.cairo index 2ecd8ae11..04f631ea8 100644 --- a/src/tests/token.cairo +++ b/src/tests/token.cairo @@ -1,3 +1,3 @@ pub(crate) mod erc1155; -// pub(crate) mod erc721; pub(crate) mod erc20; +pub(crate) mod erc721; diff --git a/src/tests/token/erc20/common.cairo b/src/tests/token/erc20/common.cairo index be65d0241..a50e5ff2e 100644 --- a/src/tests/token/erc20/common.cairo +++ b/src/tests/token/erc20/common.cairo @@ -1,7 +1,6 @@ use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::token::erc20::ERC20Component::{Approval, Transfer}; use openzeppelin::token::erc20::ERC20Component; -use openzeppelin::utils::serde::SerializedAppend; use snforge_std::EventSpy; use starknet::ContractAddress; diff --git a/src/tests/token/erc721.cairo b/src/tests/token/erc721.cairo index 0f6616806..d8b44e48b 100644 --- a/src/tests/token/erc721.cairo +++ b/src/tests/token/erc721.cairo @@ -3,3 +3,4 @@ pub(crate) mod common; mod test_dual721; mod test_dual721_receiver; mod test_erc721; +mod test_erc721_receiver; diff --git a/src/tests/token/erc721/common.cairo b/src/tests/token/erc721/common.cairo index a6601e5e1..97e94f886 100644 --- a/src/tests/token/erc721/common.cairo +++ b/src/tests/token/erc721/common.cairo @@ -1,75 +1,76 @@ -use openzeppelin::tests::utils; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::token::erc721::ERC721Component::{Approval, ApprovalForAll, Transfer}; use openzeppelin::token::erc721::ERC721Component; -use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::EventSpy; use starknet::ContractAddress; -pub(crate) fn assert_event_approval_for_all( - contract: ContractAddress, owner: ContractAddress, operator: ContractAddress, approved: bool -) { - let event = utils::pop_log::(contract).unwrap(); - let expected = ERC721Component::Event::ApprovalForAll( - ApprovalForAll { owner, operator, approved } - ); - assert!(event == expected); +#[generate_trait] +pub(crate) impl ERC721SpyHelpersImpl of ERC721SpyHelpers { + fn assert_event_approval_for_all( + ref self: EventSpy, + contract: ContractAddress, + owner: ContractAddress, + operator: ContractAddress, + approved: bool + ) { + let expected = ERC721Component::Event::ApprovalForAll( + ApprovalForAll { owner, operator, approved } + ); + self.assert_emitted_single(contract, expected); + } - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("ApprovalForAll")); - indexed_keys.append_serde(owner); - indexed_keys.append_serde(operator); - utils::assert_indexed_keys(event, indexed_keys.span()); -} - -pub(crate) fn assert_only_event_approval_for_all( - contract: ContractAddress, owner: ContractAddress, operator: ContractAddress, approved: bool -) { - assert_event_approval_for_all(contract, owner, operator, approved); - utils::assert_no_events_left(contract); -} - -pub(crate) fn assert_event_approval( - contract: ContractAddress, owner: ContractAddress, approved: ContractAddress, token_id: u256 -) { - let event = utils::pop_log::(contract).unwrap(); - let expected = ERC721Component::Event::Approval(Approval { owner, approved, token_id }); - assert!(event == expected); + fn assert_only_event_approval_for_all( + ref self: EventSpy, + contract: ContractAddress, + owner: ContractAddress, + operator: ContractAddress, + approved: bool + ) { + self.assert_event_approval_for_all(contract, owner, operator, approved); + self.assert_no_events_left_from(contract); + } - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("Approval")); - indexed_keys.append_serde(owner); - indexed_keys.append_serde(approved); - indexed_keys.append_serde(token_id); - utils::assert_indexed_keys(event, indexed_keys.span()); -} - -pub(crate) fn assert_only_event_approval( - contract: ContractAddress, owner: ContractAddress, approved: ContractAddress, token_id: u256 -) { - assert_event_approval(contract, owner, approved, token_id); - utils::assert_no_events_left(contract); -} + fn assert_event_approval( + ref self: EventSpy, + contract: ContractAddress, + owner: ContractAddress, + approved: ContractAddress, + token_id: u256 + ) { + let expected = ERC721Component::Event::Approval(Approval { owner, approved, token_id }); + self.assert_emitted_single(contract, expected); + } -pub(crate) fn assert_event_transfer( - contract: ContractAddress, from: ContractAddress, to: ContractAddress, token_id: u256 -) { - let event = utils::pop_log::(contract).unwrap(); - let expected = ERC721Component::Event::Transfer(Transfer { from, to, token_id }); - assert!(event == expected); + fn assert_only_event_approval( + ref self: EventSpy, + contract: ContractAddress, + owner: ContractAddress, + approved: ContractAddress, + token_id: u256 + ) { + self.assert_event_approval(contract, owner, approved, token_id); + self.assert_no_events_left_from(contract); + } - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("Transfer")); - indexed_keys.append_serde(from); - indexed_keys.append_serde(to); - indexed_keys.append_serde(token_id); - utils::assert_indexed_keys(event, indexed_keys.span()); -} + fn assert_event_transfer( + ref self: EventSpy, + contract: ContractAddress, + from: ContractAddress, + to: ContractAddress, + token_id: u256 + ) { + let expected = ERC721Component::Event::Transfer(Transfer { from, to, token_id }); + self.assert_emitted_single(contract, expected); + } -pub(crate) fn assert_only_event_transfer( - contract: ContractAddress, from: ContractAddress, to: ContractAddress, token_id: u256 -) { - assert_event_transfer(contract, from, to, token_id); - utils::assert_no_events_left(contract); + fn assert_only_event_transfer( + ref self: EventSpy, + contract: ContractAddress, + from: ContractAddress, + to: ContractAddress, + token_id: u256 + ) { + self.assert_event_transfer(contract, from, to, token_id); + self.assert_no_events_left_from(contract); + } } diff --git a/src/tests/token/erc721/test_dual721.cairo b/src/tests/token/erc721/test_dual721.cairo index 4cf393bf7..943608c9e 100644 --- a/src/tests/token/erc721/test_dual721.cairo +++ b/src/tests/token/erc721/test_dual721.cairo @@ -1,9 +1,5 @@ -use openzeppelin::tests::mocks::erc721_mocks::{CamelERC721Mock, SnakeERC721Mock}; -use openzeppelin::tests::mocks::erc721_mocks::{CamelERC721PanicMock, SnakeERC721PanicMock}; -use openzeppelin::tests::mocks::erc721_receiver_mocks::DualCaseERC721ReceiverMock; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::utils::constants::{ - DATA, OWNER, RECIPIENT, SPENDER, OPERATOR, OTHER, NAME, SYMBOL, BASE_URI, TOKEN_ID + DATA, OWNER, RECIPIENT, SPENDER, OPERATOR, NAME, SYMBOL, BASE_URI, TOKEN_ID }; use openzeppelin::tests::utils; use openzeppelin::token::erc721::dual721::{DualCaseERC721, DualCaseERC721Trait}; @@ -13,9 +9,8 @@ use openzeppelin::token::erc721::interface::{ }; use openzeppelin::token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::{test_address, start_cheat_caller_address}; use starknet::ContractAddress; -use starknet::testing::set_caller_address; -use starknet::testing::set_contract_address; // // Setup @@ -28,8 +23,9 @@ fn setup_snake() -> (DualCaseERC721, IERC721Dispatcher) { calldata.append_serde(BASE_URI()); calldata.append_serde(OWNER()); calldata.append_serde(TOKEN_ID); - set_contract_address(OWNER()); - let target = utils::deploy(SnakeERC721Mock::TEST_CLASS_HASH, calldata); + + start_cheat_caller_address(test_address(), OWNER()); + let target = utils::declare_and_deploy("SnakeERC721Mock", calldata); (DualCaseERC721 { contract_address: target }, IERC721Dispatcher { contract_address: target }) } @@ -40,8 +36,9 @@ fn setup_camel() -> (DualCaseERC721, IERC721CamelOnlyDispatcher) { calldata.append_serde(BASE_URI()); calldata.append_serde(OWNER()); calldata.append_serde(TOKEN_ID); - set_contract_address(OWNER()); - let target = utils::deploy(CamelERC721Mock::TEST_CLASS_HASH, calldata); + + start_cheat_caller_address(test_address(), OWNER()); + let target = utils::declare_and_deploy("CamelERC721Mock", calldata); ( DualCaseERC721 { contract_address: target }, IERC721CamelOnlyDispatcher { contract_address: target } @@ -50,13 +47,13 @@ fn setup_camel() -> (DualCaseERC721, IERC721CamelOnlyDispatcher) { fn setup_non_erc721() -> DualCaseERC721 { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("NonImplementingMock", calldata); DualCaseERC721 { contract_address: target } } fn setup_erc721_panic() -> (DualCaseERC721, DualCaseERC721) { - let snake_target = utils::deploy(SnakeERC721PanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelERC721PanicMock::TEST_CLASS_HASH, array![]); + let snake_target = utils::declare_and_deploy("SnakeERC721PanicMock", array![]); + let camel_target = utils::declare_and_deploy("CamelERC721PanicMock", array![]); ( DualCaseERC721 { contract_address: snake_target }, DualCaseERC721 { contract_address: camel_target } @@ -64,7 +61,7 @@ fn setup_erc721_panic() -> (DualCaseERC721, DualCaseERC721) { } fn setup_receiver() -> ContractAddress { - utils::deploy(DualCaseERC721ReceiverMock::TEST_CLASS_HASH, array![]) + utils::declare_and_deploy("DualCaseERC721ReceiverMock", array![]) } // @@ -72,6 +69,8 @@ fn setup_receiver() -> ContractAddress { // #[test] +#[ignore] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_name() { let (snake_dispatcher, _) = setup_snake(); let (camel_dispatcher, _) = setup_camel(); @@ -80,6 +79,7 @@ fn test_dual_name() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_name() { let dispatcher = setup_non_erc721(); @@ -87,13 +87,14 @@ fn test_dual_no_name() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_name_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.name(); } #[test] +#[ignore] fn test_dual_symbol() { let (snake_dispatcher, _) = setup_snake(); let (camel_dispatcher, _) = setup_camel(); @@ -102,6 +103,7 @@ fn test_dual_symbol() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_symbol() { let dispatcher = setup_non_erc721(); @@ -109,26 +111,30 @@ fn test_dual_no_symbol() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_symbol_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.symbol(); } #[test] +#[ignore] fn test_dual_approve() { let (snake_dispatcher, snake_target) = setup_snake(); - set_contract_address(OWNER()); + + start_cheat_caller_address(test_address(), OWNER()); snake_dispatcher.approve(SPENDER(), TOKEN_ID); assert_eq!(snake_target.get_approved(TOKEN_ID), SPENDER()); let (camel_dispatcher, camel_target) = setup_camel(); - set_contract_address(OWNER()); + + start_cheat_caller_address(test_address(), OWNER()); camel_dispatcher.approve(SPENDER(), TOKEN_ID); assert_eq!(camel_target.getApproved(TOKEN_ID), SPENDER()); } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_approve() { let dispatcher = setup_non_erc721(); @@ -136,7 +142,7 @@ fn test_dual_no_approve() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_approve_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.approve(SPENDER(), TOKEN_ID); @@ -147,12 +153,14 @@ fn test_dual_approve_exists_and_panics() { // #[test] +#[ignore] fn test_dual_balance_of() { let (dispatcher, _) = setup_snake(); assert_eq!(dispatcher.balance_of(OWNER()), 1); } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_balance_of() { let dispatcher = setup_non_erc721(); @@ -160,19 +168,21 @@ fn test_dual_no_balance_of() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_balance_of_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.balance_of(OWNER()); } #[test] +#[ignore] fn test_dual_owner_of() { let (dispatcher, _) = setup_snake(); assert_eq!(dispatcher.owner_of(TOKEN_ID), OWNER()); } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_owner_of() { let dispatcher = setup_non_erc721(); @@ -180,13 +190,14 @@ fn test_dual_no_owner_of() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_owner_of_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.owner_of(TOKEN_ID); } #[test] +#[ignore] fn test_dual_transfer_from() { let (dispatcher, target) = setup_snake(); dispatcher.transfer_from(OWNER(), RECIPIENT(), TOKEN_ID); @@ -194,6 +205,7 @@ fn test_dual_transfer_from() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_transfer_from() { let dispatcher = setup_non_erc721(); @@ -201,13 +213,14 @@ fn test_dual_no_transfer_from() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_transfer_from_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.transfer_from(OWNER(), RECIPIENT(), TOKEN_ID); } #[test] +#[ignore] fn test_dual_safe_transfer_from() { let (dispatcher, target) = setup_snake(); let receiver = setup_receiver(); @@ -216,6 +229,7 @@ fn test_dual_safe_transfer_from() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_safe_transfer_from() { let dispatcher = setup_non_erc721(); @@ -223,21 +237,24 @@ fn test_dual_no_safe_transfer_from() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_safe_transfer_from_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.safe_transfer_from(OWNER(), RECIPIENT(), TOKEN_ID, DATA(true)); } #[test] +#[ignore] fn test_dual_get_approved() { let (dispatcher, target) = setup_snake(); - set_contract_address(OWNER()); + + start_cheat_caller_address(test_address(), OWNER()); target.approve(SPENDER(), TOKEN_ID); assert_eq!(dispatcher.get_approved(TOKEN_ID), SPENDER()); } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_get_approved() { let dispatcher = setup_non_erc721(); @@ -245,16 +262,18 @@ fn test_dual_no_get_approved() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_get_approved_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.get_approved(TOKEN_ID); } #[test] +#[ignore] fn test_dual_set_approval_for_all() { let (dispatcher, target) = setup_snake(); - set_contract_address(OWNER()); + + start_cheat_caller_address(test_address(), OWNER()); dispatcher.set_approval_for_all(OPERATOR(), true); let is_approved_for_all = target.is_approved_for_all(OWNER(), OPERATOR()); @@ -262,6 +281,7 @@ fn test_dual_set_approval_for_all() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_set_approval_for_all() { let dispatcher = setup_non_erc721(); @@ -269,16 +289,18 @@ fn test_dual_no_set_approval_for_all() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_set_approval_for_all_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.set_approval_for_all(OPERATOR(), true); } #[test] +#[ignore] fn test_dual_is_approved_for_all() { let (dispatcher, target) = setup_snake(); - set_contract_address(OWNER()); + + start_cheat_caller_address(test_address(), OWNER()); target.set_approval_for_all(OPERATOR(), true); let is_approved_for_all = dispatcher.is_approved_for_all(OWNER(), OPERATOR()); @@ -286,6 +308,7 @@ fn test_dual_is_approved_for_all() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_is_approved_for_all() { let dispatcher = setup_non_erc721(); @@ -293,13 +316,14 @@ fn test_dual_no_is_approved_for_all() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_is_approved_for_all_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.is_approved_for_all(OWNER(), OPERATOR()); } #[test] +#[ignore] fn test_dual_token_uri() { let (dispatcher, _) = setup_snake(); let uri = dispatcher.token_uri(TOKEN_ID); @@ -308,6 +332,7 @@ fn test_dual_token_uri() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_token_uri() { let dispatcher = setup_non_erc721(); @@ -315,13 +340,14 @@ fn test_dual_no_token_uri() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_token_uri_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.token_uri(TOKEN_ID); } #[test] +#[ignore] fn test_dual_supports_interface() { let (dispatcher, _) = setup_snake(); let supports_ierc721 = dispatcher.supports_interface(IERC721_ID); @@ -329,6 +355,7 @@ fn test_dual_supports_interface() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_supports_interface() { let dispatcher = setup_non_erc721(); @@ -336,7 +363,7 @@ fn test_dual_no_supports_interface() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_supports_interface_exists_and_panics() { let (dispatcher, _) = setup_erc721_panic(); dispatcher.supports_interface(IERC721_ID); @@ -347,19 +374,22 @@ fn test_dual_supports_interface_exists_and_panics() { // #[test] +#[ignore] fn test_dual_balanceOf() { let (dispatcher, _) = setup_camel(); assert_eq!(dispatcher.balance_of(OWNER()), 1); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_balanceOf_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); dispatcher.balance_of(OWNER()); } #[test] +#[ignore] fn test_dual_ownerOf() { let (dispatcher, _) = setup_camel(); let current_owner = dispatcher.owner_of(TOKEN_ID); @@ -367,16 +397,19 @@ fn test_dual_ownerOf() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_ownerOf_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); dispatcher.owner_of(TOKEN_ID); } #[test] +#[ignore] fn test_dual_transferFrom() { let (dispatcher, target) = setup_camel(); - set_contract_address(OWNER()); + + start_cheat_caller_address(test_address(), OWNER()); dispatcher.transfer_from(OWNER(), RECIPIENT(), TOKEN_ID); let current_owner = target.ownerOf(TOKEN_ID); @@ -384,13 +417,15 @@ fn test_dual_transferFrom() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_transferFrom_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); dispatcher.transfer_from(OWNER(), RECIPIENT(), TOKEN_ID); } #[test] +#[ignore] fn test_dual_safeTransferFrom() { let (dispatcher, target) = setup_camel(); let receiver = setup_receiver(); @@ -401,16 +436,19 @@ fn test_dual_safeTransferFrom() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_safeTransferFrom_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); dispatcher.safe_transfer_from(OWNER(), RECIPIENT(), TOKEN_ID, DATA(true)); } #[test] +#[ignore] fn test_dual_getApproved() { let (dispatcher, _) = setup_camel(); - set_contract_address(OWNER()); + + start_cheat_caller_address(test_address(), OWNER()); dispatcher.approve(SPENDER(), TOKEN_ID); let approved = dispatcher.get_approved(TOKEN_ID); @@ -418,16 +456,19 @@ fn test_dual_getApproved() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_getApproved_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); dispatcher.get_approved(TOKEN_ID); } #[test] +#[ignore] fn test_dual_setApprovalForAll() { let (dispatcher, target) = setup_camel(); - set_contract_address(OWNER()); + + start_cheat_caller_address(test_address(), OWNER()); dispatcher.set_approval_for_all(OPERATOR(), true); let is_approved_for_all = target.isApprovedForAll(OWNER(), OPERATOR()); @@ -435,16 +476,19 @@ fn test_dual_setApprovalForAll() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_setApprovalForAll_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); dispatcher.set_approval_for_all(OPERATOR(), true); } #[test] +#[ignore] fn test_dual_isApprovedForAll() { let (dispatcher, target) = setup_camel(); - set_contract_address(OWNER()); + + start_cheat_caller_address(test_address(), OWNER()); target.setApprovalForAll(OPERATOR(), true); let is_approved_for_all = dispatcher.is_approved_for_all(OWNER(), OPERATOR()); @@ -452,13 +496,15 @@ fn test_dual_isApprovedForAll() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_isApprovedForAll_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); dispatcher.is_approved_for_all(OWNER(), OPERATOR()); } #[test] +#[ignore] fn test_dual_tokenURI() { let (dispatcher, _) = setup_camel(); let uri = dispatcher.token_uri(TOKEN_ID); @@ -467,7 +513,8 @@ fn test_dual_tokenURI() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_tokenURI_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); dispatcher.token_uri(TOKEN_ID); diff --git a/src/tests/token/erc721/test_dual721_receiver.cairo b/src/tests/token/erc721/test_dual721_receiver.cairo index b201b14d3..f70d232d8 100644 --- a/src/tests/token/erc721/test_dual721_receiver.cairo +++ b/src/tests/token/erc721/test_dual721_receiver.cairo @@ -1,10 +1,3 @@ -use openzeppelin::tests::mocks::erc721_receiver_mocks::{ - CamelERC721ReceiverMock, CamelERC721ReceiverPanicMock -}; -use openzeppelin::tests::mocks::erc721_receiver_mocks::{ - SnakeERC721ReceiverMock, SnakeERC721ReceiverPanicMock -}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::utils::constants::{DATA, OPERATOR, OWNER, TOKEN_ID}; use openzeppelin::tests::utils; use openzeppelin::token::erc721::dual721_receiver::{ @@ -23,8 +16,8 @@ use openzeppelin::token::erc721::interface::{ // fn setup_snake() -> (DualCaseERC721Receiver, IERC721ReceiverDispatcher) { - let mut calldata = ArrayTrait::new(); - let target = utils::deploy(SnakeERC721ReceiverMock::TEST_CLASS_HASH, calldata); + let calldata = array![]; + let target = utils::declare_and_deploy("SnakeERC721ReceiverMock", calldata); ( DualCaseERC721Receiver { contract_address: target }, IERC721ReceiverDispatcher { contract_address: target } @@ -32,8 +25,8 @@ fn setup_snake() -> (DualCaseERC721Receiver, IERC721ReceiverDispatcher) { } fn setup_camel() -> (DualCaseERC721Receiver, IERC721ReceiverCamelDispatcher) { - let mut calldata = ArrayTrait::new(); - let target = utils::deploy(CamelERC721ReceiverMock::TEST_CLASS_HASH, calldata); + let calldata = array![]; + let target = utils::declare_and_deploy("CamelERC721ReceiverMock", calldata); ( DualCaseERC721Receiver { contract_address: target }, IERC721ReceiverCamelDispatcher { contract_address: target } @@ -41,18 +34,14 @@ fn setup_camel() -> (DualCaseERC721Receiver, IERC721ReceiverCamelDispatcher) { } fn setup_non_erc721_receiver() -> DualCaseERC721Receiver { - let calldata = ArrayTrait::new(); - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let calldata = array![]; + let target = utils::declare_and_deploy("NonImplementingMock", calldata); DualCaseERC721Receiver { contract_address: target } } fn setup_erc721_receiver_panic() -> (DualCaseERC721Receiver, DualCaseERC721Receiver) { - let snake_target = utils::deploy( - SnakeERC721ReceiverPanicMock::TEST_CLASS_HASH, ArrayTrait::new() - ); - let camel_target = utils::deploy( - CamelERC721ReceiverPanicMock::TEST_CLASS_HASH, ArrayTrait::new() - ); + let snake_target = utils::declare_and_deploy("SnakeERC721ReceiverPanicMock", array![]); + let camel_target = utils::declare_and_deploy("CamelERC721ReceiverPanicMock", array![]); ( DualCaseERC721Receiver { contract_address: snake_target }, DualCaseERC721Receiver { contract_address: camel_target } @@ -73,6 +62,7 @@ fn test_dual_on_erc721_received() { } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_on_erc721_received() { let dispatcher = setup_non_erc721_receiver(); @@ -80,7 +70,8 @@ fn test_dual_no_on_erc721_received() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_on_erc721_received_exists_and_panics() { let (dispatcher, _) = setup_erc721_receiver_panic(); dispatcher.on_erc721_received(OPERATOR(), OWNER(), TOKEN_ID, DATA(true)); @@ -91,6 +82,7 @@ fn test_dual_on_erc721_received_exists_and_panics() { // #[test] +#[ignore] fn test_dual_onERC721Received() { let (dispatcher, _) = setup_camel(); @@ -100,7 +92,8 @@ fn test_dual_onERC721Received() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_onERC721Received_exists_and_panics() { let (_, dispatcher) = setup_erc721_receiver_panic(); dispatcher.on_erc721_received(OPERATOR(), OWNER(), TOKEN_ID, DATA(true)); diff --git a/src/tests/token/erc721/test_erc721.cairo b/src/tests/token/erc721/test_erc721.cairo index 7dd5ae1bf..365e8c942 100644 --- a/src/tests/token/erc721/test_erc721.cairo +++ b/src/tests/token/erc721/test_erc721.cairo @@ -1,34 +1,22 @@ use core::num::traits::Zero; -use openzeppelin::account::AccountComponent; use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; -use openzeppelin::introspection::src5; use openzeppelin::introspection; -use openzeppelin::tests::mocks::account_mocks::{DualCaseAccountMock, CamelAccountMock}; use openzeppelin::tests::mocks::erc721_mocks::DualCaseERC721Mock; -use openzeppelin::tests::mocks::erc721_receiver_mocks::{ - CamelERC721ReceiverMock, SnakeERC721ReceiverMock -}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::utils::constants::{ DATA, ZERO, OWNER, CALLER, RECIPIENT, SPENDER, OPERATOR, OTHER, NAME, SYMBOL, TOKEN_ID, TOKEN_ID_2, PUBKEY, BASE_URI, BASE_URI_2 }; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::tests::utils; -use openzeppelin::token::erc721::ERC721Component::{ - ERC721CamelOnlyImpl, ERC721MetadataCamelOnlyImpl -}; -use openzeppelin::token::erc721::ERC721Component::{ERC721Impl, ERC721MetadataImpl, InternalImpl}; +use openzeppelin::token::erc721::ERC721Component::{ERC721Impl, ERC721CamelOnlyImpl}; +use openzeppelin::token::erc721::ERC721Component::{ERC721MetadataImpl, InternalImpl}; use openzeppelin::token::erc721::ERC721Component; -use openzeppelin::token::erc721::interface::IERC721; use openzeppelin::token::erc721; +use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::ContractAddress; -use starknet::contract_address_const; use starknet::storage::StorageMapMemberAccessTrait; -use starknet::testing; -use super::common::{ - assert_only_event_approval, assert_only_event_approval_for_all, assert_only_event_transfer, -}; +use super::common::ERC721SpyHelpers; // // Setup @@ -47,26 +35,25 @@ fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(OWNER(), TOKEN_ID); - utils::drop_event(ZERO()); state } fn setup_receiver() -> ContractAddress { - utils::deploy(SnakeERC721ReceiverMock::TEST_CLASS_HASH, array![]) + utils::declare_and_deploy("SnakeERC721ReceiverMock", array![]) } fn setup_camel_receiver() -> ContractAddress { - utils::deploy(CamelERC721ReceiverMock::TEST_CLASS_HASH, array![]) + utils::declare_and_deploy("CamelERC721ReceiverMock", array![]) } fn setup_account() -> ContractAddress { - let mut calldata = array![PUBKEY]; - utils::deploy(DualCaseAccountMock::TEST_CLASS_HASH, calldata) + let calldata = array![PUBKEY]; + utils::declare_and_deploy("DualCaseAccountMock", calldata) } fn setup_camel_account() -> ContractAddress { - let mut calldata = array![PUBKEY]; - utils::deploy(CamelAccountMock::TEST_CLASS_HASH, calldata) + let calldata = array![PUBKEY]; + utils::declare_and_deploy("CamelAccountMock", calldata) } // @@ -177,10 +164,13 @@ fn test_get_approved_nonexistent() { #[test] fn test_approve_from_owner() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(contract_address, OWNER()); state.approve(SPENDER(), TOKEN_ID); - assert_only_event_approval(ZERO(), OWNER(), SPENDER(), TOKEN_ID); + + spy.assert_only_event_approval(contract_address, OWNER(), SPENDER(), TOKEN_ID); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -189,14 +179,16 @@ fn test_approve_from_owner() { #[test] fn test_approve_from_operator() { let mut state = setup(); + let contract_address = test_address(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(contract_address, OWNER()); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.approve(SPENDER(), TOKEN_ID); - assert_only_event_approval(ZERO(), OWNER(), SPENDER(), TOKEN_ID); + spy.assert_only_event_approval(contract_address, OWNER(), SPENDER(), TOKEN_ID); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -207,7 +199,7 @@ fn test_approve_from_operator() { fn test_approve_from_unauthorized() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.approve(SPENDER(), TOKEN_ID); } @@ -221,8 +213,11 @@ fn test_approve_nonexistent() { #[test] fn test__approve() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); + state._approve(SPENDER(), TOKEN_ID, ZERO()); - assert_only_event_approval(ZERO(), OWNER(), SPENDER(), TOKEN_ID); + spy.assert_only_event_approval(contract_address, OWNER(), SPENDER(), TOKEN_ID); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -238,8 +233,11 @@ fn test__approve_nonexistent() { #[test] fn test__approve_auth_is_owner() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); + state._approve(SPENDER(), TOKEN_ID, OWNER()); - assert_only_event_approval(ZERO(), OWNER(), SPENDER(), TOKEN_ID); + spy.assert_only_event_approval(contract_address, OWNER(), SPENDER(), TOKEN_ID); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -248,13 +246,16 @@ fn test__approve_auth_is_owner() { #[test] fn test__approve_auth_is_approved_for_all() { let mut state = setup(); + let contract_address = test_address(); let auth = CALLER(); - testing::set_caller_address(OWNER()); + + start_cheat_caller_address(contract_address, OWNER()); state.set_approval_for_all(auth, true); - utils::drop_event(ZERO()); + + let mut spy = spy_events(); state._approve(SPENDER(), TOKEN_ID, auth); - assert_only_event_approval(ZERO(), OWNER(), SPENDER(), TOKEN_ID); + spy.assert_only_event_approval(contract_address, OWNER(), SPENDER(), TOKEN_ID); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -274,19 +275,21 @@ fn test__approve_auth_not_authorized() { #[test] fn test_set_approval_for_all() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + let contract_address = test_address(); + let mut spy = spy_events(); + start_cheat_caller_address(contract_address, OWNER()); let not_approved_for_all = !state.is_approved_for_all(OWNER(), OPERATOR()); assert!(not_approved_for_all); state.set_approval_for_all(OPERATOR(), true); - assert_only_event_approval_for_all(ZERO(), OWNER(), OPERATOR(), true); + spy.assert_only_event_approval_for_all(contract_address, OWNER(), OPERATOR(), true); let is_approved_for_all = state.is_approved_for_all(OWNER(), OPERATOR()); assert!(is_approved_for_all); state.set_approval_for_all(OPERATOR(), false); - assert_only_event_approval_for_all(ZERO(), OWNER(), OPERATOR(), false); + spy.assert_only_event_approval_for_all(contract_address, OWNER(), OPERATOR(), false); let not_approved_for_all = !state.is_approved_for_all(OWNER(), OPERATOR()); assert!(not_approved_for_all); @@ -302,18 +305,20 @@ fn test_set_approval_for_all_invalid_operator() { #[test] fn test__set_approval_for_all() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); + let mut spy = spy_events(); let not_approved_for_all = !state.is_approved_for_all(OWNER(), OPERATOR()); assert!(not_approved_for_all); state._set_approval_for_all(OWNER(), OPERATOR(), true); - assert_only_event_approval_for_all(ZERO(), OWNER(), OPERATOR(), true); + spy.assert_only_event_approval_for_all(contract_address, OWNER(), OPERATOR(), true); let is_approved_for_all = state.is_approved_for_all(OWNER(), OPERATOR()); assert!(is_approved_for_all); state._set_approval_for_all(OWNER(), OPERATOR(), false); - assert_only_event_approval_for_all(ZERO(), OWNER(), OPERATOR(), false); + spy.assert_only_event_approval_for_all(contract_address, OWNER(), OPERATOR(), false); let not_approved_for_all = !state.is_approved_for_all(OWNER(), OPERATOR()); assert!(not_approved_for_all); @@ -333,21 +338,24 @@ fn test__set_approval_for_all_invalid_operator() { #[test] fn test_transfer_from_owner() { let mut state = setup(); + let contract_address = test_address(); let token_id = TOKEN_ID; let owner = OWNER(); let recipient = RECIPIENT(); + // set approval to check reset state._approve(OTHER(), token_id, ZERO()); - utils::drop_event(ZERO()); assert_state_before_transfer(owner, recipient, token_id); let approved = state.get_approved(token_id); assert_eq!(approved, OTHER()); - testing::set_caller_address(owner); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, owner); state.transfer_from(owner, recipient, token_id); - assert_only_event_transfer(ZERO(), owner, recipient, token_id); + spy.assert_only_event_transfer(contract_address, owner, recipient, token_id); assert_state_after_transfer(owner, recipient, token_id); } @@ -355,21 +363,24 @@ fn test_transfer_from_owner() { #[test] fn test_transferFrom_owner() { let mut state = setup(); + let contract_address = test_address(); let token_id = TOKEN_ID; let owner = OWNER(); let recipient = RECIPIENT(); + // set approval to check reset state._approve(OTHER(), token_id, ZERO()); - utils::drop_event(ZERO()); assert_state_before_transfer(owner, recipient, token_id); let approved = state.get_approved(token_id); assert_eq!(approved, OTHER()); - testing::set_caller_address(owner); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, owner); state.transferFrom(owner, recipient, token_id); - assert_only_event_transfer(ZERO(), owner, recipient, token_id); + spy.assert_only_event_transfer(contract_address, owner, recipient, token_id); assert_state_after_transfer(owner, recipient, token_id); } @@ -378,7 +389,7 @@ fn test_transferFrom_owner() { #[should_panic(expected: ('ERC721: invalid token ID',))] fn test_transfer_from_nonexistent() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.transfer_from(ZERO(), RECIPIENT(), TOKEN_ID); } @@ -386,7 +397,7 @@ fn test_transfer_from_nonexistent() { #[should_panic(expected: ('ERC721: invalid token ID',))] fn test_transferFrom_nonexistent() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.transferFrom(ZERO(), RECIPIENT(), TOKEN_ID); } @@ -394,7 +405,7 @@ fn test_transferFrom_nonexistent() { #[should_panic(expected: ('ERC721: invalid receiver',))] fn test_transfer_from_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.transfer_from(OWNER(), ZERO(), TOKEN_ID); } @@ -403,20 +414,22 @@ fn test_transfer_from_to_zero() { fn test_transferFrom_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.transferFrom(OWNER(), ZERO(), TOKEN_ID); } #[test] fn test_transfer_from_to_owner() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); assert_eq!(state.owner_of(TOKEN_ID), OWNER()); assert_eq!(state.balance_of(OWNER()), 1); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(contract_address, OWNER()); state.transfer_from(OWNER(), OWNER(), TOKEN_ID); - assert_only_event_transfer(ZERO(), OWNER(), OWNER(), TOKEN_ID); + spy.assert_only_event_transfer(contract_address, OWNER(), OWNER(), TOKEN_ID); assert_eq!(state.owner_of(TOKEN_ID), OWNER()); assert_eq!(state.balance_of(OWNER()), 1); @@ -425,13 +438,15 @@ fn test_transfer_from_to_owner() { #[test] fn test_transferFrom_to_owner() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); assert_eq!(state.owner_of(TOKEN_ID), OWNER()); assert_eq!(state.balance_of(OWNER()), 1); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(contract_address, OWNER()); state.transferFrom(OWNER(), OWNER(), TOKEN_ID); - assert_only_event_transfer(ZERO(), OWNER(), OWNER(), TOKEN_ID); + spy.assert_only_event_transfer(contract_address, OWNER(), OWNER(), TOKEN_ID); assert_eq!(state.owner_of(TOKEN_ID), OWNER()); assert_eq!(state.balance_of(OWNER()), 1); @@ -440,18 +455,21 @@ fn test_transferFrom_to_owner() { #[test] fn test_transfer_from_approved() { let mut state = setup(); + let contract_address = test_address(); let token_id = TOKEN_ID; let owner = OWNER(); let recipient = RECIPIENT(); + assert_state_before_transfer(owner, recipient, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.transfer_from(owner, recipient, token_id); - assert_only_event_transfer(ZERO(), owner, recipient, token_id); + spy.assert_only_event_transfer(contract_address, owner, recipient, token_id); assert_state_after_transfer(owner, recipient, token_id); } @@ -459,18 +477,21 @@ fn test_transfer_from_approved() { #[test] fn test_transferFrom_approved() { let mut state = setup(); + let contract_address = test_address(); let token_id = TOKEN_ID; let owner = OWNER(); let recipient = RECIPIENT(); + assert_state_before_transfer(owner, recipient, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.transferFrom(owner, recipient, token_id); - assert_only_event_transfer(ZERO(), owner, recipient, token_id); + spy.assert_only_event_transfer(contract_address, owner, recipient, token_id); assert_state_after_transfer(owner, recipient, token_id); } @@ -478,19 +499,21 @@ fn test_transferFrom_approved() { #[test] fn test_transfer_from_approved_for_all() { let mut state = setup(); + let contract_address = test_address(); let token_id = TOKEN_ID; let owner = OWNER(); let recipient = RECIPIENT(); assert_state_before_transfer(owner, recipient, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.transfer_from(owner, recipient, token_id); - assert_only_event_transfer(ZERO(), owner, recipient, token_id); + spy.assert_only_event_transfer(contract_address, owner, recipient, token_id); assert_state_after_transfer(owner, recipient, token_id); } @@ -498,19 +521,21 @@ fn test_transfer_from_approved_for_all() { #[test] fn test_transferFrom_approved_for_all() { let mut state = setup(); + let contract_address = test_address(); let token_id = TOKEN_ID; let owner = OWNER(); let recipient = RECIPIENT(); assert_state_before_transfer(owner, recipient, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.transferFrom(owner, recipient, token_id); - assert_only_event_transfer(ZERO(), owner, recipient, token_id); + spy.assert_only_event_transfer(contract_address, owner, recipient, token_id); assert_state_after_transfer(owner, recipient, token_id); } @@ -519,7 +544,7 @@ fn test_transferFrom_approved_for_all() { #[should_panic(expected: ('ERC721: unauthorized caller',))] fn test_transfer_from_unauthorized() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.transfer_from(OWNER(), RECIPIENT(), TOKEN_ID); } @@ -527,7 +552,7 @@ fn test_transfer_from_unauthorized() { #[should_panic(expected: ('ERC721: unauthorized caller',))] fn test_transferFrom_unauthorized() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.transferFrom(OWNER(), RECIPIENT(), TOKEN_ID); } @@ -538,15 +563,17 @@ fn test_transferFrom_unauthorized() { #[test] fn test_safe_transfer_from_to_account() { let mut state = setup(); + let contract_address = test_address(); let account = setup_account(); + let mut spy = spy_events(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, account, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.safe_transfer_from(owner, account, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, account, token_id); + spy.assert_only_event_transfer(contract_address, owner, account, token_id); assert_state_after_transfer(owner, account, token_id); } @@ -554,15 +581,17 @@ fn test_safe_transfer_from_to_account() { #[test] fn test_safeTransferFrom_to_account() { let mut state = setup(); + let contract_address = test_address(); let account = setup_account(); + let mut spy = spy_events(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, account, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.safeTransferFrom(owner, account, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, account, token_id); + spy.assert_only_event_transfer(contract_address, owner, account, token_id); assert_state_after_transfer(owner, account, token_id); } @@ -570,15 +599,17 @@ fn test_safeTransferFrom_to_account() { #[test] fn test_safe_transfer_from_to_account_camel() { let mut state = setup(); + let contract_address = test_address(); let account = setup_camel_account(); + let mut spy = spy_events(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, account, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.safe_transfer_from(owner, account, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, account, token_id); + spy.assert_only_event_transfer(contract_address, owner, account, token_id); assert_state_after_transfer(owner, account, token_id); } @@ -586,15 +617,17 @@ fn test_safe_transfer_from_to_account_camel() { #[test] fn test_safeTransferFrom_to_account_camel() { let mut state = setup(); + let contract_address = test_address(); let account = setup_camel_account(); + let mut spy = spy_events(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, account, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.safeTransferFrom(owner, account, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, account, token_id); + spy.assert_only_event_transfer(contract_address, owner, account, token_id); assert_state_after_transfer(owner, account, token_id); } @@ -602,15 +635,17 @@ fn test_safeTransferFrom_to_account_camel() { #[test] fn test_safe_transfer_from_to_receiver() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); let receiver = setup_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } @@ -618,47 +653,55 @@ fn test_safe_transfer_from_to_receiver() { #[test] fn test_safeTransferFrom_to_receiver() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); let receiver = setup_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } #[test] +#[ignore] fn test_safe_transfer_from_to_receiver_camel() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); let receiver = setup_camel_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } #[test] +#[ignore] fn test_safeTransferFrom_to_receiver_camel() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); let receiver = setup_camel_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } @@ -671,7 +714,7 @@ fn test_safe_transfer_from_to_receiver_failure() { let token_id = TOKEN_ID; let owner = OWNER(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_transfer_from(owner, receiver, token_id, DATA(false)); } @@ -683,11 +726,12 @@ fn test_safeTransferFrom_to_receiver_failure() { let token_id = TOKEN_ID; let owner = OWNER(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeTransferFrom(owner, receiver, token_id, DATA(false)); } #[test] +#[ignore] #[should_panic(expected: ('ERC721: safe transfer failed',))] fn test_safe_transfer_from_to_receiver_failure_camel() { let mut state = setup(); @@ -695,11 +739,12 @@ fn test_safe_transfer_from_to_receiver_failure_camel() { let token_id = TOKEN_ID; let owner = OWNER(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_transfer_from(owner, receiver, token_id, DATA(false)); } #[test] +#[ignore] #[should_panic(expected: ('ERC721: safe transfer failed',))] fn test_safeTransferFrom_to_receiver_failure_camel() { let mut state = setup(); @@ -707,31 +752,33 @@ fn test_safeTransferFrom_to_receiver_failure_camel() { let token_id = TOKEN_ID; let owner = OWNER(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeTransferFrom(owner, receiver, token_id, DATA(false)); } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_safe_transfer_from_to_non_receiver() { let mut state = setup(); - let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let recipient = utils::declare_and_deploy("NonImplementingMock", array![]); let token_id = TOKEN_ID; let owner = OWNER(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safe_transfer_from(owner, recipient, token_id, DATA(true)); } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_safeTransferFrom_to_non_receiver() { let mut state = setup(); - let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let recipient = utils::declare_and_deploy("NonImplementingMock", array![]); let token_id = TOKEN_ID; let owner = OWNER(); - testing::set_caller_address(owner); + start_cheat_caller_address(test_address(), owner); state.safeTransferFrom(owner, recipient, token_id, DATA(true)); } @@ -739,7 +786,7 @@ fn test_safeTransferFrom_to_non_receiver() { #[should_panic(expected: ('ERC721: invalid token ID',))] fn test_safe_transfer_from_nonexistent() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.safe_transfer_from(ZERO(), RECIPIENT(), TOKEN_ID, DATA(true)); } @@ -747,7 +794,7 @@ fn test_safe_transfer_from_nonexistent() { #[should_panic(expected: ('ERC721: invalid token ID',))] fn test_safeTransferFrom_nonexistent() { let mut state = COMPONENT_STATE(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.safeTransferFrom(ZERO(), RECIPIENT(), TOKEN_ID, DATA(true)); } @@ -755,7 +802,7 @@ fn test_safeTransferFrom_nonexistent() { #[should_panic(expected: ('ERC721: invalid receiver',))] fn test_safe_transfer_from_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.safe_transfer_from(OWNER(), ZERO(), TOKEN_ID, DATA(true)); } @@ -763,25 +810,28 @@ fn test_safe_transfer_from_to_zero() { #[should_panic(expected: ('ERC721: invalid receiver',))] fn test_safeTransferFrom_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.safeTransferFrom(OWNER(), ZERO(), TOKEN_ID, DATA(true)); } #[test] fn test_safe_transfer_from_to_owner() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); let token_id = TOKEN_ID; let owner = setup_receiver(); + state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(owner, token_id); - utils::drop_event(ZERO()); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); - testing::set_caller_address(owner); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, owner); state.safe_transfer_from(owner, owner, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, owner, token_id); + spy.assert_only_event_transfer(contract_address, owner, owner, token_id); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); @@ -790,58 +840,67 @@ fn test_safe_transfer_from_to_owner() { #[test] fn test_safeTransferFrom_to_owner() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); let token_id = TOKEN_ID; let owner = setup_receiver(); + state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(owner, token_id); - utils::drop_event(ZERO()); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); - testing::set_caller_address(owner); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, owner); state.safeTransferFrom(owner, owner, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, owner, token_id); + spy.assert_only_event_transfer(contract_address, owner, owner, token_id); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); } #[test] +#[ignore] fn test_safe_transfer_from_to_owner_camel() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); + let mut spy = spy_events(); let token_id = TOKEN_ID; let owner = setup_camel_receiver(); + state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(owner, token_id); - utils::drop_event(ZERO()); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.safe_transfer_from(owner, owner, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, owner, token_id); + spy.assert_only_event_transfer(contract_address, owner, owner, token_id); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); } #[test] +#[ignore] fn test_safeTransferFrom_to_owner_camel() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); + let mut spy = spy_events(); let token_id = TOKEN_ID; let owner = setup_camel_receiver(); + state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(owner, token_id); - utils::drop_event(ZERO()); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.safeTransferFrom(owner, owner, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, owner, token_id); + spy.assert_only_event_transfer(contract_address, owner, owner, token_id); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); @@ -850,19 +909,21 @@ fn test_safeTransferFrom_to_owner_camel() { #[test] fn test_safe_transfer_from_approved() { let mut state = setup(); + let contract_address = test_address(); let receiver = setup_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } @@ -870,59 +931,67 @@ fn test_safe_transfer_from_approved() { #[test] fn test_safeTransferFrom_approved() { let mut state = setup(); + let contract_address = test_address(); let receiver = setup_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } #[test] +#[ignore] fn test_safe_transfer_from_approved_camel() { let mut state = setup(); + let contract_address = test_address(); let receiver = setup_camel_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } #[test] +#[ignore] fn test_safeTransferFrom_approved_camel() { let mut state = setup(); + let contract_address = test_address(); let receiver = setup_camel_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } @@ -930,19 +999,21 @@ fn test_safeTransferFrom_approved_camel() { #[test] fn test_safe_transfer_from_approved_for_all() { let mut state = setup(); + let contract_address = test_address(); let receiver = setup_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } @@ -950,59 +1021,66 @@ fn test_safe_transfer_from_approved_for_all() { #[test] fn test_safeTransferFrom_approved_for_all() { let mut state = setup(); + let contract_address = test_address(); let receiver = setup_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } #[test] +#[ignore] fn test_safe_transfer_from_approved_for_all_camel() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); let receiver = setup_camel_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + start_cheat_caller_address(contract_address, OPERATOR()); state.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } #[test] +#[ignore] fn test_safeTransferFrom_approved_for_all_camel() { let mut state = setup(); + let contract_address = test_address(); let receiver = setup_camel_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); assert_state_before_transfer(owner, receiver, token_id); - testing::set_caller_address(owner); + start_cheat_caller_address(contract_address, owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); - testing::set_caller_address(OPERATOR()); + let mut spy = spy_events(); + + start_cheat_caller_address(contract_address, OPERATOR()); state.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), owner, receiver, token_id); + spy.assert_only_event_transfer(contract_address, owner, receiver, token_id); assert_state_after_transfer(owner, receiver, token_id); } @@ -1011,7 +1089,7 @@ fn test_safeTransferFrom_approved_for_all_camel() { #[should_panic(expected: ('ERC721: unauthorized caller',))] fn test_safe_transfer_from_unauthorized() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.safe_transfer_from(OWNER(), RECIPIENT(), TOKEN_ID, DATA(true)); } @@ -1019,7 +1097,7 @@ fn test_safe_transfer_from_unauthorized() { #[should_panic(expected: ('ERC721: unauthorized caller',))] fn test_safeTransferFrom_unauthorized() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.safeTransferFrom(OWNER(), RECIPIENT(), TOKEN_ID, DATA(true)); } @@ -1030,6 +1108,8 @@ fn test_safeTransferFrom_unauthorized() { #[test] fn test__transfer() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); let token_id = TOKEN_ID; let owner = OWNER(); let recipient = RECIPIENT(); @@ -1037,7 +1117,7 @@ fn test__transfer() { assert_state_before_transfer(owner, recipient, token_id); state.transfer(owner, recipient, token_id); - assert_only_event_transfer(ZERO(), owner, recipient, token_id); + spy.assert_only_event_transfer(contract_address, owner, recipient, token_id); assert_state_after_transfer(owner, recipient, token_id); } @@ -1070,12 +1150,14 @@ fn test__transfer_from_invalid_owner() { #[test] fn test_mint() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); + let mut spy = spy_events(); let recipient = RECIPIENT(); let token_id = TOKEN_ID; assert_state_before_mint(recipient); state.mint(recipient, TOKEN_ID); - assert_only_event_transfer(ZERO(), ZERO(), recipient, token_id); + spy.assert_only_event_transfer(contract_address, ZERO(), recipient, token_id); assert_state_after_mint(recipient, token_id); } @@ -1101,25 +1183,30 @@ fn test_mint_already_exist() { #[test] fn test__safe_mint_to_receiver() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); + let mut spy = spy_events(); let recipient = setup_receiver(); let token_id = TOKEN_ID; assert_state_before_mint(recipient); state.safe_mint(recipient, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), ZERO(), recipient, token_id); + spy.assert_only_event_transfer(contract_address, ZERO(), recipient, token_id); assert_state_after_mint(recipient, token_id); } #[test] +#[ignore] fn test__safe_mint_to_receiver_camel() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); + let mut spy = spy_events(); let recipient = setup_camel_receiver(); let token_id = TOKEN_ID; assert_state_before_mint(recipient); state.safe_mint(recipient, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), ZERO(), recipient, token_id); + spy.assert_only_event_transfer(contract_address, ZERO(), recipient, token_id); assert_state_after_mint(recipient, token_id); } @@ -1127,12 +1214,14 @@ fn test__safe_mint_to_receiver_camel() { #[test] fn test__safe_mint_to_account() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); let account = setup_account(); + let mut spy = spy_events(); let token_id = TOKEN_ID; assert_state_before_mint(account); state.safe_mint(account, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), ZERO(), account, token_id); + spy.assert_only_event_transfer(contract_address, ZERO(), account, token_id); assert_state_after_mint(account, token_id); } @@ -1140,21 +1229,24 @@ fn test__safe_mint_to_account() { #[test] fn test__safe_mint_to_account_camel() { let mut state = COMPONENT_STATE(); + let contract_address = test_address(); let account = setup_camel_account(); + let mut spy = spy_events(); let token_id = TOKEN_ID; assert_state_before_mint(account); state.safe_mint(account, token_id, DATA(true)); - assert_only_event_transfer(ZERO(), ZERO(), account, token_id); + spy.assert_only_event_transfer(contract_address, ZERO(), account, token_id); assert_state_after_mint(account, token_id); } #[test] +#[ignore] #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test__safe_mint_to_non_receiver() { let mut state = COMPONENT_STATE(); - let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let recipient = utils::declare_and_deploy("NonImplementingMock", array![]); let token_id = TOKEN_ID; assert_state_before_mint(recipient); @@ -1175,6 +1267,7 @@ fn test__safe_mint_to_receiver_failure() { } #[test] +#[ignore] #[should_panic(expected: ('ERC721: safe mint failed',))] fn test__safe_mint_to_receiver_failure_camel() { let mut state = COMPONENT_STATE(); @@ -1207,16 +1300,18 @@ fn test__safe_mint_already_exist() { #[test] fn test_burn() { let mut state = setup(); + let contract_address = test_address(); state._approve(OTHER(), TOKEN_ID, ZERO()); - utils::drop_event(ZERO()); assert_eq!(state.owner_of(TOKEN_ID), OWNER()); assert_eq!(state.balance_of(OWNER()), 1); assert_eq!(state.get_approved(TOKEN_ID), OTHER()); + let mut spy = spy_events(); + state.burn(TOKEN_ID); - assert_only_event_transfer(ZERO(), OWNER(), ZERO(), TOKEN_ID); + spy.assert_only_event_transfer(contract_address, OWNER(), ZERO(), TOKEN_ID); assert_eq!(state.ERC721_owners.read(TOKEN_ID), ZERO()); assert_eq!(state.balance_of(OWNER()), 0); @@ -1319,8 +1414,11 @@ fn test__exists() { #[test] fn test__approve_with_optional_event_emitting() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); + state._approve_with_optional_event(SPENDER(), TOKEN_ID, ZERO(), true); - assert_only_event_approval(ZERO(), OWNER(), SPENDER(), TOKEN_ID); + spy.assert_only_event_approval(contract_address, OWNER(), SPENDER(), TOKEN_ID); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -1329,8 +1427,10 @@ fn test__approve_with_optional_event_emitting() { #[test] fn test__approve_with_optional_event_not_emitting() { let mut state = setup(); + let mut spy = spy_events(); + state._approve_with_optional_event(SPENDER(), TOKEN_ID, ZERO(), false); - utils::assert_no_events_left(ZERO()); + spy.assert_no_events_left_from(test_address()); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -1346,8 +1446,10 @@ fn test__approve_with_optional_event_nonexistent_emitting() { #[test] fn test__approve_with_optional_event_nonexistent_not_emitting() { let mut state = setup(); + let mut spy = spy_events(); + state._approve_with_optional_event(SPENDER(), TOKEN_ID, ZERO(), false); - utils::assert_no_events_left(ZERO()); + spy.assert_no_events_left_from(test_address()); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -1356,8 +1458,10 @@ fn test__approve_with_optional_event_nonexistent_not_emitting() { #[test] fn test__approve_with_optional_event_auth_is_owner() { let mut state = setup(); + let mut spy = spy_events(); + state._approve_with_optional_event(SPENDER(), TOKEN_ID, OWNER(), false); - utils::assert_no_events_left(ZERO()); + spy.assert_no_events_left_from(test_address()); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -1367,12 +1471,15 @@ fn test__approve_with_optional_event_auth_is_owner() { fn test__approve_with_optional_event_auth_is_approved_for_all() { let mut state = setup(); let auth = CALLER(); - testing::set_caller_address(OWNER()); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, OWNER()); state.set_approval_for_all(auth, true); - utils::drop_event(ZERO()); + + let mut spy = spy_events(); state._approve_with_optional_event(SPENDER(), TOKEN_ID, auth, false); - utils::assert_no_events_left(ZERO()); + spy.assert_no_events_left_from(contract_address); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -1396,9 +1503,8 @@ fn test__is_authorized_owner() { fn test__is_authorized_approved_for_all() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.set_approval_for_all(SPENDER(), true); - utils::drop_event(ZERO()); let authorized = state._is_authorized(OWNER(), SPENDER(), TOKEN_ID); assert!(authorized); @@ -1408,9 +1514,8 @@ fn test__is_authorized_approved_for_all() { fn test__is_authorized_approved() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.approve(SPENDER(), TOKEN_ID); - utils::drop_event(ZERO()); let authorized = state._is_authorized(OWNER(), SPENDER(), TOKEN_ID); assert!(authorized); @@ -1440,9 +1545,8 @@ fn test__check_authorized_owner() { fn test__check_authorized_approved_for_all() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.set_approval_for_all(SPENDER(), true); - utils::drop_event(ZERO()); state._check_authorized(OWNER(), SPENDER(), TOKEN_ID); } @@ -1451,9 +1555,8 @@ fn test__check_authorized_approved_for_all() { fn test__check_authorized_approved() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.approve(SPENDER(), TOKEN_ID); - utils::drop_event(ZERO()); state._check_authorized(OWNER(), SPENDER(), TOKEN_ID); } @@ -1482,9 +1585,11 @@ fn test__check_authorized_zero_address() { #[test] fn test_update_mint() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); state.update(RECIPIENT(), TOKEN_ID_2, ZERO()); - assert_only_event_transfer(ZERO(), ZERO(), RECIPIENT(), TOKEN_ID_2); + spy.assert_only_event_transfer(contract_address, ZERO(), RECIPIENT(), TOKEN_ID_2); let owner = state.owner_of(TOKEN_ID_2); assert_eq!(owner, RECIPIENT()); @@ -1496,9 +1601,11 @@ fn test_update_mint() { #[test] fn test_update_burn() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); state.update(ZERO(), TOKEN_ID, ZERO()); - assert_only_event_transfer(ZERO(), OWNER(), ZERO(), TOKEN_ID); + spy.assert_only_event_transfer(contract_address, OWNER(), ZERO(), TOKEN_ID); let owner = state._owner_of(TOKEN_ID); assert_eq!(owner, ZERO()); @@ -1510,41 +1617,52 @@ fn test_update_burn() { #[test] fn test_update_transfer() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); state.update(RECIPIENT(), TOKEN_ID, ZERO()); - assert_only_event_transfer(ZERO(), OWNER(), RECIPIENT(), TOKEN_ID); + spy.assert_only_event_transfer(contract_address, OWNER(), RECIPIENT(), TOKEN_ID); assert_state_after_transfer(OWNER(), RECIPIENT(), TOKEN_ID); } #[test] fn test_update_auth_owner() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); + state.update(RECIPIENT(), TOKEN_ID, OWNER()); - assert_only_event_transfer(ZERO(), OWNER(), RECIPIENT(), TOKEN_ID); + spy.assert_only_event_transfer(contract_address, OWNER(), RECIPIENT(), TOKEN_ID); assert_state_after_transfer(OWNER(), RECIPIENT(), TOKEN_ID); } #[test] fn test_update_auth_approved_for_all() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, OWNER()); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); + + let mut spy = spy_events(); state.update(RECIPIENT(), TOKEN_ID, OPERATOR()); - assert_only_event_transfer(ZERO(), OWNER(), RECIPIENT(), TOKEN_ID); + spy.assert_only_event_transfer(contract_address, OWNER(), RECIPIENT(), TOKEN_ID); assert_state_after_transfer(OWNER(), RECIPIENT(), TOKEN_ID); } #[test] fn test_update_auth_approved() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, OWNER()); state.approve(OPERATOR(), TOKEN_ID); - utils::drop_event(ZERO()); + + let mut spy = spy_events(); state.update(RECIPIENT(), TOKEN_ID, OPERATOR()); - assert_only_event_transfer(ZERO(), OWNER(), RECIPIENT(), TOKEN_ID); + spy.assert_only_event_transfer(contract_address, OWNER(), RECIPIENT(), TOKEN_ID); assert_state_after_transfer(OWNER(), RECIPIENT(), TOKEN_ID); } diff --git a/src/tests/token/erc721/test_erc721_receiver.cairo b/src/tests/token/erc721/test_erc721_receiver.cairo index 72f8272a2..a84e1c434 100644 --- a/src/tests/token/erc721/test_erc721_receiver.cairo +++ b/src/tests/token/erc721/test_erc721_receiver.cairo @@ -1,7 +1,7 @@ use openzeppelin::introspection::interface::ISRC5_ID; use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; use openzeppelin::tests::mocks::erc721_receiver_mocks::DualCaseERC721ReceiverMock; -use openzeppelin::tests::utils::constants::{OWNER, OPERATOR, TOKEN_ID, DATA}; +use openzeppelin::tests::utils::constants::{OWNER, OPERATOR, TOKEN_ID}; use openzeppelin::token::erc721::ERC721ReceiverComponent::{ ERC721ReceiverImpl, ERC721ReceiverCamelImpl, InternalImpl }; From fbfb819b154375a5c9d8b9081f0a18247712afe5 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 16 Jul 2024 13:39:46 +0200 Subject: [PATCH 09/45] Check ignored tests (#1049) * test: check ignored tests and add reason * feat: apply review updates --- src/tests/token/erc1155/test_dual1155.cairo | 64 +++++-------- .../erc1155/test_dual1155_receiver.cairo | 16 ++-- src/tests/token/erc1155/test_erc1155.cairo | 14 +-- src/tests/token/erc20/test_dual20.cairo | 78 ++++++--------- src/tests/token/erc721/test_dual721.cairo | 94 ++++++++----------- .../token/erc721/test_dual721_receiver.cairo | 7 +- src/tests/token/erc721/test_erc721.cairo | 48 +++++----- src/tests/utils/common.cairo | 1 + 8 files changed, 140 insertions(+), 182 deletions(-) diff --git a/src/tests/token/erc1155/test_dual1155.cairo b/src/tests/token/erc1155/test_dual1155.cairo index 4589cd2c1..3248947b4 100644 --- a/src/tests/token/erc1155/test_dual1155.cairo +++ b/src/tests/token/erc1155/test_dual1155.cairo @@ -71,16 +71,19 @@ fn setup_erc1155_panic() -> (DualCaseERC1155, DualCaseERC1155) { // #[test] -#[ignore] -fn test_dual_uri() { +fn test_dual_uri_snake() { let (snake_dispatcher, _, _) = setup_snake(); - let (camel_dispatcher, _, _) = setup_camel(); assert_eq!(snake_dispatcher.uri(TOKEN_ID), "URI"); +} + +#[test] +fn test_dual_uri_camel() { + let (camel_dispatcher, _, _) = setup_camel(); assert_eq!(camel_dispatcher.uri(TOKEN_ID), "URI"); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_uri() { let dispatcher = setup_non_erc1155(); @@ -88,7 +91,6 @@ fn test_dual_no_uri() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_uri_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); @@ -100,14 +102,13 @@ fn test_dual_uri_exists_and_panics() { // #[test] -#[ignore] fn test_dual_balance_of() { let (dispatcher, _, owner) = setup_snake(); assert_eq!(dispatcher.balance_of(owner, TOKEN_ID), TOKEN_VALUE); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_balance_of() { let dispatcher = setup_non_erc1155(); @@ -115,7 +116,6 @@ fn test_dual_no_balance_of() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_balance_of_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); @@ -123,7 +123,6 @@ fn test_dual_balance_of_exists_and_panics() { } #[test] -#[ignore] fn test_dual_balance_of_batch() { let (dispatcher, _, owner) = setup_snake(); let accounts = array![owner, RECIPIENT()].span(); @@ -135,7 +134,7 @@ fn test_dual_balance_of_batch() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_balance_of_batch() { let dispatcher = setup_non_erc1155(); @@ -144,7 +143,6 @@ fn test_dual_no_balance_of_batch() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_balance_of_batch_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); @@ -153,7 +151,6 @@ fn test_dual_balance_of_batch_exists_and_panics() { } #[test] -#[ignore] fn test_dual_safe_transfer_from() { let (dispatcher, target, owner) = setup_snake(); let receiver = setup_receiver(); @@ -164,7 +161,7 @@ fn test_dual_safe_transfer_from() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_safe_transfer_from() { let dispatcher = setup_non_erc1155(); @@ -172,7 +169,6 @@ fn test_dual_no_safe_transfer_from() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_safe_transfer_from_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); @@ -180,7 +176,6 @@ fn test_dual_safe_transfer_from_exists_and_panics() { } #[test] -#[ignore] fn test_dual_safe_batch_transfer_from() { let (dispatcher, target, owner) = setup_snake(); let token_ids = array![TOKEN_ID, TOKEN_ID_2].span(); @@ -194,7 +189,7 @@ fn test_dual_safe_batch_transfer_from() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_safe_batch_transfer_from() { let dispatcher = setup_non_erc1155(); @@ -204,7 +199,6 @@ fn test_dual_no_safe_batch_transfer_from() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_safe_batch_transfer_from_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); @@ -214,7 +208,6 @@ fn test_dual_safe_batch_transfer_from_exists_and_panics() { } #[test] -#[ignore] fn test_dual_is_approved_for_all() { let (dispatcher, target, _) = setup_snake(); @@ -226,7 +219,7 @@ fn test_dual_is_approved_for_all() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_is_approved_for_all() { let dispatcher = setup_non_erc1155(); @@ -234,7 +227,6 @@ fn test_dual_no_is_approved_for_all() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_is_approved_for_all_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); @@ -242,7 +234,6 @@ fn test_dual_is_approved_for_all_exists_and_panics() { } #[test] -#[ignore] fn test_dual_set_approval_for_all() { let (dispatcher, target, _) = setup_snake(); @@ -254,7 +245,7 @@ fn test_dual_set_approval_for_all() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_set_approval_for_all() { let dispatcher = setup_non_erc1155(); @@ -262,7 +253,6 @@ fn test_dual_no_set_approval_for_all() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_set_approval_for_all_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); @@ -270,7 +260,6 @@ fn test_dual_set_approval_for_all_exists_and_panics() { } #[test] -#[ignore] fn test_dual_supports_interface() { let (dispatcher, _, _) = setup_snake(); let supports_ierc1155 = dispatcher.supports_interface(IERC1155_ID); @@ -278,7 +267,7 @@ fn test_dual_supports_interface() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_supports_interface() { let dispatcher = setup_non_erc1155(); @@ -286,7 +275,6 @@ fn test_dual_no_supports_interface() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_supports_interface_exists_and_panics() { let (dispatcher, _) = setup_erc1155_panic(); @@ -298,14 +286,14 @@ fn test_dual_supports_interface_exists_and_panics() { // #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_balanceOf() { let (dispatcher, _, owner) = setup_camel(); assert_eq!(dispatcher.balance_of(owner, TOKEN_ID), TOKEN_VALUE); } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_balanceOf_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); @@ -313,7 +301,7 @@ fn test_dual_balanceOf_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_balanceOfBatch() { let (dispatcher, _, owner) = setup_camel(); let accounts = array![owner, RECIPIENT()].span(); @@ -325,7 +313,7 @@ fn test_dual_balanceOfBatch() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_balanceOfBatch_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); @@ -334,7 +322,7 @@ fn test_dual_balanceOfBatch_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_safeTransferFrom() { let (dispatcher, target, owner) = setup_camel(); let receiver = setup_receiver(); @@ -345,7 +333,7 @@ fn test_dual_safeTransferFrom() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_safeTransferFrom_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); @@ -353,7 +341,7 @@ fn test_dual_safeTransferFrom_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_safeBatchTransferFrom() { let (dispatcher, target, owner) = setup_camel(); let token_ids = array![TOKEN_ID, TOKEN_ID_2].span(); @@ -367,7 +355,7 @@ fn test_dual_safeBatchTransferFrom() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_safeBatchTransferFrom_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); @@ -377,7 +365,7 @@ fn test_dual_safeBatchTransferFrom_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_isApprovedForAll() { let (dispatcher, target, _) = setup_camel(); @@ -389,7 +377,7 @@ fn test_dual_isApprovedForAll() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_isApprovedForAll_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); @@ -397,7 +385,7 @@ fn test_dual_isApprovedForAll_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_setApprovalForAll() { let (dispatcher, target, _) = setup_camel(); @@ -409,7 +397,7 @@ fn test_dual_setApprovalForAll() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_setApprovalForAll_exists_and_panics() { let (_, dispatcher) = setup_erc1155_panic(); diff --git a/src/tests/token/erc1155/test_dual1155_receiver.cairo b/src/tests/token/erc1155/test_dual1155_receiver.cairo index c207d3e71..f0e7c3a98 100644 --- a/src/tests/token/erc1155/test_dual1155_receiver.cairo +++ b/src/tests/token/erc1155/test_dual1155_receiver.cairo @@ -53,7 +53,6 @@ fn setup_erc1155_receiver_panic() -> (DualCaseERC1155Receiver, DualCaseERC1155Re // #[test] -#[ignore] fn test_dual_on_erc1155_received() { let (dispatcher, _) = setup_snake(); let result = dispatcher @@ -62,7 +61,7 @@ fn test_dual_on_erc1155_received() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_on_erc1155_received() { let dispatcher = setup_non_erc1155_receiver(); @@ -70,7 +69,6 @@ fn test_dual_no_on_erc1155_received() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_on_erc1155_received_exists_and_panics() { let (dispatcher, _) = setup_erc1155_receiver_panic(); @@ -78,7 +76,6 @@ fn test_dual_on_erc1155_received_exists_and_panics() { } #[test] -#[ignore] fn test_dual_on_erc1155_batch_received() { let (dispatcher, _) = setup_snake(); let (token_ids, values) = get_ids_and_values(); @@ -89,7 +86,7 @@ fn test_dual_on_erc1155_batch_received() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_on_erc1155_batch_received() { let dispatcher = setup_non_erc1155_receiver(); @@ -98,7 +95,6 @@ fn test_dual_no_on_erc1155_batch_received() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_on_erc1155_batch_received_exists_and_panics() { let (dispatcher, _) = setup_erc1155_receiver_panic(); @@ -111,7 +107,7 @@ fn test_dual_on_erc1155_batch_received_exists_and_panics() { // #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_onERC1155Received() { let (dispatcher, _) = setup_camel(); let result = dispatcher @@ -120,7 +116,7 @@ fn test_dual_onERC1155Received() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_onERC1155Received_exists_and_panics() { let (_, dispatcher) = setup_erc1155_receiver_panic(); @@ -128,7 +124,7 @@ fn test_dual_onERC1155Received_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_onERC1155BatchReceived() { let (dispatcher, _) = setup_camel(); let (token_ids, values) = get_ids_and_values(); @@ -139,7 +135,7 @@ fn test_dual_onERC1155BatchReceived() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_onERC1155BatchReceived_exists_and_panics() { let (_, dispatcher) = setup_erc1155_receiver_panic(); diff --git a/src/tests/token/erc1155/test_erc1155.cairo b/src/tests/token/erc1155/test_erc1155.cairo index db07832e5..951de7b70 100644 --- a/src/tests/token/erc1155/test_erc1155.cairo +++ b/src/tests/token/erc1155/test_erc1155.cairo @@ -158,7 +158,7 @@ fn test_safe_transfer_from_owner_to_receiver() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_transfer_from_owner_to_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); @@ -197,7 +197,7 @@ fn test_safeTransferFrom_owner_to_receiver() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeTransferFrom_owner_to_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); @@ -423,7 +423,7 @@ fn test_safe_batch_transfer_from_owner_to_receiver() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_batch_transfer_from_owner_to_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); @@ -464,7 +464,7 @@ fn test_safeBatchTransferFrom_owner_to_receiver() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeBatchTransferFrom_owner_to_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); @@ -919,7 +919,7 @@ fn test_update_wac_single_from_non_zero_to_non_zero() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_update_wac_single_from_non_zero_to_non_zero_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); @@ -983,7 +983,7 @@ fn test_update_wac_batch_from_non_zero_to_non_zero() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_update_wac_batch_from_non_zero_to_non_zero_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); @@ -1061,7 +1061,7 @@ fn test_update_wac_from_zero_to_non_zero() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_update_wac_from_zero_to_non_zero_camel_receiver() { let (mut state, owner) = setup(); let recipient = setup_camel_receiver(); diff --git a/src/tests/token/erc20/test_dual20.cairo b/src/tests/token/erc20/test_dual20.cairo index dc37ce836..8a24c3a9a 100644 --- a/src/tests/token/erc20/test_dual20.cairo +++ b/src/tests/token/erc20/test_dual20.cairo @@ -52,7 +52,6 @@ fn setup_erc20_panic() -> (DualCaseERC20, DualCaseERC20) { // #[test] -#[ignore] fn test_dual_name() { let (snake_dispatcher, _) = setup_snake(); assert_eq!(snake_dispatcher.name(), NAME()); @@ -62,7 +61,7 @@ fn test_dual_name() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_name() { let dispatcher = setup_non_erc20(); @@ -70,15 +69,13 @@ fn test_dual_no_name() { } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_name_exists_and_panics() { let (dispatcher, _) = setup_erc20_panic(); dispatcher.name(); } #[test] -#[ignore] fn test_dual_symbol() { let (snake_dispatcher, _) = setup_snake(); let (camel_dispatcher, _) = setup_camel(); @@ -87,7 +84,7 @@ fn test_dual_symbol() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_symbol() { let dispatcher = setup_non_erc20(); @@ -95,15 +92,13 @@ fn test_dual_no_symbol() { } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_symbol_exists_and_panics() { let (dispatcher, _) = setup_erc20_panic(); dispatcher.symbol(); } #[test] -#[ignore] fn test_dual_decimals() { let (snake_dispatcher, _) = setup_snake(); let (camel_dispatcher, _) = setup_camel(); @@ -112,7 +107,7 @@ fn test_dual_decimals() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_decimals() { let dispatcher = setup_non_erc20(); @@ -120,30 +115,28 @@ fn test_dual_no_decimals() { } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_decimals_exists_and_panics() { let (dispatcher, _) = setup_erc20_panic(); dispatcher.decimals(); } #[test] -#[ignore] fn test_dual_transfer() { let (snake_dispatcher, snake_target) = setup_snake(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(snake_dispatcher.contract_address, OWNER()); assert!(snake_dispatcher.transfer(RECIPIENT(), VALUE)); assert_eq!(snake_target.balance_of(RECIPIENT()), VALUE); let (camel_dispatcher, camel_target) = setup_camel(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(camel_dispatcher.contract_address, OWNER()); assert!(camel_dispatcher.transfer(RECIPIENT(), VALUE)); assert_eq!(camel_target.balanceOf(RECIPIENT()), VALUE); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_transfer() { let dispatcher = setup_non_erc20(); @@ -151,25 +144,23 @@ fn test_dual_no_transfer() { } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_transfer_exists_and_panics() { let (dispatcher, _) = setup_erc20_panic(); dispatcher.transfer(RECIPIENT(), VALUE); } #[test] -#[ignore] fn test_dual_approve() { let (snake_dispatcher, snake_target) = setup_snake(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(snake_dispatcher.contract_address, OWNER()); assert!(snake_dispatcher.approve(SPENDER(), VALUE)); let snake_allowance = snake_target.allowance(OWNER(), SPENDER()); assert_eq!(snake_allowance, VALUE); let (camel_dispatcher, camel_target) = setup_camel(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(camel_dispatcher.contract_address, OWNER()); assert!(camel_dispatcher.approve(SPENDER(), VALUE)); let camel_allowance = camel_target.allowance(OWNER(), SPENDER()); @@ -177,7 +168,7 @@ fn test_dual_approve() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_approve() { let dispatcher = setup_non_erc20(); @@ -185,8 +176,7 @@ fn test_dual_no_approve() { } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_approve_exists_and_panics() { let (dispatcher, _) = setup_erc20_panic(); dispatcher.approve(SPENDER(), VALUE); @@ -197,14 +187,13 @@ fn test_dual_approve_exists_and_panics() { // #[test] -#[ignore] fn test_dual_total_supply() { let (dispatcher, _) = setup_snake(); assert_eq!(dispatcher.total_supply(), SUPPLY); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_total_supply() { let dispatcher = setup_non_erc20(); @@ -212,22 +201,20 @@ fn test_dual_no_total_supply() { } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_total_supply_exists_and_panics() { let (dispatcher, _) = setup_erc20_panic(); dispatcher.total_supply(); } #[test] -#[ignore] fn test_dual_balance_of() { let (dispatcher, _) = setup_snake(); assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_balance_of() { let dispatcher = setup_non_erc20(); @@ -235,27 +222,25 @@ fn test_dual_no_balance_of() { } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_balance_of_exists_and_panics() { let (dispatcher, _) = setup_erc20_panic(); dispatcher.balance_of(OWNER()); } #[test] -#[ignore] fn test_dual_transfer_from() { let (dispatcher, target) = setup_snake(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); target.approve(OPERATOR(), VALUE); - start_cheat_caller_address(test_address(), OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); assert_eq!(target.balance_of(RECIPIENT()), VALUE); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_transfer_from() { let dispatcher = setup_non_erc20(); @@ -263,8 +248,7 @@ fn test_dual_no_transfer_from() { } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_transfer_from_exists_and_panics() { let (dispatcher, _) = setup_erc20_panic(); dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); @@ -275,37 +259,37 @@ fn test_dual_transfer_from_exists_and_panics() { // #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_totalSupply() { let (dispatcher, _) = setup_camel(); assert_eq!(dispatcher.total_supply(), SUPPLY); } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_totalSupply_exists_and_panics() { let (_, dispatcher) = setup_erc20_panic(); dispatcher.total_supply(); } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_balanceOf() { let (dispatcher, _) = setup_camel(); assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY); } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_balanceOf_exists_and_panics() { let (_, dispatcher) = setup_erc20_panic(); dispatcher.balance_of(OWNER()); } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_transferFrom() { let (dispatcher, target) = setup_camel(); start_cheat_caller_address(test_address(), OWNER()); @@ -317,8 +301,8 @@ fn test_dual_transferFrom() { } #[test] -#[ignore] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_transferFrom_exists_and_panics() { let (_, dispatcher) = setup_erc20_panic(); dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); diff --git a/src/tests/token/erc721/test_dual721.cairo b/src/tests/token/erc721/test_dual721.cairo index 943608c9e..b4b13cbb6 100644 --- a/src/tests/token/erc721/test_dual721.cairo +++ b/src/tests/token/erc721/test_dual721.cairo @@ -24,8 +24,8 @@ fn setup_snake() -> (DualCaseERC721, IERC721Dispatcher) { calldata.append_serde(OWNER()); calldata.append_serde(TOKEN_ID); - start_cheat_caller_address(test_address(), OWNER()); let target = utils::declare_and_deploy("SnakeERC721Mock", calldata); + start_cheat_caller_address(target, OWNER()); (DualCaseERC721 { contract_address: target }, IERC721Dispatcher { contract_address: target }) } @@ -37,8 +37,8 @@ fn setup_camel() -> (DualCaseERC721, IERC721CamelOnlyDispatcher) { calldata.append_serde(OWNER()); calldata.append_serde(TOKEN_ID); - start_cheat_caller_address(test_address(), OWNER()); let target = utils::declare_and_deploy("CamelERC721Mock", calldata); + start_cheat_caller_address(target, OWNER()); ( DualCaseERC721 { contract_address: target }, IERC721CamelOnlyDispatcher { contract_address: target } @@ -69,17 +69,16 @@ fn setup_receiver() -> ContractAddress { // #[test] -#[ignore] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_name() { let (snake_dispatcher, _) = setup_snake(); - let (camel_dispatcher, _) = setup_camel(); assert_eq!(snake_dispatcher.name(), NAME()); + + let (camel_dispatcher, _) = setup_camel(); assert_eq!(camel_dispatcher.name(), NAME()); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_name() { let dispatcher = setup_non_erc721(); @@ -94,7 +93,6 @@ fn test_dual_name_exists_and_panics() { } #[test] -#[ignore] fn test_dual_symbol() { let (snake_dispatcher, _) = setup_snake(); let (camel_dispatcher, _) = setup_camel(); @@ -103,7 +101,7 @@ fn test_dual_symbol() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_symbol() { let dispatcher = setup_non_erc721(); @@ -118,23 +116,22 @@ fn test_dual_symbol_exists_and_panics() { } #[test] -#[ignore] fn test_dual_approve() { let (snake_dispatcher, snake_target) = setup_snake(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(snake_dispatcher.contract_address, OWNER()); snake_dispatcher.approve(SPENDER(), TOKEN_ID); assert_eq!(snake_target.get_approved(TOKEN_ID), SPENDER()); let (camel_dispatcher, camel_target) = setup_camel(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(camel_dispatcher.contract_address, OWNER()); camel_dispatcher.approve(SPENDER(), TOKEN_ID); assert_eq!(camel_target.getApproved(TOKEN_ID), SPENDER()); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_approve() { let dispatcher = setup_non_erc721(); @@ -153,14 +150,13 @@ fn test_dual_approve_exists_and_panics() { // #[test] -#[ignore] fn test_dual_balance_of() { let (dispatcher, _) = setup_snake(); assert_eq!(dispatcher.balance_of(OWNER()), 1); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_balance_of() { let dispatcher = setup_non_erc721(); @@ -175,14 +171,13 @@ fn test_dual_balance_of_exists_and_panics() { } #[test] -#[ignore] fn test_dual_owner_of() { let (dispatcher, _) = setup_snake(); assert_eq!(dispatcher.owner_of(TOKEN_ID), OWNER()); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_owner_of() { let dispatcher = setup_non_erc721(); @@ -197,7 +192,6 @@ fn test_dual_owner_of_exists_and_panics() { } #[test] -#[ignore] fn test_dual_transfer_from() { let (dispatcher, target) = setup_snake(); dispatcher.transfer_from(OWNER(), RECIPIENT(), TOKEN_ID); @@ -205,7 +199,7 @@ fn test_dual_transfer_from() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_transfer_from() { let dispatcher = setup_non_erc721(); @@ -220,7 +214,6 @@ fn test_dual_transfer_from_exists_and_panics() { } #[test] -#[ignore] fn test_dual_safe_transfer_from() { let (dispatcher, target) = setup_snake(); let receiver = setup_receiver(); @@ -229,7 +222,7 @@ fn test_dual_safe_transfer_from() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_safe_transfer_from() { let dispatcher = setup_non_erc721(); @@ -244,17 +237,16 @@ fn test_dual_safe_transfer_from_exists_and_panics() { } #[test] -#[ignore] fn test_dual_get_approved() { let (dispatcher, target) = setup_snake(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); target.approve(SPENDER(), TOKEN_ID); assert_eq!(dispatcher.get_approved(TOKEN_ID), SPENDER()); } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_get_approved() { let dispatcher = setup_non_erc721(); @@ -269,11 +261,10 @@ fn test_dual_get_approved_exists_and_panics() { } #[test] -#[ignore] fn test_dual_set_approval_for_all() { let (dispatcher, target) = setup_snake(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.set_approval_for_all(OPERATOR(), true); let is_approved_for_all = target.is_approved_for_all(OWNER(), OPERATOR()); @@ -281,7 +272,7 @@ fn test_dual_set_approval_for_all() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_set_approval_for_all() { let dispatcher = setup_non_erc721(); @@ -296,11 +287,10 @@ fn test_dual_set_approval_for_all_exists_and_panics() { } #[test] -#[ignore] fn test_dual_is_approved_for_all() { let (dispatcher, target) = setup_snake(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); target.set_approval_for_all(OPERATOR(), true); let is_approved_for_all = dispatcher.is_approved_for_all(OWNER(), OPERATOR()); @@ -308,7 +298,7 @@ fn test_dual_is_approved_for_all() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_is_approved_for_all() { let dispatcher = setup_non_erc721(); @@ -323,7 +313,6 @@ fn test_dual_is_approved_for_all_exists_and_panics() { } #[test] -#[ignore] fn test_dual_token_uri() { let (dispatcher, _) = setup_snake(); let uri = dispatcher.token_uri(TOKEN_ID); @@ -332,7 +321,7 @@ fn test_dual_token_uri() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_token_uri() { let dispatcher = setup_non_erc721(); @@ -347,7 +336,6 @@ fn test_dual_token_uri_exists_and_panics() { } #[test] -#[ignore] fn test_dual_supports_interface() { let (dispatcher, _) = setup_snake(); let supports_ierc721 = dispatcher.supports_interface(IERC721_ID); @@ -355,7 +343,7 @@ fn test_dual_supports_interface() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_supports_interface() { let dispatcher = setup_non_erc721(); @@ -374,14 +362,14 @@ fn test_dual_supports_interface_exists_and_panics() { // #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_balanceOf() { let (dispatcher, _) = setup_camel(); assert_eq!(dispatcher.balance_of(OWNER()), 1); } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_balanceOf_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); @@ -389,7 +377,7 @@ fn test_dual_balanceOf_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_ownerOf() { let (dispatcher, _) = setup_camel(); let current_owner = dispatcher.owner_of(TOKEN_ID); @@ -397,7 +385,7 @@ fn test_dual_ownerOf() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_ownerOf_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); @@ -405,11 +393,11 @@ fn test_dual_ownerOf_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_transferFrom() { let (dispatcher, target) = setup_camel(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transfer_from(OWNER(), RECIPIENT(), TOKEN_ID); let current_owner = target.ownerOf(TOKEN_ID); @@ -417,7 +405,7 @@ fn test_dual_transferFrom() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_transferFrom_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); @@ -425,7 +413,7 @@ fn test_dual_transferFrom_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_safeTransferFrom() { let (dispatcher, target) = setup_camel(); let receiver = setup_receiver(); @@ -436,7 +424,7 @@ fn test_dual_safeTransferFrom() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_safeTransferFrom_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); @@ -444,11 +432,11 @@ fn test_dual_safeTransferFrom_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_getApproved() { let (dispatcher, _) = setup_camel(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(SPENDER(), TOKEN_ID); let approved = dispatcher.get_approved(TOKEN_ID); @@ -456,7 +444,7 @@ fn test_dual_getApproved() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_getApproved_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); @@ -464,11 +452,11 @@ fn test_dual_getApproved_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_setApprovalForAll() { let (dispatcher, target) = setup_camel(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.set_approval_for_all(OPERATOR(), true); let is_approved_for_all = target.isApprovedForAll(OWNER(), OPERATOR()); @@ -476,7 +464,7 @@ fn test_dual_setApprovalForAll() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_setApprovalForAll_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); @@ -484,11 +472,11 @@ fn test_dual_setApprovalForAll_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_isApprovedForAll() { let (dispatcher, target) = setup_camel(); - start_cheat_caller_address(test_address(), OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); target.setApprovalForAll(OPERATOR(), true); let is_approved_for_all = dispatcher.is_approved_for_all(OWNER(), OPERATOR()); @@ -496,7 +484,7 @@ fn test_dual_isApprovedForAll() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_isApprovedForAll_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); @@ -504,7 +492,7 @@ fn test_dual_isApprovedForAll_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_tokenURI() { let (dispatcher, _) = setup_camel(); let uri = dispatcher.token_uri(TOKEN_ID); @@ -513,7 +501,7 @@ fn test_dual_tokenURI() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_tokenURI_exists_and_panics() { let (_, dispatcher) = setup_erc721_panic(); diff --git a/src/tests/token/erc721/test_dual721_receiver.cairo b/src/tests/token/erc721/test_dual721_receiver.cairo index f70d232d8..1a5ae99e4 100644 --- a/src/tests/token/erc721/test_dual721_receiver.cairo +++ b/src/tests/token/erc721/test_dual721_receiver.cairo @@ -62,7 +62,7 @@ fn test_dual_on_erc721_received() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_on_erc721_received() { let dispatcher = setup_non_erc721_receiver(); @@ -70,7 +70,6 @@ fn test_dual_no_on_erc721_received() { } #[test] -#[ignore] #[should_panic(expected: ("Some error",))] fn test_dual_on_erc721_received_exists_and_panics() { let (dispatcher, _) = setup_erc721_receiver_panic(); @@ -82,7 +81,7 @@ fn test_dual_on_erc721_received_exists_and_panics() { // #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_onERC721Received() { let (dispatcher, _) = setup_camel(); @@ -92,7 +91,7 @@ fn test_dual_onERC721Received() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_onERC721Received_exists_and_panics() { let (_, dispatcher) = setup_erc721_receiver_panic(); diff --git a/src/tests/token/erc721/test_erc721.cairo b/src/tests/token/erc721/test_erc721.cairo index 365e8c942..8055d9c17 100644 --- a/src/tests/token/erc721/test_erc721.cairo +++ b/src/tests/token/erc721/test_erc721.cairo @@ -635,9 +635,9 @@ fn test_safeTransferFrom_to_account_camel() { #[test] fn test_safe_transfer_from_to_receiver() { let mut state = setup(); + let receiver = setup_receiver(); let contract_address = test_address(); let mut spy = spy_events(); - let receiver = setup_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); @@ -653,9 +653,9 @@ fn test_safe_transfer_from_to_receiver() { #[test] fn test_safeTransferFrom_to_receiver() { let mut state = setup(); + let receiver = setup_receiver(); let contract_address = test_address(); let mut spy = spy_events(); - let receiver = setup_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); @@ -669,12 +669,12 @@ fn test_safeTransferFrom_to_receiver() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_transfer_from_to_receiver_camel() { let mut state = setup(); + let receiver = setup_camel_receiver(); let contract_address = test_address(); let mut spy = spy_events(); - let receiver = setup_camel_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); @@ -688,12 +688,12 @@ fn test_safe_transfer_from_to_receiver_camel() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeTransferFrom_to_receiver_camel() { let mut state = setup(); - let contract_address = test_address(); - let mut spy = spy_events(); let receiver = setup_camel_receiver(); + let mut spy = spy_events(); + let contract_address = test_address(); let token_id = TOKEN_ID; let owner = OWNER(); @@ -731,7 +731,7 @@ fn test_safeTransferFrom_to_receiver_failure() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ('ERC721: safe transfer failed',))] fn test_safe_transfer_from_to_receiver_failure_camel() { let mut state = setup(); @@ -744,7 +744,7 @@ fn test_safe_transfer_from_to_receiver_failure_camel() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ('ERC721: safe transfer failed',))] fn test_safeTransferFrom_to_receiver_failure_camel() { let mut state = setup(); @@ -757,7 +757,7 @@ fn test_safeTransferFrom_to_receiver_failure_camel() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_safe_transfer_from_to_non_receiver() { let mut state = setup(); @@ -770,7 +770,7 @@ fn test_safe_transfer_from_to_non_receiver() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_safeTransferFrom_to_non_receiver() { let mut state = setup(); @@ -861,17 +861,18 @@ fn test_safeTransferFrom_to_owner() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_transfer_from_to_owner_camel() { let mut state = COMPONENT_STATE(); - let contract_address = test_address(); - let mut spy = spy_events(); let token_id = TOKEN_ID; let owner = setup_camel_receiver(); + let contract_address = test_address(); state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(owner, token_id); + let mut spy = spy_events(); + assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); @@ -884,11 +885,10 @@ fn test_safe_transfer_from_to_owner_camel() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeTransferFrom_to_owner_camel() { let mut state = COMPONENT_STATE(); let contract_address = test_address(); - let mut spy = spy_events(); let token_id = TOKEN_ID; let owner = setup_camel_receiver(); @@ -898,6 +898,8 @@ fn test_safeTransferFrom_to_owner_camel() { assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); + let mut spy = spy_events(); + start_cheat_caller_address(contract_address, owner); state.safeTransferFrom(owner, owner, token_id, DATA(true)); spy.assert_only_event_transfer(contract_address, owner, owner, token_id); @@ -951,7 +953,7 @@ fn test_safeTransferFrom_approved() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_transfer_from_approved_camel() { let mut state = setup(); let contract_address = test_address(); @@ -974,7 +976,7 @@ fn test_safe_transfer_from_approved_camel() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeTransferFrom_approved_camel() { let mut state = setup(); let contract_address = test_address(); @@ -1041,7 +1043,7 @@ fn test_safeTransferFrom_approved_for_all() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_transfer_from_approved_for_all_camel() { let mut state = setup(); let contract_address = test_address(); @@ -1063,7 +1065,7 @@ fn test_safe_transfer_from_approved_for_all_camel() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeTransferFrom_approved_for_all_camel() { let mut state = setup(); let contract_address = test_address(); @@ -1196,7 +1198,7 @@ fn test__safe_mint_to_receiver() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test__safe_mint_to_receiver_camel() { let mut state = COMPONENT_STATE(); let contract_address = test_address(); @@ -1242,7 +1244,7 @@ fn test__safe_mint_to_account_camel() { } #[test] -#[ignore] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test__safe_mint_to_non_receiver() { let mut state = COMPONENT_STATE(); @@ -1267,7 +1269,7 @@ fn test__safe_mint_to_receiver_failure() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ('ERC721: safe mint failed',))] fn test__safe_mint_to_receiver_failure_camel() { let mut state = COMPONENT_STATE(); diff --git a/src/tests/utils/common.cairo b/src/tests/utils/common.cairo index 88c443cfb..c5920b969 100644 --- a/src/tests/utils/common.cairo +++ b/src/tests/utils/common.cairo @@ -1,5 +1,6 @@ use core::starknet::SyscallResultTrait; use snforge_std::{declare, get_class_hash, ContractClass, ContractClassTrait}; +use snforge_std::{start_cheat_caller_address, stop_cheat_caller_address}; use starknet::ContractAddress; pub fn deploy(contract_class: ContractClass, calldata: Array) -> ContractAddress { From 8fe4f801cd9cb1bbd908b54bf53b66d83477c489 Mon Sep 17 00:00:00 2001 From: immrsd <103599616+immrsd@users.noreply.github.com> Date: Wed, 17 Jul 2024 14:02:44 +0200 Subject: [PATCH 10/45] Migrate Ownable tests (#1033) * Update ERC20Votes tests * Run linter * Add test helpers for Ownable tests * Migrate Ownable tests * Migrate OwnableTwoStep tests * Migrate Ownable Dual Dispatcher tests * Support event changes in snforge 0.26 * Resolve review issues * Address review comments --- src/tests.cairo | 8 +- src/tests/access.cairo | 4 +- src/tests/access/common.cairo | 44 ++++--- src/tests/access/test_dual_ownable.cairo | 54 ++++---- src/tests/access/test_ownable.cairo | 52 ++++---- src/tests/access/test_ownable_twostep.cairo | 133 +++++++++++--------- 6 files changed, 166 insertions(+), 129 deletions(-) diff --git a/src/tests.cairo b/src/tests.cairo index eceac55c6..fcb9fb1dc 100644 --- a/src/tests.cairo +++ b/src/tests.cairo @@ -1,11 +1,11 @@ -// #[cfg(test)] -// mod access; +#[cfg(test)] +mod access; // #[cfg(test)] // mod account; // #[cfg(test)] // mod cryptography; -// #[cfg(test)] -// mod introspection; +#[cfg(test)] +mod introspection; mod mocks; // #[cfg(test)] // mod presets; diff --git a/src/tests/access.cairo b/src/tests/access.cairo index cfa981899..c59f6dbc4 100644 --- a/src/tests/access.cairo +++ b/src/tests/access.cairo @@ -1,7 +1,7 @@ pub(crate) mod common; -mod test_accesscontrol; -mod test_dual_accesscontrol; +// mod test_accesscontrol; +// mod test_dual_accesscontrol; mod test_dual_ownable; mod test_ownable; mod test_ownable_twostep; diff --git a/src/tests/access/common.cairo b/src/tests/access/common.cairo index 752b08584..6836a3437 100644 --- a/src/tests/access/common.cairo +++ b/src/tests/access/common.cairo @@ -1,28 +1,32 @@ use openzeppelin::access::ownable::OwnableComponent::OwnershipTransferred; use openzeppelin::access::ownable::OwnableComponent; +use openzeppelin::tests::utils::EventSpyExt; use openzeppelin::tests::utils; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::EventSpy; use starknet::ContractAddress; -pub(crate) fn assert_only_event_ownership_transferred( - contract: ContractAddress, previous_owner: ContractAddress, new_owner: ContractAddress -) { - assert_event_ownership_transferred(contract, previous_owner, new_owner); - utils::assert_no_events_left(contract); -} - -pub(crate) fn assert_event_ownership_transferred( - contract: ContractAddress, previous_owner: ContractAddress, new_owner: ContractAddress -) { - let event = utils::pop_log::(contract).unwrap(); - let expected = OwnableComponent::Event::OwnershipTransferred( - OwnershipTransferred { previous_owner, new_owner } - ); - assert!(event == expected); +#[generate_trait] +pub(crate) impl OwnableSpyHelpersImpl of OwnableSpyHelpers { + fn assert_only_event_ownership_transferred( + ref self: EventSpy, + contract: ContractAddress, + previous_owner: ContractAddress, + new_owner: ContractAddress + ) { + self.assert_event_ownership_transferred(contract, previous_owner, new_owner); + self.assert_no_events_left_from(contract); + } - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("OwnershipTransferred")); - indexed_keys.append_serde(previous_owner); - indexed_keys.append_serde(new_owner); - utils::assert_indexed_keys(event, indexed_keys.span()); + fn assert_event_ownership_transferred( + ref self: EventSpy, + contract: ContractAddress, + previous_owner: ContractAddress, + new_owner: ContractAddress + ) { + let expected = OwnableComponent::Event::OwnershipTransferred( + OwnershipTransferred { previous_owner, new_owner } + ); + self.assert_emitted_single(contract, expected); + } } diff --git a/src/tests/access/test_dual_ownable.cairo b/src/tests/access/test_dual_ownable.cairo index c29d09fef..8d24aaae7 100644 --- a/src/tests/access/test_dual_ownable.cairo +++ b/src/tests/access/test_dual_ownable.cairo @@ -1,9 +1,8 @@ use core::num::traits::Zero; -use openzeppelin::access::ownable::dual_ownable::DualCaseOwnable; -use openzeppelin::access::ownable::dual_ownable::DualCaseOwnableTrait; -use openzeppelin::access::ownable::interface::IOwnableCamelOnlyDispatcher; -use openzeppelin::access::ownable::interface::IOwnableDispatcher; -use openzeppelin::access::ownable::interface::IOwnableDispatcherTrait; +use openzeppelin::access::ownable::dual_ownable::{DualCaseOwnable, DualCaseOwnableTrait}; +use openzeppelin::access::ownable::interface::{ + IOwnableDispatcher, IOwnableCamelOnlyDispatcher, IOwnableDispatcherTrait +}; use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::mocks::ownable_mocks::{ CamelOwnableMock, CamelOwnablePanicMock, SnakeOwnableMock, SnakeOwnablePanicMock @@ -11,7 +10,7 @@ use openzeppelin::tests::mocks::ownable_mocks::{ use openzeppelin::tests::utils::constants::{OWNER, NEW_OWNER}; use openzeppelin::tests::utils; use openzeppelin::utils::serde::SerializedAppend; -use starknet::testing::set_contract_address; +use snforge_std::start_cheat_caller_address; // // Setup @@ -20,14 +19,14 @@ use starknet::testing::set_contract_address; fn setup_snake() -> (DualCaseOwnable, IOwnableDispatcher) { let mut calldata = array![]; calldata.append_serde(OWNER()); - let target = utils::deploy(SnakeOwnableMock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("SnakeOwnableMock", calldata); (DualCaseOwnable { contract_address: target }, IOwnableDispatcher { contract_address: target }) } fn setup_camel() -> (DualCaseOwnable, IOwnableCamelOnlyDispatcher) { let mut calldata = array![]; calldata.append_serde(OWNER()); - let target = utils::deploy(CamelOwnableMock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("CamelOwnableMock", calldata); ( DualCaseOwnable { contract_address: target }, IOwnableCamelOnlyDispatcher { contract_address: target } @@ -36,13 +35,13 @@ fn setup_camel() -> (DualCaseOwnable, IOwnableCamelOnlyDispatcher) { fn setup_non_ownable() -> DualCaseOwnable { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("NonImplementingMock", calldata); DualCaseOwnable { contract_address: target } } fn setup_ownable_panic() -> (DualCaseOwnable, DualCaseOwnable) { - let snake_target = utils::deploy(SnakeOwnablePanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelOwnablePanicMock::TEST_CLASS_HASH, array![]); + let snake_target = utils::declare_and_deploy("SnakeOwnablePanicMock", array![]); + let camel_target = utils::declare_and_deploy("CamelOwnablePanicMock", array![]); ( DualCaseOwnable { contract_address: snake_target }, DualCaseOwnable { contract_address: camel_target } @@ -66,6 +65,7 @@ fn test_dual_owner() { } #[test] +#[ignore] // REASON: inconsistent ENTRYPOINT_NOT_FOUND panic message #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_owner() { let dispatcher = setup_non_ownable(); @@ -73,7 +73,7 @@ fn test_dual_no_owner() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_owner_exists_and_panics() { let (dispatcher, _) = setup_ownable_panic(); dispatcher.owner(); @@ -86,7 +86,7 @@ fn test_dual_owner_exists_and_panics() { #[test] fn test_dual_transfer_ownership() { let (dispatcher, target) = setup_snake(); - set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transfer_ownership(NEW_OWNER()); let current_owner = target.owner(); @@ -94,6 +94,7 @@ fn test_dual_transfer_ownership() { } #[test] +#[ignore] // REASON: inconsistent ENTRYPOINT_NOT_FOUND panic message #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_transfer_ownership() { let dispatcher = setup_non_ownable(); @@ -101,7 +102,7 @@ fn test_dual_no_transfer_ownership() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_transfer_ownership_exists_and_panics() { let (dispatcher, _) = setup_ownable_panic(); dispatcher.transfer_ownership(NEW_OWNER()); @@ -110,7 +111,7 @@ fn test_dual_transfer_ownership_exists_and_panics() { #[test] fn test_dual_renounce_ownership() { let (dispatcher, target) = setup_snake(); - set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.renounce_ownership(); let current_owner = target.owner(); @@ -118,6 +119,7 @@ fn test_dual_renounce_ownership() { } #[test] +#[ignore] // REASON: inconsistent ENTRYPOINT_NOT_FOUND panic message #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_renounce_ownership() { let dispatcher = setup_non_ownable(); @@ -125,7 +127,7 @@ fn test_dual_no_renounce_ownership() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_renounce_ownership_exists_and_panics() { let (dispatcher, _) = setup_ownable_panic(); dispatcher.renounce_ownership(); @@ -136,9 +138,10 @@ fn test_dual_renounce_ownership_exists_and_panics() { // #[test] +#[ignore] fn test_dual_transferOwnership() { let (dispatcher, _) = setup_camel(); - set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transfer_ownership(NEW_OWNER()); let current_owner = dispatcher.owner(); @@ -146,16 +149,18 @@ fn test_dual_transferOwnership() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_transferOwnership_exists_and_panics() { - let (_, dispatcher) = setup_ownable_panic(); - dispatcher.transfer_ownership(NEW_OWNER()); + let (_, camel_dispatcher) = setup_ownable_panic(); + camel_dispatcher.transfer_ownership(NEW_OWNER()); } #[test] +#[ignore] fn test_dual_renounceOwnership() { let (dispatcher, _) = setup_camel(); - set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.renounce_ownership(); let current_owner = dispatcher.owner(); @@ -163,9 +168,10 @@ fn test_dual_renounceOwnership() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] +#[should_panic(expected: ("Some error",))] fn test_dual_renounceOwnership_exists_and_panics() { - let (_, dispatcher) = setup_ownable_panic(); - dispatcher.renounce_ownership(); + let (_, camel_dispatcher) = setup_ownable_panic(); + camel_dispatcher.renounce_ownership(); } diff --git a/src/tests/access/test_ownable.cairo b/src/tests/access/test_ownable.cairo index ea4b97c74..463406916 100644 --- a/src/tests/access/test_ownable.cairo +++ b/src/tests/access/test_ownable.cairo @@ -4,11 +4,10 @@ use openzeppelin::access::ownable::OwnableComponent; use openzeppelin::access::ownable::interface::{IOwnable, IOwnableCamelOnly}; use openzeppelin::tests::mocks::ownable_mocks::DualCaseOwnableMock; use openzeppelin::tests::utils::constants::{ZERO, OTHER, OWNER}; -use openzeppelin::tests::utils; +use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::storage::StorageMemberAccessTrait; -use starknet::testing; -use super::common::assert_only_event_ownership_transferred; +use super::common::OwnableSpyHelpers; // // Setup @@ -23,7 +22,6 @@ fn COMPONENT_STATE() -> ComponentState { fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(OWNER()); - utils::drop_event(ZERO()); state } @@ -34,13 +32,14 @@ fn setup() -> ComponentState { #[test] fn test_initializer_owner() { let mut state = COMPONENT_STATE(); + let mut spy = spy_events(); let current_owner = state.Ownable_owner.read(); assert!(current_owner.is_zero()); state.initializer(OWNER()); - assert_only_event_ownership_transferred(ZERO(), ZERO(), OWNER()); + spy.assert_only_event_ownership_transferred(test_address(), ZERO(), OWNER()); let new_owner = state.Ownable_owner.read(); assert_eq!(new_owner, OWNER()); @@ -53,7 +52,7 @@ fn test_initializer_owner() { #[test] fn test_assert_only_owner() { let state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.assert_only_owner(); } @@ -61,7 +60,7 @@ fn test_assert_only_owner() { #[should_panic(expected: ('Caller is not the owner',))] fn test_assert_only_owner_when_not_owner() { let state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.assert_only_owner(); } @@ -79,9 +78,10 @@ fn test_assert_only_owner_when_caller_zero() { #[test] fn test__transfer_ownership() { let mut state = setup(); + let mut spy = spy_events(); state._transfer_ownership(OTHER()); - assert_only_event_ownership_transferred(ZERO(), OWNER(), OTHER()); + spy.assert_only_event_ownership_transferred(test_address(), OWNER(), OTHER()); let current_owner = state.Ownable_owner.read(); assert_eq!(current_owner, OTHER()); @@ -94,10 +94,12 @@ fn test__transfer_ownership() { #[test] fn test_transfer_ownership() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.transfer_ownership(OTHER()); - assert_only_event_ownership_transferred(ZERO(), OWNER(), OTHER()); + spy.assert_only_event_ownership_transferred(contract_address, OWNER(), OTHER()); assert_eq!(state.owner(), OTHER()); } @@ -105,7 +107,7 @@ fn test_transfer_ownership() { #[should_panic(expected: ('New owner is the zero address',))] fn test_transfer_ownership_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.transfer_ownership(ZERO()); } @@ -120,17 +122,19 @@ fn test_transfer_ownership_from_zero() { #[should_panic(expected: ('Caller is not the owner',))] fn test_transfer_ownership_from_nonowner() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.transfer_ownership(OTHER()); } #[test] fn test_transferOwnership() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.transferOwnership(OTHER()); - assert_only_event_ownership_transferred(ZERO(), OWNER(), OTHER()); + spy.assert_only_event_ownership_transferred(contract_address, OWNER(), OTHER()); assert_eq!(state.owner(), OTHER()); } @@ -138,7 +142,7 @@ fn test_transferOwnership() { #[should_panic(expected: ('New owner is the zero address',))] fn test_transferOwnership_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + start_cheat_caller_address(test_address(), OWNER()); state.transferOwnership(ZERO()); } @@ -153,7 +157,7 @@ fn test_transferOwnership_from_zero() { #[should_panic(expected: ('Caller is not the owner',))] fn test_transferOwnership_from_nonowner() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.transferOwnership(OTHER()); } @@ -164,10 +168,12 @@ fn test_transferOwnership_from_nonowner() { #[test] fn test_renounce_ownership() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.renounce_ownership(); - assert_only_event_ownership_transferred(ZERO(), OWNER(), ZERO()); + spy.assert_only_event_ownership_transferred(contract_address, OWNER(), ZERO()); assert!(state.owner().is_zero()); } @@ -182,17 +188,19 @@ fn test_renounce_ownership_from_zero_address() { #[should_panic(expected: ('Caller is not the owner',))] fn test_renounce_ownership_from_nonowner() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.renounce_ownership(); } #[test] fn test_renounceOwnership() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.renounceOwnership(); - assert_only_event_ownership_transferred(ZERO(), OWNER(), ZERO()); + spy.assert_only_event_ownership_transferred(contract_address, OWNER(), ZERO()); assert!(state.owner().is_zero()); } @@ -207,6 +215,6 @@ fn test_renounceOwnership_from_zero_address() { #[should_panic(expected: ('Caller is not the owner',))] fn test_renounceOwnership_from_nonowner() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.renounceOwnership(); } diff --git a/src/tests/access/test_ownable_twostep.cairo b/src/tests/access/test_ownable_twostep.cairo index 0b300ddc4..55b58b09a 100644 --- a/src/tests/access/test_ownable_twostep.cairo +++ b/src/tests/access/test_ownable_twostep.cairo @@ -1,17 +1,16 @@ use core::num::traits::Zero; -use openzeppelin::access::ownable::OwnableComponent::InternalTrait; -use openzeppelin::access::ownable::OwnableComponent::OwnershipTransferStarted; +use openzeppelin::access::ownable::OwnableComponent::{InternalTrait, OwnershipTransferStarted}; use openzeppelin::access::ownable::OwnableComponent; use openzeppelin::access::ownable::interface::{IOwnableTwoStep, IOwnableTwoStepCamelOnly}; use openzeppelin::tests::mocks::ownable_mocks::DualCaseTwoStepOwnableMock; use openzeppelin::tests::utils::constants::{ZERO, OWNER, OTHER, NEW_OWNER}; -use openzeppelin::tests::utils; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::{EventSpy, spy_events, start_cheat_caller_address, test_address}; use starknet::ContractAddress; use starknet::storage::StorageMemberAccessTrait; -use starknet::testing; -use super::common::assert_only_event_ownership_transferred; +use super::common::OwnableSpyHelpers; // // Setup @@ -27,7 +26,6 @@ fn COMPONENT_STATE() -> ComponentState { fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(OWNER()); - utils::drop_event(ZERO()); state } @@ -38,11 +36,12 @@ fn setup() -> ComponentState { #[test] fn test_initializer_owner_pending_owner() { let mut state = COMPONENT_STATE(); + let mut spy = spy_events(); assert!(state.Ownable_owner.read().is_zero()); assert!(state.Ownable_pending_owner.read().is_zero()); state.initializer(OWNER()); - assert_only_event_ownership_transferred(ZERO(), ZERO(), OWNER()); + spy.assert_only_event_ownership_transferred(test_address(), ZERO(), OWNER()); assert_eq!(state.Ownable_owner.read(), OWNER()); assert!(state.Ownable_pending_owner.read().is_zero()); @@ -55,11 +54,12 @@ fn test_initializer_owner_pending_owner() { #[test] fn test__accept_ownership() { let mut state = setup(); + let mut spy = spy_events(); state.Ownable_pending_owner.write(OTHER()); state._accept_ownership(); - assert_only_event_ownership_transferred(ZERO(), OWNER(), OTHER()); + spy.assert_only_event_ownership_transferred(test_address(), OWNER(), OTHER()); assert_eq!(state.owner(), OTHER()); assert!(state.pending_owner().is_zero()); } @@ -71,10 +71,11 @@ fn test__accept_ownership() { #[test] fn test__propose_owner() { let mut state = setup(); + let mut spy = spy_events(); state._propose_owner(OTHER()); - assert_event_ownership_transfer_started(OWNER(), OTHER()); + spy.assert_event_ownership_transfer_started(test_address(), OWNER(), OTHER()); assert_eq!(state.owner(), OWNER()); assert_eq!(state.pending_owner(), OTHER()); } @@ -84,17 +85,19 @@ fn test__propose_owner() { #[test] fn test_transfer_ownership() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.transfer_ownership(OTHER()); - assert_event_ownership_transfer_started(OWNER(), OTHER()); + spy.assert_event_ownership_transfer_started(contract_address, OWNER(), OTHER()); assert_eq!(state.owner(), OWNER()); assert_eq!(state.pending_owner(), OTHER()); // Transferring to yet another owner while pending is set should work state.transfer_ownership(NEW_OWNER()); - assert_event_ownership_transfer_started(OWNER(), NEW_OWNER()); + spy.assert_event_ownership_transfer_started(contract_address, OWNER(), NEW_OWNER()); assert_eq!(state.owner(), OWNER()); assert_eq!(state.pending_owner(), NEW_OWNER()); } @@ -102,10 +105,12 @@ fn test_transfer_ownership() { #[test] fn test_transfer_ownership_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.transfer_ownership(ZERO()); - assert_event_ownership_transfer_started(OWNER(), ZERO()); + spy.assert_event_ownership_transfer_started(contract_address, OWNER(), ZERO()); assert_eq!(state.owner(), OWNER()); assert_eq!(state.pending_owner(), ZERO()); } @@ -121,24 +126,26 @@ fn test_transfer_ownership_from_zero() { #[should_panic(expected: ('Caller is not the owner',))] fn test_transfer_ownership_from_nonowner() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.transfer_ownership(OTHER()); } #[test] fn test_transferOwnership() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.transferOwnership(OTHER()); - assert_event_ownership_transfer_started(OWNER(), OTHER()); + spy.assert_event_ownership_transfer_started(contract_address, OWNER(), OTHER()); assert_eq!(state.owner(), OWNER()); assert_eq!(state.pendingOwner(), OTHER()); // Transferring to yet another owner while pending is set should work state.transferOwnership(NEW_OWNER()); - assert_event_ownership_transfer_started(OWNER(), NEW_OWNER()); + spy.assert_event_ownership_transfer_started(contract_address, OWNER(), NEW_OWNER()); assert_eq!(state.owner(), OWNER()); assert_eq!(state.pendingOwner(), NEW_OWNER()); } @@ -146,10 +153,12 @@ fn test_transferOwnership() { #[test] fn test_transferOwnership_to_zero() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.transferOwnership(ZERO()); - assert_event_ownership_transfer_started(OWNER(), ZERO()); + spy.assert_event_ownership_transfer_started(contract_address, OWNER(), ZERO()); assert_eq!(state.owner(), OWNER()); assert!(state.pendingOwner().is_zero()); } @@ -165,7 +174,7 @@ fn test_transferOwnership_from_zero() { #[should_panic(expected: ('Caller is not the owner',))] fn test_transferOwnership_from_nonowner() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.transferOwnership(OTHER()); } @@ -176,12 +185,14 @@ fn test_transferOwnership_from_nonowner() { #[test] fn test_accept_ownership() { let mut state = setup(); + let mut spy = spy_events(); + let contract_address = test_address(); state.Ownable_pending_owner.write(OTHER()); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(contract_address, OTHER()); state.accept_ownership(); - assert_only_event_ownership_transferred(ZERO(), OWNER(), OTHER()); + spy.assert_only_event_ownership_transferred(contract_address, OWNER(), OTHER()); assert_eq!(state.owner(), OTHER()); assert!(state.pending_owner().is_zero()); } @@ -191,19 +202,21 @@ fn test_accept_ownership() { fn test_accept_ownership_from_nonpending() { let mut state = setup(); state.Ownable_pending_owner.write(NEW_OWNER()); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.accept_ownership(); } #[test] fn test_acceptOwnership() { let mut state = setup(); + let mut spy = spy_events(); + let contract_address = test_address(); state.Ownable_pending_owner.write(OTHER()); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(contract_address, OTHER()); state.acceptOwnership(); - assert_only_event_ownership_transferred(ZERO(), OWNER(), OTHER()); + spy.assert_only_event_ownership_transferred(contract_address, OWNER(), OTHER()); assert_eq!(state.owner(), OTHER()); assert!(state.pendingOwner().is_zero()); } @@ -213,7 +226,7 @@ fn test_acceptOwnership() { fn test_acceptOwnership_from_nonpending() { let mut state = setup(); state.Ownable_pending_owner.write(NEW_OWNER()); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.acceptOwnership(); } @@ -224,10 +237,12 @@ fn test_acceptOwnership_from_nonpending() { #[test] fn test_renounce_ownership() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.renounce_ownership(); - assert_only_event_ownership_transferred(ZERO(), OWNER(), ZERO()); + spy.assert_only_event_ownership_transferred(contract_address, OWNER(), ZERO()); assert!(state.owner().is_zero()); } @@ -243,17 +258,19 @@ fn test_renounce_ownership_from_zero_address() { #[should_panic(expected: ('Caller is not the owner',))] fn test_renounce_ownership_from_nonowner() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.renounce_ownership(); } #[test] fn test_renounceOwnership() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.renounceOwnership(); - assert_only_event_ownership_transferred(ZERO(), OWNER(), ZERO()); + spy.assert_only_event_ownership_transferred(contract_address, OWNER(), ZERO()); assert!(state.owner().is_zero()); } @@ -269,24 +286,26 @@ fn test_renounceOwnership_from_zero_address() { #[should_panic(expected: ('Caller is not the owner',))] fn test_renounceOwnership_from_nonowner() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.renounceOwnership(); } #[test] fn test_full_two_step_transfer() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.transfer_ownership(OTHER()); - assert_event_ownership_transfer_started(OWNER(), OTHER()); + spy.assert_event_ownership_transfer_started(contract_address, OWNER(), OTHER()); assert_eq!(state.owner(), OWNER()); assert_eq!(state.pending_owner(), OTHER()); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(contract_address, OTHER()); state.accept_ownership(); - assert_only_event_ownership_transferred(ZERO(), OWNER(), OTHER()); + spy.assert_only_event_ownership_transferred(contract_address, OWNER(), OTHER()); assert_eq!(state.owner(), OTHER()); assert!(state.pending_owner().is_zero()); } @@ -294,22 +313,24 @@ fn test_full_two_step_transfer() { #[test] fn test_pending_accept_after_owner_renounce() { let mut state = setup(); - testing::set_caller_address(OWNER()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OWNER()); state.transfer_ownership(OTHER()); - assert_event_ownership_transfer_started(OWNER(), OTHER()); + spy.assert_event_ownership_transfer_started(contract_address, OWNER(), OTHER()); assert_eq!(state.owner(), OWNER()); assert_eq!(state.pending_owner(), OTHER()); state.renounce_ownership(); - assert_only_event_ownership_transferred(ZERO(), OWNER(), ZERO()); + spy.assert_only_event_ownership_transferred(contract_address, OWNER(), ZERO()); assert!(state.owner().is_zero()); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(contract_address, OTHER()); state.accept_ownership(); - assert_only_event_ownership_transferred(ZERO(), ZERO(), OTHER()); + spy.assert_only_event_ownership_transferred(contract_address, ZERO(), OTHER()); assert_eq!(state.owner(), OTHER()); assert!(state.pending_owner().is_zero()); } @@ -318,19 +339,17 @@ fn test_pending_accept_after_owner_renounce() { // Helpers // -fn assert_event_ownership_transfer_started( - previous_owner: ContractAddress, new_owner: ContractAddress -) { - let event = utils::pop_log::(ZERO()).unwrap(); - let expected = OwnableComponent::Event::OwnershipTransferStarted( - OwnershipTransferStarted { previous_owner, new_owner } - ); - assert!(event == expected); - utils::assert_no_events_left(ZERO()); - - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("OwnershipTransferStarted")); - indexed_keys.append_serde(previous_owner); - indexed_keys.append_serde(new_owner); - utils::assert_indexed_keys(event, indexed_keys.span()); +#[generate_trait] +impl TwoStepSpyHelpersImpl of TwoStepSpyHelpers { + fn assert_event_ownership_transfer_started( + ref self: EventSpy, + from_address: ContractAddress, + previous_owner: ContractAddress, + new_owner: ContractAddress + ) { + let expected = OwnableComponent::Event::OwnershipTransferStarted( + OwnershipTransferStarted { previous_owner, new_owner } + ); + self.assert_emitted_single(from_address, expected); + } } From 6f7130f629bc75cd52c4333bb654d1785dbeefe0 Mon Sep 17 00:00:00 2001 From: immrsd <103599616+immrsd@users.noreply.github.com> Date: Wed, 17 Jul 2024 14:10:01 +0200 Subject: [PATCH 11/45] Migrate Upgrades tests (#1051) * Migrate Upgrades tests to Foundry * Update src/tests/upgrades/test_upgradeable.cairo Co-authored-by: Andrew Fleming * Update src/tests/upgrades/test_upgradeable.cairo Co-authored-by: Andrew Fleming --------- Co-authored-by: Eric Nordelo Co-authored-by: Andrew Fleming --- src/tests.cairo | 4 +- src/tests/upgrades/common.cairo | 24 +++++---- src/tests/upgrades/test_upgradeable.cairo | 60 ++++++++++++----------- src/tests/utils/constants.cairo | 1 + 4 files changed, 48 insertions(+), 41 deletions(-) diff --git a/src/tests.cairo b/src/tests.cairo index fcb9fb1dc..bd3cd67b5 100644 --- a/src/tests.cairo +++ b/src/tests.cairo @@ -13,7 +13,7 @@ mod mocks; mod security; #[cfg(test)] mod token; -// #[cfg(test)] -// mod upgrades; +#[cfg(test)] +mod upgrades; pub mod utils; diff --git a/src/tests/upgrades/common.cairo b/src/tests/upgrades/common.cairo index 0308fd45b..10876b756 100644 --- a/src/tests/upgrades/common.cairo +++ b/src/tests/upgrades/common.cairo @@ -1,16 +1,20 @@ -use openzeppelin::tests::utils::constants::ZERO; -use openzeppelin::tests::utils; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::upgrades::UpgradeableComponent::Upgraded; use openzeppelin::upgrades::UpgradeableComponent; +use snforge_std::{EventSpy, EventSpyAssertionsTrait}; use starknet::{ContractAddress, ClassHash}; -pub(crate) fn assert_event_upgraded(contract: ContractAddress, class_hash: ClassHash) { - let event = utils::pop_log::(contract).unwrap(); - let expected = UpgradeableComponent::Event::Upgraded(Upgraded { class_hash }); - assert!(event == expected); -} +#[generate_trait] +pub(crate) impl UpgradableSpyHelpersImpl of UpgradableSpyHelpers { + fn assert_event_upgraded(ref self: EventSpy, contract: ContractAddress, class_hash: ClassHash) { + let expected = UpgradeableComponent::Event::Upgraded(Upgraded { class_hash }); + self.assert_emitted_single(contract, expected); + } -pub(crate) fn assert_only_event_upgraded(contract: ContractAddress, class_hash: ClassHash) { - assert_event_upgraded(contract, class_hash); - utils::assert_no_events_left(ZERO()); + fn assert_only_event_upgraded( + ref self: EventSpy, contract: ContractAddress, class_hash: ClassHash + ) { + self.assert_event_upgraded(contract, class_hash); + self.assert_no_events_left_from(contract); + } } diff --git a/src/tests/upgrades/test_upgradeable.cairo b/src/tests/upgrades/test_upgradeable.cairo index c022e9c85..183f4f575 100644 --- a/src/tests/upgrades/test_upgradeable.cairo +++ b/src/tests/upgrades/test_upgradeable.cairo @@ -1,30 +1,26 @@ use openzeppelin::tests::mocks::upgrades_mocks::{ IUpgradesV1Dispatcher, IUpgradesV1DispatcherTrait, UpgradesV1 }; -use openzeppelin::tests::mocks::upgrades_mocks::{ - IUpgradesV2Dispatcher, IUpgradesV2DispatcherTrait, UpgradesV2 -}; -use openzeppelin::tests::utils::constants::{CLASS_HASH_ZERO, ZERO}; -use openzeppelin::tests::utils; +use openzeppelin::tests::mocks::upgrades_mocks::{IUpgradesV2Dispatcher, IUpgradesV2DispatcherTrait}; +use openzeppelin::tests::utils::common::{declare_class, deploy}; +use openzeppelin::tests::utils::constants::{CLASS_HASH_ZERO, ZERO, FELT_VALUE as VALUE}; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::upgrades::UpgradeableComponent; -use starknet::ClassHash; - -use super::common::assert_only_event_upgraded; +use snforge_std::ContractClass; +use snforge_std::{spy_events, EventSpy}; -const VALUE: felt252 = 123; - -fn V2_CLASS_HASH() -> ClassHash { - UpgradesV2::TEST_CLASS_HASH.try_into().unwrap() -} +use super::common::UpgradableSpyHelpers; // // Setup // -fn deploy_v1() -> IUpgradesV1Dispatcher { - let calldata = array![]; - let address = utils::deploy(UpgradesV1::TEST_CLASS_HASH, calldata); - IUpgradesV1Dispatcher { contract_address: address } +fn setup_test() -> (IUpgradesV1Dispatcher, ContractClass, ContractClass) { + let v1_class = declare_class("UpgradesV1"); + let v2_class = declare_class("UpgradesV2"); + let v1_contract_address = deploy(v1_class, array![]); + let v1 = IUpgradesV1Dispatcher { contract_address: v1_contract_address }; + (v1, v1_class, v2_class) } // @@ -32,25 +28,27 @@ fn deploy_v1() -> IUpgradesV1Dispatcher { // #[test] -#[should_panic(expected: ('Class hash cannot be zero', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Class hash cannot be zero',))] fn test_upgrade_with_class_hash_zero() { - let v1 = deploy_v1(); + let (v1, _v1_class, _v2_class) = setup_test(); v1.upgrade(CLASS_HASH_ZERO()); } #[test] fn test_upgraded_event() { - let v1 = deploy_v1(); - v1.upgrade(V2_CLASS_HASH()); + let (v1, _v1_class, v2_class) = setup_test(); + let mut spy = spy_events(); - assert_only_event_upgraded(v1.contract_address, V2_CLASS_HASH()); + v1.upgrade(v2_class.class_hash); + + spy.assert_only_event_upgraded(v1.contract_address, v2_class.class_hash); } #[test] fn test_new_selector_after_upgrade() { - let v1 = deploy_v1(); + let (v1, _v1_class, v2_class) = setup_test(); - v1.upgrade(V2_CLASS_HASH()); + v1.upgrade(v2_class.class_hash); let v2 = IUpgradesV2Dispatcher { contract_address: v1.contract_address }; v2.set_value2(VALUE); @@ -59,10 +57,11 @@ fn test_new_selector_after_upgrade() { #[test] fn test_state_persists_after_upgrade() { - let v1 = deploy_v1(); + let (v1, _v1_class, v2_class) = setup_test(); + v1.set_value(VALUE); - v1.upgrade(V2_CLASS_HASH()); + v1.upgrade(v2_class.class_hash); let v2 = IUpgradesV2Dispatcher { contract_address: v1.contract_address }; assert_eq!(v2.get_value(), VALUE); @@ -70,15 +69,18 @@ fn test_state_persists_after_upgrade() { #[test] fn test_remove_selector_passes_in_v1() { - let v1 = deploy_v1(); + let (v1, _v1_class, _v2_class) = setup_test(); + v1.remove_selector(); } #[test] +#[ignore] // REASON: inconsistent ENTRYPOINT_NOT_FOUND panic message #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_remove_selector_fails_in_v2() { - let v1 = deploy_v1(); - v1.upgrade(V2_CLASS_HASH()); + let (v1, _v1_class, v2_class) = setup_test(); + + v1.upgrade(v2_class.class_hash); // We use the v1 dispatcher because remove_selector is not in v2 interface v1.remove_selector(); } diff --git a/src/tests/utils/constants.cairo b/src/tests/utils/constants.cairo index 8f29ca4f9..c84190c20 100644 --- a/src/tests/utils/constants.cairo +++ b/src/tests/utils/constants.cairo @@ -9,6 +9,7 @@ use starknet::secp256_trait::Secp256Trait; pub(crate) const DECIMALS: u8 = 18_u8; pub(crate) const SUPPLY: u256 = 2000; pub(crate) const VALUE: u256 = 300; +pub(crate) const FELT_VALUE: felt252 = 'FELT_VALUE'; pub(crate) const ROLE: felt252 = 'ROLE'; pub(crate) const OTHER_ROLE: felt252 = 'OTHER_ROLE'; pub(crate) const TOKEN_ID: u256 = 21; From 485024536e35a18980a95787648f503d92109a3b Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 18 Jul 2024 10:50:21 +0200 Subject: [PATCH 12/45] Migrate erc20 preset tests (#1055) * feat: include erc20 preset tests * feat: tests updated * feat: remove unused imports * feat: add deployments * Update src/tests/utils/common.cairo Co-authored-by: Andrew Fleming * feat: apply review updates --------- Co-authored-by: Andrew Fleming --- src/tests.cairo | 4 +- src/tests/access/test_dual_ownable.cairo | 6 +- src/tests/presets.cairo | 12 +- src/tests/presets/test_erc20.cairo | 288 ++++++++++++---------- src/tests/upgrades/test_upgradeable.cairo | 27 +- src/tests/utils.cairo | 5 +- src/tests/utils/common.cairo | 63 ++--- src/tests/utils/deployment.cairo | 46 ++++ 8 files changed, 253 insertions(+), 198 deletions(-) create mode 100644 src/tests/utils/deployment.cairo diff --git a/src/tests.cairo b/src/tests.cairo index bd3cd67b5..a3fa799ac 100644 --- a/src/tests.cairo +++ b/src/tests.cairo @@ -7,8 +7,8 @@ mod access; #[cfg(test)] mod introspection; mod mocks; -// #[cfg(test)] -// mod presets; +#[cfg(test)] +mod presets; #[cfg(test)] mod security; #[cfg(test)] diff --git a/src/tests/access/test_dual_ownable.cairo b/src/tests/access/test_dual_ownable.cairo index 8d24aaae7..16c22514f 100644 --- a/src/tests/access/test_dual_ownable.cairo +++ b/src/tests/access/test_dual_ownable.cairo @@ -65,7 +65,7 @@ fn test_dual_owner() { } #[test] -#[ignore] // REASON: inconsistent ENTRYPOINT_NOT_FOUND panic message +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_owner() { let dispatcher = setup_non_ownable(); @@ -94,7 +94,7 @@ fn test_dual_transfer_ownership() { } #[test] -#[ignore] // REASON: inconsistent ENTRYPOINT_NOT_FOUND panic message +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_transfer_ownership() { let dispatcher = setup_non_ownable(); @@ -119,7 +119,7 @@ fn test_dual_renounce_ownership() { } #[test] -#[ignore] // REASON: inconsistent ENTRYPOINT_NOT_FOUND panic message +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_renounce_ownership() { let dispatcher = setup_non_ownable(); diff --git a/src/tests/presets.cairo b/src/tests/presets.cairo index 87e7cb2f4..638696372 100644 --- a/src/tests/presets.cairo +++ b/src/tests/presets.cairo @@ -1,6 +1,8 @@ -mod test_account; -mod test_erc1155; +// mod test_account; +// mod test_erc1155; mod test_erc20; -mod test_erc721; -mod test_eth_account; -mod test_universal_deployer; +// mod test_erc721; +// mod test_eth_account; +// mod test_universal_deployer; + + diff --git a/src/tests/presets/test_erc20.cairo b/src/tests/presets/test_erc20.cairo index b9d7f8e00..a7ead420d 100644 --- a/src/tests/presets/test_erc20.cairo +++ b/src/tests/presets/test_erc20.cairo @@ -1,35 +1,35 @@ use core::integer::BoundedInt; use core::num::traits::Zero; -use openzeppelin::access::ownable::OwnableComponent::OwnershipTransferred; -use openzeppelin::presets::ERC20Upgradeable; +use openzeppelin::presets::interfaces::erc20::{ + ERC20UpgradeableABISafeDispatcher, ERC20UpgradeableABISafeDispatcherTrait +}; use openzeppelin::presets::interfaces::{ ERC20UpgradeableABIDispatcher, ERC20UpgradeableABIDispatcherTrait }; -use openzeppelin::tests::access::common::assert_event_ownership_transferred; -use openzeppelin::tests::mocks::erc20_mocks::SnakeERC20Mock; -use openzeppelin::tests::token::erc20::common::{ - assert_event_approval, assert_only_event_approval, assert_only_event_transfer -}; -use openzeppelin::tests::upgrades::common::assert_only_event_upgraded; +use openzeppelin::tests::access::common::OwnableSpyHelpers; +use openzeppelin::tests::token::erc20::common::ERC20SpyHelpers; +use openzeppelin::tests::upgrades::common::UpgradableSpyHelpers; +use openzeppelin::tests::utils::common::IntoBase16String; use openzeppelin::tests::utils::constants::{ ZERO, OWNER, SPENDER, RECIPIENT, OTHER, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE, CLASS_HASH_ZERO }; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::tests::utils; use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::{spy_events, EventSpy, start_cheat_caller_address}; use starknet::ClassHash; -use starknet::testing; fn V2_CLASS_HASH() -> ClassHash { - SnakeERC20Mock::TEST_CLASS_HASH.try_into().unwrap() + utils::declare_class("SnakeERC20Mock").class_hash } // // Setup // -fn setup_dispatcher_with_event() -> ERC20UpgradeableABIDispatcher { +fn setup_dispatcher_with_event() -> (EventSpy, ERC20UpgradeableABIDispatcher) { let mut calldata = array![]; calldata.append_serde(NAME()); @@ -38,15 +38,15 @@ fn setup_dispatcher_with_event() -> ERC20UpgradeableABIDispatcher { calldata.append_serde(OWNER()); calldata.append_serde(OWNER()); - let address = utils::deploy(ERC20Upgradeable::TEST_CLASS_HASH, calldata); - ERC20UpgradeableABIDispatcher { contract_address: address } + let spy = spy_events(); + let address = utils::declare_and_deploy("ERC20Upgradeable", calldata); + (spy, ERC20UpgradeableABIDispatcher { contract_address: address }) } -fn setup_dispatcher() -> ERC20UpgradeableABIDispatcher { - let dispatcher = setup_dispatcher_with_event(); - utils::drop_event(dispatcher.contract_address); // Ownable `OwnershipTransferred` - utils::drop_event(dispatcher.contract_address); // ERC20 `Transfer` - dispatcher +fn setup_dispatcher() -> (EventSpy, ERC20UpgradeableABIDispatcher) { + let (mut spy, dispatcher) = setup_dispatcher_with_event(); + spy.drop_all_events(); + (spy, dispatcher) } // @@ -55,17 +55,17 @@ fn setup_dispatcher() -> ERC20UpgradeableABIDispatcher { #[test] fn test_constructor() { - let mut dispatcher = setup_dispatcher_with_event(); + let (mut spy, dispatcher) = setup_dispatcher_with_event(); assert_eq!(dispatcher.owner(), OWNER()); - assert_event_ownership_transferred(dispatcher.contract_address, ZERO(), OWNER()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, ZERO(), OWNER()); assert_eq!(dispatcher.name(), NAME()); assert_eq!(dispatcher.symbol(), SYMBOL()); assert_eq!(dispatcher.decimals(), DECIMALS); assert_eq!(dispatcher.total_supply(), SUPPLY); assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY); - assert_only_event_transfer(dispatcher.contract_address, ZERO(), OWNER(), SUPPLY); + spy.assert_only_event_transfer(dispatcher.contract_address, ZERO(), OWNER(), SUPPLY); } // @@ -74,7 +74,7 @@ fn test_constructor() { #[test] fn test_total_supply() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); assert_eq!(dispatcher.total_supply(), SUPPLY); assert_eq!(dispatcher.totalSupply(), SUPPLY); @@ -82,7 +82,7 @@ fn test_total_supply() { #[test] fn test_balance_of() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY); assert_eq!(dispatcher.balanceOf(OWNER()), SUPPLY); @@ -90,9 +90,9 @@ fn test_balance_of() { #[test] fn test_allowance() { - let mut dispatcher = setup_dispatcher(); + let (_, mut dispatcher) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(SPENDER(), VALUE); let allowance = dispatcher.allowance(OWNER(), SPENDER()); @@ -105,31 +105,32 @@ fn test_allowance() { #[test] fn test_approve() { - let mut dispatcher = setup_dispatcher(); + let (mut spy, mut dispatcher) = setup_dispatcher(); let allowance = dispatcher.allowance(OWNER(), SPENDER()); assert!(allowance.is_zero()); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); assert!(dispatcher.approve(SPENDER(), VALUE)); let allowance = dispatcher.allowance(OWNER(), SPENDER()); assert_eq!(allowance, VALUE); - assert_only_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), VALUE); + spy.assert_only_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), VALUE); } #[test] -#[should_panic(expected: ('ERC20: approve from 0', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: approve from 0',))] fn test_approve_from_zero() { - let mut dispatcher = setup_dispatcher(); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.approve(SPENDER(), VALUE); } #[test] -#[should_panic(expected: ('ERC20: approve to 0', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: approve to 0',))] fn test_approve_to_zero() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(Zero::zero(), VALUE); } @@ -139,40 +140,41 @@ fn test_approve_to_zero() { #[test] fn test_transfer() { - let mut dispatcher = setup_dispatcher(); + let (mut spy, mut dispatcher) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); assert!(dispatcher.transfer(RECIPIENT(), VALUE)); assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY - VALUE); assert_eq!(dispatcher.balance_of(RECIPIENT()), VALUE); assert_eq!(dispatcher.total_supply(), SUPPLY); - assert_only_event_transfer(dispatcher.contract_address, OWNER(), RECIPIENT(), VALUE); + spy.assert_only_event_transfer(dispatcher.contract_address, OWNER(), RECIPIENT(), VALUE); } #[test] -#[should_panic(expected: ('ERC20: insufficient balance', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: insufficient balance',))] fn test_transfer_not_enough_balance() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); let balance_plus_one = SUPPLY + 1; dispatcher.transfer(RECIPIENT(), balance_plus_one); } #[test] -#[should_panic(expected: ('ERC20: transfer from 0', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: transfer from 0',))] fn test_transfer_from_zero() { - let mut dispatcher = setup_dispatcher(); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.transfer(RECIPIENT(), VALUE); } #[test] -#[should_panic(expected: ('ERC20: transfer to 0', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: transfer to 0',))] fn test_transfer_to_zero() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transfer(ZERO(), VALUE); } @@ -182,17 +184,17 @@ fn test_transfer_to_zero() { #[test] fn test_transfer_from() { - let mut dispatcher = setup_dispatcher(); + let (mut spy, mut dispatcher) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(SPENDER(), VALUE); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(SPENDER()); + start_cheat_caller_address(dispatcher.contract_address, SPENDER()); assert!(dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE)); - assert_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), 0); - assert_only_event_transfer(dispatcher.contract_address, OWNER(), RECIPIENT(), VALUE); + spy.assert_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), 0); + spy.assert_only_event_transfer(dispatcher.contract_address, OWNER(), RECIPIENT(), VALUE); assert_eq!(dispatcher.balance_of(RECIPIENT()), VALUE); assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY - VALUE); @@ -202,12 +204,12 @@ fn test_transfer_from() { #[test] fn test_transfer_from_doesnt_consume_infinite_allowance() { - let mut dispatcher = setup_dispatcher(); + let (_, mut dispatcher) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(SPENDER(), BoundedInt::max()); - testing::set_contract_address(SPENDER()); + start_cheat_caller_address(dispatcher.contract_address, SPENDER()); dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); let allowance = dispatcher.allowance(OWNER(), SPENDER()); @@ -215,48 +217,48 @@ fn test_transfer_from_doesnt_consume_infinite_allowance() { } #[test] -#[should_panic(expected: ('ERC20: insufficient allowance', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: insufficient allowance',))] fn test_transfer_from_greater_than_allowance() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(SPENDER(), VALUE); - testing::set_contract_address(SPENDER()); + start_cheat_caller_address(dispatcher.contract_address, SPENDER()); let allowance_plus_one = VALUE + 1; dispatcher.transfer_from(OWNER(), RECIPIENT(), allowance_plus_one); } #[test] -#[should_panic(expected: ('ERC20: transfer to 0', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: transfer to 0',))] fn test_transfer_from_to_zero_address() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(SPENDER(), VALUE); - testing::set_contract_address(SPENDER()); + start_cheat_caller_address(dispatcher.contract_address, SPENDER()); dispatcher.transfer_from(OWNER(), Zero::zero(), VALUE); } #[test] -#[should_panic(expected: ('ERC20: insufficient allowance', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: insufficient allowance',))] fn test_transfer_from_from_zero_address() { - let mut dispatcher = setup_dispatcher(); + let (_, mut dispatcher) = setup_dispatcher(); dispatcher.transfer_from(Zero::zero(), RECIPIENT(), VALUE); } #[test] fn test_transferFrom() { - let mut dispatcher = setup_dispatcher(); + let (mut spy, mut dispatcher) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(SPENDER(), VALUE); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(SPENDER()); + start_cheat_caller_address(dispatcher.contract_address, SPENDER()); assert!(dispatcher.transferFrom(OWNER(), RECIPIENT(), VALUE)); - assert_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), 0); - assert_only_event_transfer(dispatcher.contract_address, OWNER(), RECIPIENT(), VALUE); + spy.assert_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), 0); + spy.assert_only_event_transfer(dispatcher.contract_address, OWNER(), RECIPIENT(), VALUE); assert_eq!(dispatcher.balance_of(RECIPIENT()), VALUE); assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY - VALUE); @@ -266,11 +268,11 @@ fn test_transferFrom() { #[test] fn test_transferFrom_doesnt_consume_infinite_allowance() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(SPENDER(), BoundedInt::max()); - testing::set_contract_address(SPENDER()); + start_cheat_caller_address(dispatcher.contract_address, SPENDER()); dispatcher.transferFrom(OWNER(), RECIPIENT(), VALUE); let allowance = dispatcher.allowance(OWNER(), SPENDER()); @@ -278,32 +280,32 @@ fn test_transferFrom_doesnt_consume_infinite_allowance() { } #[test] -#[should_panic(expected: ('ERC20: insufficient allowance', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: insufficient allowance',))] fn test_transferFrom_greater_than_allowance() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(SPENDER(), VALUE); - testing::set_contract_address(SPENDER()); + start_cheat_caller_address(dispatcher.contract_address, SPENDER()); let allowance_plus_one = VALUE + 1; dispatcher.transferFrom(OWNER(), RECIPIENT(), allowance_plus_one); } #[test] -#[should_panic(expected: ('ERC20: transfer to 0', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: transfer to 0',))] fn test_transferFrom_to_zero_address() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.approve(SPENDER(), VALUE); - testing::set_contract_address(SPENDER()); + start_cheat_caller_address(dispatcher.contract_address, SPENDER()); dispatcher.transferFrom(OWNER(), Zero::zero(), VALUE); } #[test] -#[should_panic(expected: ('ERC20: insufficient allowance', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC20: insufficient allowance',))] fn test_transferFrom_from_zero_address() { - let mut dispatcher = setup_dispatcher(); + let (_, mut dispatcher) = setup_dispatcher(); dispatcher.transferFrom(Zero::zero(), RECIPIENT(), VALUE); } @@ -313,67 +315,69 @@ fn test_transferFrom_from_zero_address() { #[test] fn test_transfer_ownership() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (mut spy, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transfer_ownership(OTHER()); - assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), OTHER()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), OTHER()); assert_eq!(dispatcher.owner(), OTHER()); } #[test] -#[should_panic(expected: ('New owner is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('New owner is the zero address',))] fn test_transfer_ownership_to_zero() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transfer_ownership(ZERO()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_transfer_ownership_from_zero() { - let mut dispatcher = setup_dispatcher(); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.transfer_ownership(OTHER()); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_transfer_ownership_from_nonowner() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.transfer_ownership(OTHER()); } #[test] fn test_transferOwnership() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (mut spy, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transferOwnership(OTHER()); - assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), OTHER()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), OTHER()); assert_eq!(dispatcher.owner(), OTHER()); } #[test] -#[should_panic(expected: ('New owner is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('New owner is the zero address',))] fn test_transferOwnership_to_zero() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transferOwnership(ZERO()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_transferOwnership_from_zero() { - let mut dispatcher = setup_dispatcher(); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.transferOwnership(OTHER()); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_transferOwnership_from_nonowner() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.transferOwnership(OTHER()); } @@ -383,51 +387,53 @@ fn test_transferOwnership_from_nonowner() { #[test] fn test_renounce_ownership() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (mut spy, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.renounce_ownership(); - assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), ZERO()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), ZERO()); assert!(dispatcher.owner().is_zero()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_renounce_ownership_from_zero_address() { - let mut dispatcher = setup_dispatcher(); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.renounce_ownership(); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_renounce_ownership_from_nonowner() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.renounce_ownership(); } #[test] fn test_renounceOwnership() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (mut spy, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.renounceOwnership(); - assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), ZERO()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), ZERO()); assert!(dispatcher.owner().is_zero()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_renounceOwnership_from_zero_address() { - let mut dispatcher = setup_dispatcher(); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.renounceOwnership(); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_renounceOwnership_from_nonowner() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.renounceOwnership(); } @@ -436,52 +442,62 @@ fn test_renounceOwnership_from_nonowner() { // #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_upgrade_unauthorized() { - let v1 = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, mut v1) = setup_dispatcher(); + start_cheat_caller_address(v1.contract_address, OTHER()); v1.upgrade(CLASS_HASH_ZERO()); } #[test] -#[should_panic(expected: ('Class hash cannot be zero', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Class hash cannot be zero',))] fn test_upgrade_with_class_hash_zero() { - let v1 = setup_dispatcher(); + let (_, mut v1) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(v1.contract_address, OWNER()); v1.upgrade(CLASS_HASH_ZERO()); } #[test] fn test_upgraded_event() { - let v1 = setup_dispatcher(); + let (mut spy, mut v1) = setup_dispatcher(); let v2_class_hash = V2_CLASS_HASH(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(v1.contract_address, OWNER()); v1.upgrade(v2_class_hash); - assert_only_event_upgraded(v1.contract_address, v2_class_hash); + spy.assert_only_event_upgraded(v1.contract_address, v2_class_hash); } #[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +#[feature("safe_dispatcher")] fn test_v2_missing_camel_selector() { - let v1 = setup_dispatcher(); + let (_, mut v1) = setup_dispatcher(); let v2_class_hash = V2_CLASS_HASH(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(v1.contract_address, OWNER()); v1.upgrade(v2_class_hash); - let dispatcher = IERC20CamelDispatcher { contract_address: v1.contract_address }; - dispatcher.totalSupply(); + let safe_dispatcher = ERC20UpgradeableABISafeDispatcher { + contract_address: v1.contract_address + }; + let mut panic_data = safe_dispatcher.totalSupply().unwrap_err(); + + let selector = selector!("totalSupply"); + let expected_panic_message = format!( + "Entry point selector {} not found in contract {}", + selector.into_base_16_string(), + v1.contract_address.into_base_16_string() + ); + assert_eq!(utils::panic_data_to_byte_array(panic_data), expected_panic_message); } #[test] fn test_state_persists_after_upgrade() { - let v1 = setup_dispatcher(); + let (_, mut v1) = setup_dispatcher(); let v2_class_hash = V2_CLASS_HASH(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(v1.contract_address, OWNER()); v1.transfer(RECIPIENT(), VALUE); // Check RECIPIENT balance v1 diff --git a/src/tests/upgrades/test_upgradeable.cairo b/src/tests/upgrades/test_upgradeable.cairo index 183f4f575..867aad502 100644 --- a/src/tests/upgrades/test_upgradeable.cairo +++ b/src/tests/upgrades/test_upgradeable.cairo @@ -1,13 +1,10 @@ -use openzeppelin::tests::mocks::upgrades_mocks::{ - IUpgradesV1Dispatcher, IUpgradesV1DispatcherTrait, UpgradesV1 -}; +use openzeppelin::tests::mocks::upgrades_mocks::{IUpgradesV1Dispatcher, IUpgradesV1DispatcherTrait}; use openzeppelin::tests::mocks::upgrades_mocks::{IUpgradesV2Dispatcher, IUpgradesV2DispatcherTrait}; -use openzeppelin::tests::utils::common::{declare_class, deploy}; use openzeppelin::tests::utils::constants::{CLASS_HASH_ZERO, ZERO, FELT_VALUE as VALUE}; use openzeppelin::tests::utils::events::EventSpyExt; +use openzeppelin::tests::utils::{declare_class, deploy}; use openzeppelin::upgrades::UpgradeableComponent; -use snforge_std::ContractClass; -use snforge_std::{spy_events, EventSpy}; +use snforge_std::{spy_events, ContractClass}; use super::common::UpgradableSpyHelpers; @@ -15,12 +12,12 @@ use super::common::UpgradableSpyHelpers; // Setup // -fn setup_test() -> (IUpgradesV1Dispatcher, ContractClass, ContractClass) { +fn setup_test() -> (IUpgradesV1Dispatcher, ContractClass) { let v1_class = declare_class("UpgradesV1"); let v2_class = declare_class("UpgradesV2"); let v1_contract_address = deploy(v1_class, array![]); let v1 = IUpgradesV1Dispatcher { contract_address: v1_contract_address }; - (v1, v1_class, v2_class) + (v1, v2_class) } // @@ -30,13 +27,13 @@ fn setup_test() -> (IUpgradesV1Dispatcher, ContractClass, ContractClass) { #[test] #[should_panic(expected: ('Class hash cannot be zero',))] fn test_upgrade_with_class_hash_zero() { - let (v1, _v1_class, _v2_class) = setup_test(); + let (v1, _) = setup_test(); v1.upgrade(CLASS_HASH_ZERO()); } #[test] fn test_upgraded_event() { - let (v1, _v1_class, v2_class) = setup_test(); + let (v1, v2_class) = setup_test(); let mut spy = spy_events(); v1.upgrade(v2_class.class_hash); @@ -46,7 +43,7 @@ fn test_upgraded_event() { #[test] fn test_new_selector_after_upgrade() { - let (v1, _v1_class, v2_class) = setup_test(); + let (v1, v2_class) = setup_test(); v1.upgrade(v2_class.class_hash); let v2 = IUpgradesV2Dispatcher { contract_address: v1.contract_address }; @@ -57,7 +54,7 @@ fn test_new_selector_after_upgrade() { #[test] fn test_state_persists_after_upgrade() { - let (v1, _v1_class, v2_class) = setup_test(); + let (v1, v2_class) = setup_test(); v1.set_value(VALUE); @@ -69,16 +66,16 @@ fn test_state_persists_after_upgrade() { #[test] fn test_remove_selector_passes_in_v1() { - let (v1, _v1_class, _v2_class) = setup_test(); + let (v1, _) = setup_test(); v1.remove_selector(); } #[test] -#[ignore] // REASON: inconsistent ENTRYPOINT_NOT_FOUND panic message +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_remove_selector_fails_in_v2() { - let (v1, _v1_class, v2_class) = setup_test(); + let (v1, v2_class) = setup_test(); v1.upgrade(v2_class.class_hash); // We use the v1 dispatcher because remove_selector is not in v2 interface diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo index 64abc3023..1c31f8a61 100644 --- a/src/tests/utils.cairo +++ b/src/tests/utils.cairo @@ -1,8 +1,11 @@ pub(crate) mod common; pub(crate) mod constants; +pub(crate) mod deployment; pub(crate) mod events; pub(crate) mod signing; -pub use common::{ + +pub use common::{panic_data_to_byte_array, to_base_16_string, IntoBase16StringTrait}; +pub use deployment::{ declare_class, declare_and_deploy, declare_and_deploy_at, deploy, deploy_at, deploy_another_at }; diff --git a/src/tests/utils/common.cairo b/src/tests/utils/common.cairo index c5920b969..c48a85344 100644 --- a/src/tests/utils/common.cairo +++ b/src/tests/utils/common.cairo @@ -1,45 +1,36 @@ -use core::starknet::SyscallResultTrait; -use snforge_std::{declare, get_class_hash, ContractClass, ContractClassTrait}; -use snforge_std::{start_cheat_caller_address, stop_cheat_caller_address}; -use starknet::ContractAddress; +use core::to_byte_array::FormatAsByteArray; -pub fn deploy(contract_class: ContractClass, calldata: Array) -> ContractAddress { - match contract_class.deploy(@calldata) { - Result::Ok((contract_address, _)) => contract_address, - Result::Err(panic_data) => panic!("Failed to deploy, error: ${:?}", panic_data) - } -} +/// Converts panic data into a string (ByteArray). +/// +/// panic_data is expected to be a valid serialized byte array with an extra +/// felt252 at the beginning, which is the BYTE_ARRAY_MAGIC. +pub fn panic_data_to_byte_array(panic_data: Array) -> ByteArray { + let mut panic_data = panic_data.span(); -pub fn deploy_at( - contract_class: ContractClass, contract_address: ContractAddress, calldata: Array -) { - match contract_class.deploy_at(@calldata, contract_address) { - Result::Ok(_) => (), - Result::Err(panic_data) => panic!("Failed to deploy, error: ${:?}", panic_data) - }; -} + // Remove BYTE_ARRAY_MAGIC from the panic data. + panic_data.pop_front().unwrap(); -/// Deploys a contract from the class hash of another contract which is already deployed. -pub fn deploy_another_at( - existing: ContractAddress, target_address: ContractAddress, calldata: Array -) { - let class_hash = get_class_hash(existing); - let contract_class = ContractClassTrait::new(class_hash); - deploy_at(contract_class, target_address, calldata) + match Serde::::deserialize(ref panic_data) { + Option::Some(string) => string, + Option::None => panic!("Failed to deserialize panic data."), + } } -pub fn declare_class(contract_name: ByteArray) -> ContractClass { - declare(contract_name).unwrap_syscall() -} +/// Converts a felt252 to a base 16 string padded to 66 characters including the `0x` prefix. +pub fn to_base_16_string(value: felt252) -> ByteArray { + let mut string = value.format_as_byte_array(16); + let mut padding = 64 - string.len(); -pub fn declare_and_deploy(contract_name: ByteArray, calldata: Array) -> ContractAddress { - let contract_class = declare(contract_name).unwrap_syscall(); - deploy(contract_class, calldata) + while padding > 0 { + string = "0" + string; + padding -= 1; + }; + format!("0x{}", string) } -pub fn declare_and_deploy_at( - contract_name: ByteArray, target_address: ContractAddress, calldata: Array -) { - let contract_class = declare(contract_name).unwrap_syscall(); - deploy_at(contract_class, target_address, calldata) +#[generate_trait] +pub impl IntoBase16String> of IntoBase16StringTrait { + fn into_base_16_string(self: T) -> ByteArray { + to_base_16_string(self.into()) + } } diff --git a/src/tests/utils/deployment.cairo b/src/tests/utils/deployment.cairo new file mode 100644 index 000000000..dae9a2071 --- /dev/null +++ b/src/tests/utils/deployment.cairo @@ -0,0 +1,46 @@ +use core::starknet::SyscallResultTrait; +use openzeppelin::tests::utils::panic_data_to_byte_array; +use snforge_std::{declare, get_class_hash, ContractClass, ContractClassTrait}; +use snforge_std::{start_cheat_caller_address, stop_cheat_caller_address}; +use starknet::ContractAddress; + +pub fn deploy(contract_class: ContractClass, calldata: Array) -> ContractAddress { + match contract_class.deploy(@calldata) { + Result::Ok((contract_address, _)) => contract_address, + Result::Err(panic_data) => panic!("{}", panic_data_to_byte_array(panic_data)) + } +} + +pub fn deploy_at( + contract_class: ContractClass, contract_address: ContractAddress, calldata: Array +) { + match contract_class.deploy_at(@calldata, contract_address) { + Result::Ok(_) => (), + Result::Err(panic_data) => panic!("{}", panic_data_to_byte_array(panic_data)) + }; +} + +/// Deploys a contract from the class hash of another contract which is already deployed. +pub fn deploy_another_at( + existing: ContractAddress, target_address: ContractAddress, calldata: Array +) { + let class_hash = get_class_hash(existing); + let contract_class = ContractClassTrait::new(class_hash); + deploy_at(contract_class, target_address, calldata) +} + +pub fn declare_class(contract_name: ByteArray) -> ContractClass { + declare(contract_name).unwrap_syscall() +} + +pub fn declare_and_deploy(contract_name: ByteArray, calldata: Array) -> ContractAddress { + let contract_class = declare(contract_name).unwrap_syscall(); + deploy(contract_class, calldata) +} + +pub fn declare_and_deploy_at( + contract_name: ByteArray, target_address: ContractAddress, calldata: Array +) { + let contract_class = declare(contract_name).unwrap_syscall(); + deploy_at(contract_class, target_address, calldata) +} From 78aa934cb4235d02e2f30eb49e48d04a48b890d8 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 19 Jul 2024 12:33:50 +0200 Subject: [PATCH 13/45] feat: update ignored tests messages (#1056) --- src/tests/presets.cairo | 2 +- src/tests/presets/test_erc20.cairo | 3 +- src/tests/presets/test_erc721.cairo | 518 +++++++++++----------- src/tests/upgrades/common.cairo | 2 +- src/tests/upgrades/test_upgradeable.cairo | 2 +- 5 files changed, 270 insertions(+), 257 deletions(-) diff --git a/src/tests/presets.cairo b/src/tests/presets.cairo index 638696372..feb573ea8 100644 --- a/src/tests/presets.cairo +++ b/src/tests/presets.cairo @@ -1,7 +1,7 @@ // mod test_account; // mod test_erc1155; mod test_erc20; -// mod test_erc721; +mod test_erc721; // mod test_eth_account; // mod test_universal_deployer; diff --git a/src/tests/presets/test_erc20.cairo b/src/tests/presets/test_erc20.cairo index a7ead420d..2625ac249 100644 --- a/src/tests/presets/test_erc20.cairo +++ b/src/tests/presets/test_erc20.cairo @@ -8,14 +8,13 @@ use openzeppelin::presets::interfaces::{ }; use openzeppelin::tests::access::common::OwnableSpyHelpers; use openzeppelin::tests::token::erc20::common::ERC20SpyHelpers; -use openzeppelin::tests::upgrades::common::UpgradableSpyHelpers; +use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; use openzeppelin::tests::utils::common::IntoBase16String; use openzeppelin::tests::utils::constants::{ ZERO, OWNER, SPENDER, RECIPIENT, OTHER, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE, CLASS_HASH_ZERO }; use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use openzeppelin::utils::serde::SerializedAppend; use snforge_std::{spy_events, EventSpy, start_cheat_caller_address}; diff --git a/src/tests/presets/test_erc721.cairo b/src/tests/presets/test_erc721.cairo index bf1d27d14..a84bb7cce 100644 --- a/src/tests/presets/test_erc721.cairo +++ b/src/tests/presets/test_erc721.cairo @@ -5,32 +5,24 @@ use openzeppelin::presets::ERC721Upgradeable; use openzeppelin::presets::interfaces::{ ERC721UpgradeableABIDispatcher, ERC721UpgradeableABIDispatcherTrait }; -use openzeppelin::tests::access::common::assert_event_ownership_transferred; -use openzeppelin::tests::mocks::account_mocks::{DualCaseAccountMock, CamelAccountMock}; -use openzeppelin::tests::mocks::erc721_mocks::SnakeERC721Mock; -use openzeppelin::tests::mocks::erc721_receiver_mocks::{ - CamelERC721ReceiverMock, SnakeERC721ReceiverMock -}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::token::erc721::common::{ - assert_event_transfer, assert_only_event_transfer, assert_event_approval, - assert_event_approval_for_all -}; -use openzeppelin::tests::upgrades::common::assert_only_event_upgraded; +use openzeppelin::tests::access::common::OwnableSpyHelpers; +use openzeppelin::tests::token::erc721::common::ERC721SpyHelpers; +use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; +use openzeppelin::tests::utils::common::IntoBase16String; use openzeppelin::tests::utils::constants::{ ZERO, DATA, OWNER, SPENDER, RECIPIENT, OTHER, OPERATOR, CLASS_HASH_ZERO, PUBKEY, NAME, SYMBOL, BASE_URI }; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::tests::utils; use openzeppelin::token::erc721::ERC721Component::ERC721Impl; -use openzeppelin::token::erc721::ERC721Component; use openzeppelin::token::erc721::interface::{ - IERC721CamelOnlyDispatcher, IERC721CamelOnlyDispatcherTrait + IERC721CamelOnlySafeDispatcher, IERC721CamelOnlySafeDispatcherTrait }; use openzeppelin::token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; use openzeppelin::token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID}; use openzeppelin::utils::serde::SerializedAppend; -use starknet::testing; +use snforge_std::{spy_events, EventSpy, start_cheat_caller_address}; use starknet::{ContractAddress, ClassHash}; @@ -43,20 +35,17 @@ const NONEXISTENT: u256 = 9898; const TOKENS_LEN: u256 = 3; fn V2_CLASS_HASH() -> ClassHash { - SnakeERC721Mock::TEST_CLASS_HASH.try_into().unwrap() + utils::declare_class("SnakeERC721Mock").class_hash } // // Setup // -fn setup_dispatcher_with_event() -> ERC721UpgradeableABIDispatcher { +fn setup_dispatcher_with_event() -> (EventSpy, ERC721UpgradeableABIDispatcher) { let mut calldata = array![]; let mut token_ids = array![TOKEN_1, TOKEN_2, TOKEN_3]; - // Set caller as `OWNER` - testing::set_contract_address(OWNER()); - calldata.append_serde(NAME()); calldata.append_serde(SYMBOL()); calldata.append_serde(BASE_URI()); @@ -64,33 +53,34 @@ fn setup_dispatcher_with_event() -> ERC721UpgradeableABIDispatcher { calldata.append_serde(token_ids); calldata.append_serde(OWNER()); - let address = utils::deploy(ERC721Upgradeable::TEST_CLASS_HASH, calldata); - ERC721UpgradeableABIDispatcher { contract_address: address } + let spy = spy_events(); + let address = utils::declare_and_deploy("ERC721Upgradeable", calldata); + start_cheat_caller_address(address, OWNER()); + (spy, ERC721UpgradeableABIDispatcher { contract_address: address }) } -fn setup_dispatcher() -> ERC721UpgradeableABIDispatcher { - let dispatcher = setup_dispatcher_with_event(); - // `OwnershipTransferred` + `Transfer`s - utils::drop_events(dispatcher.contract_address, TOKENS_LEN.try_into().unwrap() + 1); - dispatcher +fn setup_dispatcher() -> (EventSpy, ERC721UpgradeableABIDispatcher) { + let (mut spy, dispatcher) = setup_dispatcher_with_event(); + spy.drop_all_events(); + (spy, dispatcher) } fn setup_receiver() -> ContractAddress { - utils::deploy(SnakeERC721ReceiverMock::TEST_CLASS_HASH, array![]) + utils::declare_and_deploy("SnakeERC721ReceiverMock", array![]) } fn setup_camel_receiver() -> ContractAddress { - utils::deploy(CamelERC721ReceiverMock::TEST_CLASS_HASH, array![]) + utils::declare_and_deploy("CamelERC721ReceiverMock", array![]) } fn setup_account() -> ContractAddress { let mut calldata = array![PUBKEY]; - utils::deploy(DualCaseAccountMock::TEST_CLASS_HASH, calldata) + utils::declare_and_deploy("DualCaseAccountMock", calldata) } fn setup_camel_account() -> ContractAddress { let mut calldata = array![PUBKEY]; - utils::deploy(CamelAccountMock::TEST_CLASS_HASH, calldata) + utils::declare_and_deploy("CamelAccountMock", calldata) } // @@ -120,7 +110,7 @@ fn test_mint_assets() { #[test] fn test_constructor() { - let dispatcher = setup_dispatcher_with_event(); + let (_, dispatcher) = setup_dispatcher_with_event(); // Check interface registration let mut interface_ids = array![ISRC5_ID, IERC721_ID, IERC721_METADATA_ID]; @@ -149,18 +139,18 @@ fn test_constructor() { #[test] fn test_constructor_events() { - let dispatcher = setup_dispatcher_with_event(); + let (mut spy, dispatcher) = setup_dispatcher_with_event(); let mut tokens = array![TOKEN_1, TOKEN_2, TOKEN_3]; - assert_event_ownership_transferred(dispatcher.contract_address, ZERO(), OWNER()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, ZERO(), OWNER()); loop { let token = tokens.pop_front().unwrap(); if tokens.len() == 0 { // Includes event queue check - assert_only_event_transfer(dispatcher.contract_address, ZERO(), OWNER(), token); + spy.assert_only_event_transfer(dispatcher.contract_address, ZERO(), OWNER(), token); break; } - assert_event_transfer(dispatcher.contract_address, ZERO(), OWNER(), token); + spy.assert_event_transfer(dispatcher.contract_address, ZERO(), OWNER(), token); }; } @@ -170,40 +160,40 @@ fn test_constructor_events() { #[test] fn test_balance_of() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); assert_eq!(dispatcher.balance_of(OWNER()), TOKENS_LEN); } #[test] -#[should_panic(expected: ('ERC721: invalid account', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid account',))] fn test_balance_of_zero() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.balance_of(ZERO()); } #[test] fn test_owner_of() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); assert_eq!(dispatcher.owner_of(TOKEN_1), OWNER()); } #[test] -#[should_panic(expected: ('ERC721: invalid token ID', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid token ID',))] fn test_owner_of_non_minted() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.owner_of(7); } #[test] -#[should_panic(expected: ('ERC721: invalid token ID', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid token ID',))] fn test_token_uri_non_minted() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.token_uri(7); } #[test] fn test_token_uri() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); let uri = dispatcher.token_uri(TOKEN_1); let expected = format!("{}{}", BASE_URI(), TOKEN_1); @@ -212,7 +202,7 @@ fn test_token_uri() { #[test] fn test_get_approved() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); let spender = SPENDER(); let token_id = TOKEN_1; @@ -225,9 +215,9 @@ fn test_get_approved() { } #[test] -#[should_panic(expected: ('ERC721: invalid token ID', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid token ID',))] fn test_get_approved_nonexistent() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.get_approved(NONEXISTENT); } @@ -237,10 +227,10 @@ fn test_get_approved_nonexistent() { #[test] fn test_approve_from_owner() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); dispatcher.approve(SPENDER(), TOKEN_1); - assert_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), TOKEN_1); + spy.assert_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), TOKEN_1); let approved = dispatcher.get_approved(TOKEN_1); assert_eq!(approved, SPENDER()); @@ -248,32 +238,32 @@ fn test_approve_from_owner() { #[test] fn test_approve_from_operator() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.approve(SPENDER(), TOKEN_1); - assert_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), TOKEN_1); + spy.assert_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), TOKEN_1); let approved = dispatcher.get_approved(TOKEN_1); assert_eq!(approved, SPENDER()); } #[test] -#[should_panic(expected: ('ERC721: unauthorized caller', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: unauthorized caller',))] fn test_approve_from_unauthorized() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); - testing::set_contract_address(OTHER()); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.approve(SPENDER(), TOKEN_1); } #[test] -#[should_panic(expected: ('ERC721: invalid token ID', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid token ID',))] fn test_approve_nonexistent() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.approve(SPENDER(), NONEXISTENT); } @@ -283,19 +273,19 @@ fn test_approve_nonexistent() { #[test] fn test_set_approval_for_all() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let is_not_approved_for_all = !dispatcher.is_approved_for_all(OWNER(), OPERATOR()); assert!(is_not_approved_for_all); dispatcher.set_approval_for_all(OPERATOR(), true); - assert_event_approval_for_all(dispatcher.contract_address, OWNER(), OPERATOR(), true); + spy.assert_event_approval_for_all(dispatcher.contract_address, OWNER(), OPERATOR(), true); let is_approved_for_all = dispatcher.is_approved_for_all(OWNER(), OPERATOR()); assert!(is_approved_for_all); dispatcher.set_approval_for_all(OPERATOR(), false); - assert_event_approval_for_all(dispatcher.contract_address, OWNER(), OPERATOR(), false); + spy.assert_event_approval_for_all(dispatcher.contract_address, OWNER(), OPERATOR(), false); let is_not_approved_for_all = !dispatcher.is_approved_for_all(OWNER(), OPERATOR()); assert!(is_not_approved_for_all); @@ -307,14 +297,14 @@ fn test_set_approval_for_all() { #[test] fn test_transfer_from_owner() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let token_id = TOKEN_1; let owner = OWNER(); let recipient = RECIPIENT(); // set approval to check reset dispatcher.approve(OTHER(), token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); assert_state_before_transfer(dispatcher, owner, recipient, token_id); @@ -322,21 +312,21 @@ fn test_transfer_from_owner() { assert_eq!(approved, OTHER()); dispatcher.transfer_from(owner, recipient, token_id); - assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); assert_state_after_transfer(dispatcher, owner, recipient, token_id); } #[test] fn test_transferFrom_owner() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let token_id = TOKEN_1; let owner = OWNER(); let recipient = RECIPIENT(); // set approval to check reset dispatcher.approve(OTHER(), token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); assert_state_before_transfer(dispatcher, owner, recipient, token_id); @@ -344,100 +334,100 @@ fn test_transferFrom_owner() { assert_eq!(approved, OTHER()); dispatcher.transferFrom(owner, recipient, token_id); - assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); assert_state_after_transfer(dispatcher, owner, recipient, token_id); } #[test] -#[should_panic(expected: ('ERC721: invalid token ID', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid token ID',))] fn test_transfer_from_nonexistent() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.transfer_from(OWNER(), RECIPIENT(), NONEXISTENT); } #[test] -#[should_panic(expected: ('ERC721: invalid token ID', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid token ID',))] fn test_transferFrom_nonexistent() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.transferFrom(OWNER(), RECIPIENT(), NONEXISTENT); } #[test] -#[should_panic(expected: ('ERC721: invalid receiver', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid receiver',))] fn test_transfer_from_to_zero() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.transfer_from(OWNER(), ZERO(), TOKEN_1); } #[test] -#[should_panic(expected: ('ERC721: invalid receiver', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid receiver',))] fn test_transferFrom_to_zero() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.transferFrom(OWNER(), ZERO(), TOKEN_1); } #[test] fn test_transfer_from_to_owner() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); assert_state_transfer_to_self(dispatcher, OWNER(), TOKEN_1, TOKENS_LEN); dispatcher.transfer_from(OWNER(), OWNER(), TOKEN_1); - assert_only_event_transfer(dispatcher.contract_address, OWNER(), OWNER(), TOKEN_1); + spy.assert_only_event_transfer(dispatcher.contract_address, OWNER(), OWNER(), TOKEN_1); assert_state_transfer_to_self(dispatcher, OWNER(), TOKEN_1, TOKENS_LEN); } #[test] fn test_transferFrom_to_owner() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); assert_state_transfer_to_self(dispatcher, OWNER(), TOKEN_1, TOKENS_LEN); dispatcher.transferFrom(OWNER(), OWNER(), TOKEN_1); - assert_only_event_transfer(dispatcher.contract_address, OWNER(), OWNER(), TOKEN_1); + spy.assert_only_event_transfer(dispatcher.contract_address, OWNER(), OWNER(), TOKEN_1); assert_state_transfer_to_self(dispatcher, OWNER(), TOKEN_1, TOKENS_LEN); } #[test] fn test_transfer_from_approved() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let token_id = TOKEN_1; let owner = OWNER(); let recipient = RECIPIENT(); assert_state_before_transfer(dispatcher, owner, recipient, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.transfer_from(owner, recipient, token_id); - assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); assert_state_after_transfer(dispatcher, owner, recipient, token_id); } #[test] fn test_transferFrom_approved() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let token_id = TOKEN_1; let owner = OWNER(); let recipient = RECIPIENT(); assert_state_before_transfer(dispatcher, owner, recipient, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.transferFrom(owner, recipient, token_id); - assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); assert_state_after_transfer(dispatcher, owner, recipient, token_id); } #[test] fn test_transfer_from_approved_for_all() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let token_id = TOKEN_1; let owner = OWNER(); let recipient = RECIPIENT(); @@ -445,18 +435,18 @@ fn test_transfer_from_approved_for_all() { assert_state_before_transfer(dispatcher, owner, recipient, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.transfer_from(owner, recipient, token_id); - assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); assert_state_after_transfer(dispatcher, owner, recipient, token_id); } #[test] fn test_transferFrom_approved_for_all() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let token_id = TOKEN_1; let owner = OWNER(); let recipient = RECIPIENT(); @@ -464,28 +454,28 @@ fn test_transferFrom_approved_for_all() { assert_state_before_transfer(dispatcher, owner, recipient, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.transferFrom(owner, recipient, token_id); - assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, recipient, token_id); assert_state_after_transfer(dispatcher, owner, recipient, token_id); } #[test] -#[should_panic(expected: ('ERC721: unauthorized caller', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: unauthorized caller',))] fn test_transfer_from_unauthorized() { - let dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.transfer_from(OWNER(), RECIPIENT(), TOKEN_1); } #[test] -#[should_panic(expected: ('ERC721: unauthorized caller', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: unauthorized caller',))] fn test_transferFrom_unauthorized() { - let dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.transferFrom(OWNER(), RECIPIENT(), TOKEN_1); } @@ -495,67 +485,71 @@ fn test_transferFrom_unauthorized() { #[test] fn test_safe_transfer_from_to_account() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let account = setup_account(); let token_id = TOKEN_1; let owner = OWNER(); + spy.drop_all_events(); assert_state_before_transfer(dispatcher, owner, account, token_id); dispatcher.safe_transfer_from(owner, account, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, account, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, account, token_id); assert_state_after_transfer(dispatcher, owner, account, token_id); } #[test] fn test_safeTransferFrom_to_account() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let account = setup_account(); let token_id = TOKEN_1; let owner = OWNER(); + spy.drop_all_events(); assert_state_before_transfer(dispatcher, owner, account, token_id); dispatcher.safeTransferFrom(owner, account, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, account, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, account, token_id); assert_state_after_transfer(dispatcher, owner, account, token_id); } #[test] fn test_safe_transfer_from_to_account_camel() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let account = setup_camel_account(); let token_id = TOKEN_1; let owner = OWNER(); + spy.drop_all_events(); assert_state_before_transfer(dispatcher, owner, account, token_id); dispatcher.safe_transfer_from(owner, account, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, account, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, account, token_id); assert_state_after_transfer(dispatcher, owner, account, token_id); } #[test] fn test_safeTransferFrom_to_account_camel() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let account = setup_camel_account(); let token_id = TOKEN_1; let owner = OWNER(); + spy.drop_all_events(); assert_state_before_transfer(dispatcher, owner, account, token_id); dispatcher.safeTransferFrom(owner, account, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, account, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, account, token_id); assert_state_after_transfer(dispatcher, owner, account, token_id); } #[test] fn test_safe_transfer_from_to_receiver() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -563,14 +557,14 @@ fn test_safe_transfer_from_to_receiver() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] fn test_safeTransferFrom_to_receiver() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -578,14 +572,15 @@ fn test_safeTransferFrom_to_receiver() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_transfer_from_to_receiver_camel() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_camel_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -593,14 +588,15 @@ fn test_safe_transfer_from_to_receiver_camel() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeTransferFrom_to_receiver_camel() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_camel_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -608,15 +604,15 @@ fn test_safeTransferFrom_to_receiver_camel() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] -#[should_panic(expected: ('ERC721: safe transfer failed', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: safe transfer failed',))] fn test_safe_transfer_from_to_receiver_failure() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); let receiver = setup_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -625,9 +621,9 @@ fn test_safe_transfer_from_to_receiver_failure() { } #[test] -#[should_panic(expected: ('ERC721: safe transfer failed', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: safe transfer failed',))] fn test_safeTransferFrom_to_receiver_failure() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); let receiver = setup_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -636,9 +632,10 @@ fn test_safeTransferFrom_to_receiver_failure() { } #[test] -#[should_panic(expected: ('ERC721: safe transfer failed', 'ENTRYPOINT_FAILED'))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ('ERC721: safe transfer failed',))] fn test_safe_transfer_from_to_receiver_failure_camel() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); let receiver = setup_camel_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -647,9 +644,10 @@ fn test_safe_transfer_from_to_receiver_failure_camel() { } #[test] -#[should_panic(expected: ('ERC721: safe transfer failed', 'ENTRYPOINT_FAILED'))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ('ERC721: safe transfer failed',))] fn test_safeTransferFrom_to_receiver_failure_camel() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); let receiver = setup_camel_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -658,10 +656,11 @@ fn test_safeTransferFrom_to_receiver_failure_camel() { } #[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND', 'ENTRYPOINT_FAILED'))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_safe_transfer_from_to_non_receiver() { - let dispatcher = setup_dispatcher(); - let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let (_, dispatcher) = setup_dispatcher(); + let recipient = utils::declare_and_deploy("NonImplementingMock", array![]); let token_id = TOKEN_1; let owner = OWNER(); @@ -669,10 +668,11 @@ fn test_safe_transfer_from_to_non_receiver() { } #[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND', 'ENTRYPOINT_FAILED'))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_safeTransferFrom_to_non_receiver() { - let dispatcher = setup_dispatcher(); - let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let (_, dispatcher) = setup_dispatcher(); + let recipient = utils::declare_and_deploy("NonImplementingMock", array![]); let token_id = TOKEN_1; let owner = OWNER(); @@ -680,108 +680,110 @@ fn test_safeTransferFrom_to_non_receiver() { } #[test] -#[should_panic(expected: ('ERC721: invalid token ID', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid token ID',))] fn test_safe_transfer_from_nonexistent() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.safe_transfer_from(OWNER(), RECIPIENT(), NONEXISTENT, DATA(true)); } #[test] -#[should_panic(expected: ('ERC721: invalid token ID', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid token ID',))] fn test_safeTransferFrom_nonexistent() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.safeTransferFrom(OWNER(), RECIPIENT(), NONEXISTENT, DATA(true)); } #[test] -#[should_panic(expected: ('ERC721: invalid receiver', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid receiver',))] fn test_safe_transfer_from_to_zero() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.safe_transfer_from(OWNER(), ZERO(), TOKEN_1, DATA(true)); } #[test] -#[should_panic(expected: ('ERC721: invalid receiver', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: invalid receiver',))] fn test_safeTransferFrom_to_zero() { - let dispatcher = setup_dispatcher(); + let (_, dispatcher) = setup_dispatcher(); dispatcher.safeTransferFrom(OWNER(), ZERO(), TOKEN_1, DATA(true)); } #[test] fn test_safe_transfer_from_to_owner() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let token_id = TOKEN_1; let receiver = setup_receiver(); dispatcher.transfer_from(OWNER(), receiver, token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); - testing::set_contract_address(receiver); + start_cheat_caller_address(dispatcher.contract_address, receiver); dispatcher.safe_transfer_from(receiver, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, receiver, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, receiver, receiver, token_id); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); } #[test] fn test_safeTransferFrom_to_owner() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let token_id = TOKEN_1; let receiver = setup_receiver(); dispatcher.transfer_from(OWNER(), receiver, token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); - testing::set_contract_address(receiver); + start_cheat_caller_address(dispatcher.contract_address, receiver); dispatcher.safeTransferFrom(receiver, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, receiver, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, receiver, receiver, token_id); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_transfer_from_to_owner_camel() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let token_id = TOKEN_1; let receiver = setup_camel_receiver(); dispatcher.transfer_from(OWNER(), receiver, token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); - testing::set_contract_address(receiver); + start_cheat_caller_address(dispatcher.contract_address, receiver); dispatcher.safe_transfer_from(receiver, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, receiver, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, receiver, receiver, token_id); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeTransferFrom_to_owner_camel() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let token_id = TOKEN_1; let receiver = setup_camel_receiver(); dispatcher.transfer_from(OWNER(), receiver, token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); - testing::set_contract_address(receiver); + start_cheat_caller_address(dispatcher.contract_address, receiver); dispatcher.safeTransferFrom(receiver, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, receiver, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, receiver, receiver, token_id); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); } #[test] fn test_safe_transfer_from_approved() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -789,18 +791,18 @@ fn test_safe_transfer_from_approved() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] fn test_safeTransferFrom_approved() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -808,18 +810,19 @@ fn test_safeTransferFrom_approved() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_transfer_from_approved_camel() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_camel_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -827,18 +830,19 @@ fn test_safe_transfer_from_approved_camel() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeTransferFrom_approved_camel() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_camel_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -846,18 +850,18 @@ fn test_safeTransferFrom_approved_camel() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] fn test_safe_transfer_from_approved_for_all() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -865,18 +869,18 @@ fn test_safe_transfer_from_approved_for_all() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] fn test_safeTransferFrom_approved_for_all() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -884,18 +888,19 @@ fn test_safeTransferFrom_approved_for_all() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_transfer_from_approved_for_all_camel() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_camel_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -903,18 +908,19 @@ fn test_safe_transfer_from_approved_for_all_camel() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.safe_transfer_from(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeTransferFrom_approved_for_all_camel() { - let dispatcher = setup_dispatcher(); + let (mut spy, dispatcher) = setup_dispatcher(); let receiver = setup_camel_receiver(); let token_id = TOKEN_1; let owner = OWNER(); @@ -922,28 +928,28 @@ fn test_safeTransferFrom_approved_for_all_camel() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + spy.drop_event(); - testing::set_contract_address(OPERATOR()); + start_cheat_caller_address(dispatcher.contract_address, OPERATOR()); dispatcher.safeTransferFrom(owner, receiver, token_id, DATA(true)); - assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); + spy.assert_only_event_transfer(dispatcher.contract_address, owner, receiver, token_id); assert_state_after_transfer(dispatcher, owner, receiver, token_id); } #[test] -#[should_panic(expected: ('ERC721: unauthorized caller', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: unauthorized caller',))] fn test_safe_transfer_from_unauthorized() { - let dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.safe_transfer_from(OWNER(), RECIPIENT(), TOKEN_1, DATA(true)); } #[test] -#[should_panic(expected: ('ERC721: unauthorized caller', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC721: unauthorized caller',))] fn test_safeTransferFrom_unauthorized() { - let dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.safeTransferFrom(OWNER(), RECIPIENT(), TOKEN_1, DATA(true)); } @@ -953,69 +959,69 @@ fn test_safeTransferFrom_unauthorized() { #[test] fn test_transfer_ownership() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (mut spy, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transfer_ownership(OTHER()); - assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), OTHER()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), OTHER()); assert_eq!(dispatcher.owner(), OTHER()); } #[test] -#[should_panic(expected: ('New owner is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('New owner is the zero address',))] fn test_transfer_ownership_to_zero() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transfer_ownership(ZERO()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_transfer_ownership_from_zero() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(ZERO()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.transfer_ownership(OTHER()); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_transfer_ownership_from_nonowner() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.transfer_ownership(OTHER()); } #[test] fn test_transferOwnership() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (mut spy, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transferOwnership(OTHER()); - assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), OTHER()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), OTHER()); assert_eq!(dispatcher.owner(), OTHER()); } #[test] -#[should_panic(expected: ('New owner is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('New owner is the zero address',))] fn test_transferOwnership_to_zero() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.transferOwnership(ZERO()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_transferOwnership_from_zero() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(ZERO()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.transferOwnership(OTHER()); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_transferOwnership_from_nonowner() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.transferOwnership(OTHER()); } @@ -1025,53 +1031,53 @@ fn test_transferOwnership_from_nonowner() { #[test] fn test_renounce_ownership() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (mut spy, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.renounce_ownership(); - assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), ZERO()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), ZERO()); assert!(dispatcher.owner().is_zero()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_renounce_ownership_from_zero_address() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(ZERO()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.renounce_ownership(); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_renounce_ownership_from_nonowner() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.renounce_ownership(); } #[test] fn test_renounceOwnership() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (mut spy, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.renounceOwnership(); - assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), ZERO()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), ZERO()); assert!(dispatcher.owner().is_zero()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_renounceOwnership_from_zero_address() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(ZERO()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.renounceOwnership(); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_renounceOwnership_from_nonowner() { - let mut dispatcher = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, mut dispatcher) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.renounceOwnership(); } @@ -1080,52 +1086,60 @@ fn test_renounceOwnership_from_nonowner() { // #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_upgrade_unauthorized() { - let v1 = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, mut v1) = setup_dispatcher(); + start_cheat_caller_address(v1.contract_address, OTHER()); v1.upgrade(CLASS_HASH_ZERO()); } #[test] -#[should_panic(expected: ('Class hash cannot be zero', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Class hash cannot be zero',))] fn test_upgrade_with_class_hash_zero() { - let v1 = setup_dispatcher(); + let (_, mut v1) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(v1.contract_address, OWNER()); v1.upgrade(CLASS_HASH_ZERO()); } #[test] fn test_upgraded_event() { - let v1 = setup_dispatcher(); + let (mut spy, mut v1) = setup_dispatcher(); let v2_class_hash = V2_CLASS_HASH(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(v1.contract_address, OWNER()); v1.upgrade(v2_class_hash); - assert_only_event_upgraded(v1.contract_address, v2_class_hash); + spy.assert_only_event_upgraded(v1.contract_address, v2_class_hash); } #[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +#[feature("safe_dispatcher")] fn test_v2_missing_camel_selector() { - let v1 = setup_dispatcher(); + let (_, mut v1) = setup_dispatcher(); let v2_class_hash = V2_CLASS_HASH(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(v1.contract_address, OWNER()); v1.upgrade(v2_class_hash); - let dispatcher = IERC721CamelOnlyDispatcher { contract_address: v1.contract_address }; - dispatcher.ownerOf(TOKEN_1); + let safe_dispatcher = IERC721CamelOnlySafeDispatcher { contract_address: v1.contract_address }; + let mut panic_data = safe_dispatcher.ownerOf(TOKEN_1).unwrap_err(); + + let selector = selector!("ownerOf"); + let expected_panic_message = format!( + "Entry point selector {} not found in contract {}", + selector.into_base_16_string(), + v1.contract_address.into_base_16_string() + ); + assert_eq!(utils::panic_data_to_byte_array(panic_data), expected_panic_message); } #[test] fn test_state_persists_after_upgrade() { - let v1 = setup_dispatcher(); + let (_, mut v1) = setup_dispatcher(); let v2_class_hash = V2_CLASS_HASH(); - testing::set_contract_address(OWNER()); + start_cheat_caller_address(v1.contract_address, OWNER()); v1.transferFrom(OWNER(), RECIPIENT(), TOKEN_1); // Check RECIPIENT balance v1 diff --git a/src/tests/upgrades/common.cairo b/src/tests/upgrades/common.cairo index 10876b756..973f47c8b 100644 --- a/src/tests/upgrades/common.cairo +++ b/src/tests/upgrades/common.cairo @@ -5,7 +5,7 @@ use snforge_std::{EventSpy, EventSpyAssertionsTrait}; use starknet::{ContractAddress, ClassHash}; #[generate_trait] -pub(crate) impl UpgradableSpyHelpersImpl of UpgradableSpyHelpers { +pub(crate) impl UpgradeableSpyHelpersImpl of UpgradeableSpyHelpers { fn assert_event_upgraded(ref self: EventSpy, contract: ContractAddress, class_hash: ClassHash) { let expected = UpgradeableComponent::Event::Upgraded(Upgraded { class_hash }); self.assert_emitted_single(contract, expected); diff --git a/src/tests/upgrades/test_upgradeable.cairo b/src/tests/upgrades/test_upgradeable.cairo index 867aad502..d55c41f74 100644 --- a/src/tests/upgrades/test_upgradeable.cairo +++ b/src/tests/upgrades/test_upgradeable.cairo @@ -6,7 +6,7 @@ use openzeppelin::tests::utils::{declare_class, deploy}; use openzeppelin::upgrades::UpgradeableComponent; use snforge_std::{spy_events, ContractClass}; -use super::common::UpgradableSpyHelpers; +use super::common::UpgradeableSpyHelpers; // // Setup From daff8e54c34a6a8ee95c6cb1ab9bbefde46e295a Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 19 Jul 2024 21:29:14 +0200 Subject: [PATCH 14/45] Migrate erc1155 preset tests (#1057) * feat: update tests * refactor: remove unnecessary import --- src/tests/presets.cairo | 2 +- src/tests/presets/test_erc1155.cairo | 422 ++++++++++++++------------- src/tests/presets/test_erc20.cairo | 10 +- src/tests/utils.cairo | 5 +- src/tests/utils/common.cairo | 14 + 5 files changed, 246 insertions(+), 207 deletions(-) diff --git a/src/tests/presets.cairo b/src/tests/presets.cairo index feb573ea8..d8b4fdd0e 100644 --- a/src/tests/presets.cairo +++ b/src/tests/presets.cairo @@ -1,5 +1,5 @@ // mod test_account; -// mod test_erc1155; +mod test_erc1155; mod test_erc20; mod test_erc721; // mod test_eth_account; diff --git a/src/tests/presets/test_erc1155.cairo b/src/tests/presets/test_erc1155.cairo index ba1b71101..454e97ae9 100644 --- a/src/tests/presets/test_erc1155.cairo +++ b/src/tests/presets/test_erc1155.cairo @@ -1,50 +1,45 @@ use core::num::traits::Zero; use openzeppelin::introspection; -use openzeppelin::presets::ERC1155Upgradeable; use openzeppelin::presets::interfaces::{ ERC1155UpgradeableABIDispatcher, ERC1155UpgradeableABIDispatcherTrait }; -use openzeppelin::tests::access::common::assert_event_ownership_transferred; -use openzeppelin::tests::mocks::erc1155_mocks::SnakeERC1155Mock; +use openzeppelin::tests::access::common::OwnableSpyHelpers; +use openzeppelin::tests::token::erc1155::common::ERC1155SpyHelpers; use openzeppelin::tests::token::erc1155::common::{ - assert_only_event_transfer_single, assert_only_event_transfer_batch, - assert_only_event_approval_for_all -}; -use openzeppelin::tests::token::erc1155::common::{ - setup_account, setup_receiver, setup_camel_receiver, setup_account_with_salt, setup_src5 + setup_account, setup_receiver, setup_camel_receiver, deploy_another_account_at, setup_src5 }; use openzeppelin::tests::token::erc1155::common::{get_ids_and_values, get_ids_and_split_values}; -use openzeppelin::tests::upgrades::common::assert_only_event_upgraded; +use openzeppelin::tests::upgrades::common::UpgradableSpyHelpers; use openzeppelin::tests::utils::constants::{ EMPTY_DATA, ZERO, OWNER, RECIPIENT, CLASS_HASH_ZERO, OPERATOR, OTHER, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 }; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::tests::utils; use openzeppelin::token::erc1155::interface::{ - IERC1155CamelDispatcher, IERC1155CamelDispatcherTrait + IERC1155CamelSafeDispatcher, IERC1155CamelSafeDispatcherTrait }; use openzeppelin::token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; use openzeppelin::token::erc1155; use openzeppelin::utils::serde::SerializedAppend; -use starknet::testing; +use snforge_std::{spy_events, EventSpy, start_cheat_caller_address}; use starknet::{ContractAddress, ClassHash}; fn V2_CLASS_HASH() -> ClassHash { - SnakeERC1155Mock::TEST_CLASS_HASH.try_into().unwrap() + utils::declare_class("SnakeERC1155Mock").class_hash } // // Setup // -fn setup_dispatcher_with_event() -> (ERC1155UpgradeableABIDispatcher, ContractAddress) { +fn setup_dispatcher_with_event() -> (EventSpy, ERC1155UpgradeableABIDispatcher, ContractAddress) { let uri: ByteArray = "URI"; let mut calldata = array![]; let mut token_ids = array![TOKEN_ID, TOKEN_ID_2]; let mut values = array![TOKEN_VALUE, TOKEN_VALUE_2]; let owner = setup_account(); - testing::set_contract_address(owner); calldata.append_serde(uri); calldata.append_serde(owner); @@ -52,15 +47,16 @@ fn setup_dispatcher_with_event() -> (ERC1155UpgradeableABIDispatcher, ContractAd calldata.append_serde(values); calldata.append_serde(owner); - let address = utils::deploy(ERC1155Upgradeable::TEST_CLASS_HASH, calldata); - (ERC1155UpgradeableABIDispatcher { contract_address: address }, owner) + let spy = spy_events(); + let address = utils::declare_and_deploy("ERC1155Upgradeable", calldata); + start_cheat_caller_address(address, owner); + (spy, ERC1155UpgradeableABIDispatcher { contract_address: address }, owner) } -fn setup_dispatcher() -> (ERC1155UpgradeableABIDispatcher, ContractAddress) { - let (dispatcher, owner) = setup_dispatcher_with_event(); - utils::drop_event(dispatcher.contract_address); // `TransferOwnership` - utils::drop_event(dispatcher.contract_address); // `Transfer` - (dispatcher, owner) +fn setup_dispatcher() -> (EventSpy, ERC1155UpgradeableABIDispatcher, ContractAddress) { + let (mut spy, dispatcher, owner) = setup_dispatcher_with_event(); + spy.drop_all_events(); + (spy, dispatcher, owner) } // @@ -69,7 +65,7 @@ fn setup_dispatcher() -> (ERC1155UpgradeableABIDispatcher, ContractAddress) { #[test] fn test_constructor() { - let (dispatcher, owner) = setup_dispatcher_with_event(); + let (_, dispatcher, owner) = setup_dispatcher_with_event(); assert_eq!(dispatcher.uri(TOKEN_ID), "URI"); assert_eq!(dispatcher.balance_of(owner, TOKEN_ID), TOKEN_VALUE); @@ -92,7 +88,7 @@ fn test_constructor() { #[test] fn test_balance_of() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let balance = dispatcher.balance_of(owner, TOKEN_ID); assert_eq!(balance, TOKEN_VALUE); @@ -100,7 +96,7 @@ fn test_balance_of() { #[test] fn test_balanceOf() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let balance = dispatcher.balanceOf(owner, TOKEN_ID); assert_eq!(balance, TOKEN_VALUE); @@ -112,7 +108,7 @@ fn test_balanceOf() { #[test] fn test_balance_of_batch() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let accounts = array![owner, OTHER()].span(); let token_ids = array![TOKEN_ID, TOKEN_ID].span(); @@ -124,7 +120,7 @@ fn test_balance_of_batch() { #[test] fn test_balanceOfBatch() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let accounts = array![owner, OTHER()].span(); let token_ids = array![TOKEN_ID, TOKEN_ID].span(); @@ -135,9 +131,9 @@ fn test_balanceOfBatch() { } #[test] -#[should_panic(expected: ('ERC1155: no equal array length', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: no equal array length',))] fn test_balance_of_batch_invalid_inputs() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let accounts = array![owner, OTHER()].span(); let token_ids = array![TOKEN_ID].span(); @@ -146,9 +142,9 @@ fn test_balance_of_batch_invalid_inputs() { } #[test] -#[should_panic(expected: ('ERC1155: no equal array length', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: no equal array length',))] fn test_balanceOfBatch_invalid_inputs() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let accounts = array![owner, OTHER()].span(); let token_ids = array![TOKEN_ID].span(); @@ -162,203 +158,219 @@ fn test_balanceOfBatch_invalid_inputs() { #[test] fn test_safe_transfer_from_to_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; let recipient = setup_receiver(); assert_state_before_transfer_single(dispatcher, owner, recipient, TOKEN_ID); dispatcher.safe_transfer_from(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy.assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); assert_state_after_transfer_single(dispatcher, owner, recipient, TOKEN_ID); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_transfer_from_to_camel_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; let recipient = setup_camel_receiver(); assert_state_before_transfer_single(dispatcher, owner, recipient, TOKEN_ID); dispatcher.safe_transfer_from(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy.assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); assert_state_after_transfer_single(dispatcher, owner, recipient, TOKEN_ID); } #[test] fn test_safeTransferFrom_to_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; let recipient = setup_receiver(); assert_state_before_transfer_single(dispatcher, owner, recipient, TOKEN_ID); dispatcher.safeTransferFrom(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy.assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); assert_state_after_transfer_single(dispatcher, owner, recipient, TOKEN_ID); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeTransferFrom_to_camel_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; let recipient = setup_camel_receiver(); assert_state_before_transfer_single(dispatcher, owner, recipient, TOKEN_ID); dispatcher.safeTransferFrom(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy.assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); assert_state_after_transfer_single(dispatcher, owner, recipient, TOKEN_ID); } #[test] fn test_safe_transfer_from_to_account() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); + spy.drop_all_events(); assert_state_before_transfer_single(dispatcher, owner, recipient, TOKEN_ID); dispatcher.safe_transfer_from(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy.assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); assert_state_after_transfer_single(dispatcher, owner, recipient, TOKEN_ID); } #[test] fn test_safeTransferFrom_to_account() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; - let recipient = setup_account_with_salt(1); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); + spy.drop_all_events(); assert_state_before_transfer_single(dispatcher, owner, recipient, TOKEN_ID); dispatcher.safeTransferFrom(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy.assert_only_event_transfer_single(contract, owner, owner, recipient, TOKEN_ID, TOKEN_VALUE); assert_state_after_transfer_single(dispatcher, owner, recipient, TOKEN_ID); } #[test] fn test_safe_transfer_from_approved_operator() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; - let recipient = setup_account_with_salt(1); let operator = OPERATOR(); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); + spy.drop_all_events(); dispatcher.set_approval_for_all(operator, true); - assert_only_event_approval_for_all(contract, owner, operator, true); + spy.assert_only_event_approval_for_all(contract, owner, operator, true); assert_state_before_transfer_single(dispatcher, owner, recipient, TOKEN_ID); - testing::set_contract_address(operator); + start_cheat_caller_address(dispatcher.contract_address, operator); dispatcher.safe_transfer_from(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(contract, operator, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract, operator, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(dispatcher, owner, recipient, TOKEN_ID); } #[test] fn test_safeTransferFrom_approved_operator() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; - let recipient = setup_account_with_salt(1); let operator = OPERATOR(); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); + spy.drop_all_events(); dispatcher.set_approval_for_all(operator, true); - assert_only_event_approval_for_all(contract, owner, operator, true); + spy.assert_only_event_approval_for_all(contract, owner, operator, true); assert_state_before_transfer_single(dispatcher, owner, recipient, TOKEN_ID); - testing::set_contract_address(operator); + start_cheat_caller_address(dispatcher.contract_address, operator); dispatcher.safeTransferFrom(owner, recipient, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); - assert_only_event_transfer_single(contract, operator, owner, recipient, TOKEN_ID, TOKEN_VALUE); + spy + .assert_only_event_transfer_single( + contract, operator, owner, recipient, TOKEN_ID, TOKEN_VALUE + ); assert_state_after_transfer_single(dispatcher, owner, recipient, TOKEN_ID); } #[test] -#[should_panic(expected: ('ERC1155: invalid sender', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: invalid sender',))] fn test_safe_transfer_from_from_zero() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); dispatcher.safe_transfer_from(ZERO(), owner, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: invalid sender', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: invalid sender',))] fn test_safeTransferFrom_from_zero() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); dispatcher.safeTransferFrom(ZERO(), owner, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: invalid receiver', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: invalid receiver',))] fn test_safe_transfer_from_to_zero() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); dispatcher.safe_transfer_from(owner, ZERO(), TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: invalid receiver', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: invalid receiver',))] fn test_safeTransferFrom_to_zero() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); dispatcher.safeTransferFrom(owner, ZERO(), TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: unauthorized operator', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: unauthorized operator',))] fn test_safe_transfer_from_unauthorized() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); dispatcher.safe_transfer_from(OTHER(), owner, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: unauthorized operator', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: unauthorized operator',))] fn test_safeTransferFrom_unauthorized() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); dispatcher.safeTransferFrom(OTHER(), owner, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: insufficient balance', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: insufficient balance',))] fn test_safe_transfer_from_insufficient_balance() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); dispatcher.safe_transfer_from(owner, OTHER(), TOKEN_ID, TOKEN_VALUE + 1, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: insufficient balance', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: insufficient balance',))] fn test_safeTransferFrom_insufficient_balance() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); dispatcher.safeTransferFrom(owner, OTHER(), TOKEN_ID, TOKEN_VALUE + 1, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: safe transfer failed', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: safe transfer failed',))] fn test_safe_transfer_from_non_account_non_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let non_receiver = setup_src5(); dispatcher.safe_transfer_from(owner, non_receiver, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: safe transfer failed', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: safe transfer failed',))] fn test_safeTransferFrom_non_account_non_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let non_receiver = setup_src5(); dispatcher.safeTransferFrom(owner, non_receiver, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA()); @@ -370,7 +382,7 @@ fn test_safeTransferFrom_non_account_non_receiver() { #[test] fn test_safe_batch_transfer_from_to_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; let recipient = setup_receiver(); let (token_ids, values) = get_ids_and_values(); @@ -378,14 +390,15 @@ fn test_safe_batch_transfer_from_to_receiver() { assert_state_before_transfer_batch(dispatcher, owner, recipient, token_ids, values); dispatcher.safe_batch_transfer_from(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); + spy.assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); assert_state_after_transfer_batch(dispatcher, owner, recipient, token_ids, values); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safe_batch_transfer_from_to_camel_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; let recipient = setup_camel_receiver(); let (token_ids, values) = get_ids_and_values(); @@ -393,14 +406,14 @@ fn test_safe_batch_transfer_from_to_camel_receiver() { assert_state_before_transfer_batch(dispatcher, owner, recipient, token_ids, values); dispatcher.safe_batch_transfer_from(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); + spy.assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); assert_state_after_transfer_batch(dispatcher, owner, recipient, token_ids, values); } #[test] fn test_safeBatchTransferFrom_to_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; let recipient = setup_receiver(); let (token_ids, values) = get_ids_and_values(); @@ -408,14 +421,15 @@ fn test_safeBatchTransferFrom_to_receiver() { assert_state_before_transfer_batch(dispatcher, owner, recipient, token_ids, values); dispatcher.safeBatchTransferFrom(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); + spy.assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); assert_state_after_transfer_batch(dispatcher, owner, recipient, token_ids, values); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_safeBatchTransferFrom_to_camel_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; let recipient = setup_camel_receiver(); let (token_ids, values) = get_ids_and_values(); @@ -423,37 +437,41 @@ fn test_safeBatchTransferFrom_to_camel_receiver() { assert_state_before_transfer_batch(dispatcher, owner, recipient, token_ids, values); dispatcher.safeBatchTransferFrom(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); + spy.assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); assert_state_after_transfer_batch(dispatcher, owner, recipient, token_ids, values); } #[test] fn test_safe_batch_transfer_from_to_account() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; - let recipient = setup_account_with_salt(1); let (token_ids, values) = get_ids_and_values(); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); + spy.drop_all_events(); assert_state_before_transfer_batch(dispatcher, owner, recipient, token_ids, values); dispatcher.safe_batch_transfer_from(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); + spy.assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); assert_state_after_transfer_batch(dispatcher, owner, recipient, token_ids, values); } #[test] fn test_safeBatchTransferFrom_to_account() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; - let recipient = setup_account_with_salt(1); let (token_ids, values) = get_ids_and_values(); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); + spy.drop_all_events(); assert_state_before_transfer_batch(dispatcher, owner, recipient, token_ids, values); dispatcher.safeBatchTransferFrom(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); + spy.assert_only_event_transfer_batch(contract, owner, owner, recipient, token_ids, values); assert_state_after_transfer_batch(dispatcher, owner, recipient, token_ids, values); } @@ -461,101 +479,105 @@ fn test_safeBatchTransferFrom_to_account() { #[test] fn test_safe_batch_transfer_from_approved_operator() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; - let recipient = setup_account_with_salt(1); - let operator = OPERATOR(); let (token_ids, values) = get_ids_and_values(); + let operator = OPERATOR(); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); + spy.drop_all_events(); dispatcher.set_approval_for_all(operator, true); - assert_only_event_approval_for_all(contract, owner, operator, true); + spy.assert_only_event_approval_for_all(contract, owner, operator, true); assert_state_before_transfer_batch(dispatcher, owner, recipient, token_ids, values); - testing::set_contract_address(operator); + start_cheat_caller_address(dispatcher.contract_address, operator); dispatcher.safe_batch_transfer_from(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(contract, operator, owner, recipient, token_ids, values); + spy.assert_only_event_transfer_batch(contract, operator, owner, recipient, token_ids, values); assert_state_after_transfer_batch(dispatcher, owner, recipient, token_ids, values); } #[test] fn test_safeBatchTransferFrom_approved_operator() { - let (dispatcher, owner) = setup_dispatcher(); + let (mut spy, dispatcher, owner) = setup_dispatcher(); let contract = dispatcher.contract_address; - let recipient = setup_account_with_salt(1); - let operator = OPERATOR(); let (token_ids, values) = get_ids_and_values(); + let operator = OPERATOR(); + let recipient = RECIPIENT(); + deploy_another_account_at(owner, recipient); + spy.drop_all_events(); dispatcher.set_approval_for_all(operator, true); - assert_only_event_approval_for_all(contract, owner, operator, true); + spy.assert_only_event_approval_for_all(contract, owner, operator, true); assert_state_before_transfer_batch(dispatcher, owner, recipient, token_ids, values); - testing::set_contract_address(operator); + start_cheat_caller_address(dispatcher.contract_address, operator); dispatcher.safeBatchTransferFrom(owner, recipient, token_ids, values, EMPTY_DATA()); - assert_only_event_transfer_batch(contract, operator, owner, recipient, token_ids, values); + spy.assert_only_event_transfer_batch(contract, operator, owner, recipient, token_ids, values); assert_state_after_transfer_batch(dispatcher, owner, recipient, token_ids, values); } #[test] -#[should_panic(expected: ('ERC1155: invalid sender', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: invalid sender',))] fn test_safe_batch_transfer_from_from_zero() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let (token_ids, values) = get_ids_and_values(); dispatcher.safe_batch_transfer_from(ZERO(), owner, token_ids, values, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: invalid sender', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: invalid sender',))] fn test_safeBatchTransferFrom_from_zero() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let (token_ids, values) = get_ids_and_values(); dispatcher.safeBatchTransferFrom(ZERO(), owner, token_ids, values, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: invalid receiver', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: invalid receiver',))] fn test_safe_batch_transfer_from_to_zero() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let (token_ids, values) = get_ids_and_values(); dispatcher.safe_batch_transfer_from(owner, ZERO(), token_ids, values, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: invalid receiver', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: invalid receiver',))] fn test_safeBatchTransferFrom_to_zero() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let (token_ids, values) = get_ids_and_values(); dispatcher.safeBatchTransferFrom(owner, ZERO(), token_ids, values, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: unauthorized operator', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: unauthorized operator',))] fn test_safe_batch_transfer_from_unauthorized() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let (token_ids, values) = get_ids_and_values(); dispatcher.safe_batch_transfer_from(OTHER(), owner, token_ids, values, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: unauthorized operator', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: unauthorized operator',))] fn test_safeBatchTransferFrom_unauthorized() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let (token_ids, values) = get_ids_and_values(); dispatcher.safeBatchTransferFrom(OTHER(), owner, token_ids, values, EMPTY_DATA()); } #[test] -#[should_panic(expected: ('ERC1155: insufficient balance', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: insufficient balance',))] fn test_safe_batch_transfer_from_insufficient_balance() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let token_ids = array![TOKEN_ID, TOKEN_ID_2].span(); let values = array![TOKEN_VALUE + 1, TOKEN_VALUE_2].span(); @@ -563,9 +585,9 @@ fn test_safe_batch_transfer_from_insufficient_balance() { } #[test] -#[should_panic(expected: ('ERC1155: insufficient balance', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: insufficient balance',))] fn test_safeBatchTransferFrom_insufficient_balance() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let token_ids = array![TOKEN_ID, TOKEN_ID_2].span(); let values = array![TOKEN_VALUE + 1, TOKEN_VALUE_2].span(); @@ -573,9 +595,9 @@ fn test_safeBatchTransferFrom_insufficient_balance() { } #[test] -#[should_panic(expected: ('ERC1155: safe transfer failed', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: safe transfer failed',))] fn test_safe_batch_transfer_from_non_account_non_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let (token_ids, values) = get_ids_and_split_values(5); let non_receiver = setup_src5(); @@ -583,9 +605,9 @@ fn test_safe_batch_transfer_from_non_account_non_receiver() { } #[test] -#[should_panic(expected: ('ERC1155: safe transfer failed', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: safe transfer failed',))] fn test_safeBatchTransferFrom_non_account_non_receiver() { - let (dispatcher, owner) = setup_dispatcher(); + let (_, dispatcher, owner) = setup_dispatcher(); let (token_ids, values) = get_ids_and_split_values(5); let non_receiver = setup_src5(); @@ -598,39 +620,39 @@ fn test_safeBatchTransferFrom_non_account_non_receiver() { #[test] fn test_set_approval_for_all_and_is_approved_for_all() { - let (dispatcher, _) = setup_dispatcher(); + let (mut spy, dispatcher, _) = setup_dispatcher(); let contract = dispatcher.contract_address; - testing::set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); let not_approved_for_all = !dispatcher.is_approved_for_all(OWNER(), OPERATOR()); assert!(not_approved_for_all); dispatcher.set_approval_for_all(OPERATOR(), true); - assert_only_event_approval_for_all(contract, OWNER(), OPERATOR(), true); + spy.assert_only_event_approval_for_all(contract, OWNER(), OPERATOR(), true); let is_approved_for_all = dispatcher.is_approved_for_all(OWNER(), OPERATOR()); assert!(is_approved_for_all); dispatcher.set_approval_for_all(OPERATOR(), false); - assert_only_event_approval_for_all(contract, OWNER(), OPERATOR(), false); + spy.assert_only_event_approval_for_all(contract, OWNER(), OPERATOR(), false); let not_approved_for_all = !dispatcher.is_approved_for_all(OWNER(), OPERATOR()); assert!(not_approved_for_all); } #[test] -#[should_panic(expected: ('ERC1155: self approval', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: self approval',))] fn test_set_approval_for_all_owner_equal_operator_true() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.set_approval_for_all(OWNER(), true); } #[test] -#[should_panic(expected: ('ERC1155: self approval', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: self approval',))] fn test_set_approval_for_all_owner_equal_operator_false() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.set_approval_for_all(OWNER(), false); } @@ -640,39 +662,39 @@ fn test_set_approval_for_all_owner_equal_operator_false() { #[test] fn test_setApprovalForAll_and_isApprovedForAll() { - let (dispatcher, _) = setup_dispatcher(); + let (mut spy, dispatcher, _) = setup_dispatcher(); let contract = dispatcher.contract_address; - testing::set_contract_address(OWNER()); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); let not_approved_for_all = !dispatcher.isApprovedForAll(OWNER(), OPERATOR()); assert!(not_approved_for_all); dispatcher.setApprovalForAll(OPERATOR(), true); - assert_only_event_approval_for_all(contract, OWNER(), OPERATOR(), true); + spy.assert_only_event_approval_for_all(contract, OWNER(), OPERATOR(), true); let is_approved_for_all = dispatcher.isApprovedForAll(OWNER(), OPERATOR()); assert!(is_approved_for_all); dispatcher.setApprovalForAll(OPERATOR(), false); - assert_only_event_approval_for_all(contract, OWNER(), OPERATOR(), false); + spy.assert_only_event_approval_for_all(contract, OWNER(), OPERATOR(), false); let not_approved_for_all = !dispatcher.isApprovedForAll(OWNER(), OPERATOR()); assert!(not_approved_for_all); } #[test] -#[should_panic(expected: ('ERC1155: self approval', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: self approval',))] fn test_setApprovalForAll_owner_equal_operator_true() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.set_approval_for_all(OWNER(), true); } #[test] -#[should_panic(expected: ('ERC1155: self approval', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('ERC1155: self approval',))] fn test_setApprovalForAll_owner_equal_operator_false() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(OWNER()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OWNER()); dispatcher.setApprovalForAll(OWNER(), false); } @@ -682,69 +704,69 @@ fn test_setApprovalForAll_owner_equal_operator_false() { #[test] fn test_transfer_ownership() { - let (dispatcher, owner) = setup_dispatcher(); - testing::set_contract_address(owner); + let (mut spy, dispatcher, owner) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, owner); dispatcher.transfer_ownership(OTHER()); - assert_event_ownership_transferred(dispatcher.contract_address, owner, OTHER()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, owner, OTHER()); assert_eq!(dispatcher.owner(), OTHER()); } #[test] -#[should_panic(expected: ('New owner is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('New owner is the zero address',))] fn test_transfer_ownership_to_zero() { - let (dispatcher, owner) = setup_dispatcher(); - testing::set_contract_address(owner); + let (_, dispatcher, owner) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, owner); dispatcher.transfer_ownership(ZERO()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_transfer_ownership_from_zero() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(ZERO()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.transfer_ownership(OTHER()); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_transfer_ownership_from_nonowner() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.transfer_ownership(OTHER()); } #[test] fn test_transferOwnership() { - let (dispatcher, owner) = setup_dispatcher(); - testing::set_contract_address(owner); + let (mut spy, dispatcher, owner) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, owner); dispatcher.transferOwnership(OTHER()); - assert_event_ownership_transferred(dispatcher.contract_address, owner, OTHER()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, owner, OTHER()); assert_eq!(dispatcher.owner(), OTHER()); } #[test] -#[should_panic(expected: ('New owner is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('New owner is the zero address',))] fn test_transferOwnership_to_zero() { - let (dispatcher, owner) = setup_dispatcher(); - testing::set_contract_address(owner); + let (_, dispatcher, owner) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, owner); dispatcher.transferOwnership(ZERO()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_transferOwnership_from_zero() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(ZERO()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.transferOwnership(OTHER()); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_transferOwnership_from_nonowner() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.transferOwnership(OTHER()); } @@ -754,53 +776,53 @@ fn test_transferOwnership_from_nonowner() { #[test] fn test_renounce_ownership() { - let (dispatcher, owner) = setup_dispatcher(); - testing::set_contract_address(owner); + let (mut spy, dispatcher, owner) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, owner); dispatcher.renounce_ownership(); - assert_event_ownership_transferred(dispatcher.contract_address, owner, ZERO()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, owner, ZERO()); assert!(dispatcher.owner().is_zero()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_renounce_ownership_from_zero_address() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(ZERO()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.renounce_ownership(); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_renounce_ownership_from_nonowner() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.renounce_ownership(); } #[test] fn test_renounceOwnership() { - let (dispatcher, owner) = setup_dispatcher(); - testing::set_contract_address(owner); + let (mut spy, dispatcher, owner) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, owner); dispatcher.renounceOwnership(); - assert_event_ownership_transferred(dispatcher.contract_address, owner, ZERO()); + spy.assert_event_ownership_transferred(dispatcher.contract_address, owner, ZERO()); assert!(dispatcher.owner().is_zero()); } #[test] -#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is the zero address',))] fn test_renounceOwnership_from_zero_address() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(ZERO()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, ZERO()); dispatcher.renounceOwnership(); } #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_renounceOwnership_from_nonowner() { - let (dispatcher, _) = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, dispatcher, _) = setup_dispatcher(); + start_cheat_caller_address(dispatcher.contract_address, OTHER()); dispatcher.renounceOwnership(); } @@ -809,53 +831,57 @@ fn test_renounceOwnership_from_nonowner() { // #[test] -#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Caller is not the owner',))] fn test_upgrade_unauthorized() { - let (v1, _) = setup_dispatcher(); - testing::set_contract_address(OTHER()); + let (_, v1, _) = setup_dispatcher(); + start_cheat_caller_address(v1.contract_address, OTHER()); v1.upgrade(CLASS_HASH_ZERO()); } #[test] -#[should_panic(expected: ('Class hash cannot be zero', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Class hash cannot be zero',))] fn test_upgrade_with_class_hash_zero() { - let (v1, owner) = setup_dispatcher(); + let (_, v1, owner) = setup_dispatcher(); - testing::set_contract_address(owner); + start_cheat_caller_address(v1.contract_address, owner); v1.upgrade(CLASS_HASH_ZERO()); } #[test] fn test_upgraded_event() { - let (v1, owner) = setup_dispatcher(); + let (mut spy, v1, owner) = setup_dispatcher(); let v2_class_hash = V2_CLASS_HASH(); - testing::set_contract_address(owner); + start_cheat_caller_address(v1.contract_address, owner); v1.upgrade(v2_class_hash); - assert_only_event_upgraded(v1.contract_address, v2_class_hash); + spy.assert_only_event_upgraded(v1.contract_address, v2_class_hash); } #[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +#[feature("safe_dispatcher")] fn test_v2_missing_camel_selector() { - let (v1, owner) = setup_dispatcher(); + let (_, v1, owner) = setup_dispatcher(); let v2_class_hash = V2_CLASS_HASH(); - testing::set_contract_address(owner); + start_cheat_caller_address(v1.contract_address, owner); v1.upgrade(v2_class_hash); - let dispatcher = IERC1155CamelDispatcher { contract_address: v1.contract_address }; - dispatcher.balanceOf(owner, TOKEN_ID); + let safe_dispatcher = IERC1155CamelSafeDispatcher { contract_address: v1.contract_address }; + let panic_data = safe_dispatcher.balanceOf(owner, TOKEN_ID).unwrap_err(); + + utils::assert_entrypoint_not_found_error( + panic_data, selector!("balanceOf"), v1.contract_address + ) } #[test] fn test_state_persists_after_upgrade() { - let (v1, owner) = setup_dispatcher(); + let (_, v1, owner) = setup_dispatcher(); let recipient = setup_receiver(); let v2_class_hash = V2_CLASS_HASH(); - testing::set_contract_address(owner); + start_cheat_caller_address(v1.contract_address, owner); v1.safeTransferFrom(owner, recipient, TOKEN_ID, TOKEN_VALUE, array![].span()); // Check RECIPIENT balance v1 diff --git a/src/tests/presets/test_erc20.cairo b/src/tests/presets/test_erc20.cairo index 2625ac249..8d10d7ab8 100644 --- a/src/tests/presets/test_erc20.cairo +++ b/src/tests/presets/test_erc20.cairo @@ -482,13 +482,9 @@ fn test_v2_missing_camel_selector() { }; let mut panic_data = safe_dispatcher.totalSupply().unwrap_err(); - let selector = selector!("totalSupply"); - let expected_panic_message = format!( - "Entry point selector {} not found in contract {}", - selector.into_base_16_string(), - v1.contract_address.into_base_16_string() - ); - assert_eq!(utils::panic_data_to_byte_array(panic_data), expected_panic_message); + utils::assert_entrypoint_not_found_error( + panic_data, selector!("totalSupply"), v1.contract_address + ) } #[test] diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo index 1c31f8a61..509c33ee1 100644 --- a/src/tests/utils.cairo +++ b/src/tests/utils.cairo @@ -4,7 +4,10 @@ pub(crate) mod deployment; pub(crate) mod events; pub(crate) mod signing; -pub use common::{panic_data_to_byte_array, to_base_16_string, IntoBase16StringTrait}; +pub use common::{ + panic_data_to_byte_array, to_base_16_string, IntoBase16StringTrait, + assert_entrypoint_not_found_error +}; pub use deployment::{ declare_class, declare_and_deploy, declare_and_deploy_at, deploy, deploy_at, deploy_another_at }; diff --git a/src/tests/utils/common.cairo b/src/tests/utils/common.cairo index c48a85344..853be448b 100644 --- a/src/tests/utils/common.cairo +++ b/src/tests/utils/common.cairo @@ -1,4 +1,5 @@ use core::to_byte_array::FormatAsByteArray; +use starknet::ContractAddress; /// Converts panic data into a string (ByteArray). /// @@ -34,3 +35,16 @@ pub impl IntoBase16String> of IntoBase16StringTrait { to_base_16_string(self.into()) } } + +/// Asserts that the panic data is an "Entrypoint not found" error, following the starknet foundry +/// emitted error format. +pub fn assert_entrypoint_not_found_error( + panic_data: Array, selector: felt252, contract_address: ContractAddress +) { + let expected_panic_message = format!( + "Entry point selector {} not found in contract {}", + selector.into_base_16_string(), + contract_address.into_base_16_string() + ); + assert!(panic_data_to_byte_array(panic_data) == expected_panic_message); +} From c34d4d080acdf24c3a1daffc074d84fad4deff47 Mon Sep 17 00:00:00 2001 From: Andrew Fleming Date: Mon, 22 Jul 2024 14:22:34 -0400 Subject: [PATCH 15/45] Migrate cryptography and UDC tests (#1059) * fix import name * migrate cryptography tests * migrate udc tests * fix fmt * fix impl name * fix event assertions * re-add class hash helper --- src/tests.cairo | 4 +- src/tests/cryptography/test_snip12.cairo | 4 +- src/tests/presets.cairo | 4 +- src/tests/presets/test_erc1155.cairo | 2 +- .../presets/test_universal_deployer.cairo | 123 ++++++++++-------- 5 files changed, 79 insertions(+), 58 deletions(-) diff --git a/src/tests.cairo b/src/tests.cairo index a3fa799ac..f64c4098e 100644 --- a/src/tests.cairo +++ b/src/tests.cairo @@ -2,8 +2,8 @@ mod access; // #[cfg(test)] // mod account; -// #[cfg(test)] -// mod cryptography; +#[cfg(test)] +mod cryptography; #[cfg(test)] mod introspection; mod mocks; diff --git a/src/tests/cryptography/test_snip12.cairo b/src/tests/cryptography/test_snip12.cairo index e0caeffc1..6ffa80df8 100644 --- a/src/tests/cryptography/test_snip12.cairo +++ b/src/tests/cryptography/test_snip12.cairo @@ -4,6 +4,7 @@ use openzeppelin::tests::utils::constants::{OWNER, RECIPIENT}; use openzeppelin::utils::cryptography::snip12::{ STARKNET_DOMAIN_TYPE_HASH, StarknetDomain, StructHash, OffchainMessageHashImpl, SNIP12Metadata }; +use snforge_std::{start_cheat_chain_id, test_address}; use starknet::ContractAddress; const MESSAGE_TYPE_HASH: felt252 = @@ -59,7 +60,8 @@ fn test_OffchainMessageHashImpl() { let message = Message { recipient: RECIPIENT(), amount: 100, nonce: 1, expiry: 1000 }; let domain = StarknetDomain { name: 'DAPP_NAME', version: 'v1', chain_id: 'TEST', revision: 1 }; - starknet::testing::set_chain_id('TEST'); + let contract_address = test_address(); + start_cheat_chain_id(contract_address, 'TEST'); let expected = poseidon_hash_span( array!['StarkNet Message', domain.hash_struct(), OWNER().into(), message.hash_struct()] diff --git a/src/tests/presets.cairo b/src/tests/presets.cairo index d8b4fdd0e..cc599a931 100644 --- a/src/tests/presets.cairo +++ b/src/tests/presets.cairo @@ -3,6 +3,4 @@ mod test_erc1155; mod test_erc20; mod test_erc721; // mod test_eth_account; -// mod test_universal_deployer; - - +mod test_universal_deployer; diff --git a/src/tests/presets/test_erc1155.cairo b/src/tests/presets/test_erc1155.cairo index 454e97ae9..57c597612 100644 --- a/src/tests/presets/test_erc1155.cairo +++ b/src/tests/presets/test_erc1155.cairo @@ -9,7 +9,7 @@ use openzeppelin::tests::token::erc1155::common::{ setup_account, setup_receiver, setup_camel_receiver, deploy_another_account_at, setup_src5 }; use openzeppelin::tests::token::erc1155::common::{get_ids_and_values, get_ids_and_split_values}; -use openzeppelin::tests::upgrades::common::UpgradableSpyHelpers; +use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; use openzeppelin::tests::utils::constants::{ EMPTY_DATA, ZERO, OWNER, RECIPIENT, CLASS_HASH_ZERO, OPERATOR, OTHER, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 diff --git a/src/tests/presets/test_universal_deployer.cairo b/src/tests/presets/test_universal_deployer.cairo index e5247a9ae..e5874bcbc 100644 --- a/src/tests/presets/test_universal_deployer.cairo +++ b/src/tests/presets/test_universal_deployer.cairo @@ -1,7 +1,7 @@ use openzeppelin::presets::universal_deployer::UniversalDeployer::ContractDeployed; use openzeppelin::presets::universal_deployer::UniversalDeployer; -use openzeppelin::tests::mocks::erc20_mocks::DualCaseERC20Mock; use openzeppelin::tests::utils::constants::{NAME, SYMBOL, SUPPLY, SALT, CALLER, RECIPIENT}; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::tests::utils; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use openzeppelin::utils::deployments::{DeployerInfo, calculate_contract_address_from_udc}; @@ -9,13 +9,12 @@ use openzeppelin::utils::interfaces::{ IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait }; use openzeppelin::utils::serde::SerializedAppend; -use starknet::ClassHash; -use starknet::ContractAddress; -use starknet::testing; +use snforge_std::{EventSpy, spy_events, declare, start_cheat_caller_address}; +use starknet::{ClassHash, ContractAddress}; fn ERC20_CLASS_HASH() -> ClassHash { - DualCaseERC20Mock::TEST_CLASS_HASH.try_into().unwrap() + utils::declare_class("DualCaseERC20Mock").class_hash } fn ERC20_CALLDATA() -> Span { @@ -28,35 +27,45 @@ fn ERC20_CALLDATA() -> Span { } fn deploy_udc() -> IUniversalDeployerDispatcher { - let calldata = array![]; - let address = utils::deploy(UniversalDeployer::TEST_CLASS_HASH, calldata); + let mut calldata = array![]; + let address = utils::declare_and_deploy("UniversalDeployer", calldata); IUniversalDeployerDispatcher { contract_address: address } } #[test] fn test_deploy_from_zero() { let udc = deploy_udc(); + let caller = CALLER(); + + // Deploy args + let erc20_class_hash = ERC20_CLASS_HASH(); + let salt = SALT; let from_zero = true; - testing::set_contract_address(CALLER()); + let erc20_calldata = ERC20_CALLDATA(); + + let mut spy = spy_events(); + start_cheat_caller_address(udc.contract_address, caller); // Check address let expected_addr = calculate_contract_address_from_udc( - SALT, ERC20_CLASS_HASH(), ERC20_CALLDATA(), Option::None + salt, erc20_class_hash, erc20_calldata, Option::None ); - let deployed_addr = udc.deploy_contract(ERC20_CLASS_HASH(), SALT, from_zero, ERC20_CALLDATA()); + let deployed_addr = udc.deploy_contract(erc20_class_hash, salt, from_zero, erc20_calldata); assert_eq!(expected_addr, deployed_addr); - // Check event - assert_only_event_contract_deployed( - udc.contract_address, - deployed_addr, - CALLER(), - from_zero, - ERC20_CLASS_HASH(), - ERC20_CALLDATA(), - SALT - ); + // Drop ERC20 event, check deploy event + spy.drop_event(); + spy + .assert_only_event_contract_deployed( + udc.contract_address, + deployed_addr, + caller, + from_zero, + erc20_class_hash, + erc20_calldata, + salt + ); // Check deployment let erc20 = IERC20Dispatcher { contract_address: deployed_addr }; @@ -67,29 +76,39 @@ fn test_deploy_from_zero() { #[test] fn test_deploy_not_from_zero() { let udc = deploy_udc(); + let caller = CALLER(); + + // Deploy args + let erc20_class_hash = ERC20_CLASS_HASH(); + let salt = SALT; let from_zero = false; - testing::set_contract_address(CALLER()); + let erc20_calldata = ERC20_CALLDATA(); + + let mut spy = spy_events(); + start_cheat_caller_address(udc.contract_address, caller); // Check address let expected_addr = calculate_contract_address_from_udc( - SALT, - ERC20_CLASS_HASH(), - ERC20_CALLDATA(), - Option::Some(DeployerInfo { caller_address: CALLER(), udc_address: udc.contract_address }) + salt, + erc20_class_hash, + erc20_calldata, + Option::Some(DeployerInfo { caller_address: caller, udc_address: udc.contract_address }) ); - let deployed_addr = udc.deploy_contract(ERC20_CLASS_HASH(), SALT, from_zero, ERC20_CALLDATA()); + let deployed_addr = udc.deploy_contract(erc20_class_hash, salt, from_zero, erc20_calldata); assert_eq!(expected_addr, deployed_addr); - // Check event - assert_only_event_contract_deployed( - udc.contract_address, - deployed_addr, - CALLER(), - from_zero, - ERC20_CLASS_HASH(), - ERC20_CALLDATA(), - SALT - ); + // Drop ERC20 event, check deploy event + spy.drop_event(); + spy + .assert_only_event_contract_deployed( + udc.contract_address, + deployed_addr, + caller, + from_zero, + erc20_class_hash, + erc20_calldata, + salt + ); // Check deployment let erc20 = IERC20Dispatcher { contract_address: deployed_addr }; @@ -101,19 +120,21 @@ fn test_deploy_not_from_zero() { // Helpers // -fn assert_only_event_contract_deployed( - contract: ContractAddress, - address: ContractAddress, - deployer: ContractAddress, - from_zero: bool, - class_hash: ClassHash, - calldata: Span, - salt: felt252 -) { - let event = utils::pop_log::(contract).unwrap(); - let expected = UniversalDeployer::Event::ContractDeployed( - ContractDeployed { address, deployer, from_zero, class_hash, calldata, salt } - ); - assert!(event == expected); - utils::assert_no_events_left(contract); +#[generate_trait] +impl UniversalDeployerHelpersImpl of UniversalDeployerSpyHelpers { + fn assert_only_event_contract_deployed( + ref self: EventSpy, + contract: ContractAddress, + address: ContractAddress, + deployer: ContractAddress, + from_zero: bool, + class_hash: ClassHash, + calldata: Span, + salt: felt252 + ) { + let expected = UniversalDeployer::Event::ContractDeployed( + ContractDeployed { address, deployer, from_zero, class_hash, calldata, salt } + ); + self.assert_only_event(contract, expected); + } } From ba8004c029d963178722952ba73130c322c78636 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 23 Jul 2024 23:30:50 +0200 Subject: [PATCH 16/45] Migrate eth account tests (#1058) * feat: update dual_eth_account tests * feat: update eth_account tests * refactor: remove unused helpers * refactor: some inconsistencies * Update src/tests/account/ethereum/test_eth_account.cairo Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com> * feat: apply review updates * refactor: format files * Update src/tests/account/ethereum/test_eth_account.cairo Co-authored-by: Andrew Fleming --------- Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com> Co-authored-by: Andrew Fleming --- src/tests.cairo | 4 +- src/tests/account/ethereum.cairo | 1 + src/tests/account/ethereum/common.cairo | 122 ++++---- .../ethereum/test_dual_eth_account.cairo | 153 ++++------ .../account/ethereum/test_eth_account.cairo | 268 ++++++++---------- src/tests/account/starknet.cairo | 5 +- src/tests/account/starknet/common.cairo | 56 ++-- src/tests/account/test_secp256k1.cairo | 18 +- src/tests/account/test_signature.cairo | 27 +- src/tests/utils.cairo | 8 +- src/tests/utils/constants.cairo | 20 ++ src/tests/utils/signing.cairo | 20 +- 12 files changed, 335 insertions(+), 367 deletions(-) diff --git a/src/tests.cairo b/src/tests.cairo index f64c4098e..fab03b247 100644 --- a/src/tests.cairo +++ b/src/tests.cairo @@ -1,7 +1,7 @@ #[cfg(test)] mod access; -// #[cfg(test)] -// mod account; +#[cfg(test)] +mod account; #[cfg(test)] mod cryptography; #[cfg(test)] diff --git a/src/tests/account/ethereum.cairo b/src/tests/account/ethereum.cairo index d6fcf488b..2d87a5992 100644 --- a/src/tests/account/ethereum.cairo +++ b/src/tests/account/ethereum.cairo @@ -2,3 +2,4 @@ pub(crate) mod common; mod test_dual_eth_account; mod test_eth_account; + diff --git a/src/tests/account/ethereum/common.cairo b/src/tests/account/ethereum/common.cairo index faf88a25c..58f9a809f 100644 --- a/src/tests/account/ethereum/common.cairo +++ b/src/tests/account/ethereum/common.cairo @@ -1,104 +1,94 @@ +use core::hash::{HashStateTrait, HashStateExTrait}; +use core::poseidon::PoseidonTrait; use core::poseidon::poseidon_hash_span; use core::starknet::secp256_trait::Secp256PointTrait; use openzeppelin::account::EthAccountComponent::{OwnerAdded, OwnerRemoved}; use openzeppelin::account::EthAccountComponent; use openzeppelin::account::interface::EthPublicKey; use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin::tests::mocks::erc20_mocks::DualCaseERC20Mock; +use openzeppelin::tests::utils::constants::TRANSACTION_HASH; use openzeppelin::tests::utils::constants::{NAME, SYMBOL}; +use openzeppelin::tests::utils::events::EventSpyExt; +use openzeppelin::tests::utils::signing::{Secp256k1KeyPair, Secp256k1KeyPairExt}; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use openzeppelin::utils::serde::SerializedAppend; -use starknet::ContractAddress; -use starknet::SyscallResultTrait; -use starknet::secp256_trait::Secp256Trait; -use starknet::secp256k1::Secp256k1Point; +use snforge_std::EventSpy; +use snforge_std::signature::secp256k1_curve::Secp256k1CurveSignerImpl; +use starknet::{ContractAddress, SyscallResultTrait}; #[derive(Drop)] pub(crate) struct SignedTransactionData { pub(crate) private_key: u256, pub(crate) public_key: EthPublicKey, - pub(crate) transaction_hash: felt252, + pub(crate) tx_hash: felt252, pub(crate) signature: EthSignature } -/// This signature was computed using ethers.js. -pub(crate) fn SIGNED_TX_DATA() -> SignedTransactionData { +pub(crate) fn SIGNED_TX_DATA(key_pair: Secp256k1KeyPair) -> SignedTransactionData { + let tx_hash = TRANSACTION_HASH; + let (r, s) = key_pair.sign(tx_hash.into()).unwrap(); SignedTransactionData { - private_key: 0x45397ee6ca34cb49060f1c303c6cb7ee2d6123e617601ef3e31ccf7bf5bef1f9, - public_key: NEW_ETH_PUBKEY(), - transaction_hash: 0x008f882c63d0396d216d57529fe29ad5e70b6cd51b47bd2458b0a4ccb2ba0957, - signature: EthSignature { - r: 0x82bb3efc0554ec181405468f273b0dbf935cca47182b22da78967d0770f7dcc3, - s: 0x6719fef30c11c74add873e4da0e1234deb69eae6a6bd4daa44b816dc199f3e86, - } + private_key: key_pair.secret_key, + public_key: key_pair.public_key, + tx_hash, + signature: EthSignature { r, s } } } -pub(crate) fn NEW_ETH_PUBKEY() -> EthPublicKey { - Secp256Trait::secp256_ec_new_syscall( - 0x829307f82a1883c2414503ba85fc85037f22c6fc6f80910801f6b01a4131da1e, - 0x2a23f7bddf3715d11767b1247eccc68c89e11b926e2615268db6ad1af8d8da96 - ) - .unwrap() - .unwrap() +pub(crate) fn get_accept_ownership_signature( + account_address: ContractAddress, current_owner: EthPublicKey, new_key_pair: Secp256k1KeyPair +) -> Span { + let msg_hash: u256 = PoseidonTrait::new() + .update_with('StarkNet Message') + .update_with('accept_ownership') + .update_with(account_address) + .update_with(current_owner.get_coordinates().unwrap_syscall()) + .finalize() + .into(); + + new_key_pair.serialized_sign(msg_hash).span() } pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { - let name = NAME(); - let symbol = SYMBOL(); let mut calldata = array![]; - calldata.append_serde(name); - calldata.append_serde(symbol); + calldata.append_serde(NAME()); + calldata.append_serde(SYMBOL()); calldata.append_serde(initial_supply); calldata.append_serde(recipient); - let address = utils::deploy(DualCaseERC20Mock::TEST_CLASS_HASH, calldata); + let address = utils::declare_and_deploy("DualCaseERC20Mock", calldata); IERC20Dispatcher { contract_address: address } } -pub(crate) fn get_points() -> (Secp256k1Point, Secp256k1Point) { - let curve_size = Secp256Trait::::get_curve_size(); - let point_1 = Secp256Trait::secp256_ec_get_point_from_x_syscall(curve_size, true) - .unwrap_syscall() - .unwrap(); - let point_2 = Secp256Trait::secp256_ec_get_point_from_x_syscall(curve_size, false) - .unwrap_syscall() - .unwrap(); - - (point_1, point_2) -} - -pub(crate) fn assert_event_owner_added(contract: ContractAddress, public_key: EthPublicKey) { - let event = utils::pop_log::(contract).unwrap(); - let new_owner_guid = get_guid_from_public_key(public_key); - let expected = EthAccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("OwnerAdded")); - indexed_keys.append_serde(new_owner_guid); - utils::assert_indexed_keys(event, indexed_keys.span()); -} -pub(crate) fn assert_only_event_owner_added(contract: ContractAddress, public_key: EthPublicKey) { - assert_event_owner_added(contract, public_key); - utils::assert_no_events_left(contract); -} +#[generate_trait] +pub(crate) impl EthAccountSpyHelpersImpl of EthAccountSpyHelpers { + fn assert_event_owner_removed( + ref self: EventSpy, contract: ContractAddress, public_key: EthPublicKey + ) { + let removed_owner_guid = get_guid_from_public_key(public_key); + let expected = EthAccountComponent::Event::OwnerRemoved( + OwnerRemoved { removed_owner_guid } + ); + self.assert_emitted_single(contract, expected); + } -pub(crate) fn assert_event_owner_removed(contract: ContractAddress, public_key: EthPublicKey) { - let event = utils::pop_log::(contract).unwrap(); - let removed_owner_guid = get_guid_from_public_key(public_key); - let expected = EthAccountComponent::Event::OwnerRemoved(OwnerRemoved { removed_owner_guid }); - assert!(event == expected); + fn assert_event_owner_added( + ref self: EventSpy, contract: ContractAddress, public_key: EthPublicKey + ) { + let new_owner_guid = get_guid_from_public_key(public_key); + let expected = EthAccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); + self.assert_emitted_single(contract, expected); + } - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("OwnerRemoved")); - indexed_keys.append_serde(removed_owner_guid); - utils::assert_indexed_keys(event, indexed_keys.span()); + fn assert_only_event_owner_added( + ref self: EventSpy, contract: ContractAddress, public_key: EthPublicKey + ) { + self.assert_event_owner_added(contract, public_key); + self.assert_no_events_left_from(contract); + } } fn get_guid_from_public_key(public_key: EthPublicKey) -> felt252 { diff --git a/src/tests/account/ethereum/test_dual_eth_account.cairo b/src/tests/account/ethereum/test_dual_eth_account.cairo index b627724d5..bad86716a 100644 --- a/src/tests/account/ethereum/test_dual_eth_account.cairo +++ b/src/tests/account/ethereum/test_dual_eth_account.cairo @@ -5,16 +5,14 @@ use openzeppelin::account::utils::secp256k1::{ }; use openzeppelin::account::utils::signature::EthSignature; use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::tests::mocks::eth_account_mocks::{ - CamelEthAccountPanicMock, CamelEthAccountMock, SnakeEthAccountMock, SnakeEthAccountPanicMock -}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::ETH_PUBKEY; +use openzeppelin::tests::utils::constants::secp256k1::KEY_PAIR; +use openzeppelin::tests::utils::constants::{ETH_PUBKEY, NEW_ETH_PUBKEY, TRANSACTION_HASH}; +use openzeppelin::tests::utils::signing::Secp256k1KeyPairExt; use openzeppelin::tests::utils; use openzeppelin::utils::serde::SerializedAppend; -use starknet::testing; +use snforge_std::start_cheat_caller_address; -use super::common::{NEW_ETH_PUBKEY, SIGNED_TX_DATA}; +use super::common::get_accept_ownership_signature; // // Setup @@ -24,7 +22,7 @@ fn setup_snake() -> (DualCaseEthAccount, EthAccountABIDispatcher) { let mut calldata = array![]; calldata.append_serde(ETH_PUBKEY()); - let target = utils::deploy(SnakeEthAccountMock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("SnakeEthAccountMock", calldata); ( DualCaseEthAccount { contract_address: target }, EthAccountABIDispatcher { contract_address: target } @@ -35,7 +33,7 @@ fn setup_camel() -> (DualCaseEthAccount, EthAccountABIDispatcher) { let mut calldata = array![]; calldata.append_serde(ETH_PUBKEY()); - let target = utils::deploy(CamelEthAccountMock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("CamelEthAccountMock", calldata); ( DualCaseEthAccount { contract_address: target }, EthAccountABIDispatcher { contract_address: target } @@ -44,13 +42,13 @@ fn setup_camel() -> (DualCaseEthAccount, EthAccountABIDispatcher) { fn setup_non_account() -> DualCaseEthAccount { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("NonImplementingMock", calldata); DualCaseEthAccount { contract_address: target } } fn setup_account_panic() -> (DualCaseEthAccount, DualCaseEthAccount) { - let snake_target = utils::deploy(SnakeEthAccountPanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelEthAccountPanicMock::TEST_CLASS_HASH, array![]); + let snake_target = utils::declare_and_deploy("SnakeEthAccountPanicMock", array![]); + let camel_target = utils::declare_and_deploy("CamelEthAccountPanicMock", array![]); ( DualCaseEthAccount { contract_address: snake_target }, DualCaseEthAccount { contract_address: camel_target } @@ -64,15 +62,19 @@ fn setup_account_panic() -> (DualCaseEthAccount, DualCaseEthAccount) { #[test] fn test_dual_set_public_key() { let (snake_dispatcher, target) = setup_snake(); + let contract_address = snake_dispatcher.contract_address; + + start_cheat_caller_address(contract_address, contract_address); - testing::set_contract_address(snake_dispatcher.contract_address); + let key_pair = KEY_PAIR(); + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); - let new_public_key = NEW_ETH_PUBKEY(); - snake_dispatcher.set_public_key(new_public_key, get_accept_ownership_signature_snake()); - assert_eq!(target.get_public_key(), new_public_key); + snake_dispatcher.set_public_key(key_pair.public_key, signature); + assert_eq!(target.get_public_key(), key_pair.public_key); } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_set_public_key() { let dispatcher = setup_non_account(); @@ -80,7 +82,7 @@ fn test_dual_no_set_public_key() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_set_public_key_exists_and_panics() { let (dispatcher, _) = setup_account_panic(); dispatcher.set_public_key(NEW_ETH_PUBKEY(), array![].span()); @@ -93,6 +95,7 @@ fn test_dual_get_public_key() { } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_get_public_key() { let dispatcher = setup_non_account(); @@ -100,7 +103,7 @@ fn test_dual_no_get_public_key() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_get_public_key_exists_and_panics() { let (dispatcher, _) = setup_account_panic(); dispatcher.get_public_key(); @@ -109,20 +112,21 @@ fn test_dual_get_public_key_exists_and_panics() { #[test] fn test_dual_is_valid_signature() { let (snake_dispatcher, target) = setup_snake(); + let contract_address = snake_dispatcher.contract_address; - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; - let mut serialized_signature = array![]; - data.signature.serialize(ref serialized_signature); + start_cheat_caller_address(contract_address, contract_address); + let key_pair = KEY_PAIR(); + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); - testing::set_contract_address(snake_dispatcher.contract_address); - target.set_public_key(data.public_key, get_accept_ownership_signature_snake()); + target.set_public_key(key_pair.public_key, signature); + let serialized_signature = key_pair.serialized_sign(TRANSACTION_HASH.into()); - let is_valid = snake_dispatcher.is_valid_signature(hash, serialized_signature); + let is_valid = snake_dispatcher.is_valid_signature(TRANSACTION_HASH, serialized_signature); assert_eq!(is_valid, starknet::VALIDATED); } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_is_valid_signature() { let hash = 0x0; @@ -133,7 +137,7 @@ fn test_dual_no_is_valid_signature() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_is_valid_signature_exists_and_panics() { let hash = 0x0; let signature = array![]; @@ -149,6 +153,7 @@ fn test_dual_supports_interface() { } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_supports_interface() { let dispatcher = setup_non_account(); @@ -156,7 +161,7 @@ fn test_dual_no_supports_interface() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_supports_interface_exists_and_panics() { let (dispatcher, _) = setup_account_panic(); dispatcher.supports_interface(ISRC5_ID); @@ -167,54 +172,64 @@ fn test_dual_supports_interface_exists_and_panics() { // #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_setPublicKey() { let (camel_dispatcher, target) = setup_camel(); - let new_public_key = NEW_ETH_PUBKEY(); + let contract_address = camel_dispatcher.contract_address; + + start_cheat_caller_address(contract_address, contract_address); - testing::set_contract_address(camel_dispatcher.contract_address); + let key_pair = KEY_PAIR(); + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); - camel_dispatcher.set_public_key(new_public_key, get_accept_ownership_signature_camel()); - assert_eq!(target.getPublicKey(), new_public_key); + camel_dispatcher.set_public_key(key_pair.public_key, signature); + assert_eq!(target.getPublicKey(), key_pair.public_key); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_setPublicKey_exists_and_panics() { let (_, dispatcher) = setup_account_panic(); dispatcher.set_public_key(NEW_ETH_PUBKEY(), array![].span()); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_getPublicKey() { let (camel_dispatcher, _) = setup_camel(); assert_eq!(camel_dispatcher.get_public_key(), ETH_PUBKEY()); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_getPublicKey_exists_and_panics() { let (_, dispatcher) = setup_account_panic(); dispatcher.get_public_key(); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_isValidSignature() { let (camel_dispatcher, target) = setup_camel(); + let contract_address = camel_dispatcher.contract_address; - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; - let mut serialized_signature = array![]; - data.signature.serialize(ref serialized_signature); + start_cheat_caller_address(contract_address, contract_address); - testing::set_contract_address(camel_dispatcher.contract_address); - target.setPublicKey(data.public_key, get_accept_ownership_signature_camel()); + let key_pair = KEY_PAIR(); + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); - let is_valid = camel_dispatcher.is_valid_signature(hash, serialized_signature); + target.setPublicKey(key_pair.public_key, signature); + let serialized_signature = key_pair.serialized_sign(TRANSACTION_HASH.into()); + + let is_valid = camel_dispatcher.is_valid_signature(TRANSACTION_HASH, serialized_signature); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_isValidSignature_exists_and_panics() { let hash = 0x0; let signature = array![]; @@ -222,59 +237,3 @@ fn test_dual_isValidSignature_exists_and_panics() { let (_, dispatcher) = setup_account_panic(); dispatcher.is_valid_signature(hash, signature); } - -// -// Helpers -// - -fn get_accept_ownership_signature_snake() -> Span { - let mut output = array![]; - - // 0x03e8d3aa715dc5fc3b93c7572df7d6f227a6aad93a77873db3308b30897eee53 = - // PoseidonTrait::new() - // .update_with('StarkNet Message') - // .update_with('accept_ownership') - // .update_with(snake_dispatcher.contract_address) - // .update_with(ETH_PUBKEY().get_coordinates().unwrap_syscall()) - // .finalize(); - - // This signature was computed using ethers js sdk from the following values: - // - private_key: 0x45397ee6ca34cb49060f1c303c6cb7ee2d6123e617601ef3e31ccf7bf5bef1f9 - // - public_key: - // r: 0x829307f82a1883c2414503ba85fc85037f22c6fc6f80910801f6b01a4131da1e - // s: 0x2a23f7bddf3715d11767b1247eccc68c89e11b926e2615268db6ad1af8d8da96 - // - msg_hash: 0x03e8d3aa715dc5fc3b93c7572df7d6f227a6aad93a77873db3308b30897eee53 - EthSignature { - r: 0x7e1ff13cbdf03e92125a69cb1e4ad94f2178720d156df3827c8d3172484fbfd8, - s: 0x0def4eb71f21bc623c0ca896cb3356cee12504da7b19021d3253d433366e0a3e, - } - .serialize(ref output); - - output.span() -} - -fn get_accept_ownership_signature_camel() -> Span { - let mut output = array![]; - - // 0x048d4c831924c90963645d7473e0954d2ac37c1f20e201ed7c1778942df5d58d = - // PoseidonTrait::new() - // .update_with('StarkNet Message') - // .update_with('accept_ownership') - // .update_with(camel_dispatcher.contract_address) - // .update_with(ETH_PUBKEY().get_coordinates().unwrap_syscall()) - // .finalize(); - - // This signature was computed using ethers js sdk from the following values: - // - private_key: 0x45397ee6ca34cb49060f1c303c6cb7ee2d6123e617601ef3e31ccf7bf5bef1f9 - // - public_key: - // r: 0x829307f82a1883c2414503ba85fc85037f22c6fc6f80910801f6b01a4131da1e - // s: 0x2a23f7bddf3715d11767b1247eccc68c89e11b926e2615268db6ad1af8d8da96 - // - msg_hash: 0x048d4c831924c90963645d7473e0954d2ac37c1f20e201ed7c1778942df5d58d - EthSignature { - r: 0x7a0fa1e6bfc6a0b86cdbb9877551a108d42d3de50cb7a516e63fe5a26e5a9c52, - s: 0x3cc64ca8bf6963ae01125f0d932b8780ca0ed1612fb74a84d4f76593e6687b74, - } - .serialize(ref output); - - output.span() -} diff --git a/src/tests/account/ethereum/test_eth_account.cairo b/src/tests/account/ethereum/test_eth_account.cairo index 8c1a8e8d6..bb21bb6b9 100644 --- a/src/tests/account/ethereum/test_eth_account.cairo +++ b/src/tests/account/ethereum/test_eth_account.cairo @@ -1,7 +1,6 @@ use openzeppelin::account::EthAccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; use openzeppelin::account::EthAccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; use openzeppelin::account::EthAccountComponent; -use openzeppelin::account::interface::EthPublicKey; use openzeppelin::account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; use openzeppelin::account::interface::{ISRC6, ISRC6_ID}; use openzeppelin::account::utils::secp256k1::{ @@ -10,32 +9,27 @@ use openzeppelin::account::utils::secp256k1::{ use openzeppelin::account::utils::signature::EthSignature; use openzeppelin::introspection::interface::{ISRC5, ISRC5_ID}; use openzeppelin::tests::mocks::eth_account_mocks::DualCaseEthAccountMock; +use openzeppelin::tests::utils::constants::secp256k1::KEY_PAIR; use openzeppelin::tests::utils::constants::{ - ETH_PUBKEY, SALT, ZERO, OTHER, RECIPIENT, CALLER, QUERY_VERSION, MIN_TRANSACTION_VERSION + ETH_PUBKEY, NEW_ETH_PUBKEY, SALT, ZERO, OTHER, RECIPIENT, CALLER, QUERY_VERSION, + MIN_TRANSACTION_VERSION }; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; use openzeppelin::utils::selectors; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::{ + cheat_signature_global, cheat_transaction_version_global, cheat_transaction_hash_global, + start_cheat_caller_address +}; +use snforge_std::{spy_events, test_address}; +use starknet::ContractAddress; use starknet::account::Call; -use starknet::testing; -use starknet::{contract_address_const, ContractAddress}; - -use super::common::{assert_only_event_owner_added, assert_event_owner_removed}; -use super::common::{deploy_erc20, SIGNED_TX_DATA, NEW_ETH_PUBKEY, SignedTransactionData}; - - -// -// Constants -// - -fn CLASS_HASH() -> felt252 { - DualCaseEthAccountMock::TEST_CLASS_HASH -} -fn ACCOUNT_ADDRESS() -> ContractAddress { - contract_address_const::<0x111111>() -} +use super::common::EthAccountSpyHelpers; +use super::common::{ + deploy_erc20, SIGNED_TX_DATA, SignedTransactionData, get_accept_ownership_signature +}; // // Setup @@ -54,28 +48,31 @@ fn COMPONENT_STATE() -> ComponentState { fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(ETH_PUBKEY()); - utils::drop_event(ZERO()); state } -fn setup_dispatcher(data: Option<@SignedTransactionData>) -> EthAccountABIDispatcher { - testing::set_version(MIN_TRANSACTION_VERSION); - +fn setup_dispatcher(data: Option<@SignedTransactionData>) -> (EthAccountABIDispatcher, felt252) { let mut calldata = array![]; - if data.is_some() { - let data = data.unwrap(); + if let Option::Some(data) = data { let mut serialized_signature = array![]; data.signature.serialize(ref serialized_signature); - testing::set_signature(serialized_signature.span()); - testing::set_transaction_hash(*data.transaction_hash); + cheat_signature_global(serialized_signature.span()); + cheat_transaction_hash_global(*data.tx_hash); calldata.append_serde(*data.public_key); } else { calldata.append_serde(ETH_PUBKEY()); - } - let address = utils::deploy(CLASS_HASH(), calldata); - EthAccountABIDispatcher { contract_address: address } + }; + + let contract_class = utils::declare_class("DualCaseEthAccountMock"); + let address = utils::deploy(contract_class, calldata); + let dispatcher = EthAccountABIDispatcher { contract_address: address }; + + cheat_transaction_version_global(MIN_TRANSACTION_VERSION); + start_cheat_caller_address(address, ZERO()); + + (dispatcher, contract_class.class_hash.into()) } // @@ -85,8 +82,8 @@ fn setup_dispatcher(data: Option<@SignedTransactionData>) -> EthAccountABIDispat #[test] fn test_is_valid_signature() { let mut state = COMPONENT_STATE(); - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; + let data = SIGNED_TX_DATA(KEY_PAIR()); + let hash = data.tx_hash; let mut bad_signature = data.signature; bad_signature.r += 1; @@ -109,8 +106,8 @@ fn test_is_valid_signature() { #[test] fn test_isValidSignature() { let mut state = COMPONENT_STATE(); - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; + let data = SIGNED_TX_DATA(KEY_PAIR()); + let hash = data.tx_hash; let mut bad_signature = data.signature; @@ -137,93 +134,93 @@ fn test_isValidSignature() { #[test] fn test_validate_deploy() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); // `__validate_deploy__` does not directly use the passed arguments. Their // values are already integrated in the tx hash. The passed arguments in this // testing context are decoupled from the signature and have no effect on the test. - let is_valid = account.__validate_deploy__(CLASS_HASH(), SALT, ETH_PUBKEY()); + let is_valid = account.__validate_deploy__(class_hash, SALT, ETH_PUBKEY()); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('EthAccount: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: invalid signature',))] fn test_validate_deploy_invalid_signature_data() { - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher(Option::Some(@data)); + let mut data = SIGNED_TX_DATA(KEY_PAIR()); + data.tx_hash += 1; + let (account, class_hash) = setup_dispatcher(Option::Some(@data)); - account.__validate_deploy__(CLASS_HASH(), SALT, ETH_PUBKEY()); + account.__validate_deploy__(class_hash, SALT, ETH_PUBKEY()); } #[test] -#[should_panic(expected: ('Signature: Invalid format.', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Signature: Invalid format.',))] fn test_validate_deploy_invalid_signature_length() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); let signature = array![0x1]; - testing::set_signature(signature.span()); + cheat_signature_global(signature.span()); - account.__validate_deploy__(CLASS_HASH(), SALT, ETH_PUBKEY()); + account.__validate_deploy__(class_hash, SALT, ETH_PUBKEY()); } #[test] -#[should_panic(expected: ('Signature: Invalid format.', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Signature: Invalid format.',))] fn test_validate_deploy_empty_signature() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); let empty_sig = array![]; - testing::set_signature(empty_sig.span()); - account.__validate_deploy__(CLASS_HASH(), SALT, ETH_PUBKEY()); + cheat_signature_global(empty_sig.span()); + account.__validate_deploy__(class_hash, SALT, ETH_PUBKEY()); } #[test] fn test_validate_declare() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); // `__validate_declare__` does not directly use the class_hash argument. Its // value is already integrated in the tx hash. The class_hash argument in this // testing context is decoupled from the signature and has no effect on the test. - let is_valid = account.__validate_declare__(CLASS_HASH()); + let is_valid = account.__validate_declare__(class_hash); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('EthAccount: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: invalid signature',))] fn test_validate_declare_invalid_signature_data() { - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher(Option::Some(@data)); + let mut data = SIGNED_TX_DATA(KEY_PAIR()); + data.tx_hash += 1; + let (account, class_hash) = setup_dispatcher(Option::Some(@data)); - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } #[test] -#[should_panic(expected: ('Signature: Invalid format.', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Signature: Invalid format.',))] fn test_validate_declare_invalid_signature_length() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); let mut signature = array![]; signature.append(0x1); - testing::set_signature(signature.span()); + cheat_signature_global(signature.span()); - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } #[test] -#[should_panic(expected: ('Signature: Invalid format.', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Signature: Invalid format.',))] fn test_validate_declare_empty_signature() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); let empty_sig = array![]; - testing::set_signature(empty_sig.span()); + cheat_signature_global(empty_sig.span()); - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } fn test_execute_with_version(version: Option) { - let data = SIGNED_TX_DATA(); - let account = setup_dispatcher(Option::Some(@data)); + let data = SIGNED_TX_DATA(KEY_PAIR()); + let (account, _) = setup_dispatcher(Option::Some(@data)); let erc20 = deploy_erc20(account.contract_address, 1000); let recipient = RECIPIENT(); @@ -240,7 +237,7 @@ fn test_execute_with_version(version: Option) { // Handle version for test if version.is_some() { - testing::set_version(version.unwrap()); + cheat_transaction_version_global(version.unwrap()); } // Execute @@ -267,7 +264,7 @@ fn test_execute_query_version() { } #[test] -#[should_panic(expected: ('EthAccount: invalid tx version', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: invalid tx version',))] fn test_execute_invalid_version() { test_execute_with_version(Option::Some(MIN_TRANSACTION_VERSION - 1)); } @@ -275,26 +272,26 @@ fn test_execute_invalid_version() { #[test] fn test_validate() { let calls = array![]; - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let (account, _) = setup_dispatcher(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); let is_valid = account.__validate__(calls); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('EthAccount: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: invalid signature',))] fn test_validate_invalid() { let calls = array![]; - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher(Option::Some(@data)); + let mut data = SIGNED_TX_DATA(KEY_PAIR()); + data.tx_hash += 1; + let (account, _) = setup_dispatcher(Option::Some(@data)); account.__validate__(calls); } #[test] fn test_multicall() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let (account, _) = setup_dispatcher(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); let erc20 = deploy_erc20(account.contract_address, 1000); let recipient1 = RECIPIENT(); let recipient2 = OTHER(); @@ -339,7 +336,7 @@ fn test_multicall() { #[test] fn test_multicall_zero_calls() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let (account, _) = setup_dispatcher(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); let mut calls = array![]; let ret = account.__execute__(calls); @@ -354,9 +351,7 @@ fn test_account_called_from_contract() { let state = setup(); let calls = array![]; - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(CALLER()); - + start_cheat_caller_address(test_address(), CALLER()); state.__execute__(calls); } @@ -376,9 +371,7 @@ fn test_cannot_get_without_initialize() { fn test_cannot_set_without_initialize() { let mut state = COMPONENT_STATE(); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(ACCOUNT_ADDRESS()); - + start_cheat_caller_address(test_address(), test_address()); state.set_public_key(NEW_ETH_PUBKEY(), array![].span()); } @@ -386,36 +379,40 @@ fn test_cannot_set_without_initialize() { fn test_public_key_setter_and_getter() { let mut state = COMPONENT_STATE(); let public_key = ETH_PUBKEY(); - let new_public_key = NEW_ETH_PUBKEY(); - - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(ACCOUNT_ADDRESS()); + let key_pair = KEY_PAIR(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, contract_address); state.initializer(public_key); - utils::drop_event(ACCOUNT_ADDRESS()); // Check default let current = state.get_public_key(); assert_eq!(current, public_key); + let mut spy = spy_events(); + // Set key - state.set_public_key(new_public_key, get_accept_ownership_signature()); + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); + state.set_public_key(key_pair.public_key, signature); - assert_event_owner_removed(ACCOUNT_ADDRESS(), current); - assert_only_event_owner_added(ACCOUNT_ADDRESS(), new_public_key); + spy.assert_event_owner_removed(contract_address, current); + spy.assert_only_event_owner_added(contract_address, key_pair.public_key); let public_key = state.get_public_key(); - assert_eq!(public_key, new_public_key); + assert_eq!(public_key, key_pair.public_key); } #[test] #[should_panic(expected: ('EthAccount: unauthorized',))] fn test_public_key_setter_different_account() { let mut state = COMPONENT_STATE(); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(CALLER()); + let key_pair = KEY_PAIR(); + let contract_address = test_address(); + + start_cheat_caller_address(contract_address, CALLER()); - state.set_public_key(NEW_ETH_PUBKEY(), get_accept_ownership_signature()); + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); + state.set_public_key(key_pair.public_key, signature); } // @@ -426,34 +423,37 @@ fn test_public_key_setter_different_account() { fn test_public_key_setter_and_getter_camel() { let mut state = COMPONENT_STATE(); let public_key = ETH_PUBKEY(); - let new_public_key = NEW_ETH_PUBKEY(); - - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(ACCOUNT_ADDRESS()); + let key_pair = KEY_PAIR(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, contract_address); state.initializer(public_key); - utils::drop_event(ACCOUNT_ADDRESS()); let current = state.getPublicKey(); assert_eq!(current, public_key); - state.setPublicKey(new_public_key, get_accept_ownership_signature()); + let mut spy = spy_events(); + + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); + state.setPublicKey(key_pair.public_key, signature); - assert_event_owner_removed(ACCOUNT_ADDRESS(), public_key); - assert_only_event_owner_added(ACCOUNT_ADDRESS(), new_public_key); + spy.assert_event_owner_removed(contract_address, public_key); + spy.assert_only_event_owner_added(contract_address, key_pair.public_key); let public_key = state.getPublicKey(); - assert_eq!(public_key, new_public_key); + assert_eq!(public_key, key_pair.public_key); } #[test] #[should_panic(expected: ('EthAccount: unauthorized',))] fn test_public_key_setter_different_account_camel() { let mut state = COMPONENT_STATE(); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(CALLER()); + let key_pair = KEY_PAIR(); - state.setPublicKey(NEW_ETH_PUBKEY(), get_accept_ownership_signature()); + start_cheat_caller_address(test_address(), CALLER()); + + let signature = get_accept_ownership_signature(test_address(), ETH_PUBKEY(), key_pair); + state.setPublicKey(key_pair.public_key, signature); } // @@ -465,10 +465,11 @@ fn test_initializer() { let mut state = COMPONENT_STATE(); let mock_state = CONTRACT_STATE(); let public_key = ETH_PUBKEY(); + let mut spy = spy_events(); state.initializer(public_key); - assert_only_event_owner_added(ZERO(), public_key); + spy.assert_only_event_owner_added(test_address(), public_key); assert_eq!(state.get_public_key(), public_key); @@ -483,8 +484,7 @@ fn test_initializer() { fn test_assert_only_self_true() { let mut state = COMPONENT_STATE(); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(ACCOUNT_ADDRESS()); + start_cheat_caller_address(test_address(), test_address()); state.assert_only_self(); } @@ -493,17 +493,19 @@ fn test_assert_only_self_true() { fn test_assert_only_self_false() { let mut state = COMPONENT_STATE(); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.assert_only_self(); } #[test] fn test_assert_valid_new_owner() { let mut state = setup(); + let contract_address = test_address(); + + let key_pair = KEY_PAIR(); + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); - testing::set_contract_address(ACCOUNT_ADDRESS()); - state.assert_valid_new_owner(ETH_PUBKEY(), NEW_ETH_PUBKEY(), get_accept_ownership_signature()); + state.assert_valid_new_owner(ETH_PUBKEY(), key_pair.public_key, signature); } #[test] @@ -511,7 +513,7 @@ fn test_assert_valid_new_owner() { fn test_assert_valid_new_owner_invalid_signature() { let mut state = setup(); - testing::set_contract_address(ACCOUNT_ADDRESS()); + start_cheat_caller_address(test_address(), test_address()); let mut bad_signature = array![]; EthSignature { r: 0xe2c02fbaa03809019ce6501cb5e57fc4a1e96e09dd8becfde8508ceddb53330b, @@ -524,8 +526,8 @@ fn test_assert_valid_new_owner_invalid_signature() { #[test] fn test__is_valid_signature() { let mut state = COMPONENT_STATE(); - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; + let data = SIGNED_TX_DATA(KEY_PAIR()); + let hash = data.tx_hash; let mut bad_signature = data.signature; @@ -550,40 +552,12 @@ fn test__is_valid_signature() { fn test__set_public_key() { let mut state = COMPONENT_STATE(); let public_key = ETH_PUBKEY(); + let mut spy = spy_events(); + state._set_public_key(public_key); - assert_only_event_owner_added(ZERO(), public_key); + spy.assert_only_event_owner_added(test_address(), public_key); let public_key = state.get_public_key(); assert_eq!(public_key, ETH_PUBKEY()); } - -// -// Helpers -// - -fn get_accept_ownership_signature() -> Span { - let mut output = array![]; - - // 0x5b23679494e4634c66808d93eeef8301f5fd806b095e5e98b45ee97432a0d8d = - // PoseidonTrait::new() - // .update_with('StarkNet Message') - // .update_with('accept_ownership') - // .update_with(ACCOUNT_ADDRESS()) - // .update_with(ETH_PUBKEY().get_coordinates().unwrap_syscall()) - // .finalize(); - - // This signature was computed using ethers js sdk from the following values: - // - private_key: 0x45397ee6ca34cb49060f1c303c6cb7ee2d6123e617601ef3e31ccf7bf5bef1f9 - // - public_key: - // r: 0x829307f82a1883c2414503ba85fc85037f22c6fc6f80910801f6b01a4131da1e - // s: 0x2a23f7bddf3715d11767b1247eccc68c89e11b926e2615268db6ad1af8d8da96 - // - msg_hash: 0x5b23679494e4634c66808d93eeef8301f5fd806b095e5e98b45ee97432a0d8d - EthSignature { - r: 0x161de897c0232716792d7b580a577212a6573dbb60c0d0449fa673b95b22d942, - s: 0x7c7b279857889e20fb4c002fd2d1c112c9f30fa4c411f7cb32f55ab0af991a73, - } - .serialize(ref output); - - output.span() -} diff --git a/src/tests/account/starknet.cairo b/src/tests/account/starknet.cairo index e67636b10..f426692e3 100644 --- a/src/tests/account/starknet.cairo +++ b/src/tests/account/starknet.cairo @@ -1,4 +1,5 @@ pub(crate) mod common; +// mod test_account; +// mod test_dual_account; + -mod test_account; -mod test_dual_account; diff --git a/src/tests/account/starknet/common.cairo b/src/tests/account/starknet/common.cairo index 91905d856..f029dff0a 100644 --- a/src/tests/account/starknet/common.cairo +++ b/src/tests/account/starknet/common.cairo @@ -1,17 +1,18 @@ use openzeppelin::account::AccountComponent::{OwnerAdded, OwnerRemoved}; use openzeppelin::account::AccountComponent; -use openzeppelin::tests::mocks::erc20_mocks::DualCaseERC20Mock; use openzeppelin::tests::utils::constants::{NAME, SYMBOL, NEW_PUBKEY}; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::EventSpy; use starknet::ContractAddress; #[derive(Drop)] pub(crate) struct SignedTransactionData { pub(crate) private_key: felt252, pub(crate) public_key: felt252, - pub(crate) transaction_hash: felt252, + pub(crate) tx_hash: felt252, pub(crate) r: felt252, pub(crate) s: felt252 } @@ -20,7 +21,7 @@ pub(crate) fn SIGNED_TX_DATA() -> SignedTransactionData { SignedTransactionData { private_key: 1234, public_key: NEW_PUBKEY, - transaction_hash: 0x601d3d2e265c10ff645e1554c435e72ce6721f0ba5fc96f0c650bfc6231191a, + tx_hash: 0x601d3d2e265c10ff645e1554c435e72ce6721f0ba5fc96f0c650bfc6231191a, r: 0x6bc22689efcaeacb9459577138aff9f0af5b77ee7894cdc8efabaf760f6cf6e, s: 0x295989881583b9325436851934334faa9d639a2094cd1e2f8691c8a71cd4cdf } @@ -34,36 +35,31 @@ pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> calldata.append_serde(initial_supply); calldata.append_serde(recipient); - let address = utils::deploy(DualCaseERC20Mock::TEST_CLASS_HASH, calldata); + let address = utils::declare_and_deploy("DualCaseERC20Mock", calldata); IERC20Dispatcher { contract_address: address } } -pub(crate) fn assert_event_owner_removed(contract: ContractAddress, removed_owner_guid: felt252) { - let event = utils::pop_log::(contract).unwrap(); - let expected = AccountComponent::Event::OwnerRemoved(OwnerRemoved { removed_owner_guid }); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("OwnerRemoved")); - indexed_keys.append_serde(removed_owner_guid); - utils::assert_indexed_keys(event, indexed_keys.span()); -} - -pub(crate) fn assert_event_owner_added(contract: ContractAddress, new_owner_guid: felt252) { - let event = utils::pop_log::(contract).unwrap(); - let expected = AccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); - assert!(event == expected); +#[generate_trait] +pub(crate) impl AccountSpyHelpersImpl of AccountSpyHelpers { + fn assert_event_owner_removed( + ref self: EventSpy, contract: ContractAddress, removed_owner_guid: felt252 + ) { + let expected = AccountComponent::Event::OwnerRemoved(OwnerRemoved { removed_owner_guid }); + self.assert_emitted_single(contract, expected); + } - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("OwnerAdded")); - indexed_keys.append_serde(new_owner_guid); - utils::assert_indexed_keys(event, indexed_keys.span()); -} + fn assert_event_owner_added( + ref self: EventSpy, contract: ContractAddress, new_owner_guid: felt252 + ) { + let expected = AccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); + self.assert_emitted_single(contract, expected); + } -pub(crate) fn assert_only_event_owner_added(contract: ContractAddress, new_owner_guid: felt252) { - assert_event_owner_added(contract, new_owner_guid); - utils::assert_no_events_left(contract); + fn assert_only_event_owner_added( + ref self: EventSpy, contract: ContractAddress, new_owner_guid: felt252 + ) { + self.assert_event_owner_added(contract, new_owner_guid); + self.assert_no_events_left_from(contract); + } } diff --git a/src/tests/account/test_secp256k1.cairo b/src/tests/account/test_secp256k1.cairo index 5466eee55..b41160a3d 100644 --- a/src/tests/account/test_secp256k1.cairo +++ b/src/tests/account/test_secp256k1.cairo @@ -6,8 +6,6 @@ use starknet::SyscallResultTrait; use starknet::secp256_trait::{Secp256Trait, Secp256PointTrait}; use starknet::secp256k1::Secp256k1Point; -use super::ethereum::common::get_points; - #[test] fn test_pack_big_secp256k1_points() { let (big_point_1, big_point_2) = get_points(); @@ -121,3 +119,19 @@ fn test_partial_eq() { assert!(big_point_1 != big_point_2); assert!(big_point_2 != big_point_1); } + +// +// Helpers +// + +fn get_points() -> (Secp256k1Point, Secp256k1Point) { + let curve_size = Secp256Trait::::get_curve_size(); + let point_1 = Secp256Trait::secp256_ec_get_point_from_x_syscall(curve_size, true) + .unwrap_syscall() + .unwrap(); + let point_2 = Secp256Trait::secp256_ec_get_point_from_x_syscall(curve_size, false) + .unwrap_syscall() + .unwrap(); + + (point_1, point_2) +} diff --git a/src/tests/account/test_signature.cairo b/src/tests/account/test_signature.cairo index ffdb2ce74..7da6fe741 100644 --- a/src/tests/account/test_signature.cairo +++ b/src/tests/account/test_signature.cairo @@ -1,4 +1,5 @@ use openzeppelin::account::utils::signature::{is_valid_stark_signature, is_valid_eth_signature}; +use openzeppelin::tests::utils::constants::secp256k1::KEY_PAIR; use starknet::secp256_trait::Secp256Trait; use starknet::secp256k1::Secp256k1Point; @@ -12,7 +13,7 @@ use super::starknet::common::SIGNED_TX_DATA as stark_signature_data; #[test] fn test_is_valid_stark_signature_good_sig() { let data = stark_signature_data(); - let hash = data.transaction_hash; + let hash = data.tx_hash; let mut good_signature = array![data.r, data.s].span(); @@ -23,7 +24,7 @@ fn test_is_valid_stark_signature_good_sig() { #[test] fn test_is_valid_stark_signature_bad_sig() { let data = stark_signature_data(); - let hash = data.transaction_hash; + let hash = data.tx_hash; let mut bad_signature = array![0x987, 0x564].span(); @@ -34,7 +35,7 @@ fn test_is_valid_stark_signature_bad_sig() { #[test] fn test_is_valid_stark_signature_invalid_len_sig() { let data = stark_signature_data(); - let hash = data.transaction_hash; + let hash = data.tx_hash; let mut bad_signature = array![0x987].span(); @@ -48,8 +49,8 @@ fn test_is_valid_stark_signature_invalid_len_sig() { #[test] fn test_is_valid_eth_signature_good_sig() { - let data = eth_signature_data(); - let hash = data.transaction_hash; + let data = eth_signature_data(KEY_PAIR()); + let hash = data.tx_hash; let mut serialized_good_signature = array![]; @@ -61,8 +62,8 @@ fn test_is_valid_eth_signature_good_sig() { #[test] fn test_is_valid_eth_signature_bad_sig() { - let data = eth_signature_data(); - let hash = data.transaction_hash; + let data = eth_signature_data(KEY_PAIR()); + let hash = data.tx_hash; let mut bad_signature = data.signature; bad_signature.r += 1; @@ -80,8 +81,8 @@ fn test_is_valid_eth_signature_bad_sig() { #[test] #[should_panic(expected: ('Signature: Invalid format.',))] fn test_is_valid_eth_signature_invalid_format_sig() { - let data = eth_signature_data(); - let hash = data.transaction_hash; + let data = eth_signature_data(KEY_PAIR()); + let hash = data.tx_hash; let mut serialized_bad_signature = array![0x1]; @@ -90,8 +91,8 @@ fn test_is_valid_eth_signature_invalid_format_sig() { #[test] fn test_signature_r_out_of_range() { - let data = eth_signature_data(); - let hash = data.transaction_hash; + let data = eth_signature_data(KEY_PAIR()); + let hash = data.tx_hash; let mut bad_signature = data.signature; let curve_size = Secp256Trait::::get_curve_size(); @@ -110,8 +111,8 @@ fn test_signature_r_out_of_range() { #[test] fn test_signature_s_out_of_range() { - let data = eth_signature_data(); - let hash = data.transaction_hash; + let data = eth_signature_data(KEY_PAIR()); + let hash = data.tx_hash; let mut bad_signature = data.signature; let curve_size = Secp256Trait::::get_curve_size(); diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo index 509c33ee1..597fa9659 100644 --- a/src/tests/utils.cairo +++ b/src/tests/utils.cairo @@ -1,8 +1,8 @@ -pub(crate) mod common; +pub mod common; pub(crate) mod constants; -pub(crate) mod deployment; -pub(crate) mod events; -pub(crate) mod signing; +pub mod deployment; +pub mod events; +pub mod signing; pub use common::{ panic_data_to_byte_array, to_base_16_string, IntoBase16StringTrait, diff --git a/src/tests/utils/constants.cairo b/src/tests/utils/constants.cairo index c84190c20..2af608bae 100644 --- a/src/tests/utils/constants.cairo +++ b/src/tests/utils/constants.cairo @@ -25,6 +25,7 @@ pub(crate) const SALT: felt252 = 'SALT'; pub(crate) const SUCCESS: felt252 = 123123; pub(crate) const FAILURE: felt252 = 456456; pub(crate) const MIN_TRANSACTION_VERSION: felt252 = 1; +pub(crate) const TRANSACTION_HASH: felt252 = 'TRANSACTION_HASH'; // 2**128 pub(crate) const QUERY_OFFSET: felt252 = 0x100000000000000000000000000000000; // QUERY_OFFSET + MIN_TRANSACTION_VERSION @@ -115,3 +116,22 @@ pub(crate) fn DATA(success: bool) -> Span { pub(crate) fn EMPTY_DATA() -> Span { array![].span() } + +// +// Signing keys +// + +pub(crate) mod secp256k1 { + use openzeppelin::tests::utils::signing::{Secp256k1KeyPair, get_secp256k1_keys_from}; + + pub(crate) const PRIVATE_KEY: u256 = u256 { low: 'PRIVATE_LOW', high: 'PRIVATE_HIGH' }; + pub(crate) fn KEY_PAIR() -> Secp256k1KeyPair { + get_secp256k1_keys_from(PRIVATE_KEY) + } + + pub(crate) const PRIVATE_KEY_2: u256 = u256 { low: 'PRIVATE_LOW_2', high: 'PRIVATE_HIGH_2' }; + pub(crate) fn KEY_PAIR_2() -> Secp256k1KeyPair { + get_secp256k1_keys_from(PRIVATE_KEY_2) + } +} + diff --git a/src/tests/utils/signing.cairo b/src/tests/utils/signing.cairo index 90be99ed5..ee596c8d0 100644 --- a/src/tests/utils/signing.cairo +++ b/src/tests/utils/signing.cairo @@ -1,11 +1,23 @@ +use snforge_std::signature::secp256k1_curve::{Secp256k1CurveSignerImpl, Secp256k1CurveKeyPairImpl}; use snforge_std::signature::stark_curve::{StarkCurveSignerImpl, StarkCurveKeyPairImpl}; use snforge_std::signature::{KeyPair, KeyPairTrait}; +use starknet::secp256k1::Secp256k1Point; pub type StarkKeyPair = KeyPair; +pub type Secp256k1KeyPair = KeyPair; -pub fn KEY_PAIR() -> StarkKeyPair { - KeyPairTrait::from_secret_key('SECRET_KEY') +pub fn get_stark_keys_from(private_key: felt252) -> StarkKeyPair { + StarkCurveKeyPairImpl::from_secret_key(private_key) } -pub fn KEY_PAIR_2() -> StarkKeyPair { - KeyPairTrait::from_secret_key('SECRET_KEY_2') + +pub fn get_secp256k1_keys_from(private_key: u256) -> Secp256k1KeyPair { + Secp256k1CurveKeyPairImpl::from_secret_key(private_key) +} + +#[generate_trait] +pub impl Secp256k1KeyPairExt of Secp256k1KeyPairExtTrait { + fn serialized_sign(self: Secp256k1KeyPair, msg: u256) -> Array { + let (r, s) = self.sign(msg).unwrap(); + array![r.low.into(), r.high.into(), s.low.into(), s.high.into()] + } } From 9e091d4dcf72c687848e9454bfbc765079f259fb Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Tue, 23 Jul 2024 23:36:27 +0200 Subject: [PATCH 17/45] Migrate eth account preset tests (#1060) * feat: update dual_eth_account tests * feat: update eth_account tests * refactor: remove unused helpers * feat: update eth account preset tests * Update src/tests/account/ethereum/test_eth_account.cairo Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com> * Update src/tests/presets/test_eth_account.cairo Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com> * feat: apply review updates --------- Co-authored-by: immrsd <103599616+immrsd@users.noreply.github.com> --- .../account/ethereum/test_eth_account.cairo | 10 +- src/tests/presets.cairo | 2 +- src/tests/presets/test_eth_account.cairo | 291 +++++++++--------- src/tests/utils/constants.cairo | 1 - 4 files changed, 160 insertions(+), 144 deletions(-) diff --git a/src/tests/account/ethereum/test_eth_account.cairo b/src/tests/account/ethereum/test_eth_account.cairo index bb21bb6b9..a239de7f6 100644 --- a/src/tests/account/ethereum/test_eth_account.cairo +++ b/src/tests/account/ethereum/test_eth_account.cairo @@ -1,3 +1,4 @@ +use core::starknet::SyscallResultTrait; use openzeppelin::account::EthAccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; use openzeppelin::account::EthAccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; use openzeppelin::account::EthAccountComponent; @@ -236,8 +237,8 @@ fn test_execute_with_version(version: Option) { calls.append(call); // Handle version for test - if version.is_some() { - cheat_transaction_version_global(version.unwrap()); + if let Option::Some(version) = version { + cheat_transaction_version_global(version); } // Execute @@ -449,10 +450,11 @@ fn test_public_key_setter_and_getter_camel() { fn test_public_key_setter_different_account_camel() { let mut state = COMPONENT_STATE(); let key_pair = KEY_PAIR(); + let contract_address = test_address(); - start_cheat_caller_address(test_address(), CALLER()); + start_cheat_caller_address(contract_address, CALLER()); - let signature = get_accept_ownership_signature(test_address(), ETH_PUBKEY(), key_pair); + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); state.setPublicKey(key_pair.public_key, signature); } diff --git a/src/tests/presets.cairo b/src/tests/presets.cairo index cc599a931..5edfe8b18 100644 --- a/src/tests/presets.cairo +++ b/src/tests/presets.cairo @@ -2,5 +2,5 @@ mod test_erc1155; mod test_erc20; mod test_erc721; -// mod test_eth_account; +mod test_eth_account; mod test_universal_deployer; diff --git a/src/tests/presets/test_eth_account.cairo b/src/tests/presets/test_eth_account.cairo index b8510958a..81ea869ea 100644 --- a/src/tests/presets/test_eth_account.cairo +++ b/src/tests/presets/test_eth_account.cairo @@ -3,38 +3,42 @@ use openzeppelin::account::interface::ISRC6_ID; use openzeppelin::account::utils::secp256k1::{ DebugSecp256k1Point, Secp256k1PointSerde, Secp256k1PointPartialEq }; -use openzeppelin::account::utils::signature::EthSignature; use openzeppelin::introspection::interface::ISRC5_ID; use openzeppelin::presets::EthAccountUpgradeable; +use openzeppelin::presets::interfaces::eth_account::{ + EthAccountUpgradeableABISafeDispatcher, EthAccountUpgradeableABISafeDispatcherTrait +}; use openzeppelin::presets::interfaces::{ EthAccountUpgradeableABIDispatcher, EthAccountUpgradeableABIDispatcherTrait }; +use openzeppelin::tests::account::ethereum::common::EthAccountSpyHelpers; use openzeppelin::tests::account::ethereum::common::{ - assert_only_event_owner_added, assert_event_owner_removed -}; -use openzeppelin::tests::account::ethereum::common::{ - deploy_erc20, get_points, NEW_ETH_PUBKEY, SIGNED_TX_DATA, SignedTransactionData + deploy_erc20, SIGNED_TX_DATA, SignedTransactionData, get_accept_ownership_signature }; -use openzeppelin::tests::mocks::eth_account_mocks::SnakeEthAccountMock; -use openzeppelin::tests::upgrades::common::assert_only_event_upgraded; +use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; +use openzeppelin::tests::utils::constants::secp256k1::KEY_PAIR; use openzeppelin::tests::utils::constants::{ - CLASS_HASH_ZERO, ETH_PUBKEY, SALT, ZERO, RECIPIENT, QUERY_VERSION, MIN_TRANSACTION_VERSION + CLASS_HASH_ZERO, ETH_PUBKEY, NEW_ETH_PUBKEY, SALT, ZERO, RECIPIENT, QUERY_VERSION, + MIN_TRANSACTION_VERSION }; use openzeppelin::tests::utils; use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; use openzeppelin::utils::selectors; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::{ + cheat_signature_global, cheat_transaction_version_global, cheat_transaction_hash_global, + start_cheat_caller_address +}; +use snforge_std::{spy_events, test_address}; +use starknet::ClassHash; +use starknet::SyscallResultTrait; use starknet::account::Call; use starknet::contract_address_const; -use starknet::testing; -use starknet::{ContractAddress, ClassHash}; - -fn CLASS_HASH() -> felt252 { - EthAccountUpgradeable::TEST_CLASS_HASH -} +use starknet::secp256_trait::Secp256Trait; +use starknet::secp256k1::Secp256k1Point; -fn V2_CLASS_HASH() -> ClassHash { - SnakeEthAccountMock::TEST_CLASS_HASH.try_into().unwrap() +fn declare_v2_class_hash() -> ClassHash { + utils::declare_class("SnakeEthAccountMock").class_hash } // @@ -45,32 +49,33 @@ fn setup_dispatcher() -> EthAccountUpgradeableABIDispatcher { let mut calldata = array![]; calldata.append_serde(ETH_PUBKEY()); - let target = utils::deploy(CLASS_HASH(), calldata); - utils::drop_event(target); - + let target = utils::declare_and_deploy("EthAccountUpgradeable", calldata); EthAccountUpgradeableABIDispatcher { contract_address: target } } fn setup_dispatcher_with_data( data: Option<@SignedTransactionData> -) -> EthAccountUpgradeableABIDispatcher { - testing::set_version(MIN_TRANSACTION_VERSION); - +) -> (EthAccountUpgradeableABIDispatcher, felt252) { let mut calldata = array![]; - if data.is_some() { - let data = data.unwrap(); + if let Option::Some(data) = data { let mut serialized_signature = array![]; data.signature.serialize(ref serialized_signature); - testing::set_signature(serialized_signature.span()); - testing::set_transaction_hash(*data.transaction_hash); + cheat_signature_global(serialized_signature.span()); + cheat_transaction_hash_global(*data.tx_hash); calldata.append_serde(*data.public_key); } else { calldata.append_serde(ETH_PUBKEY()); } - let address = utils::deploy(CLASS_HASH(), calldata); - EthAccountUpgradeableABIDispatcher { contract_address: address } + let contract_class = utils::declare_class("EthAccountUpgradeable"); + let address = utils::deploy(contract_class, calldata); + let dispatcher = EthAccountUpgradeableABIDispatcher { contract_address: address }; + + cheat_transaction_version_global(MIN_TRANSACTION_VERSION); + start_cheat_caller_address(address, ZERO()); + + (dispatcher, contract_class.class_hash.into()) } // @@ -80,19 +85,18 @@ fn setup_dispatcher_with_data( #[test] fn test_constructor() { let mut state = EthAccountUpgradeable::contract_state_for_testing(); + let mut spy = spy_events(); EthAccountUpgradeable::constructor(ref state, ETH_PUBKEY()); - assert_only_event_owner_added(ZERO(), ETH_PUBKEY()); + spy.assert_only_event_owner_added(test_address(), ETH_PUBKEY()); let public_key = EthAccountUpgradeable::EthAccountMixinImpl::get_public_key(@state); assert_eq!(public_key, ETH_PUBKEY()); - let supports_isrc5 = EthAccountUpgradeable::EthAccountMixinImpl::supports_interface( @state, ISRC5_ID ); assert!(supports_isrc5); - let supports_isrc6 = EthAccountUpgradeable::EthAccountMixinImpl::supports_interface( @state, ISRC6_ID ); @@ -104,42 +108,48 @@ fn test_constructor() { // #[test] -fn test_public_key_setter_and_getter_2() { +fn test_public_key_setter_and_getter() { let dispatcher = setup_dispatcher(); - let new_public_key = NEW_ETH_PUBKEY(); + let key_pair = KEY_PAIR(); + let contract_address = dispatcher.contract_address; + let mut spy = spy_events(); - testing::set_contract_address(dispatcher.contract_address); + start_cheat_caller_address(contract_address, contract_address); - dispatcher.set_public_key(new_public_key, get_accept_ownership_signature()); - assert_eq!(dispatcher.get_public_key(), new_public_key); + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); + dispatcher.set_public_key(key_pair.public_key, signature); + assert_eq!(dispatcher.get_public_key(), key_pair.public_key); - assert_event_owner_removed(dispatcher.contract_address, ETH_PUBKEY()); - assert_only_event_owner_added(dispatcher.contract_address, new_public_key); + spy.assert_event_owner_removed(contract_address, ETH_PUBKEY()); + spy.assert_only_event_owner_added(contract_address, key_pair.public_key); } #[test] fn test_public_key_setter_and_getter_camel() { let dispatcher = setup_dispatcher(); - let new_public_key = NEW_ETH_PUBKEY(); + let key_pair = KEY_PAIR(); + let contract_address = dispatcher.contract_address; + let mut spy = spy_events(); - testing::set_contract_address(dispatcher.contract_address); + start_cheat_caller_address(contract_address, contract_address); - dispatcher.setPublicKey(new_public_key, get_accept_ownership_signature()); - assert_eq!(dispatcher.getPublicKey(), new_public_key); + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); + dispatcher.setPublicKey(key_pair.public_key, signature); + assert_eq!(dispatcher.getPublicKey(), key_pair.public_key); - assert_event_owner_removed(dispatcher.contract_address, ETH_PUBKEY()); - assert_only_event_owner_added(dispatcher.contract_address, new_public_key); + spy.assert_event_owner_removed(contract_address, ETH_PUBKEY()); + spy.assert_only_event_owner_added(contract_address, key_pair.public_key); } #[test] -#[should_panic(expected: ('EthAccount: unauthorized', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: unauthorized',))] fn test_set_public_key_different_account() { let dispatcher = setup_dispatcher(); dispatcher.set_public_key(NEW_ETH_PUBKEY(), array![].span()); } #[test] -#[should_panic(expected: ('EthAccount: unauthorized', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: unauthorized',))] fn test_setPublicKey_different_account() { let dispatcher = setup_dispatcher(); dispatcher.setPublicKey(NEW_ETH_PUBKEY(), array![].span()); @@ -151,14 +161,18 @@ fn test_setPublicKey_different_account() { fn is_valid_sig_dispatcher() -> (EthAccountUpgradeableABIDispatcher, felt252, Array) { let dispatcher = setup_dispatcher(); + let key_pair = KEY_PAIR(); + let contract_address = dispatcher.contract_address; + let data = SIGNED_TX_DATA(key_pair); + let hash = data.tx_hash; - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; let mut serialized_signature = array![]; data.signature.serialize(ref serialized_signature); - testing::set_contract_address(dispatcher.contract_address); - dispatcher.set_public_key(data.public_key, get_accept_ownership_signature()); + start_cheat_caller_address(contract_address, contract_address); + + let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); + dispatcher.set_public_key(data.public_key, signature); (dispatcher, hash, serialized_signature) } @@ -217,92 +231,104 @@ fn test_supports_interface() { #[test] fn test_validate_deploy() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher_with_data( + Option::Some(@SIGNED_TX_DATA(KEY_PAIR())) + ); // `__validate_deploy__` does not directly use the passed arguments. Their // values are already integrated in the tx hash. The passed arguments in this // testing context are decoupled from the signature and have no effect on the test. - let is_valid = account.__validate_deploy__(CLASS_HASH(), SALT, ETH_PUBKEY()); + let is_valid = account.__validate_deploy__(class_hash, SALT, ETH_PUBKEY()); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('EthAccount: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: invalid signature',))] fn test_validate_deploy_invalid_signature_data() { - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher_with_data(Option::Some(@data)); + let mut data = SIGNED_TX_DATA(KEY_PAIR()); + data.tx_hash += 1; + let (account, class_hash) = setup_dispatcher_with_data(Option::Some(@data)); - account.__validate_deploy__(CLASS_HASH(), SALT, ETH_PUBKEY()); + account.__validate_deploy__(class_hash, SALT, ETH_PUBKEY()); } #[test] -#[should_panic(expected: ('Signature: Invalid format.', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Signature: Invalid format.',))] fn test_validate_deploy_invalid_signature_length() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher_with_data( + Option::Some(@SIGNED_TX_DATA(KEY_PAIR())) + ); let mut signature = array![0x1]; - testing::set_signature(signature.span()); + cheat_signature_global(signature.span()); - account.__validate_deploy__(CLASS_HASH(), SALT, ETH_PUBKEY()); + account.__validate_deploy__(class_hash, SALT, ETH_PUBKEY()); } #[test] -#[should_panic(expected: ('Signature: Invalid format.', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Signature: Invalid format.',))] fn test_validate_deploy_empty_signature() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher_with_data( + Option::Some(@SIGNED_TX_DATA(KEY_PAIR())) + ); let empty_sig = array![]; - testing::set_signature(empty_sig.span()); - account.__validate_deploy__(CLASS_HASH(), SALT, ETH_PUBKEY()); + cheat_signature_global(empty_sig.span()); + account.__validate_deploy__(class_hash, SALT, ETH_PUBKEY()); } #[test] fn test_validate_declare() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher_with_data( + Option::Some(@SIGNED_TX_DATA(KEY_PAIR())) + ); // `__validate_declare__` does not directly use the class_hash argument. Its // value is already integrated in the tx hash. The class_hash argument in this // testing context is decoupled from the signature and has no effect on the test. - let is_valid = account.__validate_declare__(CLASS_HASH()); + let is_valid = account.__validate_declare__(class_hash); assert_eq!(is_valid, starknet::VALIDATED,); } #[test] -#[should_panic(expected: ('EthAccount: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: invalid signature',))] fn test_validate_declare_invalid_signature_data() { - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher_with_data(Option::Some(@data)); + let mut data = SIGNED_TX_DATA(KEY_PAIR()); + data.tx_hash += 1; + let (account, class_hash) = setup_dispatcher_with_data(Option::Some(@data)); - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } #[test] -#[should_panic(expected: ('Signature: Invalid format.', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Signature: Invalid format.',))] fn test_validate_declare_invalid_signature_length() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher_with_data( + Option::Some(@SIGNED_TX_DATA(KEY_PAIR())) + ); let mut signature = array![0x1]; - testing::set_signature(signature.span()); + cheat_signature_global(signature.span()); - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } #[test] -#[should_panic(expected: ('Signature: Invalid format.', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Signature: Invalid format.',))] fn test_validate_declare_empty_signature() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let (account, class_hash) = setup_dispatcher_with_data( + Option::Some(@SIGNED_TX_DATA(KEY_PAIR())) + ); let empty_sig = array![]; - testing::set_signature(empty_sig.span()); + cheat_signature_global(empty_sig.span()); - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } fn test_execute_with_version(version: Option) { - let data = SIGNED_TX_DATA(); - let account = setup_dispatcher_with_data(Option::Some(@data)); + let data = SIGNED_TX_DATA(KEY_PAIR()); + let (account, _) = setup_dispatcher_with_data(Option::Some(@data)); let erc20 = deploy_erc20(account.contract_address, 1000); let amount: u256 = 200; @@ -317,8 +343,8 @@ fn test_execute_with_version(version: Option) { let mut calls = array![]; calls.append(call); - if version.is_some() { - testing::set_version(version.unwrap()); + if let Option::Some(version) = version { + cheat_transaction_version_global(version); } let ret = account.__execute__(calls); @@ -342,7 +368,7 @@ fn test_execute_query_version() { } #[test] -#[should_panic(expected: ('EthAccount: invalid tx version', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: invalid tx version',))] fn test_execute_invalid_version() { test_execute_with_version(Option::Some(MIN_TRANSACTION_VERSION - 1)); } @@ -350,26 +376,26 @@ fn test_execute_invalid_version() { #[test] fn test_validate() { let calls = array![]; - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let (account, _) = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); let is_valid = account.__validate__(calls); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('EthAccount: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: invalid signature',))] fn test_validate_invalid() { let calls = array![]; - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher_with_data(Option::Some(@data)); + let mut data = SIGNED_TX_DATA(KEY_PAIR()); + data.tx_hash += 1; + let (account, _) = setup_dispatcher_with_data(Option::Some(@data)); account.__validate__(calls); } #[test] fn test_multicall() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let (account, _) = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); let erc20 = deploy_erc20(account.contract_address, 1000); let recipient1 = contract_address_const::<0x123>(); let recipient2 = contract_address_const::<0x456>(); @@ -409,7 +435,7 @@ fn test_multicall() { #[test] fn test_multicall_zero_calls() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let (account, _) = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA(KEY_PAIR()))); let mut calls = array![]; let ret = account.__execute__(calls); @@ -418,14 +444,13 @@ fn test_multicall_zero_calls() { } #[test] -#[should_panic(expected: ('EthAccount: invalid caller', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('EthAccount: invalid caller',))] fn test_account_called_from_contract() { let account = setup_dispatcher(); let calls = array![]; let caller = contract_address_const::<0x123>(); - testing::set_contract_address(account.contract_address); - testing::set_caller_address(caller); + start_cheat_caller_address(account.contract_address, caller); account.__execute__(calls); } @@ -435,57 +460,66 @@ fn test_account_called_from_contract() { // #[test] -#[should_panic(expected: ('EthAccount: unauthorized', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('EthAccount: unauthorized',))] fn test_upgrade_access_control() { let v1 = setup_dispatcher(); v1.upgrade(CLASS_HASH_ZERO()); } #[test] -#[should_panic(expected: ('Class hash cannot be zero', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Class hash cannot be zero',))] fn test_upgrade_with_class_hash_zero() { let v1 = setup_dispatcher(); - set_contract_and_caller(v1.contract_address); + start_cheat_caller_address(v1.contract_address, v1.contract_address); v1.upgrade(CLASS_HASH_ZERO()); } #[test] fn test_upgraded_event() { let v1 = setup_dispatcher(); - let v2_class_hash = V2_CLASS_HASH(); + let v2_class_hash = declare_v2_class_hash(); + let mut spy = spy_events(); - set_contract_and_caller(v1.contract_address); + start_cheat_caller_address(v1.contract_address, v1.contract_address); v1.upgrade(v2_class_hash); - assert_only_event_upgraded(v1.contract_address, v2_class_hash); + spy.assert_only_event_upgraded(v1.contract_address, v2_class_hash); } #[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +#[feature("safe_dispatcher")] fn test_v2_missing_camel_selector() { let v1 = setup_dispatcher(); - let v2_class_hash = V2_CLASS_HASH(); + let v2_class_hash = declare_v2_class_hash(); - set_contract_and_caller(v1.contract_address); + start_cheat_caller_address(v1.contract_address, v1.contract_address); v1.upgrade(v2_class_hash); - let dispatcher = EthAccountUpgradeableABIDispatcher { contract_address: v1.contract_address }; - dispatcher.getPublicKey(); + let safe_dispatcher = EthAccountUpgradeableABISafeDispatcher { + contract_address: v1.contract_address + }; + let panic_data = safe_dispatcher.getPublicKey().unwrap_err(); + + utils::assert_entrypoint_not_found_error( + panic_data, selector!("getPublicKey"), v1.contract_address + ) } #[test] fn test_state_persists_after_upgrade() { let v1 = setup_dispatcher(); - let v2_class_hash = V2_CLASS_HASH(); + let key_pair = KEY_PAIR(); + let v2_class_hash = declare_v2_class_hash(); - set_contract_and_caller(v1.contract_address); + start_cheat_caller_address(v1.contract_address, v1.contract_address); let dispatcher = EthAccountUpgradeableABIDispatcher { contract_address: v1.contract_address }; - dispatcher.set_public_key(NEW_ETH_PUBKEY(), get_accept_ownership_signature()); + let signature = get_accept_ownership_signature(v1.contract_address, ETH_PUBKEY(), KEY_PAIR()); + dispatcher.set_public_key(key_pair.public_key, signature); let camel_public_key = dispatcher.getPublicKey(); - assert_eq!(camel_public_key, NEW_ETH_PUBKEY()); + assert_eq!(camel_public_key, key_pair.public_key); v1.upgrade(v2_class_hash); let snake_public_key = dispatcher.get_public_key(); @@ -497,33 +531,14 @@ fn test_state_persists_after_upgrade() { // Helpers // -fn set_contract_and_caller(address: ContractAddress) { - testing::set_contract_address(address); - testing::set_caller_address(address); -} - -fn get_accept_ownership_signature() -> Span { - let mut output = array![]; - - // 0x054308383e1c733aa36ccf3cc62e3107b6bcb10bafcab39912108c6b52655b4c = - // PoseidonTrait::new() - // .update_with('StarkNet Message') - // .update_with('accept_ownership') - // .update_with(dispatcher.contract_address) - // .update_with(ETH_PUBKEY().get_coordinates().unwrap_syscall()) - // .finalize(); - - // This signature was computed using ethers js sdk from the following values: - // - private_key: 0x45397ee6ca34cb49060f1c303c6cb7ee2d6123e617601ef3e31ccf7bf5bef1f9 - // - public_key: - // r: 0x829307f82a1883c2414503ba85fc85037f22c6fc6f80910801f6b01a4131da1e - // s: 0x2a23f7bddf3715d11767b1247eccc68c89e11b926e2615268db6ad1af8d8da96 - // - msg_hash: 0x054308383e1c733aa36ccf3cc62e3107b6bcb10bafcab39912108c6b52655b4c - EthSignature { - r: 0xc4de7637e4206e64ddae9261782dad6d3c99eaaede20ff3fb183f751b94ee9ff, - s: 0x77c24e1ad34f5ba0627048f6a11c1e7ee1ddd3b5d518ee4c71ebd5725390f860, - } - .serialize(ref output); +fn get_points() -> (Secp256k1Point, Secp256k1Point) { + let curve_size = Secp256Trait::::get_curve_size(); + let point_1 = Secp256Trait::secp256_ec_get_point_from_x_syscall(curve_size, true) + .unwrap_syscall() + .unwrap(); + let point_2 = Secp256Trait::secp256_ec_get_point_from_x_syscall(curve_size, false) + .unwrap_syscall() + .unwrap(); - output.span() + (point_1, point_2) } diff --git a/src/tests/utils/constants.cairo b/src/tests/utils/constants.cairo index 2af608bae..2259ef968 100644 --- a/src/tests/utils/constants.cairo +++ b/src/tests/utils/constants.cairo @@ -134,4 +134,3 @@ pub(crate) mod secp256k1 { get_secp256k1_keys_from(PRIVATE_KEY_2) } } - From a794ca0222b3b70e4cb0aba26be7a1a153b4d4c7 Mon Sep 17 00:00:00 2001 From: immrsd <103599616+immrsd@users.noreply.github.com> Date: Thu, 25 Jul 2024 17:55:23 +0200 Subject: [PATCH 18/45] Migrate AccessControl Tests (#1044) * Migrate AccessControl tests * Migrate AccessControl Dual Dispatcher tests * Fix imports * Address review comments * Update error messages * Bring back separator line * Fix ignore reasons in access module * Fix review issues --- src/tests/access.cairo | 4 +- src/tests/access/test_accesscontrol.cairo | 203 ++++++++++-------- .../access/test_dual_accesscontrol.cairo | 124 ++++++----- src/tests/access/test_dual_ownable.cairo | 12 +- 4 files changed, 189 insertions(+), 154 deletions(-) diff --git a/src/tests/access.cairo b/src/tests/access.cairo index c59f6dbc4..cfa981899 100644 --- a/src/tests/access.cairo +++ b/src/tests/access.cairo @@ -1,7 +1,7 @@ pub(crate) mod common; -// mod test_accesscontrol; -// mod test_dual_accesscontrol; +mod test_accesscontrol; +mod test_dual_accesscontrol; mod test_dual_ownable; mod test_ownable; mod test_ownable_twostep; diff --git a/src/tests/access/test_accesscontrol.cairo b/src/tests/access/test_accesscontrol.cairo index 35a76c136..809669e69 100644 --- a/src/tests/access/test_accesscontrol.cairo +++ b/src/tests/access/test_accesscontrol.cairo @@ -1,19 +1,18 @@ -use openzeppelin::access::accesscontrol::AccessControlComponent::InternalImpl; -use openzeppelin::access::accesscontrol::AccessControlComponent::RoleAdminChanged; -use openzeppelin::access::accesscontrol::AccessControlComponent::RoleGranted; -use openzeppelin::access::accesscontrol::AccessControlComponent::RoleRevoked; -use openzeppelin::access::accesscontrol::AccessControlComponent; -use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; -use openzeppelin::access::accesscontrol::interface::IACCESSCONTROL_ID; -use openzeppelin::access::accesscontrol::interface::{IAccessControl, IAccessControlCamel}; +use openzeppelin::access::accesscontrol::AccessControlComponent::{ + InternalImpl, RoleAdminChanged, RoleGranted, RoleRevoked +}; +use openzeppelin::access::accesscontrol::interface::{ + IAccessControl, IAccessControlCamel, IACCESSCONTROL_ID +}; +use openzeppelin::access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE}; use openzeppelin::introspection::interface::ISRC5; use openzeppelin::tests::mocks::accesscontrol_mocks::DualCaseAccessControlMock; use openzeppelin::tests::utils::constants::{ ADMIN, AUTHORIZED, OTHER, OTHER_ADMIN, ROLE, OTHER_ROLE, ZERO }; -use openzeppelin::tests::utils; +use openzeppelin::tests::utils::events::EventSpyExt; +use snforge_std::{EventSpy, spy_events, start_cheat_caller_address, test_address}; use starknet::ContractAddress; -use starknet::testing; // // Setup @@ -33,7 +32,6 @@ fn COMPONENT_STATE() -> ComponentState { fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state._grant_role(DEFAULT_ADMIN_ROLE, ADMIN()); - utils::drop_event(ZERO()); state } @@ -76,10 +74,11 @@ fn test_hasRole() { #[test] fn test_assert_only_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, ADMIN()); state.grant_role(ROLE, AUTHORIZED()); - testing::set_caller_address(AUTHORIZED()); + start_cheat_caller_address(contract_address, AUTHORIZED()); state.assert_only_role(ROLE); } @@ -87,7 +86,7 @@ fn test_assert_only_role() { #[should_panic(expected: ('Caller is missing role',))] fn test_assert_only_role_unauthorized() { let state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.assert_only_role(ROLE); } @@ -97,7 +96,7 @@ fn test_assert_only_role_unauthorized_when_authorized_for_another_role() { let mut state = setup(); state.grant_role(ROLE, AUTHORIZED()); - testing::set_caller_address(AUTHORIZED()); + start_cheat_caller_address(test_address(), AUTHORIZED()); state.assert_only_role(OTHER_ROLE); } @@ -108,10 +107,12 @@ fn test_assert_only_role_unauthorized_when_authorized_for_another_role() { #[test] fn test_grant_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, ADMIN()); state.grant_role(ROLE, AUTHORIZED()); - assert_event_role_granted(ROLE, AUTHORIZED(), ADMIN()); + spy.assert_only_event_role_granted(contract_address, ROLE, AUTHORIZED(), ADMIN()); let has_role = state.has_role(ROLE, AUTHORIZED()); assert!(has_role); @@ -120,10 +121,12 @@ fn test_grant_role() { #[test] fn test_grantRole() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + let mut spy = spy_events(); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, ADMIN()); state.grantRole(ROLE, AUTHORIZED()); - assert_event_role_granted(ROLE, AUTHORIZED(), ADMIN()); + spy.assert_only_event_role_granted(contract_address, ROLE, AUTHORIZED(), ADMIN()); let has_role = state.hasRole(ROLE, AUTHORIZED()); assert!(has_role); @@ -132,7 +135,7 @@ fn test_grantRole() { #[test] fn test_grant_role_multiple_times_for_granted_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(test_address(), ADMIN()); state.grant_role(ROLE, AUTHORIZED()); state.grant_role(ROLE, AUTHORIZED()); @@ -142,7 +145,7 @@ fn test_grant_role_multiple_times_for_granted_role() { #[test] fn test_grantRole_multiple_times_for_granted_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(test_address(), ADMIN()); state.grantRole(ROLE, AUTHORIZED()); state.grantRole(ROLE, AUTHORIZED()); @@ -153,7 +156,7 @@ fn test_grantRole_multiple_times_for_granted_role() { #[should_panic(expected: ('Caller is missing role',))] fn test_grant_role_unauthorized() { let mut state = setup(); - testing::set_caller_address(AUTHORIZED()); + start_cheat_caller_address(test_address(), AUTHORIZED()); state.grant_role(ROLE, AUTHORIZED()); } @@ -161,7 +164,7 @@ fn test_grant_role_unauthorized() { #[should_panic(expected: ('Caller is missing role',))] fn test_grantRole_unauthorized() { let mut state = setup(); - testing::set_caller_address(AUTHORIZED()); + start_cheat_caller_address(test_address(), AUTHORIZED()); state.grantRole(ROLE, AUTHORIZED()); } @@ -172,28 +175,29 @@ fn test_grantRole_unauthorized() { #[test] fn test_revoke_role_for_role_not_granted() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(test_address(), ADMIN()); state.revoke_role(ROLE, AUTHORIZED()); } #[test] fn test_revokeRole_for_role_not_granted() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(test_address(), ADMIN()); state.revokeRole(ROLE, AUTHORIZED()); } #[test] fn test_revoke_role_for_granted_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, ADMIN()); state.grant_role(ROLE, AUTHORIZED()); - utils::drop_event(ZERO()); + let mut spy = spy_events(); state.revoke_role(ROLE, AUTHORIZED()); - assert_event_role_revoked(ROLE, AUTHORIZED(), ADMIN()); + spy.assert_only_event_role_revoked(contract_address, ROLE, AUTHORIZED(), ADMIN()); let has_not_role = !state.has_role(ROLE, AUTHORIZED()); assert!(has_not_role); @@ -202,14 +206,15 @@ fn test_revoke_role_for_granted_role() { #[test] fn test_revokeRole_for_granted_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, ADMIN()); state.grantRole(ROLE, AUTHORIZED()); - utils::drop_event(ZERO()); + let mut spy = spy_events(); state.revokeRole(ROLE, AUTHORIZED()); - assert_event_role_revoked(ROLE, AUTHORIZED(), ADMIN()); + spy.assert_only_event_role_revoked(contract_address, ROLE, AUTHORIZED(), ADMIN()); let has_not_role = !state.hasRole(ROLE, AUTHORIZED()); assert!(has_not_role); @@ -218,7 +223,7 @@ fn test_revokeRole_for_granted_role() { #[test] fn test_revoke_role_multiple_times_for_granted_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(test_address(), ADMIN()); state.grant_role(ROLE, AUTHORIZED()); state.revoke_role(ROLE, AUTHORIZED()); @@ -231,7 +236,7 @@ fn test_revoke_role_multiple_times_for_granted_role() { #[test] fn test_revokeRole_multiple_times_for_granted_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(test_address(), ADMIN()); state.grantRole(ROLE, AUTHORIZED()); state.revokeRole(ROLE, AUTHORIZED()); @@ -245,7 +250,7 @@ fn test_revokeRole_multiple_times_for_granted_role() { #[should_panic(expected: ('Caller is missing role',))] fn test_revoke_role_unauthorized() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.revoke_role(ROLE, AUTHORIZED()); } @@ -253,7 +258,7 @@ fn test_revoke_role_unauthorized() { #[should_panic(expected: ('Caller is missing role',))] fn test_revokeRole_unauthorized() { let mut state = setup(); - testing::set_caller_address(OTHER()); + start_cheat_caller_address(test_address(), OTHER()); state.revokeRole(ROLE, AUTHORIZED()); } @@ -264,29 +269,30 @@ fn test_revokeRole_unauthorized() { #[test] fn test_renounce_role_for_role_not_granted() { let mut state = setup(); - testing::set_caller_address(AUTHORIZED()); + start_cheat_caller_address(test_address(), AUTHORIZED()); state.renounce_role(ROLE, AUTHORIZED()); } #[test] fn test_renounceRole_for_role_not_granted() { let mut state = setup(); - testing::set_caller_address(AUTHORIZED()); + start_cheat_caller_address(test_address(), AUTHORIZED()); state.renounceRole(ROLE, AUTHORIZED()); } #[test] fn test_renounce_role_for_granted_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, ADMIN()); state.grant_role(ROLE, AUTHORIZED()); - utils::drop_event(ZERO()); - testing::set_caller_address(AUTHORIZED()); + let mut spy = spy_events(); + start_cheat_caller_address(contract_address, AUTHORIZED()); state.renounce_role(ROLE, AUTHORIZED()); - assert_event_role_revoked(ROLE, AUTHORIZED(), AUTHORIZED()); + spy.assert_only_event_role_revoked(contract_address, ROLE, AUTHORIZED(), AUTHORIZED()); let has_not_role = !state.has_role(ROLE, AUTHORIZED()); assert!(has_not_role); @@ -295,15 +301,16 @@ fn test_renounce_role_for_granted_role() { #[test] fn test_renounceRole_for_granted_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, ADMIN()); state.grantRole(ROLE, AUTHORIZED()); - utils::drop_event(ZERO()); - testing::set_caller_address(AUTHORIZED()); + let mut spy = spy_events(); + start_cheat_caller_address(contract_address, AUTHORIZED()); state.renounceRole(ROLE, AUTHORIZED()); - assert_event_role_revoked(ROLE, AUTHORIZED(), AUTHORIZED()); + spy.assert_only_event_role_revoked(contract_address, ROLE, AUTHORIZED(), AUTHORIZED()); let has_not_role = !state.hasRole(ROLE, AUTHORIZED()); assert!(has_not_role); @@ -312,10 +319,11 @@ fn test_renounceRole_for_granted_role() { #[test] fn test_renounce_role_multiple_times_for_granted_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, ADMIN()); state.grant_role(ROLE, AUTHORIZED()); - testing::set_caller_address(AUTHORIZED()); + start_cheat_caller_address(contract_address, AUTHORIZED()); state.renounce_role(ROLE, AUTHORIZED()); state.renounce_role(ROLE, AUTHORIZED()); @@ -326,10 +334,11 @@ fn test_renounce_role_multiple_times_for_granted_role() { #[test] fn test_renounceRole_multiple_times_for_granted_role() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, ADMIN()); state.grantRole(ROLE, AUTHORIZED()); - testing::set_caller_address(AUTHORIZED()); + start_cheat_caller_address(contract_address, AUTHORIZED()); state.renounceRole(ROLE, AUTHORIZED()); state.renounceRole(ROLE, AUTHORIZED()); @@ -341,10 +350,11 @@ fn test_renounceRole_multiple_times_for_granted_role() { #[should_panic(expected: ('Can only renounce role for self',))] fn test_renounce_role_unauthorized() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, ADMIN()); state.grant_role(ROLE, AUTHORIZED()); - testing::set_caller_address(ZERO()); + start_cheat_caller_address(contract_address, ZERO()); state.renounce_role(ROLE, AUTHORIZED()); } @@ -352,7 +362,7 @@ fn test_renounce_role_unauthorized() { #[should_panic(expected: ('Can only renounce role for self',))] fn test_renounceRole_unauthorized() { let mut state = setup(); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(test_address(), ADMIN()); state.grantRole(ROLE, AUTHORIZED()); // Admin is unauthorized caller @@ -366,10 +376,16 @@ fn test_renounceRole_unauthorized() { #[test] fn test_set_role_admin() { let mut state = setup(); + let contract_address = test_address(); + let mut spy = spy_events(); + assert_eq!(state.get_role_admin(ROLE), DEFAULT_ADMIN_ROLE); state.set_role_admin(ROLE, OTHER_ROLE); - assert_event_role_admin_changed(ROLE, DEFAULT_ADMIN_ROLE, OTHER_ROLE); + spy + .assert_only_event_role_admin_changed( + contract_address, ROLE, DEFAULT_ADMIN_ROLE, OTHER_ROLE + ); let current_admin_role = state.get_role_admin(ROLE); assert_eq!(current_admin_role, OTHER_ROLE); @@ -378,12 +394,13 @@ fn test_set_role_admin() { #[test] fn test_new_admin_can_grant_roles() { let mut state = setup(); + let contract_address = test_address(); state.set_role_admin(ROLE, OTHER_ROLE); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(contract_address, ADMIN()); state.grant_role(OTHER_ROLE, OTHER_ADMIN()); - testing::set_caller_address(OTHER_ADMIN()); + start_cheat_caller_address(contract_address, OTHER_ADMIN()); state.grant_role(ROLE, AUTHORIZED()); let has_role = state.has_role(ROLE, AUTHORIZED()); @@ -393,12 +410,13 @@ fn test_new_admin_can_grant_roles() { #[test] fn test_new_admin_can_revoke_roles() { let mut state = setup(); + let contract_address = test_address(); state.set_role_admin(ROLE, OTHER_ROLE); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(contract_address, ADMIN()); state.grant_role(OTHER_ROLE, OTHER_ADMIN()); - testing::set_caller_address(OTHER_ADMIN()); + start_cheat_caller_address(contract_address, OTHER_ADMIN()); state.grant_role(ROLE, AUTHORIZED()); state.revoke_role(ROLE, AUTHORIZED()); @@ -411,7 +429,7 @@ fn test_new_admin_can_revoke_roles() { fn test_previous_admin_cannot_grant_roles() { let mut state = setup(); state.set_role_admin(ROLE, OTHER_ROLE); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(test_address(), ADMIN()); state.grant_role(ROLE, AUTHORIZED()); } @@ -420,7 +438,7 @@ fn test_previous_admin_cannot_grant_roles() { fn test_previous_admin_cannot_revoke_roles() { let mut state = setup(); state.set_role_admin(ROLE, OTHER_ROLE); - testing::set_caller_address(ADMIN()); + start_cheat_caller_address(test_address(), ADMIN()); state.revoke_role(ROLE, AUTHORIZED()); } @@ -447,31 +465,44 @@ fn test_default_admin_role_is_its_own_admin() { // Helpers // -fn assert_event_role_revoked(role: felt252, account: ContractAddress, sender: ContractAddress) { - let event = utils::pop_log::(ZERO()).unwrap(); - let expected = AccessControlComponent::Event::RoleRevoked( - RoleRevoked { role, account, sender } - ); - assert!(event == expected); - utils::assert_no_events_left(ZERO()); -} - -fn assert_event_role_granted(role: felt252, account: ContractAddress, sender: ContractAddress) { - let event = utils::pop_log::(ZERO()).unwrap(); - let expected = AccessControlComponent::Event::RoleGranted( - RoleGranted { role, account, sender } - ); - assert!(event == expected); - utils::assert_no_events_left(ZERO()); -} - -fn assert_event_role_admin_changed( - role: felt252, previous_admin_role: felt252, new_admin_role: felt252 -) { - let event = utils::pop_log::(ZERO()).unwrap(); - let expected = AccessControlComponent::Event::RoleAdminChanged( - RoleAdminChanged { role, previous_admin_role, new_admin_role } - ); - assert!(event == expected); - utils::assert_no_events_left(ZERO()); +#[generate_trait] +impl AccessControlSpyHelpersImpl of AccessControlSpyHelpers { + fn assert_only_event_role_revoked( + ref self: EventSpy, + contract: ContractAddress, + role: felt252, + account: ContractAddress, + sender: ContractAddress + ) { + let expected = AccessControlComponent::Event::RoleRevoked( + RoleRevoked { role, account, sender } + ); + self.assert_only_event(contract, expected); + } + + fn assert_only_event_role_granted( + ref self: EventSpy, + contract: ContractAddress, + role: felt252, + account: ContractAddress, + sender: ContractAddress + ) { + let expected = AccessControlComponent::Event::RoleGranted( + RoleGranted { role, account, sender } + ); + self.assert_only_event(contract, expected); + } + + fn assert_only_event_role_admin_changed( + ref self: EventSpy, + from_address: ContractAddress, + role: felt252, + previous_admin_role: felt252, + new_admin_role: felt252 + ) { + let expected = AccessControlComponent::Event::RoleAdminChanged( + RoleAdminChanged { role, previous_admin_role, new_admin_role } + ); + self.assert_only_event(from_address, expected); + } } diff --git a/src/tests/access/test_dual_accesscontrol.cairo b/src/tests/access/test_dual_accesscontrol.cairo index e172384a7..bd8f17781 100644 --- a/src/tests/access/test_dual_accesscontrol.cairo +++ b/src/tests/access/test_dual_accesscontrol.cairo @@ -1,22 +1,16 @@ use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; use openzeppelin::access::accesscontrol::dual_accesscontrol::DualCaseAccessControl; use openzeppelin::access::accesscontrol::dual_accesscontrol::DualCaseAccessControlTrait; -use openzeppelin::access::accesscontrol::interface::IACCESSCONTROL_ID; -use openzeppelin::access::accesscontrol::interface::IAccessControlCamelDispatcher; -use openzeppelin::access::accesscontrol::interface::IAccessControlCamelDispatcherTrait; -use openzeppelin::access::accesscontrol::interface::IAccessControlDispatcher; -use openzeppelin::access::accesscontrol::interface::IAccessControlDispatcherTrait; -use openzeppelin::tests::mocks::accesscontrol_mocks::{ - CamelAccessControlMock, SnakeAccessControlMock, CamelAccessControlPanicMock, - SnakeAccessControlPanicMock +use openzeppelin::access::accesscontrol::interface::{ + IACCESSCONTROL_ID, IAccessControlCamelDispatcher, IAccessControlCamelDispatcherTrait +}; +use openzeppelin::access::accesscontrol::interface::{ + IAccessControlDispatcher, IAccessControlDispatcherTrait }; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin::tests::utils::constants::{ADMIN, AUTHORIZED, ROLE}; use openzeppelin::tests::utils; use openzeppelin::utils::serde::SerializedAppend; -use starknet::ContractAddress; -use starknet::contract_address_const; -use starknet::testing::set_contract_address; +use snforge_std::start_cheat_caller_address; // // Setup @@ -25,7 +19,7 @@ use starknet::testing::set_contract_address; fn setup_snake() -> (DualCaseAccessControl, IAccessControlDispatcher) { let mut calldata = array![]; calldata.append_serde(ADMIN()); - let target = utils::deploy(SnakeAccessControlMock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("SnakeAccessControlMock", calldata); ( DualCaseAccessControl { contract_address: target }, IAccessControlDispatcher { contract_address: target } @@ -35,7 +29,7 @@ fn setup_snake() -> (DualCaseAccessControl, IAccessControlDispatcher) { fn setup_camel() -> (DualCaseAccessControl, IAccessControlCamelDispatcher) { let mut calldata = array![]; calldata.append_serde(ADMIN()); - let target = utils::deploy(CamelAccessControlMock::TEST_CLASS_HASH, calldata); + let target = utils::declare_and_deploy("CamelAccessControlMock", calldata); ( DualCaseAccessControl { contract_address: target }, IAccessControlCamelDispatcher { contract_address: target } @@ -43,13 +37,13 @@ fn setup_camel() -> (DualCaseAccessControl, IAccessControlCamelDispatcher) { } fn setup_non_accesscontrol() -> DualCaseAccessControl { - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let target = utils::declare_and_deploy("NonImplementingMock", array![]); DualCaseAccessControl { contract_address: target } } fn setup_accesscontrol_panic() -> (DualCaseAccessControl, DualCaseAccessControl) { - let snake_target = utils::deploy(SnakeAccessControlPanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelAccessControlPanicMock::TEST_CLASS_HASH, array![]); + let snake_target = utils::declare_and_deploy("SnakeAccessControlPanicMock", array![]); + let camel_target = utils::declare_and_deploy("CamelAccessControlPanicMock", array![]); ( DualCaseAccessControl { contract_address: snake_target }, DualCaseAccessControl { contract_address: camel_target } @@ -68,6 +62,7 @@ fn test_dual_supports_interface() { } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_supports_interface() { let dispatcher = setup_non_accesscontrol(); @@ -75,20 +70,21 @@ fn test_dual_no_supports_interface() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_supports_interface_exists_and_panics() { - let (dispatcher, _) = setup_accesscontrol_panic(); - dispatcher.supports_interface(IACCESSCONTROL_ID); + let (snake_dispatcher, _) = setup_accesscontrol_panic(); + snake_dispatcher.supports_interface(IACCESSCONTROL_ID); } #[test] fn test_dual_has_role() { - let (dispatcher, _) = setup_snake(); - let has_role = dispatcher.has_role(DEFAULT_ADMIN_ROLE, ADMIN()); + let (snake_dispatcher, _) = setup_snake(); + let has_role = snake_dispatcher.has_role(DEFAULT_ADMIN_ROLE, ADMIN()); assert!(has_role); } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_has_role() { let dispatcher = setup_non_accesscontrol(); @@ -96,7 +92,7 @@ fn test_dual_no_has_role() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_has_role_exists_and_panics() { let (dispatcher, _) = setup_accesscontrol_panic(); dispatcher.has_role(DEFAULT_ADMIN_ROLE, ADMIN()); @@ -105,12 +101,12 @@ fn test_dual_has_role_exists_and_panics() { #[test] fn test_dual_get_role_admin() { let (dispatcher, _) = setup_snake(); - let current_admin_role = dispatcher.get_role_admin(ROLE); assert_eq!(current_admin_role, DEFAULT_ADMIN_ROLE); } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_get_role_admin() { let dispatcher = setup_non_accesscontrol(); @@ -118,16 +114,16 @@ fn test_dual_no_get_role_admin() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_get_role_admin_exists_and_panics() { - let (dispatcher, _) = setup_accesscontrol_panic(); - dispatcher.get_role_admin(ROLE); + let (snake_dispatcher, _) = setup_accesscontrol_panic(); + snake_dispatcher.get_role_admin(ROLE); } #[test] fn test_dual_grant_role() { let (dispatcher, target) = setup_snake(); - set_contract_address(ADMIN()); + start_cheat_caller_address(target.contract_address, ADMIN()); dispatcher.grant_role(ROLE, AUTHORIZED()); let has_role = target.has_role(ROLE, AUTHORIZED()); @@ -135,6 +131,7 @@ fn test_dual_grant_role() { } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_grant_role() { let dispatcher = setup_non_accesscontrol(); @@ -142,16 +139,16 @@ fn test_dual_no_grant_role() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_grant_role_exists_and_panics() { - let (dispatcher, _) = setup_accesscontrol_panic(); - dispatcher.grant_role(ROLE, AUTHORIZED()); + let (snake_dispatcher, _) = setup_accesscontrol_panic(); + snake_dispatcher.grant_role(ROLE, AUTHORIZED()); } #[test] fn test_dual_revoke_role() { let (dispatcher, target) = setup_snake(); - set_contract_address(ADMIN()); + start_cheat_caller_address(target.contract_address, ADMIN()); dispatcher.revoke_role(ROLE, AUTHORIZED()); let has_not_role = !target.has_role(ROLE, AUTHORIZED()); @@ -159,6 +156,7 @@ fn test_dual_revoke_role() { } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_revoke_role() { let dispatcher = setup_non_accesscontrol(); @@ -166,16 +164,16 @@ fn test_dual_no_revoke_role() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_revoke_role_exists_and_panics() { - let (dispatcher, _) = setup_accesscontrol_panic(); - dispatcher.revoke_role(ROLE, AUTHORIZED()); + let (snake_dispatcher, _) = setup_accesscontrol_panic(); + snake_dispatcher.revoke_role(ROLE, AUTHORIZED()); } #[test] fn test_dual_renounce_role() { let (dispatcher, target) = setup_snake(); - set_contract_address(ADMIN()); + start_cheat_caller_address(target.contract_address, ADMIN()); dispatcher.renounce_role(DEFAULT_ADMIN_ROLE, ADMIN()); let has_not_role = !target.has_role(DEFAULT_ADMIN_ROLE, ADMIN()); @@ -183,6 +181,7 @@ fn test_dual_renounce_role() { } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_renounce_role() { let dispatcher = setup_non_accesscontrol(); @@ -190,10 +189,10 @@ fn test_dual_no_renounce_role() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_renounce_role_exists_and_panics() { - let (dispatcher, _) = setup_accesscontrol_panic(); - dispatcher.renounce_role(DEFAULT_ADMIN_ROLE, ADMIN()); + let (snake_dispatcher, _) = setup_accesscontrol_panic(); + snake_dispatcher.renounce_role(DEFAULT_ADMIN_ROLE, ADMIN()); } // @@ -201,6 +200,7 @@ fn test_dual_renounce_role_exists_and_panics() { // #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_hasRole() { let (dispatcher, _) = setup_camel(); @@ -209,13 +209,15 @@ fn test_dual_hasRole() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_hasRole_exists_and_panics() { - let (_, dispatcher) = setup_accesscontrol_panic(); - dispatcher.has_role(DEFAULT_ADMIN_ROLE, ADMIN()); + let (_, camel_dispatcher) = setup_accesscontrol_panic(); + camel_dispatcher.has_role(DEFAULT_ADMIN_ROLE, ADMIN()); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_getRoleAdmin() { let (dispatcher, _) = setup_camel(); @@ -224,16 +226,18 @@ fn test_dual_getRoleAdmin() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_getRoleAdmin_exists_and_panics() { - let (_, dispatcher) = setup_accesscontrol_panic(); - dispatcher.get_role_admin(ROLE); + let (_, camel_dispatcher) = setup_accesscontrol_panic(); + camel_dispatcher.get_role_admin(ROLE); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_grantRole() { let (dispatcher, target) = setup_camel(); - set_contract_address(ADMIN()); + start_cheat_caller_address(target.contract_address, ADMIN()); dispatcher.grant_role(ROLE, AUTHORIZED()); let has_role = target.hasRole(ROLE, AUTHORIZED()); @@ -241,16 +245,18 @@ fn test_dual_grantRole() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_grantRole_exists_and_panics() { - let (_, dispatcher) = setup_accesscontrol_panic(); - dispatcher.grant_role(ROLE, AUTHORIZED()); + let (_, camel_dispatcher) = setup_accesscontrol_panic(); + camel_dispatcher.grant_role(ROLE, AUTHORIZED()); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_revokeRole() { let (dispatcher, target) = setup_camel(); - set_contract_address(ADMIN()); + start_cheat_caller_address(target.contract_address, ADMIN()); dispatcher.grant_role(ROLE, AUTHORIZED()); dispatcher.revoke_role(ROLE, AUTHORIZED()); @@ -259,16 +265,18 @@ fn test_dual_revokeRole() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_revokeRole_exists_and_panics() { - let (_, dispatcher) = setup_accesscontrol_panic(); - dispatcher.revoke_role(ROLE, AUTHORIZED()); + let (_, camel_dispatcher) = setup_accesscontrol_panic(); + camel_dispatcher.revoke_role(ROLE, AUTHORIZED()); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_renounceRole() { let (dispatcher, target) = setup_camel(); - set_contract_address(ADMIN()); + start_cheat_caller_address(target.contract_address, ADMIN()); dispatcher.renounce_role(DEFAULT_ADMIN_ROLE, ADMIN()); let has_not_role = !target.hasRole(DEFAULT_ADMIN_ROLE, ADMIN()); @@ -276,9 +284,9 @@ fn test_dual_renounceRole() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_renounceRole_exists_and_panics() { - let (_, dispatcher) = setup_accesscontrol_panic(); - dispatcher.renounce_role(DEFAULT_ADMIN_ROLE, ADMIN()); + let (_, camel_dispatcher) = setup_accesscontrol_panic(); + camel_dispatcher.renounce_role(DEFAULT_ADMIN_ROLE, ADMIN()); } - diff --git a/src/tests/access/test_dual_ownable.cairo b/src/tests/access/test_dual_ownable.cairo index 16c22514f..08a863498 100644 --- a/src/tests/access/test_dual_ownable.cairo +++ b/src/tests/access/test_dual_ownable.cairo @@ -3,10 +3,6 @@ use openzeppelin::access::ownable::dual_ownable::{DualCaseOwnable, DualCaseOwnab use openzeppelin::access::ownable::interface::{ IOwnableDispatcher, IOwnableCamelOnlyDispatcher, IOwnableDispatcherTrait }; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::mocks::ownable_mocks::{ - CamelOwnableMock, CamelOwnablePanicMock, SnakeOwnableMock, SnakeOwnablePanicMock -}; use openzeppelin::tests::utils::constants::{OWNER, NEW_OWNER}; use openzeppelin::tests::utils; use openzeppelin::utils::serde::SerializedAppend; @@ -138,7 +134,7 @@ fn test_dual_renounce_ownership_exists_and_panics() { // #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_transferOwnership() { let (dispatcher, _) = setup_camel(); start_cheat_caller_address(dispatcher.contract_address, OWNER()); @@ -149,7 +145,7 @@ fn test_dual_transferOwnership() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_transferOwnership_exists_and_panics() { let (_, camel_dispatcher) = setup_ownable_panic(); @@ -157,7 +153,7 @@ fn test_dual_transferOwnership_exists_and_panics() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_renounceOwnership() { let (dispatcher, _) = setup_camel(); start_cheat_caller_address(dispatcher.contract_address, OWNER()); @@ -168,7 +164,7 @@ fn test_dual_renounceOwnership() { } #[test] -#[ignore] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. #[should_panic(expected: ("Some error",))] fn test_dual_renounceOwnership_exists_and_panics() { let (_, camel_dispatcher) = setup_ownable_panic(); From bc316cae4c09bac6e27f3e43a3ff410ed1f3eec6 Mon Sep 17 00:00:00 2001 From: immrsd <103599616+immrsd@users.noreply.github.com> Date: Fri, 26 Jul 2024 12:51:53 +0200 Subject: [PATCH 19/45] Migrate Starknet Account tests (#1050) * Update test utils and helpers * Update signature tests * Update account tests * Update dual account tests * Run linter * Run linter * Fix review issues * Update ignore reason messages * Run linter * Support eth account tests changes * Run linter * Improve setup functions, remove unused imports * Remove unnecessary accept_ownership step, make use of serialized_sign fn --- src/tests/account/ethereum.cairo | 1 - src/tests/account/starknet.cairo | 6 +- src/tests/account/starknet/common.cairo | 35 +- src/tests/account/starknet/test_account.cairo | 391 +++++++++--------- .../account/starknet/test_dual_account.cairo | 221 ++++------ src/tests/account/test_signature.cairo | 58 ++- src/tests/utils/constants.cairo | 20 +- src/tests/utils/signing.cairo | 8 + 8 files changed, 349 insertions(+), 391 deletions(-) diff --git a/src/tests/account/ethereum.cairo b/src/tests/account/ethereum.cairo index 2d87a5992..d6fcf488b 100644 --- a/src/tests/account/ethereum.cairo +++ b/src/tests/account/ethereum.cairo @@ -2,4 +2,3 @@ pub(crate) mod common; mod test_dual_eth_account; mod test_eth_account; - diff --git a/src/tests/account/starknet.cairo b/src/tests/account/starknet.cairo index f426692e3..8c3e80c69 100644 --- a/src/tests/account/starknet.cairo +++ b/src/tests/account/starknet.cairo @@ -1,5 +1,3 @@ pub(crate) mod common; -// mod test_account; -// mod test_dual_account; - - +mod test_account; +mod test_dual_account; diff --git a/src/tests/account/starknet/common.cairo b/src/tests/account/starknet/common.cairo index f029dff0a..26554ba33 100644 --- a/src/tests/account/starknet/common.cairo +++ b/src/tests/account/starknet/common.cairo @@ -1,35 +1,32 @@ +use core::hash::{HashStateTrait, HashStateExTrait}; +use core::poseidon::PoseidonTrait; use openzeppelin::account::AccountComponent::{OwnerAdded, OwnerRemoved}; use openzeppelin::account::AccountComponent; -use openzeppelin::tests::utils::constants::{NAME, SYMBOL, NEW_PUBKEY}; +use openzeppelin::tests::utils::constants::{NAME, SYMBOL, TRANSACTION_HASH}; use openzeppelin::tests::utils::events::EventSpyExt; +use openzeppelin::tests::utils::signing::StarkKeyPair; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin::token::erc20::interface::IERC20Dispatcher; use openzeppelin::utils::serde::SerializedAppend; use snforge_std::EventSpy; +use snforge_std::signature::stark_curve::StarkCurveSignerImpl; use starknet::ContractAddress; #[derive(Drop)] pub(crate) struct SignedTransactionData { - pub(crate) private_key: felt252, - pub(crate) public_key: felt252, pub(crate) tx_hash: felt252, pub(crate) r: felt252, pub(crate) s: felt252 } -pub(crate) fn SIGNED_TX_DATA() -> SignedTransactionData { - SignedTransactionData { - private_key: 1234, - public_key: NEW_PUBKEY, - tx_hash: 0x601d3d2e265c10ff645e1554c435e72ce6721f0ba5fc96f0c650bfc6231191a, - r: 0x6bc22689efcaeacb9459577138aff9f0af5b77ee7894cdc8efabaf760f6cf6e, - s: 0x295989881583b9325436851934334faa9d639a2094cd1e2f8691c8a71cd4cdf - } +pub(crate) fn SIGNED_TX_DATA(key_pair: StarkKeyPair) -> SignedTransactionData { + let tx_hash = TRANSACTION_HASH; + let (r, s) = key_pair.sign(tx_hash).unwrap(); + SignedTransactionData { tx_hash, r, s } } pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { let mut calldata = array![]; - calldata.append_serde(NAME()); calldata.append_serde(SYMBOL()); calldata.append_serde(initial_supply); @@ -39,6 +36,18 @@ pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { contract_address: address } } +pub(crate) fn get_accept_ownership_signature( + account_address: ContractAddress, current_public_key: felt252, new_key_pair: StarkKeyPair +) -> Span { + let msg_hash = PoseidonTrait::new() + .update_with('StarkNet Message') + .update_with('accept_ownership') + .update_with(account_address) + .update_with(current_public_key) + .finalize(); + let (sig_r, sig_s) = new_key_pair.sign(msg_hash).unwrap(); + array![sig_r, sig_s].span() +} #[generate_trait] pub(crate) impl AccountSpyHelpersImpl of AccountSpyHelpers { diff --git a/src/tests/account/starknet/test_account.cairo b/src/tests/account/starknet/test_account.cairo index ed4dc81ed..13dd7f36e 100644 --- a/src/tests/account/starknet/test_account.cairo +++ b/src/tests/account/starknet/test_account.cairo @@ -1,4 +1,5 @@ use core::num::traits::Zero; +use core::starknet::SyscallResultTrait; use openzeppelin::account::AccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; use openzeppelin::account::AccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; use openzeppelin::account::AccountComponent; @@ -6,32 +7,24 @@ use openzeppelin::account::interface::{AccountABIDispatcherTrait, AccountABIDisp use openzeppelin::account::interface::{ISRC6, ISRC6_ID}; use openzeppelin::introspection::interface::{ISRC5, ISRC5_ID}; use openzeppelin::tests::mocks::account_mocks::DualCaseAccountMock; +use openzeppelin::tests::utils::constants::stark::{KEY_PAIR, KEY_PAIR_2}; use openzeppelin::tests::utils::constants::{ - PUBKEY, NEW_PUBKEY, SALT, ZERO, QUERY_OFFSET, QUERY_VERSION, MIN_TRANSACTION_VERSION + SALT, ZERO, OTHER, CALLER, RECIPIENT, QUERY_OFFSET, QUERY_VERSION, MIN_TRANSACTION_VERSION }; +use openzeppelin::tests::utils::signing::StarkKeyPair; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; use openzeppelin::utils::selectors; use openzeppelin::utils::serde::SerializedAppend; -use starknet::ContractAddress; +use snforge_std::{ + cheat_signature_global, cheat_transaction_version_global, cheat_transaction_hash_global +}; +use snforge_std::{spy_events, declare, test_address, start_cheat_caller_address}; use starknet::account::Call; -use starknet::contract_address_const; -use starknet::testing; +use starknet::{contract_address_const, ContractAddress, ClassHash}; -use super::common::{assert_only_event_owner_added, assert_event_owner_removed}; -use super::common::{deploy_erc20, SIGNED_TX_DATA, SignedTransactionData}; - -// -// Constants -// - -fn CLASS_HASH() -> felt252 { - DualCaseAccountMock::TEST_CLASS_HASH -} - -fn ACCOUNT_ADDRESS() -> ContractAddress { - contract_address_const::<0x111111>() -} +use super::common::{AccountSpyHelpers, SignedTransactionData}; +use super::common::{deploy_erc20, SIGNED_TX_DATA, get_accept_ownership_signature}; // // Setup @@ -47,28 +40,26 @@ fn COMPONENT_STATE() -> ComponentState { AccountComponent::component_state_for_testing() } -fn setup() -> ComponentState { +fn setup(key_pair: StarkKeyPair) -> ComponentState { let mut state = COMPONENT_STATE(); - state.initializer(PUBKEY); - utils::drop_event(ZERO()); + state.initializer(key_pair.public_key); state } -fn setup_dispatcher(data: Option<@SignedTransactionData>) -> AccountABIDispatcher { - testing::set_version(MIN_TRANSACTION_VERSION); +fn setup_dispatcher( + key_pair: StarkKeyPair, data: SignedTransactionData +) -> (AccountABIDispatcher, felt252) { + let contract_class = declare("DualCaseAccountMock").unwrap_syscall(); + let calldata = array![key_pair.public_key]; + let address = utils::deploy(contract_class, calldata); + let dispatcher = AccountABIDispatcher { contract_address: address }; - let mut calldata = array![]; - if data.is_some() { - let data = data.unwrap(); - testing::set_signature(array![*data.r, *data.s].span()); - testing::set_transaction_hash(*data.transaction_hash); - - calldata.append(*data.public_key); - } else { - calldata.append(PUBKEY); - } - let address = utils::deploy(CLASS_HASH(), calldata); - AccountABIDispatcher { contract_address: address } + cheat_signature_global(array![data.r, data.s].span()); + cheat_transaction_hash_global(data.tx_hash); + cheat_transaction_version_global(MIN_TRANSACTION_VERSION); + start_cheat_caller_address(address, ZERO()); + + (dispatcher, contract_class.class_hash.into()) } // @@ -78,36 +69,34 @@ fn setup_dispatcher(data: Option<@SignedTransactionData>) -> AccountABIDispatche #[test] fn test_is_valid_signature() { let mut state = COMPONENT_STATE(); - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; + let key_pair = KEY_PAIR(); + let data = SIGNED_TX_DATA(key_pair); - let mut good_signature = array![data.r, data.s]; - let mut bad_signature = array![0x987, 0x564]; + state._set_public_key(key_pair.public_key); - state._set_public_key(data.public_key); - - let is_valid = state.is_valid_signature(hash, good_signature); + let good_signature = array![data.r, data.s]; + let is_valid = state.is_valid_signature(data.tx_hash, good_signature); assert_eq!(is_valid, starknet::VALIDATED); - let is_valid = state.is_valid_signature(hash, bad_signature); + let bad_signature = array!['BAD', 'SIGNATURE']; + let is_valid = state.is_valid_signature(data.tx_hash, bad_signature); assert!(is_valid.is_zero(), "Should reject invalid signature"); } #[test] fn test_isValidSignature() { let mut state = COMPONENT_STATE(); - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; - - let mut good_signature = array![data.r, data.s]; - let mut bad_signature = array![0x987, 0x564]; + let key_pair = KEY_PAIR(); + let data = SIGNED_TX_DATA(key_pair); - state._set_public_key(data.public_key); + state._set_public_key(key_pair.public_key); - let is_valid = state.isValidSignature(hash, good_signature); + let good_signature = array![data.r, data.s]; + let is_valid = state.isValidSignature(data.tx_hash, good_signature); assert_eq!(is_valid, starknet::VALIDATED); - let is_valid = state.isValidSignature(hash, bad_signature); + let bad_signature = array!['BAD', 'SIGNATURE']; + let is_valid = state.isValidSignature(data.tx_hash, bad_signature); assert!(is_valid.is_zero(), "Should reject invalid signature"); } @@ -117,96 +106,99 @@ fn test_isValidSignature() { #[test] fn test_validate_deploy() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); // `__validate_deploy__` does not directly use the passed arguments. Their // values are already integrated in the tx hash. The passed arguments in this // testing context are decoupled from the signature and have no effect on the test. - let is_valid = account.__validate_deploy__(CLASS_HASH(), SALT, PUBKEY); + let is_valid = account.__validate_deploy__(class_hash, SALT, key_pair.public_key); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_deploy_invalid_signature_data() { - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher(Option::Some(@data)); + let key_pair = KEY_PAIR(); + let mut data = SIGNED_TX_DATA(key_pair); + data.tx_hash += 1; + let (account, class_hash) = setup_dispatcher(key_pair, data); - account.__validate_deploy__(CLASS_HASH(), SALT, PUBKEY); + account.__validate_deploy__(class_hash, SALT, key_pair.public_key); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_deploy_invalid_signature_length() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); - let mut signature = array![]; + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); + let invalid_len_sig = array!['INVALID_LEN_SIG']; + cheat_signature_global(invalid_len_sig.span()); - signature.append(0x1); - testing::set_signature(signature.span()); - - account.__validate_deploy__(CLASS_HASH(), SALT, PUBKEY); + account.__validate_deploy__(class_hash, SALT, key_pair.public_key); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_deploy_empty_signature() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); let empty_sig = array![]; - testing::set_signature(empty_sig.span()); - account.__validate_deploy__(CLASS_HASH(), SALT, PUBKEY); + cheat_signature_global(empty_sig.span()); + account.__validate_deploy__(class_hash, SALT, key_pair.public_key); } #[test] fn test_validate_declare() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); // `__validate_declare__` does not directly use the class_hash argument. Its // value is already integrated in the tx hash. The class_hash argument in this // testing context is decoupled from the signature and has no effect on the test. - let is_valid = account.__validate_declare__(CLASS_HASH()); + let is_valid = account.__validate_declare__(class_hash); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_declare_invalid_signature_data() { - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher(Option::Some(@data)); + let key_pair = KEY_PAIR(); + let mut data = SIGNED_TX_DATA(key_pair); + data.tx_hash += 1; + let (account, class_hash) = setup_dispatcher(key_pair, data); - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_declare_invalid_signature_length() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); - let mut signature = array![]; + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); + let invalid_len_sig = array!['INVALID_LEN_SIG']; + cheat_signature_global(invalid_len_sig.span()); - signature.append(0x1); - testing::set_signature(signature.span()); - - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_declare_empty_signature() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); let empty_sig = array![]; + cheat_signature_global(empty_sig.span()); - testing::set_signature(empty_sig.span()); - - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } fn test_execute_with_version(version: Option) { - let data = SIGNED_TX_DATA(); - let account = setup_dispatcher(Option::Some(@data)); + let key_pair = KEY_PAIR(); + let (account, _) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); let erc20 = deploy_erc20(account.contract_address, 1000); - let recipient = contract_address_const::<0x123>(); + let recipient = RECIPIENT(); // Craft call and add to calls array let mut calldata = array![]; @@ -216,12 +208,11 @@ fn test_execute_with_version(version: Option) { let call = Call { to: erc20.contract_address, selector: selectors::transfer, calldata: calldata.span() }; - let mut calls = array![]; - calls.append(call); + let calls = array![call]; // Handle version for test - if version.is_some() { - testing::set_version(version.unwrap()); + if let Option::Some(version) = version { + cheat_transaction_version_global(version); } // Execute @@ -239,7 +230,7 @@ fn test_execute_with_version(version: Option) { #[test] fn test_execute() { - test_execute_with_version(Option::None(())); + test_execute_with_version(Option::None); } #[test] @@ -253,7 +244,7 @@ fn test_execute_query_version() { } #[test] -#[should_panic(expected: ('Account: invalid tx version', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid tx version',))] fn test_execute_invalid_query_version() { test_execute_with_version(Option::Some(QUERY_OFFSET)); } @@ -264,38 +255,40 @@ fn test_execute_future_query_version() { } #[test] -#[should_panic(expected: ('Account: invalid tx version', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid tx version',))] fn test_execute_invalid_version() { test_execute_with_version(Option::Some(MIN_TRANSACTION_VERSION - 1)); } #[test] fn test_validate() { + let key_pair = KEY_PAIR(); + let (account, _) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); let calls = array![]; - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); let is_valid = account.__validate__(calls); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_invalid() { + let key_pair = KEY_PAIR(); + let mut data = SIGNED_TX_DATA(key_pair); + data.tx_hash += 1; + let (account, _) = setup_dispatcher(key_pair, data); let calls = array![]; - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher(Option::Some(@data)); account.__validate__(calls); } #[test] fn test_multicall() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); + let key_pair = KEY_PAIR(); + let (account, _) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); let erc20 = deploy_erc20(account.contract_address, 1000); - let recipient1 = contract_address_const::<0x123>(); - let recipient2 = contract_address_const::<0x456>(); - let mut calls = array![]; + let recipient1 = RECIPIENT(); + let recipient2 = OTHER(); // Craft call1 let mut calldata1 = array![]; @@ -316,8 +309,7 @@ fn test_multicall() { }; // Bundle calls and exeute - calls.append(call1); - calls.append(call2); + let calls = array![call1, call2]; let ret = account.__execute__(calls); // Assert that the transfers were successful @@ -338,8 +330,9 @@ fn test_multicall() { #[test] fn test_multicall_zero_calls() { - let account = setup_dispatcher(Option::Some(@SIGNED_TX_DATA())); - let mut calls = array![]; + let key_pair = KEY_PAIR(); + let (account, _) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); + let calls = array![]; let response = account.__execute__(calls); assert!(response.is_empty()); @@ -348,12 +341,11 @@ fn test_multicall_zero_calls() { #[test] #[should_panic(expected: ('Account: invalid caller',))] fn test_account_called_from_contract() { - let state = setup(); + let state = setup(KEY_PAIR()); + let account_address = test_address(); let calls = array![]; - let caller = contract_address_const::<0x123>(); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(caller); + start_cheat_caller_address(account_address, CALLER()); state.__execute__(calls); } @@ -365,33 +357,36 @@ fn test_account_called_from_contract() { #[test] fn test_public_key_setter_and_getter() { let mut state = COMPONENT_STATE(); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(ACCOUNT_ADDRESS()); + let account_address = test_address(); + let key_pair = KEY_PAIR(); + let new_key_pair = KEY_PAIR_2(); + start_cheat_caller_address(account_address, account_address); - state._set_public_key(PUBKEY); - utils::drop_event(ACCOUNT_ADDRESS()); - let public_key = state.get_public_key(); - assert_eq!(public_key, PUBKEY); + state._set_public_key(key_pair.public_key); + assert_eq!(state.get_public_key(), key_pair.public_key); // Set key - state.set_public_key(NEW_PUBKEY, get_accept_ownership_signature()); + let mut spy = spy_events(); + let signature = get_accept_ownership_signature( + account_address, key_pair.public_key, new_key_pair + ); + state.set_public_key(new_key_pair.public_key, signature); - assert_event_owner_removed(ACCOUNT_ADDRESS(), PUBKEY); - assert_only_event_owner_added(ACCOUNT_ADDRESS(), NEW_PUBKEY); + spy.assert_event_owner_removed(account_address, key_pair.public_key); + spy.assert_only_event_owner_added(account_address, new_key_pair.public_key); - let public_key = state.get_public_key(); - assert_eq!(public_key, NEW_PUBKEY); + assert_eq!(state.get_public_key(), new_key_pair.public_key); } #[test] #[should_panic(expected: ('Account: unauthorized',))] fn test_public_key_setter_different_account() { let mut state = COMPONENT_STATE(); - let caller = contract_address_const::<0x123>(); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(caller); + let account_address = test_address(); + let new_public_key = KEY_PAIR_2().public_key; + start_cheat_caller_address(account_address, CALLER()); - state.set_public_key(NEW_PUBKEY, array![].span()); + state.set_public_key(new_public_key, array![].span()); } // @@ -401,33 +396,36 @@ fn test_public_key_setter_different_account() { #[test] fn test_public_key_setter_and_getter_camel() { let mut state = COMPONENT_STATE(); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(ACCOUNT_ADDRESS()); + let account_address = test_address(); + let key_pair = KEY_PAIR(); + let new_key_pair = KEY_PAIR_2(); + start_cheat_caller_address(account_address, account_address); - state._set_public_key(PUBKEY); - utils::drop_event(ACCOUNT_ADDRESS()); - let public_key = state.getPublicKey(); - assert_eq!(public_key, PUBKEY); + state._set_public_key(key_pair.public_key); + assert_eq!(state.getPublicKey(), key_pair.public_key); // Set key - state.setPublicKey(NEW_PUBKEY, get_accept_ownership_signature()); + let mut spy = spy_events(); + let signature = get_accept_ownership_signature( + account_address, key_pair.public_key, new_key_pair + ); + state.setPublicKey(new_key_pair.public_key, signature); - assert_event_owner_removed(ACCOUNT_ADDRESS(), PUBKEY); - assert_only_event_owner_added(ACCOUNT_ADDRESS(), NEW_PUBKEY); + spy.assert_event_owner_removed(account_address, key_pair.public_key); + spy.assert_only_event_owner_added(account_address, new_key_pair.public_key); - let public_key = state.getPublicKey(); - assert_eq!(public_key, NEW_PUBKEY); + assert_eq!(state.getPublicKey(), new_key_pair.public_key); } #[test] #[should_panic(expected: ('Account: unauthorized',))] fn test_public_key_setter_different_account_camel() { let mut state = COMPONENT_STATE(); - let caller = contract_address_const::<0x123>(); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(caller); + let account_address = test_address(); + let new_public_key = KEY_PAIR_2().public_key; + start_cheat_caller_address(account_address, CALLER()); - state.setPublicKey(NEW_PUBKEY, array![].span()); + state.setPublicKey(new_public_key, array![].span()); } // @@ -438,12 +436,14 @@ fn test_public_key_setter_different_account_camel() { fn test_initializer() { let mut state = COMPONENT_STATE(); let mock_state = CONTRACT_STATE(); + let account_address = test_address(); + let public_key = KEY_PAIR().public_key; + let mut spy = spy_events(); - state.initializer(PUBKEY); - assert_only_event_owner_added(ZERO(), PUBKEY); + state.initializer(public_key); + spy.assert_only_event_owner_added(account_address, public_key); - let public_key = state.get_public_key(); - assert_eq!(public_key, PUBKEY); + assert_eq!(state.get_public_key(), public_key); let supports_isrc5 = mock_state.supports_interface(ISRC5_ID); assert!(supports_isrc5); @@ -455,9 +455,9 @@ fn test_initializer() { #[test] fn test_assert_only_self_true() { let mut state = COMPONENT_STATE(); + let account_address = test_address(); + start_cheat_caller_address(account_address, account_address); - testing::set_contract_address(ACCOUNT_ADDRESS()); - testing::set_caller_address(ACCOUNT_ADDRESS()); state.assert_only_self(); } @@ -465,88 +465,67 @@ fn test_assert_only_self_true() { #[should_panic(expected: ('Account: unauthorized',))] fn test_assert_only_self_false() { let mut state = COMPONENT_STATE(); + let account_address = test_address(); + start_cheat_caller_address(account_address, OTHER()); - testing::set_contract_address(ACCOUNT_ADDRESS()); - let other = contract_address_const::<0x4567>(); - testing::set_caller_address(other); state.assert_only_self(); } #[test] fn test_assert_valid_new_owner() { - let state = setup(); + let key_pair = KEY_PAIR(); + let state = setup(key_pair); + let account_address = test_address(); + + let new_key_pair = KEY_PAIR_2(); + let signature = get_accept_ownership_signature( + account_address, key_pair.public_key, new_key_pair + ); - testing::set_contract_address(ACCOUNT_ADDRESS()); - state.assert_valid_new_owner(PUBKEY, NEW_PUBKEY, get_accept_ownership_signature()); + state.assert_valid_new_owner(key_pair.public_key, new_key_pair.public_key, signature); } #[test] #[should_panic(expected: ('Account: invalid signature',))] fn test_assert_valid_new_owner_invalid_signature() { - let state = setup(); + let key_pair = KEY_PAIR(); + let state = setup(key_pair); - testing::set_contract_address(ACCOUNT_ADDRESS()); - let bad_signature = array![ - 0x2ce8fbcf8a793ee5b2a57254dc96863b696698943e3bc7845285f3851336318, - 0x6009f5720649ff1ceb0aba44f85bec3572c81aecb9d2dada7c0cc70b791debe - ]; - state.assert_valid_new_owner(PUBKEY, NEW_PUBKEY, bad_signature.span()); + let new_key_pair = KEY_PAIR_2(); + let bad_signature = array!['BAD', 'SIGNATURE']; + + state + .assert_valid_new_owner(key_pair.public_key, new_key_pair.public_key, bad_signature.span()); } #[test] fn test__is_valid_signature() { let mut state = COMPONENT_STATE(); - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; + let key_pair = KEY_PAIR(); + let data = SIGNED_TX_DATA(key_pair); - let mut good_signature = array![data.r, data.s]; - let mut bad_signature = array![0x987, 0x564]; - let mut invalid_length_signature = array![0x987]; + state._set_public_key(key_pair.public_key); - state._set_public_key(data.public_key); + let good_signature = array![data.r, data.s]; + assert!(state._is_valid_signature(data.tx_hash, good_signature.span())); - let is_valid = state._is_valid_signature(hash, good_signature.span()); - assert!(is_valid); + let bad_signature = array!['BAD', 'SIGNATURE']; + assert!(!state._is_valid_signature(data.tx_hash, bad_signature.span())); - let is_not_valid = !state._is_valid_signature(hash, bad_signature.span()); - assert!(is_not_valid); - - let is_not_valid = !state._is_valid_signature(hash, invalid_length_signature.span()); - assert!(is_not_valid); + let invalid_length_signature = array!['SINGLE_ELEMENT']; + assert!(!state._is_valid_signature(data.tx_hash, invalid_length_signature.span())); } #[test] fn test__set_public_key() { let mut state = COMPONENT_STATE(); - state._set_public_key(PUBKEY); - - assert_only_event_owner_added(ZERO(), PUBKEY); + let mut spy = spy_events(); + let public_key = KEY_PAIR().public_key; + let account_address = test_address(); - let public_key = state.get_public_key(); - assert_eq!(public_key, PUBKEY); -} - -// -// Helpers -// + state._set_public_key(public_key); -fn get_accept_ownership_signature() -> Span { - // 0x7b3d2ce38c132a36e692f6e809b518276d091513af3baf0e94ce2abceee3632 = - // PoseidonTrait::new() - // .update_with('StarkNet Message') - // .update_with('accept_ownership') - // .update_with(ACCOUNT_ADDRESS()) - // .update_with(PUBKEY) - // .finalize(); - - // This signature was computed using starknet js sdk from the following values: - // - private_key: '1234' - // - public_key: 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7 - // - msg_hash: 0x7b3d2ce38c132a36e692f6e809b518276d091513af3baf0e94ce2abceee3632 - array![ - 0x1ce8fbcf8a793ee5b2a57254dc96863b696698943e3bc7845285f3851336318, - 0x6009f5720649ff1ceb0aba44f85bec3572c81aecb9d2dada7c0cc70b791debe - ] - .span() + spy.assert_only_event_owner_added(account_address, public_key); + assert_eq!(state.get_public_key(), public_key); } diff --git a/src/tests/account/starknet/test_dual_account.cairo b/src/tests/account/starknet/test_dual_account.cairo index 003075b1f..ab0887896 100644 --- a/src/tests/account/starknet/test_dual_account.cairo +++ b/src/tests/account/starknet/test_dual_account.cairo @@ -2,45 +2,39 @@ use openzeppelin::account::dual_account::{DualCaseAccountABI, DualCaseAccount}; use openzeppelin::account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; use openzeppelin::introspection::interface::ISRC5_ID; use openzeppelin::tests::account::starknet::common::SIGNED_TX_DATA; -use openzeppelin::tests::mocks::account_mocks::{ - CamelAccountPanicMock, CamelAccountMock, SnakeAccountMock, SnakeAccountPanicMock -}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::{PUBKEY, NEW_PUBKEY}; +use openzeppelin::tests::utils::constants::TRANSACTION_HASH; +use openzeppelin::tests::utils::constants::stark::{KEY_PAIR, KEY_PAIR_2}; +use openzeppelin::tests::utils::signing::{StarkKeyPair, StarkKeyPairExt}; use openzeppelin::tests::utils; -use starknet::testing; +use snforge_std::{declare, start_cheat_caller_address}; + +use super::common::get_accept_ownership_signature; // // Setup // -fn setup_snake() -> (DualCaseAccount, AccountABIDispatcher) { - let mut calldata = array![PUBKEY]; - let target = utils::deploy(SnakeAccountMock::TEST_CLASS_HASH, calldata); - ( - DualCaseAccount { contract_address: target }, - AccountABIDispatcher { contract_address: target } - ) +fn setup_snake(key_pair: StarkKeyPair) -> (DualCaseAccount, AccountABIDispatcher) { + let calldata = array![key_pair.public_key]; + let contract_address = utils::declare_and_deploy("SnakeAccountMock", calldata); + (DualCaseAccount { contract_address }, AccountABIDispatcher { contract_address }) } -fn setup_camel() -> (DualCaseAccount, AccountABIDispatcher) { - let mut calldata = array![PUBKEY]; - let target = utils::deploy(CamelAccountMock::TEST_CLASS_HASH, calldata); - ( - DualCaseAccount { contract_address: target }, - AccountABIDispatcher { contract_address: target } - ) +fn setup_camel(key_pair: StarkKeyPair) -> (DualCaseAccount, AccountABIDispatcher) { + let calldata = array![key_pair.public_key]; + let contract_address = utils::declare_and_deploy("CamelAccountMock", calldata); + (DualCaseAccount { contract_address }, AccountABIDispatcher { contract_address }) } fn setup_non_account() -> DualCaseAccount { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); - DualCaseAccount { contract_address: target } + let contract_address = utils::declare_and_deploy("NonImplementingMock", calldata); + DualCaseAccount { contract_address } } fn setup_account_panic() -> (DualCaseAccount, DualCaseAccount) { - let snake_target = utils::deploy(SnakeAccountPanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelAccountPanicMock::TEST_CLASS_HASH, array![]); + let snake_target = utils::declare_and_deploy("SnakeAccountPanicMock", array![]); + let camel_target = utils::declare_and_deploy("CamelAccountPanicMock", array![]); ( DualCaseAccount { contract_address: snake_target }, DualCaseAccount { contract_address: camel_target } @@ -53,38 +47,46 @@ fn setup_account_panic() -> (DualCaseAccount, DualCaseAccount) { #[test] fn test_dual_set_public_key() { - let (snake_dispatcher, target) = setup_snake(); + let key_pair = KEY_PAIR(); + let (snake_dispatcher, target) = setup_snake(key_pair); + let new_key_pair = KEY_PAIR_2(); + let signature = get_accept_ownership_signature( + snake_dispatcher.contract_address, key_pair.public_key, new_key_pair + ); + start_cheat_caller_address(target.contract_address, target.contract_address); - testing::set_contract_address(snake_dispatcher.contract_address); + snake_dispatcher.set_public_key(new_key_pair.public_key, signature); - snake_dispatcher.set_public_key(NEW_PUBKEY, get_accept_ownership_signature_snake()); - - let public_key = target.get_public_key(); - assert_eq!(public_key, NEW_PUBKEY); + assert_eq!(target.get_public_key(), new_key_pair.public_key); } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_set_public_key() { let dispatcher = setup_non_account(); - dispatcher.set_public_key(NEW_PUBKEY, array![].span()); + let new_public_key = KEY_PAIR_2().public_key; + dispatcher.set_public_key(new_public_key, array![].span()); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_set_public_key_exists_and_panics() { - let (dispatcher, _) = setup_account_panic(); - dispatcher.set_public_key(NEW_PUBKEY, array![].span()); + let (snake_dispatcher, _) = setup_account_panic(); + let new_public_key = KEY_PAIR_2().public_key; + snake_dispatcher.set_public_key(new_public_key, array![].span()); } #[test] fn test_dual_get_public_key() { - let (snake_dispatcher, _) = setup_snake(); - let public_key = snake_dispatcher.get_public_key(); - assert_eq!(public_key, PUBKEY); + let key_pair = KEY_PAIR(); + let (snake_dispatcher, _) = setup_snake(key_pair); + let expected_public_key = key_pair.public_key; + assert_eq!(snake_dispatcher.get_public_key(), expected_public_key); } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_get_public_key() { let dispatcher = setup_non_account(); @@ -92,55 +94,51 @@ fn test_dual_no_get_public_key() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_get_public_key_exists_and_panics() { - let (dispatcher, _) = setup_account_panic(); - dispatcher.get_public_key(); + let (snake_dispatcher, _) = setup_account_panic(); + snake_dispatcher.get_public_key(); } #[test] fn test_dual_is_valid_signature() { - let (snake_dispatcher, target) = setup_snake(); - - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; - let mut signature = array![data.r, data.s]; + let key_pair = KEY_PAIR(); + let (snake_dispatcher, _) = setup_snake(key_pair); + let tx_hash = TRANSACTION_HASH; + let serialized_signature = key_pair.serialized_sign(tx_hash); - testing::set_contract_address(snake_dispatcher.contract_address); - target.set_public_key(data.public_key, get_accept_ownership_signature_snake()); - - let is_valid = snake_dispatcher.is_valid_signature(hash, signature); + let is_valid = snake_dispatcher.is_valid_signature(tx_hash, serialized_signature); assert_eq!(is_valid, starknet::VALIDATED); } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_is_valid_signature() { - let hash = 0x0; let signature = array![]; let dispatcher = setup_non_account(); - dispatcher.is_valid_signature(hash, signature); + dispatcher.is_valid_signature(TRANSACTION_HASH, signature); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_is_valid_signature_exists_and_panics() { - let hash = 0x0; let signature = array![]; + let (snake_dispatcher, _) = setup_account_panic(); - let (dispatcher, _) = setup_account_panic(); - dispatcher.is_valid_signature(hash, signature); + snake_dispatcher.is_valid_signature(TRANSACTION_HASH, signature); } #[test] fn test_dual_supports_interface() { - let (snake_dispatcher, _) = setup_snake(); + let (snake_dispatcher, _) = setup_snake(KEY_PAIR()); let supports_isrc5 = snake_dispatcher.supports_interface(ISRC5_ID); assert!(supports_isrc5); } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_dual_no_supports_interface() { let dispatcher = setup_non_account(); @@ -148,10 +146,10 @@ fn test_dual_no_supports_interface() { } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ("Some error",))] fn test_dual_supports_interface_exists_and_panics() { - let (dispatcher, _) = setup_account_panic(); - dispatcher.supports_interface(ISRC5_ID); + let (snake_dispatcher, _) = setup_account_panic(); + snake_dispatcher.supports_interface(ISRC5_ID); } // @@ -159,102 +157,65 @@ fn test_dual_supports_interface_exists_and_panics() { // #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_setPublicKey() { - let (camel_dispatcher, target) = setup_camel(); + let key_pair = KEY_PAIR(); + let (camel_dispatcher, target) = setup_camel(key_pair); + let new_key_pair = KEY_PAIR_2(); + let signature = get_accept_ownership_signature( + camel_dispatcher.contract_address, key_pair.public_key, new_key_pair + ); + start_cheat_caller_address(target.contract_address, target.contract_address); - testing::set_contract_address(camel_dispatcher.contract_address); - camel_dispatcher.set_public_key(NEW_PUBKEY, get_accept_ownership_signature_camel()); + camel_dispatcher.set_public_key(new_key_pair.public_key, signature); - let public_key = target.getPublicKey(); - assert_eq!(public_key, NEW_PUBKEY); + assert_eq!(target.getPublicKey(), new_key_pair.public_key); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_setPublicKey_exists_and_panics() { - let (_, dispatcher) = setup_account_panic(); - dispatcher.set_public_key(NEW_PUBKEY, array![].span()); + let (_, camel_dispatcher) = setup_account_panic(); + let new_public_key = KEY_PAIR_2().public_key; + camel_dispatcher.set_public_key(new_public_key, array![].span()); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_getPublicKey() { - let (camel_dispatcher, _) = setup_camel(); - let public_key = camel_dispatcher.get_public_key(); - assert_eq!(public_key, PUBKEY); + let key_pair = KEY_PAIR(); + let (camel_dispatcher, _) = setup_camel(key_pair); + let expected_public_key = key_pair.public_key; + assert_eq!(camel_dispatcher.get_public_key(), expected_public_key); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_getPublicKey_exists_and_panics() { - let (_, dispatcher) = setup_account_panic(); - dispatcher.get_public_key(); + let (_, camel_dispatcher) = setup_account_panic(); + camel_dispatcher.get_public_key(); } #[test] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. fn test_dual_isValidSignature() { - let (camel_dispatcher, target) = setup_camel(); - - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; - let signature = array![data.r, data.s]; - - testing::set_contract_address(camel_dispatcher.contract_address); - target.setPublicKey(data.public_key, get_accept_ownership_signature_camel()); + let key_pair = KEY_PAIR(); + let (camel_dispatcher, _) = setup_camel(key_pair); + let tx_hash = TRANSACTION_HASH; + let serialized_signature = key_pair.serialized_sign(tx_hash); - let is_valid = camel_dispatcher.is_valid_signature(hash, signature); + let is_valid = camel_dispatcher.is_valid_signature(tx_hash, serialized_signature); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ("Some error", 'ENTRYPOINT_FAILED',))] +#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. +#[should_panic(expected: ("Some error",))] fn test_dual_isValidSignature_exists_and_panics() { - let hash = 0x0; let signature = array![]; - let (_, dispatcher) = setup_account_panic(); - dispatcher.is_valid_signature(hash, signature); -} - -// -// Helpers -// - -fn get_accept_ownership_signature_snake() -> Span { - // 0x26a14ae81fad8adcb81337e49fd68ac44d508cfca09c4a6167c71e85759e98d = - // PoseidonTrait::new() - // .update_with('StarkNet Message') - // .update_with('accept_ownership') - // .update_with(snake_dispatcher.contract_address) - // .update_with(PUBKEY) - // .finalize(); - - // This signature was computed using starknet js sdk from the following values: - // - private_key: '1234' - // - public_key: 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7 - // - msg_hash: 0x26a14ae81fad8adcb81337e49fd68ac44d508cfca09c4a6167c71e85759e98d - array![ - 0x14de5d99a3a43bc7e8e0ddf8ff72fab172798ac3dd7bd858d4f6f489a2a4bcb, - 0x88dd5cb7f27a8932a5c6d226b486830e952e3d9e78996e7ca2315afa9c0be2 - ] - .span() -} - -fn get_accept_ownership_signature_camel() -> Span { - // 0x1e2acd787c2778bebfbf4d8770fdc0834db1576b5fd190f35afae5a6f7f469f = - // PoseidonTrait::new() - // .update_with('StarkNet Message') - // .update_with('accept_ownership') - // .update_with(camel_dispatcher.contract_address) - // .update_with(PUBKEY) - // .finalize(); - - // This signature was computed using starknet js sdk from the following values: - // - private_key: '1234' - // - public_key: 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7 - // - msg_hash: 0x1e2acd787c2778bebfbf4d8770fdc0834db1576b5fd190f35afae5a6f7f469f - array![ - 0xd0eab69db72a46ee0fb39c833cfaec035ca809eb884285d0e603262f15e0dd, - 0x768e984a96d5f731c3cf1660c5a00f508f3d99d8240bf3ba4c3e69561a545d1 - ] - .span() + let (_, camel_dispatcher) = setup_account_panic(); + camel_dispatcher.is_valid_signature(TRANSACTION_HASH, signature); } diff --git a/src/tests/account/test_signature.cairo b/src/tests/account/test_signature.cairo index 7da6fe741..548afb817 100644 --- a/src/tests/account/test_signature.cairo +++ b/src/tests/account/test_signature.cairo @@ -1,5 +1,5 @@ use openzeppelin::account::utils::signature::{is_valid_stark_signature, is_valid_eth_signature}; -use openzeppelin::tests::utils::constants::secp256k1::KEY_PAIR; +use openzeppelin::tests::utils::constants::{stark, secp256k1}; use starknet::secp256_trait::Secp256Trait; use starknet::secp256k1::Secp256k1Point; @@ -12,34 +12,31 @@ use super::starknet::common::SIGNED_TX_DATA as stark_signature_data; #[test] fn test_is_valid_stark_signature_good_sig() { - let data = stark_signature_data(); - let hash = data.tx_hash; + let key_pair = stark::KEY_PAIR(); + let data = stark_signature_data(key_pair); + let good_signature = array![data.r, data.s].span(); - let mut good_signature = array![data.r, data.s].span(); - - let is_valid = is_valid_stark_signature(hash, data.public_key, good_signature); + let is_valid = is_valid_stark_signature(data.tx_hash, key_pair.public_key, good_signature); assert!(is_valid); } #[test] fn test_is_valid_stark_signature_bad_sig() { - let data = stark_signature_data(); - let hash = data.tx_hash; - - let mut bad_signature = array![0x987, 0x564].span(); + let key_pair = stark::KEY_PAIR(); + let data = stark_signature_data(key_pair); + let bad_signature = array!['BAD', 'SIGNATURE'].span(); - let is_invalid = !is_valid_stark_signature(hash, data.public_key, bad_signature); + let is_invalid = !is_valid_stark_signature(data.tx_hash, key_pair.public_key, bad_signature); assert!(is_invalid); } #[test] fn test_is_valid_stark_signature_invalid_len_sig() { - let data = stark_signature_data(); - let hash = data.tx_hash; - - let mut bad_signature = array![0x987].span(); + let key_pair = stark::KEY_PAIR(); + let data = stark_signature_data(key_pair); + let bad_signature = array!['BAD_SIGNATURE'].span(); - let is_invalid = !is_valid_stark_signature(hash, data.public_key, bad_signature); + let is_invalid = !is_valid_stark_signature(data.tx_hash, key_pair.public_key, bad_signature); assert!(is_invalid); } @@ -49,21 +46,20 @@ fn test_is_valid_stark_signature_invalid_len_sig() { #[test] fn test_is_valid_eth_signature_good_sig() { - let data = eth_signature_data(KEY_PAIR()); - let hash = data.tx_hash; + let data = eth_signature_data(secp256k1::KEY_PAIR()); let mut serialized_good_signature = array![]; - data.signature.serialize(ref serialized_good_signature); - let is_valid = is_valid_eth_signature(hash, data.public_key, serialized_good_signature.span()); + let is_valid = is_valid_eth_signature( + data.tx_hash, data.public_key, serialized_good_signature.span() + ); assert!(is_valid); } #[test] fn test_is_valid_eth_signature_bad_sig() { - let data = eth_signature_data(KEY_PAIR()); - let hash = data.tx_hash; + let data = eth_signature_data(secp256k1::KEY_PAIR()); let mut bad_signature = data.signature; bad_signature.r += 1; @@ -73,7 +69,7 @@ fn test_is_valid_eth_signature_bad_sig() { bad_signature.serialize(ref serialized_bad_signature); let is_invalid = !is_valid_eth_signature( - hash, data.public_key, serialized_bad_signature.span() + data.tx_hash, data.public_key, serialized_bad_signature.span() ); assert!(is_invalid); } @@ -81,18 +77,15 @@ fn test_is_valid_eth_signature_bad_sig() { #[test] #[should_panic(expected: ('Signature: Invalid format.',))] fn test_is_valid_eth_signature_invalid_format_sig() { - let data = eth_signature_data(KEY_PAIR()); - let hash = data.tx_hash; - + let data = eth_signature_data(secp256k1::KEY_PAIR()); let mut serialized_bad_signature = array![0x1]; - is_valid_eth_signature(hash, data.public_key, serialized_bad_signature.span()); + is_valid_eth_signature(data.tx_hash, data.public_key, serialized_bad_signature.span()); } #[test] fn test_signature_r_out_of_range() { - let data = eth_signature_data(KEY_PAIR()); - let hash = data.tx_hash; + let data = eth_signature_data(secp256k1::KEY_PAIR()); let mut bad_signature = data.signature; let curve_size = Secp256Trait::::get_curve_size(); @@ -104,15 +97,14 @@ fn test_signature_r_out_of_range() { bad_signature.serialize(ref serialized_bad_signature); let is_invalid = !is_valid_eth_signature( - hash, data.public_key, serialized_bad_signature.span() + data.tx_hash, data.public_key, serialized_bad_signature.span() ); assert!(is_invalid); } #[test] fn test_signature_s_out_of_range() { - let data = eth_signature_data(KEY_PAIR()); - let hash = data.tx_hash; + let data = eth_signature_data(secp256k1::KEY_PAIR()); let mut bad_signature = data.signature; let curve_size = Secp256Trait::::get_curve_size(); @@ -124,7 +116,7 @@ fn test_signature_s_out_of_range() { bad_signature.serialize(ref serialized_bad_signature); let is_invalid = !is_valid_eth_signature( - hash, data.public_key, serialized_bad_signature.span() + data.tx_hash, data.public_key, serialized_bad_signature.span() ); assert!(is_invalid); } diff --git a/src/tests/utils/constants.cairo b/src/tests/utils/constants.cairo index 2259ef968..4d8df0911 100644 --- a/src/tests/utils/constants.cairo +++ b/src/tests/utils/constants.cairo @@ -124,13 +124,25 @@ pub(crate) fn EMPTY_DATA() -> Span { pub(crate) mod secp256k1 { use openzeppelin::tests::utils::signing::{Secp256k1KeyPair, get_secp256k1_keys_from}; - pub(crate) const PRIVATE_KEY: u256 = u256 { low: 'PRIVATE_LOW', high: 'PRIVATE_HIGH' }; pub(crate) fn KEY_PAIR() -> Secp256k1KeyPair { - get_secp256k1_keys_from(PRIVATE_KEY) + let private_key = u256 { low: 'PRIVATE_LOW', high: 'PRIVATE_HIGH' }; + get_secp256k1_keys_from(private_key) } - pub(crate) const PRIVATE_KEY_2: u256 = u256 { low: 'PRIVATE_LOW_2', high: 'PRIVATE_HIGH_2' }; pub(crate) fn KEY_PAIR_2() -> Secp256k1KeyPair { - get_secp256k1_keys_from(PRIVATE_KEY_2) + let private_key = u256 { low: 'PRIVATE_LOW_2', high: 'PRIVATE_HIGH_2' }; + get_secp256k1_keys_from(private_key) + } +} + +pub(crate) mod stark { + use openzeppelin::tests::utils::signing::{StarkKeyPair, get_stark_keys_from}; + + pub(crate) fn KEY_PAIR() -> StarkKeyPair { + get_stark_keys_from('PRIVATE_KEY') + } + + pub(crate) fn KEY_PAIR_2() -> StarkKeyPair { + get_stark_keys_from('PRIVATE_KEY_2') } } diff --git a/src/tests/utils/signing.cairo b/src/tests/utils/signing.cairo index ee596c8d0..8b1e7ca44 100644 --- a/src/tests/utils/signing.cairo +++ b/src/tests/utils/signing.cairo @@ -14,6 +14,14 @@ pub fn get_secp256k1_keys_from(private_key: u256) -> Secp256k1KeyPair { Secp256k1CurveKeyPairImpl::from_secret_key(private_key) } +#[generate_trait] +pub impl StarkKeyPairExt of StarkKeyPairExtTrait { + fn serialized_sign(self: StarkKeyPair, msg: felt252) -> Array { + let (r, s) = self.sign(msg).unwrap(); + array![r, s] + } +} + #[generate_trait] pub impl Secp256k1KeyPairExt of Secp256k1KeyPairExtTrait { fn serialized_sign(self: Secp256k1KeyPair, msg: u256) -> Array { From 852c43b58ec500b93486399648202ca676da22bd Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 26 Jul 2024 13:23:53 +0200 Subject: [PATCH 20/45] feat: make contracts build --- Scarb.lock | 19 ++++++++------- Scarb.toml | 4 ++-- packages/access/Scarb.toml | 7 ++---- packages/account/Scarb.toml | 7 ++---- packages/account/src/dual_eth_account.cairo | 10 ++++---- packages/account/src/eth_account.cairo | 16 ++++++------- packages/governance/Scarb.toml | 8 +++---- .../governance/src/timelock/interface.cairo | 2 +- .../src/timelock/timelock_controller.cairo | 16 ++++++------- packages/introspection/Scarb.toml | 4 ++-- packages/introspection/src/src5.cairo | 3 ++- packages/presets/Scarb.toml | 4 ++-- packages/presets/src/eth_account.cairo | 10 ++++---- .../presets/src/interfaces/eth_account.cairo | 2 +- packages/security/Scarb.toml | 4 ++-- packages/token/Scarb.toml | 4 ++-- packages/upgrades/Scarb.toml | 4 ++-- packages/utils/Scarb.toml | 4 ++-- packages/utils/src/structs/checkpoint.cairo | 4 ++-- src/lib.cairo | 2 +- .../ethereum/test_dual_eth_account.cairo | 10 ++++---- .../account/ethereum/test_eth_account.cairo | 18 +++++++------- src/tests/account/test_secp256k1.cairo | 2 +- src/tests/governance/test_timelock.cairo | 24 +++++++++---------- src/tests/governance/test_utils.cairo | 2 +- src/tests/mocks/eth_account_mocks.cairo | 22 ++++++++--------- src/tests/mocks/timelock_mocks.cairo | 8 +++---- src/tests/presets/test_eth_account.cairo | 8 +++---- src/tests/token/erc1155/test_erc1155.cairo | 4 ++-- 29 files changed, 113 insertions(+), 119 deletions(-) diff --git a/Scarb.lock b/Scarb.lock index 1327fcc71..91c58cb42 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "openzeppelin_access" -version = "0.1.0" +version = "0.15.0-rc.0" dependencies = [ "openzeppelin_introspection", "openzeppelin_utils", @@ -11,7 +11,7 @@ dependencies = [ [[package]] name = "openzeppelin_account" -version = "0.1.0" +version = "0.15.0-rc.0" dependencies = [ "openzeppelin_introspection", "openzeppelin_utils", @@ -19,19 +19,20 @@ dependencies = [ [[package]] name = "openzeppelin_governance" -version = "0.1.0" +version = "0.15.0-rc.0" dependencies = [ + "openzeppelin_access", "openzeppelin_introspection", "openzeppelin_utils", ] [[package]] name = "openzeppelin_introspection" -version = "0.1.0" +version = "0.15.0-rc.0" [[package]] name = "openzeppelin_presets" -version = "0.1.0" +version = "0.15.0-rc.0" dependencies = [ "openzeppelin_access", "openzeppelin_account", @@ -42,11 +43,11 @@ dependencies = [ [[package]] name = "openzeppelin_security" -version = "0.1.0" +version = "0.15.0-rc.0" [[package]] name = "openzeppelin_token" -version = "0.1.0" +version = "0.15.0-rc.0" dependencies = [ "openzeppelin_account", "openzeppelin_governance", @@ -55,8 +56,8 @@ dependencies = [ [[package]] name = "openzeppelin_upgrades" -version = "0.1.0" +version = "0.15.0-rc.0" [[package]] name = "openzeppelin_utils" -version = "0.1.0" +version = "0.15.0-rc.0" diff --git a/Scarb.toml b/Scarb.toml index 961d63a5b..89f0f74d4 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -30,10 +30,10 @@ keywords = [ "standards", ] -[dependencies] +[workspace.dependencies] starknet = "2.7.0-rc.3" -[dev-dependencies] +[workspace.dev-dependencies] cairo_test = "2.7.0-rc.3" [lib] diff --git a/packages/access/Scarb.toml b/packages/access/Scarb.toml index 23e831497..8d5f86ff0 100644 --- a/packages/access/Scarb.toml +++ b/packages/access/Scarb.toml @@ -1,15 +1,12 @@ - [package] name = "openzeppelin_access" -version = "0.1.0" -description = "" -homepage = "" +version = "0.15.0-rc.0" edition = "2023_11" [tool] fmt.workspace = true [dependencies] -starknet = "2.6.4" +starknet = "2.7.0-rc.3" openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } diff --git a/packages/account/Scarb.toml b/packages/account/Scarb.toml index 04b44efbe..e2d3b14b9 100644 --- a/packages/account/Scarb.toml +++ b/packages/account/Scarb.toml @@ -1,15 +1,12 @@ - [package] name = "openzeppelin_account" -version = "0.1.0" -description = "" -homepage = "" +version = "0.15.0-rc.0" edition = "2023_11" [tool] fmt.workspace = true [dependencies] -starknet = "2.6.4" +starknet = "2.7.0-rc.3" openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } diff --git a/packages/account/src/dual_eth_account.cairo b/packages/account/src/dual_eth_account.cairo index 22cd39f9e..182797209 100644 --- a/packages/account/src/dual_eth_account.cairo +++ b/packages/account/src/dual_eth_account.cairo @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (account/dual_eth_account.cairo) -use openzeppelin::account::interface::EthPublicKey; -use openzeppelin::utils::UnwrapAndCast; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use openzeppelin::utils::try_selector_with_fallback; +use openzeppelin_account::interface::EthPublicKey; +use openzeppelin_utils::UnwrapAndCast; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::syscalls::call_contract_syscall; diff --git a/packages/account/src/eth_account.cairo b/packages/account/src/eth_account.cairo index 61eb038af..1329c2f2b 100644 --- a/packages/account/src/eth_account.cairo +++ b/packages/account/src/eth_account.cairo @@ -10,14 +10,14 @@ pub mod EthAccountComponent { use core::num::traits::Zero; use core::poseidon::{PoseidonTrait, poseidon_hash_span}; use core::starknet::secp256_trait::Secp256PointTrait; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::interface; - use openzeppelin::account::utils::secp256k1::Secp256k1PointStorePacking; - use openzeppelin::account::utils::{MIN_TRANSACTION_VERSION, QUERY_VERSION, QUERY_OFFSET}; - use openzeppelin::account::utils::{execute_calls, is_valid_eth_signature}; - use openzeppelin::introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; - use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_account::interface; + use openzeppelin_account::utils::secp256k1::Secp256k1PointStorePacking; + use openzeppelin_account::utils::{MIN_TRANSACTION_VERSION, QUERY_VERSION, QUERY_OFFSET}; + use openzeppelin_account::utils::{execute_calls, is_valid_eth_signature}; + use openzeppelin_introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; + use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin_introspection::src5::SRC5Component; use starknet::SyscallResultTrait; use starknet::account::Call; use starknet::get_caller_address; diff --git a/packages/governance/Scarb.toml b/packages/governance/Scarb.toml index d1d505f38..59adde024 100644 --- a/packages/governance/Scarb.toml +++ b/packages/governance/Scarb.toml @@ -1,15 +1,13 @@ - [package] name = "openzeppelin_governance" -version = "0.1.0" -description = "" -homepage = "" +version = "0.15.0-rc.0" edition = "2023_11" [tool] fmt.workspace = true [dependencies] -starknet = "2.6.4" +starknet = "2.7.0-rc.3" +openzeppelin_access = { path = "../access" } openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } diff --git a/packages/governance/src/timelock/interface.cairo b/packages/governance/src/timelock/interface.cairo index 0c89d0c20..b228ed664 100644 --- a/packages/governance/src/timelock/interface.cairo +++ b/packages/governance/src/timelock/interface.cairo @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (governance/timelock/interface.cairo) -use openzeppelin::governance::timelock::OperationState; +use openzeppelin_governance::timelock::OperationState; use starknet::ContractAddress; use starknet::account::Call; diff --git a/packages/governance/src/timelock/timelock_controller.cairo b/packages/governance/src/timelock/timelock_controller.cairo index 494692025..40d269622 100644 --- a/packages/governance/src/timelock/timelock_controller.cairo +++ b/packages/governance/src/timelock/timelock_controller.cairo @@ -17,18 +17,18 @@ pub mod TimelockControllerComponent { use core::hash::{HashStateTrait, HashStateExTrait}; use core::num::traits::Zero; use core::pedersen::PedersenTrait; - use openzeppelin::access::accesscontrol::AccessControlComponent::InternalTrait as AccessControlInternalTrait; - use openzeppelin::access::accesscontrol::AccessControlComponent::{ + use openzeppelin_access::accesscontrol::AccessControlComponent::InternalTrait as AccessControlInternalTrait; + use openzeppelin_access::accesscontrol::AccessControlComponent::{ AccessControlImpl, AccessControlCamelImpl }; - use openzeppelin::access::accesscontrol::AccessControlComponent; - use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; - use openzeppelin::governance::timelock::interface::{ITimelock, TimelockABI}; - use openzeppelin::governance::timelock::utils::call_impls::{ + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; + use openzeppelin_governance::timelock::interface::{ITimelock, TimelockABI}; + use openzeppelin_governance::timelock::utils::call_impls::{ HashCallImpl, HashCallsImpl, CallPartialEq }; - use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin_introspection::src5::SRC5Component; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::account::Call; diff --git a/packages/introspection/Scarb.toml b/packages/introspection/Scarb.toml index 29ba1d7d4..9cdfa4415 100644 --- a/packages/introspection/Scarb.toml +++ b/packages/introspection/Scarb.toml @@ -1,7 +1,7 @@ [package] name = "openzeppelin_introspection" -version = "0.1.0" +version = "0.15.0-rc.0" description = "" homepage = "" edition = "2023_11" @@ -10,4 +10,4 @@ edition = "2023_11" fmt.workspace = true [dependencies] -starknet = "2.6.4" +starknet = "2.7.0-rc.3" diff --git a/packages/introspection/src/src5.cairo b/packages/introspection/src/src5.cairo index 7a249d298..52b683fbc 100644 --- a/packages/introspection/src/src5.cairo +++ b/packages/introspection/src/src5.cairo @@ -6,7 +6,8 @@ /// The SRC5 component allows contracts to expose the interfaces they implement. #[starknet::component] pub mod SRC5Component { - use openzeppelin::introspection::interface; + use openzeppelin_introspection::interface; + use starknet::storage::Map; #[storage] struct Storage { diff --git a/packages/presets/Scarb.toml b/packages/presets/Scarb.toml index dd703aa1a..54efc9b90 100644 --- a/packages/presets/Scarb.toml +++ b/packages/presets/Scarb.toml @@ -1,7 +1,7 @@ [package] name = "openzeppelin_presets" -version = "0.1.0" +version = "0.15.0-rc.0" description = "" homepage = "" edition = "2023_11" @@ -10,7 +10,7 @@ edition = "2023_11" fmt.workspace = true [dependencies] -starknet = "2.6.4" +starknet = "2.7.0-rc.3" openzeppelin_access = { path = "../access" } openzeppelin_account = { path = "../account" } openzeppelin_introspection = { path = "../introspection" } diff --git a/packages/presets/src/eth_account.cairo b/packages/presets/src/eth_account.cairo index 97bdbc8b4..b4cdf2080 100644 --- a/packages/presets/src/eth_account.cairo +++ b/packages/presets/src/eth_account.cairo @@ -7,11 +7,11 @@ /// deploy, or call contracts, using Ethereum signing keys. #[starknet::contract(account)] pub(crate) mod EthAccountUpgradeable { - use openzeppelin::account::EthAccountComponent; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::introspection::src5::SRC5Component; - use openzeppelin::upgrades::UpgradeableComponent; - use openzeppelin::upgrades::interface::IUpgradeable; + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_upgrades::UpgradeableComponent; + use openzeppelin_upgrades::interface::IUpgradeable; use starknet::ClassHash; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); diff --git a/packages/presets/src/interfaces/eth_account.cairo b/packages/presets/src/interfaces/eth_account.cairo index ab9af2f69..82a5aae18 100644 --- a/packages/presets/src/interfaces/eth_account.cairo +++ b/packages/presets/src/interfaces/eth_account.cairo @@ -1,4 +1,4 @@ -use openzeppelin::account::interface::EthPublicKey; +use openzeppelin_account::interface::EthPublicKey; use starknet::account::Call; use starknet::{ContractAddress, ClassHash}; diff --git a/packages/security/Scarb.toml b/packages/security/Scarb.toml index c61dcab09..9d65956c6 100644 --- a/packages/security/Scarb.toml +++ b/packages/security/Scarb.toml @@ -1,7 +1,7 @@ [package] name = "openzeppelin_security" -version = "0.1.0" +version = "0.15.0-rc.0" description = "" homepage = "" edition = "2023_11" @@ -10,4 +10,4 @@ edition = "2023_11" fmt.workspace = true [dependencies] -starknet = "2.6.4" +starknet = "2.7.0-rc.3" diff --git a/packages/token/Scarb.toml b/packages/token/Scarb.toml index 3c0bd4f64..97c7479b2 100644 --- a/packages/token/Scarb.toml +++ b/packages/token/Scarb.toml @@ -1,7 +1,7 @@ [package] name = "openzeppelin_token" -version = "0.1.0" +version = "0.15.0-rc.0" description = "" homepage = "" edition = "2023_11" @@ -10,7 +10,7 @@ edition = "2023_11" fmt.workspace = true [dependencies] -starknet = "2.6.4" +starknet = "2.7.0-rc.3" openzeppelin_account = { path = "../account" } openzeppelin_introspection = { path = "../introspection" } openzeppelin_governance = { path = "../governance" } diff --git a/packages/upgrades/Scarb.toml b/packages/upgrades/Scarb.toml index 754d0f126..7b936e853 100644 --- a/packages/upgrades/Scarb.toml +++ b/packages/upgrades/Scarb.toml @@ -1,7 +1,7 @@ [package] name = "openzeppelin_upgrades" -version = "0.1.0" +version = "0.15.0-rc.0" description = "" homepage = "" edition = "2023_11" @@ -10,4 +10,4 @@ edition = "2023_11" fmt.workspace = true [dependencies] -starknet = "2.6.4" +starknet = "2.7.0-rc.3" diff --git a/packages/utils/Scarb.toml b/packages/utils/Scarb.toml index adb37135d..52ccff3f4 100644 --- a/packages/utils/Scarb.toml +++ b/packages/utils/Scarb.toml @@ -1,7 +1,7 @@ [package] name = "openzeppelin_utils" -version = "0.1.0" +version = "0.15.0-rc.0" description = "" homepage = "" edition = "2023_11" @@ -10,4 +10,4 @@ edition = "2023_11" fmt.workspace = true [dependencies] -starknet = "2.6.4" +starknet = "2.7.0-rc.3" diff --git a/packages/utils/src/structs/checkpoint.cairo b/packages/utils/src/structs/checkpoint.cairo index 31d874f94..caff302b4 100644 --- a/packages/utils/src/structs/checkpoint.cairo +++ b/packages/utils/src/structs/checkpoint.cairo @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/structs/checkpoint.cairo) -use core::integer::u32_sqrt; +use core::num::traits::Sqrt; use openzeppelin_utils::math; use starknet::storage_access::StorePacking; use super::storage_array::{StorageArray, StorageArrayTrait}; @@ -55,7 +55,7 @@ pub impl TraceImpl of TraceTrait { let mut high = len; if (len > 5) { - let mid = len - u32_sqrt(len).into(); + let mid = len - len.sqrt().into(); if (key < checkpoints.read_at(mid).key) { high = mid; } else { diff --git a/src/lib.cairo b/src/lib.cairo index 182a000c4..78bf8b567 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -1,4 +1,4 @@ -// pub mod access; +pub mod access; pub mod account; pub mod governance; pub mod introspection; diff --git a/src/tests/account/ethereum/test_dual_eth_account.cairo b/src/tests/account/ethereum/test_dual_eth_account.cairo index bebb48e1d..17138b578 100644 --- a/src/tests/account/ethereum/test_dual_eth_account.cairo +++ b/src/tests/account/ethereum/test_dual_eth_account.cairo @@ -1,8 +1,8 @@ -use openzeppelin::account::dual_eth_account::{DualCaseEthAccountABI, DualCaseEthAccount}; -use openzeppelin::account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; -use openzeppelin::account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin::introspection::interface::ISRC5_ID; +use openzeppelin_account::dual_eth_account::{DualCaseEthAccountABI, DualCaseEthAccount}; +use openzeppelin_account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; +use openzeppelin_account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; +use openzeppelin_account::utils::signature::EthSignature; +use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin::tests::mocks::eth_account_mocks::{ CamelEthAccountPanicMock, CamelEthAccountMock, SnakeEthAccountMock, SnakeEthAccountPanicMock }; diff --git a/src/tests/account/ethereum/test_eth_account.cairo b/src/tests/account/ethereum/test_eth_account.cairo index 162ebc5b1..9e3ae70c5 100644 --- a/src/tests/account/ethereum/test_eth_account.cairo +++ b/src/tests/account/ethereum/test_eth_account.cairo @@ -1,12 +1,12 @@ -use openzeppelin::account::EthAccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; -use openzeppelin::account::EthAccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; -use openzeppelin::account::EthAccountComponent; -use openzeppelin::account::interface::EthPublicKey; -use openzeppelin::account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; -use openzeppelin::account::interface::{ISRC6, ISRC6_ID}; -use openzeppelin::account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin::introspection::interface::{ISRC5, ISRC5_ID}; +use openzeppelin_account::EthAccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; +use openzeppelin_account::EthAccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; +use openzeppelin_account::EthAccountComponent; +use openzeppelin_account::interface::EthPublicKey; +use openzeppelin_account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; +use openzeppelin_account::interface::{ISRC6, ISRC6_ID}; +use openzeppelin_account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; +use openzeppelin_account::utils::signature::EthSignature; +use openzeppelin_introspection::interface::{ISRC5, ISRC5_ID}; use openzeppelin::tests::mocks::eth_account_mocks::DualCaseEthAccountMock; use openzeppelin::tests::utils::constants::{ ETH_PUBKEY, SALT, ZERO, OTHER, RECIPIENT, CALLER, QUERY_VERSION, MIN_TRANSACTION_VERSION diff --git a/src/tests/account/test_secp256k1.cairo b/src/tests/account/test_secp256k1.cairo index 8c7b8117b..8427c5ac2 100644 --- a/src/tests/account/test_secp256k1.cairo +++ b/src/tests/account/test_secp256k1.cairo @@ -1,4 +1,4 @@ -use openzeppelin::account::utils::secp256k1::{ +use openzeppelin_account::utils::secp256k1::{ DebugSecp256k1Point, Secp256k1PointPartialEq, Secp256k1PointStorePacking as StorePacking }; use starknet::SyscallResultTrait; diff --git a/src/tests/governance/test_timelock.cairo b/src/tests/governance/test_timelock.cairo index c654c2082..269999994 100644 --- a/src/tests/governance/test_timelock.cairo +++ b/src/tests/governance/test_timelock.cairo @@ -1,26 +1,26 @@ use core::hash::{HashStateTrait, HashStateExTrait}; use core::num::traits::Zero; use core::pedersen::PedersenTrait; -use openzeppelin::access::accesscontrol::AccessControlComponent::{ +use openzeppelin_access::accesscontrol::AccessControlComponent::{ AccessControlImpl, InternalImpl as AccessControlInternalImpl }; -use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; -use openzeppelin::access::accesscontrol::interface::IACCESSCONTROL_ID; -use openzeppelin::access::accesscontrol::interface::IAccessControl; -use openzeppelin::governance::timelock::OperationState; -use openzeppelin::governance::timelock::TimelockControllerComponent::{ +use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; +use openzeppelin_access::accesscontrol::interface::IACCESSCONTROL_ID; +use openzeppelin_access::accesscontrol::interface::IAccessControl; +use openzeppelin_governance::timelock::OperationState; +use openzeppelin_governance::timelock::TimelockControllerComponent::{ CallScheduled, CallExecuted, CallSalt, CallCancelled, MinDelayChanged }; -use openzeppelin::governance::timelock::TimelockControllerComponent::{ +use openzeppelin_governance::timelock::TimelockControllerComponent::{ TimelockImpl, InternalImpl as TimelockInternalImpl }; -use openzeppelin::governance::timelock::TimelockControllerComponent; -use openzeppelin::governance::timelock::interface::{ +use openzeppelin_governance::timelock::TimelockControllerComponent; +use openzeppelin_governance::timelock::interface::{ TimelockABIDispatcher, TimelockABIDispatcherTrait }; -use openzeppelin::governance::timelock::{PROPOSER_ROLE, EXECUTOR_ROLE, CANCELLER_ROLE}; -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; +use openzeppelin_governance::timelock::{PROPOSER_ROLE, EXECUTOR_ROLE, CANCELLER_ROLE}; +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; use openzeppelin::tests::mocks::timelock_mocks::MockContract; use openzeppelin::tests::mocks::timelock_mocks::{ IMockContractDispatcher, IMockContractDispatcherTrait diff --git a/src/tests/governance/test_utils.cairo b/src/tests/governance/test_utils.cairo index 874fe2615..f66bafa33 100644 --- a/src/tests/governance/test_utils.cairo +++ b/src/tests/governance/test_utils.cairo @@ -1,4 +1,4 @@ -use openzeppelin::governance::timelock::utils::call_impls::CallPartialEq; +use openzeppelin_governance::timelock::utils::call_impls::CallPartialEq; use starknet::account::Call; use starknet::contract_address_const; diff --git a/src/tests/mocks/eth_account_mocks.cairo b/src/tests/mocks/eth_account_mocks.cairo index 4115e6715..16f56e1f3 100644 --- a/src/tests/mocks/eth_account_mocks.cairo +++ b/src/tests/mocks/eth_account_mocks.cairo @@ -1,8 +1,8 @@ #[starknet::contract(account)] pub(crate) mod DualCaseEthAccountMock { - use openzeppelin::account::EthAccountComponent; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_introspection::src5::SRC5Component; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -50,9 +50,9 @@ pub(crate) mod SnakeEthAccountMock { use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin_introspection::src5::SRC5Component; ======= - use openzeppelin::account::EthAccountComponent; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_introspection::src5::SRC5Component; >>>>>>> fa708bd2ade2969be3131180174093c3b9bd0666 component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); @@ -97,9 +97,9 @@ pub(crate) mod CamelEthAccountMock { use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin_introspection::src5::SRC5Component; ======= - use openzeppelin::account::EthAccountComponent; - use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_introspection::src5::SRC5Component; >>>>>>> fa708bd2ade2969be3131180174093c3b9bd0666 use starknet::account::Call; @@ -165,7 +165,7 @@ pub(crate) mod SnakeEthAccountPanicMock { use openzeppelin_account::interface::EthPublicKey; use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; ======= - use openzeppelin::account::interface::EthPublicKey; + use openzeppelin_account::interface::EthPublicKey; >>>>>>> fa708bd2ade2969be3131180174093c3b9bd0666 use starknet::SyscallResultTrait; use starknet::secp256_trait::Secp256Trait; @@ -211,7 +211,7 @@ pub(crate) mod CamelEthAccountPanicMock { use openzeppelin_account::interface::EthPublicKey; use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; ======= - use openzeppelin::account::interface::EthPublicKey; + use openzeppelin_account::interface::EthPublicKey; >>>>>>> fa708bd2ade2969be3131180174093c3b9bd0666 use starknet::SyscallResultTrait; use starknet::secp256_trait::Secp256Trait; diff --git a/src/tests/mocks/timelock_mocks.cairo b/src/tests/mocks/timelock_mocks.cairo index a60a9da19..810d88cac 100644 --- a/src/tests/mocks/timelock_mocks.cairo +++ b/src/tests/mocks/timelock_mocks.cairo @@ -1,8 +1,8 @@ #[starknet::contract] pub(crate) mod TimelockControllerMock { - use openzeppelin::access::accesscontrol::AccessControlComponent; - use openzeppelin::governance::timelock::TimelockControllerComponent; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_governance::timelock::TimelockControllerComponent; + use openzeppelin_introspection::src5::SRC5Component; use starknet::ContractAddress; component!(path: AccessControlComponent, storage: access_control, event: AccessControlEvent); @@ -88,7 +88,7 @@ pub(crate) trait ITimelockAttacker { #[starknet::contract] pub(crate) mod TimelockAttackerMock { - use openzeppelin::governance::timelock::interface::{ + use openzeppelin_governance::timelock::interface::{ ITimelockDispatcher, ITimelockDispatcherTrait }; use starknet::ContractAddress; diff --git a/src/tests/presets/test_eth_account.cairo b/src/tests/presets/test_eth_account.cairo index db77cc002..98a37d4d4 100644 --- a/src/tests/presets/test_eth_account.cairo +++ b/src/tests/presets/test_eth_account.cairo @@ -1,8 +1,8 @@ use core::num::traits::Zero; -use openzeppelin::account::interface::ISRC6_ID; -use openzeppelin::account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin::introspection::interface::ISRC5_ID; +use openzeppelin_account::interface::ISRC6_ID; +use openzeppelin_account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; +use openzeppelin_account::utils::signature::EthSignature; +use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin::presets::EthAccountUpgradeable; use openzeppelin::presets::interfaces::{ EthAccountUpgradeableABIDispatcher, EthAccountUpgradeableABIDispatcherTrait diff --git a/src/tests/token/erc1155/test_erc1155.cairo b/src/tests/token/erc1155/test_erc1155.cairo index ae7fad5e1..d14bab72f 100644 --- a/src/tests/token/erc1155/test_erc1155.cairo +++ b/src/tests/token/erc1155/test_erc1155.cairo @@ -1,6 +1,6 @@ use core::num::traits::Zero; -use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; -use openzeppelin::introspection; +use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; +use openzeppelin_introspection; use openzeppelin::tests::mocks::erc1155_mocks::DualCaseERC1155Mock; use openzeppelin::tests::utils::constants::{ EMPTY_DATA, ZERO, OWNER, RECIPIENT, OPERATOR, OTHER, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, From b8d597ad56b3e57262a98eea1740acb334116423 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 26 Jul 2024 13:35:19 +0200 Subject: [PATCH 21/45] feat: update packages Scarb.toml --- Scarb.toml | 4 +++- packages/access/README.md | 0 packages/access/Scarb.toml | 15 ++++++++++++--- packages/account/README.md | 0 packages/account/Scarb.toml | 15 ++++++++++++--- packages/governance/README.md | 0 packages/governance/Scarb.toml | 15 ++++++++++++--- packages/introspection/README.md | 0 packages/introspection/Scarb.toml | 17 ++++++++++++----- packages/presets/README.md | 0 packages/presets/Scarb.toml | 17 ++++++++++++----- packages/security/README.md | 0 packages/security/Scarb.toml | 17 ++++++++++++----- packages/token/README.md | 0 packages/token/Scarb.toml | 17 ++++++++++++----- packages/upgrades/README.md | 0 packages/upgrades/Scarb.toml | 17 ++++++++++++----- packages/utils/README.md | 0 packages/utils/Scarb.toml | 17 ++++++++++++----- 19 files changed, 111 insertions(+), 40 deletions(-) delete mode 100644 packages/access/README.md delete mode 100644 packages/account/README.md delete mode 100644 packages/governance/README.md delete mode 100644 packages/introspection/README.md delete mode 100644 packages/presets/README.md delete mode 100644 packages/security/README.md delete mode 100644 packages/token/README.md delete mode 100644 packages/upgrades/README.md delete mode 100644 packages/utils/README.md diff --git a/Scarb.toml b/Scarb.toml index 89f0f74d4..0b6bac875 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,4 +1,5 @@ [workspace] +name = "openzeppelin" members = [ "packages/access", "packages/account", @@ -10,7 +11,8 @@ members = [ "packages/upgrades", "packages/utils", ] -name = "openzeppelin" + +[workspace.package] version = "0.15.0-rc.0" edition = "2023_11" cairo-version = "2.7.0-rc.3" diff --git a/packages/access/README.md b/packages/access/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/access/Scarb.toml b/packages/access/Scarb.toml index 8d5f86ff0..802ddd620 100644 --- a/packages/access/Scarb.toml +++ b/packages/access/Scarb.toml @@ -1,12 +1,21 @@ [package] name = "openzeppelin_access" -version = "0.15.0-rc.0" -edition = "2023_11" +version.workspace = true +edition.workspace = true +cairo-version.workspace = true +scarb-version.workspace = true +authors.workspace = true +description.workspace = true +documentation.workspace = true +readme.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [tool] fmt.workspace = true [dependencies] -starknet = "2.7.0-rc.3" +starknet.workspace = true openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } diff --git a/packages/account/README.md b/packages/account/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/account/Scarb.toml b/packages/account/Scarb.toml index e2d3b14b9..c728c6cbb 100644 --- a/packages/account/Scarb.toml +++ b/packages/account/Scarb.toml @@ -1,12 +1,21 @@ [package] name = "openzeppelin_account" -version = "0.15.0-rc.0" -edition = "2023_11" +version.workspace = true +edition.workspace = true +cairo-version.workspace = true +scarb-version.workspace = true +authors.workspace = true +description.workspace = true +documentation.workspace = true +readme.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [tool] fmt.workspace = true [dependencies] -starknet = "2.7.0-rc.3" +starknet.workspace = true openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } diff --git a/packages/governance/README.md b/packages/governance/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/governance/Scarb.toml b/packages/governance/Scarb.toml index 59adde024..6febe7691 100644 --- a/packages/governance/Scarb.toml +++ b/packages/governance/Scarb.toml @@ -1,13 +1,22 @@ [package] name = "openzeppelin_governance" -version = "0.15.0-rc.0" -edition = "2023_11" +version.workspace = true +edition.workspace = true +cairo-version.workspace = true +scarb-version.workspace = true +authors.workspace = true +description.workspace = true +documentation.workspace = true +readme.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [tool] fmt.workspace = true [dependencies] -starknet = "2.7.0-rc.3" +starknet.workspace = true openzeppelin_access = { path = "../access" } openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } diff --git a/packages/introspection/README.md b/packages/introspection/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/introspection/Scarb.toml b/packages/introspection/Scarb.toml index 9cdfa4415..4cb78d346 100644 --- a/packages/introspection/Scarb.toml +++ b/packages/introspection/Scarb.toml @@ -1,13 +1,20 @@ [package] name = "openzeppelin_introspection" -version = "0.15.0-rc.0" -description = "" -homepage = "" -edition = "2023_11" +version.workspace = true +edition.workspace = true +cairo-version.workspace = true +scarb-version.workspace = true +authors.workspace = true +description.workspace = true +documentation.workspace = true +readme.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [tool] fmt.workspace = true [dependencies] -starknet = "2.7.0-rc.3" +starknet.workspace = true diff --git a/packages/presets/README.md b/packages/presets/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/presets/Scarb.toml b/packages/presets/Scarb.toml index 54efc9b90..2f5d3ea58 100644 --- a/packages/presets/Scarb.toml +++ b/packages/presets/Scarb.toml @@ -1,16 +1,23 @@ [package] name = "openzeppelin_presets" -version = "0.15.0-rc.0" -description = "" -homepage = "" -edition = "2023_11" +version.workspace = true +edition.workspace = true +cairo-version.workspace = true +scarb-version.workspace = true +authors.workspace = true +description.workspace = true +documentation.workspace = true +readme.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [tool] fmt.workspace = true [dependencies] -starknet = "2.7.0-rc.3" +starknet.workspace = true openzeppelin_access = { path = "../access" } openzeppelin_account = { path = "../account" } openzeppelin_introspection = { path = "../introspection" } diff --git a/packages/security/README.md b/packages/security/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/security/Scarb.toml b/packages/security/Scarb.toml index 9d65956c6..24712d7d6 100644 --- a/packages/security/Scarb.toml +++ b/packages/security/Scarb.toml @@ -1,13 +1,20 @@ [package] name = "openzeppelin_security" -version = "0.15.0-rc.0" -description = "" -homepage = "" -edition = "2023_11" +version.workspace = true +edition.workspace = true +cairo-version.workspace = true +scarb-version.workspace = true +authors.workspace = true +description.workspace = true +documentation.workspace = true +readme.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [tool] fmt.workspace = true [dependencies] -starknet = "2.7.0-rc.3" +starknet.workspace = true diff --git a/packages/token/README.md b/packages/token/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/token/Scarb.toml b/packages/token/Scarb.toml index 97c7479b2..41014afc0 100644 --- a/packages/token/Scarb.toml +++ b/packages/token/Scarb.toml @@ -1,16 +1,23 @@ [package] name = "openzeppelin_token" -version = "0.15.0-rc.0" -description = "" -homepage = "" -edition = "2023_11" +version.workspace = true +edition.workspace = true +cairo-version.workspace = true +scarb-version.workspace = true +authors.workspace = true +description.workspace = true +documentation.workspace = true +readme.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [tool] fmt.workspace = true [dependencies] -starknet = "2.7.0-rc.3" +starknet.workspace = true openzeppelin_account = { path = "../account" } openzeppelin_introspection = { path = "../introspection" } openzeppelin_governance = { path = "../governance" } diff --git a/packages/upgrades/README.md b/packages/upgrades/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/upgrades/Scarb.toml b/packages/upgrades/Scarb.toml index 7b936e853..39548c389 100644 --- a/packages/upgrades/Scarb.toml +++ b/packages/upgrades/Scarb.toml @@ -1,13 +1,20 @@ [package] name = "openzeppelin_upgrades" -version = "0.15.0-rc.0" -description = "" -homepage = "" -edition = "2023_11" +version.workspace = true +edition.workspace = true +cairo-version.workspace = true +scarb-version.workspace = true +authors.workspace = true +description.workspace = true +documentation.workspace = true +readme.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [tool] fmt.workspace = true [dependencies] -starknet = "2.7.0-rc.3" +starknet.workspace = true diff --git a/packages/utils/README.md b/packages/utils/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/utils/Scarb.toml b/packages/utils/Scarb.toml index 52ccff3f4..a05c75b5f 100644 --- a/packages/utils/Scarb.toml +++ b/packages/utils/Scarb.toml @@ -1,13 +1,20 @@ [package] name = "openzeppelin_utils" -version = "0.15.0-rc.0" -description = "" -homepage = "" -edition = "2023_11" +version.workspace = true +edition.workspace = true +cairo-version.workspace = true +scarb-version.workspace = true +authors.workspace = true +description.workspace = true +documentation.workspace = true +readme.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [tool] fmt.workspace = true [dependencies] -starknet = "2.7.0-rc.3" +starknet.workspace = true From fddddbd37d5164510d1a3fcbe266ea55518eaaf1 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 26 Jul 2024 13:37:30 +0200 Subject: [PATCH 22/45] refactor: remove gitmodules file --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 269eb8546..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "cairo"] - path = cairo - url = https://github.com/starkware-libs/cairo.git From 8851d2b87d48c7b3eff50067c5000089d3476ab5 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 26 Jul 2024 20:01:43 +0200 Subject: [PATCH 23/45] feat: refactor tests --- Scarb.lock | 22 ++ Scarb.toml | 22 +- docs/modules/ROOT/pages/api/utilities.adoc | 12 +- packages/access/Scarb.toml | 3 + packages/access/src/lib.cairo | 2 + .../access/src/tests.cairo | 8 +- .../access/src/tests}/common.cairo | 12 +- packages/access/src/tests/mocks.cairo | 3 + .../tests/mocks/accesscontrol_mocks.cairo | 0 .../tests/mocks/non_implementing_mock.cairo | 0 .../src}/tests/mocks/ownable_mocks.cairo | 0 .../src/tests}/test_accesscontrol.cairo | 28 +- .../src/tests}/test_dual_accesscontrol.cairo | 18 +- .../access/src/tests}/test_dual_ownable.cairo | 18 +- .../access/src/tests}/test_ownable.cairo | 8 +- .../src/tests}/test_ownable_twostep.cairo | 14 +- packages/account/Scarb.toml | 4 + packages/account/src/lib.cairo | 2 + packages/account/src/tests.cairo | 8 + .../account/src/tests}/ethereum.cairo | 4 +- .../account/src/tests}/ethereum/common.cairo | 42 +-- .../ethereum/test_dual_eth_account.cairo | 22 +- .../tests}/ethereum/test_eth_account.cairo | 18 +- packages/account/src/tests/mocks.cairo | 4 + .../src}/tests/mocks/account_mocks.cairo | 0 .../src}/tests/mocks/erc20_mocks.cairo | 0 .../src}/tests/mocks/eth_account_mocks.cairo | 24 -- .../tests/mocks/non_implementing_mock.cairo | 10 + .../account/src/tests}/starknet.cairo | 4 +- .../account/src/tests}/starknet/common.cairo | 40 +- .../src/tests}/starknet/test_account.cairo | 18 +- .../tests}/starknet/test_dual_account.cairo | 22 +- .../account/src/tests}/test_secp256k1.cairo | 0 .../account/src/tests}/test_signature.cairo | 0 packages/account/src/utils/secp256k1.cairo | 4 +- packages/governance/Scarb.toml | 3 + packages/governance/src/lib.cairo | 2 + .../governance/src/tests.cairo | 2 + packages/governance/src/tests/mocks.cairo | 2 + .../tests/mocks/non_implementing_mock.cairo | 10 + .../src}/tests/mocks/timelock_mocks.cairo | 0 .../governance/src/tests}/test_timelock.cairo | 71 ++-- .../governance/src/tests}/test_utils.cairo | 0 .../src/timelock/utils/call_impls.cairo | 6 +- packages/introspection/Scarb.toml | 3 + packages/introspection/src/lib.cairo | 3 + packages/introspection/src/tests.cairo | 3 + packages/introspection/src/tests/mocks.cairo | 1 + .../src}/tests/mocks/src5_mocks.cairo | 0 .../introspection/src/tests}/test_src5.cairo | 2 +- packages/presets/Scarb.toml | 3 + packages/presets/src/account.cairo | 4 +- packages/presets/src/erc1155.cairo | 2 +- packages/presets/src/erc20.cairo | 2 +- packages/presets/src/erc721.cairo | 2 +- packages/presets/src/lib.cairo | 27 +- .../presets/src/tests.cairo | 2 + packages/presets/src/tests/mocks.cairo | 7 + .../src/tests/mocks/account_mocks.cairo | 223 +++++++++++ .../src}/tests/mocks/erc1155_mocks.cairo | 0 .../presets/src/tests/mocks/erc20_mocks.cairo | 253 +++++++++++++ .../src}/tests/mocks/erc721_mocks.cairo | 0 .../tests/mocks/erc721_receiver_mocks.cairo | 2 +- .../src/tests/mocks/eth_account_mocks.cairo | 228 ++++++++++++ .../tests/mocks/non_implementing_mock.cairo | 10 + .../presets/src/tests}/test_account.cairo | 32 +- .../presets/src/tests}/test_erc1155.cairo | 34 +- .../presets/src/tests}/test_erc20.cairo | 28 +- .../presets/src/tests}/test_erc721.cairo | 84 ++--- .../presets/src/tests}/test_eth_account.cairo | 34 +- .../src/tests}/test_universal_deployer.cairo | 12 +- packages/presets/src/universal_deployer.cairo | 2 +- packages/security/Scarb.toml | 4 + packages/security/src/lib.cairo | 3 + .../security/src/tests.cairo | 2 + packages/security/src/tests/mocks.cairo | 3 + .../tests/mocks/initializable_mocks.cairo | 0 .../src}/tests/mocks/pausable_mocks.cairo | 0 .../src}/tests/mocks/reentrancy_mocks.cairo | 0 .../src/tests}/test_initializable.cairo | 2 +- .../security/src/tests}/test_pausable.cairo | 16 +- .../src/tests}/test_reentrancyguard.cairo | 8 +- packages/token/Scarb.toml | 3 + packages/token/src/lib.cairo | 2 + packages/token/src/tests.cairo | 5 + .../token/src/tests}/erc1155.cairo | 6 +- .../token/src/tests}/erc1155/common.cairo | 70 ++-- .../src/tests}/erc1155/test_dual1155.cairo | 28 +- .../erc1155/test_dual1155_receiver.cairo | 24 +- .../src/tests}/erc1155/test_erc1155.cairo | 18 +- .../erc1155/test_erc1155_receiver.cairo | 4 +- .../token/src/tests}/erc20.cairo | 5 +- .../token/src/tests}/erc20/common.cairo | 22 +- .../token/src/tests}/erc20/test_dual20.cairo | 24 +- .../token/src/tests}/erc20/test_erc20.cairo | 18 +- .../src/tests}/erc20/test_erc20_votes.cairo | 26 +- .../token/src/tests}/erc721.cairo | 5 +- .../token/src/tests}/erc721/common.cairo | 32 +- .../src/tests}/erc721/test_dual721.cairo | 28 +- .../tests}/erc721/test_dual721_receiver.cairo | 28 +- .../token/src/tests}/erc721/test_erc721.cairo | 106 +++--- .../tests}/erc721/test_erc721_receiver.cairo | 4 +- packages/token/src/tests/mocks.cairo | 20 + .../token/src/tests/mocks/account_mocks.cairo | 223 +++++++++++ .../token/src/tests/mocks/erc1155_mocks.cairo | 306 +++++++++++++++ .../tests/mocks/erc1155_receiver_mocks.cairo | 2 +- .../token/src/tests/mocks/erc20_mocks.cairo | 253 +++++++++++++ .../src}/tests/mocks/erc20_votes_mocks.cairo | 0 .../token/src/tests/mocks/erc721_mocks.cairo | 347 ++++++++++++++++++ .../tests/mocks/erc721_receiver_mocks.cairo | 237 ++++++++++++ .../tests/mocks/non_implementing_mock.cairo | 10 + .../token/src/tests/mocks/src5_mocks.cairo | 22 ++ packages/upgrades/Scarb.toml | 4 + packages/upgrades/src/lib.cairo | 2 + packages/upgrades/src/tests.cairo | 5 + packages/upgrades/src/tests/common.cairo | 16 + packages/upgrades/src/tests/mocks.cairo | 1 + .../src}/tests/mocks/upgrades_mocks.cairo | 0 .../src/tests}/test_upgradeable.cairo | 12 +- packages/utils/Scarb.toml | 3 + packages/utils/src/deployments.cairo | 3 + packages/utils/src/lib.cairo | 1 + .../utils/src/test_utils.cairo | 7 +- packages/utils/src/test_utils/constants.cairo | 117 ++++++ .../utils/tests.cairo | 0 {src => packages/utils}/tests/mocks.cairo | 0 .../tests/mocks/accesscontrol_mocks.cairo | 224 +++++++++++ .../utils/tests/mocks/account_mocks.cairo | 223 +++++++++++ .../utils/tests/mocks/erc1155_mocks.cairo | 306 +++++++++++++++ .../tests/mocks/erc1155_receiver_mocks.cairo | 197 ++++++++++ packages/utils/tests/mocks/erc20_mocks.cairo | 253 +++++++++++++ .../utils/tests/mocks/erc20_votes_mocks.cairo | 101 +++++ packages/utils/tests/mocks/erc721_mocks.cairo | 347 ++++++++++++++++++ .../tests/mocks/erc721_receiver_mocks.cairo | 237 ++++++++++++ .../utils/tests/mocks/eth_account_mocks.cairo | 228 ++++++++++++ .../tests/mocks/initializable_mocks.cairo | 23 ++ .../tests/mocks/non_implementing_mock.cairo | 10 + .../utils}/tests/mocks/nonces_mocks.cairo | 0 .../utils/tests/mocks/ownable_mocks.cairo | 188 ++++++++++ .../utils/tests/mocks/pausable_mocks.cairo | 23 ++ .../utils/tests/mocks/reentrancy_mocks.cairo | 125 +++++++ packages/utils/tests/mocks/src5_mocks.cairo | 22 ++ .../utils/tests/mocks/timelock_mocks.cairo | 151 ++++++++ .../utils/tests/mocks/upgrades_mocks.cairo | 111 ++++++ .../utils/tests}/test_nonces.cairo | 5 +- .../utils/tests}/test_snip12.cairo | 2 +- src/lib.cairo | 19 +- src/tests.cairo | 22 -- src/tests/account.cairo | 5 - src/tests/introspection.cairo | 1 - src/tests/token.cairo | 3 - src/tests/upgrades.cairo | 3 - src/tests/upgrades/common.cairo | 16 - src/tests/utils/constants.cairo | 116 ------ 154 files changed, 5784 insertions(+), 759 deletions(-) rename src/tests/access.cairo => packages/access/src/tests.cairo (54%) rename {src/tests/access => packages/access/src/tests}/common.cairo (72%) create mode 100644 packages/access/src/tests/mocks.cairo rename {src => packages/access/src}/tests/mocks/accesscontrol_mocks.cairo (100%) rename {src => packages/access/src}/tests/mocks/non_implementing_mock.cairo (100%) rename {src => packages/access/src}/tests/mocks/ownable_mocks.cairo (100%) rename {src/tests/access => packages/access/src/tests}/test_accesscontrol.cairo (94%) rename {src/tests/access => packages/access/src/tests}/test_dual_accesscontrol.cairo (91%) rename {src/tests/access => packages/access/src/tests}/test_dual_ownable.cairo (86%) rename {src/tests/access => packages/access/src/tests}/test_ownable.cairo (95%) rename {src/tests/access => packages/access/src/tests}/test_ownable_twostep.cairo (95%) create mode 100644 packages/account/src/tests.cairo rename {src/tests/account => packages/account/src/tests}/ethereum.cairo (54%) rename {src/tests/account => packages/account/src/tests}/ethereum/common.cairo (69%) rename {src/tests/account => packages/account/src/tests}/ethereum/test_dual_eth_account.cairo (92%) rename {src/tests/account => packages/account/src/tests}/ethereum/test_eth_account.cairo (98%) create mode 100644 packages/account/src/tests/mocks.cairo rename {src => packages/account/src}/tests/mocks/account_mocks.cairo (100%) rename {src => packages/account/src}/tests/mocks/erc20_mocks.cairo (100%) rename {src => packages/account/src}/tests/mocks/eth_account_mocks.cairo (87%) create mode 100644 packages/account/src/tests/mocks/non_implementing_mock.cairo rename {src/tests/account => packages/account/src/tests}/starknet.cairo (50%) rename {src/tests/account => packages/account/src/tests}/starknet/common.cairo (55%) rename {src/tests/account => packages/account/src/tests}/starknet/test_account.cairo (97%) rename {src/tests/account => packages/account/src/tests}/starknet/test_dual_account.cairo (91%) rename {src/tests/account => packages/account/src/tests}/test_secp256k1.cairo (100%) rename {src/tests/account => packages/account/src/tests}/test_signature.cairo (100%) rename src/tests/governance.cairo => packages/governance/src/tests.cairo (60%) create mode 100644 packages/governance/src/tests/mocks.cairo create mode 100644 packages/governance/src/tests/mocks/non_implementing_mock.cairo rename {src => packages/governance/src}/tests/mocks/timelock_mocks.cairo (100%) rename {src/tests/governance => packages/governance/src/tests}/test_timelock.cairo (96%) rename {src/tests/governance => packages/governance/src/tests}/test_utils.cairo (100%) create mode 100644 packages/introspection/src/tests.cairo create mode 100644 packages/introspection/src/tests/mocks.cairo rename {src => packages/introspection/src}/tests/mocks/src5_mocks.cairo (100%) rename {src/tests/introspection => packages/introspection/src/tests}/test_src5.cairo (95%) rename src/tests/presets.cairo => packages/presets/src/tests.cairo (83%) create mode 100644 packages/presets/src/tests/mocks.cairo create mode 100644 packages/presets/src/tests/mocks/account_mocks.cairo rename {src => packages/presets/src}/tests/mocks/erc1155_mocks.cairo (100%) create mode 100644 packages/presets/src/tests/mocks/erc20_mocks.cairo rename {src => packages/presets/src}/tests/mocks/erc721_mocks.cairo (100%) rename {src => packages/presets/src}/tests/mocks/erc721_receiver_mocks.cairo (99%) create mode 100644 packages/presets/src/tests/mocks/eth_account_mocks.cairo create mode 100644 packages/presets/src/tests/mocks/non_implementing_mock.cairo rename {src/tests/presets => packages/presets/src/tests}/test_account.cairo (97%) rename {src/tests/presets => packages/presets/src/tests}/test_erc1155.cairo (97%) rename {src/tests/presets => packages/presets/src/tests}/test_erc20.cairo (95%) rename {src/tests/presets => packages/presets/src/tests}/test_erc721.cairo (93%) rename {src/tests/presets => packages/presets/src/tests}/test_eth_account.cairo (96%) rename {src/tests/presets => packages/presets/src/tests}/test_universal_deployer.cairo (88%) rename src/tests/security.cairo => packages/security/src/tests.cairo (75%) create mode 100644 packages/security/src/tests/mocks.cairo rename {src => packages/security/src}/tests/mocks/initializable_mocks.cairo (100%) rename {src => packages/security/src}/tests/mocks/pausable_mocks.cairo (100%) rename {src => packages/security/src}/tests/mocks/reentrancy_mocks.cairo (100%) rename {src/tests/security => packages/security/src/tests}/test_initializable.cairo (89%) rename {src/tests/security => packages/security/src/tests}/test_pausable.cairo (84%) rename {src/tests/security => packages/security/src/tests}/test_reentrancyguard.cairo (90%) create mode 100644 packages/token/src/tests.cairo rename {src/tests/token => packages/token/src/tests}/erc1155.cairo (57%) rename {src/tests/token => packages/token/src/tests}/erc1155/common.cairo (61%) rename {src/tests/token => packages/token/src/tests}/erc1155/test_dual1155.cairo (93%) rename {src/tests/token => packages/token/src/tests}/erc1155/test_dual1155_receiver.cairo (86%) rename {src/tests/token => packages/token/src/tests}/erc1155/test_erc1155.cairo (99%) rename {src/tests/token => packages/token/src/tests}/erc1155/test_erc1155_receiver.cairo (92%) rename {src/tests/token => packages/token/src/tests}/erc20.cairo (50%) rename {src/tests/token => packages/token/src/tests}/erc20/common.cairo (70%) rename {src/tests/token => packages/token/src/tests}/erc20/test_dual20.cairo (91%) rename {src/tests/token => packages/token/src/tests}/erc20/test_erc20.cairo (97%) rename {src/tests/token => packages/token/src/tests}/erc20/test_erc20_votes.cairo (92%) rename {src/tests/token => packages/token/src/tests}/erc721.cairo (53%) rename {src/tests/token => packages/token/src/tests}/erc721/common.cairo (71%) rename {src/tests/token => packages/token/src/tests}/erc721/test_dual721.cairo (93%) rename {src/tests/token => packages/token/src/tests}/erc721/test_dual721_receiver.cairo (77%) rename {src/tests/token => packages/token/src/tests}/erc721/test_erc721.cairo (94%) rename {src/tests/token => packages/token/src/tests}/erc721/test_erc721_receiver.cairo (88%) create mode 100644 packages/token/src/tests/mocks.cairo create mode 100644 packages/token/src/tests/mocks/account_mocks.cairo create mode 100644 packages/token/src/tests/mocks/erc1155_mocks.cairo rename {src => packages/token/src}/tests/mocks/erc1155_receiver_mocks.cairo (98%) create mode 100644 packages/token/src/tests/mocks/erc20_mocks.cairo rename {src => packages/token/src}/tests/mocks/erc20_votes_mocks.cairo (100%) create mode 100644 packages/token/src/tests/mocks/erc721_mocks.cairo create mode 100644 packages/token/src/tests/mocks/erc721_receiver_mocks.cairo create mode 100644 packages/token/src/tests/mocks/non_implementing_mock.cairo create mode 100644 packages/token/src/tests/mocks/src5_mocks.cairo create mode 100644 packages/upgrades/src/tests.cairo create mode 100644 packages/upgrades/src/tests/common.cairo create mode 100644 packages/upgrades/src/tests/mocks.cairo rename {src => packages/upgrades/src}/tests/mocks/upgrades_mocks.cairo (100%) rename {src/tests/upgrades => packages/upgrades/src/tests}/test_upgradeable.cairo (85%) rename src/tests/utils.cairo => packages/utils/src/test_utils.cairo (93%) create mode 100644 packages/utils/src/test_utils/constants.cairo rename src/tests/cryptography.cairo => packages/utils/tests.cairo (100%) rename {src => packages/utils}/tests/mocks.cairo (100%) create mode 100644 packages/utils/tests/mocks/accesscontrol_mocks.cairo create mode 100644 packages/utils/tests/mocks/account_mocks.cairo create mode 100644 packages/utils/tests/mocks/erc1155_mocks.cairo create mode 100644 packages/utils/tests/mocks/erc1155_receiver_mocks.cairo create mode 100644 packages/utils/tests/mocks/erc20_mocks.cairo create mode 100644 packages/utils/tests/mocks/erc20_votes_mocks.cairo create mode 100644 packages/utils/tests/mocks/erc721_mocks.cairo create mode 100644 packages/utils/tests/mocks/erc721_receiver_mocks.cairo create mode 100644 packages/utils/tests/mocks/eth_account_mocks.cairo create mode 100644 packages/utils/tests/mocks/initializable_mocks.cairo create mode 100644 packages/utils/tests/mocks/non_implementing_mock.cairo rename {src => packages/utils}/tests/mocks/nonces_mocks.cairo (100%) create mode 100644 packages/utils/tests/mocks/ownable_mocks.cairo create mode 100644 packages/utils/tests/mocks/pausable_mocks.cairo create mode 100644 packages/utils/tests/mocks/reentrancy_mocks.cairo create mode 100644 packages/utils/tests/mocks/src5_mocks.cairo create mode 100644 packages/utils/tests/mocks/timelock_mocks.cairo create mode 100644 packages/utils/tests/mocks/upgrades_mocks.cairo rename {src/tests/cryptography => packages/utils/tests}/test_nonces.cairo (90%) rename {src/tests/cryptography => packages/utils/tests}/test_snip12.cairo (96%) delete mode 100644 src/tests.cairo delete mode 100644 src/tests/account.cairo delete mode 100644 src/tests/introspection.cairo delete mode 100644 src/tests/token.cairo delete mode 100644 src/tests/upgrades.cairo delete mode 100644 src/tests/upgrades/common.cairo delete mode 100644 src/tests/utils/constants.cairo diff --git a/Scarb.lock b/Scarb.lock index 91c58cb42..018df04af 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -1,6 +1,21 @@ # Code generated by scarb DO NOT EDIT. version = 1 +[[package]] +name = "openzeppelin" +version = "0.15.0-rc.0" +dependencies = [ + "openzeppelin_access", + "openzeppelin_account", + "openzeppelin_governance", + "openzeppelin_introspection", + "openzeppelin_presets", + "openzeppelin_security", + "openzeppelin_token", + "openzeppelin_upgrades", + "openzeppelin_utils", +] + [[package]] name = "openzeppelin_access" version = "0.15.0-rc.0" @@ -14,6 +29,7 @@ name = "openzeppelin_account" version = "0.15.0-rc.0" dependencies = [ "openzeppelin_introspection", + "openzeppelin_token", "openzeppelin_utils", ] @@ -44,6 +60,9 @@ dependencies = [ [[package]] name = "openzeppelin_security" version = "0.15.0-rc.0" +dependencies = [ + "openzeppelin_utils", +] [[package]] name = "openzeppelin_token" @@ -57,6 +76,9 @@ dependencies = [ [[package]] name = "openzeppelin_upgrades" version = "0.15.0-rc.0" +dependencies = [ + "openzeppelin_utils", +] [[package]] name = "openzeppelin_utils" diff --git a/Scarb.toml b/Scarb.toml index 0b6bac875..0736f26a2 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,5 +1,4 @@ [workspace] -name = "openzeppelin" members = [ "packages/access", "packages/account", @@ -12,6 +11,10 @@ members = [ "packages/utils", ] +[package] +name = "openzeppelin" +version.workspace = true + [workspace.package] version = "0.15.0-rc.0" edition = "2023_11" @@ -34,10 +37,23 @@ keywords = [ [workspace.dependencies] starknet = "2.7.0-rc.3" - -[workspace.dev-dependencies] cairo_test = "2.7.0-rc.3" +[dependencies] +starknet.workspace = true +openzeppelin_access = { path = "packages/access" } +openzeppelin_account = { path = "packages/account" } +openzeppelin_governance = { path = "packages/governance" } +openzeppelin_introspection = { path = "packages/introspection" } +openzeppelin_presets = { path = "packages/presets" } +openzeppelin_security = { path = "packages/security" } +openzeppelin_token = { path = "packages/token" } +openzeppelin_upgrades = { path = "packages/upgrades" } +openzeppelin_utils = { path = "packages/utils" } + +[dev-dependencies] +cairo_test.workspace = true + [lib] [[target.starknet-contract]] diff --git a/docs/modules/ROOT/pages/api/utilities.adoc b/docs/modules/ROOT/pages/api/utilities.adoc index c6ff30cbd..1566857fc 100644 --- a/docs/modules/ROOT/pages/api/utilities.adoc +++ b/docs/modules/ROOT/pages/api/utilities.adoc @@ -3,7 +3,7 @@ :deploy_syscall: link:https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy[deploy_syscall] The following documentation provides reasoning and examples for functions and constants found in `openzeppelin_utils` -and `openzeppelin::tests::utils`. +and `use openzeppelin_utils::test_utils;`. CAUTION: Expect this module to evolve (as it has already done). @@ -387,7 +387,7 @@ xref:/guides/snip12.adoc[SNIP12 and Typed Messages] guide. === `++utils++` ```cairo -use openzeppelin::tests::utils; +use openzeppelin_utils::test_utils; ``` Module containing utilities for testing the library. @@ -420,14 +420,14 @@ Usage example: ```cairo use openzeppelin_presets::AccountUpgradeable; -use openzeppelin::tests::utils; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; const PUBKEY: felt252 = 'PUBKEY'; fn deploy_test_contract() -> ContractAddress { let calldata = array![PUBKEY]; - utils::deploy(AccountUpgradeable::TEST_CLASS_HASH, calldata) + test_utils::deploy(AccountUpgradeable::TEST_CLASS_HASH, calldata) } ``` @@ -459,7 +459,7 @@ Requirements: Usage example: ```cairo -use openzeppelin::tests::utils; +use openzeppelin_utils::test_utils; use openzeppelin_token::erc20::ERC20Component; use openzeppelin_token::erc20::ERC20Component::Transfer; use starknet::ContractAddress; @@ -467,7 +467,7 @@ use starknet::ContractAddress; fn assert_emitted_event( target: ContractAddress, from: ContractAddress, to: ContractAddress, value: u256 ) { - let event = utils::pop_log::(target).unwrap(); + let event = test_utils::pop_log::(target).unwrap(); let expected = ERC20Component::Event::Transfer(Transfer { from, to, value }); assert!(event == expected); } diff --git a/packages/access/Scarb.toml b/packages/access/Scarb.toml index 802ddd620..4e8ed333e 100644 --- a/packages/access/Scarb.toml +++ b/packages/access/Scarb.toml @@ -19,3 +19,6 @@ fmt.workspace = true starknet.workspace = true openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } + +[dev-dependencies] +cairo_test.workspace = true diff --git a/packages/access/src/lib.cairo b/packages/access/src/lib.cairo index e2a102dc1..b9ab604d4 100644 --- a/packages/access/src/lib.cairo +++ b/packages/access/src/lib.cairo @@ -1,2 +1,4 @@ pub mod accesscontrol; pub mod ownable; + +pub mod tests; diff --git a/src/tests/access.cairo b/packages/access/src/tests.cairo similarity index 54% rename from src/tests/access.cairo rename to packages/access/src/tests.cairo index cfa981899..8c3f28828 100644 --- a/src/tests/access.cairo +++ b/packages/access/src/tests.cairo @@ -1,7 +1,13 @@ -pub(crate) mod common; +pub mod common; +pub(crate) mod mocks; +#[cfg(test)] mod test_accesscontrol; +#[cfg(test)] mod test_dual_accesscontrol; +#[cfg(test)] mod test_dual_ownable; +#[cfg(test)] mod test_ownable; +#[cfg(test)] mod test_ownable_twostep; diff --git a/src/tests/access/common.cairo b/packages/access/src/tests/common.cairo similarity index 72% rename from src/tests/access/common.cairo rename to packages/access/src/tests/common.cairo index 32697f1d4..13737add8 100644 --- a/src/tests/access/common.cairo +++ b/packages/access/src/tests/common.cairo @@ -1,20 +1,20 @@ use openzeppelin_access::ownable::OwnableComponent::OwnershipTransferred; use openzeppelin_access::ownable::OwnableComponent; -use openzeppelin::tests::utils; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; -pub(crate) fn assert_only_event_ownership_transferred( +pub fn assert_only_event_ownership_transferred( contract: ContractAddress, previous_owner: ContractAddress, new_owner: ContractAddress ) { assert_event_ownership_transferred(contract, previous_owner, new_owner); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } -pub(crate) fn assert_event_ownership_transferred( +pub fn assert_event_ownership_transferred( contract: ContractAddress, previous_owner: ContractAddress, new_owner: ContractAddress ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = OwnableComponent::Event::OwnershipTransferred( OwnershipTransferred { previous_owner, new_owner } ); @@ -24,5 +24,5 @@ pub(crate) fn assert_event_ownership_transferred( indexed_keys.append_serde(selector!("OwnershipTransferred")); indexed_keys.append_serde(previous_owner); indexed_keys.append_serde(new_owner); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } diff --git a/packages/access/src/tests/mocks.cairo b/packages/access/src/tests/mocks.cairo new file mode 100644 index 000000000..f3eca4c97 --- /dev/null +++ b/packages/access/src/tests/mocks.cairo @@ -0,0 +1,3 @@ +pub(crate) mod accesscontrol_mocks; +pub(crate) mod non_implementing_mock; +pub(crate) mod ownable_mocks; diff --git a/src/tests/mocks/accesscontrol_mocks.cairo b/packages/access/src/tests/mocks/accesscontrol_mocks.cairo similarity index 100% rename from src/tests/mocks/accesscontrol_mocks.cairo rename to packages/access/src/tests/mocks/accesscontrol_mocks.cairo diff --git a/src/tests/mocks/non_implementing_mock.cairo b/packages/access/src/tests/mocks/non_implementing_mock.cairo similarity index 100% rename from src/tests/mocks/non_implementing_mock.cairo rename to packages/access/src/tests/mocks/non_implementing_mock.cairo diff --git a/src/tests/mocks/ownable_mocks.cairo b/packages/access/src/tests/mocks/ownable_mocks.cairo similarity index 100% rename from src/tests/mocks/ownable_mocks.cairo rename to packages/access/src/tests/mocks/ownable_mocks.cairo diff --git a/src/tests/access/test_accesscontrol.cairo b/packages/access/src/tests/test_accesscontrol.cairo similarity index 94% rename from src/tests/access/test_accesscontrol.cairo rename to packages/access/src/tests/test_accesscontrol.cairo index 287fa30e7..16bb85d86 100644 --- a/src/tests/access/test_accesscontrol.cairo +++ b/packages/access/src/tests/test_accesscontrol.cairo @@ -6,12 +6,12 @@ use openzeppelin_access::accesscontrol::AccessControlComponent; use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; use openzeppelin_access::accesscontrol::interface::IACCESSCONTROL_ID; use openzeppelin_access::accesscontrol::interface::{IAccessControl, IAccessControlCamel}; +use openzeppelin_access::tests::mocks::accesscontrol_mocks::DualCaseAccessControlMock; use openzeppelin_introspection::interface::ISRC5; -use openzeppelin::tests::mocks::accesscontrol_mocks::DualCaseAccessControlMock; -use openzeppelin::tests::utils::constants::{ +use openzeppelin_utils::test_utils::constants::{ ADMIN, AUTHORIZED, OTHER, OTHER_ADMIN, ROLE, OTHER_ROLE, ZERO }; -use openzeppelin::tests::utils; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::testing; @@ -33,7 +33,7 @@ fn COMPONENT_STATE() -> ComponentState { fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state._grant_role(DEFAULT_ADMIN_ROLE, ADMIN()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state } @@ -189,7 +189,7 @@ fn test_revoke_role_for_granted_role() { testing::set_caller_address(ADMIN()); state.grant_role(ROLE, AUTHORIZED()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state.revoke_role(ROLE, AUTHORIZED()); @@ -205,7 +205,7 @@ fn test_revokeRole_for_granted_role() { testing::set_caller_address(ADMIN()); state.grantRole(ROLE, AUTHORIZED()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state.revokeRole(ROLE, AUTHORIZED()); @@ -281,7 +281,7 @@ fn test_renounce_role_for_granted_role() { testing::set_caller_address(ADMIN()); state.grant_role(ROLE, AUTHORIZED()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(AUTHORIZED()); state.renounce_role(ROLE, AUTHORIZED()); @@ -298,7 +298,7 @@ fn test_renounceRole_for_granted_role() { testing::set_caller_address(ADMIN()); state.grantRole(ROLE, AUTHORIZED()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(AUTHORIZED()); state.renounceRole(ROLE, AUTHORIZED()); @@ -448,30 +448,30 @@ fn test_default_admin_role_is_its_own_admin() { // fn assert_event_role_revoked(role: felt252, account: ContractAddress, sender: ContractAddress) { - let event = utils::pop_log::(ZERO()).unwrap(); + let event = test_utils::pop_log::(ZERO()).unwrap(); let expected = AccessControlComponent::Event::RoleRevoked( RoleRevoked { role, account, sender } ); assert!(event == expected); - utils::assert_no_events_left(ZERO()); + test_utils::assert_no_events_left(ZERO()); } fn assert_event_role_granted(role: felt252, account: ContractAddress, sender: ContractAddress) { - let event = utils::pop_log::(ZERO()).unwrap(); + let event = test_utils::pop_log::(ZERO()).unwrap(); let expected = AccessControlComponent::Event::RoleGranted( RoleGranted { role, account, sender } ); assert!(event == expected); - utils::assert_no_events_left(ZERO()); + test_utils::assert_no_events_left(ZERO()); } fn assert_event_role_admin_changed( role: felt252, previous_admin_role: felt252, new_admin_role: felt252 ) { - let event = utils::pop_log::(ZERO()).unwrap(); + let event = test_utils::pop_log::(ZERO()).unwrap(); let expected = AccessControlComponent::Event::RoleAdminChanged( RoleAdminChanged { role, previous_admin_role, new_admin_role } ); assert!(event == expected); - utils::assert_no_events_left(ZERO()); + test_utils::assert_no_events_left(ZERO()); } diff --git a/src/tests/access/test_dual_accesscontrol.cairo b/packages/access/src/tests/test_dual_accesscontrol.cairo similarity index 91% rename from src/tests/access/test_dual_accesscontrol.cairo rename to packages/access/src/tests/test_dual_accesscontrol.cairo index ad6ce6536..bad412e9b 100644 --- a/src/tests/access/test_dual_accesscontrol.cairo +++ b/packages/access/src/tests/test_dual_accesscontrol.cairo @@ -6,14 +6,14 @@ use openzeppelin_access::accesscontrol::interface::IAccessControlCamelDispatcher use openzeppelin_access::accesscontrol::interface::IAccessControlCamelDispatcherTrait; use openzeppelin_access::accesscontrol::interface::IAccessControlDispatcher; use openzeppelin_access::accesscontrol::interface::IAccessControlDispatcherTrait; -use openzeppelin::tests::mocks::accesscontrol_mocks::{ +use openzeppelin_access::tests::mocks::accesscontrol_mocks::{ CamelAccessControlMock, SnakeAccessControlMock, CamelAccessControlPanicMock, SnakeAccessControlPanicMock }; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::{ADMIN, AUTHORIZED, ROLE}; -use openzeppelin::tests::utils; +use openzeppelin_access::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ADMIN, AUTHORIZED, ROLE}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::testing::set_contract_address; @@ -25,7 +25,7 @@ use starknet::testing::set_contract_address; fn setup_snake() -> (DualCaseAccessControl, IAccessControlDispatcher) { let mut calldata = array![]; calldata.append_serde(ADMIN()); - let target = utils::deploy(SnakeAccessControlMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(SnakeAccessControlMock::TEST_CLASS_HASH, calldata); ( DualCaseAccessControl { contract_address: target }, IAccessControlDispatcher { contract_address: target } @@ -35,7 +35,7 @@ fn setup_snake() -> (DualCaseAccessControl, IAccessControlDispatcher) { fn setup_camel() -> (DualCaseAccessControl, IAccessControlCamelDispatcher) { let mut calldata = array![]; calldata.append_serde(ADMIN()); - let target = utils::deploy(CamelAccessControlMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(CamelAccessControlMock::TEST_CLASS_HASH, calldata); ( DualCaseAccessControl { contract_address: target }, IAccessControlCamelDispatcher { contract_address: target } @@ -43,13 +43,13 @@ fn setup_camel() -> (DualCaseAccessControl, IAccessControlCamelDispatcher) { } fn setup_non_accesscontrol() -> DualCaseAccessControl { - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let target = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); DualCaseAccessControl { contract_address: target } } fn setup_accesscontrol_panic() -> (DualCaseAccessControl, DualCaseAccessControl) { - let snake_target = utils::deploy(SnakeAccessControlPanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelAccessControlPanicMock::TEST_CLASS_HASH, array![]); + let snake_target = test_utils::deploy(SnakeAccessControlPanicMock::TEST_CLASS_HASH, array![]); + let camel_target = test_utils::deploy(CamelAccessControlPanicMock::TEST_CLASS_HASH, array![]); ( DualCaseAccessControl { contract_address: snake_target }, DualCaseAccessControl { contract_address: camel_target } diff --git a/src/tests/access/test_dual_ownable.cairo b/packages/access/src/tests/test_dual_ownable.cairo similarity index 86% rename from src/tests/access/test_dual_ownable.cairo rename to packages/access/src/tests/test_dual_ownable.cairo index d2a6788ee..50bdcce7b 100644 --- a/src/tests/access/test_dual_ownable.cairo +++ b/packages/access/src/tests/test_dual_ownable.cairo @@ -4,13 +4,13 @@ use openzeppelin_access::ownable::dual_ownable::DualCaseOwnableTrait; use openzeppelin_access::ownable::interface::IOwnableCamelOnlyDispatcher; use openzeppelin_access::ownable::interface::IOwnableDispatcher; use openzeppelin_access::ownable::interface::IOwnableDispatcherTrait; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::mocks::ownable_mocks::{ +use openzeppelin_access::tests::mocks::non_implementing_mock::NonImplementingMock; +use openzeppelin_access::tests::mocks::ownable_mocks::{ CamelOwnableMock, CamelOwnablePanicMock, SnakeOwnableMock, SnakeOwnablePanicMock }; -use openzeppelin::tests::utils::constants::{OWNER, NEW_OWNER}; -use openzeppelin::tests::utils; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{OWNER, NEW_OWNER}; +use openzeppelin_utils::test_utils; use starknet::testing::set_contract_address; // @@ -20,14 +20,14 @@ use starknet::testing::set_contract_address; fn setup_snake() -> (DualCaseOwnable, IOwnableDispatcher) { let mut calldata = array![]; calldata.append_serde(OWNER()); - let target = utils::deploy(SnakeOwnableMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(SnakeOwnableMock::TEST_CLASS_HASH, calldata); (DualCaseOwnable { contract_address: target }, IOwnableDispatcher { contract_address: target }) } fn setup_camel() -> (DualCaseOwnable, IOwnableCamelOnlyDispatcher) { let mut calldata = array![]; calldata.append_serde(OWNER()); - let target = utils::deploy(CamelOwnableMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(CamelOwnableMock::TEST_CLASS_HASH, calldata); ( DualCaseOwnable { contract_address: target }, IOwnableCamelOnlyDispatcher { contract_address: target } @@ -36,13 +36,13 @@ fn setup_camel() -> (DualCaseOwnable, IOwnableCamelOnlyDispatcher) { fn setup_non_ownable() -> DualCaseOwnable { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); DualCaseOwnable { contract_address: target } } fn setup_ownable_panic() -> (DualCaseOwnable, DualCaseOwnable) { - let snake_target = utils::deploy(SnakeOwnablePanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelOwnablePanicMock::TEST_CLASS_HASH, array![]); + let snake_target = test_utils::deploy(SnakeOwnablePanicMock::TEST_CLASS_HASH, array![]); + let camel_target = test_utils::deploy(CamelOwnablePanicMock::TEST_CLASS_HASH, array![]); ( DualCaseOwnable { contract_address: snake_target }, DualCaseOwnable { contract_address: camel_target } diff --git a/src/tests/access/test_ownable.cairo b/packages/access/src/tests/test_ownable.cairo similarity index 95% rename from src/tests/access/test_ownable.cairo rename to packages/access/src/tests/test_ownable.cairo index b3abbe13a..2c7b702da 100644 --- a/src/tests/access/test_ownable.cairo +++ b/packages/access/src/tests/test_ownable.cairo @@ -2,9 +2,9 @@ use core::num::traits::Zero; use openzeppelin_access::ownable::OwnableComponent::InternalTrait; use openzeppelin_access::ownable::OwnableComponent; use openzeppelin_access::ownable::interface::{IOwnable, IOwnableCamelOnly}; -use openzeppelin::tests::mocks::ownable_mocks::DualCaseOwnableMock; -use openzeppelin::tests::utils::constants::{ZERO, OTHER, OWNER}; -use openzeppelin::tests::utils; +use openzeppelin_access::tests::mocks::ownable_mocks::DualCaseOwnableMock; +use openzeppelin_utils::test_utils::constants::{ZERO, OTHER, OWNER}; +use openzeppelin_utils::test_utils; use starknet::testing; use super::common::assert_only_event_ownership_transferred; @@ -22,7 +22,7 @@ fn COMPONENT_STATE() -> ComponentState { fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(OWNER()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state } diff --git a/src/tests/access/test_ownable_twostep.cairo b/packages/access/src/tests/test_ownable_twostep.cairo similarity index 95% rename from src/tests/access/test_ownable_twostep.cairo rename to packages/access/src/tests/test_ownable_twostep.cairo index cd9b5e484..5e327d503 100644 --- a/src/tests/access/test_ownable_twostep.cairo +++ b/packages/access/src/tests/test_ownable_twostep.cairo @@ -3,10 +3,10 @@ use openzeppelin_access::ownable::OwnableComponent::InternalTrait; use openzeppelin_access::ownable::OwnableComponent::OwnershipTransferStarted; use openzeppelin_access::ownable::OwnableComponent; use openzeppelin_access::ownable::interface::{IOwnableTwoStep, IOwnableTwoStepCamelOnly}; -use openzeppelin::tests::mocks::ownable_mocks::DualCaseTwoStepOwnableMock; -use openzeppelin::tests::utils::constants::{ZERO, OWNER, OTHER, NEW_OWNER}; -use openzeppelin::tests::utils; +use openzeppelin_access::tests::mocks::ownable_mocks::DualCaseTwoStepOwnableMock; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ZERO, OWNER, OTHER, NEW_OWNER}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::testing; @@ -26,7 +26,7 @@ fn COMPONENT_STATE() -> ComponentState { fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(OWNER()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state } @@ -320,16 +320,16 @@ fn test_pending_accept_after_owner_renounce() { fn assert_event_ownership_transfer_started( previous_owner: ContractAddress, new_owner: ContractAddress ) { - let event = utils::pop_log::(ZERO()).unwrap(); + let event = test_utils::pop_log::(ZERO()).unwrap(); let expected = OwnableComponent::Event::OwnershipTransferStarted( OwnershipTransferStarted { previous_owner, new_owner } ); assert!(event == expected); - utils::assert_no_events_left(ZERO()); + test_utils::assert_no_events_left(ZERO()); let mut indexed_keys = array![]; indexed_keys.append_serde(selector!("OwnershipTransferStarted")); indexed_keys.append_serde(previous_owner); indexed_keys.append_serde(new_owner); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } diff --git a/packages/account/Scarb.toml b/packages/account/Scarb.toml index c728c6cbb..688316073 100644 --- a/packages/account/Scarb.toml +++ b/packages/account/Scarb.toml @@ -19,3 +19,7 @@ fmt.workspace = true starknet.workspace = true openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } + +[dev-dependencies] +cairo_test.workspace = true +openzeppelin_token = { path = "../token" } diff --git a/packages/account/src/lib.cairo b/packages/account/src/lib.cairo index 0cc865d90..1504180fb 100644 --- a/packages/account/src/lib.cairo +++ b/packages/account/src/lib.cairo @@ -3,6 +3,8 @@ pub mod dual_account; pub mod dual_eth_account; pub mod eth_account; pub mod interface; + +pub mod tests; pub mod utils; pub use account::AccountComponent; diff --git a/packages/account/src/tests.cairo b/packages/account/src/tests.cairo new file mode 100644 index 000000000..a35ada124 --- /dev/null +++ b/packages/account/src/tests.cairo @@ -0,0 +1,8 @@ +pub mod ethereum; +pub mod mocks; +pub mod starknet; + +#[cfg(test)] +mod test_secp256k1; +#[cfg(test)] +mod test_signature; diff --git a/src/tests/account/ethereum.cairo b/packages/account/src/tests/ethereum.cairo similarity index 54% rename from src/tests/account/ethereum.cairo rename to packages/account/src/tests/ethereum.cairo index d6fcf488b..79548d497 100644 --- a/src/tests/account/ethereum.cairo +++ b/packages/account/src/tests/ethereum.cairo @@ -1,4 +1,6 @@ -pub(crate) mod common; +pub mod common; +#[cfg(test)] mod test_dual_eth_account; +#[cfg(test)] mod test_eth_account; diff --git a/src/tests/account/ethereum/common.cairo b/packages/account/src/tests/ethereum/common.cairo similarity index 69% rename from src/tests/account/ethereum/common.cairo rename to packages/account/src/tests/ethereum/common.cairo index b307f378e..dd72c91e1 100644 --- a/src/tests/account/ethereum/common.cairo +++ b/packages/account/src/tests/ethereum/common.cairo @@ -3,27 +3,27 @@ use core::starknet::secp256_trait::Secp256PointTrait; use openzeppelin_account::EthAccountComponent::{OwnerAdded, OwnerRemoved}; use openzeppelin_account::EthAccountComponent; use openzeppelin_account::interface::EthPublicKey; +use openzeppelin_account::tests::mocks::erc20_mocks::DualCaseERC20Mock; use openzeppelin_account::utils::signature::EthSignature; -use openzeppelin::tests::mocks::erc20_mocks::DualCaseERC20Mock; -use openzeppelin::tests::utils::constants::{NAME, SYMBOL}; -use openzeppelin::tests::utils; use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{NAME, SYMBOL}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::SyscallResultTrait; use starknet::secp256_trait::Secp256Trait; use starknet::secp256k1::Secp256k1Point; #[derive(Drop)] -pub(crate) struct SignedTransactionData { - pub(crate) private_key: u256, - pub(crate) public_key: EthPublicKey, - pub(crate) transaction_hash: felt252, - pub(crate) signature: EthSignature +pub struct SignedTransactionData { + pub private_key: u256, + pub public_key: EthPublicKey, + pub transaction_hash: felt252, + pub signature: EthSignature } /// This signature was computed using ethers.js. -pub(crate) fn SIGNED_TX_DATA() -> SignedTransactionData { +pub fn SIGNED_TX_DATA() -> SignedTransactionData { SignedTransactionData { private_key: 0x45397ee6ca34cb49060f1c303c6cb7ee2d6123e617601ef3e31ccf7bf5bef1f9, public_key: NEW_ETH_PUBKEY(), @@ -35,7 +35,7 @@ pub(crate) fn SIGNED_TX_DATA() -> SignedTransactionData { } } -pub(crate) fn NEW_ETH_PUBKEY() -> EthPublicKey { +pub fn NEW_ETH_PUBKEY() -> EthPublicKey { Secp256Trait::secp256_ec_new_syscall( 0x829307f82a1883c2414503ba85fc85037f22c6fc6f80910801f6b01a4131da1e, 0x2a23f7bddf3715d11767b1247eccc68c89e11b926e2615268db6ad1af8d8da96 @@ -44,7 +44,7 @@ pub(crate) fn NEW_ETH_PUBKEY() -> EthPublicKey { .unwrap() } -pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { +pub fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { let name = NAME(); let symbol = SYMBOL(); let mut calldata = array![]; @@ -54,11 +54,11 @@ pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> calldata.append_serde(initial_supply); calldata.append_serde(recipient); - let address = utils::deploy(DualCaseERC20Mock::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(DualCaseERC20Mock::TEST_CLASS_HASH, calldata); IERC20Dispatcher { contract_address: address } } -pub(crate) fn get_points() -> (Secp256k1Point, Secp256k1Point) { +pub fn get_points() -> (Secp256k1Point, Secp256k1Point) { let curve_size = Secp256Trait::::get_curve_size(); let point_1 = Secp256Trait::secp256_ec_get_point_from_x_syscall(curve_size, true) .unwrap_syscall() @@ -70,8 +70,8 @@ pub(crate) fn get_points() -> (Secp256k1Point, Secp256k1Point) { (point_1, point_2) } -pub(crate) fn assert_event_owner_added(contract: ContractAddress, public_key: EthPublicKey) { - let event = utils::pop_log::(contract).unwrap(); +pub fn assert_event_owner_added(contract: ContractAddress, public_key: EthPublicKey) { + let event = test_utils::pop_log::(contract).unwrap(); let new_owner_guid = get_guid_from_public_key(public_key); let expected = EthAccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); assert!(event == expected); @@ -80,16 +80,16 @@ pub(crate) fn assert_event_owner_added(contract: ContractAddress, public_key: Et let mut indexed_keys = array![]; indexed_keys.append_serde(selector!("OwnerAdded")); indexed_keys.append_serde(new_owner_guid); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } -pub(crate) fn assert_only_event_owner_added(contract: ContractAddress, public_key: EthPublicKey) { +pub fn assert_only_event_owner_added(contract: ContractAddress, public_key: EthPublicKey) { assert_event_owner_added(contract, public_key); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } -pub(crate) fn assert_event_owner_removed(contract: ContractAddress, public_key: EthPublicKey) { - let event = utils::pop_log::(contract).unwrap(); +pub fn assert_event_owner_removed(contract: ContractAddress, public_key: EthPublicKey) { + let event = test_utils::pop_log::(contract).unwrap(); let removed_owner_guid = get_guid_from_public_key(public_key); let expected = EthAccountComponent::Event::OwnerRemoved(OwnerRemoved { removed_owner_guid }); assert!(event == expected); @@ -98,7 +98,7 @@ pub(crate) fn assert_event_owner_removed(contract: ContractAddress, public_key: let mut indexed_keys = array![]; indexed_keys.append_serde(selector!("OwnerRemoved")); indexed_keys.append_serde(removed_owner_guid); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } fn get_guid_from_public_key(public_key: EthPublicKey) -> felt252 { diff --git a/src/tests/account/ethereum/test_dual_eth_account.cairo b/packages/account/src/tests/ethereum/test_dual_eth_account.cairo similarity index 92% rename from src/tests/account/ethereum/test_dual_eth_account.cairo rename to packages/account/src/tests/ethereum/test_dual_eth_account.cairo index 17138b578..443b3da63 100644 --- a/src/tests/account/ethereum/test_dual_eth_account.cairo +++ b/packages/account/src/tests/ethereum/test_dual_eth_account.cairo @@ -1,15 +1,15 @@ use openzeppelin_account::dual_eth_account::{DualCaseEthAccountABI, DualCaseEthAccount}; use openzeppelin_account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; +use openzeppelin_account::tests::mocks::eth_account_mocks::{ + CamelEthAccountPanicMock, CamelEthAccountMock, SnakeEthAccountMock, SnakeEthAccountPanicMock +}; +use openzeppelin_account::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin_account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; use openzeppelin_account::utils::signature::EthSignature; use openzeppelin_introspection::interface::ISRC5_ID; -use openzeppelin::tests::mocks::eth_account_mocks::{ - CamelEthAccountPanicMock, CamelEthAccountMock, SnakeEthAccountMock, SnakeEthAccountPanicMock -}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::ETH_PUBKEY; -use openzeppelin::tests::utils; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::ETH_PUBKEY; +use openzeppelin_utils::test_utils; use starknet::testing; use super::common::{NEW_ETH_PUBKEY, SIGNED_TX_DATA}; @@ -22,7 +22,7 @@ fn setup_snake() -> (DualCaseEthAccount, EthAccountABIDispatcher) { let mut calldata = array![]; calldata.append_serde(ETH_PUBKEY()); - let target = utils::deploy(SnakeEthAccountMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(SnakeEthAccountMock::TEST_CLASS_HASH, calldata); ( DualCaseEthAccount { contract_address: target }, EthAccountABIDispatcher { contract_address: target } @@ -33,7 +33,7 @@ fn setup_camel() -> (DualCaseEthAccount, EthAccountABIDispatcher) { let mut calldata = array![]; calldata.append_serde(ETH_PUBKEY()); - let target = utils::deploy(CamelEthAccountMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(CamelEthAccountMock::TEST_CLASS_HASH, calldata); ( DualCaseEthAccount { contract_address: target }, EthAccountABIDispatcher { contract_address: target } @@ -42,13 +42,13 @@ fn setup_camel() -> (DualCaseEthAccount, EthAccountABIDispatcher) { fn setup_non_account() -> DualCaseEthAccount { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); DualCaseEthAccount { contract_address: target } } fn setup_account_panic() -> (DualCaseEthAccount, DualCaseEthAccount) { - let snake_target = utils::deploy(SnakeEthAccountPanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelEthAccountPanicMock::TEST_CLASS_HASH, array![]); + let snake_target = test_utils::deploy(SnakeEthAccountPanicMock::TEST_CLASS_HASH, array![]); + let camel_target = test_utils::deploy(CamelEthAccountPanicMock::TEST_CLASS_HASH, array![]); ( DualCaseEthAccount { contract_address: snake_target }, DualCaseEthAccount { contract_address: camel_target } diff --git a/src/tests/account/ethereum/test_eth_account.cairo b/packages/account/src/tests/ethereum/test_eth_account.cairo similarity index 98% rename from src/tests/account/ethereum/test_eth_account.cairo rename to packages/account/src/tests/ethereum/test_eth_account.cairo index 9e3ae70c5..aeceaac98 100644 --- a/src/tests/account/ethereum/test_eth_account.cairo +++ b/packages/account/src/tests/ethereum/test_eth_account.cairo @@ -4,17 +4,17 @@ use openzeppelin_account::EthAccountComponent; use openzeppelin_account::interface::EthPublicKey; use openzeppelin_account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; use openzeppelin_account::interface::{ISRC6, ISRC6_ID}; +use openzeppelin_account::tests::mocks::eth_account_mocks::DualCaseEthAccountMock; use openzeppelin_account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; use openzeppelin_account::utils::signature::EthSignature; use openzeppelin_introspection::interface::{ISRC5, ISRC5_ID}; -use openzeppelin::tests::mocks::eth_account_mocks::DualCaseEthAccountMock; -use openzeppelin::tests::utils::constants::{ - ETH_PUBKEY, SALT, ZERO, OTHER, RECIPIENT, CALLER, QUERY_VERSION, MIN_TRANSACTION_VERSION -}; -use openzeppelin::tests::utils; use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; use openzeppelin_utils::selectors; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ + ETH_PUBKEY, SALT, ZERO, OTHER, RECIPIENT, CALLER, QUERY_VERSION, MIN_TRANSACTION_VERSION +}; +use openzeppelin_utils::test_utils; use starknet::account::Call; use starknet::testing; use starknet::{contract_address_const, ContractAddress}; @@ -52,7 +52,7 @@ fn COMPONENT_STATE() -> ComponentState { fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(ETH_PUBKEY()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state } @@ -72,7 +72,7 @@ fn setup_dispatcher(data: Option<@SignedTransactionData>) -> EthAccountABIDispat } else { calldata.append_serde(ETH_PUBKEY()); } - let address = utils::deploy(CLASS_HASH(), calldata); + let address = test_utils::deploy(CLASS_HASH(), calldata); EthAccountABIDispatcher { contract_address: address } } @@ -390,7 +390,7 @@ fn test_public_key_setter_and_getter() { testing::set_caller_address(ACCOUNT_ADDRESS()); state.initializer(public_key); - utils::drop_event(ACCOUNT_ADDRESS()); + test_utils::drop_event(ACCOUNT_ADDRESS()); // Check default let current = state.get_public_key(); @@ -430,7 +430,7 @@ fn test_public_key_setter_and_getter_camel() { testing::set_caller_address(ACCOUNT_ADDRESS()); state.initializer(public_key); - utils::drop_event(ACCOUNT_ADDRESS()); + test_utils::drop_event(ACCOUNT_ADDRESS()); let current = state.getPublicKey(); assert_eq!(current, public_key); diff --git a/packages/account/src/tests/mocks.cairo b/packages/account/src/tests/mocks.cairo new file mode 100644 index 000000000..8b7ce956f --- /dev/null +++ b/packages/account/src/tests/mocks.cairo @@ -0,0 +1,4 @@ +pub(crate) mod account_mocks; +pub(crate) mod erc20_mocks; +pub(crate) mod eth_account_mocks; +pub(crate) mod non_implementing_mock; diff --git a/src/tests/mocks/account_mocks.cairo b/packages/account/src/tests/mocks/account_mocks.cairo similarity index 100% rename from src/tests/mocks/account_mocks.cairo rename to packages/account/src/tests/mocks/account_mocks.cairo diff --git a/src/tests/mocks/erc20_mocks.cairo b/packages/account/src/tests/mocks/erc20_mocks.cairo similarity index 100% rename from src/tests/mocks/erc20_mocks.cairo rename to packages/account/src/tests/mocks/erc20_mocks.cairo diff --git a/src/tests/mocks/eth_account_mocks.cairo b/packages/account/src/tests/mocks/eth_account_mocks.cairo similarity index 87% rename from src/tests/mocks/eth_account_mocks.cairo rename to packages/account/src/tests/mocks/eth_account_mocks.cairo index 16f56e1f3..b230e524d 100644 --- a/src/tests/mocks/eth_account_mocks.cairo +++ b/packages/account/src/tests/mocks/eth_account_mocks.cairo @@ -44,16 +44,9 @@ pub(crate) mod DualCaseEthAccountMock { #[starknet::contract(account)] pub(crate) mod SnakeEthAccountMock { -<<<<<<< HEAD use openzeppelin_account::EthAccountComponent; use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin_introspection::src5::SRC5Component; -======= - use openzeppelin_account::EthAccountComponent; - use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_introspection::src5::SRC5Component; ->>>>>>> fa708bd2ade2969be3131180174093c3b9bd0666 component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -91,16 +84,9 @@ pub(crate) mod SnakeEthAccountMock { #[starknet::contract(account)] pub(crate) mod CamelEthAccountMock { -<<<<<<< HEAD - use openzeppelin_account::EthAccountComponent; - use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; - use openzeppelin_introspection::src5::SRC5Component; -======= use openzeppelin_account::EthAccountComponent; use openzeppelin_account::interface::EthPublicKey; use openzeppelin_introspection::src5::SRC5Component; ->>>>>>> fa708bd2ade2969be3131180174093c3b9bd0666 use starknet::account::Call; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); @@ -161,12 +147,7 @@ pub(crate) mod CamelEthAccountMock { #[starknet::contract] pub(crate) mod SnakeEthAccountPanicMock { -<<<<<<< HEAD use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; -======= - use openzeppelin_account::interface::EthPublicKey; ->>>>>>> fa708bd2ade2969be3131180174093c3b9bd0666 use starknet::SyscallResultTrait; use starknet::secp256_trait::Secp256Trait; @@ -207,12 +188,7 @@ pub(crate) mod SnakeEthAccountPanicMock { #[starknet::contract] pub(crate) mod CamelEthAccountPanicMock { -<<<<<<< HEAD - use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; -======= use openzeppelin_account::interface::EthPublicKey; ->>>>>>> fa708bd2ade2969be3131180174093c3b9bd0666 use starknet::SyscallResultTrait; use starknet::secp256_trait::Secp256Trait; diff --git a/packages/account/src/tests/mocks/non_implementing_mock.cairo b/packages/account/src/tests/mocks/non_implementing_mock.cairo new file mode 100644 index 000000000..c1212dbdd --- /dev/null +++ b/packages/account/src/tests/mocks/non_implementing_mock.cairo @@ -0,0 +1,10 @@ +#[starknet::contract] +pub(crate) mod NonImplementingMock { + #[storage] + struct Storage {} + + #[external(v0)] + fn nope(self: @ContractState) -> bool { + false + } +} diff --git a/src/tests/account/starknet.cairo b/packages/account/src/tests/starknet.cairo similarity index 50% rename from src/tests/account/starknet.cairo rename to packages/account/src/tests/starknet.cairo index e67636b10..3a098e2c2 100644 --- a/src/tests/account/starknet.cairo +++ b/packages/account/src/tests/starknet.cairo @@ -1,4 +1,6 @@ -pub(crate) mod common; +pub mod common; +#[cfg(test)] mod test_account; +#[cfg(test)] mod test_dual_account; diff --git a/src/tests/account/starknet/common.cairo b/packages/account/src/tests/starknet/common.cairo similarity index 55% rename from src/tests/account/starknet/common.cairo rename to packages/account/src/tests/starknet/common.cairo index 755d59ab8..9c89498cb 100644 --- a/src/tests/account/starknet/common.cairo +++ b/packages/account/src/tests/starknet/common.cairo @@ -1,22 +1,22 @@ use openzeppelin_account::AccountComponent::{OwnerAdded, OwnerRemoved}; use openzeppelin_account::AccountComponent; -use openzeppelin::tests::mocks::erc20_mocks::DualCaseERC20Mock; -use openzeppelin::tests::utils::constants::{NAME, SYMBOL, NEW_PUBKEY}; -use openzeppelin::tests::utils; +use openzeppelin_account::tests::mocks::erc20_mocks::DualCaseERC20Mock; use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{NAME, SYMBOL, NEW_PUBKEY}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; #[derive(Drop)] -pub(crate) struct SignedTransactionData { - pub(crate) private_key: felt252, - pub(crate) public_key: felt252, - pub(crate) transaction_hash: felt252, - pub(crate) r: felt252, - pub(crate) s: felt252 +pub struct SignedTransactionData { + pub private_key: felt252, + pub public_key: felt252, + pub transaction_hash: felt252, + pub r: felt252, + pub s: felt252 } -pub(crate) fn SIGNED_TX_DATA() -> SignedTransactionData { +pub fn SIGNED_TX_DATA() -> SignedTransactionData { SignedTransactionData { private_key: 1234, public_key: NEW_PUBKEY, @@ -26,7 +26,7 @@ pub(crate) fn SIGNED_TX_DATA() -> SignedTransactionData { } } -pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { +pub fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { let mut calldata = array![]; calldata.append_serde(NAME()); @@ -34,13 +34,13 @@ pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> calldata.append_serde(initial_supply); calldata.append_serde(recipient); - let address = utils::deploy(DualCaseERC20Mock::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(DualCaseERC20Mock::TEST_CLASS_HASH, calldata); IERC20Dispatcher { contract_address: address } } -pub(crate) fn assert_event_owner_removed(contract: ContractAddress, removed_owner_guid: felt252) { - let event = utils::pop_log::(contract).unwrap(); +pub fn assert_event_owner_removed(contract: ContractAddress, removed_owner_guid: felt252) { + let event = test_utils::pop_log::(contract).unwrap(); let expected = AccountComponent::Event::OwnerRemoved(OwnerRemoved { removed_owner_guid }); assert!(event == expected); @@ -48,11 +48,11 @@ pub(crate) fn assert_event_owner_removed(contract: ContractAddress, removed_owne let mut indexed_keys = array![]; indexed_keys.append_serde(selector!("OwnerRemoved")); indexed_keys.append_serde(removed_owner_guid); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } -pub(crate) fn assert_event_owner_added(contract: ContractAddress, new_owner_guid: felt252) { - let event = utils::pop_log::(contract).unwrap(); +pub fn assert_event_owner_added(contract: ContractAddress, new_owner_guid: felt252) { + let event = test_utils::pop_log::(contract).unwrap(); let expected = AccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); assert!(event == expected); @@ -60,10 +60,10 @@ pub(crate) fn assert_event_owner_added(contract: ContractAddress, new_owner_guid let mut indexed_keys = array![]; indexed_keys.append_serde(selector!("OwnerAdded")); indexed_keys.append_serde(new_owner_guid); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } -pub(crate) fn assert_only_event_owner_added(contract: ContractAddress, new_owner_guid: felt252) { +pub fn assert_only_event_owner_added(contract: ContractAddress, new_owner_guid: felt252) { assert_event_owner_added(contract, new_owner_guid); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } diff --git a/src/tests/account/starknet/test_account.cairo b/packages/account/src/tests/starknet/test_account.cairo similarity index 97% rename from src/tests/account/starknet/test_account.cairo rename to packages/account/src/tests/starknet/test_account.cairo index 0a54556e8..668357dc8 100644 --- a/src/tests/account/starknet/test_account.cairo +++ b/packages/account/src/tests/starknet/test_account.cairo @@ -4,15 +4,15 @@ use openzeppelin_account::AccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; use openzeppelin_account::AccountComponent; use openzeppelin_account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; use openzeppelin_account::interface::{ISRC6, ISRC6_ID}; +use openzeppelin_account::tests::mocks::account_mocks::DualCaseAccountMock; use openzeppelin_introspection::interface::{ISRC5, ISRC5_ID}; -use openzeppelin::tests::mocks::account_mocks::DualCaseAccountMock; -use openzeppelin::tests::utils::constants::{ - PUBKEY, NEW_PUBKEY, SALT, ZERO, QUERY_OFFSET, QUERY_VERSION, MIN_TRANSACTION_VERSION -}; -use openzeppelin::tests::utils; use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; use openzeppelin_utils::selectors; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ + PUBKEY, NEW_PUBKEY, SALT, ZERO, QUERY_OFFSET, QUERY_VERSION, MIN_TRANSACTION_VERSION +}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::account::Call; use starknet::contract_address_const; @@ -50,7 +50,7 @@ fn COMPONENT_STATE() -> ComponentState { fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(PUBKEY); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state } @@ -67,7 +67,7 @@ fn setup_dispatcher(data: Option<@SignedTransactionData>) -> AccountABIDispatche } else { calldata.append(PUBKEY); } - let address = utils::deploy(CLASS_HASH(), calldata); + let address = test_utils::deploy(CLASS_HASH(), calldata); AccountABIDispatcher { contract_address: address } } @@ -369,7 +369,7 @@ fn test_public_key_setter_and_getter() { testing::set_caller_address(ACCOUNT_ADDRESS()); state._set_public_key(PUBKEY); - utils::drop_event(ACCOUNT_ADDRESS()); + test_utils::drop_event(ACCOUNT_ADDRESS()); let public_key = state.get_public_key(); assert_eq!(public_key, PUBKEY); @@ -405,7 +405,7 @@ fn test_public_key_setter_and_getter_camel() { testing::set_caller_address(ACCOUNT_ADDRESS()); state._set_public_key(PUBKEY); - utils::drop_event(ACCOUNT_ADDRESS()); + test_utils::drop_event(ACCOUNT_ADDRESS()); let public_key = state.getPublicKey(); assert_eq!(public_key, PUBKEY); diff --git a/src/tests/account/starknet/test_dual_account.cairo b/packages/account/src/tests/starknet/test_dual_account.cairo similarity index 91% rename from src/tests/account/starknet/test_dual_account.cairo rename to packages/account/src/tests/starknet/test_dual_account.cairo index bd2d80dc4..96c7a2e70 100644 --- a/src/tests/account/starknet/test_dual_account.cairo +++ b/packages/account/src/tests/starknet/test_dual_account.cairo @@ -1,13 +1,13 @@ use openzeppelin_account::dual_account::{DualCaseAccountABI, DualCaseAccount}; use openzeppelin_account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; -use openzeppelin_introspection::interface::ISRC5_ID; -use openzeppelin::tests::account::starknet::common::SIGNED_TX_DATA; -use openzeppelin::tests::mocks::account_mocks::{ +use openzeppelin_account::tests::starknet::common::SIGNED_TX_DATA; +use openzeppelin_account::tests::mocks::account_mocks::{ CamelAccountPanicMock, CamelAccountMock, SnakeAccountMock, SnakeAccountPanicMock }; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::{PUBKEY, NEW_PUBKEY}; -use openzeppelin::tests::utils; +use openzeppelin_account::tests::mocks::non_implementing_mock::NonImplementingMock; +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_utils::test_utils::constants::{PUBKEY, NEW_PUBKEY}; +use openzeppelin_utils::test_utils; use starknet::testing; // @@ -16,7 +16,7 @@ use starknet::testing; fn setup_snake() -> (DualCaseAccount, AccountABIDispatcher) { let mut calldata = array![PUBKEY]; - let target = utils::deploy(SnakeAccountMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(SnakeAccountMock::TEST_CLASS_HASH, calldata); ( DualCaseAccount { contract_address: target }, AccountABIDispatcher { contract_address: target } @@ -25,7 +25,7 @@ fn setup_snake() -> (DualCaseAccount, AccountABIDispatcher) { fn setup_camel() -> (DualCaseAccount, AccountABIDispatcher) { let mut calldata = array![PUBKEY]; - let target = utils::deploy(CamelAccountMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(CamelAccountMock::TEST_CLASS_HASH, calldata); ( DualCaseAccount { contract_address: target }, AccountABIDispatcher { contract_address: target } @@ -34,13 +34,13 @@ fn setup_camel() -> (DualCaseAccount, AccountABIDispatcher) { fn setup_non_account() -> DualCaseAccount { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); DualCaseAccount { contract_address: target } } fn setup_account_panic() -> (DualCaseAccount, DualCaseAccount) { - let snake_target = utils::deploy(SnakeAccountPanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelAccountPanicMock::TEST_CLASS_HASH, array![]); + let snake_target = test_utils::deploy(SnakeAccountPanicMock::TEST_CLASS_HASH, array![]); + let camel_target = test_utils::deploy(CamelAccountPanicMock::TEST_CLASS_HASH, array![]); ( DualCaseAccount { contract_address: snake_target }, DualCaseAccount { contract_address: camel_target } diff --git a/src/tests/account/test_secp256k1.cairo b/packages/account/src/tests/test_secp256k1.cairo similarity index 100% rename from src/tests/account/test_secp256k1.cairo rename to packages/account/src/tests/test_secp256k1.cairo diff --git a/src/tests/account/test_signature.cairo b/packages/account/src/tests/test_signature.cairo similarity index 100% rename from src/tests/account/test_signature.cairo rename to packages/account/src/tests/test_signature.cairo diff --git a/packages/account/src/utils/secp256k1.cairo b/packages/account/src/utils/secp256k1.cairo index fe4f00695..838a5e23f 100644 --- a/packages/account/src/utils/secp256k1.cairo +++ b/packages/account/src/utils/secp256k1.cairo @@ -39,7 +39,7 @@ pub impl Secp256k1PointStorePacking of StorePacking { +pub impl Secp256k1PointPartialEq of PartialEq { #[inline(always)] fn eq(lhs: @Secp256k1Point, rhs: @Secp256k1Point) -> bool { (*lhs).get_coordinates().unwrap_syscall() == (*rhs).get_coordinates().unwrap_syscall() @@ -50,7 +50,7 @@ pub(crate) impl Secp256k1PointPartialEq of PartialEq { } } -pub(crate) impl DebugSecp256k1Point of core::fmt::Debug { +pub impl DebugSecp256k1Point of core::fmt::Debug { fn fmt(self: @Secp256k1Point, ref f: Formatter) -> Result<(), Error> { let (x, y) = (*self).get_coordinates().unwrap_syscall(); write!(f, "({x:?},{y:?})") diff --git a/packages/governance/Scarb.toml b/packages/governance/Scarb.toml index 6febe7691..7b065bb14 100644 --- a/packages/governance/Scarb.toml +++ b/packages/governance/Scarb.toml @@ -20,3 +20,6 @@ starknet.workspace = true openzeppelin_access = { path = "../access" } openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } + +[dev-dependencies] +cairo_test.workspace = true diff --git a/packages/governance/src/lib.cairo b/packages/governance/src/lib.cairo index 01d740d38..d1e6ccb58 100644 --- a/packages/governance/src/lib.cairo +++ b/packages/governance/src/lib.cairo @@ -1,2 +1,4 @@ +#[cfg(test)] +mod tests; pub mod timelock; pub mod utils; diff --git a/src/tests/governance.cairo b/packages/governance/src/tests.cairo similarity index 60% rename from src/tests/governance.cairo rename to packages/governance/src/tests.cairo index 3aa8297b3..883a2ac5d 100644 --- a/src/tests/governance.cairo +++ b/packages/governance/src/tests.cairo @@ -1,2 +1,4 @@ +pub(crate) mod mocks; + mod test_timelock; mod test_utils; diff --git a/packages/governance/src/tests/mocks.cairo b/packages/governance/src/tests/mocks.cairo new file mode 100644 index 000000000..6d38a6715 --- /dev/null +++ b/packages/governance/src/tests/mocks.cairo @@ -0,0 +1,2 @@ +pub(crate) mod non_implementing_mock; +pub(crate) mod timelock_mocks; diff --git a/packages/governance/src/tests/mocks/non_implementing_mock.cairo b/packages/governance/src/tests/mocks/non_implementing_mock.cairo new file mode 100644 index 000000000..c1212dbdd --- /dev/null +++ b/packages/governance/src/tests/mocks/non_implementing_mock.cairo @@ -0,0 +1,10 @@ +#[starknet::contract] +pub(crate) mod NonImplementingMock { + #[storage] + struct Storage {} + + #[external(v0)] + fn nope(self: @ContractState) -> bool { + false + } +} diff --git a/src/tests/mocks/timelock_mocks.cairo b/packages/governance/src/tests/mocks/timelock_mocks.cairo similarity index 100% rename from src/tests/mocks/timelock_mocks.cairo rename to packages/governance/src/tests/mocks/timelock_mocks.cairo diff --git a/src/tests/governance/test_timelock.cairo b/packages/governance/src/tests/test_timelock.cairo similarity index 96% rename from src/tests/governance/test_timelock.cairo rename to packages/governance/src/tests/test_timelock.cairo index 269999994..555930f22 100644 --- a/src/tests/governance/test_timelock.cairo +++ b/packages/governance/src/tests/test_timelock.cairo @@ -1,5 +1,4 @@ use core::hash::{HashStateTrait, HashStateExTrait}; -use core::num::traits::Zero; use core::pedersen::PedersenTrait; use openzeppelin_access::accesscontrol::AccessControlComponent::{ AccessControlImpl, InternalImpl as AccessControlInternalImpl @@ -7,6 +6,16 @@ use openzeppelin_access::accesscontrol::AccessControlComponent::{ use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; use openzeppelin_access::accesscontrol::interface::IACCESSCONTROL_ID; use openzeppelin_access::accesscontrol::interface::IAccessControl; +use openzeppelin_governance::tests::mocks::timelock_mocks::MockContract; +use openzeppelin_governance::tests::mocks::timelock_mocks::{ + IMockContractDispatcher, IMockContractDispatcherTrait +}; +use openzeppelin_governance::tests::mocks::timelock_mocks::{ + ITimelockAttackerDispatcher, ITimelockAttackerDispatcherTrait +}; +use openzeppelin_governance::tests::mocks::timelock_mocks::{ + TimelockControllerMock, TimelockAttackerMock +}; use openzeppelin_governance::timelock::OperationState; use openzeppelin_governance::timelock::TimelockControllerComponent::{ CallScheduled, CallExecuted, CallSalt, CallCancelled, MinDelayChanged @@ -21,18 +30,10 @@ use openzeppelin_governance::timelock::interface::{ use openzeppelin_governance::timelock::{PROPOSER_ROLE, EXECUTOR_ROLE, CANCELLER_ROLE}; use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; -use openzeppelin::tests::mocks::timelock_mocks::MockContract; -use openzeppelin::tests::mocks::timelock_mocks::{ - IMockContractDispatcher, IMockContractDispatcherTrait -}; -use openzeppelin::tests::mocks::timelock_mocks::{ - ITimelockAttackerDispatcher, ITimelockAttackerDispatcherTrait -}; -use openzeppelin::tests::mocks::timelock_mocks::{TimelockControllerMock, TimelockAttackerMock}; -use openzeppelin::tests::utils::constants::{ADMIN, ZERO, OTHER, SALT}; -use openzeppelin::tests::utils; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ADMIN, ZERO, OTHER, SALT}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::account::Call; use starknet::contract_address_const; @@ -133,18 +134,18 @@ fn deploy_timelock() -> TimelockABIDispatcher { calldata.append_serde(executors); calldata.append_serde(admin); - let address = utils::deploy(TimelockControllerMock::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(TimelockControllerMock::TEST_CLASS_HASH, calldata); // Events dropped: // - 5 RoleGranted: self, proposer, canceller, executor, admin // - MinDelayChanged - utils::drop_events(address, 6); + test_utils::drop_events(address, 6); TimelockABIDispatcher { contract_address: address } } fn deploy_mock_target() -> IMockContractDispatcher { let mut calldata = array![]; - let address = utils::deploy(MockContract::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(MockContract::TEST_CLASS_HASH, calldata); IMockContractDispatcher { contract_address: address } } @@ -158,7 +159,7 @@ fn setup_dispatchers() -> (TimelockABIDispatcher, IMockContractDispatcher) { fn deploy_attacker() -> ITimelockAttackerDispatcher { let mut calldata = array![]; - let address = utils::deploy(TimelockAttackerMock::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(TimelockAttackerMock::TEST_CLASS_HASH, calldata); ITimelockAttackerDispatcher { contract_address: address } } @@ -1209,7 +1210,7 @@ fn test_initializer_min_delay() { // - 1 proposer // - 1 canceller // - 1 executor - utils::drop_events(ZERO(), 4); + test_utils::drop_events(ZERO(), 4); assert_only_event_delay_change(ZERO(), 0, MIN_DELAY); } @@ -1635,7 +1636,7 @@ fn assert_operation_state(timelock: TimelockABIDispatcher, exp_state: OperationS // fn assert_event_delay_change(contract: ContractAddress, old_duration: u64, new_duration: u64) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = TimelockControllerComponent::Event::MinDelayChanged( MinDelayChanged { old_duration, new_duration } ); @@ -1644,7 +1645,7 @@ fn assert_event_delay_change(contract: ContractAddress, old_duration: u64, new_d fn assert_only_event_delay_change(contract: ContractAddress, old_duration: u64, new_duration: u64) { assert_event_delay_change(contract, old_duration, new_duration); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } // @@ -1659,7 +1660,7 @@ fn assert_event_schedule( predecessor: felt252, delay: u64 ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = TimelockControllerComponent::Event::CallScheduled( CallScheduled { id, index, call, predecessor, delay } ); @@ -1670,7 +1671,7 @@ fn assert_event_schedule( indexed_keys.append_serde(selector!("CallScheduled")); indexed_keys.append_serde(id); indexed_keys.append_serde(index); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } fn assert_only_event_schedule( @@ -1682,7 +1683,7 @@ fn assert_only_event_schedule( delay: u64 ) { assert_event_schedule(contract, id, index, call, predecessor, delay); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } fn assert_events_schedule_batch( @@ -1702,7 +1703,7 @@ fn assert_only_events_schedule_batch( contract: ContractAddress, id: felt252, calls: Span, predecessor: felt252, delay: u64 ) { assert_events_schedule_batch(contract, id, calls, predecessor, delay); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } // @@ -1710,14 +1711,14 @@ fn assert_only_events_schedule_batch( // fn assert_event_call_salt(contract: ContractAddress, id: felt252, salt: felt252) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = TimelockControllerComponent::Event::CallSalt(CallSalt { id, salt }); assert!(event == expected); } fn assert_only_event_call_salt(contract: ContractAddress, id: felt252, salt: felt252) { assert_event_call_salt(contract, id, salt); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } // @@ -1725,7 +1726,7 @@ fn assert_only_event_call_salt(contract: ContractAddress, id: felt252, salt: fel // fn assert_event_execute(contract: ContractAddress, id: felt252, index: felt252, call: Call) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = TimelockControllerComponent::Event::CallExecuted( CallExecuted { id, index, call } ); @@ -1736,12 +1737,12 @@ fn assert_event_execute(contract: ContractAddress, id: felt252, index: felt252, indexed_keys.append_serde(selector!("CallExecuted")); indexed_keys.append_serde(id); indexed_keys.append_serde(index); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } fn assert_only_event_execute(contract: ContractAddress, id: felt252, index: felt252, call: Call) { assert_event_execute(contract, id, index, call); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } fn assert_events_execute_batch(contract: ContractAddress, id: felt252, calls: Span) { @@ -1757,7 +1758,7 @@ fn assert_events_execute_batch(contract: ContractAddress, id: felt252, calls: Sp fn assert_only_events_execute_batch(contract: ContractAddress, id: felt252, calls: Span) { assert_events_execute_batch(contract, id, calls); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } // @@ -1765,7 +1766,7 @@ fn assert_only_events_execute_batch(contract: ContractAddress, id: felt252, call // fn assert_event_cancel(contract: ContractAddress, id: felt252) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = TimelockControllerComponent::Event::CallCancelled(CallCancelled { id }); assert!(event == expected); @@ -1773,12 +1774,12 @@ fn assert_event_cancel(contract: ContractAddress, id: felt252) { let mut indexed_keys = array![]; indexed_keys.append_serde(selector!("CallCancelled")); indexed_keys.append_serde(id); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } fn assert_only_event_cancel(contract: ContractAddress, id: felt252) { assert_event_cancel(contract, id); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } // @@ -1786,7 +1787,7 @@ fn assert_only_event_cancel(contract: ContractAddress, id: felt252) { // fn assert_event_delay(contract: ContractAddress, old_duration: u64, new_duration: u64) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = TimelockControllerComponent::Event::MinDelayChanged( MinDelayChanged { old_duration, new_duration } ); @@ -1795,5 +1796,5 @@ fn assert_event_delay(contract: ContractAddress, old_duration: u64, new_duration fn assert_only_event_delay(contract: ContractAddress, old_duration: u64, new_duration: u64) { assert_event_delay(contract, old_duration, new_duration); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } diff --git a/src/tests/governance/test_utils.cairo b/packages/governance/src/tests/test_utils.cairo similarity index 100% rename from src/tests/governance/test_utils.cairo rename to packages/governance/src/tests/test_utils.cairo diff --git a/packages/governance/src/timelock/utils/call_impls.cairo b/packages/governance/src/timelock/utils/call_impls.cairo index 428259e57..5a46b6efe 100644 --- a/packages/governance/src/timelock/utils/call_impls.cairo +++ b/packages/governance/src/timelock/utils/call_impls.cairo @@ -4,7 +4,7 @@ use core::hash::{HashStateTrait, HashStateExTrait, Hash}; use starknet::account::Call; -pub(crate) impl HashCallImpl, +Drop> of Hash { +pub impl HashCallImpl, +Drop> of Hash { fn update_state(mut state: S, value: Call) -> S { let Call { to, selector, calldata } = value; state = state.update_with(to).update_with(selector).update_with(calldata.len()); @@ -16,7 +16,7 @@ pub(crate) impl HashCallImpl, +Drop> of Hash { } } -pub(crate) impl HashCallsImpl, +Drop> of Hash, S> { +pub impl HashCallsImpl, +Drop> of Hash, S> { fn update_state(mut state: S, value: Span) -> S { state = state.update_with(value.len()); for call in value { @@ -27,7 +27,7 @@ pub(crate) impl HashCallsImpl, +Drop> of Hash { +pub impl CallPartialEq of PartialEq { #[inline(always)] fn eq(lhs: @Call, rhs: @Call) -> bool { let Call { to: l_to, selector: l_selector, calldata: l_calldata } = lhs; diff --git a/packages/introspection/Scarb.toml b/packages/introspection/Scarb.toml index 4cb78d346..978c7dbdf 100644 --- a/packages/introspection/Scarb.toml +++ b/packages/introspection/Scarb.toml @@ -18,3 +18,6 @@ fmt.workspace = true [dependencies] starknet.workspace = true + +[dev-dependencies] +cairo_test.workspace = true diff --git a/packages/introspection/src/lib.cairo b/packages/introspection/src/lib.cairo index 584b93016..01a03e7d8 100644 --- a/packages/introspection/src/lib.cairo +++ b/packages/introspection/src/lib.cairo @@ -1,2 +1,5 @@ pub mod interface; pub mod src5; + +#[cfg(test)] +mod tests; diff --git a/packages/introspection/src/tests.cairo b/packages/introspection/src/tests.cairo new file mode 100644 index 000000000..0fe30300f --- /dev/null +++ b/packages/introspection/src/tests.cairo @@ -0,0 +1,3 @@ +pub(crate) mod mocks; + +mod test_src5; diff --git a/packages/introspection/src/tests/mocks.cairo b/packages/introspection/src/tests/mocks.cairo new file mode 100644 index 000000000..dc995e8e3 --- /dev/null +++ b/packages/introspection/src/tests/mocks.cairo @@ -0,0 +1 @@ +pub(crate) mod src5_mocks; diff --git a/src/tests/mocks/src5_mocks.cairo b/packages/introspection/src/tests/mocks/src5_mocks.cairo similarity index 100% rename from src/tests/mocks/src5_mocks.cairo rename to packages/introspection/src/tests/mocks/src5_mocks.cairo diff --git a/src/tests/introspection/test_src5.cairo b/packages/introspection/src/tests/test_src5.cairo similarity index 95% rename from src/tests/introspection/test_src5.cairo rename to packages/introspection/src/tests/test_src5.cairo index a46498ae8..9fa6cf108 100644 --- a/src/tests/introspection/test_src5.cairo +++ b/packages/introspection/src/tests/test_src5.cairo @@ -1,7 +1,7 @@ use openzeppelin_introspection::interface::{ISRC5_ID, ISRC5}; use openzeppelin_introspection::src5::SRC5Component::InternalTrait; use openzeppelin_introspection::src5::SRC5Component; -use openzeppelin::tests::mocks::src5_mocks::SRC5Mock; +use openzeppelin_introspection::tests::mocks::src5_mocks::SRC5Mock; const OTHER_ID: felt252 = 0x12345678; diff --git a/packages/presets/Scarb.toml b/packages/presets/Scarb.toml index 2f5d3ea58..80170f0f9 100644 --- a/packages/presets/Scarb.toml +++ b/packages/presets/Scarb.toml @@ -23,3 +23,6 @@ openzeppelin_account = { path = "../account" } openzeppelin_introspection = { path = "../introspection" } openzeppelin_token = { path = "../token" } openzeppelin_upgrades = { path = "../upgrades" } + +[dev-dependencies] +cairo_test.workspace = true diff --git a/packages/presets/src/account.cairo b/packages/presets/src/account.cairo index 78a6e75a3..3c5c10c8b 100644 --- a/packages/presets/src/account.cairo +++ b/packages/presets/src/account.cairo @@ -6,7 +6,7 @@ /// OpenZeppelin's upgradeable account which can change its public key and declare, deploy, or call /// contracts. #[starknet::contract(account)] -pub(crate) mod AccountUpgradeable { +pub mod AccountUpgradeable { use openzeppelin_account::AccountComponent; use openzeppelin_introspection::src5::SRC5Component; use openzeppelin_upgrades::UpgradeableComponent; @@ -48,7 +48,7 @@ pub(crate) mod AccountUpgradeable { } #[constructor] - pub(crate) fn constructor(ref self: ContractState, public_key: felt252) { + pub fn constructor(ref self: ContractState, public_key: felt252) { self.account.initializer(public_key); } diff --git a/packages/presets/src/erc1155.cairo b/packages/presets/src/erc1155.cairo index 35290b3bf..cc387852a 100644 --- a/packages/presets/src/erc1155.cairo +++ b/packages/presets/src/erc1155.cairo @@ -9,7 +9,7 @@ /// For more complex or custom contracts, use Wizard for Cairo /// https://wizard.openzeppelin.com/cairo #[starknet::contract] -pub(crate) mod ERC1155Upgradeable { +pub mod ERC1155Upgradeable { use openzeppelin_access::ownable::OwnableComponent; use openzeppelin_introspection::src5::SRC5Component; use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; diff --git a/packages/presets/src/erc20.cairo b/packages/presets/src/erc20.cairo index 0ea248d22..8b213ee86 100644 --- a/packages/presets/src/erc20.cairo +++ b/packages/presets/src/erc20.cairo @@ -10,7 +10,7 @@ /// For more complex or custom contracts, use Wizard for Cairo /// https://wizard.openzeppelin.com/cairo #[starknet::contract] -pub(crate) mod ERC20Upgradeable { +pub mod ERC20Upgradeable { use openzeppelin_access::ownable::OwnableComponent; use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use openzeppelin_upgrades::UpgradeableComponent; diff --git a/packages/presets/src/erc721.cairo b/packages/presets/src/erc721.cairo index a36fb720f..800b587e2 100644 --- a/packages/presets/src/erc721.cairo +++ b/packages/presets/src/erc721.cairo @@ -9,7 +9,7 @@ /// For more complex or custom contracts, use Wizard for Cairo /// https://wizard.openzeppelin.com/cairo #[starknet::contract] -pub(crate) mod ERC721Upgradeable { +pub mod ERC721Upgradeable { use openzeppelin_access::ownable::OwnableComponent; use openzeppelin_introspection::src5::SRC5Component; use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; diff --git a/packages/presets/src/lib.cairo b/packages/presets/src/lib.cairo index e7dd01ef0..38eab598a 100644 --- a/packages/presets/src/lib.cairo +++ b/packages/presets/src/lib.cairo @@ -1,14 +1,17 @@ -pub(crate) mod account; -pub(crate) mod erc1155; -pub(crate) mod erc20; -pub(crate) mod erc721; -pub(crate) mod eth_account; +pub mod account; +pub mod erc1155; +pub mod erc20; +pub mod erc721; +pub mod eth_account; pub mod interfaces; -pub(crate) mod universal_deployer; -pub(crate) use account::AccountUpgradeable; -pub(crate) use erc1155::ERC1155Upgradeable; -pub(crate) use erc20::ERC20Upgradeable; -pub(crate) use erc721::ERC721Upgradeable; -pub(crate) use eth_account::EthAccountUpgradeable; -pub(crate) use universal_deployer::UniversalDeployer; +#[cfg(test)] +mod tests; +pub mod universal_deployer; + +pub use account::AccountUpgradeable; +pub use erc1155::ERC1155Upgradeable; +pub use erc20::ERC20Upgradeable; +pub use erc721::ERC721Upgradeable; +pub use eth_account::EthAccountUpgradeable; +pub use universal_deployer::UniversalDeployer; diff --git a/src/tests/presets.cairo b/packages/presets/src/tests.cairo similarity index 83% rename from src/tests/presets.cairo rename to packages/presets/src/tests.cairo index 87e7cb2f4..88a945487 100644 --- a/src/tests/presets.cairo +++ b/packages/presets/src/tests.cairo @@ -1,3 +1,5 @@ +pub(crate) mod mocks; + mod test_account; mod test_erc1155; mod test_erc20; diff --git a/packages/presets/src/tests/mocks.cairo b/packages/presets/src/tests/mocks.cairo new file mode 100644 index 000000000..61147b2a1 --- /dev/null +++ b/packages/presets/src/tests/mocks.cairo @@ -0,0 +1,7 @@ +pub(crate) mod account_mocks; +pub(crate) mod erc1155_mocks; +pub(crate) mod erc20_mocks; +pub(crate) mod erc721_mocks; +pub(crate) mod erc721_receiver_mocks; +pub(crate) mod eth_account_mocks; +pub(crate) mod non_implementing_mock; diff --git a/packages/presets/src/tests/mocks/account_mocks.cairo b/packages/presets/src/tests/mocks/account_mocks.cairo new file mode 100644 index 000000000..c2f7d9f57 --- /dev/null +++ b/packages/presets/src/tests/mocks/account_mocks.cairo @@ -0,0 +1,223 @@ +#[starknet::contract(account)] +pub(crate) mod DualCaseAccountMock { + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: AccountComponent, storage: account, event: AccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // Account + #[abi(embed_v0)] + impl SRC6Impl = AccountComponent::SRC6Impl; + #[abi(embed_v0)] + impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl; + #[abi(embed_v0)] + impl DeclarerImpl = AccountComponent::DeclarerImpl; + #[abi(embed_v0)] + impl DeployableImpl = AccountComponent::DeployableImpl; + impl AccountInternalImpl = AccountComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + account: AccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccountEvent: AccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: felt252) { + self.account.initializer(public_key); + } +} + +#[starknet::contract(account)] +pub(crate) mod SnakeAccountMock { + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: AccountComponent, storage: account, event: AccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // Account + #[abi(embed_v0)] + impl SRC6Impl = AccountComponent::SRC6Impl; + #[abi(embed_v0)] + impl PublicKeyImpl = AccountComponent::PublicKeyImpl; + impl AccountInternalImpl = AccountComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + account: AccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccountEvent: AccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: felt252) { + self.account.initializer(public_key); + } +} + +#[starknet::contract(account)] +pub(crate) mod CamelAccountMock { + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; + use starknet::account::Call; + + component!(path: AccountComponent, storage: account, event: AccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // Account + #[abi(embed_v0)] + impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl; + #[abi(embed_v0)] + impl PublicKeyCamelImpl = AccountComponent::PublicKeyCamelImpl; + impl SRC6Impl = AccountComponent::SRC6Impl; + impl AccountInternalImpl = AccountComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + account: AccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccountEvent: AccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, publicKey: felt252) { + self.account.initializer(publicKey); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn __execute__(self: @ContractState, mut calls: Array) -> Array> { + self.account.__execute__(calls) + } + + #[external(v0)] + fn __validate__(self: @ContractState, mut calls: Array) -> felt252 { + self.account.__validate__(calls) + } + } +} + +// Although these modules are designed to panic, functions +// still need a valid return value. We chose: +// +// 3 for felt252 +// false for bool + +#[starknet::contract] +pub(crate) mod SnakeAccountPanicMock { + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn set_public_key( + ref self: ContractState, new_public_key: felt252, signature: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn get_public_key(self: @ContractState) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn is_valid_signature( + self: @ContractState, hash: felt252, signature: Array + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelAccountPanicMock { + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn setPublicKey(ref self: ContractState, newPublicKey: felt252, signature: Span) { + panic!("Some error"); + } + + #[external(v0)] + fn getPublicKey(self: @ContractState) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn isValidSignature( + self: @ContractState, hash: felt252, signature: Array + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { + panic!("Some error"); + false + } + } +} diff --git a/src/tests/mocks/erc1155_mocks.cairo b/packages/presets/src/tests/mocks/erc1155_mocks.cairo similarity index 100% rename from src/tests/mocks/erc1155_mocks.cairo rename to packages/presets/src/tests/mocks/erc1155_mocks.cairo diff --git a/packages/presets/src/tests/mocks/erc20_mocks.cairo b/packages/presets/src/tests/mocks/erc20_mocks.cairo new file mode 100644 index 000000000..80a66d34f --- /dev/null +++ b/packages/presets/src/tests/mocks/erc20_mocks.cairo @@ -0,0 +1,253 @@ +#[starknet::contract] +pub(crate) mod DualCaseERC20Mock { + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20Impl = ERC20Component::ERC20Impl; + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; + #[abi(embed_v0)] + impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; + impl InternalImpl = ERC20Component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + initial_supply: u256, + recipient: ContractAddress + ) { + self.erc20.initializer(name, symbol); + self.erc20.mint(recipient, initial_supply); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC20Mock { + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20Impl = ERC20Component::ERC20Impl; + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; + impl InternalImpl = ERC20Component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + initial_supply: u256, + recipient: ContractAddress + ) { + self.erc20.initializer(name, symbol); + self.erc20.mint(recipient, initial_supply); + } +} + +#[starknet::contract] +pub(crate) mod CamelERC20Mock { + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; + #[abi(embed_v0)] + impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; + + // `ERC20Impl` is not embedded because it would defeat the purpose of the + // mock. The `ERC20Impl` case-agnostic methods are manually exposed. + impl ERC20Impl = ERC20Component::ERC20Impl; + impl InternalImpl = ERC20Component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + initial_supply: u256, + recipient: ContractAddress + ) { + self.erc20.initializer(name, symbol); + self.erc20.mint(recipient, initial_supply); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn allowance( + self: @ContractState, owner: ContractAddress, spender: ContractAddress + ) -> u256 { + self.erc20.allowance(owner, spender) + } + + #[external(v0)] + fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { + self.erc20.transfer(recipient, amount) + } + + #[external(v0)] + fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool { + self.erc20.approve(spender, amount) + } + } +} + +/// Although these modules are designed to panic, functions +/// still need a valid return value. We chose: +/// +/// 3 for felt252, u8, and u256 +/// zero for ContractAddress +/// false for bool +#[starknet::contract] +pub(crate) mod SnakeERC20Panic { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn name(self: @ContractState) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn symbol(self: @ContractState) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn decimals(self: @ContractState) -> u8 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn allowance( + self: @ContractState, owner: ContractAddress, spender: ContractAddress + ) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn total_supply(self: @ContractState) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn transfer_from( + ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256 + ) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC20Panic { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn totalSupply(self: @ContractState) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn transferFrom( + ref self: ContractState, + sender: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) { + panic!("Some error"); + } + } +} diff --git a/src/tests/mocks/erc721_mocks.cairo b/packages/presets/src/tests/mocks/erc721_mocks.cairo similarity index 100% rename from src/tests/mocks/erc721_mocks.cairo rename to packages/presets/src/tests/mocks/erc721_mocks.cairo diff --git a/src/tests/mocks/erc721_receiver_mocks.cairo b/packages/presets/src/tests/mocks/erc721_receiver_mocks.cairo similarity index 99% rename from src/tests/mocks/erc721_receiver_mocks.cairo rename to packages/presets/src/tests/mocks/erc721_receiver_mocks.cairo index 0cdd3dec9..e321c0d58 100644 --- a/src/tests/mocks/erc721_receiver_mocks.cairo +++ b/packages/presets/src/tests/mocks/erc721_receiver_mocks.cairo @@ -1,4 +1,4 @@ -use openzeppelin::tests::utils::constants::SUCCESS; +use openzeppelin_utils::test_utils::constants::SUCCESS; #[starknet::contract] pub(crate) mod DualCaseERC721ReceiverMock { diff --git a/packages/presets/src/tests/mocks/eth_account_mocks.cairo b/packages/presets/src/tests/mocks/eth_account_mocks.cairo new file mode 100644 index 000000000..b230e524d --- /dev/null +++ b/packages/presets/src/tests/mocks/eth_account_mocks.cairo @@ -0,0 +1,228 @@ +#[starknet::contract(account)] +pub(crate) mod DualCaseEthAccountMock { + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC6Impl = EthAccountComponent::SRC6Impl; + #[abi(embed_v0)] + impl SRC6CamelOnlyImpl = EthAccountComponent::SRC6CamelOnlyImpl; + #[abi(embed_v0)] + impl DeclarerImpl = EthAccountComponent::DeclarerImpl; + #[abi(embed_v0)] + impl DeployableImpl = EthAccountComponent::DeployableImpl; + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + eth_account: EthAccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + EthAccountEvent: EthAccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: EthPublicKey) { + self.eth_account.initializer(public_key); + } +} + +#[starknet::contract(account)] +pub(crate) mod SnakeEthAccountMock { + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC6Impl = EthAccountComponent::SRC6Impl; + #[abi(embed_v0)] + impl PublicKeyImpl = EthAccountComponent::PublicKeyImpl; + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + eth_account: EthAccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + EthAccountEvent: EthAccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: EthPublicKey) { + self.eth_account.initializer(public_key); + } +} + +#[starknet::contract(account)] +pub(crate) mod CamelEthAccountMock { + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_introspection::src5::SRC5Component; + use starknet::account::Call; + + component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC6CamelOnlyImpl = EthAccountComponent::SRC6CamelOnlyImpl; + #[abi(embed_v0)] + impl PublicKeyCamelImpl = + EthAccountComponent::PublicKeyCamelImpl; + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + impl SRC6Impl = EthAccountComponent::SRC6Impl; + impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + eth_account: EthAccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + EthAccountEvent: EthAccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, publicKey: EthPublicKey) { + self.eth_account.initializer(publicKey); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn __execute__(self: @ContractState, mut calls: Array) -> Array> { + self.eth_account.__execute__(calls) + } + + #[external(v0)] + fn __validate__(self: @ContractState, mut calls: Array) -> felt252 { + self.eth_account.__validate__(calls) + } + } +} + +// Although these modules are designed to panic, functions +// still need a valid return value. We chose: +// +// 3 for felt252 +// false for bool + +#[starknet::contract] +pub(crate) mod SnakeEthAccountPanicMock { + use openzeppelin_account::interface::EthPublicKey; + use starknet::SyscallResultTrait; + use starknet::secp256_trait::Secp256Trait; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn set_public_key( + ref self: ContractState, new_public_key: EthPublicKey, signature: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn get_public_key(self: @ContractState) -> EthPublicKey { + panic!("Some error"); + Secp256Trait::secp256_ec_new_syscall(3, 3).unwrap_syscall().unwrap() + } + + #[external(v0)] + fn is_valid_signature( + self: @ContractState, hash: felt252, signature: Array + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelEthAccountPanicMock { + use openzeppelin_account::interface::EthPublicKey; + use starknet::SyscallResultTrait; + use starknet::secp256_trait::Secp256Trait; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn setPublicKey( + ref self: ContractState, newPublicKey: EthPublicKey, signature: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn getPublicKey(self: @ContractState) -> EthPublicKey { + panic!("Some error"); + Secp256Trait::secp256_ec_new_syscall(3, 3).unwrap_syscall().unwrap() + } + + #[external(v0)] + fn isValidSignature( + self: @ContractState, hash: felt252, signature: Array + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { + panic!("Some error"); + false + } + } +} diff --git a/packages/presets/src/tests/mocks/non_implementing_mock.cairo b/packages/presets/src/tests/mocks/non_implementing_mock.cairo new file mode 100644 index 000000000..c1212dbdd --- /dev/null +++ b/packages/presets/src/tests/mocks/non_implementing_mock.cairo @@ -0,0 +1,10 @@ +#[starknet::contract] +pub(crate) mod NonImplementingMock { + #[storage] + struct Storage {} + + #[external(v0)] + fn nope(self: @ContractState) -> bool { + false + } +} diff --git a/src/tests/presets/test_account.cairo b/packages/presets/src/tests/test_account.cairo similarity index 97% rename from src/tests/presets/test_account.cairo rename to packages/presets/src/tests/test_account.cairo index 284de0718..f2634a58f 100644 --- a/src/tests/presets/test_account.cairo +++ b/packages/presets/src/tests/test_account.cairo @@ -1,27 +1,27 @@ use core::num::traits::Zero; use openzeppelin_account::AccountComponent::{OwnerAdded, OwnerRemoved}; use openzeppelin_account::interface::ISRC6_ID; -use openzeppelin_introspection::interface::ISRC5_ID; -use openzeppelin_presets::AccountUpgradeable; -use openzeppelin_presets::interfaces::{ - AccountUpgradeableABIDispatcher, AccountUpgradeableABIDispatcherTrait -}; -use openzeppelin::tests::account::starknet::common::{ +use openzeppelin_account::tests::starknet::common::{ assert_only_event_owner_added, assert_event_owner_removed }; -use openzeppelin::tests::account::starknet::common::{ +use openzeppelin_account::tests::starknet::common::{ deploy_erc20, SIGNED_TX_DATA, SignedTransactionData }; -use openzeppelin::tests::mocks::account_mocks::SnakeAccountMock; -use openzeppelin::tests::upgrades::common::assert_only_event_upgraded; -use openzeppelin::tests::utils::constants::{ - PUBKEY, NEW_PUBKEY, SALT, ZERO, CALLER, RECIPIENT, OTHER, QUERY_OFFSET, QUERY_VERSION, - MIN_TRANSACTION_VERSION, CLASS_HASH_ZERO +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_presets::AccountUpgradeable; +use openzeppelin_presets::interfaces::{ + AccountUpgradeableABIDispatcher, AccountUpgradeableABIDispatcherTrait }; -use openzeppelin::tests::utils; +use openzeppelin_presets::tests::mocks::account_mocks::SnakeAccountMock; use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin_upgrades::tests::common::assert_only_event_upgraded; use openzeppelin_utils::selectors; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ + PUBKEY, NEW_PUBKEY, SALT, ZERO, CALLER, RECIPIENT, OTHER, QUERY_OFFSET, QUERY_VERSION, + MIN_TRANSACTION_VERSION, CLASS_HASH_ZERO +}; +use openzeppelin_utils::test_utils; use starknet::account::Call; use starknet::testing; use starknet::{ContractAddress, ClassHash}; @@ -40,8 +40,8 @@ fn V2_CLASS_HASH() -> ClassHash { fn setup_dispatcher() -> AccountUpgradeableABIDispatcher { let calldata = array![PUBKEY]; - let target = utils::deploy(CLASS_HASH(), calldata); - utils::drop_event(target); + let target = test_utils::deploy(CLASS_HASH(), calldata); + test_utils::drop_event(target); AccountUpgradeableABIDispatcher { contract_address: target } } @@ -61,7 +61,7 @@ fn setup_dispatcher_with_data( } else { calldata.append(PUBKEY); } - let address = utils::deploy(CLASS_HASH(), calldata); + let address = test_utils::deploy(CLASS_HASH(), calldata); AccountUpgradeableABIDispatcher { contract_address: address } } diff --git a/src/tests/presets/test_erc1155.cairo b/packages/presets/src/tests/test_erc1155.cairo similarity index 97% rename from src/tests/presets/test_erc1155.cairo rename to packages/presets/src/tests/test_erc1155.cairo index 7073c6516..6c3b3ac7c 100644 --- a/src/tests/presets/test_erc1155.cairo +++ b/packages/presets/src/tests/test_erc1155.cairo @@ -1,29 +1,28 @@ use core::num::traits::Zero; -use openzeppelin_introspection; +use openzeppelin_access::tests::common::assert_event_ownership_transferred; use openzeppelin_presets::ERC1155Upgradeable; use openzeppelin_presets::interfaces::{ ERC1155UpgradeableABIDispatcher, ERC1155UpgradeableABIDispatcherTrait }; -use openzeppelin::tests::access::common::assert_event_ownership_transferred; -use openzeppelin::tests::mocks::erc1155_mocks::SnakeERC1155Mock; -use openzeppelin::tests::token::erc1155::common::{ +use openzeppelin_presets::tests::mocks::erc1155_mocks::SnakeERC1155Mock; +use openzeppelin_token::erc1155::interface::{IERC1155CamelDispatcher, IERC1155CamelDispatcherTrait}; +use openzeppelin_token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; +use openzeppelin_token::erc1155; +use openzeppelin_token::tests::erc1155::common::{ assert_only_event_transfer_single, assert_only_event_transfer_batch, assert_only_event_approval_for_all }; -use openzeppelin::tests::token::erc1155::common::{ +use openzeppelin_token::tests::erc1155::common::{ setup_account, setup_receiver, setup_camel_receiver, setup_account_with_salt, setup_src5 }; -use openzeppelin::tests::token::erc1155::common::{get_ids_and_values, get_ids_and_split_values}; -use openzeppelin::tests::upgrades::common::assert_only_event_upgraded; -use openzeppelin::tests::utils::constants::{ +use openzeppelin_token::tests::erc1155::common::{get_ids_and_values, get_ids_and_split_values}; +use openzeppelin_upgrades::tests::common::assert_only_event_upgraded; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ EMPTY_DATA, ZERO, OWNER, RECIPIENT, CLASS_HASH_ZERO, OPERATOR, OTHER, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 }; -use openzeppelin::tests::utils; -use openzeppelin_token::erc1155::interface::{IERC1155CamelDispatcher, IERC1155CamelDispatcherTrait}; -use openzeppelin_token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; -use openzeppelin_token::erc1155; -use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils; use starknet::testing; use starknet::{ContractAddress, ClassHash}; @@ -50,14 +49,14 @@ fn setup_dispatcher_with_event() -> (ERC1155UpgradeableABIDispatcher, ContractAd calldata.append_serde(values); calldata.append_serde(owner); - let address = utils::deploy(ERC1155Upgradeable::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(ERC1155Upgradeable::TEST_CLASS_HASH, calldata); (ERC1155UpgradeableABIDispatcher { contract_address: address }, owner) } fn setup_dispatcher() -> (ERC1155UpgradeableABIDispatcher, ContractAddress) { let (dispatcher, owner) = setup_dispatcher_with_event(); - utils::drop_event(dispatcher.contract_address); // `TransferOwnership` - utils::drop_event(dispatcher.contract_address); // `Transfer` + test_utils::drop_event(dispatcher.contract_address); // `TransferOwnership` + test_utils::drop_event(dispatcher.contract_address); // `Transfer` (dispatcher, owner) } @@ -80,7 +79,8 @@ fn test_constructor() { .supports_interface(erc1155::interface::IERC1155_METADATA_URI_ID); assert!(supports_ierc1155_metadata_uri); - let supports_isrc5 = dispatcher.supports_interface(introspection::interface::ISRC5_ID); + let supports_isrc5 = dispatcher + .supports_interface(openzeppelin_introspection::interface::ISRC5_ID); assert!(supports_isrc5); } diff --git a/src/tests/presets/test_erc20.cairo b/packages/presets/src/tests/test_erc20.cairo similarity index 95% rename from src/tests/presets/test_erc20.cairo rename to packages/presets/src/tests/test_erc20.cairo index 9f39fc240..ec742b124 100644 --- a/src/tests/presets/test_erc20.cairo +++ b/packages/presets/src/tests/test_erc20.cairo @@ -1,23 +1,23 @@ use core::integer::BoundedInt; use core::num::traits::Zero; use openzeppelin_access::ownable::OwnableComponent::OwnershipTransferred; +use openzeppelin_access::tests::common::assert_event_ownership_transferred; use openzeppelin_presets::ERC20Upgradeable; use openzeppelin_presets::interfaces::{ ERC20UpgradeableABIDispatcher, ERC20UpgradeableABIDispatcherTrait }; -use openzeppelin::tests::access::common::assert_event_ownership_transferred; -use openzeppelin::tests::mocks::erc20_mocks::SnakeERC20Mock; -use openzeppelin::tests::token::erc20::common::{ +use openzeppelin_presets::tests::mocks::erc20_mocks::SnakeERC20Mock; +use openzeppelin_token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; +use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin_token::tests::erc20::common::{ assert_event_approval, assert_only_event_approval, assert_only_event_transfer }; -use openzeppelin::tests::upgrades::common::assert_only_event_upgraded; -use openzeppelin::tests::utils::constants::{ +use openzeppelin_upgrades::tests::common::assert_only_event_upgraded; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ ZERO, OWNER, SPENDER, RECIPIENT, OTHER, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE, CLASS_HASH_ZERO }; -use openzeppelin::tests::utils; -use openzeppelin_token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; -use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils; use starknet::ClassHash; use starknet::testing; @@ -38,14 +38,14 @@ fn setup_dispatcher_with_event() -> ERC20UpgradeableABIDispatcher { calldata.append_serde(OWNER()); calldata.append_serde(OWNER()); - let address = utils::deploy(ERC20Upgradeable::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(ERC20Upgradeable::TEST_CLASS_HASH, calldata); ERC20UpgradeableABIDispatcher { contract_address: address } } fn setup_dispatcher() -> ERC20UpgradeableABIDispatcher { let dispatcher = setup_dispatcher_with_event(); - utils::drop_event(dispatcher.contract_address); // Ownable `OwnershipTransferred` - utils::drop_event(dispatcher.contract_address); // ERC20 `Transfer` + test_utils::drop_event(dispatcher.contract_address); // Ownable `OwnershipTransferred` + test_utils::drop_event(dispatcher.contract_address); // ERC20 `Transfer` dispatcher } @@ -186,7 +186,7 @@ fn test_transfer_from() { testing::set_contract_address(OWNER()); dispatcher.approve(SPENDER(), VALUE); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(SPENDER()); assert!(dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE)); @@ -250,7 +250,7 @@ fn test_transferFrom() { testing::set_contract_address(OWNER()); dispatcher.approve(SPENDER(), VALUE); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(SPENDER()); assert!(dispatcher.transferFrom(OWNER(), RECIPIENT(), VALUE)); diff --git a/src/tests/presets/test_erc721.cairo b/packages/presets/src/tests/test_erc721.cairo similarity index 93% rename from src/tests/presets/test_erc721.cairo rename to packages/presets/src/tests/test_erc721.cairo index 3c54e3bd0..b3788736c 100644 --- a/src/tests/presets/test_erc721.cairo +++ b/packages/presets/src/tests/test_erc721.cairo @@ -1,27 +1,17 @@ use core::num::traits::Zero; +use openzeppelin_access::tests::common::assert_event_ownership_transferred; use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin_presets::ERC721Upgradeable::InternalImpl; use openzeppelin_presets::ERC721Upgradeable; use openzeppelin_presets::interfaces::{ ERC721UpgradeableABIDispatcher, ERC721UpgradeableABIDispatcherTrait }; -use openzeppelin::tests::access::common::assert_event_ownership_transferred; -use openzeppelin::tests::mocks::account_mocks::{DualCaseAccountMock, CamelAccountMock}; -use openzeppelin::tests::mocks::erc721_mocks::SnakeERC721Mock; -use openzeppelin::tests::mocks::erc721_receiver_mocks::{ +use openzeppelin_presets::tests::mocks::account_mocks::{DualCaseAccountMock, CamelAccountMock}; +use openzeppelin_presets::tests::mocks::erc721_mocks::SnakeERC721Mock; +use openzeppelin_presets::tests::mocks::erc721_receiver_mocks::{ CamelERC721ReceiverMock, SnakeERC721ReceiverMock }; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::token::erc721::common::{ - assert_event_transfer, assert_only_event_transfer, assert_event_approval, - assert_event_approval_for_all -}; -use openzeppelin::tests::upgrades::common::assert_only_event_upgraded; -use openzeppelin::tests::utils::constants::{ - ZERO, DATA, OWNER, SPENDER, RECIPIENT, OTHER, OPERATOR, CLASS_HASH_ZERO, PUBKEY, NAME, SYMBOL, - BASE_URI -}; -use openzeppelin::tests::utils; +use openzeppelin_presets::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin_token::erc721::ERC721Component::ERC721Impl; use openzeppelin_token::erc721::ERC721Component; use openzeppelin_token::erc721::interface::{ @@ -29,7 +19,17 @@ use openzeppelin_token::erc721::interface::{ }; use openzeppelin_token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; use openzeppelin_token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID}; +use openzeppelin_token::tests::erc721::common::{ + assert_event_transfer, assert_only_event_transfer, assert_event_approval, + assert_event_approval_for_all +}; +use openzeppelin_upgrades::tests::common::assert_only_event_upgraded; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ + ZERO, DATA, OWNER, SPENDER, RECIPIENT, OTHER, OPERATOR, CLASS_HASH_ZERO, PUBKEY, NAME, SYMBOL, + BASE_URI +}; +use openzeppelin_utils::test_utils; use starknet::testing; use starknet::{ContractAddress, ClassHash}; @@ -64,33 +64,33 @@ fn setup_dispatcher_with_event() -> ERC721UpgradeableABIDispatcher { calldata.append_serde(token_ids); calldata.append_serde(OWNER()); - let address = utils::deploy(ERC721Upgradeable::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(ERC721Upgradeable::TEST_CLASS_HASH, calldata); ERC721UpgradeableABIDispatcher { contract_address: address } } fn setup_dispatcher() -> ERC721UpgradeableABIDispatcher { let dispatcher = setup_dispatcher_with_event(); // `OwnershipTransferred` + `Transfer`s - utils::drop_events(dispatcher.contract_address, TOKENS_LEN.try_into().unwrap() + 1); + test_utils::drop_events(dispatcher.contract_address, TOKENS_LEN.try_into().unwrap() + 1); dispatcher } fn setup_receiver() -> ContractAddress { - utils::deploy(SnakeERC721ReceiverMock::TEST_CLASS_HASH, array![]) + test_utils::deploy(SnakeERC721ReceiverMock::TEST_CLASS_HASH, array![]) } fn setup_camel_receiver() -> ContractAddress { - utils::deploy(CamelERC721ReceiverMock::TEST_CLASS_HASH, array![]) + test_utils::deploy(CamelERC721ReceiverMock::TEST_CLASS_HASH, array![]) } fn setup_account() -> ContractAddress { let mut calldata = array![PUBKEY]; - utils::deploy(DualCaseAccountMock::TEST_CLASS_HASH, calldata) + test_utils::deploy(DualCaseAccountMock::TEST_CLASS_HASH, calldata) } fn setup_camel_account() -> ContractAddress { let mut calldata = array![PUBKEY]; - utils::deploy(CamelAccountMock::TEST_CLASS_HASH, calldata) + test_utils::deploy(CamelAccountMock::TEST_CLASS_HASH, calldata) } // @@ -251,7 +251,7 @@ fn test_approve_from_operator() { let dispatcher = setup_dispatcher(); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.approve(SPENDER(), TOKEN_1); @@ -314,7 +314,7 @@ fn test_transfer_from_owner() { // set approval to check reset dispatcher.approve(OTHER(), token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); assert_state_before_transfer(dispatcher, owner, recipient, token_id); @@ -336,7 +336,7 @@ fn test_transferFrom_owner() { // set approval to check reset dispatcher.approve(OTHER(), token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); assert_state_before_transfer(dispatcher, owner, recipient, token_id); @@ -408,7 +408,7 @@ fn test_transfer_from_approved() { assert_state_before_transfer(dispatcher, owner, recipient, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.transfer_from(owner, recipient, token_id); @@ -426,7 +426,7 @@ fn test_transferFrom_approved() { assert_state_before_transfer(dispatcher, owner, recipient, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.transferFrom(owner, recipient, token_id); @@ -445,7 +445,7 @@ fn test_transfer_from_approved_for_all() { assert_state_before_transfer(dispatcher, owner, recipient, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.transfer_from(owner, recipient, token_id); @@ -464,7 +464,7 @@ fn test_transferFrom_approved_for_all() { assert_state_before_transfer(dispatcher, owner, recipient, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.transferFrom(owner, recipient, token_id); @@ -661,7 +661,7 @@ fn test_safeTransferFrom_to_receiver_failure_camel() { #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND', 'ENTRYPOINT_FAILED'))] fn test_safe_transfer_from_to_non_receiver() { let dispatcher = setup_dispatcher(); - let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let recipient = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); let token_id = TOKEN_1; let owner = OWNER(); @@ -672,7 +672,7 @@ fn test_safe_transfer_from_to_non_receiver() { #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND', 'ENTRYPOINT_FAILED'))] fn test_safeTransferFrom_to_non_receiver() { let dispatcher = setup_dispatcher(); - let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let recipient = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); let token_id = TOKEN_1; let owner = OWNER(); @@ -714,7 +714,7 @@ fn test_safe_transfer_from_to_owner() { let receiver = setup_receiver(); dispatcher.transfer_from(OWNER(), receiver, token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); @@ -732,7 +732,7 @@ fn test_safeTransferFrom_to_owner() { let receiver = setup_receiver(); dispatcher.transfer_from(OWNER(), receiver, token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); @@ -750,7 +750,7 @@ fn test_safe_transfer_from_to_owner_camel() { let receiver = setup_camel_receiver(); dispatcher.transfer_from(OWNER(), receiver, token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); @@ -768,7 +768,7 @@ fn test_safeTransferFrom_to_owner_camel() { let receiver = setup_camel_receiver(); dispatcher.transfer_from(OWNER(), receiver, token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); assert_state_transfer_to_self(dispatcher, receiver, token_id, 1); @@ -789,7 +789,7 @@ fn test_safe_transfer_from_approved() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.safe_transfer_from(owner, receiver, token_id, DATA(true)); @@ -808,7 +808,7 @@ fn test_safeTransferFrom_approved() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.safeTransferFrom(owner, receiver, token_id, DATA(true)); @@ -827,7 +827,7 @@ fn test_safe_transfer_from_approved_camel() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.safe_transfer_from(owner, receiver, token_id, DATA(true)); @@ -846,7 +846,7 @@ fn test_safeTransferFrom_approved_camel() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.approve(OPERATOR(), token_id); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.safeTransferFrom(owner, receiver, token_id, DATA(true)); @@ -865,7 +865,7 @@ fn test_safe_transfer_from_approved_for_all() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.safe_transfer_from(owner, receiver, token_id, DATA(true)); @@ -884,7 +884,7 @@ fn test_safeTransferFrom_approved_for_all() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.safeTransferFrom(owner, receiver, token_id, DATA(true)); @@ -903,7 +903,7 @@ fn test_safe_transfer_from_approved_for_all_camel() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.safe_transfer_from(owner, receiver, token_id, DATA(true)); @@ -922,7 +922,7 @@ fn test_safeTransferFrom_approved_for_all_camel() { assert_state_before_transfer(dispatcher, owner, receiver, token_id); dispatcher.set_approval_for_all(OPERATOR(), true); - utils::drop_event(dispatcher.contract_address); + test_utils::drop_event(dispatcher.contract_address); testing::set_contract_address(OPERATOR()); dispatcher.safeTransferFrom(owner, receiver, token_id, DATA(true)); diff --git a/src/tests/presets/test_eth_account.cairo b/packages/presets/src/tests/test_eth_account.cairo similarity index 96% rename from src/tests/presets/test_eth_account.cairo rename to packages/presets/src/tests/test_eth_account.cairo index 98a37d4d4..92fba3b34 100644 --- a/src/tests/presets/test_eth_account.cairo +++ b/packages/presets/src/tests/test_eth_account.cairo @@ -1,27 +1,27 @@ use core::num::traits::Zero; use openzeppelin_account::interface::ISRC6_ID; -use openzeppelin_account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; -use openzeppelin_account::utils::signature::EthSignature; -use openzeppelin_introspection::interface::ISRC5_ID; -use openzeppelin::presets::EthAccountUpgradeable; -use openzeppelin::presets::interfaces::{ - EthAccountUpgradeableABIDispatcher, EthAccountUpgradeableABIDispatcherTrait -}; -use openzeppelin::tests::account::ethereum::common::{ +use openzeppelin_account::tests::ethereum::common::{ assert_only_event_owner_added, assert_event_owner_removed }; -use openzeppelin::tests::account::ethereum::common::{ +use openzeppelin_account::tests::ethereum::common::{ deploy_erc20, get_points, NEW_ETH_PUBKEY, SIGNED_TX_DATA, SignedTransactionData }; -use openzeppelin::tests::mocks::eth_account_mocks::SnakeEthAccountMock; -use openzeppelin::tests::upgrades::common::assert_only_event_upgraded; -use openzeppelin::tests::utils::constants::{ - CLASS_HASH_ZERO, ETH_PUBKEY, SALT, ZERO, RECIPIENT, QUERY_VERSION, MIN_TRANSACTION_VERSION +use openzeppelin_account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; +use openzeppelin_account::utils::signature::EthSignature; +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_presets::EthAccountUpgradeable; +use openzeppelin_presets::interfaces::{ + EthAccountUpgradeableABIDispatcher, EthAccountUpgradeableABIDispatcherTrait }; -use openzeppelin::tests::utils; +use openzeppelin_presets::tests::mocks::eth_account_mocks::SnakeEthAccountMock; use openzeppelin_token::erc20::interface::IERC20DispatcherTrait; +use openzeppelin_upgrades::tests::common::assert_only_event_upgraded; use openzeppelin_utils::selectors; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ + CLASS_HASH_ZERO, ETH_PUBKEY, SALT, ZERO, RECIPIENT, QUERY_VERSION, MIN_TRANSACTION_VERSION +}; +use openzeppelin_utils::test_utils; use starknet::account::Call; use starknet::contract_address_const; use starknet::testing; @@ -43,8 +43,8 @@ fn setup_dispatcher() -> EthAccountUpgradeableABIDispatcher { let mut calldata = array![]; calldata.append_serde(ETH_PUBKEY()); - let target = utils::deploy(CLASS_HASH(), calldata); - utils::drop_event(target); + let target = test_utils::deploy(CLASS_HASH(), calldata); + test_utils::drop_event(target); EthAccountUpgradeableABIDispatcher { contract_address: target } } @@ -67,7 +67,7 @@ fn setup_dispatcher_with_data( } else { calldata.append_serde(ETH_PUBKEY()); } - let address = utils::deploy(CLASS_HASH(), calldata); + let address = test_utils::deploy(CLASS_HASH(), calldata); EthAccountUpgradeableABIDispatcher { contract_address: address } } diff --git a/src/tests/presets/test_universal_deployer.cairo b/packages/presets/src/tests/test_universal_deployer.cairo similarity index 88% rename from src/tests/presets/test_universal_deployer.cairo rename to packages/presets/src/tests/test_universal_deployer.cairo index e5425ffa8..37547556d 100644 --- a/src/tests/presets/test_universal_deployer.cairo +++ b/packages/presets/src/tests/test_universal_deployer.cairo @@ -1,14 +1,14 @@ +use openzeppelin_presets::tests::mocks::erc20_mocks::DualCaseERC20Mock; use openzeppelin_presets::universal_deployer::UniversalDeployer::ContractDeployed; use openzeppelin_presets::universal_deployer::UniversalDeployer; -use openzeppelin::tests::mocks::erc20_mocks::DualCaseERC20Mock; -use openzeppelin::tests::utils::constants::{NAME, SYMBOL, SUPPLY, SALT, CALLER, RECIPIENT}; -use openzeppelin::tests::utils; use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use openzeppelin_utils::deployments::{DeployerInfo, calculate_contract_address_from_udc}; use openzeppelin_utils::interfaces::{ IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait }; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{NAME, SYMBOL, SUPPLY, SALT, CALLER, RECIPIENT}; +use openzeppelin_utils::test_utils; use starknet::ClassHash; use starknet::ContractAddress; use starknet::testing; @@ -29,7 +29,7 @@ fn ERC20_CALLDATA() -> Span { fn deploy_udc() -> IUniversalDeployerDispatcher { let calldata = array![]; - let address = utils::deploy(UniversalDeployer::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(UniversalDeployer::TEST_CLASS_HASH, calldata); IUniversalDeployerDispatcher { contract_address: address } } @@ -110,10 +110,10 @@ fn assert_only_event_contract_deployed( calldata: Span, salt: felt252 ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = UniversalDeployer::Event::ContractDeployed( ContractDeployed { address, deployer, from_zero, class_hash, calldata, salt } ); assert!(event == expected); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } diff --git a/packages/presets/src/universal_deployer.cairo b/packages/presets/src/universal_deployer.cairo index d01c7c82d..b12b997e2 100644 --- a/packages/presets/src/universal_deployer.cairo +++ b/packages/presets/src/universal_deployer.cairo @@ -5,7 +5,7 @@ /// /// The Universal Deployer Contract is a standardized generic factory of Starknet contracts. #[starknet::contract] -pub(crate) mod UniversalDeployer { +pub mod UniversalDeployer { use core::hash::{HashStateTrait, HashStateExTrait}; use core::poseidon::PoseidonTrait; use openzeppelin_utils::interfaces::IUniversalDeployer; diff --git a/packages/security/Scarb.toml b/packages/security/Scarb.toml index 24712d7d6..efe241305 100644 --- a/packages/security/Scarb.toml +++ b/packages/security/Scarb.toml @@ -18,3 +18,7 @@ fmt.workspace = true [dependencies] starknet.workspace = true + +[dev-dependencies] +cairo_test.workspace = true +openzeppelin_utils = { path = "../utils" } diff --git a/packages/security/src/lib.cairo b/packages/security/src/lib.cairo index 17ecc6dbe..d479f9e05 100644 --- a/packages/security/src/lib.cairo +++ b/packages/security/src/lib.cairo @@ -3,6 +3,9 @@ pub mod interface; pub mod pausable; pub mod reentrancyguard; +#[cfg(test)] +mod tests; + pub use initializable::InitializableComponent; pub use pausable::PausableComponent; pub use reentrancyguard::ReentrancyGuardComponent; diff --git a/src/tests/security.cairo b/packages/security/src/tests.cairo similarity index 75% rename from src/tests/security.cairo rename to packages/security/src/tests.cairo index 35c30a0e8..59cc6e392 100644 --- a/src/tests/security.cairo +++ b/packages/security/src/tests.cairo @@ -1,3 +1,5 @@ +pub(crate) mod mocks; + mod test_initializable; mod test_pausable; mod test_reentrancyguard; diff --git a/packages/security/src/tests/mocks.cairo b/packages/security/src/tests/mocks.cairo new file mode 100644 index 000000000..81134e172 --- /dev/null +++ b/packages/security/src/tests/mocks.cairo @@ -0,0 +1,3 @@ +pub(crate) mod initializable_mocks; +pub(crate) mod pausable_mocks; +pub(crate) mod reentrancy_mocks; diff --git a/src/tests/mocks/initializable_mocks.cairo b/packages/security/src/tests/mocks/initializable_mocks.cairo similarity index 100% rename from src/tests/mocks/initializable_mocks.cairo rename to packages/security/src/tests/mocks/initializable_mocks.cairo diff --git a/src/tests/mocks/pausable_mocks.cairo b/packages/security/src/tests/mocks/pausable_mocks.cairo similarity index 100% rename from src/tests/mocks/pausable_mocks.cairo rename to packages/security/src/tests/mocks/pausable_mocks.cairo diff --git a/src/tests/mocks/reentrancy_mocks.cairo b/packages/security/src/tests/mocks/reentrancy_mocks.cairo similarity index 100% rename from src/tests/mocks/reentrancy_mocks.cairo rename to packages/security/src/tests/mocks/reentrancy_mocks.cairo diff --git a/src/tests/security/test_initializable.cairo b/packages/security/src/tests/test_initializable.cairo similarity index 89% rename from src/tests/security/test_initializable.cairo rename to packages/security/src/tests/test_initializable.cairo index 37d27debc..bae478f6a 100644 --- a/src/tests/security/test_initializable.cairo +++ b/packages/security/src/tests/test_initializable.cairo @@ -1,6 +1,6 @@ use openzeppelin_security::InitializableComponent::{InitializableImpl, InternalImpl}; use openzeppelin_security::InitializableComponent; -use openzeppelin::tests::mocks::initializable_mocks::InitializableMock; +use openzeppelin_security::tests::mocks::initializable_mocks::InitializableMock; type ComponentState = InitializableComponent::ComponentState; diff --git a/src/tests/security/test_pausable.cairo b/packages/security/src/tests/test_pausable.cairo similarity index 84% rename from src/tests/security/test_pausable.cairo rename to packages/security/src/tests/test_pausable.cairo index b646d820b..f5b71d2f3 100644 --- a/src/tests/security/test_pausable.cairo +++ b/packages/security/src/tests/test_pausable.cairo @@ -1,9 +1,9 @@ use openzeppelin_security::PausableComponent::{InternalImpl, PausableImpl}; use openzeppelin_security::PausableComponent::{Paused, Unpaused}; use openzeppelin_security::PausableComponent; -use openzeppelin::tests::mocks::pausable_mocks::PausableMock; -use openzeppelin::tests::utils::constants::{CALLER, ZERO}; -use openzeppelin::tests::utils; +use openzeppelin_security::tests::mocks::pausable_mocks::PausableMock; +use openzeppelin_utils::test_utils::constants::{CALLER, ZERO}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::testing; @@ -99,7 +99,7 @@ fn test_unpause_when_paused() { testing::set_caller_address(CALLER()); state.pause(); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state.unpause(); @@ -120,15 +120,15 @@ fn test_unpause_when_unpaused() { // fn assert_event_paused(account: ContractAddress) { - let event = utils::pop_log::(ZERO()).unwrap(); + let event = test_utils::pop_log::(ZERO()).unwrap(); let expected = PausableComponent::Event::Paused(Paused { account }); assert!(event == expected); - utils::assert_no_events_left(ZERO()); + test_utils::assert_no_events_left(ZERO()); } fn assert_event_unpaused(account: ContractAddress) { - let event = utils::pop_log::(ZERO()).unwrap(); + let event = test_utils::pop_log::(ZERO()).unwrap(); let expected = PausableComponent::Event::Unpaused(Unpaused { account }); assert!(event == expected); - utils::assert_no_events_left(ZERO()); + test_utils::assert_no_events_left(ZERO()); } diff --git a/src/tests/security/test_reentrancyguard.cairo b/packages/security/src/tests/test_reentrancyguard.cairo similarity index 90% rename from src/tests/security/test_reentrancyguard.cairo rename to packages/security/src/tests/test_reentrancyguard.cairo index bf4375a29..de3ed8daf 100644 --- a/src/tests/security/test_reentrancyguard.cairo +++ b/packages/security/src/tests/test_reentrancyguard.cairo @@ -1,9 +1,9 @@ use openzeppelin_security::ReentrancyGuardComponent::InternalImpl; use openzeppelin_security::ReentrancyGuardComponent; -use openzeppelin::tests::mocks::reentrancy_mocks::{ +use openzeppelin_security::tests::mocks::reentrancy_mocks::{ Attacker, ReentrancyMock, IReentrancyMockDispatcher, IReentrancyMockDispatcherTrait }; -use openzeppelin::tests::utils; +use openzeppelin_utils::test_utils; type ComponentState = ReentrancyGuardComponent::ComponentState; @@ -13,7 +13,7 @@ fn COMPONENT_STATE() -> ComponentState { fn deploy_mock() -> IReentrancyMockDispatcher { let calldata = array![]; - let address = utils::deploy(ReentrancyMock::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(ReentrancyMock::TEST_CLASS_HASH, calldata); IReentrancyMockDispatcher { contract_address: address } } @@ -76,7 +76,7 @@ fn test_remote_callback() { // Deploy attacker let calldata = array![]; - let attacker_addr = utils::deploy(Attacker::TEST_CLASS_HASH, calldata); + let attacker_addr = test_utils::deploy(Attacker::TEST_CLASS_HASH, calldata); contract.count_and_call(attacker_addr); } diff --git a/packages/token/Scarb.toml b/packages/token/Scarb.toml index 41014afc0..9819a35a2 100644 --- a/packages/token/Scarb.toml +++ b/packages/token/Scarb.toml @@ -21,3 +21,6 @@ starknet.workspace = true openzeppelin_account = { path = "../account" } openzeppelin_introspection = { path = "../introspection" } openzeppelin_governance = { path = "../governance" } + +[dev-dependencies] +cairo_test.workspace = true diff --git a/packages/token/src/lib.cairo b/packages/token/src/lib.cairo index afe47f7ac..2c0afce45 100644 --- a/packages/token/src/lib.cairo +++ b/packages/token/src/lib.cairo @@ -1,3 +1,5 @@ pub mod erc1155; pub mod erc20; pub mod erc721; + +pub mod tests; diff --git a/packages/token/src/tests.cairo b/packages/token/src/tests.cairo new file mode 100644 index 000000000..047d3ad2f --- /dev/null +++ b/packages/token/src/tests.cairo @@ -0,0 +1,5 @@ +pub mod erc1155; +pub mod erc20; +pub mod erc721; + +pub(crate) mod mocks; diff --git a/src/tests/token/erc1155.cairo b/packages/token/src/tests/erc1155.cairo similarity index 57% rename from src/tests/token/erc1155.cairo rename to packages/token/src/tests/erc1155.cairo index 888f16dc2..1cc8d702b 100644 --- a/src/tests/token/erc1155.cairo +++ b/packages/token/src/tests/erc1155.cairo @@ -1,6 +1,10 @@ -pub(crate) mod common; +pub mod common; +#[cfg(test)] mod test_dual1155; +#[cfg(test)] mod test_dual1155_receiver; +#[cfg(test)] mod test_erc1155; +#[cfg(test)] mod test_erc1155_receiver; diff --git a/src/tests/token/erc1155/common.cairo b/packages/token/src/tests/erc1155/common.cairo similarity index 61% rename from src/tests/token/erc1155/common.cairo rename to packages/token/src/tests/erc1155/common.cairo index 692207bb7..36308b873 100644 --- a/src/tests/token/erc1155/common.cairo +++ b/packages/token/src/tests/erc1155/common.cairo @@ -1,44 +1,44 @@ -use openzeppelin::tests::mocks::account_mocks::SnakeAccountMock; -use openzeppelin::tests::mocks::erc1155_receiver_mocks::{ +use openzeppelin_token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; +use openzeppelin_token::erc1155::ERC1155Component; +use openzeppelin_token::tests::mocks::account_mocks::SnakeAccountMock; +use openzeppelin_token::tests::mocks::erc1155_receiver_mocks::{ CamelERC1155ReceiverMock, SnakeERC1155ReceiverMock }; -use openzeppelin::tests::mocks::src5_mocks::SRC5Mock; -use openzeppelin::tests::utils::constants::{ +use openzeppelin_token::tests::mocks::src5_mocks::SRC5Mock; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ PUBKEY, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 }; -use openzeppelin::tests::utils; -use openzeppelin_token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; -use openzeppelin_token::erc1155::ERC1155Component; -use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; -pub(crate) fn setup_receiver() -> ContractAddress { - utils::deploy(SnakeERC1155ReceiverMock::TEST_CLASS_HASH, array![]) +pub fn setup_receiver() -> ContractAddress { + test_utils::deploy(SnakeERC1155ReceiverMock::TEST_CLASS_HASH, array![]) } -pub(crate) fn setup_camel_receiver() -> ContractAddress { - utils::deploy(CamelERC1155ReceiverMock::TEST_CLASS_HASH, array![]) +pub fn setup_camel_receiver() -> ContractAddress { + test_utils::deploy(CamelERC1155ReceiverMock::TEST_CLASS_HASH, array![]) } -pub(crate) fn setup_account() -> ContractAddress { +pub fn setup_account() -> ContractAddress { let calldata = array![PUBKEY]; - utils::deploy(SnakeAccountMock::TEST_CLASS_HASH, calldata) + test_utils::deploy(SnakeAccountMock::TEST_CLASS_HASH, calldata) } -pub(crate) fn setup_account_with_salt(salt: felt252) -> ContractAddress { +pub fn setup_account_with_salt(salt: felt252) -> ContractAddress { let calldata = array![PUBKEY]; - utils::deploy_with_salt(SnakeAccountMock::TEST_CLASS_HASH, calldata, salt) + test_utils::deploy_with_salt(SnakeAccountMock::TEST_CLASS_HASH, calldata, salt) } -pub(crate) fn setup_src5() -> ContractAddress { - utils::deploy(SRC5Mock::TEST_CLASS_HASH, array![]) +pub fn setup_src5() -> ContractAddress { + test_utils::deploy(SRC5Mock::TEST_CLASS_HASH, array![]) } -pub(crate) fn assert_event_approval_for_all( +pub fn assert_event_approval_for_all( contract: ContractAddress, owner: ContractAddress, operator: ContractAddress, approved: bool ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = ERC1155Component::Event::ApprovalForAll( ApprovalForAll { owner, operator, approved } ); @@ -49,10 +49,10 @@ pub(crate) fn assert_event_approval_for_all( indexed_keys.append_serde(selector!("ApprovalForAll")); indexed_keys.append_serde(owner); indexed_keys.append_serde(operator); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } -pub(crate) fn assert_event_transfer_single( +pub fn assert_event_transfer_single( contract: ContractAddress, operator: ContractAddress, from: ContractAddress, @@ -60,7 +60,7 @@ pub(crate) fn assert_event_transfer_single( token_id: u256, value: u256 ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let id = token_id; let expected = ERC1155Component::Event::TransferSingle( TransferSingle { operator, from, to, id, value } @@ -73,10 +73,10 @@ pub(crate) fn assert_event_transfer_single( indexed_keys.append_serde(operator); indexed_keys.append_serde(from); indexed_keys.append_serde(to); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } -pub(crate) fn assert_event_transfer_batch( +pub fn assert_event_transfer_batch( contract: ContractAddress, operator: ContractAddress, from: ContractAddress, @@ -84,7 +84,7 @@ pub(crate) fn assert_event_transfer_batch( token_ids: Span, values: Span ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let ids = token_ids; let expected = ERC1155Component::Event::TransferBatch( TransferBatch { operator, from, to, ids, values } @@ -97,10 +97,10 @@ pub(crate) fn assert_event_transfer_batch( indexed_keys.append_serde(operator); indexed_keys.append_serde(from); indexed_keys.append_serde(to); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } -pub(crate) fn assert_only_event_transfer_single( +pub fn assert_only_event_transfer_single( contract: ContractAddress, operator: ContractAddress, from: ContractAddress, @@ -109,10 +109,10 @@ pub(crate) fn assert_only_event_transfer_single( value: u256 ) { assert_event_transfer_single(contract, operator, from, to, token_id, value); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } -pub(crate) fn assert_only_event_transfer_batch( +pub fn assert_only_event_transfer_batch( contract: ContractAddress, operator: ContractAddress, from: ContractAddress, @@ -121,23 +121,23 @@ pub(crate) fn assert_only_event_transfer_batch( values: Span ) { assert_event_transfer_batch(contract, operator, from, to, token_ids, values); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } -pub(crate) fn assert_only_event_approval_for_all( +pub fn assert_only_event_approval_for_all( contract: ContractAddress, owner: ContractAddress, operator: ContractAddress, approved: bool ) { assert_event_approval_for_all(contract, owner, operator, approved); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } -pub(crate) fn get_ids_and_values() -> (Span, Span) { +pub fn get_ids_and_values() -> (Span, Span) { let ids = array![TOKEN_ID, TOKEN_ID_2].span(); let values = array![TOKEN_VALUE, TOKEN_VALUE_2].span(); (ids, values) } -pub(crate) fn get_ids_and_split_values(split: u256) -> (Span, Span) { +pub fn get_ids_and_split_values(split: u256) -> (Span, Span) { let ids = array![TOKEN_ID, TOKEN_ID].span(); let values = array![TOKEN_VALUE - split, split].span(); (ids, values) diff --git a/src/tests/token/erc1155/test_dual1155.cairo b/packages/token/src/tests/erc1155/test_dual1155.cairo similarity index 93% rename from src/tests/token/erc1155/test_dual1155.cairo rename to packages/token/src/tests/erc1155/test_dual1155.cairo index c7c10dc65..544266729 100644 --- a/src/tests/token/erc1155/test_dual1155.cairo +++ b/packages/token/src/tests/erc1155/test_dual1155.cairo @@ -1,18 +1,16 @@ use core::num::traits::Zero; -use openzeppelin::tests::mocks::erc1155_mocks::{CamelERC1155Mock, SnakeERC1155Mock}; -use openzeppelin::tests::mocks::erc1155_mocks::{CamelERC1155PanicMock, SnakeERC1155PanicMock}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::{ - EMPTY_DATA, OWNER, RECIPIENT, OPERATOR, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE -}; -use openzeppelin::tests::utils; use openzeppelin_token::erc1155::dual1155::{DualCaseERC1155, DualCaseERC1155Trait}; use openzeppelin_token::erc1155::interface::IERC1155_ID; -use openzeppelin_token::erc1155::interface::{ - IERC1155CamelDispatcher, IERC1155CamelDispatcherTrait -}; +use openzeppelin_token::erc1155::interface::{IERC1155CamelDispatcher, IERC1155CamelDispatcherTrait}; use openzeppelin_token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; +use openzeppelin_token::tests::mocks::erc1155_mocks::{CamelERC1155Mock, SnakeERC1155Mock}; +use openzeppelin_token::tests::mocks::erc1155_mocks::{CamelERC1155PanicMock, SnakeERC1155PanicMock}; +use openzeppelin_token::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ + EMPTY_DATA, OWNER, RECIPIENT, OPERATOR, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE +}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::testing; @@ -30,7 +28,7 @@ fn setup_snake() -> (DualCaseERC1155, IERC1155Dispatcher, ContractAddress) { calldata.append_serde(owner); calldata.append_serde(TOKEN_ID); calldata.append_serde(TOKEN_VALUE); - let target = utils::deploy(SnakeERC1155Mock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(SnakeERC1155Mock::TEST_CLASS_HASH, calldata); ( DualCaseERC1155 { contract_address: target }, IERC1155Dispatcher { contract_address: target }, @@ -46,7 +44,7 @@ fn setup_camel() -> (DualCaseERC1155, IERC1155CamelDispatcher, ContractAddress) calldata.append_serde(owner); calldata.append_serde(TOKEN_ID); calldata.append_serde(TOKEN_VALUE); - let target = utils::deploy(CamelERC1155Mock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(CamelERC1155Mock::TEST_CLASS_HASH, calldata); ( DualCaseERC1155 { contract_address: target }, IERC1155CamelDispatcher { contract_address: target }, @@ -56,13 +54,13 @@ fn setup_camel() -> (DualCaseERC1155, IERC1155CamelDispatcher, ContractAddress) fn setup_non_erc1155() -> DualCaseERC1155 { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); DualCaseERC1155 { contract_address: target } } fn setup_erc1155_panic() -> (DualCaseERC1155, DualCaseERC1155) { - let snake_target = utils::deploy(SnakeERC1155PanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelERC1155PanicMock::TEST_CLASS_HASH, array![]); + let snake_target = test_utils::deploy(SnakeERC1155PanicMock::TEST_CLASS_HASH, array![]); + let camel_target = test_utils::deploy(CamelERC1155PanicMock::TEST_CLASS_HASH, array![]); ( DualCaseERC1155 { contract_address: snake_target }, DualCaseERC1155 { contract_address: camel_target } diff --git a/src/tests/token/erc1155/test_dual1155_receiver.cairo b/packages/token/src/tests/erc1155/test_dual1155_receiver.cairo similarity index 86% rename from src/tests/token/erc1155/test_dual1155_receiver.cairo rename to packages/token/src/tests/erc1155/test_dual1155_receiver.cairo index b17e3d8fe..9e6d361e8 100644 --- a/src/tests/token/erc1155/test_dual1155_receiver.cairo +++ b/packages/token/src/tests/erc1155/test_dual1155_receiver.cairo @@ -1,10 +1,3 @@ -use openzeppelin::tests::mocks::erc1155_receiver_mocks::{ - CamelERC1155ReceiverMock, CamelERC1155ReceiverPanicMock, SnakeERC1155ReceiverMock, - SnakeERC1155ReceiverPanicMock -}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::{EMPTY_DATA, OPERATOR, OWNER, TOKEN_ID, TOKEN_VALUE}; -use openzeppelin::tests::utils; use openzeppelin_token::erc1155::dual1155_receiver::{ DualCaseERC1155Receiver, DualCaseERC1155ReceiverTrait }; @@ -15,6 +8,13 @@ use openzeppelin_token::erc1155::interface::{ use openzeppelin_token::erc1155::interface::{ IERC1155ReceiverDispatcher, IERC1155ReceiverDispatcherTrait }; +use openzeppelin_token::tests::mocks::erc1155_receiver_mocks::{ + CamelERC1155ReceiverMock, CamelERC1155ReceiverPanicMock, SnakeERC1155ReceiverMock, + SnakeERC1155ReceiverPanicMock +}; +use openzeppelin_token::tests::mocks::non_implementing_mock::NonImplementingMock; +use openzeppelin_utils::test_utils::constants::{EMPTY_DATA, OPERATOR, OWNER, TOKEN_ID, TOKEN_VALUE}; +use openzeppelin_utils::test_utils; // // Setup @@ -22,7 +22,7 @@ use openzeppelin_token::erc1155::interface::{ fn setup_snake() -> (DualCaseERC1155Receiver, IERC1155ReceiverDispatcher) { let calldata = array![]; - let target = utils::deploy(SnakeERC1155ReceiverMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(SnakeERC1155ReceiverMock::TEST_CLASS_HASH, calldata); ( DualCaseERC1155Receiver { contract_address: target }, IERC1155ReceiverDispatcher { contract_address: target } @@ -31,7 +31,7 @@ fn setup_snake() -> (DualCaseERC1155Receiver, IERC1155ReceiverDispatcher) { fn setup_camel() -> (DualCaseERC1155Receiver, IERC1155ReceiverCamelDispatcher) { let calldata = array![]; - let target = utils::deploy(CamelERC1155ReceiverMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(CamelERC1155ReceiverMock::TEST_CLASS_HASH, calldata); ( DualCaseERC1155Receiver { contract_address: target }, IERC1155ReceiverCamelDispatcher { contract_address: target } @@ -40,13 +40,13 @@ fn setup_camel() -> (DualCaseERC1155Receiver, IERC1155ReceiverCamelDispatcher) { fn setup_non_erc1155_receiver() -> DualCaseERC1155Receiver { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); DualCaseERC1155Receiver { contract_address: target } } fn setup_erc1155_receiver_panic() -> (DualCaseERC1155Receiver, DualCaseERC1155Receiver) { - let snake_target = utils::deploy(SnakeERC1155ReceiverPanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelERC1155ReceiverPanicMock::TEST_CLASS_HASH, array![]); + let snake_target = test_utils::deploy(SnakeERC1155ReceiverPanicMock::TEST_CLASS_HASH, array![]); + let camel_target = test_utils::deploy(CamelERC1155ReceiverPanicMock::TEST_CLASS_HASH, array![]); ( DualCaseERC1155Receiver { contract_address: snake_target }, DualCaseERC1155Receiver { contract_address: camel_target } diff --git a/src/tests/token/erc1155/test_erc1155.cairo b/packages/token/src/tests/erc1155/test_erc1155.cairo similarity index 99% rename from src/tests/token/erc1155/test_erc1155.cairo rename to packages/token/src/tests/erc1155/test_erc1155.cairo index d14bab72f..f768887ca 100644 --- a/src/tests/token/erc1155/test_erc1155.cairo +++ b/packages/token/src/tests/erc1155/test_erc1155.cairo @@ -1,12 +1,5 @@ use core::num::traits::Zero; use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; -use openzeppelin_introspection; -use openzeppelin::tests::mocks::erc1155_mocks::DualCaseERC1155Mock; -use openzeppelin::tests::utils::constants::{ - EMPTY_DATA, ZERO, OWNER, RECIPIENT, OPERATOR, OTHER, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, - TOKEN_VALUE_2 -}; -use openzeppelin::tests::utils; use openzeppelin_token::erc1155::ERC1155Component::ERC1155CamelImpl; use openzeppelin_token::erc1155::ERC1155Component::{ ERC1155Impl, ERC1155MetadataURIImpl, InternalImpl @@ -14,7 +7,13 @@ use openzeppelin_token::erc1155::ERC1155Component::{ use openzeppelin_token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; use openzeppelin_token::erc1155::ERC1155Component; use openzeppelin_token::erc1155; +use openzeppelin_token::tests::mocks::erc1155_mocks::DualCaseERC1155Mock; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ + EMPTY_DATA, ZERO, OWNER, RECIPIENT, OPERATOR, OTHER, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, + TOKEN_VALUE_2 +}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::testing; @@ -49,7 +48,7 @@ fn setup() -> (ComponentState, ContractAddress) { let values = array![TOKEN_VALUE, TOKEN_VALUE_2].span(); state.batch_mint_with_acceptance_check(owner, token_ids, values, array![].span()); - utils::drop_events(ZERO(), 2); + test_utils::drop_events(ZERO(), 2); (state, owner) } @@ -75,7 +74,8 @@ fn test_initialize() { .supports_interface(erc1155::interface::IERC1155_METADATA_URI_ID); assert!(supports_ierc1155_metadata_uri); - let supports_isrc5 = mock_state.supports_interface(introspection::interface::ISRC5_ID); + let supports_isrc5 = mock_state + .supports_interface(openzeppelin_introspection::interface::ISRC5_ID); assert!(supports_isrc5); } diff --git a/src/tests/token/erc1155/test_erc1155_receiver.cairo b/packages/token/src/tests/erc1155/test_erc1155_receiver.cairo similarity index 92% rename from src/tests/token/erc1155/test_erc1155_receiver.cairo rename to packages/token/src/tests/erc1155/test_erc1155_receiver.cairo index a7645e941..c7cbb7c47 100644 --- a/src/tests/token/erc1155/test_erc1155_receiver.cairo +++ b/packages/token/src/tests/erc1155/test_erc1155_receiver.cairo @@ -1,11 +1,11 @@ use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; -use openzeppelin::tests::mocks::erc1155_receiver_mocks::DualCaseERC1155ReceiverMock; -use openzeppelin::tests::utils::constants::{OWNER, OPERATOR, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA}; use openzeppelin_token::erc1155::ERC1155ReceiverComponent::{ ERC1155ReceiverImpl, ERC1155ReceiverCamelImpl, InternalImpl }; use openzeppelin_token::erc1155::interface::IERC1155_RECEIVER_ID; +use openzeppelin_token::tests::mocks::erc1155_receiver_mocks::DualCaseERC1155ReceiverMock; +use openzeppelin_utils::test_utils::constants::{OWNER, OPERATOR, TOKEN_ID, TOKEN_VALUE, EMPTY_DATA}; fn STATE() -> DualCaseERC1155ReceiverMock::ContractState { DualCaseERC1155ReceiverMock::contract_state_for_testing() diff --git a/src/tests/token/erc20.cairo b/packages/token/src/tests/erc20.cairo similarity index 50% rename from src/tests/token/erc20.cairo rename to packages/token/src/tests/erc20.cairo index 8d094274f..69da33c96 100644 --- a/src/tests/token/erc20.cairo +++ b/packages/token/src/tests/erc20.cairo @@ -1,5 +1,8 @@ -pub(crate) mod common; +pub mod common; +#[cfg(test)] mod test_dual20; +#[cfg(test)] mod test_erc20; +#[cfg(test)] mod test_erc20_votes; diff --git a/src/tests/token/erc20/common.cairo b/packages/token/src/tests/erc20/common.cairo similarity index 70% rename from src/tests/token/erc20/common.cairo rename to packages/token/src/tests/erc20/common.cairo index 8b39e9b6d..e0cde5ce3 100644 --- a/src/tests/token/erc20/common.cairo +++ b/packages/token/src/tests/erc20/common.cairo @@ -1,13 +1,13 @@ -use openzeppelin::tests::utils; use openzeppelin_token::erc20::ERC20Component::{Approval, Transfer}; use openzeppelin_token::erc20::ERC20Component; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; -pub(crate) fn assert_event_approval( +pub fn assert_event_approval( contract: ContractAddress, owner: ContractAddress, spender: ContractAddress, value: u256 ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = ERC20Component::Event::Approval(Approval { owner, spender, value }); assert!(event == expected); @@ -16,20 +16,20 @@ pub(crate) fn assert_event_approval( indexed_keys.append_serde(selector!("Approval")); indexed_keys.append_serde(owner); indexed_keys.append_serde(spender); - utils::assert_indexed_keys(event, indexed_keys.span()) + test_utils::assert_indexed_keys(event, indexed_keys.span()) } -pub(crate) fn assert_only_event_approval( +pub fn assert_only_event_approval( contract: ContractAddress, owner: ContractAddress, spender: ContractAddress, value: u256 ) { assert_event_approval(contract, owner, spender, value); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } -pub(crate) fn assert_event_transfer( +pub fn assert_event_transfer( contract: ContractAddress, from: ContractAddress, to: ContractAddress, value: u256 ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = ERC20Component::Event::Transfer(Transfer { from, to, value }); assert!(event == expected); @@ -38,12 +38,12 @@ pub(crate) fn assert_event_transfer( indexed_keys.append_serde(selector!("Transfer")); indexed_keys.append_serde(from); indexed_keys.append_serde(to); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } -pub(crate) fn assert_only_event_transfer( +pub fn assert_only_event_transfer( contract: ContractAddress, from: ContractAddress, to: ContractAddress, value: u256 ) { assert_event_transfer(contract, from, to, value); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } diff --git a/src/tests/token/erc20/test_dual20.cairo b/packages/token/src/tests/erc20/test_dual20.cairo similarity index 91% rename from src/tests/token/erc20/test_dual20.cairo rename to packages/token/src/tests/erc20/test_dual20.cairo index ce6fae07e..cc561a0e9 100644 --- a/src/tests/token/erc20/test_dual20.cairo +++ b/packages/token/src/tests/erc20/test_dual20.cairo @@ -1,14 +1,14 @@ -use openzeppelin::tests::mocks::erc20_mocks::{CamelERC20Mock, SnakeERC20Mock}; -use openzeppelin::tests::mocks::erc20_mocks::{CamelERC20Panic, SnakeERC20Panic}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::{ - OWNER, RECIPIENT, SPENDER, OPERATOR, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE -}; -use openzeppelin::tests::utils; use openzeppelin_token::erc20::dual20::{DualCaseERC20, DualCaseERC20Trait}; use openzeppelin_token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin_token::tests::mocks::erc20_mocks::{CamelERC20Mock, SnakeERC20Mock}; +use openzeppelin_token::tests::mocks::erc20_mocks::{CamelERC20Panic, SnakeERC20Panic}; +use openzeppelin_token::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ + OWNER, RECIPIENT, SPENDER, OPERATOR, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE +}; +use openzeppelin_utils::test_utils; use starknet::testing::set_contract_address; // @@ -21,7 +21,7 @@ fn setup_snake() -> (DualCaseERC20, IERC20Dispatcher) { calldata.append_serde(SYMBOL()); calldata.append_serde(SUPPLY); calldata.append_serde(OWNER()); - let target = utils::deploy(SnakeERC20Mock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(SnakeERC20Mock::TEST_CLASS_HASH, calldata); (DualCaseERC20 { contract_address: target }, IERC20Dispatcher { contract_address: target }) } @@ -31,19 +31,19 @@ fn setup_camel() -> (DualCaseERC20, IERC20CamelDispatcher) { calldata.append_serde(SYMBOL()); calldata.append_serde(SUPPLY); calldata.append_serde(OWNER()); - let target = utils::deploy(CamelERC20Mock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(CamelERC20Mock::TEST_CLASS_HASH, calldata); (DualCaseERC20 { contract_address: target }, IERC20CamelDispatcher { contract_address: target }) } fn setup_non_erc20() -> DualCaseERC20 { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); DualCaseERC20 { contract_address: target } } fn setup_erc20_panic() -> (DualCaseERC20, DualCaseERC20) { - let snake_target = utils::deploy(SnakeERC20Panic::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelERC20Panic::TEST_CLASS_HASH, array![]); + let snake_target = test_utils::deploy(SnakeERC20Panic::TEST_CLASS_HASH, array![]); + let camel_target = test_utils::deploy(CamelERC20Panic::TEST_CLASS_HASH, array![]); ( DualCaseERC20 { contract_address: snake_target }, DualCaseERC20 { contract_address: camel_target } diff --git a/src/tests/token/erc20/test_erc20.cairo b/packages/token/src/tests/erc20/test_erc20.cairo similarity index 97% rename from src/tests/token/erc20/test_erc20.cairo rename to packages/token/src/tests/erc20/test_erc20.cairo index 9ac361d26..670414d2e 100644 --- a/src/tests/token/erc20/test_erc20.cairo +++ b/packages/token/src/tests/erc20/test_erc20.cairo @@ -1,14 +1,14 @@ use core::integer::BoundedInt; -use openzeppelin::tests::mocks::erc20_mocks::DualCaseERC20Mock; -use openzeppelin::tests::utils::constants::{ - ZERO, OWNER, SPENDER, RECIPIENT, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE -}; -use openzeppelin::tests::utils; use openzeppelin_token::erc20::ERC20Component::{Approval, Transfer}; use openzeppelin_token::erc20::ERC20Component::{ERC20CamelOnlyImpl, ERC20Impl}; use openzeppelin_token::erc20::ERC20Component::{ERC20MetadataImpl, InternalImpl}; use openzeppelin_token::erc20::ERC20Component; +use openzeppelin_token::tests::mocks::erc20_mocks::DualCaseERC20Mock; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ + ZERO, OWNER, SPENDER, RECIPIENT, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE +}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::testing; @@ -28,7 +28,7 @@ fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(NAME(), SYMBOL()); state.mint(OWNER(), SUPPLY); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state } @@ -233,7 +233,7 @@ fn test_transfer_from() { let mut state = setup(); testing::set_caller_address(OWNER()); state.approve(SPENDER(), VALUE); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(SPENDER()); assert!(state.transfer_from(OWNER(), RECIPIENT(), VALUE)); @@ -297,7 +297,7 @@ fn test_transferFrom() { let mut state = setup(); testing::set_caller_address(OWNER()); state.approve(SPENDER(), VALUE); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(SPENDER()); assert!(state.transferFrom(OWNER(), RECIPIENT(), VALUE)); @@ -366,7 +366,7 @@ fn test__spend_allowance_not_unlimited() { let mut state = setup(); state._approve(OWNER(), SPENDER(), SUPPLY); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state._spend_allowance(OWNER(), SPENDER(), VALUE); diff --git a/src/tests/token/erc20/test_erc20_votes.cairo b/packages/token/src/tests/erc20/test_erc20_votes.cairo similarity index 92% rename from src/tests/token/erc20/test_erc20_votes.cairo rename to packages/token/src/tests/erc20/test_erc20_votes.cairo index 2b960dcab..c2eb75bcc 100644 --- a/src/tests/token/erc20/test_erc20_votes.cairo +++ b/packages/token/src/tests/erc20/test_erc20_votes.cairo @@ -1,10 +1,5 @@ use core::integer::BoundedInt; use core::num::traits::Zero; -use openzeppelin::tests::mocks::account_mocks::DualCaseAccountMock; -use openzeppelin::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock::SNIP12MetadataImpl; -use openzeppelin::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock; -use openzeppelin::tests::utils::constants::{SUPPLY, ZERO, OWNER, PUBKEY, RECIPIENT}; -use openzeppelin::tests::utils; use openzeppelin_token::erc20::ERC20Component::InternalImpl as ERC20Impl; use openzeppelin_token::erc20::extensions::ERC20VotesComponent::{ DelegateChanged, DelegateVotesChanged @@ -12,9 +7,14 @@ use openzeppelin_token::erc20::extensions::ERC20VotesComponent::{ use openzeppelin_token::erc20::extensions::ERC20VotesComponent::{ERC20VotesImpl, InternalImpl}; use openzeppelin_token::erc20::extensions::ERC20VotesComponent; use openzeppelin_token::erc20::extensions::erc20_votes::Delegation; +use openzeppelin_token::tests::mocks::account_mocks::DualCaseAccountMock; +use openzeppelin_token::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock::SNIP12MetadataImpl; +use openzeppelin_token::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock; use openzeppelin_utils::cryptography::snip12::OffchainMessageHash; use openzeppelin_utils::serde::SerializedAppend; use openzeppelin_utils::structs::checkpoint::{Checkpoint, Trace, TraceTrait}; +use openzeppelin_utils::test_utils::constants::{SUPPLY, ZERO, OWNER, PUBKEY, RECIPIENT}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::testing; @@ -40,13 +40,13 @@ fn setup() -> ComponentState { mock_state.erc20.mint(OWNER(), SUPPLY); state.transfer_voting_units(ZERO(), OWNER(), SUPPLY); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state } fn setup_account() -> ContractAddress { let mut calldata = array![0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7]; - utils::deploy(DualCaseAccountMock::TEST_CLASS_HASH, calldata) + test_utils::deploy(DualCaseAccountMock::TEST_CLASS_HASH, calldata) } // Checkpoints unordered insertion @@ -355,7 +355,7 @@ fn assert_event_delegate_changed( from_delegate: ContractAddress, to_delegate: ContractAddress ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = ERC20VotesComponent::Event::DelegateChanged( DelegateChanged { delegator, from_delegate, to_delegate } ); @@ -367,7 +367,7 @@ fn assert_event_delegate_changed( indexed_keys.append_serde(delegator); indexed_keys.append_serde(from_delegate); indexed_keys.append_serde(to_delegate); - utils::assert_indexed_keys(event, indexed_keys.span()) + test_utils::assert_indexed_keys(event, indexed_keys.span()) } fn assert_only_event_delegate_changed( @@ -377,13 +377,13 @@ fn assert_only_event_delegate_changed( to_delegate: ContractAddress ) { assert_event_delegate_changed(contract, delegator, from_delegate, to_delegate); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } fn assert_event_delegate_votes_changed( contract: ContractAddress, delegate: ContractAddress, previous_votes: u256, new_votes: u256 ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = ERC20VotesComponent::Event::DelegateVotesChanged( DelegateVotesChanged { delegate, previous_votes, new_votes } ); @@ -393,12 +393,12 @@ fn assert_event_delegate_votes_changed( let mut indexed_keys = array![]; indexed_keys.append_serde(selector!("DelegateVotesChanged")); indexed_keys.append_serde(delegate); - utils::assert_indexed_keys(event, indexed_keys.span()) + test_utils::assert_indexed_keys(event, indexed_keys.span()) } fn assert_only_event_delegate_votes_changed( contract: ContractAddress, delegate: ContractAddress, previous_votes: u256, new_votes: u256 ) { assert_event_delegate_votes_changed(contract, delegate, previous_votes, new_votes); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } diff --git a/src/tests/token/erc721.cairo b/packages/token/src/tests/erc721.cairo similarity index 53% rename from src/tests/token/erc721.cairo rename to packages/token/src/tests/erc721.cairo index 0f6616806..6faa18522 100644 --- a/src/tests/token/erc721.cairo +++ b/packages/token/src/tests/erc721.cairo @@ -1,5 +1,8 @@ -pub(crate) mod common; +pub mod common; +#[cfg(test)] mod test_dual721; +#[cfg(test)] mod test_dual721_receiver; +#[cfg(test)] mod test_erc721; diff --git a/src/tests/token/erc721/common.cairo b/packages/token/src/tests/erc721/common.cairo similarity index 71% rename from src/tests/token/erc721/common.cairo rename to packages/token/src/tests/erc721/common.cairo index d640956bf..26a5cb19f 100644 --- a/src/tests/token/erc721/common.cairo +++ b/packages/token/src/tests/erc721/common.cairo @@ -1,13 +1,13 @@ -use openzeppelin::tests::utils; use openzeppelin_token::erc721::ERC721Component::{Approval, ApprovalForAll, Transfer}; use openzeppelin_token::erc721::ERC721Component; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; -pub(crate) fn assert_event_approval_for_all( +pub fn assert_event_approval_for_all( contract: ContractAddress, owner: ContractAddress, operator: ContractAddress, approved: bool ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = ERC721Component::Event::ApprovalForAll( ApprovalForAll { owner, operator, approved } ); @@ -18,20 +18,20 @@ pub(crate) fn assert_event_approval_for_all( indexed_keys.append_serde(selector!("ApprovalForAll")); indexed_keys.append_serde(owner); indexed_keys.append_serde(operator); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } -pub(crate) fn assert_only_event_approval_for_all( +pub fn assert_only_event_approval_for_all( contract: ContractAddress, owner: ContractAddress, operator: ContractAddress, approved: bool ) { assert_event_approval_for_all(contract, owner, operator, approved); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } -pub(crate) fn assert_event_approval( +pub fn assert_event_approval( contract: ContractAddress, owner: ContractAddress, approved: ContractAddress, token_id: u256 ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = ERC721Component::Event::Approval(Approval { owner, approved, token_id }); assert!(event == expected); @@ -41,20 +41,20 @@ pub(crate) fn assert_event_approval( indexed_keys.append_serde(owner); indexed_keys.append_serde(approved); indexed_keys.append_serde(token_id); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } -pub(crate) fn assert_only_event_approval( +pub fn assert_only_event_approval( contract: ContractAddress, owner: ContractAddress, approved: ContractAddress, token_id: u256 ) { assert_event_approval(contract, owner, approved, token_id); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } -pub(crate) fn assert_event_transfer( +pub fn assert_event_transfer( contract: ContractAddress, from: ContractAddress, to: ContractAddress, token_id: u256 ) { - let event = utils::pop_log::(contract).unwrap(); + let event = test_utils::pop_log::(contract).unwrap(); let expected = ERC721Component::Event::Transfer(Transfer { from, to, token_id }); assert!(event == expected); @@ -64,12 +64,12 @@ pub(crate) fn assert_event_transfer( indexed_keys.append_serde(from); indexed_keys.append_serde(to); indexed_keys.append_serde(token_id); - utils::assert_indexed_keys(event, indexed_keys.span()); + test_utils::assert_indexed_keys(event, indexed_keys.span()); } -pub(crate) fn assert_only_event_transfer( +pub fn assert_only_event_transfer( contract: ContractAddress, from: ContractAddress, to: ContractAddress, token_id: u256 ) { assert_event_transfer(contract, from, to, token_id); - utils::assert_no_events_left(contract); + test_utils::assert_no_events_left(contract); } diff --git a/src/tests/token/erc721/test_dual721.cairo b/packages/token/src/tests/erc721/test_dual721.cairo similarity index 93% rename from src/tests/token/erc721/test_dual721.cairo rename to packages/token/src/tests/erc721/test_dual721.cairo index b90962f67..c997067e9 100644 --- a/src/tests/token/erc721/test_dual721.cairo +++ b/packages/token/src/tests/erc721/test_dual721.cairo @@ -1,18 +1,18 @@ -use openzeppelin::tests::mocks::erc721_mocks::{CamelERC721Mock, SnakeERC721Mock}; -use openzeppelin::tests::mocks::erc721_mocks::{CamelERC721PanicMock, SnakeERC721PanicMock}; -use openzeppelin::tests::mocks::erc721_receiver_mocks::DualCaseERC721ReceiverMock; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::{ - DATA, OWNER, RECIPIENT, SPENDER, OPERATOR, OTHER, NAME, SYMBOL, BASE_URI, TOKEN_ID -}; -use openzeppelin::tests::utils; use openzeppelin_token::erc721::dual721::{DualCaseERC721, DualCaseERC721Trait}; use openzeppelin_token::erc721::interface::IERC721_ID; use openzeppelin_token::erc721::interface::{ IERC721CamelOnlyDispatcher, IERC721CamelOnlyDispatcherTrait }; use openzeppelin_token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; +use openzeppelin_token::tests::mocks::erc721_mocks::{CamelERC721Mock, SnakeERC721Mock}; +use openzeppelin_token::tests::mocks::erc721_mocks::{CamelERC721PanicMock, SnakeERC721PanicMock}; +use openzeppelin_token::tests::mocks::erc721_receiver_mocks::DualCaseERC721ReceiverMock; +use openzeppelin_token::tests::mocks::non_implementing_mock::NonImplementingMock; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ + DATA, OWNER, RECIPIENT, SPENDER, OPERATOR, OTHER, NAME, SYMBOL, BASE_URI, TOKEN_ID +}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::testing::set_caller_address; use starknet::testing::set_contract_address; @@ -29,7 +29,7 @@ fn setup_snake() -> (DualCaseERC721, IERC721Dispatcher) { calldata.append_serde(OWNER()); calldata.append_serde(TOKEN_ID); set_contract_address(OWNER()); - let target = utils::deploy(SnakeERC721Mock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(SnakeERC721Mock::TEST_CLASS_HASH, calldata); (DualCaseERC721 { contract_address: target }, IERC721Dispatcher { contract_address: target }) } @@ -41,7 +41,7 @@ fn setup_camel() -> (DualCaseERC721, IERC721CamelOnlyDispatcher) { calldata.append_serde(OWNER()); calldata.append_serde(TOKEN_ID); set_contract_address(OWNER()); - let target = utils::deploy(CamelERC721Mock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(CamelERC721Mock::TEST_CLASS_HASH, calldata); ( DualCaseERC721 { contract_address: target }, IERC721CamelOnlyDispatcher { contract_address: target } @@ -50,13 +50,13 @@ fn setup_camel() -> (DualCaseERC721, IERC721CamelOnlyDispatcher) { fn setup_non_erc721() -> DualCaseERC721 { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); DualCaseERC721 { contract_address: target } } fn setup_erc721_panic() -> (DualCaseERC721, DualCaseERC721) { - let snake_target = utils::deploy(SnakeERC721PanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelERC721PanicMock::TEST_CLASS_HASH, array![]); + let snake_target = test_utils::deploy(SnakeERC721PanicMock::TEST_CLASS_HASH, array![]); + let camel_target = test_utils::deploy(CamelERC721PanicMock::TEST_CLASS_HASH, array![]); ( DualCaseERC721 { contract_address: snake_target }, DualCaseERC721 { contract_address: camel_target } @@ -64,7 +64,7 @@ fn setup_erc721_panic() -> (DualCaseERC721, DualCaseERC721) { } fn setup_receiver() -> ContractAddress { - utils::deploy(DualCaseERC721ReceiverMock::TEST_CLASS_HASH, array![]) + test_utils::deploy(DualCaseERC721ReceiverMock::TEST_CLASS_HASH, array![]) } // diff --git a/src/tests/token/erc721/test_dual721_receiver.cairo b/packages/token/src/tests/erc721/test_dual721_receiver.cairo similarity index 77% rename from src/tests/token/erc721/test_dual721_receiver.cairo rename to packages/token/src/tests/erc721/test_dual721_receiver.cairo index 44fc3ee8b..9302370cf 100644 --- a/src/tests/token/erc721/test_dual721_receiver.cairo +++ b/packages/token/src/tests/erc721/test_dual721_receiver.cairo @@ -1,12 +1,3 @@ -use openzeppelin::tests::mocks::erc721_receiver_mocks::{ - CamelERC721ReceiverMock, CamelERC721ReceiverPanicMock -}; -use openzeppelin::tests::mocks::erc721_receiver_mocks::{ - SnakeERC721ReceiverMock, SnakeERC721ReceiverPanicMock -}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::{DATA, OPERATOR, OWNER, TOKEN_ID}; -use openzeppelin::tests::utils; use openzeppelin_token::erc721::dual721_receiver::{ DualCaseERC721Receiver, DualCaseERC721ReceiverTrait }; @@ -17,6 +8,15 @@ use openzeppelin_token::erc721::interface::{ use openzeppelin_token::erc721::interface::{ IERC721ReceiverDispatcher, IERC721ReceiverDispatcherTrait }; +use openzeppelin_token::tests::mocks::erc721_receiver_mocks::{ + CamelERC721ReceiverMock, CamelERC721ReceiverPanicMock +}; +use openzeppelin_token::tests::mocks::erc721_receiver_mocks::{ + SnakeERC721ReceiverMock, SnakeERC721ReceiverPanicMock +}; +use openzeppelin_token::tests::mocks::non_implementing_mock::NonImplementingMock; +use openzeppelin_utils::test_utils::constants::{DATA, OPERATOR, OWNER, TOKEN_ID}; +use openzeppelin_utils::test_utils; // // Setup @@ -24,7 +24,7 @@ use openzeppelin_token::erc721::interface::{ fn setup_snake() -> (DualCaseERC721Receiver, IERC721ReceiverDispatcher) { let mut calldata = array![]; - let target = utils::deploy(SnakeERC721ReceiverMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(SnakeERC721ReceiverMock::TEST_CLASS_HASH, calldata); ( DualCaseERC721Receiver { contract_address: target }, IERC721ReceiverDispatcher { contract_address: target } @@ -33,7 +33,7 @@ fn setup_snake() -> (DualCaseERC721Receiver, IERC721ReceiverDispatcher) { fn setup_camel() -> (DualCaseERC721Receiver, IERC721ReceiverCamelDispatcher) { let mut calldata = array![]; - let target = utils::deploy(CamelERC721ReceiverMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(CamelERC721ReceiverMock::TEST_CLASS_HASH, calldata); ( DualCaseERC721Receiver { contract_address: target }, IERC721ReceiverCamelDispatcher { contract_address: target } @@ -42,13 +42,13 @@ fn setup_camel() -> (DualCaseERC721Receiver, IERC721ReceiverCamelDispatcher) { fn setup_non_erc721_receiver() -> DualCaseERC721Receiver { let calldata = array![]; - let target = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); + let target = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, calldata); DualCaseERC721Receiver { contract_address: target } } fn setup_erc721_receiver_panic() -> (DualCaseERC721Receiver, DualCaseERC721Receiver) { - let snake_target = utils::deploy(SnakeERC721ReceiverPanicMock::TEST_CLASS_HASH, array![]); - let camel_target = utils::deploy(CamelERC721ReceiverPanicMock::TEST_CLASS_HASH, array![]); + let snake_target = test_utils::deploy(SnakeERC721ReceiverPanicMock::TEST_CLASS_HASH, array![]); + let camel_target = test_utils::deploy(CamelERC721ReceiverPanicMock::TEST_CLASS_HASH, array![]); ( DualCaseERC721Receiver { contract_address: snake_target }, DualCaseERC721Receiver { contract_address: camel_target } diff --git a/src/tests/token/erc721/test_erc721.cairo b/packages/token/src/tests/erc721/test_erc721.cairo similarity index 94% rename from src/tests/token/erc721/test_erc721.cairo rename to packages/token/src/tests/erc721/test_erc721.cairo index 0b706b3e6..1d97ac652 100644 --- a/src/tests/token/erc721/test_erc721.cairo +++ b/packages/token/src/tests/erc721/test_erc721.cairo @@ -2,23 +2,22 @@ use core::num::traits::Zero; use openzeppelin_account::AccountComponent; use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; use openzeppelin_introspection::src5; -use openzeppelin_introspection; -use openzeppelin::tests::mocks::account_mocks::{DualCaseAccountMock, CamelAccountMock}; -use openzeppelin::tests::mocks::erc721_mocks::DualCaseERC721Mock; -use openzeppelin::tests::mocks::erc721_receiver_mocks::{ - CamelERC721ReceiverMock, SnakeERC721ReceiverMock -}; -use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; -use openzeppelin::tests::utils::constants::{ - DATA, ZERO, OWNER, CALLER, RECIPIENT, SPENDER, OPERATOR, OTHER, NAME, SYMBOL, TOKEN_ID, - TOKEN_ID_2, PUBKEY, BASE_URI, BASE_URI_2 -}; -use openzeppelin::tests::utils; use openzeppelin_token::erc721::ERC721Component::{ERC721CamelOnlyImpl, ERC721MetadataCamelOnlyImpl}; use openzeppelin_token::erc721::ERC721Component::{ERC721Impl, ERC721MetadataImpl, InternalImpl}; use openzeppelin_token::erc721::ERC721Component; use openzeppelin_token::erc721::interface::IERC721; use openzeppelin_token::erc721; +use openzeppelin_token::tests::mocks::account_mocks::{DualCaseAccountMock, CamelAccountMock}; +use openzeppelin_token::tests::mocks::erc721_mocks::DualCaseERC721Mock; +use openzeppelin_token::tests::mocks::erc721_receiver_mocks::{ + CamelERC721ReceiverMock, SnakeERC721ReceiverMock +}; +use openzeppelin_token::tests::mocks::non_implementing_mock::NonImplementingMock; +use openzeppelin_utils::test_utils::constants::{ + DATA, ZERO, OWNER, CALLER, RECIPIENT, SPENDER, OPERATOR, OTHER, NAME, SYMBOL, TOKEN_ID, + TOKEN_ID_2, PUBKEY, BASE_URI, BASE_URI_2 +}; +use openzeppelin_utils::test_utils; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::testing; @@ -44,26 +43,26 @@ fn setup() -> ComponentState { let mut state = COMPONENT_STATE(); state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(OWNER(), TOKEN_ID); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state } fn setup_receiver() -> ContractAddress { - utils::deploy(SnakeERC721ReceiverMock::TEST_CLASS_HASH, array![]) + test_utils::deploy(SnakeERC721ReceiverMock::TEST_CLASS_HASH, array![]) } fn setup_camel_receiver() -> ContractAddress { - utils::deploy(CamelERC721ReceiverMock::TEST_CLASS_HASH, array![]) + test_utils::deploy(CamelERC721ReceiverMock::TEST_CLASS_HASH, array![]) } fn setup_account() -> ContractAddress { let mut calldata = array![PUBKEY]; - utils::deploy(DualCaseAccountMock::TEST_CLASS_HASH, calldata) + test_utils::deploy(DualCaseAccountMock::TEST_CLASS_HASH, calldata) } fn setup_camel_account() -> ContractAddress { let mut calldata = array![PUBKEY]; - utils::deploy(CamelAccountMock::TEST_CLASS_HASH, calldata) + test_utils::deploy(CamelAccountMock::TEST_CLASS_HASH, calldata) } // @@ -89,7 +88,8 @@ fn test_initializer() { .supports_interface(erc721::interface::IERC721_METADATA_ID); assert!(supports_ierc721_metadata); - let supports_isrc5 = mock_state.supports_interface(introspection::interface::ISRC5_ID); + let supports_isrc5 = mock_state + .supports_interface(openzeppelin_introspection::interface::ISRC5_ID); assert!(supports_isrc5); } @@ -189,7 +189,7 @@ fn test_approve_from_operator() { testing::set_caller_address(OWNER()); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.approve(SPENDER(), TOKEN_ID); @@ -248,7 +248,7 @@ fn test__approve_auth_is_approved_for_all() { let auth = CALLER(); testing::set_caller_address(OWNER()); state.set_approval_for_all(auth, true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state._approve(SPENDER(), TOKEN_ID, auth); assert_only_event_approval(ZERO(), OWNER(), SPENDER(), TOKEN_ID); @@ -335,7 +335,7 @@ fn test_transfer_from_owner() { let recipient = RECIPIENT(); // set approval to check reset state._approve(OTHER(), token_id, ZERO()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); assert_state_before_transfer(owner, recipient, token_id); @@ -357,7 +357,7 @@ fn test_transferFrom_owner() { let recipient = RECIPIENT(); // set approval to check reset state._approve(OTHER(), token_id, ZERO()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); assert_state_before_transfer(owner, recipient, token_id); @@ -444,7 +444,7 @@ fn test_transfer_from_approved() { testing::set_caller_address(owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.transfer_from(owner, recipient, token_id); @@ -463,7 +463,7 @@ fn test_transferFrom_approved() { testing::set_caller_address(owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.transferFrom(owner, recipient, token_id); @@ -483,7 +483,7 @@ fn test_transfer_from_approved_for_all() { testing::set_caller_address(owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.transfer_from(owner, recipient, token_id); @@ -503,7 +503,7 @@ fn test_transferFrom_approved_for_all() { testing::set_caller_address(owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.transferFrom(owner, recipient, token_id); @@ -712,7 +712,7 @@ fn test_safeTransferFrom_to_receiver_failure_camel() { #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_safe_transfer_from_to_non_receiver() { let mut state = setup(); - let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let recipient = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); let token_id = TOKEN_ID; let owner = OWNER(); @@ -724,7 +724,7 @@ fn test_safe_transfer_from_to_non_receiver() { #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_safeTransferFrom_to_non_receiver() { let mut state = setup(); - let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let recipient = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); let token_id = TOKEN_ID; let owner = OWNER(); @@ -771,7 +771,7 @@ fn test_safe_transfer_from_to_owner() { let owner = setup_receiver(); state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(owner, token_id); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); @@ -791,7 +791,7 @@ fn test_safeTransferFrom_to_owner() { let owner = setup_receiver(); state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(owner, token_id); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); @@ -811,7 +811,7 @@ fn test_safe_transfer_from_to_owner_camel() { let owner = setup_camel_receiver(); state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(owner, token_id); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); @@ -831,7 +831,7 @@ fn test_safeTransferFrom_to_owner_camel() { let owner = setup_camel_receiver(); state.initializer(NAME(), SYMBOL(), BASE_URI()); state.mint(owner, token_id); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); assert_eq!(state.owner_of(token_id), owner); assert_eq!(state.balance_of(owner), 1); @@ -855,7 +855,7 @@ fn test_safe_transfer_from_approved() { testing::set_caller_address(owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.safe_transfer_from(owner, receiver, token_id, DATA(true)); @@ -875,7 +875,7 @@ fn test_safeTransferFrom_approved() { testing::set_caller_address(owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.safeTransferFrom(owner, receiver, token_id, DATA(true)); @@ -895,7 +895,7 @@ fn test_safe_transfer_from_approved_camel() { testing::set_caller_address(owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.safe_transfer_from(owner, receiver, token_id, DATA(true)); @@ -915,7 +915,7 @@ fn test_safeTransferFrom_approved_camel() { testing::set_caller_address(owner); state.approve(OPERATOR(), token_id); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.safeTransferFrom(owner, receiver, token_id, DATA(true)); @@ -935,7 +935,7 @@ fn test_safe_transfer_from_approved_for_all() { testing::set_caller_address(owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.safe_transfer_from(owner, receiver, token_id, DATA(true)); @@ -955,7 +955,7 @@ fn test_safeTransferFrom_approved_for_all() { testing::set_caller_address(owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.safeTransferFrom(owner, receiver, token_id, DATA(true)); @@ -975,7 +975,7 @@ fn test_safe_transfer_from_approved_for_all_camel() { testing::set_caller_address(owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.safe_transfer_from(owner, receiver, token_id, DATA(true)); @@ -995,7 +995,7 @@ fn test_safeTransferFrom_approved_for_all_camel() { testing::set_caller_address(owner); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); testing::set_caller_address(OPERATOR()); state.safeTransferFrom(owner, receiver, token_id, DATA(true)); @@ -1151,7 +1151,7 @@ fn test__safe_mint_to_account_camel() { #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test__safe_mint_to_non_receiver() { let mut state = COMPONENT_STATE(); - let recipient = utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); + let recipient = test_utils::deploy(NonImplementingMock::TEST_CLASS_HASH, array![]); let token_id = TOKEN_ID; assert_state_before_mint(recipient); @@ -1206,7 +1206,7 @@ fn test_burn() { let mut state = setup(); state._approve(OTHER(), TOKEN_ID, ZERO()); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); assert_eq!(state.owner_of(TOKEN_ID), OWNER()); assert_eq!(state.balance_of(OWNER()), 1); @@ -1327,7 +1327,7 @@ fn test__approve_with_optional_event_emitting() { fn test__approve_with_optional_event_not_emitting() { let mut state = setup(); state._approve_with_optional_event(SPENDER(), TOKEN_ID, ZERO(), false); - utils::assert_no_events_left(ZERO()); + test_utils::assert_no_events_left(ZERO()); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -1344,7 +1344,7 @@ fn test__approve_with_optional_event_nonexistent_emitting() { fn test__approve_with_optional_event_nonexistent_not_emitting() { let mut state = setup(); state._approve_with_optional_event(SPENDER(), TOKEN_ID, ZERO(), false); - utils::assert_no_events_left(ZERO()); + test_utils::assert_no_events_left(ZERO()); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -1354,7 +1354,7 @@ fn test__approve_with_optional_event_nonexistent_not_emitting() { fn test__approve_with_optional_event_auth_is_owner() { let mut state = setup(); state._approve_with_optional_event(SPENDER(), TOKEN_ID, OWNER(), false); - utils::assert_no_events_left(ZERO()); + test_utils::assert_no_events_left(ZERO()); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -1366,10 +1366,10 @@ fn test__approve_with_optional_event_auth_is_approved_for_all() { let auth = CALLER(); testing::set_caller_address(OWNER()); state.set_approval_for_all(auth, true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state._approve_with_optional_event(SPENDER(), TOKEN_ID, auth, false); - utils::assert_no_events_left(ZERO()); + test_utils::assert_no_events_left(ZERO()); let approved = state.get_approved(TOKEN_ID); assert_eq!(approved, SPENDER()); @@ -1395,7 +1395,7 @@ fn test__is_authorized_approved_for_all() { testing::set_caller_address(OWNER()); state.set_approval_for_all(SPENDER(), true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); let authorized = state._is_authorized(OWNER(), SPENDER(), TOKEN_ID); assert!(authorized); @@ -1407,7 +1407,7 @@ fn test__is_authorized_approved() { testing::set_caller_address(OWNER()); state.approve(SPENDER(), TOKEN_ID); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); let authorized = state._is_authorized(OWNER(), SPENDER(), TOKEN_ID); assert!(authorized); @@ -1439,7 +1439,7 @@ fn test__check_authorized_approved_for_all() { testing::set_caller_address(OWNER()); state.set_approval_for_all(SPENDER(), true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state._check_authorized(OWNER(), SPENDER(), TOKEN_ID); } @@ -1450,7 +1450,7 @@ fn test__check_authorized_approved() { testing::set_caller_address(OWNER()); state.approve(SPENDER(), TOKEN_ID); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state._check_authorized(OWNER(), SPENDER(), TOKEN_ID); } @@ -1526,7 +1526,7 @@ fn test_update_auth_approved_for_all() { let mut state = setup(); testing::set_caller_address(OWNER()); state.set_approval_for_all(OPERATOR(), true); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state.update(RECIPIENT(), TOKEN_ID, OPERATOR()); assert_only_event_transfer(ZERO(), OWNER(), RECIPIENT(), TOKEN_ID); @@ -1538,7 +1538,7 @@ fn test_update_auth_approved() { let mut state = setup(); testing::set_caller_address(OWNER()); state.approve(OPERATOR(), TOKEN_ID); - utils::drop_event(ZERO()); + test_utils::drop_event(ZERO()); state.update(RECIPIENT(), TOKEN_ID, OPERATOR()); assert_only_event_transfer(ZERO(), OWNER(), RECIPIENT(), TOKEN_ID); diff --git a/src/tests/token/erc721/test_erc721_receiver.cairo b/packages/token/src/tests/erc721/test_erc721_receiver.cairo similarity index 88% rename from src/tests/token/erc721/test_erc721_receiver.cairo rename to packages/token/src/tests/erc721/test_erc721_receiver.cairo index 62315b482..5f2a6006c 100644 --- a/src/tests/token/erc721/test_erc721_receiver.cairo +++ b/packages/token/src/tests/erc721/test_erc721_receiver.cairo @@ -1,11 +1,11 @@ +use crate::tests::mocks::erc721_receiver_mocks::DualCaseERC721ReceiverMock; use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; -use openzeppelin::tests::mocks::erc721_receiver_mocks::DualCaseERC721ReceiverMock; -use openzeppelin::tests::utils::constants::{OWNER, OPERATOR, TOKEN_ID, DATA}; use openzeppelin_token::erc721::ERC721ReceiverComponent::{ ERC721ReceiverImpl, ERC721ReceiverCamelImpl, InternalImpl }; use openzeppelin_token::erc721::interface::IERC721_RECEIVER_ID; +use openzeppelin_utils::test_utils::constants::{OWNER, OPERATOR, TOKEN_ID, DATA}; fn STATE() -> DualCaseERC721ReceiverMock::ContractState { DualCaseERC721ReceiverMock::contract_state_for_testing() diff --git a/packages/token/src/tests/mocks.cairo b/packages/token/src/tests/mocks.cairo new file mode 100644 index 000000000..d0d42421e --- /dev/null +++ b/packages/token/src/tests/mocks.cairo @@ -0,0 +1,20 @@ +// pub(crate) mod accesscontrol_mocks; +pub(crate) mod account_mocks; +pub(crate) mod erc1155_mocks; +pub(crate) mod erc1155_receiver_mocks; +pub(crate) mod erc20_mocks; +pub(crate) mod erc20_votes_mocks; +pub(crate) mod erc721_mocks; +pub(crate) mod erc721_receiver_mocks; +// pub(crate) mod eth_account_mocks; +// pub(crate) mod initializable_mocks; +pub(crate) mod non_implementing_mock; +// pub(crate) mod nonces_mocks; +// pub(crate) mod ownable_mocks; +// pub(crate) mod pausable_mocks; +// pub(crate) mod reentrancy_mocks; +pub(crate) mod src5_mocks; +// pub(crate) mod timelock_mocks; +// pub(crate) mod upgrades_mocks; + + diff --git a/packages/token/src/tests/mocks/account_mocks.cairo b/packages/token/src/tests/mocks/account_mocks.cairo new file mode 100644 index 000000000..c2f7d9f57 --- /dev/null +++ b/packages/token/src/tests/mocks/account_mocks.cairo @@ -0,0 +1,223 @@ +#[starknet::contract(account)] +pub(crate) mod DualCaseAccountMock { + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: AccountComponent, storage: account, event: AccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // Account + #[abi(embed_v0)] + impl SRC6Impl = AccountComponent::SRC6Impl; + #[abi(embed_v0)] + impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl; + #[abi(embed_v0)] + impl DeclarerImpl = AccountComponent::DeclarerImpl; + #[abi(embed_v0)] + impl DeployableImpl = AccountComponent::DeployableImpl; + impl AccountInternalImpl = AccountComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + account: AccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccountEvent: AccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: felt252) { + self.account.initializer(public_key); + } +} + +#[starknet::contract(account)] +pub(crate) mod SnakeAccountMock { + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: AccountComponent, storage: account, event: AccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // Account + #[abi(embed_v0)] + impl SRC6Impl = AccountComponent::SRC6Impl; + #[abi(embed_v0)] + impl PublicKeyImpl = AccountComponent::PublicKeyImpl; + impl AccountInternalImpl = AccountComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + account: AccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccountEvent: AccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: felt252) { + self.account.initializer(public_key); + } +} + +#[starknet::contract(account)] +pub(crate) mod CamelAccountMock { + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; + use starknet::account::Call; + + component!(path: AccountComponent, storage: account, event: AccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // Account + #[abi(embed_v0)] + impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl; + #[abi(embed_v0)] + impl PublicKeyCamelImpl = AccountComponent::PublicKeyCamelImpl; + impl SRC6Impl = AccountComponent::SRC6Impl; + impl AccountInternalImpl = AccountComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + account: AccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccountEvent: AccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, publicKey: felt252) { + self.account.initializer(publicKey); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn __execute__(self: @ContractState, mut calls: Array) -> Array> { + self.account.__execute__(calls) + } + + #[external(v0)] + fn __validate__(self: @ContractState, mut calls: Array) -> felt252 { + self.account.__validate__(calls) + } + } +} + +// Although these modules are designed to panic, functions +// still need a valid return value. We chose: +// +// 3 for felt252 +// false for bool + +#[starknet::contract] +pub(crate) mod SnakeAccountPanicMock { + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn set_public_key( + ref self: ContractState, new_public_key: felt252, signature: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn get_public_key(self: @ContractState) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn is_valid_signature( + self: @ContractState, hash: felt252, signature: Array + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelAccountPanicMock { + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn setPublicKey(ref self: ContractState, newPublicKey: felt252, signature: Span) { + panic!("Some error"); + } + + #[external(v0)] + fn getPublicKey(self: @ContractState) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn isValidSignature( + self: @ContractState, hash: felt252, signature: Array + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { + panic!("Some error"); + false + } + } +} diff --git a/packages/token/src/tests/mocks/erc1155_mocks.cairo b/packages/token/src/tests/mocks/erc1155_mocks.cairo new file mode 100644 index 000000000..9d8d79181 --- /dev/null +++ b/packages/token/src/tests/mocks/erc1155_mocks.cairo @@ -0,0 +1,306 @@ +#[starknet::contract] +pub(crate) mod DualCaseERC1155Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC1155 + #[abi(embed_v0)] + impl ERC1155Impl = ERC1155Component::ERC1155Impl; + #[abi(embed_v0)] + impl ERC1155MetadataURIImpl = + ERC1155Component::ERC1155MetadataURIImpl; + #[abi(embed_v0)] + impl ERC721Camel = ERC1155Component::ERC1155CamelImpl; + impl ERC1155InternalImpl = ERC1155Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155: ERC1155Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155Event: ERC1155Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256, + value: u256 + ) { + self.erc1155.initializer(base_uri); + self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC1155Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC1155 + #[abi(embed_v0)] + impl ERC1155Impl = ERC1155Component::ERC1155Impl; + #[abi(embed_v0)] + impl ERC1155MetadataURIImpl = + ERC1155Component::ERC1155MetadataURIImpl; + impl ERC1155InternalImpl = ERC1155Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155: ERC1155Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155Event: ERC1155Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256, + value: u256 + ) { + self.erc1155.initializer(base_uri); + self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); + } +} + +#[starknet::contract] +pub(crate) mod CamelERC1155Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC1155 + #[abi(embed_v0)] + impl ERC1155Camel = ERC1155Component::ERC1155CamelImpl; + #[abi(embed_v0)] + impl ERC1155MetadataURIImpl = + ERC1155Component::ERC1155MetadataURIImpl; + impl ERC1155InternalImpl = ERC1155Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155: ERC1155Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155Event: ERC1155Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256, + value: u256 + ) { + self.erc1155.initializer(base_uri); + self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC1155PanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn uri(self: @ContractState, token_id: u256) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn balance_of(self: @ContractState, account: ContractAddress, token_id: u256) -> u256 { + panic!("Some error"); + u256 { low: 3, high: 3 } + } + + #[external(v0)] + fn balance_of_batch( + self: @ContractState, accounts: Span, token_ids: Span + ) -> Span { + panic!("Some error"); + array![u256 { low: 3, high: 3 }].span() + } + + #[external(v0)] + fn safe_transfer_from( + ref self: ContractState, + from: ContractAddress, + to: ContractAddress, + token_id: u256, + value: u256, + data: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn safe_batch_transfer_from( + ref self: ContractState, + from: starknet::ContractAddress, + to: starknet::ContractAddress, + token_ids: Span, + values: Span, + data: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn is_approved_for_all( + self: @ContractState, owner: ContractAddress, operator: ContractAddress + ) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn set_approval_for_all( + ref self: ContractState, operator: ContractAddress, approved: bool + ) { + panic!("Some error"); + } + + #[external(v0)] + fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC1155PanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn uri(self: @ContractState, tokenId: u256) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn balanceOf(self: @ContractState, account: ContractAddress, tokenId: u256) -> u256 { + panic!("Some error"); + u256 { low: 3, high: 3 } + } + + #[external(v0)] + fn balanceOfBatch( + self: @ContractState, accounts: Span, token_ids: Span + ) -> Span { + panic!("Some error"); + array![u256 { low: 3, high: 3 }].span() + } + + #[external(v0)] + fn safeTransferFrom( + ref self: ContractState, + from: ContractAddress, + to: ContractAddress, + tokenId: u256, + value: u256, + data: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn safeBatchTransferFrom( + ref self: ContractState, + from: starknet::ContractAddress, + to: starknet::ContractAddress, + token_ids: Span, + values: Span, + data: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn isApprovedForAll( + self: @ContractState, owner: ContractAddress, operator: ContractAddress + ) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) { + panic!("Some error"); + } + + #[external(v0)] + fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { + panic!("Some error"); + false + } + } +} diff --git a/src/tests/mocks/erc1155_receiver_mocks.cairo b/packages/token/src/tests/mocks/erc1155_receiver_mocks.cairo similarity index 98% rename from src/tests/mocks/erc1155_receiver_mocks.cairo rename to packages/token/src/tests/mocks/erc1155_receiver_mocks.cairo index adbf6bdab..34ec82649 100644 --- a/src/tests/mocks/erc1155_receiver_mocks.cairo +++ b/packages/token/src/tests/mocks/erc1155_receiver_mocks.cairo @@ -1,4 +1,4 @@ -use openzeppelin::tests::utils::constants::SUCCESS; +use openzeppelin_utils::test_utils::constants::SUCCESS; #[starknet::contract] pub(crate) mod DualCaseERC1155ReceiverMock { diff --git a/packages/token/src/tests/mocks/erc20_mocks.cairo b/packages/token/src/tests/mocks/erc20_mocks.cairo new file mode 100644 index 000000000..80a66d34f --- /dev/null +++ b/packages/token/src/tests/mocks/erc20_mocks.cairo @@ -0,0 +1,253 @@ +#[starknet::contract] +pub(crate) mod DualCaseERC20Mock { + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20Impl = ERC20Component::ERC20Impl; + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; + #[abi(embed_v0)] + impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; + impl InternalImpl = ERC20Component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + initial_supply: u256, + recipient: ContractAddress + ) { + self.erc20.initializer(name, symbol); + self.erc20.mint(recipient, initial_supply); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC20Mock { + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20Impl = ERC20Component::ERC20Impl; + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; + impl InternalImpl = ERC20Component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + initial_supply: u256, + recipient: ContractAddress + ) { + self.erc20.initializer(name, symbol); + self.erc20.mint(recipient, initial_supply); + } +} + +#[starknet::contract] +pub(crate) mod CamelERC20Mock { + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; + #[abi(embed_v0)] + impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; + + // `ERC20Impl` is not embedded because it would defeat the purpose of the + // mock. The `ERC20Impl` case-agnostic methods are manually exposed. + impl ERC20Impl = ERC20Component::ERC20Impl; + impl InternalImpl = ERC20Component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + initial_supply: u256, + recipient: ContractAddress + ) { + self.erc20.initializer(name, symbol); + self.erc20.mint(recipient, initial_supply); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn allowance( + self: @ContractState, owner: ContractAddress, spender: ContractAddress + ) -> u256 { + self.erc20.allowance(owner, spender) + } + + #[external(v0)] + fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { + self.erc20.transfer(recipient, amount) + } + + #[external(v0)] + fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool { + self.erc20.approve(spender, amount) + } + } +} + +/// Although these modules are designed to panic, functions +/// still need a valid return value. We chose: +/// +/// 3 for felt252, u8, and u256 +/// zero for ContractAddress +/// false for bool +#[starknet::contract] +pub(crate) mod SnakeERC20Panic { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn name(self: @ContractState) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn symbol(self: @ContractState) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn decimals(self: @ContractState) -> u8 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn allowance( + self: @ContractState, owner: ContractAddress, spender: ContractAddress + ) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn total_supply(self: @ContractState) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn transfer_from( + ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256 + ) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC20Panic { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn totalSupply(self: @ContractState) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn transferFrom( + ref self: ContractState, + sender: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) { + panic!("Some error"); + } + } +} diff --git a/src/tests/mocks/erc20_votes_mocks.cairo b/packages/token/src/tests/mocks/erc20_votes_mocks.cairo similarity index 100% rename from src/tests/mocks/erc20_votes_mocks.cairo rename to packages/token/src/tests/mocks/erc20_votes_mocks.cairo diff --git a/packages/token/src/tests/mocks/erc721_mocks.cairo b/packages/token/src/tests/mocks/erc721_mocks.cairo new file mode 100644 index 000000000..05aaf81f2 --- /dev/null +++ b/packages/token/src/tests/mocks/erc721_mocks.cairo @@ -0,0 +1,347 @@ +#[starknet::contract] +pub(crate) mod DualCaseERC721Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC721Component, storage: erc721, event: ERC721Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721 + #[abi(embed_v0)] + impl ERC721Impl = ERC721Component::ERC721Impl; + #[abi(embed_v0)] + impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl; + #[abi(embed_v0)] + impl ERC721CamelOnly = ERC721Component::ERC721CamelOnlyImpl; + #[abi(embed_v0)] + impl ERC721MetadataCamelOnly = + ERC721Component::ERC721MetadataCamelOnlyImpl; + impl ERC721InternalImpl = ERC721Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721: ERC721Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721Event: ERC721Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256 + ) { + self.erc721.initializer(name, symbol, base_uri); + self.erc721.mint(recipient, token_id); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC721Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC721Component, storage: erc721, event: ERC721Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721 + #[abi(embed_v0)] + impl ERC721Impl = ERC721Component::ERC721Impl; + #[abi(embed_v0)] + impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl; + impl ERC721InternalImpl = ERC721Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721: ERC721Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721Event: ERC721Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256 + ) { + self.erc721.initializer(name, symbol, base_uri); + self.erc721.mint(recipient, token_id); + } +} + +#[starknet::contract] +pub(crate) mod CamelERC721Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721Component::{ERC721Impl, ERC721MetadataImpl}; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC721Component, storage: erc721, event: ERC721Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721 + #[abi(embed_v0)] + impl ERC721CamelOnly = ERC721Component::ERC721CamelOnlyImpl; + #[abi(embed_v0)] + impl ERC721MetadataCamelOnly = + ERC721Component::ERC721MetadataCamelOnlyImpl; + impl ERC721InternalImpl = ERC721Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721: ERC721Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721Event: ERC721Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256 + ) { + self.erc721.initializer(name, symbol, base_uri); + self.erc721.mint(recipient, token_id); + } + + /// The following external methods are included because they are case-agnostic + /// and this contract should not embed the snake_case impl. + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn approve(ref self: ContractState, to: ContractAddress, tokenId: u256) { + self.erc721.approve(to, tokenId); + } + + #[external(v0)] + fn name(self: @ContractState) -> ByteArray { + self.erc721.name() + } + + #[external(v0)] + fn symbol(self: @ContractState) -> ByteArray { + self.erc721.symbol() + } + } +} + +/// Although these modules are designed to panic, functions +/// still need a valid return value. We chose: +/// +/// 3 for felt252 +/// zero for ContractAddress +/// u256 { 3, 3 } for u256 +#[starknet::contract] +pub(crate) mod SnakeERC721PanicMock { + use core::num::traits::Zero; + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn name(self: @ContractState) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn symbol(self: @ContractState) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) { + panic!("Some error"); + } + + #[external(v0)] + fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn token_uri(self: @ContractState, token_id: u256) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { + panic!("Some error"); + u256 { low: 3, high: 3 } + } + + #[external(v0)] + fn owner_of(self: @ContractState, token_id: u256) -> ContractAddress { + panic!("Some error"); + Zero::zero() + } + + #[external(v0)] + fn get_approved(self: @ContractState, token_id: u256) -> ContractAddress { + panic!("Some error"); + Zero::zero() + } + + #[external(v0)] + fn is_approved_for_all( + self: @ContractState, owner: ContractAddress, operator: ContractAddress + ) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn set_approval_for_all( + ref self: ContractState, operator: ContractAddress, approved: bool + ) { + panic!("Some error"); + } + + #[external(v0)] + fn transfer_from( + ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256 + ) { + panic!("Some error"); + } + + #[external(v0)] + fn safe_transfer_from( + ref self: ContractState, + from: ContractAddress, + to: ContractAddress, + token_id: u256, + data: Span + ) { + panic!("Some error"); + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC721PanicMock { + use core::num::traits::Zero; + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn tokenURI(self: @ContractState, tokenId: u256) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { + panic!("Some error"); + u256 { low: 3, high: 3 } + } + + #[external(v0)] + fn ownerOf(self: @ContractState, tokenId: u256) -> ContractAddress { + panic!("Some error"); + Zero::zero() + } + + #[external(v0)] + fn getApproved(self: @ContractState, tokenId: u256) -> ContractAddress { + panic!("Some error"); + Zero::zero() + } + + #[external(v0)] + fn isApprovedForAll( + self: @ContractState, owner: ContractAddress, operator: ContractAddress + ) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) { + panic!("Some error"); + } + + #[external(v0)] + fn transferFrom( + ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256 + ) { + panic!("Some error"); + } + + #[external(v0)] + fn safeTransferFrom( + ref self: ContractState, + from: ContractAddress, + to: ContractAddress, + tokenId: u256, + data: Span + ) { + panic!("Some error"); + } + } +} diff --git a/packages/token/src/tests/mocks/erc721_receiver_mocks.cairo b/packages/token/src/tests/mocks/erc721_receiver_mocks.cairo new file mode 100644 index 000000000..e321c0d58 --- /dev/null +++ b/packages/token/src/tests/mocks/erc721_receiver_mocks.cairo @@ -0,0 +1,237 @@ +use openzeppelin_utils::test_utils::constants::SUCCESS; + +#[starknet::contract] +pub(crate) mod DualCaseERC721ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721ReceiverComponent; + use starknet::ContractAddress; + + component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721Receiver + impl ERC721ReceiverImpl = ERC721ReceiverComponent::ERC721ReceiverImpl; + impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721_receiver: ERC721ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721ReceiverEvent: ERC721ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc721_receiver.initializer(); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn on_erc721_received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + token_id: u256, + data: Span + ) -> felt252 { + if *data.at(0) == super::SUCCESS { + self.erc721_receiver.on_erc721_received(operator, from, token_id, data) + } else { + 0 + } + } + + #[external(v0)] + fn onERC721Received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenId: u256, + data: Span + ) -> felt252 { + Self::on_erc721_received(self, operator, from, tokenId, data) + } + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC721ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721ReceiverComponent; + use starknet::ContractAddress; + + component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721Receiver + impl ERC721ReceiverImpl = ERC721ReceiverComponent::ERC721ReceiverImpl; + impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721_receiver: ERC721ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721ReceiverEvent: ERC721ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc721_receiver.initializer(); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn on_erc721_received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + token_id: u256, + data: Span + ) -> felt252 { + if *data.at(0) == super::SUCCESS { + self.erc721_receiver.on_erc721_received(operator, from, token_id, data) + } else { + 0 + } + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC721ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721ReceiverComponent; + use starknet::ContractAddress; + + component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721Receiver + impl ERC721ReceiverCamelImpl = ERC721ReceiverComponent::ERC721ReceiverCamelImpl; + impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721_receiver: ERC721ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721ReceiverEvent: ERC721ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc721_receiver.initializer(); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn onERC721Received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenId: u256, + data: Span + ) -> felt252 { + if *data.at(0) == super::SUCCESS { + self.erc721_receiver.onERC721Received(operator, from, tokenId, data) + } else { + 0 + } + } + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC721ReceiverPanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn on_erc721_received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + token_id: u256, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC721ReceiverPanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn onERC721Received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenId: u256, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } + } +} diff --git a/packages/token/src/tests/mocks/non_implementing_mock.cairo b/packages/token/src/tests/mocks/non_implementing_mock.cairo new file mode 100644 index 000000000..c1212dbdd --- /dev/null +++ b/packages/token/src/tests/mocks/non_implementing_mock.cairo @@ -0,0 +1,10 @@ +#[starknet::contract] +pub(crate) mod NonImplementingMock { + #[storage] + struct Storage {} + + #[external(v0)] + fn nope(self: @ContractState) -> bool { + false + } +} diff --git a/packages/token/src/tests/mocks/src5_mocks.cairo b/packages/token/src/tests/mocks/src5_mocks.cairo new file mode 100644 index 000000000..86e8c5167 --- /dev/null +++ b/packages/token/src/tests/mocks/src5_mocks.cairo @@ -0,0 +1,22 @@ +#[starknet::contract] +pub(crate) mod SRC5Mock { + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + SRC5Event: SRC5Component::Event + } +} diff --git a/packages/upgrades/Scarb.toml b/packages/upgrades/Scarb.toml index 39548c389..0a14a4ebc 100644 --- a/packages/upgrades/Scarb.toml +++ b/packages/upgrades/Scarb.toml @@ -18,3 +18,7 @@ fmt.workspace = true [dependencies] starknet.workspace = true + +[dev-dependencies] +cairo_test.workspace = true +openzeppelin_utils = { path = "../utils" } diff --git a/packages/upgrades/src/lib.cairo b/packages/upgrades/src/lib.cairo index d85c912e6..1f6920e8c 100644 --- a/packages/upgrades/src/lib.cairo +++ b/packages/upgrades/src/lib.cairo @@ -1,4 +1,6 @@ pub mod interface; + +pub mod tests; pub mod upgradeable; pub use upgradeable::UpgradeableComponent; diff --git a/packages/upgrades/src/tests.cairo b/packages/upgrades/src/tests.cairo new file mode 100644 index 000000000..036225e91 --- /dev/null +++ b/packages/upgrades/src/tests.cairo @@ -0,0 +1,5 @@ +pub mod common; +pub(crate) mod mocks; + +#[cfg(test)] +mod test_upgradeable; diff --git a/packages/upgrades/src/tests/common.cairo b/packages/upgrades/src/tests/common.cairo new file mode 100644 index 000000000..f8771e460 --- /dev/null +++ b/packages/upgrades/src/tests/common.cairo @@ -0,0 +1,16 @@ +use openzeppelin_upgrades::UpgradeableComponent::Upgraded; +use openzeppelin_upgrades::UpgradeableComponent; +use openzeppelin_utils::test_utils::constants::ZERO; +use openzeppelin_utils::test_utils; +use starknet::{ContractAddress, ClassHash}; + +pub fn assert_event_upgraded(contract: ContractAddress, class_hash: ClassHash) { + let event = test_utils::pop_log::(contract).unwrap(); + let expected = UpgradeableComponent::Event::Upgraded(Upgraded { class_hash }); + assert!(event == expected); +} + +pub fn assert_only_event_upgraded(contract: ContractAddress, class_hash: ClassHash) { + assert_event_upgraded(contract, class_hash); + test_utils::assert_no_events_left(ZERO()); +} diff --git a/packages/upgrades/src/tests/mocks.cairo b/packages/upgrades/src/tests/mocks.cairo new file mode 100644 index 000000000..a287b9e8f --- /dev/null +++ b/packages/upgrades/src/tests/mocks.cairo @@ -0,0 +1 @@ +pub(crate) mod upgrades_mocks; diff --git a/src/tests/mocks/upgrades_mocks.cairo b/packages/upgrades/src/tests/mocks/upgrades_mocks.cairo similarity index 100% rename from src/tests/mocks/upgrades_mocks.cairo rename to packages/upgrades/src/tests/mocks/upgrades_mocks.cairo diff --git a/src/tests/upgrades/test_upgradeable.cairo b/packages/upgrades/src/tests/test_upgradeable.cairo similarity index 85% rename from src/tests/upgrades/test_upgradeable.cairo rename to packages/upgrades/src/tests/test_upgradeable.cairo index 52e0e26eb..fd8648c3a 100644 --- a/src/tests/upgrades/test_upgradeable.cairo +++ b/packages/upgrades/src/tests/test_upgradeable.cairo @@ -1,12 +1,12 @@ -use openzeppelin::tests::mocks::upgrades_mocks::{ +use openzeppelin_upgrades::UpgradeableComponent; +use openzeppelin_upgrades::tests::mocks::upgrades_mocks::{ IUpgradesV1Dispatcher, IUpgradesV1DispatcherTrait, UpgradesV1 }; -use openzeppelin::tests::mocks::upgrades_mocks::{ +use openzeppelin_upgrades::tests::mocks::upgrades_mocks::{ IUpgradesV2Dispatcher, IUpgradesV2DispatcherTrait, UpgradesV2 }; -use openzeppelin::tests::utils::constants::{CLASS_HASH_ZERO, ZERO}; -use openzeppelin::tests::utils; -use openzeppelin_upgrades::UpgradeableComponent; +use openzeppelin_utils::test_utils::constants::{CLASS_HASH_ZERO, ZERO}; +use openzeppelin_utils::test_utils; use starknet::ClassHash; use super::common::assert_only_event_upgraded; @@ -23,7 +23,7 @@ fn V2_CLASS_HASH() -> ClassHash { fn deploy_v1() -> IUpgradesV1Dispatcher { let calldata = array![]; - let address = utils::deploy(UpgradesV1::TEST_CLASS_HASH, calldata); + let address = test_utils::deploy(UpgradesV1::TEST_CLASS_HASH, calldata); IUpgradesV1Dispatcher { contract_address: address } } diff --git a/packages/utils/Scarb.toml b/packages/utils/Scarb.toml index a05c75b5f..a83d99966 100644 --- a/packages/utils/Scarb.toml +++ b/packages/utils/Scarb.toml @@ -18,3 +18,6 @@ fmt.workspace = true [dependencies] starknet.workspace = true + +[dev-dependencies] +cairo_test.workspace = true diff --git a/packages/utils/src/deployments.cairo b/packages/utils/src/deployments.cairo index 7d8423ce0..bec5bed0a 100644 --- a/packages/utils/src/deployments.cairo +++ b/packages/utils/src/deployments.cairo @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/deployments.cairo) + pub mod interface; use core::hash::{HashStateTrait, HashStateExTrait}; diff --git a/packages/utils/src/lib.cairo b/packages/utils/src/lib.cairo index 530d909b3..be157a06d 100644 --- a/packages/utils/src/lib.cairo +++ b/packages/utils/src/lib.cairo @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils.cairo) +pub mod test_utils; pub mod cryptography; pub mod deployments; pub mod interfaces; diff --git a/src/tests/utils.cairo b/packages/utils/src/test_utils.cairo similarity index 93% rename from src/tests/utils.cairo rename to packages/utils/src/test_utils.cairo index 658b94645..3a8ec8547 100644 --- a/src/tests/utils.cairo +++ b/packages/utils/src/test_utils.cairo @@ -1,4 +1,9 @@ -pub(crate) mod constants; +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/test.cairo) + +//! Utilities for testing. + +pub mod constants; use starknet::ContractAddress; use starknet::SyscallResultTrait; diff --git a/packages/utils/src/test_utils/constants.cairo b/packages/utils/src/test_utils/constants.cairo new file mode 100644 index 000000000..c869eae4a --- /dev/null +++ b/packages/utils/src/test_utils/constants.cairo @@ -0,0 +1,117 @@ +use starknet::ClassHash; +use starknet::ContractAddress; +use starknet::SyscallResultTrait; +use starknet::class_hash::class_hash_const; +use starknet::contract_address_const; +use starknet::secp256_trait::Secp256Trait; + +pub type EthPublicKey = starknet::secp256k1::Secp256k1Point; + +pub const DECIMALS: u8 = 18_u8; +pub const SUPPLY: u256 = 2000; +pub const VALUE: u256 = 300; +pub const ROLE: felt252 = 'ROLE'; +pub const OTHER_ROLE: felt252 = 'OTHER_ROLE'; +pub const TOKEN_ID: u256 = 21; +pub const TOKEN_ID_2: u256 = 121; +pub const TOKEN_VALUE: u256 = 42; +pub const TOKEN_VALUE_2: u256 = 142; +pub const PUBKEY: felt252 = 'PUBKEY'; +pub const NEW_PUBKEY: felt252 = + 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7; +pub const DAPP_NAME: felt252 = 'DAPP_NAME'; +pub const DAPP_VERSION: felt252 = 'DAPP_VERSION'; +pub const SALT: felt252 = 'SALT'; +pub const SUCCESS: felt252 = 123123; +pub const FAILURE: felt252 = 456456; +pub const MIN_TRANSACTION_VERSION: felt252 = 1; +// 2**128 +pub const QUERY_OFFSET: felt252 = 0x100000000000000000000000000000000; +// QUERY_OFFSET + MIN_TRANSACTION_VERSION +pub const QUERY_VERSION: felt252 = 0x100000000000000000000000000000001; + +pub fn NAME() -> ByteArray { + "NAME" +} + +pub fn SYMBOL() -> ByteArray { + "SYMBOL" +} + +pub fn BASE_URI() -> ByteArray { + "https://api.example.com/v1/" +} + +pub fn BASE_URI_2() -> ByteArray { + "https://api.example.com/v2/" +} + +pub fn ETH_PUBKEY() -> EthPublicKey { + Secp256Trait::secp256_ec_get_point_from_x_syscall(3, false).unwrap_syscall().unwrap() +} + +pub fn NEW_ETH_PUBKEY() -> EthPublicKey { + Secp256Trait::secp256_ec_get_point_from_x_syscall(4, false).unwrap_syscall().unwrap() +} + +pub fn ADMIN() -> ContractAddress { + contract_address_const::<'ADMIN'>() +} + +pub fn AUTHORIZED() -> ContractAddress { + contract_address_const::<'AUTHORIZED'>() +} + +pub fn ZERO() -> ContractAddress { + contract_address_const::<0>() +} + +pub fn CLASS_HASH_ZERO() -> ClassHash { + class_hash_const::<0>() +} + +pub fn CALLER() -> ContractAddress { + contract_address_const::<'CALLER'>() +} + +pub fn OWNER() -> ContractAddress { + contract_address_const::<'OWNER'>() +} + +pub fn NEW_OWNER() -> ContractAddress { + contract_address_const::<'NEW_OWNER'>() +} + +pub fn OTHER() -> ContractAddress { + contract_address_const::<'OTHER'>() +} + +pub fn OTHER_ADMIN() -> ContractAddress { + contract_address_const::<'OTHER_ADMIN'>() +} + +pub fn SPENDER() -> ContractAddress { + contract_address_const::<'SPENDER'>() +} + +pub fn RECIPIENT() -> ContractAddress { + contract_address_const::<'RECIPIENT'>() +} + +pub fn OPERATOR() -> ContractAddress { + contract_address_const::<'OPERATOR'>() +} + +pub fn DATA(success: bool) -> Span { + let mut data = array![]; + if success { + data.append(SUCCESS); + } else { + data.append(FAILURE); + } + data.span() +} + +pub fn EMPTY_DATA() -> Span { + array![].span() +} diff --git a/src/tests/cryptography.cairo b/packages/utils/tests.cairo similarity index 100% rename from src/tests/cryptography.cairo rename to packages/utils/tests.cairo diff --git a/src/tests/mocks.cairo b/packages/utils/tests/mocks.cairo similarity index 100% rename from src/tests/mocks.cairo rename to packages/utils/tests/mocks.cairo diff --git a/packages/utils/tests/mocks/accesscontrol_mocks.cairo b/packages/utils/tests/mocks/accesscontrol_mocks.cairo new file mode 100644 index 000000000..f9ddb0b38 --- /dev/null +++ b/packages/utils/tests/mocks/accesscontrol_mocks.cairo @@ -0,0 +1,224 @@ +#[starknet::contract] +pub(crate) mod DualCaseAccessControlMock { + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; + use openzeppelin_introspection::src5::SRC5Component; + use starknet::ContractAddress; + + component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // AccessControlMixin + #[abi(embed_v0)] + impl AccessControlMixinImpl = + AccessControlComponent::AccessControlMixinImpl; + impl AccessControlInternalImpl = AccessControlComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + accesscontrol: AccessControlComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccessControlEvent: AccessControlComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, admin: ContractAddress) { + self.accesscontrol.initializer(); + self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin); + } +} + +#[starknet::contract] +pub(crate) mod SnakeAccessControlMock { + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; + use openzeppelin_introspection::src5::SRC5Component; + use starknet::ContractAddress; + + component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // AccessControl + #[abi(embed_v0)] + impl AccessControlImpl = + AccessControlComponent::AccessControlImpl; + impl AccessControlInternalImpl = AccessControlComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + accesscontrol: AccessControlComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage, + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccessControlEvent: AccessControlComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, admin: ContractAddress) { + self.accesscontrol.initializer(); + self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin); + } +} + +#[starknet::contract] +pub(crate) mod CamelAccessControlMock { + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; + use openzeppelin_introspection::src5::SRC5Component; + use starknet::ContractAddress; + + component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // AccessControl + #[abi(embed_v0)] + impl AccessControlCamelImpl = + AccessControlComponent::AccessControlCamelImpl; + impl AccessControlInternalImpl = AccessControlComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + + #[storage] + struct Storage { + #[substorage(v0)] + accesscontrol: AccessControlComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccessControlEvent: AccessControlComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, admin: ContractAddress) { + self.accesscontrol.initializer(); + self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin); + } +} + +// Although these modules are designed to panic, functions +// still need a valid return value. We chose: +// +// 3 for felt252 +// false for bool + +#[starknet::contract] +pub(crate) mod SnakeAccessControlPanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn has_role(self: @ContractState, role: felt252, account: ContractAddress) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn get_role_admin(self: @ContractState, role: felt252) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn grant_role(ref self: ContractState, role: felt252, account: ContractAddress) { + panic!("Some error"); + } + + #[external(v0)] + fn revoke_role(ref self: ContractState, role: felt252, account: ContractAddress) { + panic!("Some error"); + } + + #[external(v0)] + fn renounce_role(ref self: ContractState, role: felt252, account: ContractAddress) { + panic!("Some error"); + } + + #[external(v0)] + fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelAccessControlPanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn hasRole(self: @ContractState, role: felt252, account: ContractAddress) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn getRoleAdmin(self: @ContractState, role: felt252) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn grantRole(ref self: ContractState, role: felt252, account: ContractAddress) { + panic!("Some error"); + } + + #[external(v0)] + fn revokeRole(ref self: ContractState, role: felt252, account: ContractAddress) { + panic!("Some error"); + } + + #[external(v0)] + fn renounceRole(ref self: ContractState, role: felt252, account: ContractAddress) { + panic!("Some error"); + } + + #[external(v0)] + fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { + panic!("Some error"); + false + } + } +} diff --git a/packages/utils/tests/mocks/account_mocks.cairo b/packages/utils/tests/mocks/account_mocks.cairo new file mode 100644 index 000000000..c2f7d9f57 --- /dev/null +++ b/packages/utils/tests/mocks/account_mocks.cairo @@ -0,0 +1,223 @@ +#[starknet::contract(account)] +pub(crate) mod DualCaseAccountMock { + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: AccountComponent, storage: account, event: AccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // Account + #[abi(embed_v0)] + impl SRC6Impl = AccountComponent::SRC6Impl; + #[abi(embed_v0)] + impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl; + #[abi(embed_v0)] + impl DeclarerImpl = AccountComponent::DeclarerImpl; + #[abi(embed_v0)] + impl DeployableImpl = AccountComponent::DeployableImpl; + impl AccountInternalImpl = AccountComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + account: AccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccountEvent: AccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: felt252) { + self.account.initializer(public_key); + } +} + +#[starknet::contract(account)] +pub(crate) mod SnakeAccountMock { + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: AccountComponent, storage: account, event: AccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // Account + #[abi(embed_v0)] + impl SRC6Impl = AccountComponent::SRC6Impl; + #[abi(embed_v0)] + impl PublicKeyImpl = AccountComponent::PublicKeyImpl; + impl AccountInternalImpl = AccountComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + account: AccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccountEvent: AccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: felt252) { + self.account.initializer(public_key); + } +} + +#[starknet::contract(account)] +pub(crate) mod CamelAccountMock { + use openzeppelin_account::AccountComponent; + use openzeppelin_introspection::src5::SRC5Component; + use starknet::account::Call; + + component!(path: AccountComponent, storage: account, event: AccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // Account + #[abi(embed_v0)] + impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl; + #[abi(embed_v0)] + impl PublicKeyCamelImpl = AccountComponent::PublicKeyCamelImpl; + impl SRC6Impl = AccountComponent::SRC6Impl; + impl AccountInternalImpl = AccountComponent::InternalImpl; + + // SCR5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + account: AccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccountEvent: AccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, publicKey: felt252) { + self.account.initializer(publicKey); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn __execute__(self: @ContractState, mut calls: Array) -> Array> { + self.account.__execute__(calls) + } + + #[external(v0)] + fn __validate__(self: @ContractState, mut calls: Array) -> felt252 { + self.account.__validate__(calls) + } + } +} + +// Although these modules are designed to panic, functions +// still need a valid return value. We chose: +// +// 3 for felt252 +// false for bool + +#[starknet::contract] +pub(crate) mod SnakeAccountPanicMock { + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn set_public_key( + ref self: ContractState, new_public_key: felt252, signature: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn get_public_key(self: @ContractState) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn is_valid_signature( + self: @ContractState, hash: felt252, signature: Array + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelAccountPanicMock { + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn setPublicKey(ref self: ContractState, newPublicKey: felt252, signature: Span) { + panic!("Some error"); + } + + #[external(v0)] + fn getPublicKey(self: @ContractState) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn isValidSignature( + self: @ContractState, hash: felt252, signature: Array + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { + panic!("Some error"); + false + } + } +} diff --git a/packages/utils/tests/mocks/erc1155_mocks.cairo b/packages/utils/tests/mocks/erc1155_mocks.cairo new file mode 100644 index 000000000..9d8d79181 --- /dev/null +++ b/packages/utils/tests/mocks/erc1155_mocks.cairo @@ -0,0 +1,306 @@ +#[starknet::contract] +pub(crate) mod DualCaseERC1155Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC1155 + #[abi(embed_v0)] + impl ERC1155Impl = ERC1155Component::ERC1155Impl; + #[abi(embed_v0)] + impl ERC1155MetadataURIImpl = + ERC1155Component::ERC1155MetadataURIImpl; + #[abi(embed_v0)] + impl ERC721Camel = ERC1155Component::ERC1155CamelImpl; + impl ERC1155InternalImpl = ERC1155Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155: ERC1155Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155Event: ERC1155Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256, + value: u256 + ) { + self.erc1155.initializer(base_uri); + self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC1155Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC1155 + #[abi(embed_v0)] + impl ERC1155Impl = ERC1155Component::ERC1155Impl; + #[abi(embed_v0)] + impl ERC1155MetadataURIImpl = + ERC1155Component::ERC1155MetadataURIImpl; + impl ERC1155InternalImpl = ERC1155Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155: ERC1155Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155Event: ERC1155Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256, + value: u256 + ) { + self.erc1155.initializer(base_uri); + self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); + } +} + +#[starknet::contract] +pub(crate) mod CamelERC1155Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC1155 + #[abi(embed_v0)] + impl ERC1155Camel = ERC1155Component::ERC1155CamelImpl; + #[abi(embed_v0)] + impl ERC1155MetadataURIImpl = + ERC1155Component::ERC1155MetadataURIImpl; + impl ERC1155InternalImpl = ERC1155Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155: ERC1155Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155Event: ERC1155Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256, + value: u256 + ) { + self.erc1155.initializer(base_uri); + self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC1155PanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn uri(self: @ContractState, token_id: u256) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn balance_of(self: @ContractState, account: ContractAddress, token_id: u256) -> u256 { + panic!("Some error"); + u256 { low: 3, high: 3 } + } + + #[external(v0)] + fn balance_of_batch( + self: @ContractState, accounts: Span, token_ids: Span + ) -> Span { + panic!("Some error"); + array![u256 { low: 3, high: 3 }].span() + } + + #[external(v0)] + fn safe_transfer_from( + ref self: ContractState, + from: ContractAddress, + to: ContractAddress, + token_id: u256, + value: u256, + data: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn safe_batch_transfer_from( + ref self: ContractState, + from: starknet::ContractAddress, + to: starknet::ContractAddress, + token_ids: Span, + values: Span, + data: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn is_approved_for_all( + self: @ContractState, owner: ContractAddress, operator: ContractAddress + ) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn set_approval_for_all( + ref self: ContractState, operator: ContractAddress, approved: bool + ) { + panic!("Some error"); + } + + #[external(v0)] + fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC1155PanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn uri(self: @ContractState, tokenId: u256) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn balanceOf(self: @ContractState, account: ContractAddress, tokenId: u256) -> u256 { + panic!("Some error"); + u256 { low: 3, high: 3 } + } + + #[external(v0)] + fn balanceOfBatch( + self: @ContractState, accounts: Span, token_ids: Span + ) -> Span { + panic!("Some error"); + array![u256 { low: 3, high: 3 }].span() + } + + #[external(v0)] + fn safeTransferFrom( + ref self: ContractState, + from: ContractAddress, + to: ContractAddress, + tokenId: u256, + value: u256, + data: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn safeBatchTransferFrom( + ref self: ContractState, + from: starknet::ContractAddress, + to: starknet::ContractAddress, + token_ids: Span, + values: Span, + data: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn isApprovedForAll( + self: @ContractState, owner: ContractAddress, operator: ContractAddress + ) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) { + panic!("Some error"); + } + + #[external(v0)] + fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { + panic!("Some error"); + false + } + } +} diff --git a/packages/utils/tests/mocks/erc1155_receiver_mocks.cairo b/packages/utils/tests/mocks/erc1155_receiver_mocks.cairo new file mode 100644 index 000000000..34ec82649 --- /dev/null +++ b/packages/utils/tests/mocks/erc1155_receiver_mocks.cairo @@ -0,0 +1,197 @@ +use openzeppelin_utils::test_utils::constants::SUCCESS; + +#[starknet::contract] +pub(crate) mod DualCaseERC1155ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::ERC1155ReceiverComponent; + use starknet::ContractAddress; + + component!(path: SRC5Component, storage: src5, event: SRC5Event); + component!( + path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent + ); + + // ERC1155Receiver Mixin + #[abi(embed_v0)] + impl ERC1155ReceiverMixinImpl = + ERC1155ReceiverComponent::ERC1155ReceiverMixinImpl; + impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155_receiver: ERC1155ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc1155_receiver.initializer(); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC1155ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::ERC1155ReceiverComponent; + use starknet::ContractAddress; + + component!(path: SRC5Component, storage: src5, event: SRC5Event); + component!( + path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent + ); + + // ERC1155Receiver + #[abi(embed_v0)] + impl ERC1155ReceiverImpl = + ERC1155ReceiverComponent::ERC1155ReceiverImpl; + impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155_receiver: ERC1155ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc1155_receiver.initializer(); + } +} + +#[starknet::contract] +pub(crate) mod CamelERC1155ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::ERC1155ReceiverComponent; + use starknet::ContractAddress; + + component!(path: SRC5Component, storage: src5, event: SRC5Event); + component!( + path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent + ); + + // ERC1155Receiver + #[abi(embed_v0)] + impl ERC1155ReceiverCamelImpl = + ERC1155ReceiverComponent::ERC1155ReceiverCamelImpl; + impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155_receiver: ERC1155ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc1155_receiver.initializer(); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC1155ReceiverPanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[external(v0)] + fn on_erc1155_received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + token_id: u256, + value: u256, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn on_erc1155_batch_received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenIds: Span, + values: Span, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } +} + +#[starknet::contract] +pub(crate) mod CamelERC1155ReceiverPanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[external(v0)] + fn onERC1155Received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenId: u256, + value: u256, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn onERC1155BatchReceived( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenIds: Span, + values: Span, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } +} diff --git a/packages/utils/tests/mocks/erc20_mocks.cairo b/packages/utils/tests/mocks/erc20_mocks.cairo new file mode 100644 index 000000000..80a66d34f --- /dev/null +++ b/packages/utils/tests/mocks/erc20_mocks.cairo @@ -0,0 +1,253 @@ +#[starknet::contract] +pub(crate) mod DualCaseERC20Mock { + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20Impl = ERC20Component::ERC20Impl; + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; + #[abi(embed_v0)] + impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; + impl InternalImpl = ERC20Component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + initial_supply: u256, + recipient: ContractAddress + ) { + self.erc20.initializer(name, symbol); + self.erc20.mint(recipient, initial_supply); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC20Mock { + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20Impl = ERC20Component::ERC20Impl; + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; + impl InternalImpl = ERC20Component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + initial_supply: u256, + recipient: ContractAddress + ) { + self.erc20.initializer(name, symbol); + self.erc20.mint(recipient, initial_supply); + } +} + +#[starknet::contract] +pub(crate) mod CamelERC20Mock { + use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + + #[abi(embed_v0)] + impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; + #[abi(embed_v0)] + impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; + + // `ERC20Impl` is not embedded because it would defeat the purpose of the + // mock. The `ERC20Impl` case-agnostic methods are manually exposed. + impl ERC20Impl = ERC20Component::ERC20Impl; + impl InternalImpl = ERC20Component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20: ERC20Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20Event: ERC20Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + initial_supply: u256, + recipient: ContractAddress + ) { + self.erc20.initializer(name, symbol); + self.erc20.mint(recipient, initial_supply); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn allowance( + self: @ContractState, owner: ContractAddress, spender: ContractAddress + ) -> u256 { + self.erc20.allowance(owner, spender) + } + + #[external(v0)] + fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { + self.erc20.transfer(recipient, amount) + } + + #[external(v0)] + fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool { + self.erc20.approve(spender, amount) + } + } +} + +/// Although these modules are designed to panic, functions +/// still need a valid return value. We chose: +/// +/// 3 for felt252, u8, and u256 +/// zero for ContractAddress +/// false for bool +#[starknet::contract] +pub(crate) mod SnakeERC20Panic { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn name(self: @ContractState) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn symbol(self: @ContractState) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn decimals(self: @ContractState) -> u8 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn allowance( + self: @ContractState, owner: ContractAddress, spender: ContractAddress + ) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn total_supply(self: @ContractState) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn transfer_from( + ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256 + ) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC20Panic { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn totalSupply(self: @ContractState) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn transferFrom( + ref self: ContractState, + sender: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) { + panic!("Some error"); + } + } +} diff --git a/packages/utils/tests/mocks/erc20_votes_mocks.cairo b/packages/utils/tests/mocks/erc20_votes_mocks.cairo new file mode 100644 index 000000000..a2a79ca18 --- /dev/null +++ b/packages/utils/tests/mocks/erc20_votes_mocks.cairo @@ -0,0 +1,101 @@ +#[starknet::contract] +pub(crate) mod DualCaseERC20VotesMock { + use openzeppelin_token::erc20::ERC20Component; + use openzeppelin_token::erc20::extensions::ERC20VotesComponent::InternalTrait as ERC20VotesInternalTrait; + use openzeppelin_token::erc20::extensions::ERC20VotesComponent; + use openzeppelin_utils::cryptography::nonces::NoncesComponent; + use openzeppelin_utils::cryptography::snip12::SNIP12Metadata; + use starknet::ContractAddress; + + component!(path: ERC20VotesComponent, storage: erc20_votes, event: ERC20VotesEvent); + component!(path: ERC20Component, storage: erc20, event: ERC20Event); + component!(path: NoncesComponent, storage: nonces, event: NoncesEvent); + + // ERC20Votes + #[abi(embed_v0)] + impl ERC20VotesComponentImpl = + ERC20VotesComponent::ERC20VotesImpl; + + // ERC20Mixin + #[abi(embed_v0)] + impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl; + impl InternalImpl = ERC20Component::InternalImpl; + + // Nonces + #[abi(embed_v0)] + impl NoncesImpl = NoncesComponent::NoncesImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc20_votes: ERC20VotesComponent::Storage, + #[substorage(v0)] + erc20: ERC20Component::Storage, + #[substorage(v0)] + nonces: NoncesComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC20VotesEvent: ERC20VotesComponent::Event, + #[flat] + ERC20Event: ERC20Component::Event, + #[flat] + NoncesEvent: NoncesComponent::Event + } + + /// Required for hash computation. + pub(crate) impl SNIP12MetadataImpl of SNIP12Metadata { + fn name() -> felt252 { + 'DAPP_NAME' + } + fn version() -> felt252 { + 'DAPP_VERSION' + } + } + + // + // Hooks + // + + impl ERC20VotesHooksImpl< + TContractState, + impl ERC20Votes: ERC20VotesComponent::HasComponent, + impl HasComponent: ERC20Component::HasComponent, + +NoncesComponent::HasComponent, + +Drop + > of ERC20Component::ERC20HooksTrait { + fn before_update( + ref self: ERC20Component::ComponentState, + from: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) {} + + fn after_update( + ref self: ERC20Component::ComponentState, + from: ContractAddress, + recipient: ContractAddress, + amount: u256 + ) { + let mut erc20_votes_component = get_dep_component_mut!(ref self, ERC20Votes); + erc20_votes_component.transfer_voting_units(from, recipient, amount); + } + } + + /// Sets the token `name` and `symbol`. + /// Mints `fixed_supply` tokens to `recipient`. + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + fixed_supply: u256, + recipient: ContractAddress + ) { + self.erc20.initializer(name, symbol); + self.erc20.mint(recipient, fixed_supply); + } +} diff --git a/packages/utils/tests/mocks/erc721_mocks.cairo b/packages/utils/tests/mocks/erc721_mocks.cairo new file mode 100644 index 000000000..05aaf81f2 --- /dev/null +++ b/packages/utils/tests/mocks/erc721_mocks.cairo @@ -0,0 +1,347 @@ +#[starknet::contract] +pub(crate) mod DualCaseERC721Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC721Component, storage: erc721, event: ERC721Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721 + #[abi(embed_v0)] + impl ERC721Impl = ERC721Component::ERC721Impl; + #[abi(embed_v0)] + impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl; + #[abi(embed_v0)] + impl ERC721CamelOnly = ERC721Component::ERC721CamelOnlyImpl; + #[abi(embed_v0)] + impl ERC721MetadataCamelOnly = + ERC721Component::ERC721MetadataCamelOnlyImpl; + impl ERC721InternalImpl = ERC721Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721: ERC721Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721Event: ERC721Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256 + ) { + self.erc721.initializer(name, symbol, base_uri); + self.erc721.mint(recipient, token_id); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC721Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC721Component, storage: erc721, event: ERC721Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721 + #[abi(embed_v0)] + impl ERC721Impl = ERC721Component::ERC721Impl; + #[abi(embed_v0)] + impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl; + impl ERC721InternalImpl = ERC721Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721: ERC721Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721Event: ERC721Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256 + ) { + self.erc721.initializer(name, symbol, base_uri); + self.erc721.mint(recipient, token_id); + } +} + +#[starknet::contract] +pub(crate) mod CamelERC721Mock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721Component::{ERC721Impl, ERC721MetadataImpl}; + use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use starknet::ContractAddress; + + component!(path: ERC721Component, storage: erc721, event: ERC721Event); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721 + #[abi(embed_v0)] + impl ERC721CamelOnly = ERC721Component::ERC721CamelOnlyImpl; + #[abi(embed_v0)] + impl ERC721MetadataCamelOnly = + ERC721Component::ERC721MetadataCamelOnlyImpl; + impl ERC721InternalImpl = ERC721Component::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721: ERC721Component::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721Event: ERC721Component::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + name: ByteArray, + symbol: ByteArray, + base_uri: ByteArray, + recipient: ContractAddress, + token_id: u256 + ) { + self.erc721.initializer(name, symbol, base_uri); + self.erc721.mint(recipient, token_id); + } + + /// The following external methods are included because they are case-agnostic + /// and this contract should not embed the snake_case impl. + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn approve(ref self: ContractState, to: ContractAddress, tokenId: u256) { + self.erc721.approve(to, tokenId); + } + + #[external(v0)] + fn name(self: @ContractState) -> ByteArray { + self.erc721.name() + } + + #[external(v0)] + fn symbol(self: @ContractState) -> ByteArray { + self.erc721.symbol() + } + } +} + +/// Although these modules are designed to panic, functions +/// still need a valid return value. We chose: +/// +/// 3 for felt252 +/// zero for ContractAddress +/// u256 { 3, 3 } for u256 +#[starknet::contract] +pub(crate) mod SnakeERC721PanicMock { + use core::num::traits::Zero; + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn name(self: @ContractState) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn symbol(self: @ContractState) -> ByteArray { + panic!("Some error"); + "3" + } + + #[external(v0)] + fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) { + panic!("Some error"); + } + + #[external(v0)] + fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn token_uri(self: @ContractState, token_id: u256) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { + panic!("Some error"); + u256 { low: 3, high: 3 } + } + + #[external(v0)] + fn owner_of(self: @ContractState, token_id: u256) -> ContractAddress { + panic!("Some error"); + Zero::zero() + } + + #[external(v0)] + fn get_approved(self: @ContractState, token_id: u256) -> ContractAddress { + panic!("Some error"); + Zero::zero() + } + + #[external(v0)] + fn is_approved_for_all( + self: @ContractState, owner: ContractAddress, operator: ContractAddress + ) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn set_approval_for_all( + ref self: ContractState, operator: ContractAddress, approved: bool + ) { + panic!("Some error"); + } + + #[external(v0)] + fn transfer_from( + ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256 + ) { + panic!("Some error"); + } + + #[external(v0)] + fn safe_transfer_from( + ref self: ContractState, + from: ContractAddress, + to: ContractAddress, + token_id: u256, + data: Span + ) { + panic!("Some error"); + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC721PanicMock { + use core::num::traits::Zero; + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn tokenURI(self: @ContractState, tokenId: u256) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { + panic!("Some error"); + u256 { low: 3, high: 3 } + } + + #[external(v0)] + fn ownerOf(self: @ContractState, tokenId: u256) -> ContractAddress { + panic!("Some error"); + Zero::zero() + } + + #[external(v0)] + fn getApproved(self: @ContractState, tokenId: u256) -> ContractAddress { + panic!("Some error"); + Zero::zero() + } + + #[external(v0)] + fn isApprovedForAll( + self: @ContractState, owner: ContractAddress, operator: ContractAddress + ) -> bool { + panic!("Some error"); + false + } + + #[external(v0)] + fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) { + panic!("Some error"); + } + + #[external(v0)] + fn transferFrom( + ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256 + ) { + panic!("Some error"); + } + + #[external(v0)] + fn safeTransferFrom( + ref self: ContractState, + from: ContractAddress, + to: ContractAddress, + tokenId: u256, + data: Span + ) { + panic!("Some error"); + } + } +} diff --git a/packages/utils/tests/mocks/erc721_receiver_mocks.cairo b/packages/utils/tests/mocks/erc721_receiver_mocks.cairo new file mode 100644 index 000000000..e321c0d58 --- /dev/null +++ b/packages/utils/tests/mocks/erc721_receiver_mocks.cairo @@ -0,0 +1,237 @@ +use openzeppelin_utils::test_utils::constants::SUCCESS; + +#[starknet::contract] +pub(crate) mod DualCaseERC721ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721ReceiverComponent; + use starknet::ContractAddress; + + component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721Receiver + impl ERC721ReceiverImpl = ERC721ReceiverComponent::ERC721ReceiverImpl; + impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721_receiver: ERC721ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721ReceiverEvent: ERC721ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc721_receiver.initializer(); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn on_erc721_received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + token_id: u256, + data: Span + ) -> felt252 { + if *data.at(0) == super::SUCCESS { + self.erc721_receiver.on_erc721_received(operator, from, token_id, data) + } else { + 0 + } + } + + #[external(v0)] + fn onERC721Received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenId: u256, + data: Span + ) -> felt252 { + Self::on_erc721_received(self, operator, from, tokenId, data) + } + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC721ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721ReceiverComponent; + use starknet::ContractAddress; + + component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721Receiver + impl ERC721ReceiverImpl = ERC721ReceiverComponent::ERC721ReceiverImpl; + impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721_receiver: ERC721ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721ReceiverEvent: ERC721ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc721_receiver.initializer(); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn on_erc721_received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + token_id: u256, + data: Span + ) -> felt252 { + if *data.at(0) == super::SUCCESS { + self.erc721_receiver.on_erc721_received(operator, from, token_id, data) + } else { + 0 + } + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC721ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc721::ERC721ReceiverComponent; + use starknet::ContractAddress; + + component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + // ERC721Receiver + impl ERC721ReceiverCamelImpl = ERC721ReceiverComponent::ERC721ReceiverCamelImpl; + impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc721_receiver: ERC721ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC721ReceiverEvent: ERC721ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc721_receiver.initializer(); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn onERC721Received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenId: u256, + data: Span + ) -> felt252 { + if *data.at(0) == super::SUCCESS { + self.erc721_receiver.onERC721Received(operator, from, tokenId, data) + } else { + 0 + } + } + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC721ReceiverPanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn on_erc721_received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + token_id: u256, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } + } +} + +#[starknet::contract] +pub(crate) mod CamelERC721ReceiverPanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn onERC721Received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenId: u256, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } + } +} diff --git a/packages/utils/tests/mocks/eth_account_mocks.cairo b/packages/utils/tests/mocks/eth_account_mocks.cairo new file mode 100644 index 000000000..b230e524d --- /dev/null +++ b/packages/utils/tests/mocks/eth_account_mocks.cairo @@ -0,0 +1,228 @@ +#[starknet::contract(account)] +pub(crate) mod DualCaseEthAccountMock { + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC6Impl = EthAccountComponent::SRC6Impl; + #[abi(embed_v0)] + impl SRC6CamelOnlyImpl = EthAccountComponent::SRC6CamelOnlyImpl; + #[abi(embed_v0)] + impl DeclarerImpl = EthAccountComponent::DeclarerImpl; + #[abi(embed_v0)] + impl DeployableImpl = EthAccountComponent::DeployableImpl; + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + eth_account: EthAccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + EthAccountEvent: EthAccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: EthPublicKey) { + self.eth_account.initializer(public_key); + } +} + +#[starknet::contract(account)] +pub(crate) mod SnakeEthAccountMock { + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC6Impl = EthAccountComponent::SRC6Impl; + #[abi(embed_v0)] + impl PublicKeyImpl = EthAccountComponent::PublicKeyImpl; + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + eth_account: EthAccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + EthAccountEvent: EthAccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: EthPublicKey) { + self.eth_account.initializer(public_key); + } +} + +#[starknet::contract(account)] +pub(crate) mod CamelEthAccountMock { + use openzeppelin_account::EthAccountComponent; + use openzeppelin_account::interface::EthPublicKey; + use openzeppelin_introspection::src5::SRC5Component; + use starknet::account::Call; + + component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC6CamelOnlyImpl = EthAccountComponent::SRC6CamelOnlyImpl; + #[abi(embed_v0)] + impl PublicKeyCamelImpl = + EthAccountComponent::PublicKeyCamelImpl; + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + impl SRC6Impl = EthAccountComponent::SRC6Impl; + impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + eth_account: EthAccountComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + EthAccountEvent: EthAccountComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState, publicKey: EthPublicKey) { + self.eth_account.initializer(publicKey); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn __execute__(self: @ContractState, mut calls: Array) -> Array> { + self.eth_account.__execute__(calls) + } + + #[external(v0)] + fn __validate__(self: @ContractState, mut calls: Array) -> felt252 { + self.eth_account.__validate__(calls) + } + } +} + +// Although these modules are designed to panic, functions +// still need a valid return value. We chose: +// +// 3 for felt252 +// false for bool + +#[starknet::contract] +pub(crate) mod SnakeEthAccountPanicMock { + use openzeppelin_account::interface::EthPublicKey; + use starknet::SyscallResultTrait; + use starknet::secp256_trait::Secp256Trait; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn set_public_key( + ref self: ContractState, new_public_key: EthPublicKey, signature: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn get_public_key(self: @ContractState) -> EthPublicKey { + panic!("Some error"); + Secp256Trait::secp256_ec_new_syscall(3, 3).unwrap_syscall().unwrap() + } + + #[external(v0)] + fn is_valid_signature( + self: @ContractState, hash: felt252, signature: Array + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + panic!("Some error"); + false + } + } +} + +#[starknet::contract] +pub(crate) mod CamelEthAccountPanicMock { + use openzeppelin_account::interface::EthPublicKey; + use starknet::SyscallResultTrait; + use starknet::secp256_trait::Secp256Trait; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn setPublicKey( + ref self: ContractState, newPublicKey: EthPublicKey, signature: Span + ) { + panic!("Some error"); + } + + #[external(v0)] + fn getPublicKey(self: @ContractState) -> EthPublicKey { + panic!("Some error"); + Secp256Trait::secp256_ec_new_syscall(3, 3).unwrap_syscall().unwrap() + } + + #[external(v0)] + fn isValidSignature( + self: @ContractState, hash: felt252, signature: Array + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { + panic!("Some error"); + false + } + } +} diff --git a/packages/utils/tests/mocks/initializable_mocks.cairo b/packages/utils/tests/mocks/initializable_mocks.cairo new file mode 100644 index 000000000..92841237d --- /dev/null +++ b/packages/utils/tests/mocks/initializable_mocks.cairo @@ -0,0 +1,23 @@ +#[starknet::contract] +pub(crate) mod InitializableMock { + use openzeppelin_security::initializable::InitializableComponent; + + component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); + + #[abi(embed_v0)] + impl InitializableImpl = + InitializableComponent::InitializableImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + initializable: InitializableComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + InitializableEvent: InitializableComponent::Event + } +} diff --git a/packages/utils/tests/mocks/non_implementing_mock.cairo b/packages/utils/tests/mocks/non_implementing_mock.cairo new file mode 100644 index 000000000..c1212dbdd --- /dev/null +++ b/packages/utils/tests/mocks/non_implementing_mock.cairo @@ -0,0 +1,10 @@ +#[starknet::contract] +pub(crate) mod NonImplementingMock { + #[storage] + struct Storage {} + + #[external(v0)] + fn nope(self: @ContractState) -> bool { + false + } +} diff --git a/src/tests/mocks/nonces_mocks.cairo b/packages/utils/tests/mocks/nonces_mocks.cairo similarity index 100% rename from src/tests/mocks/nonces_mocks.cairo rename to packages/utils/tests/mocks/nonces_mocks.cairo diff --git a/packages/utils/tests/mocks/ownable_mocks.cairo b/packages/utils/tests/mocks/ownable_mocks.cairo new file mode 100644 index 000000000..1448f0cb0 --- /dev/null +++ b/packages/utils/tests/mocks/ownable_mocks.cairo @@ -0,0 +1,188 @@ +#[starknet::contract] +pub(crate) mod DualCaseOwnableMock { + use openzeppelin_access::ownable::OwnableComponent; + use starknet::ContractAddress; + + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); + + #[abi(embed_v0)] + impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl; + impl InternalImpl = OwnableComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + ownable: OwnableComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + OwnableEvent: OwnableComponent::Event + } + + #[constructor] + fn constructor(ref self: ContractState, owner: ContractAddress) { + self.ownable.initializer(owner); + } +} + +#[starknet::contract] +pub(crate) mod SnakeOwnableMock { + use openzeppelin_access::ownable::OwnableComponent; + use starknet::ContractAddress; + + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); + + #[abi(embed_v0)] + impl OwnableImpl = OwnableComponent::OwnableImpl; + impl InternalImpl = OwnableComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + ownable: OwnableComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + OwnableEvent: OwnableComponent::Event + } + + #[constructor] + fn constructor(ref self: ContractState, owner: ContractAddress) { + self.ownable.initializer(owner); + } +} + +#[starknet::contract] +pub(crate) mod CamelOwnableMock { + use openzeppelin_access::ownable::OwnableComponent; + use starknet::ContractAddress; + + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); + + #[abi(embed_v0)] + impl OwnableCamelOnlyImpl = + OwnableComponent::OwnableCamelOnlyImpl; + impl InternalImpl = OwnableComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + ownable: OwnableComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + OwnableEvent: OwnableComponent::Event + } + + #[constructor] + fn constructor(ref self: ContractState, owner: ContractAddress) { + self.ownable.initializer(owner); + } + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn owner(self: @ContractState) -> ContractAddress { + self.ownable.Ownable_owner.read() + } + } +} + +#[starknet::contract] +pub(crate) mod SnakeOwnablePanicMock { + use core::num::traits::Zero; + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn owner(self: @ContractState) -> ContractAddress { + panic!("Some error"); + Zero::zero() + } + + #[external(v0)] + fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) { + panic!("Some error"); + } + + #[external(v0)] + fn renounce_ownership(ref self: ContractState) { + panic!("Some error"); + } + } +} + +#[starknet::contract] +pub(crate) mod CamelOwnablePanicMock { + use core::num::traits::Zero; + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[abi(per_item)] + #[generate_trait] + impl ExternalImpl of ExternalTrait { + #[external(v0)] + fn owner(self: @ContractState) -> ContractAddress { + panic!("Some error"); + Zero::zero() + } + + #[external(v0)] + fn transferOwnership(ref self: ContractState, newOwner: ContractAddress) { + panic!("Some error"); + } + + #[external(v0)] + fn renounceOwnership(ref self: ContractState) { + panic!("Some error"); + } + } +} + +#[starknet::contract] +pub(crate) mod DualCaseTwoStepOwnableMock { + use openzeppelin_access::ownable::OwnableComponent; + use starknet::ContractAddress; + + component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); + + #[abi(embed_v0)] + impl OwnableTwoStepMixinImpl = + OwnableComponent::OwnableTwoStepMixinImpl; + impl InternalImpl = OwnableComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + ownable: OwnableComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + OwnableEvent: OwnableComponent::Event + } + + #[constructor] + fn constructor(ref self: ContractState, owner: ContractAddress) { + self.ownable.initializer(owner); + } +} diff --git a/packages/utils/tests/mocks/pausable_mocks.cairo b/packages/utils/tests/mocks/pausable_mocks.cairo new file mode 100644 index 000000000..c37584a24 --- /dev/null +++ b/packages/utils/tests/mocks/pausable_mocks.cairo @@ -0,0 +1,23 @@ +#[starknet::contract] +pub(crate) mod PausableMock { + use openzeppelin_security::pausable::PausableComponent; + + component!(path: PausableComponent, storage: pausable, event: PausableEvent); + + #[abi(embed_v0)] + impl PausableImpl = PausableComponent::PausableImpl; + impl InternalImpl = PausableComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + pausable: PausableComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + PausableEvent: PausableComponent::Event + } +} diff --git a/packages/utils/tests/mocks/reentrancy_mocks.cairo b/packages/utils/tests/mocks/reentrancy_mocks.cairo new file mode 100644 index 000000000..e7768e70f --- /dev/null +++ b/packages/utils/tests/mocks/reentrancy_mocks.cairo @@ -0,0 +1,125 @@ +use starknet::ContractAddress; + +#[starknet::interface] +trait IReentrancyGuarded { + fn count_external_recursive(ref self: TState, n: felt252); +} + +#[starknet::interface] +pub(crate) trait IReentrancyMock { + fn count(ref self: TState); + fn current_count(self: @TState) -> felt252; + fn callback(ref self: TState); + fn count_local_recursive(ref self: TState, n: felt252); + fn count_external_recursive(ref self: TState, n: felt252); + fn count_and_call(ref self: TState, attacker: ContractAddress); +} + +#[starknet::contract] +pub(crate) mod ReentrancyMock { + use openzeppelin_security::reentrancyguard::ReentrancyGuardComponent; + use starknet::ContractAddress; + use starknet::get_contract_address; + use super::IAttackerDispatcher; + use super::IAttackerDispatcherTrait; + use super::IReentrancyGuardedDispatcher; + use super::IReentrancyGuardedDispatcherTrait; + + component!( + path: ReentrancyGuardComponent, storage: reentrancy_guard, event: ReentrancyGuardEvent + ); + + impl InternalImpl = ReentrancyGuardComponent::InternalImpl; + + #[storage] + struct Storage { + counter: felt252, + #[substorage(v0)] + reentrancy_guard: ReentrancyGuardComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ReentrancyGuardEvent: ReentrancyGuardComponent::Event + } + + #[abi(embed_v0)] + impl IReentrancyMockImpl of super::IReentrancyMock { + fn count(ref self: ContractState) { + self.counter.write(self.counter.read() + 1); + } + + fn current_count(self: @ContractState) -> felt252 { + self.counter.read() + } + + fn callback(ref self: ContractState) { + self.reentrancy_guard.start(); + self.count(); + self.reentrancy_guard.end(); + } + + fn count_local_recursive(ref self: ContractState, n: felt252) { + self.reentrancy_guard.start(); + + if n != 0 { + self.count(); + self.count_local_recursive(n - 1); + } + + self.reentrancy_guard.end(); + } + + fn count_external_recursive(ref self: ContractState, n: felt252) { + self.reentrancy_guard.start(); + + if n != 0 { + self.count(); + let this: ContractAddress = get_contract_address(); + IReentrancyGuardedDispatcher { contract_address: this } + .count_external_recursive(n - 1) + } + + self.reentrancy_guard.end(); + } + + fn count_and_call(ref self: ContractState, attacker: ContractAddress) { + self.reentrancy_guard.start(); + + self.count(); + IAttackerDispatcher { contract_address: attacker }.call_sender(); + + self.reentrancy_guard.end(); + } + } +} + +// +// Attacker +// + +#[starknet::interface] +trait IAttacker { + fn call_sender(self: @TState); +} + +#[starknet::contract] +pub(crate) mod Attacker { + use starknet::ContractAddress; + use starknet::get_caller_address; + use super::IReentrancyMockDispatcher; + use super::IReentrancyMockDispatcherTrait; + + #[storage] + struct Storage {} + + #[abi(embed_v0)] + impl IAttackerImpl of super::IAttacker { + fn call_sender(self: @ContractState) { + let caller: ContractAddress = get_caller_address(); + IReentrancyMockDispatcher { contract_address: caller }.callback(); + } + } +} diff --git a/packages/utils/tests/mocks/src5_mocks.cairo b/packages/utils/tests/mocks/src5_mocks.cairo new file mode 100644 index 000000000..86e8c5167 --- /dev/null +++ b/packages/utils/tests/mocks/src5_mocks.cairo @@ -0,0 +1,22 @@ +#[starknet::contract] +pub(crate) mod SRC5Mock { + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + SRC5Event: SRC5Component::Event + } +} diff --git a/packages/utils/tests/mocks/timelock_mocks.cairo b/packages/utils/tests/mocks/timelock_mocks.cairo new file mode 100644 index 000000000..810d88cac --- /dev/null +++ b/packages/utils/tests/mocks/timelock_mocks.cairo @@ -0,0 +1,151 @@ +#[starknet::contract] +pub(crate) mod TimelockControllerMock { + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_governance::timelock::TimelockControllerComponent; + use openzeppelin_introspection::src5::SRC5Component; + use starknet::ContractAddress; + + component!(path: AccessControlComponent, storage: access_control, event: AccessControlEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + component!(path: TimelockControllerComponent, storage: timelock, event: TimelockEvent); + + // Timelock Mixin + #[abi(embed_v0)] + impl TimelockMixinImpl = + TimelockControllerComponent::TimelockMixinImpl; + impl TimelockInternalImpl = TimelockControllerComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + access_control: AccessControlComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage, + #[substorage(v0)] + timelock: TimelockControllerComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccessControlEvent: AccessControlComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event, + #[flat] + TimelockEvent: TimelockControllerComponent::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + min_delay: u64, + proposers: Span, + executors: Span, + admin: ContractAddress + ) { + self.timelock.initializer(min_delay, proposers, executors, admin); + } +} + +#[starknet::interface] +pub(crate) trait IMockContract { + fn set_number(ref self: TState, new_number: felt252); + fn get_number(self: @TState) -> felt252; + fn failing_function(self: @TState); +} + +#[starknet::contract] +pub(crate) mod MockContract { + use super::IMockContract; + + #[storage] + struct Storage { + number: felt252, + } + + #[abi(embed_v0)] + impl MockContractImpl of IMockContract { + fn set_number(ref self: ContractState, new_number: felt252) { + self.number.write(new_number); + } + + fn get_number(self: @ContractState) -> felt252 { + self.number.read() + } + + fn failing_function(self: @ContractState) { + core::panic_with_felt252('Expected failure'); + } + } +} + +#[starknet::interface] +pub(crate) trait ITimelockAttacker { + fn reenter(ref self: TState); + fn reenter_batch(ref self: TState); +} + +#[starknet::contract] +pub(crate) mod TimelockAttackerMock { + use openzeppelin_governance::timelock::interface::{ + ITimelockDispatcher, ITimelockDispatcherTrait + }; + use starknet::ContractAddress; + use starknet::account::Call; + use super::ITimelockAttacker; + + const NO_PREDECESSOR: felt252 = 0; + const NO_SALT: felt252 = 0; + + #[storage] + struct Storage { + balance: felt252, + count: felt252 + } + + #[abi(embed_v0)] + impl TimelockAttackerImpl of ITimelockAttacker { + fn reenter(ref self: ContractState) { + let new_balance = self.balance.read() + 1; + self.balance.write(new_balance); + + let sender = starknet::get_caller_address(); + let this = starknet::get_contract_address(); + + let current_count = self.count.read(); + if current_count != 2 { + self.count.write(current_count + 1); + + let reentrant_call = Call { + to: this, selector: selector!("reenter"), calldata: array![].span() + }; + + let timelock = ITimelockDispatcher { contract_address: sender }; + timelock.execute(reentrant_call, NO_PREDECESSOR, NO_SALT); + } + } + + fn reenter_batch(ref self: ContractState) { + let new_balance = self.balance.read() + 1; + self.balance.write(new_balance); + + let sender = starknet::get_caller_address(); + let this = starknet::get_contract_address(); + + let current_count = self.count.read(); + if current_count != 2 { + self.count.write(current_count + 1); + + let reentrant_call = Call { + to: this, selector: selector!("reenter_batch"), calldata: array![].span() + }; + + let calls = array![reentrant_call].span(); + + let timelock = ITimelockDispatcher { contract_address: sender }; + timelock.execute_batch(calls, NO_PREDECESSOR, NO_SALT); + } + } + } +} diff --git a/packages/utils/tests/mocks/upgrades_mocks.cairo b/packages/utils/tests/mocks/upgrades_mocks.cairo new file mode 100644 index 000000000..266680d56 --- /dev/null +++ b/packages/utils/tests/mocks/upgrades_mocks.cairo @@ -0,0 +1,111 @@ +// These contracts are mocks used to test the core functionality of the upgrade functions. +// The functions are NOT PROTECTED. +// DO NOT USE IN PRODUCTION. + +use starknet::ClassHash; + +#[starknet::interface] +pub(crate) trait IUpgradesV1 { + fn upgrade(ref self: TState, new_class_hash: ClassHash); + fn set_value(ref self: TState, val: felt252); + fn get_value(self: @TState) -> felt252; + fn remove_selector(self: @TState); +} + +#[starknet::contract] +pub(crate) mod UpgradesV1 { + use openzeppelin_upgrades::UpgradeableComponent; + use starknet::ClassHash; + + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); + + impl InternalImpl = UpgradeableComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + upgradeable: UpgradeableComponent::Storage, + value: felt252 + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + UpgradeableEvent: UpgradeableComponent::Event + } + + #[abi(embed_v0)] + impl UpgradesV1Impl of super::IUpgradesV1 { + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { + self.upgradeable.upgrade(new_class_hash); + } + + fn set_value(ref self: ContractState, val: felt252) { + self.value.write(val); + } + + fn get_value(self: @ContractState) -> felt252 { + self.value.read() + } + + fn remove_selector(self: @ContractState) {} + } +} + +#[starknet::interface] +pub(crate) trait IUpgradesV2 { + fn upgrade(ref self: TState, new_class_hash: ClassHash); + fn set_value(ref self: TState, val: felt252); + fn set_value2(ref self: TState, val: felt252); + fn get_value(self: @TState) -> felt252; + fn get_value2(self: @TState) -> felt252; +} + +#[starknet::contract] +pub(crate) mod UpgradesV2 { + use openzeppelin_upgrades::UpgradeableComponent; + use starknet::ClassHash; + + component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); + + impl InternalImpl = UpgradeableComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + upgradeable: UpgradeableComponent::Storage, + value: felt252, + value2: felt252 + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + UpgradeableEvent: UpgradeableComponent::Event + } + + #[abi(embed_v0)] + impl UpgradesV2Impl of super::IUpgradesV2 { + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { + self.upgradeable.upgrade(new_class_hash); + } + + fn set_value(ref self: ContractState, val: felt252) { + self.value.write(val); + } + + fn set_value2(ref self: ContractState, val: felt252) { + self.value2.write(val); + } + + fn get_value(self: @ContractState) -> felt252 { + self.value.read() + } + + fn get_value2(self: @ContractState) -> felt252 { + self.value2.read() + } + } +} diff --git a/src/tests/cryptography/test_nonces.cairo b/packages/utils/tests/test_nonces.cairo similarity index 90% rename from src/tests/cryptography/test_nonces.cairo rename to packages/utils/tests/test_nonces.cairo index 8c5d8fb7a..e64c1bfd7 100644 --- a/src/tests/cryptography/test_nonces.cairo +++ b/packages/utils/tests/test_nonces.cairo @@ -1,6 +1,5 @@ -use core::num::traits::Zero; -use openzeppelin::tests::mocks::nonces_mocks::NoncesMock; -use openzeppelin::tests::utils::constants::OWNER; +use crate::tests::mocks::nonces_mocks::NoncesMock; +use openzeppelin_utils::test_utils::constants::OWNER; use openzeppelin_utils::cryptography::interface::INonces; use openzeppelin_utils::cryptography::nonces::NoncesComponent::InternalTrait; use openzeppelin_utils::cryptography::nonces::NoncesComponent; diff --git a/src/tests/cryptography/test_snip12.cairo b/packages/utils/tests/test_snip12.cairo similarity index 96% rename from src/tests/cryptography/test_snip12.cairo rename to packages/utils/tests/test_snip12.cairo index cedce5fb4..c9d6a5daf 100644 --- a/src/tests/cryptography/test_snip12.cairo +++ b/packages/utils/tests/test_snip12.cairo @@ -1,6 +1,6 @@ use core::hash::{Hash, HashStateTrait, HashStateExTrait}; use core::poseidon::{PoseidonTrait, poseidon_hash_span}; -use openzeppelin::tests::utils::constants::{OWNER, RECIPIENT}; +use openzeppelin_utils::test_utils::constants::{OWNER, RECIPIENT}; use openzeppelin_utils::cryptography::snip12::{ STARKNET_DOMAIN_TYPE_HASH, StarknetDomain, StructHash, OffchainMessageHashImpl, SNIP12Metadata }; diff --git a/src/lib.cairo b/src/lib.cairo index 78bf8b567..9c8fdf03a 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -1,10 +1,9 @@ -pub mod access; -pub mod account; -pub mod governance; -pub mod introspection; -pub mod presets; -pub mod security; -pub mod tests; -pub mod token; -pub mod upgrades; -pub mod utils; +pub use openzeppelin_access as access; +pub use openzeppelin_account as account; +pub use openzeppelin_governance as governance; +pub use openzeppelin_introspection as introspection; +pub use openzeppelin_presets as presets; +pub use openzeppelin_security as security; +pub use openzeppelin_token as token; +pub use openzeppelin_upgrades as upgrades; +pub use openzeppelin_utils as utils; diff --git a/src/tests.cairo b/src/tests.cairo deleted file mode 100644 index f2263ef47..000000000 --- a/src/tests.cairo +++ /dev/null @@ -1,22 +0,0 @@ -#[cfg(test)] -mod access; -#[cfg(test)] -mod account; -#[cfg(test)] -mod cryptography; -#[cfg(test)] -mod governance; -#[cfg(test)] -mod introspection; -#[cfg(test)] -mod mocks; -#[cfg(test)] -mod presets; -#[cfg(test)] -mod security; -#[cfg(test)] -mod token; -#[cfg(test)] -mod upgrades; - -pub mod utils; diff --git a/src/tests/account.cairo b/src/tests/account.cairo deleted file mode 100644 index 2622d9aa5..000000000 --- a/src/tests/account.cairo +++ /dev/null @@ -1,5 +0,0 @@ -pub(crate) mod ethereum; -pub(crate) mod starknet; - -mod test_secp256k1; -mod test_signature; diff --git a/src/tests/introspection.cairo b/src/tests/introspection.cairo deleted file mode 100644 index 32094b462..000000000 --- a/src/tests/introspection.cairo +++ /dev/null @@ -1 +0,0 @@ -mod test_src5; diff --git a/src/tests/token.cairo b/src/tests/token.cairo deleted file mode 100644 index 04f631ea8..000000000 --- a/src/tests/token.cairo +++ /dev/null @@ -1,3 +0,0 @@ -pub(crate) mod erc1155; -pub(crate) mod erc20; -pub(crate) mod erc721; diff --git a/src/tests/upgrades.cairo b/src/tests/upgrades.cairo deleted file mode 100644 index 7b8b842ad..000000000 --- a/src/tests/upgrades.cairo +++ /dev/null @@ -1,3 +0,0 @@ -pub(crate) mod common; - -mod test_upgradeable; diff --git a/src/tests/upgrades/common.cairo b/src/tests/upgrades/common.cairo deleted file mode 100644 index ce9b03c0f..000000000 --- a/src/tests/upgrades/common.cairo +++ /dev/null @@ -1,16 +0,0 @@ -use openzeppelin::tests::utils::constants::ZERO; -use openzeppelin::tests::utils; -use openzeppelin_upgrades::UpgradeableComponent::Upgraded; -use openzeppelin_upgrades::UpgradeableComponent; -use starknet::{ContractAddress, ClassHash}; - -pub(crate) fn assert_event_upgraded(contract: ContractAddress, class_hash: ClassHash) { - let event = utils::pop_log::(contract).unwrap(); - let expected = UpgradeableComponent::Event::Upgraded(Upgraded { class_hash }); - assert!(event == expected); -} - -pub(crate) fn assert_only_event_upgraded(contract: ContractAddress, class_hash: ClassHash) { - assert_event_upgraded(contract, class_hash); - utils::assert_no_events_left(ZERO()); -} diff --git a/src/tests/utils/constants.cairo b/src/tests/utils/constants.cairo deleted file mode 100644 index cbdfd16d8..000000000 --- a/src/tests/utils/constants.cairo +++ /dev/null @@ -1,116 +0,0 @@ -use openzeppelin_account::interface::EthPublicKey; -use starknet::ClassHash; -use starknet::ContractAddress; -use starknet::SyscallResultTrait; -use starknet::class_hash::class_hash_const; -use starknet::contract_address_const; -use starknet::secp256_trait::Secp256Trait; - -pub(crate) const DECIMALS: u8 = 18_u8; -pub(crate) const SUPPLY: u256 = 2000; -pub(crate) const VALUE: u256 = 300; -pub(crate) const ROLE: felt252 = 'ROLE'; -pub(crate) const OTHER_ROLE: felt252 = 'OTHER_ROLE'; -pub(crate) const TOKEN_ID: u256 = 21; -pub(crate) const TOKEN_ID_2: u256 = 121; -pub(crate) const TOKEN_VALUE: u256 = 42; -pub(crate) const TOKEN_VALUE_2: u256 = 142; -pub(crate) const PUBKEY: felt252 = 'PUBKEY'; -pub(crate) const NEW_PUBKEY: felt252 = - 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7; -pub(crate) const DAPP_NAME: felt252 = 'DAPP_NAME'; -pub(crate) const DAPP_VERSION: felt252 = 'DAPP_VERSION'; -pub(crate) const SALT: felt252 = 'SALT'; -pub(crate) const SUCCESS: felt252 = 123123; -pub(crate) const FAILURE: felt252 = 456456; -pub(crate) const MIN_TRANSACTION_VERSION: felt252 = 1; -// 2**128 -pub(crate) const QUERY_OFFSET: felt252 = 0x100000000000000000000000000000000; -// QUERY_OFFSET + MIN_TRANSACTION_VERSION -pub(crate) const QUERY_VERSION: felt252 = 0x100000000000000000000000000000001; - -pub(crate) fn NAME() -> ByteArray { - "NAME" -} - -pub(crate) fn SYMBOL() -> ByteArray { - "SYMBOL" -} - -pub(crate) fn BASE_URI() -> ByteArray { - "https://api.example.com/v1/" -} - -pub(crate) fn BASE_URI_2() -> ByteArray { - "https://api.example.com/v2/" -} - -pub(crate) fn ETH_PUBKEY() -> EthPublicKey { - Secp256Trait::secp256_ec_get_point_from_x_syscall(3, false).unwrap_syscall().unwrap() -} - -pub(crate) fn NEW_ETH_PUBKEY() -> EthPublicKey { - Secp256Trait::secp256_ec_get_point_from_x_syscall(4, false).unwrap_syscall().unwrap() -} - -pub(crate) fn ADMIN() -> ContractAddress { - contract_address_const::<'ADMIN'>() -} - -pub(crate) fn AUTHORIZED() -> ContractAddress { - contract_address_const::<'AUTHORIZED'>() -} - -pub(crate) fn ZERO() -> ContractAddress { - contract_address_const::<0>() -} - -pub(crate) fn CLASS_HASH_ZERO() -> ClassHash { - class_hash_const::<0>() -} - -pub(crate) fn CALLER() -> ContractAddress { - contract_address_const::<'CALLER'>() -} - -pub(crate) fn OWNER() -> ContractAddress { - contract_address_const::<'OWNER'>() -} - -pub(crate) fn NEW_OWNER() -> ContractAddress { - contract_address_const::<'NEW_OWNER'>() -} - -pub(crate) fn OTHER() -> ContractAddress { - contract_address_const::<'OTHER'>() -} - -pub(crate) fn OTHER_ADMIN() -> ContractAddress { - contract_address_const::<'OTHER_ADMIN'>() -} - -pub(crate) fn SPENDER() -> ContractAddress { - contract_address_const::<'SPENDER'>() -} - -pub(crate) fn RECIPIENT() -> ContractAddress { - contract_address_const::<'RECIPIENT'>() -} - -pub(crate) fn OPERATOR() -> ContractAddress { - contract_address_const::<'OPERATOR'>() -} - -pub(crate) fn DATA(success: bool) -> Span { - let mut data = array![]; - if success { - data.append(SUCCESS); - } else { - data.append(FAILURE); - } - data.span() -} - -pub(crate) fn EMPTY_DATA() -> Span { - array![].span() -} From 4ac190375de4fde76d683291adf888415dd4e2b5 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 26 Jul 2024 20:22:50 +0200 Subject: [PATCH 24/45] feat: update workflow --- .github/workflows/test.yml | 4 ++-- .../account/src/tests/starknet/test_dual_account.cairo | 2 +- packages/utils/src/lib.cairo | 8 ++++---- packages/utils/src/test_utils/constants.cairo | 3 +-- packages/utils/tests/test_nonces.cairo | 2 +- packages/utils/tests/test_snip12.cairo | 2 +- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 023569891..28607d2bb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,6 +28,6 @@ jobs: *.md !PULL_REQUEST_TEMPLATE.md - name: Cairo lint - run: scarb fmt --check + run: scarb fmt --check --workspace - name: Cairo test - run: scarb test + run: scarb test --workspace diff --git a/packages/account/src/tests/starknet/test_dual_account.cairo b/packages/account/src/tests/starknet/test_dual_account.cairo index 96c7a2e70..50a89d3f5 100644 --- a/packages/account/src/tests/starknet/test_dual_account.cairo +++ b/packages/account/src/tests/starknet/test_dual_account.cairo @@ -1,10 +1,10 @@ use openzeppelin_account::dual_account::{DualCaseAccountABI, DualCaseAccount}; use openzeppelin_account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; -use openzeppelin_account::tests::starknet::common::SIGNED_TX_DATA; use openzeppelin_account::tests::mocks::account_mocks::{ CamelAccountPanicMock, CamelAccountMock, SnakeAccountMock, SnakeAccountPanicMock }; use openzeppelin_account::tests::mocks::non_implementing_mock::NonImplementingMock; +use openzeppelin_account::tests::starknet::common::SIGNED_TX_DATA; use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin_utils::test_utils::constants::{PUBKEY, NEW_PUBKEY}; use openzeppelin_utils::test_utils; diff --git a/packages/utils/src/lib.cairo b/packages/utils/src/lib.cairo index be157a06d..7754bbf8a 100644 --- a/packages/utils/src/lib.cairo +++ b/packages/utils/src/lib.cairo @@ -1,7 +1,3 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils.cairo) - -pub mod test_utils; pub mod cryptography; pub mod deployments; pub mod interfaces; @@ -9,6 +5,10 @@ pub mod math; pub mod selectors; pub mod serde; pub mod structs; +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils.cairo) + +pub mod test_utils; pub mod unwrap_and_cast; pub use cryptography::nonces; diff --git a/packages/utils/src/test_utils/constants.cairo b/packages/utils/src/test_utils/constants.cairo index c869eae4a..8e2d02552 100644 --- a/packages/utils/src/test_utils/constants.cairo +++ b/packages/utils/src/test_utils/constants.cairo @@ -17,8 +17,7 @@ pub const TOKEN_ID_2: u256 = 121; pub const TOKEN_VALUE: u256 = 42; pub const TOKEN_VALUE_2: u256 = 142; pub const PUBKEY: felt252 = 'PUBKEY'; -pub const NEW_PUBKEY: felt252 = - 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7; +pub const NEW_PUBKEY: felt252 = 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7; pub const DAPP_NAME: felt252 = 'DAPP_NAME'; pub const DAPP_VERSION: felt252 = 'DAPP_VERSION'; pub const SALT: felt252 = 'SALT'; diff --git a/packages/utils/tests/test_nonces.cairo b/packages/utils/tests/test_nonces.cairo index e64c1bfd7..15d7f9d73 100644 --- a/packages/utils/tests/test_nonces.cairo +++ b/packages/utils/tests/test_nonces.cairo @@ -1,8 +1,8 @@ use crate::tests::mocks::nonces_mocks::NoncesMock; -use openzeppelin_utils::test_utils::constants::OWNER; use openzeppelin_utils::cryptography::interface::INonces; use openzeppelin_utils::cryptography::nonces::NoncesComponent::InternalTrait; use openzeppelin_utils::cryptography::nonces::NoncesComponent; +use openzeppelin_utils::test_utils::constants::OWNER; type ComponentState = NoncesComponent::ComponentState; diff --git a/packages/utils/tests/test_snip12.cairo b/packages/utils/tests/test_snip12.cairo index c9d6a5daf..fa4adf480 100644 --- a/packages/utils/tests/test_snip12.cairo +++ b/packages/utils/tests/test_snip12.cairo @@ -1,9 +1,9 @@ use core::hash::{Hash, HashStateTrait, HashStateExTrait}; use core::poseidon::{PoseidonTrait, poseidon_hash_span}; -use openzeppelin_utils::test_utils::constants::{OWNER, RECIPIENT}; use openzeppelin_utils::cryptography::snip12::{ STARKNET_DOMAIN_TYPE_HASH, StarknetDomain, StructHash, OffchainMessageHashImpl, SNIP12Metadata }; +use openzeppelin_utils::test_utils::constants::{OWNER, RECIPIENT}; use starknet::ContractAddress; const MESSAGE_TYPE_HASH: felt252 = From 094ab98ccff0b551ca3ecc1b7a934a6fef72bf36 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 26 Jul 2024 20:29:46 +0200 Subject: [PATCH 25/45] feat: test utils --- packages/utils/src/lib.cairo | 9 +- packages/utils/tests.cairo | 2 - packages/utils/tests/mocks.cairo | 18 - .../tests/mocks/accesscontrol_mocks.cairo | 224 ----------- .../utils/tests/mocks/account_mocks.cairo | 223 ----------- .../utils/tests/mocks/erc1155_mocks.cairo | 306 --------------- .../tests/mocks/erc1155_receiver_mocks.cairo | 197 ---------- packages/utils/tests/mocks/erc20_mocks.cairo | 253 ------------- .../utils/tests/mocks/erc20_votes_mocks.cairo | 101 ----- packages/utils/tests/mocks/erc721_mocks.cairo | 347 ------------------ .../tests/mocks/erc721_receiver_mocks.cairo | 237 ------------ .../utils/tests/mocks/eth_account_mocks.cairo | 228 ------------ .../tests/mocks/initializable_mocks.cairo | 23 -- .../tests/mocks/non_implementing_mock.cairo | 10 - packages/utils/tests/mocks/nonces_mocks.cairo | 23 -- .../utils/tests/mocks/ownable_mocks.cairo | 188 ---------- .../utils/tests/mocks/pausable_mocks.cairo | 23 -- .../utils/tests/mocks/reentrancy_mocks.cairo | 125 ------- packages/utils/tests/mocks/src5_mocks.cairo | 22 -- .../utils/tests/mocks/timelock_mocks.cairo | 151 -------- .../utils/tests/mocks/upgrades_mocks.cairo | 111 ------ packages/utils/tests/test_nonces.cairo | 45 --- packages/utils/tests/test_snip12.cairo | 70 ---- 23 files changed, 7 insertions(+), 2929 deletions(-) delete mode 100644 packages/utils/tests.cairo delete mode 100644 packages/utils/tests/mocks.cairo delete mode 100644 packages/utils/tests/mocks/accesscontrol_mocks.cairo delete mode 100644 packages/utils/tests/mocks/account_mocks.cairo delete mode 100644 packages/utils/tests/mocks/erc1155_mocks.cairo delete mode 100644 packages/utils/tests/mocks/erc1155_receiver_mocks.cairo delete mode 100644 packages/utils/tests/mocks/erc20_mocks.cairo delete mode 100644 packages/utils/tests/mocks/erc20_votes_mocks.cairo delete mode 100644 packages/utils/tests/mocks/erc721_mocks.cairo delete mode 100644 packages/utils/tests/mocks/erc721_receiver_mocks.cairo delete mode 100644 packages/utils/tests/mocks/eth_account_mocks.cairo delete mode 100644 packages/utils/tests/mocks/initializable_mocks.cairo delete mode 100644 packages/utils/tests/mocks/non_implementing_mock.cairo delete mode 100644 packages/utils/tests/mocks/nonces_mocks.cairo delete mode 100644 packages/utils/tests/mocks/ownable_mocks.cairo delete mode 100644 packages/utils/tests/mocks/pausable_mocks.cairo delete mode 100644 packages/utils/tests/mocks/reentrancy_mocks.cairo delete mode 100644 packages/utils/tests/mocks/src5_mocks.cairo delete mode 100644 packages/utils/tests/mocks/timelock_mocks.cairo delete mode 100644 packages/utils/tests/mocks/upgrades_mocks.cairo delete mode 100644 packages/utils/tests/test_nonces.cairo delete mode 100644 packages/utils/tests/test_snip12.cairo diff --git a/packages/utils/src/lib.cairo b/packages/utils/src/lib.cairo index 7754bbf8a..08cb871b9 100644 --- a/packages/utils/src/lib.cairo +++ b/packages/utils/src/lib.cairo @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils.cairo) + pub mod cryptography; pub mod deployments; pub mod interfaces; @@ -5,10 +8,12 @@ pub mod math; pub mod selectors; pub mod serde; pub mod structs; -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils.cairo) pub mod test_utils; + +#[cfg(test)] +mod tests; + pub mod unwrap_and_cast; pub use cryptography::nonces; diff --git a/packages/utils/tests.cairo b/packages/utils/tests.cairo deleted file mode 100644 index fedcc380c..000000000 --- a/packages/utils/tests.cairo +++ /dev/null @@ -1,2 +0,0 @@ -mod test_nonces; -mod test_snip12; diff --git a/packages/utils/tests/mocks.cairo b/packages/utils/tests/mocks.cairo deleted file mode 100644 index daaf65baf..000000000 --- a/packages/utils/tests/mocks.cairo +++ /dev/null @@ -1,18 +0,0 @@ -pub(crate) mod accesscontrol_mocks; -pub(crate) mod account_mocks; -pub(crate) mod erc1155_mocks; -pub(crate) mod erc1155_receiver_mocks; -pub(crate) mod erc20_mocks; -pub(crate) mod erc20_votes_mocks; -pub(crate) mod erc721_mocks; -pub(crate) mod erc721_receiver_mocks; -pub(crate) mod eth_account_mocks; -pub(crate) mod initializable_mocks; -pub(crate) mod non_implementing_mock; -pub(crate) mod nonces_mocks; -pub(crate) mod ownable_mocks; -pub(crate) mod pausable_mocks; -pub(crate) mod reentrancy_mocks; -pub(crate) mod src5_mocks; -pub(crate) mod timelock_mocks; -pub(crate) mod upgrades_mocks; diff --git a/packages/utils/tests/mocks/accesscontrol_mocks.cairo b/packages/utils/tests/mocks/accesscontrol_mocks.cairo deleted file mode 100644 index f9ddb0b38..000000000 --- a/packages/utils/tests/mocks/accesscontrol_mocks.cairo +++ /dev/null @@ -1,224 +0,0 @@ -#[starknet::contract] -pub(crate) mod DualCaseAccessControlMock { - use openzeppelin_access::accesscontrol::AccessControlComponent; - use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; - use openzeppelin_introspection::src5::SRC5Component; - use starknet::ContractAddress; - - component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // AccessControlMixin - #[abi(embed_v0)] - impl AccessControlMixinImpl = - AccessControlComponent::AccessControlMixinImpl; - impl AccessControlInternalImpl = AccessControlComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - accesscontrol: AccessControlComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - AccessControlEvent: AccessControlComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, admin: ContractAddress) { - self.accesscontrol.initializer(); - self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin); - } -} - -#[starknet::contract] -pub(crate) mod SnakeAccessControlMock { - use openzeppelin_access::accesscontrol::AccessControlComponent; - use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; - use openzeppelin_introspection::src5::SRC5Component; - use starknet::ContractAddress; - - component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // AccessControl - #[abi(embed_v0)] - impl AccessControlImpl = - AccessControlComponent::AccessControlImpl; - impl AccessControlInternalImpl = AccessControlComponent::InternalImpl; - - // SCR5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - accesscontrol: AccessControlComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage, - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - AccessControlEvent: AccessControlComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, admin: ContractAddress) { - self.accesscontrol.initializer(); - self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin); - } -} - -#[starknet::contract] -pub(crate) mod CamelAccessControlMock { - use openzeppelin_access::accesscontrol::AccessControlComponent; - use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; - use openzeppelin_introspection::src5::SRC5Component; - use starknet::ContractAddress; - - component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // AccessControl - #[abi(embed_v0)] - impl AccessControlCamelImpl = - AccessControlComponent::AccessControlCamelImpl; - impl AccessControlInternalImpl = AccessControlComponent::InternalImpl; - - // SCR5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - - #[storage] - struct Storage { - #[substorage(v0)] - accesscontrol: AccessControlComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - AccessControlEvent: AccessControlComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, admin: ContractAddress) { - self.accesscontrol.initializer(); - self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, admin); - } -} - -// Although these modules are designed to panic, functions -// still need a valid return value. We chose: -// -// 3 for felt252 -// false for bool - -#[starknet::contract] -pub(crate) mod SnakeAccessControlPanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn has_role(self: @ContractState, role: felt252, account: ContractAddress) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn get_role_admin(self: @ContractState, role: felt252) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn grant_role(ref self: ContractState, role: felt252, account: ContractAddress) { - panic!("Some error"); - } - - #[external(v0)] - fn revoke_role(ref self: ContractState, role: felt252, account: ContractAddress) { - panic!("Some error"); - } - - #[external(v0)] - fn renounce_role(ref self: ContractState, role: felt252, account: ContractAddress) { - panic!("Some error"); - } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelAccessControlPanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn hasRole(self: @ContractState, role: felt252, account: ContractAddress) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn getRoleAdmin(self: @ContractState, role: felt252) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn grantRole(ref self: ContractState, role: felt252, account: ContractAddress) { - panic!("Some error"); - } - - #[external(v0)] - fn revokeRole(ref self: ContractState, role: felt252, account: ContractAddress) { - panic!("Some error"); - } - - #[external(v0)] - fn renounceRole(ref self: ContractState, role: felt252, account: ContractAddress) { - panic!("Some error"); - } - - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - panic!("Some error"); - false - } - } -} diff --git a/packages/utils/tests/mocks/account_mocks.cairo b/packages/utils/tests/mocks/account_mocks.cairo deleted file mode 100644 index c2f7d9f57..000000000 --- a/packages/utils/tests/mocks/account_mocks.cairo +++ /dev/null @@ -1,223 +0,0 @@ -#[starknet::contract(account)] -pub(crate) mod DualCaseAccountMock { - use openzeppelin_account::AccountComponent; - use openzeppelin_introspection::src5::SRC5Component; - - component!(path: AccountComponent, storage: account, event: AccountEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // Account - #[abi(embed_v0)] - impl SRC6Impl = AccountComponent::SRC6Impl; - #[abi(embed_v0)] - impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl; - #[abi(embed_v0)] - impl DeclarerImpl = AccountComponent::DeclarerImpl; - #[abi(embed_v0)] - impl DeployableImpl = AccountComponent::DeployableImpl; - impl AccountInternalImpl = AccountComponent::InternalImpl; - - // SCR5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - account: AccountComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - AccountEvent: AccountComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, public_key: felt252) { - self.account.initializer(public_key); - } -} - -#[starknet::contract(account)] -pub(crate) mod SnakeAccountMock { - use openzeppelin_account::AccountComponent; - use openzeppelin_introspection::src5::SRC5Component; - - component!(path: AccountComponent, storage: account, event: AccountEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // Account - #[abi(embed_v0)] - impl SRC6Impl = AccountComponent::SRC6Impl; - #[abi(embed_v0)] - impl PublicKeyImpl = AccountComponent::PublicKeyImpl; - impl AccountInternalImpl = AccountComponent::InternalImpl; - - // SCR5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - account: AccountComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - AccountEvent: AccountComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, public_key: felt252) { - self.account.initializer(public_key); - } -} - -#[starknet::contract(account)] -pub(crate) mod CamelAccountMock { - use openzeppelin_account::AccountComponent; - use openzeppelin_introspection::src5::SRC5Component; - use starknet::account::Call; - - component!(path: AccountComponent, storage: account, event: AccountEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // Account - #[abi(embed_v0)] - impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl; - #[abi(embed_v0)] - impl PublicKeyCamelImpl = AccountComponent::PublicKeyCamelImpl; - impl SRC6Impl = AccountComponent::SRC6Impl; - impl AccountInternalImpl = AccountComponent::InternalImpl; - - // SCR5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - account: AccountComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - AccountEvent: AccountComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, publicKey: felt252) { - self.account.initializer(publicKey); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn __execute__(self: @ContractState, mut calls: Array) -> Array> { - self.account.__execute__(calls) - } - - #[external(v0)] - fn __validate__(self: @ContractState, mut calls: Array) -> felt252 { - self.account.__validate__(calls) - } - } -} - -// Although these modules are designed to panic, functions -// still need a valid return value. We chose: -// -// 3 for felt252 -// false for bool - -#[starknet::contract] -pub(crate) mod SnakeAccountPanicMock { - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn set_public_key( - ref self: ContractState, new_public_key: felt252, signature: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn get_public_key(self: @ContractState) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn is_valid_signature( - self: @ContractState, hash: felt252, signature: Array - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelAccountPanicMock { - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn setPublicKey(ref self: ContractState, newPublicKey: felt252, signature: Span) { - panic!("Some error"); - } - - #[external(v0)] - fn getPublicKey(self: @ContractState) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn isValidSignature( - self: @ContractState, hash: felt252, signature: Array - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - panic!("Some error"); - false - } - } -} diff --git a/packages/utils/tests/mocks/erc1155_mocks.cairo b/packages/utils/tests/mocks/erc1155_mocks.cairo deleted file mode 100644 index 9d8d79181..000000000 --- a/packages/utils/tests/mocks/erc1155_mocks.cairo +++ /dev/null @@ -1,306 +0,0 @@ -#[starknet::contract] -pub(crate) mod DualCaseERC1155Mock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC1155 - #[abi(embed_v0)] - impl ERC1155Impl = ERC1155Component::ERC1155Impl; - #[abi(embed_v0)] - impl ERC1155MetadataURIImpl = - ERC1155Component::ERC1155MetadataURIImpl; - #[abi(embed_v0)] - impl ERC721Camel = ERC1155Component::ERC1155CamelImpl; - impl ERC1155InternalImpl = ERC1155Component::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc1155: ERC1155Component::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC1155Event: ERC1155Component::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - base_uri: ByteArray, - recipient: ContractAddress, - token_id: u256, - value: u256 - ) { - self.erc1155.initializer(base_uri); - self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); - } -} - -#[starknet::contract] -pub(crate) mod SnakeERC1155Mock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC1155 - #[abi(embed_v0)] - impl ERC1155Impl = ERC1155Component::ERC1155Impl; - #[abi(embed_v0)] - impl ERC1155MetadataURIImpl = - ERC1155Component::ERC1155MetadataURIImpl; - impl ERC1155InternalImpl = ERC1155Component::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc1155: ERC1155Component::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC1155Event: ERC1155Component::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - base_uri: ByteArray, - recipient: ContractAddress, - token_id: u256, - value: u256 - ) { - self.erc1155.initializer(base_uri); - self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); - } -} - -#[starknet::contract] -pub(crate) mod CamelERC1155Mock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC1155 - #[abi(embed_v0)] - impl ERC1155Camel = ERC1155Component::ERC1155CamelImpl; - #[abi(embed_v0)] - impl ERC1155MetadataURIImpl = - ERC1155Component::ERC1155MetadataURIImpl; - impl ERC1155InternalImpl = ERC1155Component::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc1155: ERC1155Component::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC1155Event: ERC1155Component::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - base_uri: ByteArray, - recipient: ContractAddress, - token_id: u256, - value: u256 - ) { - self.erc1155.initializer(base_uri); - self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); - } -} - -#[starknet::contract] -pub(crate) mod SnakeERC1155PanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn uri(self: @ContractState, token_id: u256) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn balance_of(self: @ContractState, account: ContractAddress, token_id: u256) -> u256 { - panic!("Some error"); - u256 { low: 3, high: 3 } - } - - #[external(v0)] - fn balance_of_batch( - self: @ContractState, accounts: Span, token_ids: Span - ) -> Span { - panic!("Some error"); - array![u256 { low: 3, high: 3 }].span() - } - - #[external(v0)] - fn safe_transfer_from( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - value: u256, - data: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn safe_batch_transfer_from( - ref self: ContractState, - from: starknet::ContractAddress, - to: starknet::ContractAddress, - token_ids: Span, - values: Span, - data: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn is_approved_for_all( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn set_approval_for_all( - ref self: ContractState, operator: ContractAddress, approved: bool - ) { - panic!("Some error"); - } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelERC1155PanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn uri(self: @ContractState, tokenId: u256) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn balanceOf(self: @ContractState, account: ContractAddress, tokenId: u256) -> u256 { - panic!("Some error"); - u256 { low: 3, high: 3 } - } - - #[external(v0)] - fn balanceOfBatch( - self: @ContractState, accounts: Span, token_ids: Span - ) -> Span { - panic!("Some error"); - array![u256 { low: 3, high: 3 }].span() - } - - #[external(v0)] - fn safeTransferFrom( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - tokenId: u256, - value: u256, - data: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn safeBatchTransferFrom( - ref self: ContractState, - from: starknet::ContractAddress, - to: starknet::ContractAddress, - token_ids: Span, - values: Span, - data: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn isApprovedForAll( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) { - panic!("Some error"); - } - - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - panic!("Some error"); - false - } - } -} diff --git a/packages/utils/tests/mocks/erc1155_receiver_mocks.cairo b/packages/utils/tests/mocks/erc1155_receiver_mocks.cairo deleted file mode 100644 index 34ec82649..000000000 --- a/packages/utils/tests/mocks/erc1155_receiver_mocks.cairo +++ /dev/null @@ -1,197 +0,0 @@ -use openzeppelin_utils::test_utils::constants::SUCCESS; - -#[starknet::contract] -pub(crate) mod DualCaseERC1155ReceiverMock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::ERC1155ReceiverComponent; - use starknet::ContractAddress; - - component!(path: SRC5Component, storage: src5, event: SRC5Event); - component!( - path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent - ); - - // ERC1155Receiver Mixin - #[abi(embed_v0)] - impl ERC1155ReceiverMixinImpl = - ERC1155ReceiverComponent::ERC1155ReceiverMixinImpl; - impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc1155_receiver: ERC1155ReceiverComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState) { - self.erc1155_receiver.initializer(); - } -} - -#[starknet::contract] -pub(crate) mod SnakeERC1155ReceiverMock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::ERC1155ReceiverComponent; - use starknet::ContractAddress; - - component!(path: SRC5Component, storage: src5, event: SRC5Event); - component!( - path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent - ); - - // ERC1155Receiver - #[abi(embed_v0)] - impl ERC1155ReceiverImpl = - ERC1155ReceiverComponent::ERC1155ReceiverImpl; - impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc1155_receiver: ERC1155ReceiverComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState) { - self.erc1155_receiver.initializer(); - } -} - -#[starknet::contract] -pub(crate) mod CamelERC1155ReceiverMock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::ERC1155ReceiverComponent; - use starknet::ContractAddress; - - component!(path: SRC5Component, storage: src5, event: SRC5Event); - component!( - path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent - ); - - // ERC1155Receiver - #[abi(embed_v0)] - impl ERC1155ReceiverCamelImpl = - ERC1155ReceiverComponent::ERC1155ReceiverCamelImpl; - impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc1155_receiver: ERC1155ReceiverComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState) { - self.erc1155_receiver.initializer(); - } -} - -#[starknet::contract] -pub(crate) mod SnakeERC1155ReceiverPanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[external(v0)] - fn on_erc1155_received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - token_id: u256, - value: u256, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn on_erc1155_batch_received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenIds: Span, - values: Span, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } -} - -#[starknet::contract] -pub(crate) mod CamelERC1155ReceiverPanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[external(v0)] - fn onERC1155Received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenId: u256, - value: u256, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn onERC1155BatchReceived( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenIds: Span, - values: Span, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } -} diff --git a/packages/utils/tests/mocks/erc20_mocks.cairo b/packages/utils/tests/mocks/erc20_mocks.cairo deleted file mode 100644 index 80a66d34f..000000000 --- a/packages/utils/tests/mocks/erc20_mocks.cairo +++ /dev/null @@ -1,253 +0,0 @@ -#[starknet::contract] -pub(crate) mod DualCaseERC20Mock { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - - #[abi(embed_v0)] - impl ERC20Impl = ERC20Component::ERC20Impl; - #[abi(embed_v0)] - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; - #[abi(embed_v0)] - impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; - impl InternalImpl = ERC20Component::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - initial_supply: u256, - recipient: ContractAddress - ) { - self.erc20.initializer(name, symbol); - self.erc20.mint(recipient, initial_supply); - } -} - -#[starknet::contract] -pub(crate) mod SnakeERC20Mock { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - - #[abi(embed_v0)] - impl ERC20Impl = ERC20Component::ERC20Impl; - #[abi(embed_v0)] - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; - impl InternalImpl = ERC20Component::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - initial_supply: u256, - recipient: ContractAddress - ) { - self.erc20.initializer(name, symbol); - self.erc20.mint(recipient, initial_supply); - } -} - -#[starknet::contract] -pub(crate) mod CamelERC20Mock { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - - #[abi(embed_v0)] - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; - #[abi(embed_v0)] - impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; - - // `ERC20Impl` is not embedded because it would defeat the purpose of the - // mock. The `ERC20Impl` case-agnostic methods are manually exposed. - impl ERC20Impl = ERC20Component::ERC20Impl; - impl InternalImpl = ERC20Component::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - initial_supply: u256, - recipient: ContractAddress - ) { - self.erc20.initializer(name, symbol); - self.erc20.mint(recipient, initial_supply); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress - ) -> u256 { - self.erc20.allowance(owner, spender) - } - - #[external(v0)] - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { - self.erc20.transfer(recipient, amount) - } - - #[external(v0)] - fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool { - self.erc20.approve(spender, amount) - } - } -} - -/// Although these modules are designed to panic, functions -/// still need a valid return value. We chose: -/// -/// 3 for felt252, u8, and u256 -/// zero for ContractAddress -/// false for bool -#[starknet::contract] -pub(crate) mod SnakeERC20Panic { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn name(self: @ContractState) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn symbol(self: @ContractState) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn decimals(self: @ContractState) -> u8 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress - ) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn total_supply(self: @ContractState) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn transfer_from( - ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256 - ) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelERC20Panic { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn totalSupply(self: @ContractState) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn transferFrom( - ref self: ContractState, - sender: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) { - panic!("Some error"); - } - } -} diff --git a/packages/utils/tests/mocks/erc20_votes_mocks.cairo b/packages/utils/tests/mocks/erc20_votes_mocks.cairo deleted file mode 100644 index a2a79ca18..000000000 --- a/packages/utils/tests/mocks/erc20_votes_mocks.cairo +++ /dev/null @@ -1,101 +0,0 @@ -#[starknet::contract] -pub(crate) mod DualCaseERC20VotesMock { - use openzeppelin_token::erc20::ERC20Component; - use openzeppelin_token::erc20::extensions::ERC20VotesComponent::InternalTrait as ERC20VotesInternalTrait; - use openzeppelin_token::erc20::extensions::ERC20VotesComponent; - use openzeppelin_utils::cryptography::nonces::NoncesComponent; - use openzeppelin_utils::cryptography::snip12::SNIP12Metadata; - use starknet::ContractAddress; - - component!(path: ERC20VotesComponent, storage: erc20_votes, event: ERC20VotesEvent); - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - component!(path: NoncesComponent, storage: nonces, event: NoncesEvent); - - // ERC20Votes - #[abi(embed_v0)] - impl ERC20VotesComponentImpl = - ERC20VotesComponent::ERC20VotesImpl; - - // ERC20Mixin - #[abi(embed_v0)] - impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl; - impl InternalImpl = ERC20Component::InternalImpl; - - // Nonces - #[abi(embed_v0)] - impl NoncesImpl = NoncesComponent::NoncesImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20_votes: ERC20VotesComponent::Storage, - #[substorage(v0)] - erc20: ERC20Component::Storage, - #[substorage(v0)] - nonces: NoncesComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20VotesEvent: ERC20VotesComponent::Event, - #[flat] - ERC20Event: ERC20Component::Event, - #[flat] - NoncesEvent: NoncesComponent::Event - } - - /// Required for hash computation. - pub(crate) impl SNIP12MetadataImpl of SNIP12Metadata { - fn name() -> felt252 { - 'DAPP_NAME' - } - fn version() -> felt252 { - 'DAPP_VERSION' - } - } - - // - // Hooks - // - - impl ERC20VotesHooksImpl< - TContractState, - impl ERC20Votes: ERC20VotesComponent::HasComponent, - impl HasComponent: ERC20Component::HasComponent, - +NoncesComponent::HasComponent, - +Drop - > of ERC20Component::ERC20HooksTrait { - fn before_update( - ref self: ERC20Component::ComponentState, - from: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) {} - - fn after_update( - ref self: ERC20Component::ComponentState, - from: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) { - let mut erc20_votes_component = get_dep_component_mut!(ref self, ERC20Votes); - erc20_votes_component.transfer_voting_units(from, recipient, amount); - } - } - - /// Sets the token `name` and `symbol`. - /// Mints `fixed_supply` tokens to `recipient`. - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - fixed_supply: u256, - recipient: ContractAddress - ) { - self.erc20.initializer(name, symbol); - self.erc20.mint(recipient, fixed_supply); - } -} diff --git a/packages/utils/tests/mocks/erc721_mocks.cairo b/packages/utils/tests/mocks/erc721_mocks.cairo deleted file mode 100644 index 05aaf81f2..000000000 --- a/packages/utils/tests/mocks/erc721_mocks.cairo +++ /dev/null @@ -1,347 +0,0 @@ -#[starknet::contract] -pub(crate) mod DualCaseERC721Mock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC721Component, storage: erc721, event: ERC721Event); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC721 - #[abi(embed_v0)] - impl ERC721Impl = ERC721Component::ERC721Impl; - #[abi(embed_v0)] - impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl; - #[abi(embed_v0)] - impl ERC721CamelOnly = ERC721Component::ERC721CamelOnlyImpl; - #[abi(embed_v0)] - impl ERC721MetadataCamelOnly = - ERC721Component::ERC721MetadataCamelOnlyImpl; - impl ERC721InternalImpl = ERC721Component::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc721: ERC721Component::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC721Event: ERC721Component::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - base_uri: ByteArray, - recipient: ContractAddress, - token_id: u256 - ) { - self.erc721.initializer(name, symbol, base_uri); - self.erc721.mint(recipient, token_id); - } -} - -#[starknet::contract] -pub(crate) mod SnakeERC721Mock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC721Component, storage: erc721, event: ERC721Event); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC721 - #[abi(embed_v0)] - impl ERC721Impl = ERC721Component::ERC721Impl; - #[abi(embed_v0)] - impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl; - impl ERC721InternalImpl = ERC721Component::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc721: ERC721Component::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC721Event: ERC721Component::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - base_uri: ByteArray, - recipient: ContractAddress, - token_id: u256 - ) { - self.erc721.initializer(name, symbol, base_uri); - self.erc721.mint(recipient, token_id); - } -} - -#[starknet::contract] -pub(crate) mod CamelERC721Mock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::ERC721Component::{ERC721Impl, ERC721MetadataImpl}; - use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC721Component, storage: erc721, event: ERC721Event); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC721 - #[abi(embed_v0)] - impl ERC721CamelOnly = ERC721Component::ERC721CamelOnlyImpl; - #[abi(embed_v0)] - impl ERC721MetadataCamelOnly = - ERC721Component::ERC721MetadataCamelOnlyImpl; - impl ERC721InternalImpl = ERC721Component::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc721: ERC721Component::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC721Event: ERC721Component::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - base_uri: ByteArray, - recipient: ContractAddress, - token_id: u256 - ) { - self.erc721.initializer(name, symbol, base_uri); - self.erc721.mint(recipient, token_id); - } - - /// The following external methods are included because they are case-agnostic - /// and this contract should not embed the snake_case impl. - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn approve(ref self: ContractState, to: ContractAddress, tokenId: u256) { - self.erc721.approve(to, tokenId); - } - - #[external(v0)] - fn name(self: @ContractState) -> ByteArray { - self.erc721.name() - } - - #[external(v0)] - fn symbol(self: @ContractState) -> ByteArray { - self.erc721.symbol() - } - } -} - -/// Although these modules are designed to panic, functions -/// still need a valid return value. We chose: -/// -/// 3 for felt252 -/// zero for ContractAddress -/// u256 { 3, 3 } for u256 -#[starknet::contract] -pub(crate) mod SnakeERC721PanicMock { - use core::num::traits::Zero; - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn name(self: @ContractState) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn symbol(self: @ContractState) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) { - panic!("Some error"); - } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn token_uri(self: @ContractState, token_id: u256) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { - panic!("Some error"); - u256 { low: 3, high: 3 } - } - - #[external(v0)] - fn owner_of(self: @ContractState, token_id: u256) -> ContractAddress { - panic!("Some error"); - Zero::zero() - } - - #[external(v0)] - fn get_approved(self: @ContractState, token_id: u256) -> ContractAddress { - panic!("Some error"); - Zero::zero() - } - - #[external(v0)] - fn is_approved_for_all( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn set_approval_for_all( - ref self: ContractState, operator: ContractAddress, approved: bool - ) { - panic!("Some error"); - } - - #[external(v0)] - fn transfer_from( - ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256 - ) { - panic!("Some error"); - } - - #[external(v0)] - fn safe_transfer_from( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - data: Span - ) { - panic!("Some error"); - } - } -} - -#[starknet::contract] -pub(crate) mod CamelERC721PanicMock { - use core::num::traits::Zero; - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn tokenURI(self: @ContractState, tokenId: u256) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { - panic!("Some error"); - u256 { low: 3, high: 3 } - } - - #[external(v0)] - fn ownerOf(self: @ContractState, tokenId: u256) -> ContractAddress { - panic!("Some error"); - Zero::zero() - } - - #[external(v0)] - fn getApproved(self: @ContractState, tokenId: u256) -> ContractAddress { - panic!("Some error"); - Zero::zero() - } - - #[external(v0)] - fn isApprovedForAll( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) { - panic!("Some error"); - } - - #[external(v0)] - fn transferFrom( - ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256 - ) { - panic!("Some error"); - } - - #[external(v0)] - fn safeTransferFrom( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - tokenId: u256, - data: Span - ) { - panic!("Some error"); - } - } -} diff --git a/packages/utils/tests/mocks/erc721_receiver_mocks.cairo b/packages/utils/tests/mocks/erc721_receiver_mocks.cairo deleted file mode 100644 index e321c0d58..000000000 --- a/packages/utils/tests/mocks/erc721_receiver_mocks.cairo +++ /dev/null @@ -1,237 +0,0 @@ -use openzeppelin_utils::test_utils::constants::SUCCESS; - -#[starknet::contract] -pub(crate) mod DualCaseERC721ReceiverMock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::ERC721ReceiverComponent; - use starknet::ContractAddress; - - component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC721Receiver - impl ERC721ReceiverImpl = ERC721ReceiverComponent::ERC721ReceiverImpl; - impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc721_receiver: ERC721ReceiverComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC721ReceiverEvent: ERC721ReceiverComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState) { - self.erc721_receiver.initializer(); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn on_erc721_received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - token_id: u256, - data: Span - ) -> felt252 { - if *data.at(0) == super::SUCCESS { - self.erc721_receiver.on_erc721_received(operator, from, token_id, data) - } else { - 0 - } - } - - #[external(v0)] - fn onERC721Received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenId: u256, - data: Span - ) -> felt252 { - Self::on_erc721_received(self, operator, from, tokenId, data) - } - } -} - -#[starknet::contract] -pub(crate) mod SnakeERC721ReceiverMock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::ERC721ReceiverComponent; - use starknet::ContractAddress; - - component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC721Receiver - impl ERC721ReceiverImpl = ERC721ReceiverComponent::ERC721ReceiverImpl; - impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc721_receiver: ERC721ReceiverComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC721ReceiverEvent: ERC721ReceiverComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState) { - self.erc721_receiver.initializer(); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn on_erc721_received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - token_id: u256, - data: Span - ) -> felt252 { - if *data.at(0) == super::SUCCESS { - self.erc721_receiver.on_erc721_received(operator, from, token_id, data) - } else { - 0 - } - } - } -} - -#[starknet::contract] -pub(crate) mod CamelERC721ReceiverMock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::ERC721ReceiverComponent; - use starknet::ContractAddress; - - component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC721Receiver - impl ERC721ReceiverCamelImpl = ERC721ReceiverComponent::ERC721ReceiverCamelImpl; - impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc721_receiver: ERC721ReceiverComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC721ReceiverEvent: ERC721ReceiverComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState) { - self.erc721_receiver.initializer(); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn onERC721Received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenId: u256, - data: Span - ) -> felt252 { - if *data.at(0) == super::SUCCESS { - self.erc721_receiver.onERC721Received(operator, from, tokenId, data) - } else { - 0 - } - } - } -} - -#[starknet::contract] -pub(crate) mod SnakeERC721ReceiverPanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn on_erc721_received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - token_id: u256, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } - } -} - -#[starknet::contract] -pub(crate) mod CamelERC721ReceiverPanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn onERC721Received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenId: u256, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } - } -} diff --git a/packages/utils/tests/mocks/eth_account_mocks.cairo b/packages/utils/tests/mocks/eth_account_mocks.cairo deleted file mode 100644 index b230e524d..000000000 --- a/packages/utils/tests/mocks/eth_account_mocks.cairo +++ /dev/null @@ -1,228 +0,0 @@ -#[starknet::contract(account)] -pub(crate) mod DualCaseEthAccountMock { - use openzeppelin_account::EthAccountComponent; - use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_introspection::src5::SRC5Component; - - component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - #[abi(embed_v0)] - impl SRC6Impl = EthAccountComponent::SRC6Impl; - #[abi(embed_v0)] - impl SRC6CamelOnlyImpl = EthAccountComponent::SRC6CamelOnlyImpl; - #[abi(embed_v0)] - impl DeclarerImpl = EthAccountComponent::DeclarerImpl; - #[abi(embed_v0)] - impl DeployableImpl = EthAccountComponent::DeployableImpl; - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - eth_account: EthAccountComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - EthAccountEvent: EthAccountComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, public_key: EthPublicKey) { - self.eth_account.initializer(public_key); - } -} - -#[starknet::contract(account)] -pub(crate) mod SnakeEthAccountMock { - use openzeppelin_account::EthAccountComponent; - use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_introspection::src5::SRC5Component; - - component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - #[abi(embed_v0)] - impl SRC6Impl = EthAccountComponent::SRC6Impl; - #[abi(embed_v0)] - impl PublicKeyImpl = EthAccountComponent::PublicKeyImpl; - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - eth_account: EthAccountComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - EthAccountEvent: EthAccountComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, public_key: EthPublicKey) { - self.eth_account.initializer(public_key); - } -} - -#[starknet::contract(account)] -pub(crate) mod CamelEthAccountMock { - use openzeppelin_account::EthAccountComponent; - use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_introspection::src5::SRC5Component; - use starknet::account::Call; - - component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - #[abi(embed_v0)] - impl SRC6CamelOnlyImpl = EthAccountComponent::SRC6CamelOnlyImpl; - #[abi(embed_v0)] - impl PublicKeyCamelImpl = - EthAccountComponent::PublicKeyCamelImpl; - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - impl SRC6Impl = EthAccountComponent::SRC6Impl; - impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - eth_account: EthAccountComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - EthAccountEvent: EthAccountComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, publicKey: EthPublicKey) { - self.eth_account.initializer(publicKey); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn __execute__(self: @ContractState, mut calls: Array) -> Array> { - self.eth_account.__execute__(calls) - } - - #[external(v0)] - fn __validate__(self: @ContractState, mut calls: Array) -> felt252 { - self.eth_account.__validate__(calls) - } - } -} - -// Although these modules are designed to panic, functions -// still need a valid return value. We chose: -// -// 3 for felt252 -// false for bool - -#[starknet::contract] -pub(crate) mod SnakeEthAccountPanicMock { - use openzeppelin_account::interface::EthPublicKey; - use starknet::SyscallResultTrait; - use starknet::secp256_trait::Secp256Trait; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn set_public_key( - ref self: ContractState, new_public_key: EthPublicKey, signature: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn get_public_key(self: @ContractState) -> EthPublicKey { - panic!("Some error"); - Secp256Trait::secp256_ec_new_syscall(3, 3).unwrap_syscall().unwrap() - } - - #[external(v0)] - fn is_valid_signature( - self: @ContractState, hash: felt252, signature: Array - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelEthAccountPanicMock { - use openzeppelin_account::interface::EthPublicKey; - use starknet::SyscallResultTrait; - use starknet::secp256_trait::Secp256Trait; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn setPublicKey( - ref self: ContractState, newPublicKey: EthPublicKey, signature: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn getPublicKey(self: @ContractState) -> EthPublicKey { - panic!("Some error"); - Secp256Trait::secp256_ec_new_syscall(3, 3).unwrap_syscall().unwrap() - } - - #[external(v0)] - fn isValidSignature( - self: @ContractState, hash: felt252, signature: Array - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - panic!("Some error"); - false - } - } -} diff --git a/packages/utils/tests/mocks/initializable_mocks.cairo b/packages/utils/tests/mocks/initializable_mocks.cairo deleted file mode 100644 index 92841237d..000000000 --- a/packages/utils/tests/mocks/initializable_mocks.cairo +++ /dev/null @@ -1,23 +0,0 @@ -#[starknet::contract] -pub(crate) mod InitializableMock { - use openzeppelin_security::initializable::InitializableComponent; - - component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); - - #[abi(embed_v0)] - impl InitializableImpl = - InitializableComponent::InitializableImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - initializable: InitializableComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - InitializableEvent: InitializableComponent::Event - } -} diff --git a/packages/utils/tests/mocks/non_implementing_mock.cairo b/packages/utils/tests/mocks/non_implementing_mock.cairo deleted file mode 100644 index c1212dbdd..000000000 --- a/packages/utils/tests/mocks/non_implementing_mock.cairo +++ /dev/null @@ -1,10 +0,0 @@ -#[starknet::contract] -pub(crate) mod NonImplementingMock { - #[storage] - struct Storage {} - - #[external(v0)] - fn nope(self: @ContractState) -> bool { - false - } -} diff --git a/packages/utils/tests/mocks/nonces_mocks.cairo b/packages/utils/tests/mocks/nonces_mocks.cairo deleted file mode 100644 index 4c68d5f06..000000000 --- a/packages/utils/tests/mocks/nonces_mocks.cairo +++ /dev/null @@ -1,23 +0,0 @@ -#[starknet::contract] -pub(crate) mod NoncesMock { - use openzeppelin_utils::cryptography::nonces::NoncesComponent; - - component!(path: NoncesComponent, storage: nonces, event: NoncesEvent); - - #[abi(embed_v0)] - impl NoncesImpl = NoncesComponent::NoncesImpl; - impl InternalImpl = NoncesComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - nonces: NoncesComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - NoncesEvent: NoncesComponent::Event - } -} diff --git a/packages/utils/tests/mocks/ownable_mocks.cairo b/packages/utils/tests/mocks/ownable_mocks.cairo deleted file mode 100644 index 1448f0cb0..000000000 --- a/packages/utils/tests/mocks/ownable_mocks.cairo +++ /dev/null @@ -1,188 +0,0 @@ -#[starknet::contract] -pub(crate) mod DualCaseOwnableMock { - use openzeppelin_access::ownable::OwnableComponent; - use starknet::ContractAddress; - - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); - - #[abi(embed_v0)] - impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl; - impl InternalImpl = OwnableComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - ownable: OwnableComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - OwnableEvent: OwnableComponent::Event - } - - #[constructor] - fn constructor(ref self: ContractState, owner: ContractAddress) { - self.ownable.initializer(owner); - } -} - -#[starknet::contract] -pub(crate) mod SnakeOwnableMock { - use openzeppelin_access::ownable::OwnableComponent; - use starknet::ContractAddress; - - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); - - #[abi(embed_v0)] - impl OwnableImpl = OwnableComponent::OwnableImpl; - impl InternalImpl = OwnableComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - ownable: OwnableComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - OwnableEvent: OwnableComponent::Event - } - - #[constructor] - fn constructor(ref self: ContractState, owner: ContractAddress) { - self.ownable.initializer(owner); - } -} - -#[starknet::contract] -pub(crate) mod CamelOwnableMock { - use openzeppelin_access::ownable::OwnableComponent; - use starknet::ContractAddress; - - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); - - #[abi(embed_v0)] - impl OwnableCamelOnlyImpl = - OwnableComponent::OwnableCamelOnlyImpl; - impl InternalImpl = OwnableComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - ownable: OwnableComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - OwnableEvent: OwnableComponent::Event - } - - #[constructor] - fn constructor(ref self: ContractState, owner: ContractAddress) { - self.ownable.initializer(owner); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn owner(self: @ContractState) -> ContractAddress { - self.ownable.Ownable_owner.read() - } - } -} - -#[starknet::contract] -pub(crate) mod SnakeOwnablePanicMock { - use core::num::traits::Zero; - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn owner(self: @ContractState) -> ContractAddress { - panic!("Some error"); - Zero::zero() - } - - #[external(v0)] - fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) { - panic!("Some error"); - } - - #[external(v0)] - fn renounce_ownership(ref self: ContractState) { - panic!("Some error"); - } - } -} - -#[starknet::contract] -pub(crate) mod CamelOwnablePanicMock { - use core::num::traits::Zero; - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn owner(self: @ContractState) -> ContractAddress { - panic!("Some error"); - Zero::zero() - } - - #[external(v0)] - fn transferOwnership(ref self: ContractState, newOwner: ContractAddress) { - panic!("Some error"); - } - - #[external(v0)] - fn renounceOwnership(ref self: ContractState) { - panic!("Some error"); - } - } -} - -#[starknet::contract] -pub(crate) mod DualCaseTwoStepOwnableMock { - use openzeppelin_access::ownable::OwnableComponent; - use starknet::ContractAddress; - - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); - - #[abi(embed_v0)] - impl OwnableTwoStepMixinImpl = - OwnableComponent::OwnableTwoStepMixinImpl; - impl InternalImpl = OwnableComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - ownable: OwnableComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - OwnableEvent: OwnableComponent::Event - } - - #[constructor] - fn constructor(ref self: ContractState, owner: ContractAddress) { - self.ownable.initializer(owner); - } -} diff --git a/packages/utils/tests/mocks/pausable_mocks.cairo b/packages/utils/tests/mocks/pausable_mocks.cairo deleted file mode 100644 index c37584a24..000000000 --- a/packages/utils/tests/mocks/pausable_mocks.cairo +++ /dev/null @@ -1,23 +0,0 @@ -#[starknet::contract] -pub(crate) mod PausableMock { - use openzeppelin_security::pausable::PausableComponent; - - component!(path: PausableComponent, storage: pausable, event: PausableEvent); - - #[abi(embed_v0)] - impl PausableImpl = PausableComponent::PausableImpl; - impl InternalImpl = PausableComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - pausable: PausableComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - PausableEvent: PausableComponent::Event - } -} diff --git a/packages/utils/tests/mocks/reentrancy_mocks.cairo b/packages/utils/tests/mocks/reentrancy_mocks.cairo deleted file mode 100644 index e7768e70f..000000000 --- a/packages/utils/tests/mocks/reentrancy_mocks.cairo +++ /dev/null @@ -1,125 +0,0 @@ -use starknet::ContractAddress; - -#[starknet::interface] -trait IReentrancyGuarded { - fn count_external_recursive(ref self: TState, n: felt252); -} - -#[starknet::interface] -pub(crate) trait IReentrancyMock { - fn count(ref self: TState); - fn current_count(self: @TState) -> felt252; - fn callback(ref self: TState); - fn count_local_recursive(ref self: TState, n: felt252); - fn count_external_recursive(ref self: TState, n: felt252); - fn count_and_call(ref self: TState, attacker: ContractAddress); -} - -#[starknet::contract] -pub(crate) mod ReentrancyMock { - use openzeppelin_security::reentrancyguard::ReentrancyGuardComponent; - use starknet::ContractAddress; - use starknet::get_contract_address; - use super::IAttackerDispatcher; - use super::IAttackerDispatcherTrait; - use super::IReentrancyGuardedDispatcher; - use super::IReentrancyGuardedDispatcherTrait; - - component!( - path: ReentrancyGuardComponent, storage: reentrancy_guard, event: ReentrancyGuardEvent - ); - - impl InternalImpl = ReentrancyGuardComponent::InternalImpl; - - #[storage] - struct Storage { - counter: felt252, - #[substorage(v0)] - reentrancy_guard: ReentrancyGuardComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ReentrancyGuardEvent: ReentrancyGuardComponent::Event - } - - #[abi(embed_v0)] - impl IReentrancyMockImpl of super::IReentrancyMock { - fn count(ref self: ContractState) { - self.counter.write(self.counter.read() + 1); - } - - fn current_count(self: @ContractState) -> felt252 { - self.counter.read() - } - - fn callback(ref self: ContractState) { - self.reentrancy_guard.start(); - self.count(); - self.reentrancy_guard.end(); - } - - fn count_local_recursive(ref self: ContractState, n: felt252) { - self.reentrancy_guard.start(); - - if n != 0 { - self.count(); - self.count_local_recursive(n - 1); - } - - self.reentrancy_guard.end(); - } - - fn count_external_recursive(ref self: ContractState, n: felt252) { - self.reentrancy_guard.start(); - - if n != 0 { - self.count(); - let this: ContractAddress = get_contract_address(); - IReentrancyGuardedDispatcher { contract_address: this } - .count_external_recursive(n - 1) - } - - self.reentrancy_guard.end(); - } - - fn count_and_call(ref self: ContractState, attacker: ContractAddress) { - self.reentrancy_guard.start(); - - self.count(); - IAttackerDispatcher { contract_address: attacker }.call_sender(); - - self.reentrancy_guard.end(); - } - } -} - -// -// Attacker -// - -#[starknet::interface] -trait IAttacker { - fn call_sender(self: @TState); -} - -#[starknet::contract] -pub(crate) mod Attacker { - use starknet::ContractAddress; - use starknet::get_caller_address; - use super::IReentrancyMockDispatcher; - use super::IReentrancyMockDispatcherTrait; - - #[storage] - struct Storage {} - - #[abi(embed_v0)] - impl IAttackerImpl of super::IAttacker { - fn call_sender(self: @ContractState) { - let caller: ContractAddress = get_caller_address(); - IReentrancyMockDispatcher { contract_address: caller }.callback(); - } - } -} diff --git a/packages/utils/tests/mocks/src5_mocks.cairo b/packages/utils/tests/mocks/src5_mocks.cairo deleted file mode 100644 index 86e8c5167..000000000 --- a/packages/utils/tests/mocks/src5_mocks.cairo +++ /dev/null @@ -1,22 +0,0 @@ -#[starknet::contract] -pub(crate) mod SRC5Mock { - use openzeppelin_introspection::src5::SRC5Component; - - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - SRC5Event: SRC5Component::Event - } -} diff --git a/packages/utils/tests/mocks/timelock_mocks.cairo b/packages/utils/tests/mocks/timelock_mocks.cairo deleted file mode 100644 index 810d88cac..000000000 --- a/packages/utils/tests/mocks/timelock_mocks.cairo +++ /dev/null @@ -1,151 +0,0 @@ -#[starknet::contract] -pub(crate) mod TimelockControllerMock { - use openzeppelin_access::accesscontrol::AccessControlComponent; - use openzeppelin_governance::timelock::TimelockControllerComponent; - use openzeppelin_introspection::src5::SRC5Component; - use starknet::ContractAddress; - - component!(path: AccessControlComponent, storage: access_control, event: AccessControlEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - component!(path: TimelockControllerComponent, storage: timelock, event: TimelockEvent); - - // Timelock Mixin - #[abi(embed_v0)] - impl TimelockMixinImpl = - TimelockControllerComponent::TimelockMixinImpl; - impl TimelockInternalImpl = TimelockControllerComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - access_control: AccessControlComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage, - #[substorage(v0)] - timelock: TimelockControllerComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - AccessControlEvent: AccessControlComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event, - #[flat] - TimelockEvent: TimelockControllerComponent::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - min_delay: u64, - proposers: Span, - executors: Span, - admin: ContractAddress - ) { - self.timelock.initializer(min_delay, proposers, executors, admin); - } -} - -#[starknet::interface] -pub(crate) trait IMockContract { - fn set_number(ref self: TState, new_number: felt252); - fn get_number(self: @TState) -> felt252; - fn failing_function(self: @TState); -} - -#[starknet::contract] -pub(crate) mod MockContract { - use super::IMockContract; - - #[storage] - struct Storage { - number: felt252, - } - - #[abi(embed_v0)] - impl MockContractImpl of IMockContract { - fn set_number(ref self: ContractState, new_number: felt252) { - self.number.write(new_number); - } - - fn get_number(self: @ContractState) -> felt252 { - self.number.read() - } - - fn failing_function(self: @ContractState) { - core::panic_with_felt252('Expected failure'); - } - } -} - -#[starknet::interface] -pub(crate) trait ITimelockAttacker { - fn reenter(ref self: TState); - fn reenter_batch(ref self: TState); -} - -#[starknet::contract] -pub(crate) mod TimelockAttackerMock { - use openzeppelin_governance::timelock::interface::{ - ITimelockDispatcher, ITimelockDispatcherTrait - }; - use starknet::ContractAddress; - use starknet::account::Call; - use super::ITimelockAttacker; - - const NO_PREDECESSOR: felt252 = 0; - const NO_SALT: felt252 = 0; - - #[storage] - struct Storage { - balance: felt252, - count: felt252 - } - - #[abi(embed_v0)] - impl TimelockAttackerImpl of ITimelockAttacker { - fn reenter(ref self: ContractState) { - let new_balance = self.balance.read() + 1; - self.balance.write(new_balance); - - let sender = starknet::get_caller_address(); - let this = starknet::get_contract_address(); - - let current_count = self.count.read(); - if current_count != 2 { - self.count.write(current_count + 1); - - let reentrant_call = Call { - to: this, selector: selector!("reenter"), calldata: array![].span() - }; - - let timelock = ITimelockDispatcher { contract_address: sender }; - timelock.execute(reentrant_call, NO_PREDECESSOR, NO_SALT); - } - } - - fn reenter_batch(ref self: ContractState) { - let new_balance = self.balance.read() + 1; - self.balance.write(new_balance); - - let sender = starknet::get_caller_address(); - let this = starknet::get_contract_address(); - - let current_count = self.count.read(); - if current_count != 2 { - self.count.write(current_count + 1); - - let reentrant_call = Call { - to: this, selector: selector!("reenter_batch"), calldata: array![].span() - }; - - let calls = array![reentrant_call].span(); - - let timelock = ITimelockDispatcher { contract_address: sender }; - timelock.execute_batch(calls, NO_PREDECESSOR, NO_SALT); - } - } - } -} diff --git a/packages/utils/tests/mocks/upgrades_mocks.cairo b/packages/utils/tests/mocks/upgrades_mocks.cairo deleted file mode 100644 index 266680d56..000000000 --- a/packages/utils/tests/mocks/upgrades_mocks.cairo +++ /dev/null @@ -1,111 +0,0 @@ -// These contracts are mocks used to test the core functionality of the upgrade functions. -// The functions are NOT PROTECTED. -// DO NOT USE IN PRODUCTION. - -use starknet::ClassHash; - -#[starknet::interface] -pub(crate) trait IUpgradesV1 { - fn upgrade(ref self: TState, new_class_hash: ClassHash); - fn set_value(ref self: TState, val: felt252); - fn get_value(self: @TState) -> felt252; - fn remove_selector(self: @TState); -} - -#[starknet::contract] -pub(crate) mod UpgradesV1 { - use openzeppelin_upgrades::UpgradeableComponent; - use starknet::ClassHash; - - component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); - - impl InternalImpl = UpgradeableComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - upgradeable: UpgradeableComponent::Storage, - value: felt252 - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - UpgradeableEvent: UpgradeableComponent::Event - } - - #[abi(embed_v0)] - impl UpgradesV1Impl of super::IUpgradesV1 { - fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { - self.upgradeable.upgrade(new_class_hash); - } - - fn set_value(ref self: ContractState, val: felt252) { - self.value.write(val); - } - - fn get_value(self: @ContractState) -> felt252 { - self.value.read() - } - - fn remove_selector(self: @ContractState) {} - } -} - -#[starknet::interface] -pub(crate) trait IUpgradesV2 { - fn upgrade(ref self: TState, new_class_hash: ClassHash); - fn set_value(ref self: TState, val: felt252); - fn set_value2(ref self: TState, val: felt252); - fn get_value(self: @TState) -> felt252; - fn get_value2(self: @TState) -> felt252; -} - -#[starknet::contract] -pub(crate) mod UpgradesV2 { - use openzeppelin_upgrades::UpgradeableComponent; - use starknet::ClassHash; - - component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); - - impl InternalImpl = UpgradeableComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - upgradeable: UpgradeableComponent::Storage, - value: felt252, - value2: felt252 - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - UpgradeableEvent: UpgradeableComponent::Event - } - - #[abi(embed_v0)] - impl UpgradesV2Impl of super::IUpgradesV2 { - fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { - self.upgradeable.upgrade(new_class_hash); - } - - fn set_value(ref self: ContractState, val: felt252) { - self.value.write(val); - } - - fn set_value2(ref self: ContractState, val: felt252) { - self.value2.write(val); - } - - fn get_value(self: @ContractState) -> felt252 { - self.value.read() - } - - fn get_value2(self: @ContractState) -> felt252 { - self.value2.read() - } - } -} diff --git a/packages/utils/tests/test_nonces.cairo b/packages/utils/tests/test_nonces.cairo deleted file mode 100644 index 15d7f9d73..000000000 --- a/packages/utils/tests/test_nonces.cairo +++ /dev/null @@ -1,45 +0,0 @@ -use crate::tests::mocks::nonces_mocks::NoncesMock; -use openzeppelin_utils::cryptography::interface::INonces; -use openzeppelin_utils::cryptography::nonces::NoncesComponent::InternalTrait; -use openzeppelin_utils::cryptography::nonces::NoncesComponent; -use openzeppelin_utils::test_utils::constants::OWNER; - -type ComponentState = NoncesComponent::ComponentState; - -fn COMPONENT_STATE() -> ComponentState { - NoncesComponent::component_state_for_testing() -} - -#[test] -fn test_nonces_getter() { - let state = COMPONENT_STATE(); - let nonce = state.nonces(OWNER()); - assert!(nonce.is_zero()); -} - -#[test] -fn test_use_nonce() { - let mut state = COMPONENT_STATE(); - let nonce = state.use_nonce(OWNER()); - assert!(nonce.is_zero()); - - let nonce = state.nonces(OWNER()); - assert_eq!(nonce, 1, "use_nonce should increment the nonce by 1"); -} - -#[test] -fn test_use_checked_nonce() { - let mut state = COMPONENT_STATE(); - let nonce = state.use_checked_nonce(OWNER(), 0); - assert!(nonce.is_zero()); - - let nonce = state.nonces(OWNER()); - assert_eq!(nonce, 1, "use_checked_nonce should increment the nonce by 1"); -} - -#[test] -#[should_panic(expected: ('Nonces: invalid nonce',))] -fn test_use_checked_nonce_invalid_current() { - let mut state = COMPONENT_STATE(); - state.use_checked_nonce(OWNER(), 15); -} diff --git a/packages/utils/tests/test_snip12.cairo b/packages/utils/tests/test_snip12.cairo deleted file mode 100644 index fa4adf480..000000000 --- a/packages/utils/tests/test_snip12.cairo +++ /dev/null @@ -1,70 +0,0 @@ -use core::hash::{Hash, HashStateTrait, HashStateExTrait}; -use core::poseidon::{PoseidonTrait, poseidon_hash_span}; -use openzeppelin_utils::cryptography::snip12::{ - STARKNET_DOMAIN_TYPE_HASH, StarknetDomain, StructHash, OffchainMessageHashImpl, SNIP12Metadata -}; -use openzeppelin_utils::test_utils::constants::{OWNER, RECIPIENT}; -use starknet::ContractAddress; - -const MESSAGE_TYPE_HASH: felt252 = - 0x120ae1bdaf7c1e48349da94bb8dad27351ca115d6605ce345aee02d68d99ec1; - -#[derive(Copy, Drop, Hash)] -struct Message { - recipient: ContractAddress, - amount: u256, - nonce: felt252, - expiry: u64 -} - -impl StructHashImpl of StructHash { - fn hash_struct(self: @Message) -> felt252 { - let hash_state = PoseidonTrait::new(); - hash_state.update_with(MESSAGE_TYPE_HASH).update_with(*self).finalize() - } -} - -impl SNIP12MetadataImpl of SNIP12Metadata { - fn name() -> felt252 { - 'DAPP_NAME' - } - fn version() -> felt252 { - 'v1' - } -} - -#[test] -fn test_starknet_domain_type_hash() { - let expected = selector!( - "\"StarknetDomain\"(\"name\":\"shortstring\",\"version\":\"shortstring\",\"chainId\":\"shortstring\",\"revision\":\"shortstring\")" - ); - assert_eq!(STARKNET_DOMAIN_TYPE_HASH, expected); -} - -#[test] -fn test_StructHashStarknetDomainImpl() { - let domain = StarknetDomain { name: 'DAPP_NAME', version: 'v1', chain_id: 'TEST', revision: 1 }; - - let expected = poseidon_hash_span( - array![ - STARKNET_DOMAIN_TYPE_HASH, domain.name, domain.version, domain.chain_id, domain.revision - ] - .span() - ); - assert_eq!(domain.hash_struct(), expected); -} - -#[test] -fn test_OffchainMessageHashImpl() { - let message = Message { recipient: RECIPIENT(), amount: 100, nonce: 1, expiry: 1000 }; - let domain = StarknetDomain { name: 'DAPP_NAME', version: 'v1', chain_id: 'TEST', revision: 1 }; - - starknet::testing::set_chain_id('TEST'); - - let expected = poseidon_hash_span( - array!['StarkNet Message', domain.hash_struct(), OWNER().into(), message.hash_struct()] - .span() - ); - assert_eq!(message.get_message_hash(OWNER()), expected); -} - From 6dcdad3be0f5af86f8141e78c57d0c2a7a531ebd Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 26 Jul 2024 20:35:16 +0200 Subject: [PATCH 26/45] feat: add missing tests --- Scarb.toml | 3 + packages/utils/src/tests.cairo | 4 ++ packages/utils/src/tests/mocks.cairo | 1 + .../utils/src/tests/mocks/nonces_mocks.cairo | 23 ++++++ packages/utils/src/tests/test_nonces.cairo | 46 ++++++++++++ packages/utils/src/tests/test_snip12.cairo | 70 +++++++++++++++++++ 6 files changed, 147 insertions(+) create mode 100644 packages/utils/src/tests.cairo create mode 100644 packages/utils/src/tests/mocks.cairo create mode 100644 packages/utils/src/tests/mocks/nonces_mocks.cairo create mode 100644 packages/utils/src/tests/test_nonces.cairo create mode 100644 packages/utils/src/tests/test_snip12.cairo diff --git a/Scarb.toml b/Scarb.toml index 0736f26a2..f771fb33b 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -63,3 +63,6 @@ casm = false [workspace.tool.fmt] sort-module-level-items = true + +[tool] +fmt.workspace = true diff --git a/packages/utils/src/tests.cairo b/packages/utils/src/tests.cairo new file mode 100644 index 000000000..37cf414d3 --- /dev/null +++ b/packages/utils/src/tests.cairo @@ -0,0 +1,4 @@ +pub(crate) mod mocks; + +mod test_nonces; +mod test_snip12; diff --git a/packages/utils/src/tests/mocks.cairo b/packages/utils/src/tests/mocks.cairo new file mode 100644 index 000000000..7a238265a --- /dev/null +++ b/packages/utils/src/tests/mocks.cairo @@ -0,0 +1 @@ +pub(crate) mod nonces_mocks; diff --git a/packages/utils/src/tests/mocks/nonces_mocks.cairo b/packages/utils/src/tests/mocks/nonces_mocks.cairo new file mode 100644 index 000000000..4c68d5f06 --- /dev/null +++ b/packages/utils/src/tests/mocks/nonces_mocks.cairo @@ -0,0 +1,23 @@ +#[starknet::contract] +pub(crate) mod NoncesMock { + use openzeppelin_utils::cryptography::nonces::NoncesComponent; + + component!(path: NoncesComponent, storage: nonces, event: NoncesEvent); + + #[abi(embed_v0)] + impl NoncesImpl = NoncesComponent::NoncesImpl; + impl InternalImpl = NoncesComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + nonces: NoncesComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + NoncesEvent: NoncesComponent::Event + } +} diff --git a/packages/utils/src/tests/test_nonces.cairo b/packages/utils/src/tests/test_nonces.cairo new file mode 100644 index 000000000..fb3d500d4 --- /dev/null +++ b/packages/utils/src/tests/test_nonces.cairo @@ -0,0 +1,46 @@ +use core::num::traits::Zero; +use openzeppelin_utils::cryptography::interface::INonces; +use openzeppelin_utils::cryptography::nonces::NoncesComponent::InternalTrait; +use openzeppelin_utils::cryptography::nonces::NoncesComponent; +use openzeppelin_utils::test_utils::constants::OWNER; +use openzeppelin_utils::tests::mocks::nonces_mocks::NoncesMock; + +type ComponentState = NoncesComponent::ComponentState; + +fn COMPONENT_STATE() -> ComponentState { + NoncesComponent::component_state_for_testing() +} + +#[test] +fn test_nonces_getter() { + let state = COMPONENT_STATE(); + let nonce = state.nonces(OWNER()); + assert!(nonce.is_zero()); +} + +#[test] +fn test_use_nonce() { + let mut state = COMPONENT_STATE(); + let nonce = state.use_nonce(OWNER()); + assert!(nonce.is_zero()); + + let nonce = state.nonces(OWNER()); + assert_eq!(nonce, 1, "use_nonce should increment the nonce by 1"); +} + +#[test] +fn test_use_checked_nonce() { + let mut state = COMPONENT_STATE(); + let nonce = state.use_checked_nonce(OWNER(), 0); + assert!(nonce.is_zero()); + + let nonce = state.nonces(OWNER()); + assert_eq!(nonce, 1, "use_checked_nonce should increment the nonce by 1"); +} + +#[test] +#[should_panic(expected: ('Nonces: invalid nonce',))] +fn test_use_checked_nonce_invalid_current() { + let mut state = COMPONENT_STATE(); + state.use_checked_nonce(OWNER(), 15); +} diff --git a/packages/utils/src/tests/test_snip12.cairo b/packages/utils/src/tests/test_snip12.cairo new file mode 100644 index 000000000..fa4adf480 --- /dev/null +++ b/packages/utils/src/tests/test_snip12.cairo @@ -0,0 +1,70 @@ +use core::hash::{Hash, HashStateTrait, HashStateExTrait}; +use core::poseidon::{PoseidonTrait, poseidon_hash_span}; +use openzeppelin_utils::cryptography::snip12::{ + STARKNET_DOMAIN_TYPE_HASH, StarknetDomain, StructHash, OffchainMessageHashImpl, SNIP12Metadata +}; +use openzeppelin_utils::test_utils::constants::{OWNER, RECIPIENT}; +use starknet::ContractAddress; + +const MESSAGE_TYPE_HASH: felt252 = + 0x120ae1bdaf7c1e48349da94bb8dad27351ca115d6605ce345aee02d68d99ec1; + +#[derive(Copy, Drop, Hash)] +struct Message { + recipient: ContractAddress, + amount: u256, + nonce: felt252, + expiry: u64 +} + +impl StructHashImpl of StructHash { + fn hash_struct(self: @Message) -> felt252 { + let hash_state = PoseidonTrait::new(); + hash_state.update_with(MESSAGE_TYPE_HASH).update_with(*self).finalize() + } +} + +impl SNIP12MetadataImpl of SNIP12Metadata { + fn name() -> felt252 { + 'DAPP_NAME' + } + fn version() -> felt252 { + 'v1' + } +} + +#[test] +fn test_starknet_domain_type_hash() { + let expected = selector!( + "\"StarknetDomain\"(\"name\":\"shortstring\",\"version\":\"shortstring\",\"chainId\":\"shortstring\",\"revision\":\"shortstring\")" + ); + assert_eq!(STARKNET_DOMAIN_TYPE_HASH, expected); +} + +#[test] +fn test_StructHashStarknetDomainImpl() { + let domain = StarknetDomain { name: 'DAPP_NAME', version: 'v1', chain_id: 'TEST', revision: 1 }; + + let expected = poseidon_hash_span( + array![ + STARKNET_DOMAIN_TYPE_HASH, domain.name, domain.version, domain.chain_id, domain.revision + ] + .span() + ); + assert_eq!(domain.hash_struct(), expected); +} + +#[test] +fn test_OffchainMessageHashImpl() { + let message = Message { recipient: RECIPIENT(), amount: 100, nonce: 1, expiry: 1000 }; + let domain = StarknetDomain { name: 'DAPP_NAME', version: 'v1', chain_id: 'TEST', revision: 1 }; + + starknet::testing::set_chain_id('TEST'); + + let expected = poseidon_hash_span( + array!['StarkNet Message', domain.hash_struct(), OWNER().into(), message.hash_struct()] + .span() + ); + assert_eq!(message.get_message_hash(OWNER()), expected); +} + From d678419f984c8199c2c206b44a538e14f2b6f6f1 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 26 Jul 2024 23:46:09 +0200 Subject: [PATCH 27/45] fix: tests --- Scarb.lock | 19 +++ docs/modules/ROOT/pages/accounts.adoc | 2 - packages/access/Scarb.toml | 9 +- packages/access/src/tests/common.cairo | 2 +- .../access/src/tests/test_accesscontrol.cairo | 6 +- .../src/tests/test_dual_accesscontrol.cairo | 4 +- .../access/src/tests/test_dual_ownable.cairo | 4 +- packages/access/src/tests/test_ownable.cairo | 5 +- .../src/tests/test_ownable_twostep.cairo | 7 +- packages/account/Scarb.toml | 11 +- .../account/src/tests/ethereum/common.cairo | 38 ++--- .../ethereum/test_dual_eth_account.cairo | 20 ++- .../src/tests/ethereum/test_eth_account.cairo | 32 ++-- .../account/src/tests/starknet/common.cairo | 95 +++++------ .../src/tests/starknet/test_account.cairo | 28 ++-- .../tests/starknet/test_dual_account.cairo | 16 +- .../account/src/tests/test_signature.cairo | 4 +- packages/governance/Scarb.toml | 9 +- packages/governance/src/tests.cairo | 5 +- packages/introspection/Scarb.toml | 9 +- packages/presets/Scarb.toml | 9 +- packages/presets/src/tests.cairo | 2 +- packages/presets/src/tests/test_erc1155.cairo | 31 ++-- packages/presets/src/tests/test_erc20.cairo | 22 +-- packages/presets/src/tests/test_erc721.cairo | 29 ++-- .../presets/src/tests/test_eth_account.cairo | 34 ++-- .../src/tests/test_universal_deployer.cairo | 12 +- packages/security/Scarb.toml | 9 +- .../security/src/tests/test_pausable.cairo | 12 +- .../src/tests/test_reentrancyguard.cairo | 6 +- packages/token/Scarb.toml | 9 +- packages/token/src/tests/erc1155/common.cairo | 24 ++- .../src/tests/erc1155/test_dual1155.cairo | 16 +- .../erc1155/test_dual1155_receiver.cairo | 12 +- .../src/tests/erc1155/test_erc1155.cairo | 4 - packages/token/src/tests/erc20/common.cairo | 8 +- .../token/src/tests/erc20/test_dual20.cairo | 12 +- .../token/src/tests/erc20/test_erc20.cairo | 3 - .../src/tests/erc20/test_erc20_votes.cairo | 21 ++- packages/token/src/tests/erc721.cairo | 1 + packages/token/src/tests/erc721/common.cairo | 8 +- .../token/src/tests/erc721/test_dual721.cairo | 16 +- .../tests/erc721/test_dual721_receiver.cairo | 5 +- .../token/src/tests/erc721/test_erc721.cairo | 21 +-- .../tests/erc721/test_erc721_receiver.cairo | 11 +- packages/upgrades/Scarb.toml | 11 +- packages/upgrades/src/tests/common.cairo | 24 +-- .../upgrades/src/tests/test_upgradeable.cairo | 16 +- packages/utils/Scarb.toml | 9 +- packages/utils/src/test_utils.cairo | 2 +- .../utils/src/test_utils}/common.cairo | 0 packages/utils/src/test_utils/constants.cairo | 32 ++++ .../utils/src/test_utils}/deployment.cairo | 2 +- .../utils/src/test_utils}/events.cairo | 0 .../utils/src/test_utils}/signing.cairo | 0 packages/utils/src/tests/test_snip12.cairo | 1 + src/tests.cairo | 19 --- src/tests/account/starknet/common.cairo | 74 --------- src/tests/upgrades/common.cairo | 20 --- src/tests/utils/constants.cairo | 148 ------------------ 60 files changed, 431 insertions(+), 589 deletions(-) rename {src/tests/utils => packages/utils/src/test_utils}/common.cairo (100%) rename {src/tests/utils => packages/utils/src/test_utils}/deployment.cairo (96%) rename {src/tests/utils => packages/utils/src/test_utils}/events.cairo (100%) rename {src/tests/utils => packages/utils/src/test_utils}/signing.cairo (100%) delete mode 100644 src/tests.cairo delete mode 100644 src/tests/account/starknet/common.cairo delete mode 100644 src/tests/upgrades/common.cairo delete mode 100644 src/tests/utils/constants.cairo diff --git a/Scarb.lock b/Scarb.lock index 018df04af..11da63c54 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -14,6 +14,7 @@ dependencies = [ "openzeppelin_token", "openzeppelin_upgrades", "openzeppelin_utils", + "snforge_std", ] [[package]] @@ -22,6 +23,7 @@ version = "0.15.0-rc.0" dependencies = [ "openzeppelin_introspection", "openzeppelin_utils", + "snforge_std", ] [[package]] @@ -31,6 +33,7 @@ dependencies = [ "openzeppelin_introspection", "openzeppelin_token", "openzeppelin_utils", + "snforge_std", ] [[package]] @@ -40,11 +43,15 @@ dependencies = [ "openzeppelin_access", "openzeppelin_introspection", "openzeppelin_utils", + "snforge_std", ] [[package]] name = "openzeppelin_introspection" version = "0.15.0-rc.0" +dependencies = [ + "snforge_std", +] [[package]] name = "openzeppelin_presets" @@ -55,6 +62,7 @@ dependencies = [ "openzeppelin_introspection", "openzeppelin_token", "openzeppelin_upgrades", + "snforge_std", ] [[package]] @@ -62,6 +70,7 @@ name = "openzeppelin_security" version = "0.15.0-rc.0" dependencies = [ "openzeppelin_utils", + "snforge_std", ] [[package]] @@ -71,6 +80,7 @@ dependencies = [ "openzeppelin_account", "openzeppelin_governance", "openzeppelin_introspection", + "snforge_std", ] [[package]] @@ -78,8 +88,17 @@ name = "openzeppelin_upgrades" version = "0.15.0-rc.0" dependencies = [ "openzeppelin_utils", + "snforge_std", ] [[package]] name = "openzeppelin_utils" version = "0.15.0-rc.0" +dependencies = [ + "snforge_std", +] + +[[package]] +name = "snforge_std" +version = "0.26.0" +source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.26.0#50eb589db65e113efe4f09241feb59b574228c7e" diff --git a/docs/modules/ROOT/pages/accounts.adoc b/docs/modules/ROOT/pages/accounts.adoc index 68d93e161..1cd0e8fed 100644 --- a/docs/modules/ROOT/pages/accounts.adoc +++ b/docs/modules/ROOT/pages/accounts.adoc @@ -204,7 +204,6 @@ Here’s an example of a basic contract: mod MyEthAccount { use openzeppelin_account::EthAccountComponent; use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin_introspection::src5::SRC5Component; use starknet::ClassHash; @@ -389,7 +388,6 @@ First, let's take the example account we created before and deploy it: mod MyEthAccount { use openzeppelin_account::EthAccountComponent; use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin_introspection::src5::SRC5Component; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); diff --git a/packages/access/Scarb.toml b/packages/access/Scarb.toml index 4e8ed333e..cbb1b5421 100644 --- a/packages/access/Scarb.toml +++ b/packages/access/Scarb.toml @@ -21,4 +21,11 @@ openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } [dev-dependencies] -cairo_test.workspace = true +snforge_std.workspace = true + +[lib] + +[[target.starknet-contract]] +allowed-libfuncs-list.name = "experimental" +sierra = true +casm = false diff --git a/packages/access/src/tests/common.cairo b/packages/access/src/tests/common.cairo index e649639fe..bd04a48d0 100644 --- a/packages/access/src/tests/common.cairo +++ b/packages/access/src/tests/common.cairo @@ -1,7 +1,7 @@ use openzeppelin_access::ownable::OwnableComponent::OwnershipTransferred; use openzeppelin_access::ownable::OwnableComponent; -use openzeppelin_utils::tests_utils::EventSpyExt; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::EventSpyExt; use snforge_std::EventSpy; use starknet::ContractAddress; diff --git a/packages/access/src/tests/test_accesscontrol.cairo b/packages/access/src/tests/test_accesscontrol.cairo index e167845f1..497dd20f6 100644 --- a/packages/access/src/tests/test_accesscontrol.cairo +++ b/packages/access/src/tests/test_accesscontrol.cairo @@ -5,12 +5,12 @@ use openzeppelin_access::accesscontrol::interface::{ IAccessControl, IAccessControlCamel, IACCESSCONTROL_ID }; use openzeppelin_access::accesscontrol::{AccessControlComponent, DEFAULT_ADMIN_ROLE}; -use openzeppelin_access::interface::ISRC5; use openzeppelin_access::tests::mocks::accesscontrol_mocks::DualCaseAccessControlMock; -use openzeppelin_utils::tests_utils::constants::{ +use openzeppelin_introspection::interface::ISRC5; +use openzeppelin_utils::test_utils::constants::{ ADMIN, AUTHORIZED, OTHER, OTHER_ADMIN, ROLE, OTHER_ROLE, ZERO }; -use openzeppelin_utils::tests_utils::events::EventSpyExt; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::{EventSpy, spy_events, start_cheat_caller_address, test_address}; use starknet::ContractAddress; diff --git a/packages/access/src/tests/test_dual_accesscontrol.cairo b/packages/access/src/tests/test_dual_accesscontrol.cairo index 74fecf766..e315b6e17 100644 --- a/packages/access/src/tests/test_dual_accesscontrol.cairo +++ b/packages/access/src/tests/test_dual_accesscontrol.cairo @@ -7,9 +7,9 @@ use openzeppelin_access::accesscontrol::interface::{ use openzeppelin_access::accesscontrol::interface::{ IAccessControlDispatcher, IAccessControlDispatcherTrait }; -use openzeppelin_utils::tests_utils::constants::{ADMIN, AUTHORIZED, ROLE}; -use openzeppelin_utils::tests_utils as utils; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{ADMIN, AUTHORIZED, ROLE}; use snforge_std::start_cheat_caller_address; // diff --git a/packages/access/src/tests/test_dual_ownable.cairo b/packages/access/src/tests/test_dual_ownable.cairo index d92c69880..792b600c8 100644 --- a/packages/access/src/tests/test_dual_ownable.cairo +++ b/packages/access/src/tests/test_dual_ownable.cairo @@ -3,9 +3,9 @@ use openzeppelin_access::ownable::dual_ownable::{DualCaseOwnable, DualCaseOwnabl use openzeppelin_access::ownable::interface::{ IOwnableDispatcher, IOwnableCamelOnlyDispatcher, IOwnableDispatcherTrait }; -use openzeppelin_utils::tests_utils::constants::{OWNER, NEW_OWNER}; -use openzeppelin_utils::tests_utils as utils; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{OWNER, NEW_OWNER}; use snforge_std::start_cheat_caller_address; // diff --git a/packages/access/src/tests/test_ownable.cairo b/packages/access/src/tests/test_ownable.cairo index 515b51d88..7771e137f 100644 --- a/packages/access/src/tests/test_ownable.cairo +++ b/packages/access/src/tests/test_ownable.cairo @@ -2,10 +2,9 @@ use core::num::traits::Zero; use openzeppelin_access::ownable::OwnableComponent::InternalTrait; use openzeppelin_access::ownable::OwnableComponent; use openzeppelin_access::ownable::interface::{IOwnable, IOwnableCamelOnly}; -use openzeppelin::tests::mocks::ownable_mocks::DualCaseOwnableMock; -use openzeppelin_utils::tests_utils::constants::{ZERO, OTHER, OWNER}; +use openzeppelin_access::tests::mocks::ownable_mocks::DualCaseOwnableMock; +use openzeppelin_utils::test_utils::constants::{ZERO, OTHER, OWNER}; use snforge_std::{spy_events, test_address, start_cheat_caller_address}; -use starknet::storage::StorageMemberAccessTrait; use super::common::OwnableSpyHelpers; diff --git a/packages/access/src/tests/test_ownable_twostep.cairo b/packages/access/src/tests/test_ownable_twostep.cairo index db8c0f410..8a667862d 100644 --- a/packages/access/src/tests/test_ownable_twostep.cairo +++ b/packages/access/src/tests/test_ownable_twostep.cairo @@ -2,13 +2,12 @@ use core::num::traits::Zero; use openzeppelin_access::ownable::OwnableComponent::{InternalTrait, OwnershipTransferStarted}; use openzeppelin_access::ownable::OwnableComponent; use openzeppelin_access::ownable::interface::{IOwnableTwoStep, IOwnableTwoStepCamelOnly}; -use openzeppelin::tests::mocks::ownable_mocks::DualCaseTwoStepOwnableMock; -use openzeppelin_utils::tests_utils::constants::{ZERO, OWNER, OTHER, NEW_OWNER}; -use openzeppelin_utils::tests_utils::events::EventSpyExt; +use openzeppelin_access::tests::mocks::ownable_mocks::DualCaseTwoStepOwnableMock; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::constants::{ZERO, OWNER, OTHER, NEW_OWNER}; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::{EventSpy, spy_events, start_cheat_caller_address, test_address}; use starknet::ContractAddress; -use starknet::storage::StorageMemberAccessTrait; use super::common::OwnableSpyHelpers; diff --git a/packages/account/Scarb.toml b/packages/account/Scarb.toml index 688316073..68775ceb4 100644 --- a/packages/account/Scarb.toml +++ b/packages/account/Scarb.toml @@ -19,7 +19,14 @@ fmt.workspace = true starknet.workspace = true openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } +openzeppelin_token = { path = "../token" } [dev-dependencies] -cairo_test.workspace = true -openzeppelin_token = { path = "../token" } +snforge_std.workspace = true + +[lib] + +[[target.starknet-contract]] +allowed-libfuncs-list.name = "experimental" +sierra = true +casm = false diff --git a/packages/account/src/tests/ethereum/common.cairo b/packages/account/src/tests/ethereum/common.cairo index 06bb129bc..40b214834 100644 --- a/packages/account/src/tests/ethereum/common.cairo +++ b/packages/account/src/tests/ethereum/common.cairo @@ -2,30 +2,30 @@ use core::hash::{HashStateTrait, HashStateExTrait}; use core::poseidon::PoseidonTrait; use core::poseidon::poseidon_hash_span; use core::starknet::secp256_trait::Secp256PointTrait; -use openzeppelin::account::EthAccountComponent::{OwnerAdded, OwnerRemoved}; -use openzeppelin::account::EthAccountComponent; -use openzeppelin::account::interface::EthPublicKey; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin_utils::tests_utils::constants::TRANSACTION_HASH; -use openzeppelin_utils::tests_utils::constants::{NAME, SYMBOL}; -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin_utils::tests_utils::signing::{Secp256k1KeyPair, Secp256k1KeyPairExt}; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin_account::EthAccountComponent::{OwnerAdded, OwnerRemoved}; +use openzeppelin_account::EthAccountComponent; +use openzeppelin_account::interface::EthPublicKey; +use openzeppelin_account::utils::signature::EthSignature; +use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::TRANSACTION_HASH; +use openzeppelin_utils::test_utils::constants::{NAME, SYMBOL}; +use openzeppelin_utils::test_utils::events::EventSpyExt; +use openzeppelin_utils::test_utils::signing::{Secp256k1KeyPair, Secp256k1KeyPairExt}; use snforge_std::EventSpy; use snforge_std::signature::secp256k1_curve::Secp256k1CurveSignerImpl; use starknet::{ContractAddress, SyscallResultTrait}; #[derive(Drop)] -pub(crate) struct SignedTransactionData { - pub(crate) private_key: u256, - pub(crate) public_key: EthPublicKey, - pub(crate) tx_hash: felt252, - pub(crate) signature: EthSignature +pub struct SignedTransactionData { + pub private_key: u256, + pub public_key: EthPublicKey, + pub tx_hash: felt252, + pub signature: EthSignature } -pub(crate) fn SIGNED_TX_DATA(key_pair: Secp256k1KeyPair) -> SignedTransactionData { +pub fn SIGNED_TX_DATA(key_pair: Secp256k1KeyPair) -> SignedTransactionData { let tx_hash = TRANSACTION_HASH; let (r, s) = key_pair.sign(tx_hash.into()).unwrap(); SignedTransactionData { @@ -36,7 +36,7 @@ pub(crate) fn SIGNED_TX_DATA(key_pair: Secp256k1KeyPair) -> SignedTransactionDat } } -pub(crate) fn get_accept_ownership_signature( +pub fn get_accept_ownership_signature( account_address: ContractAddress, current_owner: EthPublicKey, new_key_pair: Secp256k1KeyPair ) -> Span { let msg_hash: u256 = PoseidonTrait::new() @@ -50,7 +50,7 @@ pub(crate) fn get_accept_ownership_signature( new_key_pair.serialized_sign(msg_hash).span() } -pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { +pub fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { let mut calldata = array![]; calldata.append_serde(NAME()); @@ -64,7 +64,7 @@ pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> #[generate_trait] -pub(crate) impl EthAccountSpyHelpersImpl of EthAccountSpyHelpers { +pub impl EthAccountSpyHelpersImpl of EthAccountSpyHelpers { fn assert_event_owner_removed( ref self: EventSpy, contract: ContractAddress, public_key: EthPublicKey ) { diff --git a/packages/account/src/tests/ethereum/test_dual_eth_account.cairo b/packages/account/src/tests/ethereum/test_dual_eth_account.cairo index b207fa2aa..eafd219cc 100644 --- a/packages/account/src/tests/ethereum/test_dual_eth_account.cairo +++ b/packages/account/src/tests/ethereum/test_dual_eth_account.cairo @@ -1,15 +1,13 @@ -use openzeppelin::account::dual_eth_account::{DualCaseEthAccountABI, DualCaseEthAccount}; -use openzeppelin::account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; -use openzeppelin::account::utils::secp256k1::{ - DebugSecp256k1Point, Secp256k1PointPartialEq, Secp256k1PointSerde -}; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin_access::interface::ISRC5_ID; -use openzeppelin_utils::tests_utils::constants::secp256k1::KEY_PAIR; -use openzeppelin_utils::tests_utils::constants::{ETH_PUBKEY, NEW_ETH_PUBKEY, TRANSACTION_HASH}; -use openzeppelin_utils::tests_utils::signing::Secp256k1KeyPairExt; -use openzeppelin_utils::tests_utils as utils; +use openzeppelin_account::dual_eth_account::{DualCaseEthAccountABI, DualCaseEthAccount}; +use openzeppelin_account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; +use openzeppelin_account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; +use openzeppelin_account::utils::signature::EthSignature; +use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::secp256k1::KEY_PAIR; +use openzeppelin_utils::test_utils::constants::{ETH_PUBKEY, NEW_ETH_PUBKEY, TRANSACTION_HASH}; +use openzeppelin_utils::test_utils::signing::Secp256k1KeyPairExt; use snforge_std::start_cheat_caller_address; use super::common::get_accept_ownership_signature; diff --git a/packages/account/src/tests/ethereum/test_eth_account.cairo b/packages/account/src/tests/ethereum/test_eth_account.cairo index 205d577d0..8b5bc2274 100644 --- a/packages/account/src/tests/ethereum/test_eth_account.cairo +++ b/packages/account/src/tests/ethereum/test_eth_account.cairo @@ -1,24 +1,22 @@ use core::starknet::SyscallResultTrait; -use openzeppelin::account::EthAccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; -use openzeppelin::account::EthAccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; -use openzeppelin::account::EthAccountComponent; -use openzeppelin::account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; -use openzeppelin::account::interface::{ISRC6, ISRC6_ID}; -use openzeppelin::account::utils::secp256k1::{ - DebugSecp256k1Point, Secp256k1PointPartialEq, Secp256k1PointSerde -}; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin_access::interface::{ISRC5, ISRC5_ID}; -use openzeppelin::tests::mocks::eth_account_mocks::DualCaseEthAccountMock; -use openzeppelin_utils::tests_utils::constants::secp256k1::KEY_PAIR; -use openzeppelin_utils::tests_utils::constants::{ +use openzeppelin_account::EthAccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; +use openzeppelin_account::EthAccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; +use openzeppelin_account::EthAccountComponent; +use openzeppelin_account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; +use openzeppelin_account::interface::{ISRC6, ISRC6_ID}; +use openzeppelin_account::tests::mocks::eth_account_mocks::DualCaseEthAccountMock; +use openzeppelin_account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; +use openzeppelin_account::utils::signature::EthSignature; +use openzeppelin_introspection::interface::{ISRC5, ISRC5_ID}; +use openzeppelin_token::erc20::interface::IERC20DispatcherTrait; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::secp256k1::KEY_PAIR; +use openzeppelin_utils::test_utils::constants::{ ETH_PUBKEY, NEW_ETH_PUBKEY, SALT, ZERO, OTHER, RECIPIENT, CALLER, QUERY_VERSION, MIN_TRANSACTION_VERSION }; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; -use openzeppelin_utils::selectors; -use openzeppelin_utils::serde::SerializedAppend; use snforge_std::{ cheat_signature_global, cheat_transaction_version_global, cheat_transaction_hash_global, start_cheat_caller_address diff --git a/packages/account/src/tests/starknet/common.cairo b/packages/account/src/tests/starknet/common.cairo index 9c89498cb..cde377be5 100644 --- a/packages/account/src/tests/starknet/common.cairo +++ b/packages/account/src/tests/starknet/common.cairo @@ -1,69 +1,74 @@ +use core::hash::{HashStateTrait, HashStateExTrait}; +use core::poseidon::PoseidonTrait; use openzeppelin_account::AccountComponent::{OwnerAdded, OwnerRemoved}; use openzeppelin_account::AccountComponent; -use openzeppelin_account::tests::mocks::erc20_mocks::DualCaseERC20Mock; -use openzeppelin_token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin_token::erc20::interface::IERC20Dispatcher; use openzeppelin_utils::serde::SerializedAppend; -use openzeppelin_utils::test_utils::constants::{NAME, SYMBOL, NEW_PUBKEY}; -use openzeppelin_utils::test_utils; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{NAME, SYMBOL, TRANSACTION_HASH}; +use openzeppelin_utils::test_utils::events::EventSpyExt; +use openzeppelin_utils::test_utils::signing::StarkKeyPair; +use snforge_std::EventSpy; +use snforge_std::signature::stark_curve::StarkCurveSignerImpl; use starknet::ContractAddress; #[derive(Drop)] -pub struct SignedTransactionData { - pub private_key: felt252, - pub public_key: felt252, - pub transaction_hash: felt252, - pub r: felt252, - pub s: felt252 +pub(crate) struct SignedTransactionData { + pub(crate) tx_hash: felt252, + pub(crate) r: felt252, + pub(crate) s: felt252 } -pub fn SIGNED_TX_DATA() -> SignedTransactionData { - SignedTransactionData { - private_key: 1234, - public_key: NEW_PUBKEY, - transaction_hash: 0x601d3d2e265c10ff645e1554c435e72ce6721f0ba5fc96f0c650bfc6231191a, - r: 0x6bc22689efcaeacb9459577138aff9f0af5b77ee7894cdc8efabaf760f6cf6e, - s: 0x295989881583b9325436851934334faa9d639a2094cd1e2f8691c8a71cd4cdf - } +pub(crate) fn SIGNED_TX_DATA(key_pair: StarkKeyPair) -> SignedTransactionData { + let tx_hash = TRANSACTION_HASH; + let (r, s) = key_pair.sign(tx_hash).unwrap(); + SignedTransactionData { tx_hash, r, s } } -pub fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { +pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { let mut calldata = array![]; - calldata.append_serde(NAME()); calldata.append_serde(SYMBOL()); calldata.append_serde(initial_supply); calldata.append_serde(recipient); - let address = test_utils::deploy(DualCaseERC20Mock::TEST_CLASS_HASH, calldata); + let address = utils::declare_and_deploy("DualCaseERC20Mock", calldata); IERC20Dispatcher { contract_address: address } } - -pub fn assert_event_owner_removed(contract: ContractAddress, removed_owner_guid: felt252) { - let event = test_utils::pop_log::(contract).unwrap(); - let expected = AccountComponent::Event::OwnerRemoved(OwnerRemoved { removed_owner_guid }); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("OwnerRemoved")); - indexed_keys.append_serde(removed_owner_guid); - test_utils::assert_indexed_keys(event, indexed_keys.span()); +pub(crate) fn get_accept_ownership_signature( + account_address: ContractAddress, current_public_key: felt252, new_key_pair: StarkKeyPair +) -> Span { + let msg_hash = PoseidonTrait::new() + .update_with('StarkNet Message') + .update_with('accept_ownership') + .update_with(account_address) + .update_with(current_public_key) + .finalize(); + let (sig_r, sig_s) = new_key_pair.sign(msg_hash).unwrap(); + array![sig_r, sig_s].span() } -pub fn assert_event_owner_added(contract: ContractAddress, new_owner_guid: felt252) { - let event = test_utils::pop_log::(contract).unwrap(); - let expected = AccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); - assert!(event == expected); +#[generate_trait] +pub(crate) impl AccountSpyHelpersImpl of AccountSpyHelpers { + fn assert_event_owner_removed( + ref self: EventSpy, contract: ContractAddress, removed_owner_guid: felt252 + ) { + let expected = AccountComponent::Event::OwnerRemoved(OwnerRemoved { removed_owner_guid }); + self.assert_emitted_single(contract, expected); + } - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("OwnerAdded")); - indexed_keys.append_serde(new_owner_guid); - test_utils::assert_indexed_keys(event, indexed_keys.span()); -} + fn assert_event_owner_added( + ref self: EventSpy, contract: ContractAddress, new_owner_guid: felt252 + ) { + let expected = AccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); + self.assert_emitted_single(contract, expected); + } -pub fn assert_only_event_owner_added(contract: ContractAddress, new_owner_guid: felt252) { - assert_event_owner_added(contract, new_owner_guid); - test_utils::assert_no_events_left(contract); + fn assert_only_event_owner_added( + ref self: EventSpy, contract: ContractAddress, new_owner_guid: felt252 + ) { + self.assert_event_owner_added(contract, new_owner_guid); + self.assert_no_events_left_from(contract); + } } diff --git a/packages/account/src/tests/starknet/test_account.cairo b/packages/account/src/tests/starknet/test_account.cairo index 0f1809eb7..2ee484708 100644 --- a/packages/account/src/tests/starknet/test_account.cairo +++ b/packages/account/src/tests/starknet/test_account.cairo @@ -1,21 +1,21 @@ use core::num::traits::Zero; use core::starknet::SyscallResultTrait; -use openzeppelin::account::AccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; -use openzeppelin::account::AccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; -use openzeppelin::account::AccountComponent; -use openzeppelin::account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; -use openzeppelin::account::interface::{ISRC6, ISRC6_ID}; -use openzeppelin_access::interface::{ISRC5, ISRC5_ID}; -use openzeppelin::tests::mocks::account_mocks::DualCaseAccountMock; -use openzeppelin_utils::tests_utils::constants::stark::{KEY_PAIR, KEY_PAIR_2}; -use openzeppelin_utils::tests_utils::constants::{ - SALT, ZERO, OTHER, CALLER, RECIPIENT, QUERY_OFFSET, QUERY_VERSION, MIN_TRANSACTION_VERSION -}; -use openzeppelin_utils::tests_utils::signing::StarkKeyPair; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; +use openzeppelin_account::AccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; +use openzeppelin_account::AccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; +use openzeppelin_account::AccountComponent; +use openzeppelin_account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; +use openzeppelin_account::interface::{ISRC6, ISRC6_ID}; +use openzeppelin_account::tests::mocks::account_mocks::DualCaseAccountMock; +use openzeppelin_introspection::interface::{ISRC5, ISRC5_ID}; +use openzeppelin_token::erc20::interface::IERC20DispatcherTrait; use openzeppelin_utils::selectors; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::stark::{KEY_PAIR, KEY_PAIR_2}; +use openzeppelin_utils::test_utils::constants::{ + SALT, ZERO, OTHER, CALLER, RECIPIENT, QUERY_OFFSET, QUERY_VERSION, MIN_TRANSACTION_VERSION +}; +use openzeppelin_utils::test_utils::signing::StarkKeyPair; use snforge_std::{ cheat_signature_global, cheat_transaction_version_global, cheat_transaction_hash_global }; diff --git a/packages/account/src/tests/starknet/test_dual_account.cairo b/packages/account/src/tests/starknet/test_dual_account.cairo index 7e2ea78cb..9609514a8 100644 --- a/packages/account/src/tests/starknet/test_dual_account.cairo +++ b/packages/account/src/tests/starknet/test_dual_account.cairo @@ -1,11 +1,11 @@ -use openzeppelin::account::dual_account::{DualCaseAccountABI, DualCaseAccount}; -use openzeppelin::account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; -use openzeppelin_access::interface::ISRC5_ID; -use openzeppelin::tests::account::starknet::common::SIGNED_TX_DATA; -use openzeppelin_utils::tests_utils::constants::TRANSACTION_HASH; -use openzeppelin_utils::tests_utils::constants::stark::{KEY_PAIR, KEY_PAIR_2}; -use openzeppelin_utils::tests_utils::signing::{StarkKeyPair, StarkKeyPairExt}; -use openzeppelin_utils::tests_utils as utils; +use openzeppelin_account::dual_account::{DualCaseAccountABI, DualCaseAccount}; +use openzeppelin_account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; +use openzeppelin_account::tests::starknet::common::SIGNED_TX_DATA; +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::TRANSACTION_HASH; +use openzeppelin_utils::test_utils::constants::stark::{KEY_PAIR, KEY_PAIR_2}; +use openzeppelin_utils::test_utils::signing::{StarkKeyPair, StarkKeyPairExt}; use snforge_std::{declare, start_cheat_caller_address}; use super::common::get_accept_ownership_signature; diff --git a/packages/account/src/tests/test_signature.cairo b/packages/account/src/tests/test_signature.cairo index 94a956a83..79f9368b5 100644 --- a/packages/account/src/tests/test_signature.cairo +++ b/packages/account/src/tests/test_signature.cairo @@ -1,5 +1,5 @@ -use openzeppelin::account::utils::signature::{is_valid_stark_signature, is_valid_eth_signature}; -use openzeppelin_utils::tests_utils::constants::{stark, secp256k1}; +use openzeppelin_account::utils::signature::{is_valid_stark_signature, is_valid_eth_signature}; +use openzeppelin_utils::test_utils::constants::{stark, secp256k1}; use starknet::secp256_trait::Secp256Trait; use starknet::secp256k1::Secp256k1Point; diff --git a/packages/governance/Scarb.toml b/packages/governance/Scarb.toml index 7b065bb14..d719a38ce 100644 --- a/packages/governance/Scarb.toml +++ b/packages/governance/Scarb.toml @@ -22,4 +22,11 @@ openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } [dev-dependencies] -cairo_test.workspace = true +snforge_std.workspace = true + +[lib] + +[[target.starknet-contract]] +allowed-libfuncs-list.name = "experimental" +sierra = true +casm = false diff --git a/packages/governance/src/tests.cairo b/packages/governance/src/tests.cairo index 883a2ac5d..086c8625d 100644 --- a/packages/governance/src/tests.cairo +++ b/packages/governance/src/tests.cairo @@ -1,4 +1,5 @@ pub(crate) mod mocks; +// mod test_timelock; +// mod test_utils; + -mod test_timelock; -mod test_utils; diff --git a/packages/introspection/Scarb.toml b/packages/introspection/Scarb.toml index 978c7dbdf..1ccc1aae8 100644 --- a/packages/introspection/Scarb.toml +++ b/packages/introspection/Scarb.toml @@ -20,4 +20,11 @@ fmt.workspace = true starknet.workspace = true [dev-dependencies] -cairo_test.workspace = true +snforge_std.workspace = true + +[lib] + +[[target.starknet-contract]] +allowed-libfuncs-list.name = "experimental" +sierra = true +casm = false diff --git a/packages/presets/Scarb.toml b/packages/presets/Scarb.toml index 80170f0f9..8319757ba 100644 --- a/packages/presets/Scarb.toml +++ b/packages/presets/Scarb.toml @@ -25,4 +25,11 @@ openzeppelin_token = { path = "../token" } openzeppelin_upgrades = { path = "../upgrades" } [dev-dependencies] -cairo_test.workspace = true +snforge_std.workspace = true + +[lib] + +[[target.starknet-contract]] +allowed-libfuncs-list.name = "experimental" +sierra = true +casm = false diff --git a/packages/presets/src/tests.cairo b/packages/presets/src/tests.cairo index 88a945487..057d56023 100644 --- a/packages/presets/src/tests.cairo +++ b/packages/presets/src/tests.cairo @@ -1,6 +1,6 @@ pub(crate) mod mocks; -mod test_account; +// mod test_account; mod test_erc1155; mod test_erc20; mod test_erc721; diff --git a/packages/presets/src/tests/test_erc1155.cairo b/packages/presets/src/tests/test_erc1155.cairo index 079b68145..3eafdc687 100644 --- a/packages/presets/src/tests/test_erc1155.cairo +++ b/packages/presets/src/tests/test_erc1155.cairo @@ -1,27 +1,26 @@ use core::num::traits::Zero; -use openzeppelin_access; -use openzeppelin::presets::interfaces::{ +use openzeppelin_access::tests::common::OwnableSpyHelpers; +use openzeppelin_presets::interfaces::{ ERC1155UpgradeableABIDispatcher, ERC1155UpgradeableABIDispatcherTrait }; -use openzeppelin::tests::access::common::OwnableSpyHelpers; -use openzeppelin::tests::token::erc1155::common::ERC1155SpyHelpers; -use openzeppelin::tests::token::erc1155::common::{ +use openzeppelin_token::erc1155::interface::{ + IERC1155CamelSafeDispatcher, IERC1155CamelSafeDispatcherTrait +}; +use openzeppelin_token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; +use openzeppelin_token::erc1155; +use openzeppelin_token::tests::erc1155::common::ERC1155SpyHelpers; +use openzeppelin_token::tests::erc1155::common::{ setup_account, setup_receiver, setup_camel_receiver, deploy_another_account_at, setup_src5 }; -use openzeppelin::tests::token::erc1155::common::{get_ids_and_values, get_ids_and_split_values}; -use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; -use openzeppelin_utils::tests_utils::constants::{ +use openzeppelin_token::tests::erc1155::common::{get_ids_and_values, get_ids_and_split_values}; +use openzeppelin_upgrades::tests::common::UpgradeableSpyHelpers; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{ EMPTY_DATA, ZERO, OWNER, RECIPIENT, CLASS_HASH_ZERO, OPERATOR, OTHER, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 }; -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc1155::interface::{ - IERC1155CamelSafeDispatcher, IERC1155CamelSafeDispatcherTrait -}; -use openzeppelin::token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; -use openzeppelin::token::erc1155; -use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::{spy_events, EventSpy, start_cheat_caller_address}; use starknet::{ContractAddress, ClassHash}; diff --git a/packages/presets/src/tests/test_erc20.cairo b/packages/presets/src/tests/test_erc20.cairo index e2b8c99d3..cfe0f9d2c 100644 --- a/packages/presets/src/tests/test_erc20.cairo +++ b/packages/presets/src/tests/test_erc20.cairo @@ -1,22 +1,22 @@ use core::integer::BoundedInt; use core::num::traits::Zero; -use openzeppelin::presets::interfaces::erc20::{ +use openzeppelin_access::tests::common::OwnableSpyHelpers; +use openzeppelin_presets::interfaces::erc20::{ ERC20UpgradeableABISafeDispatcher, ERC20UpgradeableABISafeDispatcherTrait }; -use openzeppelin::presets::interfaces::{ +use openzeppelin_presets::interfaces::{ ERC20UpgradeableABIDispatcher, ERC20UpgradeableABIDispatcherTrait }; -use openzeppelin::tests::access::common::OwnableSpyHelpers; -use openzeppelin::tests::token::erc20::common::ERC20SpyHelpers; -use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; -use openzeppelin_utils::tests_utils::common::IntoBase16String; -use openzeppelin_utils::tests_utils::constants::{ +use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin_token::tests::erc20::common::ERC20SpyHelpers; +use openzeppelin_upgrades::tests::common::UpgradeableSpyHelpers; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::common::IntoBase16String; +use openzeppelin_utils::test_utils::constants::{ ZERO, OWNER, SPENDER, RECIPIENT, OTHER, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE, CLASS_HASH_ZERO }; -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::{spy_events, EventSpy, start_cheat_caller_address}; use starknet::ClassHash; diff --git a/packages/presets/src/tests/test_erc721.cairo b/packages/presets/src/tests/test_erc721.cairo index 921652ab6..45e067f4e 100644 --- a/packages/presets/src/tests/test_erc721.cairo +++ b/packages/presets/src/tests/test_erc721.cairo @@ -1,28 +1,27 @@ use core::num::traits::Zero; -use openzeppelin_access::tests::common::assert_event_ownership_transferred; +use openzeppelin_access::tests::common::OwnableSpyHelpers; use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin_presets::ERC721Upgradeable::InternalImpl; use openzeppelin_presets::ERC721Upgradeable; use openzeppelin_presets::interfaces::{ ERC721UpgradeableABIDispatcher, ERC721UpgradeableABIDispatcherTrait }; -use openzeppelin::tests::access::common::OwnableSpyHelpers; -use openzeppelin::tests::token::erc721::common::ERC721SpyHelpers; -use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; -use openzeppelin_utils::tests_utils::common::IntoBase16String; -use openzeppelin_utils::tests_utils::constants::{ - ZERO, DATA, OWNER, SPENDER, RECIPIENT, OTHER, OPERATOR, CLASS_HASH_ZERO, PUBKEY, NAME, SYMBOL, - BASE_URI -}; -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc721::ERC721Component::ERC721Impl; -use openzeppelin::token::erc721::interface::{ +use openzeppelin_token::erc721::ERC721Component::ERC721Impl; +use openzeppelin_token::erc721::interface::{ IERC721CamelOnlySafeDispatcher, IERC721CamelOnlySafeDispatcherTrait }; -use openzeppelin::token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; -use openzeppelin::token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID}; +use openzeppelin_token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; +use openzeppelin_token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID}; +use openzeppelin_token::tests::erc721::common::ERC721SpyHelpers; +use openzeppelin_upgrades::tests::common::UpgradeableSpyHelpers; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::common::IntoBase16String; +use openzeppelin_utils::test_utils::constants::{ + ZERO, DATA, OWNER, SPENDER, RECIPIENT, OTHER, OPERATOR, CLASS_HASH_ZERO, PUBKEY, NAME, SYMBOL, + BASE_URI +}; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::{spy_events, EventSpy, start_cheat_caller_address}; use starknet::{ContractAddress, ClassHash}; diff --git a/packages/presets/src/tests/test_eth_account.cairo b/packages/presets/src/tests/test_eth_account.cairo index 8f1515725..5605f1513 100644 --- a/packages/presets/src/tests/test_eth_account.cairo +++ b/packages/presets/src/tests/test_eth_account.cairo @@ -1,30 +1,28 @@ use core::num::traits::Zero; -use openzeppelin::account::interface::ISRC6_ID; -use openzeppelin::account::utils::secp256k1::{ - DebugSecp256k1Point, Secp256k1PointSerde, Secp256k1PointPartialEq +use openzeppelin_account::interface::ISRC6_ID; +use openzeppelin_account::tests::ethereum::common::EthAccountSpyHelpers; +use openzeppelin_account::tests::ethereum::common::{ + deploy_erc20, SIGNED_TX_DATA, SignedTransactionData, get_accept_ownership_signature }; -use openzeppelin_access::interface::ISRC5_ID; -use openzeppelin::presets::EthAccountUpgradeable; -use openzeppelin::presets::interfaces::eth_account::{ +use openzeppelin_account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_presets::EthAccountUpgradeable; +use openzeppelin_presets::interfaces::eth_account::{ EthAccountUpgradeableABISafeDispatcher, EthAccountUpgradeableABISafeDispatcherTrait }; -use openzeppelin::presets::interfaces::{ +use openzeppelin_presets::interfaces::{ EthAccountUpgradeableABIDispatcher, EthAccountUpgradeableABIDispatcherTrait }; -use openzeppelin::tests::account::ethereum::common::EthAccountSpyHelpers; -use openzeppelin::tests::account::ethereum::common::{ - deploy_erc20, SIGNED_TX_DATA, SignedTransactionData, get_accept_ownership_signature -}; -use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; -use openzeppelin_utils::tests_utils::constants::secp256k1::KEY_PAIR; -use openzeppelin_utils::tests_utils::constants::{ +use openzeppelin_token::erc20::interface::IERC20DispatcherTrait; +use openzeppelin_upgrades::tests::common::UpgradeableSpyHelpers; +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::secp256k1::KEY_PAIR; +use openzeppelin_utils::test_utils::constants::{ CLASS_HASH_ZERO, ETH_PUBKEY, NEW_ETH_PUBKEY, SALT, ZERO, RECIPIENT, QUERY_VERSION, MIN_TRANSACTION_VERSION }; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; -use openzeppelin_utils::selectors; -use openzeppelin_utils::serde::SerializedAppend; use snforge_std::{ cheat_signature_global, cheat_transaction_version_global, cheat_transaction_hash_global, start_cheat_caller_address diff --git a/packages/presets/src/tests/test_universal_deployer.cairo b/packages/presets/src/tests/test_universal_deployer.cairo index 8e26c5fca..d33bd8f75 100644 --- a/packages/presets/src/tests/test_universal_deployer.cairo +++ b/packages/presets/src/tests/test_universal_deployer.cairo @@ -1,14 +1,14 @@ -use openzeppelin::presets::universal_deployer::UniversalDeployer::ContractDeployed; -use openzeppelin::presets::universal_deployer::UniversalDeployer; -use openzeppelin_utils::tests_utils::constants::{NAME, SYMBOL, SUPPLY, SALT, CALLER, RECIPIENT}; -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin_presets::universal_deployer::UniversalDeployer::ContractDeployed; +use openzeppelin_presets::universal_deployer::UniversalDeployer; +use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use openzeppelin_utils::deployments::{DeployerInfo, calculate_contract_address_from_udc}; use openzeppelin_utils::interfaces::{ IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait }; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{NAME, SYMBOL, SUPPLY, SALT, CALLER, RECIPIENT}; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::{EventSpy, spy_events, declare, start_cheat_caller_address}; use starknet::{ClassHash, ContractAddress}; diff --git a/packages/security/Scarb.toml b/packages/security/Scarb.toml index efe241305..fb0a15b07 100644 --- a/packages/security/Scarb.toml +++ b/packages/security/Scarb.toml @@ -20,5 +20,12 @@ fmt.workspace = true starknet.workspace = true [dev-dependencies] -cairo_test.workspace = true +snforge_std.workspace = true openzeppelin_utils = { path = "../utils" } + +[lib] + +[[target.starknet-contract]] +allowed-libfuncs-list.name = "experimental" +sierra = true +casm = false diff --git a/packages/security/src/tests/test_pausable.cairo b/packages/security/src/tests/test_pausable.cairo index ec3021a68..4189c34d8 100644 --- a/packages/security/src/tests/test_pausable.cairo +++ b/packages/security/src/tests/test_pausable.cairo @@ -1,9 +1,9 @@ -use openzeppelin::security::PausableComponent::{InternalImpl, PausableImpl}; -use openzeppelin::security::PausableComponent::{Paused, Unpaused}; -use openzeppelin::security::PausableComponent; -use openzeppelin::tests::mocks::pausable_mocks::PausableMock; -use openzeppelin_utils::tests_utils::constants::CALLER; -use openzeppelin_utils::tests_utils::events::EventSpyExt; +use openzeppelin_security::PausableComponent::{InternalImpl, PausableImpl}; +use openzeppelin_security::PausableComponent::{Paused, Unpaused}; +use openzeppelin_security::PausableComponent; +use openzeppelin_security::tests::mocks::pausable_mocks::PausableMock; +use openzeppelin_utils::test_utils::constants::CALLER; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::EventSpy; use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::ContractAddress; diff --git a/packages/security/src/tests/test_reentrancyguard.cairo b/packages/security/src/tests/test_reentrancyguard.cairo index 553714439..b3c647f5d 100644 --- a/packages/security/src/tests/test_reentrancyguard.cairo +++ b/packages/security/src/tests/test_reentrancyguard.cairo @@ -1,6 +1,6 @@ -use openzeppelin::security::ReentrancyGuardComponent::InternalImpl; -use openzeppelin::security::ReentrancyGuardComponent; -use openzeppelin::tests::mocks::reentrancy_mocks::{ +use openzeppelin_security::ReentrancyGuardComponent::InternalImpl; +use openzeppelin_security::ReentrancyGuardComponent; +use openzeppelin_security::tests::mocks::reentrancy_mocks::{ ReentrancyMock, IReentrancyMockDispatcher, IReentrancyMockDispatcherTrait }; use openzeppelin_utils::test_utils as utils; diff --git a/packages/token/Scarb.toml b/packages/token/Scarb.toml index 9819a35a2..93bdc6fd3 100644 --- a/packages/token/Scarb.toml +++ b/packages/token/Scarb.toml @@ -23,4 +23,11 @@ openzeppelin_introspection = { path = "../introspection" } openzeppelin_governance = { path = "../governance" } [dev-dependencies] -cairo_test.workspace = true +snforge_std.workspace = true + +[lib] + +[[target.starknet-contract]] +allowed-libfuncs-list.name = "experimental" +sierra = true +casm = false diff --git a/packages/token/src/tests/erc1155/common.cairo b/packages/token/src/tests/erc1155/common.cairo index 4b62b1497..9a74c42bb 100644 --- a/packages/token/src/tests/erc1155/common.cairo +++ b/packages/token/src/tests/erc1155/common.cairo @@ -1,35 +1,33 @@ -use openzeppelin_utils::tests_utils::constants::{ +use openzeppelin_token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; +use openzeppelin_token::erc1155::ERC1155Component; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{ PUBKEY, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 }; -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; -use openzeppelin::token::erc1155::ERC1155Component; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::EventSpy; use starknet::ContractAddress; -pub(crate) fn setup_receiver() -> ContractAddress { +pub fn setup_receiver() -> ContractAddress { utils::declare_and_deploy("SnakeERC1155ReceiverMock", array![]) } -pub(crate) fn setup_camel_receiver() -> ContractAddress { +pub fn setup_camel_receiver() -> ContractAddress { utils::declare_and_deploy("CamelERC1155ReceiverMock", array![]) } -pub(crate) fn setup_account() -> ContractAddress { +pub fn setup_account() -> ContractAddress { let calldata = array![PUBKEY]; utils::declare_and_deploy("SnakeAccountMock", calldata) } -pub(crate) fn deploy_another_account_at( - existing: ContractAddress, target_address: ContractAddress -) { +pub fn deploy_another_account_at(existing: ContractAddress, target_address: ContractAddress) { let calldata = array![PUBKEY]; utils::deploy_another_at(existing, target_address, calldata); } -pub(crate) fn setup_src5() -> ContractAddress { +pub fn setup_src5() -> ContractAddress { utils::declare_and_deploy("SRC5Mock", array![]) } @@ -46,7 +44,7 @@ pub fn get_ids_and_split_values(split: u256) -> (Span, Span) { } #[generate_trait] -pub(crate) impl ERC1155SpyHelpersImpl of ERC1155SpyHelpers { +pub impl ERC1155SpyHelpersImpl of ERC1155SpyHelpers { fn assert_event_approval_for_all( ref self: EventSpy, contract: ContractAddress, diff --git a/packages/token/src/tests/erc1155/test_dual1155.cairo b/packages/token/src/tests/erc1155/test_dual1155.cairo index 31b0816ca..971134ce3 100644 --- a/packages/token/src/tests/erc1155/test_dual1155.cairo +++ b/packages/token/src/tests/erc1155/test_dual1155.cairo @@ -1,15 +1,13 @@ use core::num::traits::Zero; -use openzeppelin_utils::tests_utils::constants::{ +use openzeppelin_token::erc1155::dual1155::{DualCaseERC1155, DualCaseERC1155Trait}; +use openzeppelin_token::erc1155::interface::IERC1155_ID; +use openzeppelin_token::erc1155::interface::{IERC1155CamelDispatcher, IERC1155CamelDispatcherTrait}; +use openzeppelin_token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{ EMPTY_DATA, OWNER, RECIPIENT, OPERATOR, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE }; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc1155::dual1155::{DualCaseERC1155, DualCaseERC1155Trait}; -use openzeppelin::token::erc1155::interface::IERC1155_ID; -use openzeppelin::token::erc1155::interface::{ - IERC1155CamelDispatcher, IERC1155CamelDispatcherTrait -}; -use openzeppelin::token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; -use openzeppelin_utils::serde::SerializedAppend; use snforge_std::start_cheat_caller_address; use starknet::ContractAddress; diff --git a/packages/token/src/tests/erc1155/test_dual1155_receiver.cairo b/packages/token/src/tests/erc1155/test_dual1155_receiver.cairo index f02056f04..3c6e64c85 100644 --- a/packages/token/src/tests/erc1155/test_dual1155_receiver.cairo +++ b/packages/token/src/tests/erc1155/test_dual1155_receiver.cairo @@ -1,15 +1,15 @@ -use openzeppelin_utils::tests_utils::constants::{EMPTY_DATA, OPERATOR, OWNER, TOKEN_ID, TOKEN_VALUE}; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc1155::dual1155_receiver::{ +use openzeppelin_token::erc1155::dual1155_receiver::{ DualCaseERC1155Receiver, DualCaseERC1155ReceiverTrait }; -use openzeppelin::token::erc1155::interface::IERC1155_RECEIVER_ID; -use openzeppelin::token::erc1155::interface::{ +use openzeppelin_token::erc1155::interface::IERC1155_RECEIVER_ID; +use openzeppelin_token::erc1155::interface::{ IERC1155ReceiverCamelDispatcher, IERC1155ReceiverCamelDispatcherTrait }; -use openzeppelin::token::erc1155::interface::{ +use openzeppelin_token::erc1155::interface::{ IERC1155ReceiverDispatcher, IERC1155ReceiverDispatcherTrait }; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{EMPTY_DATA, OPERATOR, OWNER, TOKEN_ID, TOKEN_VALUE}; // // Setup diff --git a/packages/token/src/tests/erc1155/test_erc1155.cairo b/packages/token/src/tests/erc1155/test_erc1155.cairo index d707165e6..6c3db0ebf 100644 --- a/packages/token/src/tests/erc1155/test_erc1155.cairo +++ b/packages/token/src/tests/erc1155/test_erc1155.cairo @@ -13,10 +13,6 @@ use openzeppelin_utils::test_utils::constants::{ EMPTY_DATA, ZERO, OWNER, RECIPIENT, OPERATOR, OTHER, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 }; -use openzeppelin::token::erc1155::ERC1155Component::ERC1155CamelImpl; -use openzeppelin::token::erc1155::ERC1155Component::{ERC1155Impl, InternalImpl}; -use openzeppelin::token::erc1155::ERC1155Component; -use openzeppelin::token::erc1155; use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::ContractAddress; diff --git a/packages/token/src/tests/erc20/common.cairo b/packages/token/src/tests/erc20/common.cairo index 888017a95..f3a0d58bf 100644 --- a/packages/token/src/tests/erc20/common.cairo +++ b/packages/token/src/tests/erc20/common.cairo @@ -1,11 +1,11 @@ -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin::token::erc20::ERC20Component::{Approval, Transfer}; -use openzeppelin::token::erc20::ERC20Component; +use openzeppelin_token::erc20::ERC20Component::{Approval, Transfer}; +use openzeppelin_token::erc20::ERC20Component; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::EventSpy; use starknet::ContractAddress; #[generate_trait] -pub(crate) impl ERC20SpyHelpersImpl of ERC20SpyHelpers { +pub impl ERC20SpyHelpersImpl of ERC20SpyHelpers { fn assert_event_approval( ref self: EventSpy, contract: ContractAddress, diff --git a/packages/token/src/tests/erc20/test_dual20.cairo b/packages/token/src/tests/erc20/test_dual20.cairo index a38a5463f..8edc96a23 100644 --- a/packages/token/src/tests/erc20/test_dual20.cairo +++ b/packages/token/src/tests/erc20/test_dual20.cairo @@ -1,11 +1,11 @@ -use openzeppelin_utils::tests_utils::constants::{ +use openzeppelin_token::erc20::dual20::{DualCaseERC20, DualCaseERC20Trait}; +use openzeppelin_token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; +use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{ OWNER, RECIPIENT, SPENDER, OPERATOR, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE }; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc20::dual20::{DualCaseERC20, DualCaseERC20Trait}; -use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin_utils::serde::SerializedAppend; use snforge_std::{test_address, start_cheat_caller_address}; // diff --git a/packages/token/src/tests/erc20/test_erc20.cairo b/packages/token/src/tests/erc20/test_erc20.cairo index 9e309c397..b87c72e8b 100644 --- a/packages/token/src/tests/erc20/test_erc20.cairo +++ b/packages/token/src/tests/erc20/test_erc20.cairo @@ -8,9 +8,6 @@ use openzeppelin_utils::serde::SerializedAppend; use openzeppelin_utils::test_utils::constants::{ ZERO, OWNER, SPENDER, RECIPIENT, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE }; -use openzeppelin::token::erc20::ERC20Component::{ERC20CamelOnlyImpl, ERC20Impl}; -use openzeppelin::token::erc20::ERC20Component::{ERC20MetadataImpl, InternalImpl}; -use openzeppelin::token::erc20::ERC20Component; use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::ContractAddress; diff --git a/packages/token/src/tests/erc20/test_erc20_votes.cairo b/packages/token/src/tests/erc20/test_erc20_votes.cairo index b6533a88e..ec4c64e95 100644 --- a/packages/token/src/tests/erc20/test_erc20_votes.cairo +++ b/packages/token/src/tests/erc20/test_erc20_votes.cairo @@ -1,20 +1,20 @@ use core::integer::BoundedInt; use core::num::traits::Zero; -use openzeppelin::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock::SNIP12MetadataImpl; -use openzeppelin::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock; -use openzeppelin_utils::tests_utils::constants::{SUPPLY, ZERO, OWNER, RECIPIENT}; -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc20::ERC20Component::InternalImpl as ERC20Impl; -use openzeppelin::token::erc20::extensions::ERC20VotesComponent::{ +use openzeppelin_token::erc20::ERC20Component::InternalImpl as ERC20Impl; +use openzeppelin_token::erc20::extensions::ERC20VotesComponent::{ DelegateChanged, DelegateVotesChanged }; -use openzeppelin::token::erc20::extensions::ERC20VotesComponent::{ERC20VotesImpl, InternalImpl}; -use openzeppelin::token::erc20::extensions::ERC20VotesComponent; -use openzeppelin::token::erc20::extensions::erc20_votes::Delegation; +use openzeppelin_token::erc20::extensions::ERC20VotesComponent::{ERC20VotesImpl, InternalImpl}; +use openzeppelin_token::erc20::extensions::ERC20VotesComponent; +use openzeppelin_token::erc20::extensions::erc20_votes::Delegation; +use openzeppelin_token::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock::SNIP12MetadataImpl; +use openzeppelin_token::tests::mocks::erc20_votes_mocks::DualCaseERC20VotesMock; use openzeppelin_utils::cryptography::snip12::OffchainMessageHash; use openzeppelin_utils::serde::SerializedAppend; use openzeppelin_utils::structs::checkpoint::{Checkpoint, TraceTrait}; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{SUPPLY, ZERO, OWNER, RECIPIENT}; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::signature::KeyPairTrait; use snforge_std::signature::stark_curve::{StarkCurveKeyPairImpl, StarkCurveSignerImpl}; use snforge_std::{ @@ -24,7 +24,6 @@ use snforge_std::{ use snforge_std::{EventSpy, EventSpyAssertionsTrait}; use starknet::ContractAddress; use starknet::contract_address_const; -use starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; // // Setup diff --git a/packages/token/src/tests/erc721.cairo b/packages/token/src/tests/erc721.cairo index 7edd2f96d..27cc79035 100644 --- a/packages/token/src/tests/erc721.cairo +++ b/packages/token/src/tests/erc721.cairo @@ -6,4 +6,5 @@ mod test_dual721; mod test_dual721_receiver; #[cfg(test)] mod test_erc721; +#[cfg(test)] mod test_erc721_receiver; diff --git a/packages/token/src/tests/erc721/common.cairo b/packages/token/src/tests/erc721/common.cairo index c1e7382d8..f35fe41fb 100644 --- a/packages/token/src/tests/erc721/common.cairo +++ b/packages/token/src/tests/erc721/common.cairo @@ -1,11 +1,11 @@ -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin::token::erc721::ERC721Component::{Approval, ApprovalForAll, Transfer}; -use openzeppelin::token::erc721::ERC721Component; +use openzeppelin_token::erc721::ERC721Component::{Approval, ApprovalForAll, Transfer}; +use openzeppelin_token::erc721::ERC721Component; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::EventSpy; use starknet::ContractAddress; #[generate_trait] -pub(crate) impl ERC721SpyHelpersImpl of ERC721SpyHelpers { +pub impl ERC721SpyHelpersImpl of ERC721SpyHelpers { fn assert_event_approval_for_all( ref self: EventSpy, contract: ContractAddress, diff --git a/packages/token/src/tests/erc721/test_dual721.cairo b/packages/token/src/tests/erc721/test_dual721.cairo index 32c77b54e..04dd336a8 100644 --- a/packages/token/src/tests/erc721/test_dual721.cairo +++ b/packages/token/src/tests/erc721/test_dual721.cairo @@ -1,14 +1,14 @@ -use openzeppelin_utils::tests_utils::constants::{ - DATA, OWNER, RECIPIENT, SPENDER, OPERATOR, NAME, SYMBOL, BASE_URI, TOKEN_ID -}; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc721::dual721::{DualCaseERC721, DualCaseERC721Trait}; -use openzeppelin::token::erc721::interface::IERC721_ID; -use openzeppelin::token::erc721::interface::{ +use openzeppelin_token::erc721::dual721::{DualCaseERC721, DualCaseERC721Trait}; +use openzeppelin_token::erc721::interface::IERC721_ID; +use openzeppelin_token::erc721::interface::{ IERC721CamelOnlyDispatcher, IERC721CamelOnlyDispatcherTrait }; -use openzeppelin::token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; +use openzeppelin_token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{ + DATA, OWNER, RECIPIENT, SPENDER, OPERATOR, NAME, SYMBOL, BASE_URI, TOKEN_ID +}; use snforge_std::{test_address, start_cheat_caller_address}; use starknet::ContractAddress; diff --git a/packages/token/src/tests/erc721/test_dual721_receiver.cairo b/packages/token/src/tests/erc721/test_dual721_receiver.cairo index a9e13288b..a4be9f3a1 100644 --- a/packages/token/src/tests/erc721/test_dual721_receiver.cairo +++ b/packages/token/src/tests/erc721/test_dual721_receiver.cairo @@ -1,6 +1,4 @@ -use openzeppelin_utils::tests_utils::constants::{DATA, OPERATOR, OWNER, TOKEN_ID}; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc721::dual721_receiver::{ +use openzeppelin_token::erc721::dual721_receiver::{ DualCaseERC721Receiver, DualCaseERC721ReceiverTrait }; use openzeppelin_token::erc721::interface::IERC721_RECEIVER_ID; @@ -17,6 +15,7 @@ use openzeppelin_token::tests::mocks::erc721_receiver_mocks::{ SnakeERC721ReceiverMock, SnakeERC721ReceiverPanicMock }; use openzeppelin_token::tests::mocks::non_implementing_mock::NonImplementingMock; +use openzeppelin_utils::test_utils as utils; use openzeppelin_utils::test_utils::constants::{DATA, OPERATOR, OWNER, TOKEN_ID}; // diff --git a/packages/token/src/tests/erc721/test_erc721.cairo b/packages/token/src/tests/erc721/test_erc721.cairo index 5bf228723..4ce77d621 100644 --- a/packages/token/src/tests/erc721/test_erc721.cairo +++ b/packages/token/src/tests/erc721/test_erc721.cairo @@ -1,19 +1,18 @@ use core::num::traits::Zero; -use openzeppelin_access::src5::SRC5Component::SRC5Impl; -use openzeppelin::tests::mocks::erc721_mocks::DualCaseERC721Mock; -use openzeppelin_utils::tests_utils::constants::{ +use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; +use openzeppelin_token::erc721::ERC721Component::{ERC721Impl, ERC721CamelOnlyImpl}; +use openzeppelin_token::erc721::ERC721Component::{ERC721MetadataImpl, InternalImpl}; +use openzeppelin_token::erc721::ERC721Component; +use openzeppelin_token::erc721; +use openzeppelin_token::tests::mocks::erc721_mocks::DualCaseERC721Mock; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::test_utils::constants::{ DATA, ZERO, OWNER, CALLER, RECIPIENT, SPENDER, OPERATOR, OTHER, NAME, SYMBOL, TOKEN_ID, TOKEN_ID_2, PUBKEY, BASE_URI, BASE_URI_2 }; -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin_utils::tests_utils as utils; -use openzeppelin::token::erc721::ERC721Component::{ERC721Impl, ERC721CamelOnlyImpl}; -use openzeppelin::token::erc721::ERC721Component::{ERC721MetadataImpl, InternalImpl}; -use openzeppelin::token::erc721::ERC721Component; -use openzeppelin::token::erc721; +use openzeppelin_utils::test_utils::events::EventSpyExt; use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::ContractAddress; -use starknet::storage::StorageMapMemberAccessTrait; use super::common::ERC721SpyHelpers; @@ -979,6 +978,7 @@ fn test_safeTransferFrom_approved_camel() { let receiver = setup_camel_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); + let mut spy = spy_events(); assert_state_before_transfer(owner, receiver, token_id); @@ -1064,6 +1064,7 @@ fn test_safeTransferFrom_approved_for_all_camel() { let receiver = setup_camel_receiver(); let token_id = TOKEN_ID; let owner = OWNER(); + let mut spy = spy_events(); assert_state_before_transfer(owner, receiver, token_id); diff --git a/packages/token/src/tests/erc721/test_erc721_receiver.cairo b/packages/token/src/tests/erc721/test_erc721_receiver.cairo index 3c53a4ca6..90fb42f3a 100644 --- a/packages/token/src/tests/erc721/test_erc721_receiver.cairo +++ b/packages/token/src/tests/erc721/test_erc721_receiver.cairo @@ -1,12 +1,11 @@ -use openzeppelin_access::interface::ISRC5_ID; -use openzeppelin_access::src5::SRC5Component::SRC5Impl; -use openzeppelin::tests::mocks::erc721_receiver_mocks::DualCaseERC721ReceiverMock; -use openzeppelin_utils::tests_utils::constants::{OWNER, OPERATOR, TOKEN_ID}; -use openzeppelin::token::erc721::ERC721ReceiverComponent::{ +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; +use openzeppelin_token::erc721::ERC721ReceiverComponent::{ ERC721ReceiverImpl, ERC721ReceiverCamelImpl, InternalImpl }; use openzeppelin_token::erc721::interface::IERC721_RECEIVER_ID; -use openzeppelin_utils::test_utils::constants::{OWNER, OPERATOR, TOKEN_ID, DATA}; +use openzeppelin_token::tests::mocks::erc721_receiver_mocks::DualCaseERC721ReceiverMock; +use openzeppelin_utils::test_utils::constants::{OWNER, OPERATOR, TOKEN_ID}; fn STATE() -> DualCaseERC721ReceiverMock::ContractState { DualCaseERC721ReceiverMock::contract_state_for_testing() diff --git a/packages/upgrades/Scarb.toml b/packages/upgrades/Scarb.toml index 0a14a4ebc..8e751d426 100644 --- a/packages/upgrades/Scarb.toml +++ b/packages/upgrades/Scarb.toml @@ -18,7 +18,14 @@ fmt.workspace = true [dependencies] starknet.workspace = true +openzeppelin_utils = { path = "../utils" } [dev-dependencies] -cairo_test.workspace = true -openzeppelin_utils = { path = "../utils" } +snforge_std.workspace = true + +[lib] + +[[target.starknet-contract]] +allowed-libfuncs-list.name = "experimental" +sierra = true +casm = false diff --git a/packages/upgrades/src/tests/common.cairo b/packages/upgrades/src/tests/common.cairo index f8771e460..e5fe93100 100644 --- a/packages/upgrades/src/tests/common.cairo +++ b/packages/upgrades/src/tests/common.cairo @@ -1,16 +1,20 @@ use openzeppelin_upgrades::UpgradeableComponent::Upgraded; use openzeppelin_upgrades::UpgradeableComponent; -use openzeppelin_utils::test_utils::constants::ZERO; -use openzeppelin_utils::test_utils; +use openzeppelin_utils::test_utils::events::EventSpyExt; +use snforge_std::{EventSpy, EventSpyAssertionsTrait}; use starknet::{ContractAddress, ClassHash}; -pub fn assert_event_upgraded(contract: ContractAddress, class_hash: ClassHash) { - let event = test_utils::pop_log::(contract).unwrap(); - let expected = UpgradeableComponent::Event::Upgraded(Upgraded { class_hash }); - assert!(event == expected); -} +#[generate_trait] +pub impl UpgradeableSpyHelpersImpl of UpgradeableSpyHelpers { + fn assert_event_upgraded(ref self: EventSpy, contract: ContractAddress, class_hash: ClassHash) { + let expected = UpgradeableComponent::Event::Upgraded(Upgraded { class_hash }); + self.assert_emitted_single(contract, expected); + } -pub fn assert_only_event_upgraded(contract: ContractAddress, class_hash: ClassHash) { - assert_event_upgraded(contract, class_hash); - test_utils::assert_no_events_left(ZERO()); + fn assert_only_event_upgraded( + ref self: EventSpy, contract: ContractAddress, class_hash: ClassHash + ) { + self.assert_event_upgraded(contract, class_hash); + self.assert_no_events_left_from(contract); + } } diff --git a/packages/upgrades/src/tests/test_upgradeable.cairo b/packages/upgrades/src/tests/test_upgradeable.cairo index d0a6073ce..c976ce1cc 100644 --- a/packages/upgrades/src/tests/test_upgradeable.cairo +++ b/packages/upgrades/src/tests/test_upgradeable.cairo @@ -1,9 +1,13 @@ -use openzeppelin::tests::mocks::upgrades_mocks::{IUpgradesV1Dispatcher, IUpgradesV1DispatcherTrait}; -use openzeppelin::tests::mocks::upgrades_mocks::{IUpgradesV2Dispatcher, IUpgradesV2DispatcherTrait}; -use openzeppelin_utils::tests_utils::constants::{CLASS_HASH_ZERO, ZERO, FELT_VALUE as VALUE}; -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin_utils::tests_utils::{declare_class, deploy}; -use openzeppelin::upgrades::UpgradeableComponent; +use openzeppelin_upgrades::UpgradeableComponent; +use openzeppelin_upgrades::tests::mocks::upgrades_mocks::{ + IUpgradesV1Dispatcher, IUpgradesV1DispatcherTrait +}; +use openzeppelin_upgrades::tests::mocks::upgrades_mocks::{ + IUpgradesV2Dispatcher, IUpgradesV2DispatcherTrait +}; +use openzeppelin_utils::test_utils::constants::{CLASS_HASH_ZERO, ZERO, FELT_VALUE as VALUE}; +use openzeppelin_utils::test_utils::events::EventSpyExt; +use openzeppelin_utils::test_utils::{declare_class, deploy}; use snforge_std::{spy_events, ContractClass}; use super::common::UpgradeableSpyHelpers; diff --git a/packages/utils/Scarb.toml b/packages/utils/Scarb.toml index a83d99966..dbc349820 100644 --- a/packages/utils/Scarb.toml +++ b/packages/utils/Scarb.toml @@ -18,6 +18,11 @@ fmt.workspace = true [dependencies] starknet.workspace = true +snforge_std.workspace = true -[dev-dependencies] -cairo_test.workspace = true +[lib] + +[[target.starknet-contract]] +allowed-libfuncs-list.name = "experimental" +sierra = true +casm = false diff --git a/packages/utils/src/test_utils.cairo b/packages/utils/src/test_utils.cairo index 597fa9659..c2b8b42f8 100644 --- a/packages/utils/src/test_utils.cairo +++ b/packages/utils/src/test_utils.cairo @@ -1,5 +1,5 @@ pub mod common; -pub(crate) mod constants; +pub mod constants; pub mod deployment; pub mod events; pub mod signing; diff --git a/src/tests/utils/common.cairo b/packages/utils/src/test_utils/common.cairo similarity index 100% rename from src/tests/utils/common.cairo rename to packages/utils/src/test_utils/common.cairo diff --git a/packages/utils/src/test_utils/constants.cairo b/packages/utils/src/test_utils/constants.cairo index 8e2d02552..b72c96c44 100644 --- a/packages/utils/src/test_utils/constants.cairo +++ b/packages/utils/src/test_utils/constants.cairo @@ -10,6 +10,7 @@ pub type EthPublicKey = starknet::secp256k1::Secp256k1Point; pub const DECIMALS: u8 = 18_u8; pub const SUPPLY: u256 = 2000; pub const VALUE: u256 = 300; +pub const FELT_VALUE: felt252 = 'FELT_VALUE'; pub const ROLE: felt252 = 'ROLE'; pub const OTHER_ROLE: felt252 = 'OTHER_ROLE'; pub const TOKEN_ID: u256 = 21; @@ -24,6 +25,7 @@ pub const SALT: felt252 = 'SALT'; pub const SUCCESS: felt252 = 123123; pub const FAILURE: felt252 = 456456; pub const MIN_TRANSACTION_VERSION: felt252 = 1; +pub const TRANSACTION_HASH: felt252 = 'TRANSACTION_HASH'; // 2**128 pub const QUERY_OFFSET: felt252 = 0x100000000000000000000000000000000; // QUERY_OFFSET + MIN_TRANSACTION_VERSION @@ -114,3 +116,33 @@ pub fn DATA(success: bool) -> Span { pub fn EMPTY_DATA() -> Span { array![].span() } + +// +// Signing keys +// + +pub mod secp256k1 { + use openzeppelin_utils::test_utils::signing::{Secp256k1KeyPair, get_secp256k1_keys_from}; + + pub fn KEY_PAIR() -> Secp256k1KeyPair { + let private_key = u256 { low: 'PRIVATE_LOW', high: 'PRIVATE_HIGH' }; + get_secp256k1_keys_from(private_key) + } + + pub fn KEY_PAIR_2() -> Secp256k1KeyPair { + let private_key = u256 { low: 'PRIVATE_LOW_2', high: 'PRIVATE_HIGH_2' }; + get_secp256k1_keys_from(private_key) + } +} + +pub mod stark { + use openzeppelin_utils::test_utils::signing::{StarkKeyPair, get_stark_keys_from}; + + pub fn KEY_PAIR() -> StarkKeyPair { + get_stark_keys_from('PRIVATE_KEY') + } + + pub fn KEY_PAIR_2() -> StarkKeyPair { + get_stark_keys_from('PRIVATE_KEY_2') + } +} diff --git a/src/tests/utils/deployment.cairo b/packages/utils/src/test_utils/deployment.cairo similarity index 96% rename from src/tests/utils/deployment.cairo rename to packages/utils/src/test_utils/deployment.cairo index 5f9917215..0113a9d60 100644 --- a/src/tests/utils/deployment.cairo +++ b/packages/utils/src/test_utils/deployment.cairo @@ -1,5 +1,5 @@ use core::starknet::SyscallResultTrait; -use openzeppelin_utils::tests_utils::panic_data_to_byte_array; +use openzeppelin_utils::test_utils::panic_data_to_byte_array; use snforge_std::{declare, get_class_hash, ContractClass, ContractClassTrait}; use snforge_std::{start_cheat_caller_address, stop_cheat_caller_address}; use starknet::ContractAddress; diff --git a/src/tests/utils/events.cairo b/packages/utils/src/test_utils/events.cairo similarity index 100% rename from src/tests/utils/events.cairo rename to packages/utils/src/test_utils/events.cairo diff --git a/src/tests/utils/signing.cairo b/packages/utils/src/test_utils/signing.cairo similarity index 100% rename from src/tests/utils/signing.cairo rename to packages/utils/src/test_utils/signing.cairo diff --git a/packages/utils/src/tests/test_snip12.cairo b/packages/utils/src/tests/test_snip12.cairo index 2137a7f70..2511a8780 100644 --- a/packages/utils/src/tests/test_snip12.cairo +++ b/packages/utils/src/tests/test_snip12.cairo @@ -3,6 +3,7 @@ use core::poseidon::{PoseidonTrait, poseidon_hash_span}; use openzeppelin_utils::cryptography::snip12::{ STARKNET_DOMAIN_TYPE_HASH, StarknetDomain, StructHash, OffchainMessageHashImpl, SNIP12Metadata }; +use openzeppelin_utils::test_utils::constants::{OWNER, RECIPIENT}; use snforge_std::{start_cheat_chain_id, test_address}; use starknet::ContractAddress; diff --git a/src/tests.cairo b/src/tests.cairo deleted file mode 100644 index fab03b247..000000000 --- a/src/tests.cairo +++ /dev/null @@ -1,19 +0,0 @@ -#[cfg(test)] -mod access; -#[cfg(test)] -mod account; -#[cfg(test)] -mod cryptography; -#[cfg(test)] -mod introspection; -mod mocks; -#[cfg(test)] -mod presets; -#[cfg(test)] -mod security; -#[cfg(test)] -mod token; -#[cfg(test)] -mod upgrades; - -pub mod utils; diff --git a/src/tests/account/starknet/common.cairo b/src/tests/account/starknet/common.cairo deleted file mode 100644 index 21054270e..000000000 --- a/src/tests/account/starknet/common.cairo +++ /dev/null @@ -1,74 +0,0 @@ -use core::hash::{HashStateTrait, HashStateExTrait}; -use core::poseidon::PoseidonTrait; -use openzeppelin::account::AccountComponent::{OwnerAdded, OwnerRemoved}; -use openzeppelin::account::AccountComponent; -use openzeppelin_utils::tests_utils::constants::{NAME, SYMBOL, TRANSACTION_HASH}; -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin_utils::tests_utils::signing::StarkKeyPair; -use openzeppelin_utils::tests_utils; -use openzeppelin::token::erc20::interface::IERC20Dispatcher; -use openzeppelin_utils::serde::SerializedAppend; -use snforge_std::EventSpy; -use snforge_std::signature::stark_curve::StarkCurveSignerImpl; -use starknet::ContractAddress; - -#[derive(Drop)] -pub(crate) struct SignedTransactionData { - pub(crate) tx_hash: felt252, - pub(crate) r: felt252, - pub(crate) s: felt252 -} - -pub(crate) fn SIGNED_TX_DATA(key_pair: StarkKeyPair) -> SignedTransactionData { - let tx_hash = TRANSACTION_HASH; - let (r, s) = key_pair.sign(tx_hash).unwrap(); - SignedTransactionData { tx_hash, r, s } -} - -pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { - let mut calldata = array![]; - calldata.append_serde(NAME()); - calldata.append_serde(SYMBOL()); - calldata.append_serde(initial_supply); - calldata.append_serde(recipient); - - let address = utils::declare_and_deploy("DualCaseERC20Mock", calldata); - IERC20Dispatcher { contract_address: address } -} - -pub(crate) fn get_accept_ownership_signature( - account_address: ContractAddress, current_public_key: felt252, new_key_pair: StarkKeyPair -) -> Span { - let msg_hash = PoseidonTrait::new() - .update_with('StarkNet Message') - .update_with('accept_ownership') - .update_with(account_address) - .update_with(current_public_key) - .finalize(); - let (sig_r, sig_s) = new_key_pair.sign(msg_hash).unwrap(); - array![sig_r, sig_s].span() -} - -#[generate_trait] -pub(crate) impl AccountSpyHelpersImpl of AccountSpyHelpers { - fn assert_event_owner_removed( - ref self: EventSpy, contract: ContractAddress, removed_owner_guid: felt252 - ) { - let expected = AccountComponent::Event::OwnerRemoved(OwnerRemoved { removed_owner_guid }); - self.assert_emitted_single(contract, expected); - } - - fn assert_event_owner_added( - ref self: EventSpy, contract: ContractAddress, new_owner_guid: felt252 - ) { - let expected = AccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_owner_added( - ref self: EventSpy, contract: ContractAddress, new_owner_guid: felt252 - ) { - self.assert_event_owner_added(contract, new_owner_guid); - self.assert_no_events_left_from(contract); - } -} diff --git a/src/tests/upgrades/common.cairo b/src/tests/upgrades/common.cairo deleted file mode 100644 index 2f2ecc68a..000000000 --- a/src/tests/upgrades/common.cairo +++ /dev/null @@ -1,20 +0,0 @@ -use openzeppelin_utils::tests_utils::events::EventSpyExt; -use openzeppelin::upgrades::UpgradeableComponent::Upgraded; -use openzeppelin::upgrades::UpgradeableComponent; -use snforge_std::{EventSpy, EventSpyAssertionsTrait}; -use starknet::{ContractAddress, ClassHash}; - -#[generate_trait] -pub(crate) impl UpgradeableSpyHelpersImpl of UpgradeableSpyHelpers { - fn assert_event_upgraded(ref self: EventSpy, contract: ContractAddress, class_hash: ClassHash) { - let expected = UpgradeableComponent::Event::Upgraded(Upgraded { class_hash }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_upgraded( - ref self: EventSpy, contract: ContractAddress, class_hash: ClassHash - ) { - self.assert_event_upgraded(contract, class_hash); - self.assert_no_events_left_from(contract); - } -} diff --git a/src/tests/utils/constants.cairo b/src/tests/utils/constants.cairo deleted file mode 100644 index 17633f89c..000000000 --- a/src/tests/utils/constants.cairo +++ /dev/null @@ -1,148 +0,0 @@ -use openzeppelin::account::interface::EthPublicKey; -use starknet::ClassHash; -use starknet::ContractAddress; -use starknet::SyscallResultTrait; -use starknet::class_hash::class_hash_const; -use starknet::contract_address_const; -use starknet::secp256_trait::Secp256Trait; - -pub(crate) const DECIMALS: u8 = 18_u8; -pub(crate) const SUPPLY: u256 = 2000; -pub(crate) const VALUE: u256 = 300; -pub(crate) const FELT_VALUE: felt252 = 'FELT_VALUE'; -pub(crate) const ROLE: felt252 = 'ROLE'; -pub(crate) const OTHER_ROLE: felt252 = 'OTHER_ROLE'; -pub(crate) const TOKEN_ID: u256 = 21; -pub(crate) const TOKEN_ID_2: u256 = 121; -pub(crate) const TOKEN_VALUE: u256 = 42; -pub(crate) const TOKEN_VALUE_2: u256 = 142; -pub(crate) const PUBKEY: felt252 = 'PUBKEY'; -pub(crate) const NEW_PUBKEY: felt252 = - 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7; -pub(crate) const DAPP_NAME: felt252 = 'DAPP_NAME'; -pub(crate) const DAPP_VERSION: felt252 = 'DAPP_VERSION'; -pub(crate) const SALT: felt252 = 'SALT'; -pub(crate) const SUCCESS: felt252 = 123123; -pub(crate) const FAILURE: felt252 = 456456; -pub(crate) const MIN_TRANSACTION_VERSION: felt252 = 1; -pub(crate) const TRANSACTION_HASH: felt252 = 'TRANSACTION_HASH'; -// 2**128 -pub(crate) const QUERY_OFFSET: felt252 = 0x100000000000000000000000000000000; -// QUERY_OFFSET + MIN_TRANSACTION_VERSION -pub(crate) const QUERY_VERSION: felt252 = 0x100000000000000000000000000000001; - -pub(crate) fn NAME() -> ByteArray { - "NAME" -} - -pub(crate) fn SYMBOL() -> ByteArray { - "SYMBOL" -} - -pub(crate) fn BASE_URI() -> ByteArray { - "https://api.example.com/v1/" -} - -pub(crate) fn BASE_URI_2() -> ByteArray { - "https://api.example.com/v2/" -} - -pub(crate) fn ETH_PUBKEY() -> EthPublicKey { - Secp256Trait::secp256_ec_get_point_from_x_syscall(3, false).unwrap_syscall().unwrap() -} - -pub(crate) fn NEW_ETH_PUBKEY() -> EthPublicKey { - Secp256Trait::secp256_ec_get_point_from_x_syscall(4, false).unwrap_syscall().unwrap() -} - -pub(crate) fn ADMIN() -> ContractAddress { - contract_address_const::<'ADMIN'>() -} - -pub(crate) fn AUTHORIZED() -> ContractAddress { - contract_address_const::<'AUTHORIZED'>() -} - -pub(crate) fn ZERO() -> ContractAddress { - contract_address_const::<0>() -} - -pub(crate) fn CLASS_HASH_ZERO() -> ClassHash { - class_hash_const::<0>() -} - -pub(crate) fn CALLER() -> ContractAddress { - contract_address_const::<'CALLER'>() -} - -pub(crate) fn OWNER() -> ContractAddress { - contract_address_const::<'OWNER'>() -} - -pub(crate) fn NEW_OWNER() -> ContractAddress { - contract_address_const::<'NEW_OWNER'>() -} - -pub(crate) fn OTHER() -> ContractAddress { - contract_address_const::<'OTHER'>() -} - -pub(crate) fn OTHER_ADMIN() -> ContractAddress { - contract_address_const::<'OTHER_ADMIN'>() -} - -pub(crate) fn SPENDER() -> ContractAddress { - contract_address_const::<'SPENDER'>() -} - -pub(crate) fn RECIPIENT() -> ContractAddress { - contract_address_const::<'RECIPIENT'>() -} - -pub(crate) fn OPERATOR() -> ContractAddress { - contract_address_const::<'OPERATOR'>() -} - -pub(crate) fn DATA(success: bool) -> Span { - let mut data = array![]; - if success { - data.append(SUCCESS); - } else { - data.append(FAILURE); - } - data.span() -} - -pub(crate) fn EMPTY_DATA() -> Span { - array![].span() -} - -// -// Signing keys -// - -pub(crate) mod secp256k1 { - use openzeppelin_utils::tests_utils::signing::{Secp256k1KeyPair, get_secp256k1_keys_from}; - - pub(crate) fn KEY_PAIR() -> Secp256k1KeyPair { - let private_key = u256 { low: 'PRIVATE_LOW', high: 'PRIVATE_HIGH' }; - get_secp256k1_keys_from(private_key) - } - - pub(crate) fn KEY_PAIR_2() -> Secp256k1KeyPair { - let private_key = u256 { low: 'PRIVATE_LOW_2', high: 'PRIVATE_HIGH_2' }; - get_secp256k1_keys_from(private_key) - } -} - -pub(crate) mod stark { - use openzeppelin_utils::tests_utils::signing::{StarkKeyPair, get_stark_keys_from}; - - pub(crate) fn KEY_PAIR() -> StarkKeyPair { - get_stark_keys_from('PRIVATE_KEY') - } - - pub(crate) fn KEY_PAIR_2() -> StarkKeyPair { - get_stark_keys_from('PRIVATE_KEY_2') - } -} From 47ab176751811875508df0bfd02fc72f9c7c51c1 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Mon, 29 Jul 2024 13:33:21 +0200 Subject: [PATCH 28/45] fix: remaining tests --- .github/workflows/test.yml | 2 +- packages/introspection/src/lib.cairo | 1 - packages/introspection/src/tests.cairo | 1 + packages/presets/src/lib.cairo | 1 - packages/presets/src/tests.cairo | 7 +- packages/presets/src/tests/mocks.cairo | 2 + .../tests/mocks/erc1155_receiver_mocks.cairo | 197 ++++++++++++++++++ .../presets/src/tests/mocks/src5_mocks.cairo | 22 ++ packages/security/src/lib.cairo | 1 - packages/security/src/tests.cairo | 3 + packages/token/src/tests/mocks.cairo | 11 - 11 files changed, 232 insertions(+), 16 deletions(-) create mode 100644 packages/presets/src/tests/mocks/erc1155_receiver_mocks.cairo create mode 100644 packages/presets/src/tests/mocks/src5_mocks.cairo diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1c7023075..14c31c6d4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,4 +35,4 @@ jobs: - name: Cairo lint run: scarb fmt --check --workspace - name: Cairo test - run: snforge test + run: snforge test --workspace diff --git a/packages/introspection/src/lib.cairo b/packages/introspection/src/lib.cairo index 01a03e7d8..6134bb225 100644 --- a/packages/introspection/src/lib.cairo +++ b/packages/introspection/src/lib.cairo @@ -1,5 +1,4 @@ pub mod interface; pub mod src5; -#[cfg(test)] mod tests; diff --git a/packages/introspection/src/tests.cairo b/packages/introspection/src/tests.cairo index 0fe30300f..72a21d551 100644 --- a/packages/introspection/src/tests.cairo +++ b/packages/introspection/src/tests.cairo @@ -1,3 +1,4 @@ pub(crate) mod mocks; +#[cfg(test)] mod test_src5; diff --git a/packages/presets/src/lib.cairo b/packages/presets/src/lib.cairo index 38eab598a..55240efd2 100644 --- a/packages/presets/src/lib.cairo +++ b/packages/presets/src/lib.cairo @@ -5,7 +5,6 @@ pub mod erc721; pub mod eth_account; pub mod interfaces; -#[cfg(test)] mod tests; pub mod universal_deployer; diff --git a/packages/presets/src/tests.cairo b/packages/presets/src/tests.cairo index 057d56023..27c970734 100644 --- a/packages/presets/src/tests.cairo +++ b/packages/presets/src/tests.cairo @@ -1,8 +1,13 @@ -pub(crate) mod mocks; +mod mocks; // mod test_account; +#[cfg(test)] mod test_erc1155; +#[cfg(test)] mod test_erc20; +#[cfg(test)] mod test_erc721; +#[cfg(test)] mod test_eth_account; +#[cfg(test)] mod test_universal_deployer; diff --git a/packages/presets/src/tests/mocks.cairo b/packages/presets/src/tests/mocks.cairo index 61147b2a1..df1f54c6b 100644 --- a/packages/presets/src/tests/mocks.cairo +++ b/packages/presets/src/tests/mocks.cairo @@ -1,5 +1,7 @@ +pub(crate) mod src5_mocks; pub(crate) mod account_mocks; pub(crate) mod erc1155_mocks; +pub(crate) mod erc1155_receiver_mocks; pub(crate) mod erc20_mocks; pub(crate) mod erc721_mocks; pub(crate) mod erc721_receiver_mocks; diff --git a/packages/presets/src/tests/mocks/erc1155_receiver_mocks.cairo b/packages/presets/src/tests/mocks/erc1155_receiver_mocks.cairo new file mode 100644 index 000000000..34ec82649 --- /dev/null +++ b/packages/presets/src/tests/mocks/erc1155_receiver_mocks.cairo @@ -0,0 +1,197 @@ +use openzeppelin_utils::test_utils::constants::SUCCESS; + +#[starknet::contract] +pub(crate) mod DualCaseERC1155ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::ERC1155ReceiverComponent; + use starknet::ContractAddress; + + component!(path: SRC5Component, storage: src5, event: SRC5Event); + component!( + path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent + ); + + // ERC1155Receiver Mixin + #[abi(embed_v0)] + impl ERC1155ReceiverMixinImpl = + ERC1155ReceiverComponent::ERC1155ReceiverMixinImpl; + impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155_receiver: ERC1155ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc1155_receiver.initializer(); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC1155ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::ERC1155ReceiverComponent; + use starknet::ContractAddress; + + component!(path: SRC5Component, storage: src5, event: SRC5Event); + component!( + path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent + ); + + // ERC1155Receiver + #[abi(embed_v0)] + impl ERC1155ReceiverImpl = + ERC1155ReceiverComponent::ERC1155ReceiverImpl; + impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155_receiver: ERC1155ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc1155_receiver.initializer(); + } +} + +#[starknet::contract] +pub(crate) mod CamelERC1155ReceiverMock { + use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin_token::erc1155::ERC1155ReceiverComponent; + use starknet::ContractAddress; + + component!(path: SRC5Component, storage: src5, event: SRC5Event); + component!( + path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent + ); + + // ERC1155Receiver + #[abi(embed_v0)] + impl ERC1155ReceiverCamelImpl = + ERC1155ReceiverComponent::ERC1155ReceiverCamelImpl; + impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; + + // SRC5 + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + erc1155_receiver: ERC1155ReceiverComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event + } + + #[constructor] + fn constructor(ref self: ContractState) { + self.erc1155_receiver.initializer(); + } +} + +#[starknet::contract] +pub(crate) mod SnakeERC1155ReceiverPanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[external(v0)] + fn on_erc1155_received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + token_id: u256, + value: u256, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn on_erc1155_batch_received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenIds: Span, + values: Span, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } +} + +#[starknet::contract] +pub(crate) mod CamelERC1155ReceiverPanicMock { + use starknet::ContractAddress; + + #[storage] + struct Storage {} + + #[external(v0)] + fn onERC1155Received( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenId: u256, + value: u256, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } + + #[external(v0)] + fn onERC1155BatchReceived( + self: @ContractState, + operator: ContractAddress, + from: ContractAddress, + tokenIds: Span, + values: Span, + data: Span + ) -> felt252 { + panic!("Some error"); + 3 + } +} diff --git a/packages/presets/src/tests/mocks/src5_mocks.cairo b/packages/presets/src/tests/mocks/src5_mocks.cairo new file mode 100644 index 000000000..86e8c5167 --- /dev/null +++ b/packages/presets/src/tests/mocks/src5_mocks.cairo @@ -0,0 +1,22 @@ +#[starknet::contract] +pub(crate) mod SRC5Mock { + use openzeppelin_introspection::src5::SRC5Component; + + component!(path: SRC5Component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5Impl = SRC5Component::SRC5Impl; + + #[storage] + struct Storage { + #[substorage(v0)] + src5: SRC5Component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + SRC5Event: SRC5Component::Event + } +} diff --git a/packages/security/src/lib.cairo b/packages/security/src/lib.cairo index d479f9e05..f8ecbcedc 100644 --- a/packages/security/src/lib.cairo +++ b/packages/security/src/lib.cairo @@ -3,7 +3,6 @@ pub mod interface; pub mod pausable; pub mod reentrancyguard; -#[cfg(test)] mod tests; pub use initializable::InitializableComponent; diff --git a/packages/security/src/tests.cairo b/packages/security/src/tests.cairo index 59cc6e392..0f674d192 100644 --- a/packages/security/src/tests.cairo +++ b/packages/security/src/tests.cairo @@ -1,5 +1,8 @@ pub(crate) mod mocks; +#[cfg(test)] mod test_initializable; +#[cfg(test)] mod test_pausable; +#[cfg(test)] mod test_reentrancyguard; diff --git a/packages/token/src/tests/mocks.cairo b/packages/token/src/tests/mocks.cairo index d0d42421e..db8bcba0d 100644 --- a/packages/token/src/tests/mocks.cairo +++ b/packages/token/src/tests/mocks.cairo @@ -1,4 +1,3 @@ -// pub(crate) mod accesscontrol_mocks; pub(crate) mod account_mocks; pub(crate) mod erc1155_mocks; pub(crate) mod erc1155_receiver_mocks; @@ -6,15 +5,5 @@ pub(crate) mod erc20_mocks; pub(crate) mod erc20_votes_mocks; pub(crate) mod erc721_mocks; pub(crate) mod erc721_receiver_mocks; -// pub(crate) mod eth_account_mocks; -// pub(crate) mod initializable_mocks; pub(crate) mod non_implementing_mock; -// pub(crate) mod nonces_mocks; -// pub(crate) mod ownable_mocks; -// pub(crate) mod pausable_mocks; -// pub(crate) mod reentrancy_mocks; pub(crate) mod src5_mocks; -// pub(crate) mod timelock_mocks; -// pub(crate) mod upgrades_mocks; - - From cf80dd5f6f959f4f8b8825b94fc0e6746475b31b Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Mon, 29 Jul 2024 13:33:56 +0200 Subject: [PATCH 29/45] refactor: format files --- packages/presets/src/tests/mocks.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/presets/src/tests/mocks.cairo b/packages/presets/src/tests/mocks.cairo index df1f54c6b..2037caeeb 100644 --- a/packages/presets/src/tests/mocks.cairo +++ b/packages/presets/src/tests/mocks.cairo @@ -1,4 +1,3 @@ -pub(crate) mod src5_mocks; pub(crate) mod account_mocks; pub(crate) mod erc1155_mocks; pub(crate) mod erc1155_receiver_mocks; @@ -7,3 +6,4 @@ pub(crate) mod erc721_mocks; pub(crate) mod erc721_receiver_mocks; pub(crate) mod eth_account_mocks; pub(crate) mod non_implementing_mock; +pub(crate) mod src5_mocks; From 05b877d36ca2e116eca7123b0e05a37b9f44fe5d Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Mon, 29 Jul 2024 13:35:26 +0200 Subject: [PATCH 30/45] tmp: workflow update --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 14c31c6d4..69d42189c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,5 +34,8 @@ jobs: !PULL_REQUEST_TEMPLATE.md - name: Cairo lint run: scarb fmt --check --workspace + - name: Temporary USC manually install + run: | + curl -L https://raw.githubusercontent.com/software-mansion/universal-sierra-compiler/master/scripts/install.sh | sh -s -- v2.2.0-rc.1 - name: Cairo test run: snforge test --workspace From 0af0fff7113956b539aad401ca9e1e7e42fc802d Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Mon, 29 Jul 2024 13:51:33 +0200 Subject: [PATCH 31/45] feat: add entry to CHANGELOG and update README --- CHANGELOG.md | 10 ++++++++++ README.md | 10 +++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1ff29a21..761e3baa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - TimelockController component (#996) - HashCall implementation (#996) +- Separated package for each submodule (#1065) + - `openzeppelin_access` + - `openzeppelin_account` + - `openzeppelin_governance` + - `openzeppelin_introspection` + - `openzeppelin_presets` + - `openzeppelin_security` + - `openzeppelin_token` + - `openzeppelin_upgrades` + - `openzeppelin_utils` ### Changed diff --git a/README.md b/README.md index 390523ae6..82615cb0e 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,13 @@ Edit `scarb.toml` and add: openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.15.0-rc.0" } ``` +The previous example would import the entire library. we can also add each package as a separated dependency to improve the time for building by not including modules that won't be used: + +```toml +[dependencies] +openzeppelin_token = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.15.0-rc.0" } +``` + Build the project to download it: ```bash @@ -65,7 +72,8 @@ For example, this is how to write an ERC20-compliant contract: ```cairo #[starknet::contract] mod MyToken { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + // If only the token package was added as a dependency, use `openzeppelin_token::` instead + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); From 15d5fcb508b51374d6702c037ad362c7ca65357f Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Mon, 29 Jul 2024 14:05:31 +0200 Subject: [PATCH 32/45] doc: update imports --- Scarb.toml | 1 - docs/modules/ROOT/pages/access.adoc | 22 ++++---- docs/modules/ROOT/pages/accounts.adoc | 20 +++---- docs/modules/ROOT/pages/api/access.adoc | 6 +-- docs/modules/ROOT/pages/api/account.adoc | 10 ++-- docs/modules/ROOT/pages/api/erc1155.adoc | 14 ++--- docs/modules/ROOT/pages/api/erc20.adoc | 12 ++--- docs/modules/ROOT/pages/api/erc721.adoc | 14 ++--- docs/modules/ROOT/pages/api/governance.adoc | 2 +- .../modules/ROOT/pages/api/introspection.adoc | 4 +- docs/modules/ROOT/pages/api/security.adoc | 6 +-- docs/modules/ROOT/pages/api/udc.adoc | 4 +- docs/modules/ROOT/pages/api/upgrades.adoc | 4 +- docs/modules/ROOT/pages/api/utilities.adoc | 52 +++++++++---------- docs/modules/ROOT/pages/components.adoc | 22 ++++---- docs/modules/ROOT/pages/erc1155.adoc | 8 +-- docs/modules/ROOT/pages/erc20.adoc | 4 +- docs/modules/ROOT/pages/erc721.adoc | 8 +-- .../ROOT/pages/guides/erc20-supply.adoc | 4 +- docs/modules/ROOT/pages/guides/snip12.adoc | 20 +++---- .../ROOT/pages/guides/src5-migration.adoc | 6 +-- docs/modules/ROOT/pages/index.adoc | 2 +- docs/modules/ROOT/pages/interfaces.adoc | 4 +- docs/modules/ROOT/pages/introspection.adoc | 12 ++--- docs/modules/ROOT/pages/presets.adoc | 8 +-- docs/modules/ROOT/pages/security.adoc | 10 ++-- docs/modules/ROOT/pages/udc.adoc | 2 +- docs/modules/ROOT/pages/upgrades.adoc | 6 +-- 28 files changed, 143 insertions(+), 144 deletions(-) diff --git a/Scarb.toml b/Scarb.toml index 3a500bb60..9ac8ca001 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -37,7 +37,6 @@ keywords = [ [workspace.dependencies] starknet = "2.7.0-rc.3" -cairo_test = "2.7.0-rc.3" snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.26.0" } [dependencies] diff --git a/docs/modules/ROOT/pages/access.adoc b/docs/modules/ROOT/pages/access.adoc index 28f8fa8be..dbd987a1e 100644 --- a/docs/modules/ROOT/pages/access.adoc +++ b/docs/modules/ROOT/pages/access.adoc @@ -26,7 +26,7 @@ xref:/api/access.adoc#OwnableComponent-initializer[`initializer`] like this: ---- #[starknet::contract] mod MyContract { - use openzeppelin_access::ownable::OwnableComponent; + use openzeppelin::access::ownable::OwnableComponent; use starknet::ContractAddress; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); @@ -174,9 +174,9 @@ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE"); #[starknet::contract] mod MyContract { - use openzeppelin_access::accesscontrol::AccessControlComponent; - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::access::accesscontrol::AccessControlComponent; + use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; use super::MINTER_ROLE; @@ -265,9 +265,9 @@ const BURNER_ROLE: felt252 = selector!("BURNER_ROLE"); #[starknet::contract] mod MyContract { - use openzeppelin_access::accesscontrol::AccessControlComponent; - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::access::accesscontrol::AccessControlComponent; + use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; use super::{MINTER_ROLE, BURNER_ROLE}; @@ -387,10 +387,10 @@ const BURNER_ROLE: felt252 = selector!("BURNER_ROLE"); #[starknet::contract] mod MyContract { - use openzeppelin_access::accesscontrol::AccessControlComponent; - use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::access::accesscontrol::AccessControlComponent; + use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; + use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; use super::{MINTER_ROLE, BURNER_ROLE}; diff --git a/docs/modules/ROOT/pages/accounts.adoc b/docs/modules/ROOT/pages/accounts.adoc index 1cd0e8fed..bf064a01d 100644 --- a/docs/modules/ROOT/pages/accounts.adoc +++ b/docs/modules/ROOT/pages/accounts.adoc @@ -112,8 +112,8 @@ Constructing an account contract requires integrating both {account-component} a ---- #[starknet::contract(account)] mod MyAccount { - use openzeppelin_account::AccountComponent; - use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin::account::AccountComponent; + use openzeppelin::introspection::src5::SRC5Component; component!(path: AccountComponent, storage: account, event: AccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -202,9 +202,9 @@ Here’s an example of a basic contract: ---- #[starknet::contract(account)] mod MyEthAccount { - use openzeppelin_account::EthAccountComponent; - use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin::account::EthAccountComponent; + use openzeppelin::account::interface::EthPublicKey; + use openzeppelin::introspection::src5::SRC5Component; use starknet::ClassHash; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); @@ -303,8 +303,8 @@ First, let's take the example account we created before and deploy it: ```[,cairo] #[starknet::contract(account)] mod MyAccount { - use openzeppelin_account::AccountComponent; - use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin::account::AccountComponent; + use openzeppelin::introspection::src5::SRC5Component; component!(path: AccountComponent, storage: account, event: AccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -386,9 +386,9 @@ First, let's take the example account we created before and deploy it: ```[,cairo] #[starknet::contract(account)] mod MyEthAccount { - use openzeppelin_account::EthAccountComponent; - use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin::account::EthAccountComponent; + use openzeppelin::account::interface::EthPublicKey; + use openzeppelin::introspection::src5::SRC5Component; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); diff --git a/docs/modules/ROOT/pages/api/access.adoc b/docs/modules/ROOT/pages/api/access.adoc index 529187cac..1b362e728 100644 --- a/docs/modules/ROOT/pages/api/access.adoc +++ b/docs/modules/ROOT/pages/api/access.adoc @@ -23,7 +23,7 @@ assigned each to multiple accounts. === `++OwnableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/access/ownable/ownable.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_access::ownable::OwnableComponent; +use openzeppelin::access::ownable::OwnableComponent; ``` `Ownable` provides a basic access control mechanism where an account @@ -276,7 +276,7 @@ Emitted when the ownership is transferred. :RoleAdminChanged: xref:#IAccessControl-RoleAdminChanged[RoleAdminChanged] ```cairo -use openzeppelin_access::accesscontrol::interface::IAccessControl; +use openzeppelin::access::accesscontrol::interface::IAccessControl; ``` External interface of AccessControl. @@ -407,7 +407,7 @@ Emitted when `account` is revoked `role`. :revoke_role: xref:#AccessControlComponent-revoke_role[revoke_role] ```cairo -use openzeppelin_access::accesscontrol::AccessControlComponent; +use openzeppelin::access::accesscontrol::AccessControlComponent; ``` Component that allows contracts to implement role-based access control mechanisms. diff --git a/docs/modules/ROOT/pages/api/account.adoc b/docs/modules/ROOT/pages/api/account.adoc index 34bbc3681..c5ece578d 100644 --- a/docs/modules/ROOT/pages/api/account.adoc +++ b/docs/modules/ROOT/pages/api/account.adoc @@ -15,7 +15,7 @@ include::../utils/_common.adoc[] === `++ISRC6++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/account/interface.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_account::interface::ISRC6; +use openzeppelin::account::interface::ISRC6; ``` Interface of the SRC6 Standard Account as defined in the {snip6}. @@ -72,7 +72,7 @@ Returns the short string `'VALID'` if valid, otherwise it reverts. :starknet-curve: https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/stark-curve/[Starknet curve] ```cairo -use openzeppelin_account::AccountComponent; +use openzeppelin::account::AccountComponent; ``` Account component implementing xref:ISRC6[`ISRC6`] for signatures over the {starknet-curve}. @@ -322,7 +322,7 @@ Emitted when a `public_key` is removed. :secp256k1-curve: https://en.bitcoin.it/wiki/Secp256k1[Secp256k1 curve] ```cairo -use openzeppelin_account::eth_account::EthAccountComponent; +use openzeppelin::account::eth_account::EthAccountComponent; ``` Account component implementing xref:ISRC6[`ISRC6`] for signatures over the {secp256k1-curve}. @@ -573,7 +573,7 @@ Emitted when a `public_key` is removed. === `++AccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets/account.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_presets::AccountUpgradeable; +use openzeppelin::presets::AccountUpgradeable; ``` Upgradeable account contract leveraging xref:#AccountComponent[AccountComponent]. @@ -634,7 +634,7 @@ Requirements: === `++EthAccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets/eth_account.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_presets::EthAccountUpgradeable; +use openzeppelin::presets::EthAccountUpgradeable; ``` Upgradeable account contract leveraging xref:#EthAccountComponent[EthAccountComponent]. diff --git a/docs/modules/ROOT/pages/api/erc1155.adoc b/docs/modules/ROOT/pages/api/erc1155.adoc index b3196697e..20846ec46 100644 --- a/docs/modules/ROOT/pages/api/erc1155.adoc +++ b/docs/modules/ROOT/pages/api/erc1155.adoc @@ -20,7 +20,7 @@ TIP: For an overview of ERC1155, read our xref:erc1155.adoc[ERC1155 guide]. [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc1155::interface::IERC1155; +use openzeppelin::token::erc1155::interface::IERC1155; ``` Interface of the IERC1155 standard as defined in {eip1155}. @@ -130,7 +130,7 @@ Emitted when the token URI is updated to `value` for the `id` token. [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc1155::interface::IERC1155MetadataURI; +use openzeppelin::token::erc1155::interface::IERC1155MetadataURI; ``` Interface for the optional metadata function in {eip1155-metadata}[EIP1155]. @@ -160,7 +160,7 @@ Returns the Uniform Resource Identifier (URI) for the `token_id` token. [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc1155::ERC1155Component; +use openzeppelin::token::erc1155::ERC1155Component; ``` ERC1155 component implementing <> and <>. @@ -246,7 +246,7 @@ Hooks are functions which implementations can extend the functionality of the co using ERC1155Component is expected to provide an implementation of the ERC1155HooksTrait. For basic token contracts, an empty implementation with no logic must be provided. -TIP: You can use `openzeppelin_token::erc1155::ERC1155HooksEmptyImpl` which is already available as part of the library +TIP: You can use `openzeppelin::token::erc1155::ERC1155HooksEmptyImpl` which is already available as part of the library for this purpose. [.contract-item] @@ -547,7 +547,7 @@ See <>. [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc1155::interface::IERC1155Receiver; +use openzeppelin::token::erc1155::interface::IERC1155Receiver; ``` Interface for contracts that support receiving token transfers from `ERC1155` contracts. @@ -587,7 +587,7 @@ via <> by [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc1155::ERC1155ReceiverComponent; +use openzeppelin::token::erc1155::ERC1155ReceiverComponent; ``` ERC1155Receiver component implementing <>. @@ -663,7 +663,7 @@ Registers the `IERC1155Receiver` interface ID as supported through introspection === `++ERC1155Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets/erc1155.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_presets::ERC1155; +use openzeppelin::presets::ERC1155; ``` Upgradeable ERC1155 contract leveraging xref:#ERC1155Component[ERC1155Component]. diff --git a/docs/modules/ROOT/pages/api/erc20.adoc b/docs/modules/ROOT/pages/api/erc20.adoc index c4df315e5..05fe286fd 100644 --- a/docs/modules/ROOT/pages/api/erc20.adoc +++ b/docs/modules/ROOT/pages/api/erc20.adoc @@ -20,7 +20,7 @@ TIP: For an overview of ERC20, read our {erc20-guide}. [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc20::interface::IERC20; +use openzeppelin::token::erc20::interface::IERC20; ``` Interface of the IERC20 standard as defined in {eip20}. @@ -118,7 +118,7 @@ Emitted when the allowance of a `spender` for an `owner` is set. [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc20::interface::IERC20Metadata; +use openzeppelin::token::erc20::interface::IERC20Metadata; ``` Interface for the optional metadata functions in {eip20}. @@ -166,7 +166,7 @@ NOTE: This information is only used for _display_ purposes: it in no way affects [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc20::ERC20Component; +use openzeppelin::token::erc20::ERC20Component; ``` ERC20 component extending <> and <>. @@ -242,7 +242,7 @@ Hooks are functions which implementations can extend the functionality of the co using ERC20Component is expected to provide an implementation of the ERC20HooksTrait. For basic token contracts, an empty implementation with no logic must be provided. -TIP: You can use `openzeppelin_token::erc20::ERC20HooksEmptyImpl` which is already available as part of the library +TIP: You can use `openzeppelin::token::erc20::ERC20HooksEmptyImpl` which is already available as part of the library for this purpose. [.contract-item] @@ -463,7 +463,7 @@ See <>. === `++ERC20VotesComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc20/extensions/erc20_votes.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_token::extensions::ERC20VotesComponent; +use openzeppelin::token::extensions::ERC20VotesComponent; ``` :DelegateChanged: xref:ERC20VotesComponent-DelegateChanged[DelegateChanged] @@ -658,7 +658,7 @@ Emitted when `delegate` votes are updated from `previous_votes` to `new_votes`. === `++ERC20Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets/erc20.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_presets::ERC20Upgradeable; +use openzeppelin::presets::ERC20Upgradeable; ``` Upgradeable ERC20 contract leveraging xref:#ERC20Component[ERC20Component] with a fixed-supply mechanism for token distribution. diff --git a/docs/modules/ROOT/pages/api/erc721.adoc b/docs/modules/ROOT/pages/api/erc721.adoc index d671cae07..09ab75d29 100644 --- a/docs/modules/ROOT/pages/api/erc721.adoc +++ b/docs/modules/ROOT/pages/api/erc721.adoc @@ -20,7 +20,7 @@ TIP: For an overview of ERC721, read our xref:erc721.adoc[ERC721 guide]. [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc721::interface::IERC721; +use openzeppelin::token::erc721::interface::IERC721; ``` Interface of the IERC721 standard as defined in {eip721}. @@ -139,7 +139,7 @@ Emitted when `token_id` token is transferred from `from` to `to`. [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc721::interface::IERC721Metadata; +use openzeppelin::token::erc721::interface::IERC721Metadata; ``` Interface for the optional metadata functions in {eip721}. @@ -185,7 +185,7 @@ If the URI is not set for `token_id`, the return value will be an empty `ByteArr [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc721::ERC721Component; +use openzeppelin::token::erc721::ERC721Component; ``` ERC721 component implementing <> and <>. @@ -292,7 +292,7 @@ Hooks are functions which implementations can extend the functionality of the co using ERC721Component is expected to provide an implementation of the ERC721HooksTrait. For basic token contracts, an empty implementation with no logic must be provided. -TIP: You can use `openzeppelin_token::erc721::ERC721HooksEmptyImpl` which is already available as part of the library +TIP: You can use `openzeppelin::token::erc721::ERC721HooksEmptyImpl` which is already available as part of the library for this purpose. [.contract-item] @@ -697,7 +697,7 @@ See <>. [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc721::interface::IERC721Receiver; +use openzeppelin::token::erc721::interface::IERC721Receiver; ``` Interface for contracts that support receiving `safe_transfer_from` transfers. @@ -728,7 +728,7 @@ Whenever an IERC721 `token_id` token is transferred to this non-account contract [.hljs-theme-dark] ```cairo -use openzeppelin_token::erc721::ERC721ReceiverComponent; +use openzeppelin::token::erc721::ERC721ReceiverComponent; ``` ERC721Receiver component implementing <>. @@ -793,7 +793,7 @@ Registers the `IERC721Receiver` interface ID as supported through introspection. === `++ERC721Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets/erc721.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_presets::ERC721Upgradeable; +use openzeppelin::presets::ERC721Upgradeable; ``` Upgradeable ERC721 contract leveraging xref:#ERC721Component[ERC721Component]. diff --git a/docs/modules/ROOT/pages/api/governance.adoc b/docs/modules/ROOT/pages/api/governance.adoc index 59221fa3e..997815023 100644 --- a/docs/modules/ROOT/pages/api/governance.adoc +++ b/docs/modules/ROOT/pages/api/governance.adoc @@ -12,7 +12,7 @@ Reference of interfaces and utilities related to Governance. [.hljs-theme-dark] ```cairo -use openzeppelin_governance::utils::interfaces::IVotes; +use openzeppelin::governance::utils::interfaces::IVotes; ``` Common interface for Votes-enabled contracts. For an implementation example see diff --git a/docs/modules/ROOT/pages/api/introspection.adoc b/docs/modules/ROOT/pages/api/introspection.adoc index 6ff0e934a..77fb3b2b9 100644 --- a/docs/modules/ROOT/pages/api/introspection.adoc +++ b/docs/modules/ROOT/pages/api/introspection.adoc @@ -13,7 +13,7 @@ Reference of interfaces and utilities related to https://en.wikipedia.org/wiki/T === `++ISRC5++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/introspection/interface.cairo#L7[{github-icon},role=heading-link] ```cairo -use openzeppelin_introspection::interface::ISRC5; +use openzeppelin::introspection::interface::ISRC5; ``` Interface of the SRC5 Introspection Standard as defined in {snip5}. @@ -47,7 +47,7 @@ on how to compute this ID. === `++SRC5Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/introspection/src5.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_introspection::src5::SRC5Component; +use openzeppelin::introspection::src5::SRC5Component; ``` SRC5 component extending xref:ISRC5[`ISRC5`]. diff --git a/docs/modules/ROOT/pages/api/security.adoc b/docs/modules/ROOT/pages/api/security.adoc index 8e4a4ba3d..3a6558408 100644 --- a/docs/modules/ROOT/pages/api/security.adoc +++ b/docs/modules/ROOT/pages/api/security.adoc @@ -11,7 +11,7 @@ Reference of components, interfaces and utilities found in the library's `securi === `++InitializableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/security/initializable.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_security::InitializableComponent; +use openzeppelin::security::InitializableComponent; ``` Component enabling one-time initialization for contracts. @@ -64,7 +64,7 @@ Requirements: :Unpaused: xref:PausableComponent-Unpaused[Unpaused] ```cairo -use openzeppelin_security::PausableComponent; +use openzeppelin::security::PausableComponent; ``` Component to implement an emergency stop mechanism. @@ -166,7 +166,7 @@ Emitted when the contract is unpaused by `account`. === `++ReentrancyGuardComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/security/reentrancyguard.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_security::ReentrancyGuardComponent; +use openzeppelin::security::ReentrancyGuardComponent; ``` Component to help prevent reentrant calls. diff --git a/docs/modules/ROOT/pages/api/udc.adoc b/docs/modules/ROOT/pages/api/udc.adoc index 3f61021be..25c68731e 100644 --- a/docs/modules/ROOT/pages/api/udc.adoc +++ b/docs/modules/ROOT/pages/api/udc.adoc @@ -11,7 +11,7 @@ Reference of the Universal Deployer Contract (UDC) interface and preset. === `++IUniversalDeployer++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/utils/universal_deployer/interface.cairo#L7[{github-icon},role=heading-link] ```cairo -use openzeppelin_utils::interfaces::IUniversalDeployer; +use openzeppelin::utils::interfaces::IUniversalDeployer; ``` [.contract-index] @@ -54,7 +54,7 @@ Emitted when `deployer` deploys a contract through the Universal Deployer Contra === `++UniversalDeployer++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.10.0/src/presets/universal_deployer.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_presets::UniversalDeployer; +use openzeppelin::presets::UniversalDeployer; ``` The standard Universal Deployer Contract. diff --git a/docs/modules/ROOT/pages/api/upgrades.adoc b/docs/modules/ROOT/pages/api/upgrades.adoc index 18a3378cc..08060dd87 100644 --- a/docs/modules/ROOT/pages/api/upgrades.adoc +++ b/docs/modules/ROOT/pages/api/upgrades.adoc @@ -14,7 +14,7 @@ Reference of interfaces and utilities related to upgradeability. :Upgraded: xref:UpgradeableComponent-Upgraded[Upgraded] ```cairo -use openzeppelin_upgrades::interface::IUpgradeable; +use openzeppelin::upgrades::interface::IUpgradeable; ``` Interface of an upgradeable contract. @@ -41,7 +41,7 @@ NOTE: This function is usually protected by an xref:access.adoc[Access Control] === `++UpgradeableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/upgrades/upgradeable.cairo[{github-icon},role=heading-link] ```cairo -use openzeppelin_upgrades::upgradeable::UpgradeableComponent; +use openzeppelin::upgrades::upgradeable::UpgradeableComponent; ``` Upgradeable component. diff --git a/docs/modules/ROOT/pages/api/utilities.adoc b/docs/modules/ROOT/pages/api/utilities.adoc index 1566857fc..56c28ef5f 100644 --- a/docs/modules/ROOT/pages/api/utilities.adoc +++ b/docs/modules/ROOT/pages/api/utilities.adoc @@ -2,8 +2,8 @@ :deploy_syscall: link:https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#deploy[deploy_syscall] -The following documentation provides reasoning and examples for functions and constants found in `openzeppelin_utils` -and `use openzeppelin_utils::test_utils;`. +The following documentation provides reasoning and examples for functions and constants found in `openzeppelin::utils` +and `use openzeppelin::utils::test_utils;`. CAUTION: Expect this module to evolve (as it has already done). @@ -14,7 +14,7 @@ CAUTION: Expect this module to evolve (as it has already done). === `++utils++` ```cairo -use openzeppelin_utils; +use openzeppelin::utils; ``` Module containing core utilities of the library. @@ -77,8 +77,8 @@ casting and unwrapping the result multiple times. Usage example: ```cairo -use openzeppelin_utils::selectors; -use openzeppelin_utils::UnwrapAndCast; +use openzeppelin::utils::selectors; +use openzeppelin::utils::UnwrapAndCast; fn call_and_cast_to_bool(target: ContractAddress, args: Span) -> bool { try_selector_with_fallback( @@ -102,31 +102,31 @@ Note that it can be automatically casted to any type implementing the `Serde` tr [[utils-cryptography]] ==== `[.contract-item-name]#++cryptography++#` [.item-kind]#module# -See xref:#cryptography[`openzeppelin_utils::cryptography`]. +See xref:#cryptography[`openzeppelin::utils::cryptography`]. [.contract-item] [[utils-deployments]] ==== `[.contract-item-name]#++deployments++#` [.item-kind]#module# -See xref:#deployments[`openzeppelin_utils::deployments`]. +See xref:#deployments[`openzeppelin::utils::deployments`]. [.contract-item] [[utils-math]] ==== `[.contract-item-name]#++math++#` [.item-kind]#module# -See xref:#math[`openzeppelin_utils::math`]. +See xref:#math[`openzeppelin::utils::math`]. [.contract-item] [[utils-selectors]] ==== `[.contract-item-name]#++selectors++#` [.item-kind]#module# -See xref:#selectors[`openzeppelin_utils::selectors`]. +See xref:#selectors[`openzeppelin::utils::selectors`]. [.contract-item] [[utils-serde]] ==== `[.contract-item-name]#++serde++#` [.item-kind]#module# -See xref:#serde[`openzeppelin_utils::serde`]. +See xref:#serde[`openzeppelin::utils::serde`]. [.contract] [[cryptography]] @@ -135,7 +135,7 @@ See xref:#serde[`openzeppelin_utils::serde`]. :snip12: https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md[SNIP12] ```cairo -use openzeppelin_utils::cryptography; +use openzeppelin::utils::cryptography; ``` Module containing utilities related to cryptography. @@ -155,13 +155,13 @@ Module containing utilities related to cryptography. [[cryptography-nonces]] ==== `[.contract-item-name]#++nonces++#` [.item-kind]#module# -See xref:#NoncesComponent[`openzeppelin_utils::cryptography::nonces::NoncesComponent`]. +See xref:#NoncesComponent[`openzeppelin::utils::cryptography::nonces::NoncesComponent`]. [.contract-item] [[cryptography-snip12]] ==== `[.contract-item-name]#++snip12++#` [.item-kind]#module# -See xref:#snip12[`openzeppelin_utils::cryptography::snip12`]. +See xref:#snip12[`openzeppelin::utils::cryptography::snip12`]. [.contract] [[deployments]] @@ -170,7 +170,7 @@ See xref:#snip12[`openzeppelin_utils::cryptography::snip12`]. :udc-doc: xref:/udc.adoc[Universal Deployer Contract] ```cairo -use openzeppelin_utils::deployments; +use openzeppelin::utils::deployments; ``` Module containing utility functions for calculating contract addresses through {deploy_syscall} and the {udc-doc} (UDC). @@ -230,7 +230,7 @@ Origin-dependent deployments hash `salt` with `caller_address` (member of {deplo === `++math++` ```cairo -use openzeppelin_utils::math; +use openzeppelin::utils::math; ``` Module containing math utilities. @@ -258,7 +258,7 @@ NOTE: `T` is a generic value matching different numeric implementations. === `++selectors++` ```cairo -use openzeppelin_utils::selectors; +use openzeppelin::utils::selectors; ``` :selectors: https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/utils/selectors.cairo[selectors.cairo] @@ -271,7 +271,7 @@ To see the full list of selectors, see {selectors}. === `++serde++` ```cairo -use openzeppelin_utils::serde; +use openzeppelin::utils::serde; ``` Module containing utilities related to serialization and deserialization of Cairo data structures. @@ -296,7 +296,7 @@ implementing the `Serde` trait to a `felt252` buffer. Usage example: ```cairo -use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin::utils::serde::SerializedAppend; use starknet::ContractAddress; fn to_calldata(recipient: ContractAddress, amount: u256) -> Array { @@ -317,7 +317,7 @@ that implements the `Serde` trait. === `++NoncesComponent++` ```cairo -use openzeppelin_utils::cryptography::nonces::NoncesComponent; +use openzeppelin::utils::cryptography::nonces::NoncesComponent; ``` Simple component for managing nonces. @@ -372,7 +372,7 @@ Same as `use_nonce` but checking that `nonce` is the next valid one for `owner`. === `++snip12++` ```cairo -use openzeppelin_utils::snip12; +use openzeppelin::utils::snip12; ``` Supports on-chain generation of message hashes compliant with {snip12}. @@ -387,7 +387,7 @@ xref:/guides/snip12.adoc[SNIP12 and Typed Messages] guide. === `++utils++` ```cairo -use openzeppelin_utils::test_utils; +use openzeppelin::utils::test_utils; ``` Module containing utilities for testing the library. @@ -419,8 +419,8 @@ The `contract_address_salt` is always set to zero, and `deploy_from_zero` is set Usage example: ```cairo -use openzeppelin_presets::AccountUpgradeable; -use openzeppelin_utils::test_utils; +use openzeppelin::presets::AccountUpgradeable; +use openzeppelin::utils::test_utils; use starknet::ContractAddress; const PUBKEY: felt252 = 'PUBKEY'; @@ -459,9 +459,9 @@ Requirements: Usage example: ```cairo -use openzeppelin_utils::test_utils; -use openzeppelin_token::erc20::ERC20Component; -use openzeppelin_token::erc20::ERC20Component::Transfer; +use openzeppelin::utils::test_utils; +use openzeppelin::token::erc20::ERC20Component; +use openzeppelin::token::erc20::ERC20Component::Transfer; use starknet::ContractAddress; fn assert_emitted_event( diff --git a/docs/modules/ROOT/pages/components.adoc b/docs/modules/ROOT/pages/components.adoc index eb3051414..8d527b332 100644 --- a/docs/modules/ROOT/pages/components.adoc +++ b/docs/modules/ROOT/pages/components.adoc @@ -25,7 +25,7 @@ The contract should first import the component and declare it with the `componen #[starknet::contract] mod MyContract { // Import the component - use openzeppelin_security::InitializableComponent; + use openzeppelin::security::InitializableComponent; // Declare the component component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -40,7 +40,7 @@ Note that even if the component doesn't define any events, the compiler will sti ---- #[starknet::contract] mod MyContract { - use openzeppelin_security::InitializableComponent; + use openzeppelin::security::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -79,7 +79,7 @@ Integrating an implementation looks like this: [,cairo] ---- mod MyContract { - use openzeppelin_security::InitializableComponent; + use openzeppelin::security::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -99,7 +99,7 @@ A function on the contract level can expose it like this: ---- #[starknet::contract] mod MyContract { - use openzeppelin_security::InitializableComponent; + use openzeppelin::security::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -202,8 +202,8 @@ Here's a full example of an account contract that embeds the `AccountMixinImpl`: ---- #[starknet::contract] mod Account { - use openzeppelin_account::AccountComponent; - use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin::account::AccountComponent; + use openzeppelin::introspection::src5::SRC5Component; component!(path: AccountComponent, storage: account, event: AccountEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -298,7 +298,7 @@ Creating a contract with `AccessControlComponent` should look like this: #[starknet::contract] mod MyContract { use openzeppelinaccess::accesscontrol::AccessControlComponent; - use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin::introspection::src5::SRC5Component; component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -358,10 +358,10 @@ Here's the setup: ---- #[starknet::contract] mod ERC20Pausable { - use openzeppelin_security::pausable::PausableComponent; - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::security::pausable::PausableComponent; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; // Import the ERC20 interfaces to create custom implementations - use openzeppelin_token::erc20::interface::{IERC20, IERC20CamelOnly}; + use openzeppelin::token::erc20::interface::{IERC20, IERC20CamelOnly}; use starknet::ContractAddress; component!(path: PausableComponent, storage: pausable, event: PausableEvent); @@ -462,7 +462,7 @@ To do so, use the same syntax as calling an implementation method except replace ---- #[starknet::contract] mod MyContract { - use openzeppelin_security::InitializableComponent; + use openzeppelin::security::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); diff --git a/docs/modules/ROOT/pages/erc1155.adoc b/docs/modules/ROOT/pages/erc1155.adoc index 87f593660..78cdc322b 100644 --- a/docs/modules/ROOT/pages/erc1155.adoc +++ b/docs/modules/ROOT/pages/erc1155.adoc @@ -34,8 +34,8 @@ Here's an example of a basic contract: ---- #[starknet::contract] mod MyERC1155 { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin::token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); @@ -227,8 +227,8 @@ Here's an example of a simple token receiver contract: ---- #[starknet::contract] mod MyTokenReceiver { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::ERC1155ReceiverComponent; + use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin::token::erc1155::ERC1155ReceiverComponent; use starknet::ContractAddress; component!(path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent); diff --git a/docs/modules/ROOT/pages/erc20.adoc b/docs/modules/ROOT/pages/erc20.adoc index b73124f12..67d100db9 100644 --- a/docs/modules/ROOT/pages/erc20.adoc +++ b/docs/modules/ROOT/pages/erc20.adoc @@ -23,7 +23,7 @@ Here's what that looks like: ---- #[starknet::contract] mod MyToken { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); @@ -170,7 +170,7 @@ TIP: Note that we are not using the MixinImpl in this case, since we need to cus ---- #[starknet::contract] mod MyToken { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); diff --git a/docs/modules/ROOT/pages/erc721.adoc b/docs/modules/ROOT/pages/erc721.adoc index b4166ae12..33c250ebf 100644 --- a/docs/modules/ROOT/pages/erc721.adoc +++ b/docs/modules/ROOT/pages/erc721.adoc @@ -18,8 +18,8 @@ Here's an example of a basic contract: ---- #[starknet::contract] mod MyNFT { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; + use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC721Component, storage: erc721, event: ERC721Event); @@ -195,8 +195,8 @@ Here's an example of a simple token receiver contract: ---- #[starknet::contract] mod MyTokenReceiver { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::ERC721ReceiverComponent; + use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin::token::erc721::ERC721ReceiverComponent; use starknet::ContractAddress; component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); diff --git a/docs/modules/ROOT/pages/guides/erc20-supply.adoc b/docs/modules/ROOT/pages/guides/erc20-supply.adoc index 71543e19d..a1c86340e 100644 --- a/docs/modules/ROOT/pages/guides/erc20-supply.adoc +++ b/docs/modules/ROOT/pages/guides/erc20-supply.adoc @@ -15,7 +15,7 @@ We can achieve this by setting the token supply in the constructor which will ex ---- #[starknet::contract] mod MyToken { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); @@ -69,7 +69,7 @@ Let's make a few changes to the almighty `MyToken` contract and create a minting ---- #[starknet::contract] mod MyToken { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); diff --git a/docs/modules/ROOT/pages/guides/snip12.adoc b/docs/modules/ROOT/pages/guides/snip12.adoc index 18b8f5181..fb919e065 100644 --- a/docs/modules/ROOT/pages/guides/snip12.adoc +++ b/docs/modules/ROOT/pages/guides/snip12.adoc @@ -26,7 +26,7 @@ Note that some declarations are omitted for brevity. The full example will be av ---- #[starknet::contract] mod CustomERC20 { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); @@ -117,12 +117,12 @@ NOTE: In practice it's better to compute the type hash off-chain and hardcode it === 3. Implement the `StructHash` trait for the struct. -You can import the trait from: `openzeppelin_utils::snip12::StructHash`. And this implementation +You can import the trait from: `openzeppelin::utils::snip12::StructHash`. And this implementation is nothing more than the encoding of the message as defined in the {snip}. [,cairo] ---- -use openzeppelin_utils::snip12::StructHash; +use openzeppelin::utils::snip12::StructHash; use core::hash::HashStateExTrait; use hash::{HashStateTrait, Hash}; @@ -155,7 +155,7 @@ because the `chain_id` is obtained on-chain, and the `revision` is hardcoded to [,cairo] ---- -use openzeppelin_utils::snip12::SNIP12Metadata; +use openzeppelin::utils::snip12::SNIP12Metadata; impl SNIP12MetadataImpl of SNIP12Metadata { fn name() -> felt252 { 'DAPP_NAME' } @@ -169,7 +169,7 @@ the trait is not bounded to the ContractState, like this: [,cairo] ---- -use openzeppelin_utils::snip12::SNIP12Metadata; +use openzeppelin::utils::snip12::SNIP12Metadata; impl SNIP12MetadataImpl of SNIP12Metadata { fn name() -> felt252 { @@ -190,7 +190,7 @@ using the `get_message_hash` function. The implementation is already available a [,cairo] ---- -use openzeppelin_utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl}; +use openzeppelin::utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl}; use core::hash::HashStateExTrait; use hash::{HashStateTrait, Hash}; @@ -251,7 +251,7 @@ and the {nonces}[`NoncesComponent`] to handle nonces to prevent replay attacks. [,cairo] ---- -use openzeppelin_utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl}; +use openzeppelin::utils::snip12::{SNIP12Metadata, StructHash, OffchainMessageHashImpl}; use core::hash::HashStateExTrait; use hash::{HashStateTrait, Hash}; @@ -278,9 +278,9 @@ impl StructHashImpl of StructHash { #[starknet::contract] mod CustomERC20 { - use openzeppelin_account::dual_account::{DualCaseAccount, DualCaseAccountABI}; - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use openzeppelin_utils::cryptography::nonces::NoncesComponent; + use openzeppelin::account::dual_account::{DualCaseAccount, DualCaseAccountABI}; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::utils::cryptography::nonces::NoncesComponent; use starknet::ContractAddress; use super::{Message, OffchainMessageHashImpl, SNIP12Metadata}; diff --git a/docs/modules/ROOT/pages/guides/src5-migration.adoc b/docs/modules/ROOT/pages/guides/src5-migration.adoc index b12eb5239..5f97d5ee3 100644 --- a/docs/modules/ROOT/pages/guides/src5-migration.adoc +++ b/docs/modules/ROOT/pages/guides/src5-migration.adoc @@ -36,8 +36,8 @@ Here's the setup: ---- #[starknet::contract] mod MigratingContract { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_security::initializable::InitializableComponent; + use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin::security::initializable::InitializableComponent; component!(path: SRC5Component, storage: src5, event: SRC5Event); component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -84,7 +84,7 @@ The contract should implement an `InternalImpl` and add a function to register t ---- #[starknet::contract] mod MigratingContract { - use openzeppelin_token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID}; + use openzeppelin::token::erc721::interface::{IERC721_ID, IERC721_METADATA_ID}; (...) diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 910848493..41e20d036 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -71,7 +71,7 @@ Copy the code into `src/lib.cairo`. ---- #[starknet::contract] mod MyERC20Token { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); diff --git a/docs/modules/ROOT/pages/interfaces.adoc b/docs/modules/ROOT/pages/interfaces.adoc index 36462d458..d6e6a7fc8 100644 --- a/docs/modules/ROOT/pages/interfaces.adoc +++ b/docs/modules/ROOT/pages/interfaces.adoc @@ -7,13 +7,13 @@ This section describes the interfaces OpenZeppelin Contracts for Cairo offer, an Interfaces can be found in the module tree under the `interface` submodule, such as `token::erc20::interface`. For example: ```cairo -use openzeppelin_token::erc20::interface::IERC20; +use openzeppelin::token::erc20::interface::IERC20; ``` or ```cairo -use openzeppelin_token::erc20::dual20::DualCaseERC20; +use openzeppelin::token::erc20::dual20::DualCaseERC20; ``` NOTE: For simplicity, we'll use ERC20 as example but the same concepts apply to other modules. diff --git a/docs/modules/ROOT/pages/introspection.adoc b/docs/modules/ROOT/pages/introspection.adoc index 18a4f0bff..d4c9a4170 100644 --- a/docs/modules/ROOT/pages/introspection.adoc +++ b/docs/modules/ROOT/pages/introspection.adoc @@ -26,7 +26,7 @@ Here is an example contract: ---- #[starknet::contract] mod MyContract { - use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin::introspection::src5::SRC5Component; component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -82,8 +82,8 @@ For a contract to declare its support for a given interface, we recommend using ---- #[starknet::contract] mod MyContract { - use openzeppelin_account::interface; - use openzeppelin_introspection::src5::SRC5Component; + use openzeppelin::account::interface; + use openzeppelin::introspection::src5::SRC5Component; component!(path: SRC5Component, storage: src5, event: SRC5Event); @@ -122,9 +122,9 @@ Use the `supports_interface` function to query a contract's support for a given ---- #[starknet::contract] mod MyContract { - use openzeppelin_account::interface; - use openzeppelin_introspection::interface::ISRC5DispatcherTrait; - use openzeppelin_introspection::interface::ISRC5Dispatcher; + use openzeppelin::account::interface; + use openzeppelin::introspection::interface::ISRC5DispatcherTrait; + use openzeppelin::introspection::interface::ISRC5Dispatcher; use starknet::ContractAddress; #[storage] diff --git a/docs/modules/ROOT/pages/presets.adoc b/docs/modules/ROOT/pages/presets.adoc index 18f1e02d2..3f56743f1 100644 --- a/docs/modules/ROOT/pages/presets.adoc +++ b/docs/modules/ROOT/pages/presets.adoc @@ -76,10 +76,10 @@ Copy the target preset contract from the {presets_dir} and paste it in the new p #[starknet::contract] mod ERC20Upgradeable { - use openzeppelin_access::ownable::OwnableComponent; - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use openzeppelin_upgrades::UpgradeableComponent; - use openzeppelin_upgrades::interface::IUpgradeable; + use openzeppelin::access::ownable::OwnableComponent; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; + use openzeppelin::upgrades::UpgradeableComponent; + use openzeppelin::upgrades::interface::IUpgradeable; use starknet::{ContractAddress, ClassHash}; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); diff --git a/docs/modules/ROOT/pages/security.adoc b/docs/modules/ROOT/pages/security.adoc index b3d44c1ae..9ccfe9c1a 100644 --- a/docs/modules/ROOT/pages/security.adoc +++ b/docs/modules/ROOT/pages/security.adoc @@ -1,6 +1,6 @@ = Security -The following documentation provides context, reasoning, and examples of modules found under `openzeppelin_security`. +The following documentation provides context, reasoning, and examples of modules found under `openzeppelin::security`. CAUTION: Expect these modules to evolve. @@ -18,7 +18,7 @@ You can use the component in your contracts like this: ---- #[starknet::contract] mod MyInitializableContract { - use openzeppelin_security::InitializableComponent; + use openzeppelin::security::InitializableComponent; component!(path: InitializableComponent, storage: initializable, event: InitializableEvent); @@ -82,8 +82,8 @@ For example (using the xref:api/access.adoc#OwnableComponent[Ownable] component ---- #[starknet::contract] mod MyPausableContract { - use openzeppelin_access::ownable::OwnableComponent; - use openzeppelin_security::PausableComponent; + use openzeppelin::access::ownable::OwnableComponent; + use openzeppelin::security::PausableComponent; use starknet::ContractAddress; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); @@ -176,7 +176,7 @@ The protected function must call `start` before the first function statement, an ---- #[starknet::contract] mod MyReentrancyContract { - use openzeppelin_security::ReentrancyGuardComponent; + use openzeppelin::security::ReentrancyGuardComponent; component!( path: ReentrancyGuardComponent, storage: reentrancy_guard, event: ReentrancyGuardEvent diff --git a/docs/modules/ROOT/pages/udc.adoc b/docs/modules/ROOT/pages/udc.adoc index 823ee7c96..fd30ce729 100644 --- a/docs/modules/ROOT/pages/udc.adoc +++ b/docs/modules/ROOT/pages/udc.adoc @@ -41,7 +41,7 @@ Here's an implementation example in Cairo: [,cairo] ---- -use openzeppelin_utils::interfaces::{IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait}; +use openzeppelin::utils::interfaces::{IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait}; const UDC_ADDRESS: felt252 = 0x04a64cd09a853868621d94cae9952b106f2c36a3f81260f85de6696c6b050221; diff --git a/docs/modules/ROOT/pages/upgrades.adoc b/docs/modules/ROOT/pages/upgrades.adoc index bceb25fdf..3f58469e0 100644 --- a/docs/modules/ROOT/pages/upgrades.adoc +++ b/docs/modules/ROOT/pages/upgrades.adoc @@ -51,9 +51,9 @@ NOTE: We will be using the following module to implement the {i_upgradeable} int ---- #[starknet::contract] mod UpgradeableContract { - use openzeppelin_access::ownable::OwnableComponent; - use openzeppelin_upgrades::UpgradeableComponent; - use openzeppelin_upgrades::interface::IUpgradeable; + use openzeppelin::access::ownable::OwnableComponent; + use openzeppelin::upgrades::UpgradeableComponent; + use openzeppelin::upgrades::interface::IUpgradeable; use starknet::ClassHash; use starknet::ContractAddress; From 2e0f3c641feb28796272990c4247ba668296b809 Mon Sep 17 00:00:00 2001 From: immrsd <103599616+immrsd@users.noreply.github.com> Date: Mon, 29 Jul 2024 20:19:01 +0200 Subject: [PATCH 33/45] Migrate Starknet Account Preset tests (#1069) * Update test utils and helpers * Update signature tests * Update account tests * Update dual account tests * Run linter * Run linter * Fix review issues * Update ignore reason messages * Run linter * Support eth account tests changes * Run linter * Improve setup functions, remove unused imports * Remove unnecessary accept_ownership step, make use of serialized_sign fn * Migrate Starknet Account Preset tests, make some code improvements * Run linter * Remove unnecessary clone * Update the comment for assert_entrypoint_not_found_error function * Minor review fixes --- .../account/ethereum/test_eth_account.cairo | 2 +- src/tests/account/starknet/test_account.cairo | 2 +- src/tests/presets.cairo | 2 +- src/tests/presets/test_account.cairo | 442 ++++++++++-------- src/tests/presets/test_erc1155.cairo | 6 +- src/tests/presets/test_erc20.cairo | 6 +- src/tests/presets/test_eth_account.cairo | 6 +- src/tests/utils/common.cairo | 32 +- src/tests/utils/deployment.cairo | 14 +- 9 files changed, 275 insertions(+), 237 deletions(-) diff --git a/src/tests/account/ethereum/test_eth_account.cairo b/src/tests/account/ethereum/test_eth_account.cairo index a239de7f6..1f26956e0 100644 --- a/src/tests/account/ethereum/test_eth_account.cairo +++ b/src/tests/account/ethereum/test_eth_account.cairo @@ -316,7 +316,7 @@ fn test_multicall() { to: erc20.contract_address, selector: selectors::transfer, calldata: calldata2.span() }; - // Bundle calls and exeute + // Bundle calls and execute calls.append(call1); calls.append(call2); let ret = account.__execute__(calls); diff --git a/src/tests/account/starknet/test_account.cairo b/src/tests/account/starknet/test_account.cairo index 13dd7f36e..7bfa8e377 100644 --- a/src/tests/account/starknet/test_account.cairo +++ b/src/tests/account/starknet/test_account.cairo @@ -308,7 +308,7 @@ fn test_multicall() { to: erc20.contract_address, selector: selectors::transfer, calldata: calldata2.span() }; - // Bundle calls and exeute + // Bundle calls and execute let calls = array![call1, call2]; let ret = account.__execute__(calls); diff --git a/src/tests/presets.cairo b/src/tests/presets.cairo index 5edfe8b18..87e7cb2f4 100644 --- a/src/tests/presets.cairo +++ b/src/tests/presets.cairo @@ -1,4 +1,4 @@ -// mod test_account; +mod test_account; mod test_erc1155; mod test_erc20; mod test_erc721; diff --git a/src/tests/presets/test_account.cairo b/src/tests/presets/test_account.cairo index 61dc1c803..3aaf59543 100644 --- a/src/tests/presets/test_account.cairo +++ b/src/tests/presets/test_account.cairo @@ -1,68 +1,65 @@ use core::num::traits::Zero; -use openzeppelin::account::AccountComponent::{OwnerAdded, OwnerRemoved}; use openzeppelin::account::interface::ISRC6_ID; use openzeppelin::introspection::interface::ISRC5_ID; use openzeppelin::presets::AccountUpgradeable; +use openzeppelin::presets::interfaces::account::{ + AccountUpgradeableABISafeDispatcher, AccountUpgradeableABISafeDispatcherTrait +}; use openzeppelin::presets::interfaces::{ AccountUpgradeableABIDispatcher, AccountUpgradeableABIDispatcherTrait }; use openzeppelin::tests::account::starknet::common::{ - assert_only_event_owner_added, assert_event_owner_removed -}; -use openzeppelin::tests::account::starknet::common::{ - deploy_erc20, SIGNED_TX_DATA, SignedTransactionData + get_accept_ownership_signature, deploy_erc20, SIGNED_TX_DATA, }; -use openzeppelin::tests::mocks::account_mocks::SnakeAccountMock; -use openzeppelin::tests::upgrades::common::assert_only_event_upgraded; +use openzeppelin::tests::account::starknet::common::{AccountSpyHelpers, SignedTransactionData}; +use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; +use openzeppelin::tests::utils::constants::stark::{KEY_PAIR, KEY_PAIR_2}; use openzeppelin::tests::utils::constants::{ - PUBKEY, NEW_PUBKEY, SALT, ZERO, CALLER, RECIPIENT, OTHER, QUERY_OFFSET, QUERY_VERSION, - MIN_TRANSACTION_VERSION, CLASS_HASH_ZERO + SALT, QUERY_OFFSET, QUERY_VERSION, MIN_TRANSACTION_VERSION }; +use openzeppelin::tests::utils::constants::{ZERO, CALLER, RECIPIENT, OTHER, CLASS_HASH_ZERO}; +use openzeppelin::tests::utils::signing::{StarkKeyPair, StarkKeyPairExt}; use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher}; +use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; use openzeppelin::utils::selectors; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::{ + cheat_signature_global, cheat_transaction_version_global, cheat_transaction_hash_global +}; +use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::account::Call; -use starknet::testing; use starknet::{ContractAddress, ClassHash}; -fn CLASS_HASH() -> felt252 { - AccountUpgradeable::TEST_CLASS_HASH -} - -fn V2_CLASS_HASH() -> ClassHash { - SnakeAccountMock::TEST_CLASS_HASH.try_into().unwrap() -} - // // Setup // -fn setup_dispatcher() -> AccountUpgradeableABIDispatcher { - let calldata = array![PUBKEY]; - let target = utils::deploy(CLASS_HASH(), calldata); - utils::drop_event(target); +fn declare_v2_class() -> ClassHash { + utils::declare_class("SnakeAccountMock").class_hash +} + +fn setup_dispatcher(key_pair: StarkKeyPair) -> (ContractAddress, AccountUpgradeableABIDispatcher) { + let calldata = array![key_pair.public_key]; + let account_address = utils::declare_and_deploy("AccountUpgradeable", calldata); + let dispatcher = AccountUpgradeableABIDispatcher { contract_address: account_address }; - AccountUpgradeableABIDispatcher { contract_address: target } + (account_address, dispatcher) } fn setup_dispatcher_with_data( - data: Option<@SignedTransactionData> -) -> AccountUpgradeableABIDispatcher { - testing::set_version(MIN_TRANSACTION_VERSION); + key_pair: StarkKeyPair, data: SignedTransactionData +) -> (AccountUpgradeableABIDispatcher, felt252) { + let account_class = utils::declare_class("AccountUpgradeable"); + let calldata = array![key_pair.public_key]; + let contract_address = utils::deploy(account_class, calldata); + let account_dispatcher = AccountUpgradeableABIDispatcher { contract_address }; - let mut calldata = array![]; - if data.is_some() { - let data = data.unwrap(); - testing::set_signature(array![*data.r, *data.s].span()); - testing::set_transaction_hash(*data.transaction_hash); - - calldata.append(*data.public_key); - } else { - calldata.append(PUBKEY); - } - let address = utils::deploy(CLASS_HASH(), calldata); - AccountUpgradeableABIDispatcher { contract_address: address } + cheat_signature_global(array![data.r, data.s].span()); + cheat_transaction_hash_global(data.tx_hash); + cheat_transaction_version_global(MIN_TRANSACTION_VERSION); + start_cheat_caller_address(contract_address, ZERO()); + + (account_dispatcher, account_class.class_hash.into()) } // @@ -72,12 +69,15 @@ fn setup_dispatcher_with_data( #[test] fn test_constructor() { let mut state = AccountUpgradeable::contract_state_for_testing(); - AccountUpgradeable::constructor(ref state, PUBKEY); + let mut spy = spy_events(); + let key_pair = KEY_PAIR(); + let account_address = test_address(); + AccountUpgradeable::constructor(ref state, key_pair.public_key); - assert_only_event_owner_added(ZERO(), PUBKEY); + spy.assert_only_event_owner_added(account_address, key_pair.public_key); let public_key = AccountUpgradeable::AccountMixinImpl::get_public_key(@state); - assert_eq!(public_key, PUBKEY); + assert_eq!(public_key, key_pair.public_key); let supports_isrc5 = AccountUpgradeable::AccountMixinImpl::supports_interface(@state, ISRC5_ID); assert!(supports_isrc5); @@ -92,44 +92,66 @@ fn test_constructor() { #[test] fn test_public_key_setter_and_getter() { - let dispatcher = setup_dispatcher(); + let key_pair = KEY_PAIR(); + let (account_address, dispatcher) = setup_dispatcher(key_pair); + let mut spy = spy_events(); - testing::set_contract_address(dispatcher.contract_address); + let new_key_pair = KEY_PAIR_2(); + let signature = get_accept_ownership_signature( + account_address, key_pair.public_key, new_key_pair + ); + start_cheat_caller_address(account_address, account_address); + dispatcher.set_public_key(new_key_pair.public_key, signature); - dispatcher.set_public_key(NEW_PUBKEY, get_accept_ownership_signature()); - let public_key = dispatcher.get_public_key(); - assert_eq!(public_key, NEW_PUBKEY); + assert_eq!(dispatcher.get_public_key(), new_key_pair.public_key); - assert_event_owner_removed(dispatcher.contract_address, PUBKEY); - assert_only_event_owner_added(dispatcher.contract_address, NEW_PUBKEY); + spy.assert_event_owner_removed(dispatcher.contract_address, key_pair.public_key); + spy.assert_only_event_owner_added(dispatcher.contract_address, new_key_pair.public_key); } #[test] fn test_public_key_setter_and_getter_camel() { - let dispatcher = setup_dispatcher(); + let key_pair = KEY_PAIR(); + let (account_address, dispatcher) = setup_dispatcher(key_pair); + let mut spy = spy_events(); - testing::set_contract_address(dispatcher.contract_address); + let new_key_pair = KEY_PAIR_2(); + let signature = get_accept_ownership_signature( + account_address, key_pair.public_key, new_key_pair + ); + start_cheat_caller_address(account_address, account_address); + dispatcher.setPublicKey(new_key_pair.public_key, signature); - dispatcher.setPublicKey(NEW_PUBKEY, get_accept_ownership_signature()); - let public_key = dispatcher.getPublicKey(); - assert_eq!(public_key, NEW_PUBKEY); + assert_eq!(dispatcher.getPublicKey(), new_key_pair.public_key); - assert_event_owner_removed(dispatcher.contract_address, PUBKEY); - assert_only_event_owner_added(dispatcher.contract_address, NEW_PUBKEY); + spy.assert_event_owner_removed(dispatcher.contract_address, key_pair.public_key); + spy.assert_only_event_owner_added(dispatcher.contract_address, new_key_pair.public_key); } #[test] -#[should_panic(expected: ('Account: unauthorized', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: unauthorized',))] fn test_set_public_key_different_account() { - let dispatcher = setup_dispatcher(); - dispatcher.set_public_key(NEW_PUBKEY, get_accept_ownership_signature()); + let key_pair = KEY_PAIR(); + let (account_address, dispatcher) = setup_dispatcher(key_pair); + + let new_key_pair = KEY_PAIR_2(); + let signature = get_accept_ownership_signature( + account_address, key_pair.public_key, new_key_pair + ); + dispatcher.set_public_key(new_key_pair.public_key, signature); } #[test] -#[should_panic(expected: ('Account: unauthorized', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: unauthorized',))] fn test_setPublicKey_different_account() { - let dispatcher = setup_dispatcher(); - dispatcher.setPublicKey(NEW_PUBKEY, get_accept_ownership_signature()); + let key_pair = KEY_PAIR(); + let (account_address, dispatcher) = setup_dispatcher(key_pair); + + let new_key_pair = KEY_PAIR_2(); + let signature = get_accept_ownership_signature( + account_address, key_pair.public_key, new_key_pair + ); + dispatcher.setPublicKey(new_key_pair.public_key, signature); } // @@ -137,16 +159,12 @@ fn test_setPublicKey_different_account() { // fn is_valid_sig_dispatcher() -> (AccountUpgradeableABIDispatcher, felt252, Array) { - let dispatcher = setup_dispatcher(); - - let data = SIGNED_TX_DATA(); - let hash = data.transaction_hash; - let mut signature = array![data.r, data.s]; - - testing::set_contract_address(dispatcher.contract_address); - dispatcher.set_public_key(data.public_key, get_accept_ownership_signature()); + let key_pair = KEY_PAIR(); + let (_, dispatcher) = setup_dispatcher(key_pair); - (dispatcher, hash, signature) + let data = SIGNED_TX_DATA(key_pair); + let signature = array![data.r, data.s]; + (dispatcher, data.tx_hash, signature) } #[test] @@ -159,44 +177,64 @@ fn test_is_valid_signature() { #[test] fn test_is_valid_signature_bad_sig() { - let (dispatcher, hash, _) = is_valid_sig_dispatcher(); + let (dispatcher, tx_hash, _) = is_valid_sig_dispatcher(); + let bad_signature = array!['BAD', 'SIG']; - let bad_signature = array![0x987, 0x564]; - - let is_valid = dispatcher.is_valid_signature(hash, bad_signature.clone()); + let is_valid = dispatcher.is_valid_signature(tx_hash, bad_signature); assert!(is_valid.is_zero(), "Should reject invalid signature"); } +#[test] +fn test_is_valid_signature_invalid_len_sig() { + let (dispatcher, tx_hash, _) = is_valid_sig_dispatcher(); + let invalid_len_sig = array!['INVALID_LEN']; + + let is_valid = dispatcher.is_valid_signature(tx_hash, invalid_len_sig); + assert!(is_valid.is_zero(), "Should reject signature of invalid length"); +} + #[test] fn test_isValidSignature() { - let (dispatcher, hash, signature) = is_valid_sig_dispatcher(); + let (dispatcher, tx_hash, signature) = is_valid_sig_dispatcher(); - let is_valid = dispatcher.isValidSignature(hash, signature); + let is_valid = dispatcher.isValidSignature(tx_hash, signature); assert_eq!(is_valid, starknet::VALIDATED); } #[test] fn test_isValidSignature_bad_sig() { - let (dispatcher, hash, _) = is_valid_sig_dispatcher(); + let (dispatcher, tx_hash, _) = is_valid_sig_dispatcher(); + let bad_signature = array!['BAD', 'SIG']; - let bad_signature = array![0x987, 0x564]; - - let is_valid = dispatcher.isValidSignature(hash, bad_signature); + let is_valid = dispatcher.isValidSignature(tx_hash, bad_signature); assert!(is_valid.is_zero(), "Should reject invalid signature"); } +#[test] +fn test_isValidSignature_invalid_len_sig() { + let (dispatcher, tx_hash, _) = is_valid_sig_dispatcher(); + let invalid_len_sig = array!['INVALID_LEN']; + + let is_valid = dispatcher.isValidSignature(tx_hash, invalid_len_sig); + assert!(is_valid.is_zero(), "Should reject signature of invalid length"); +} + // // supports_interface // #[test] fn test_supports_interface() { - let dispatcher = setup_dispatcher(); + let key_pair = KEY_PAIR(); + let (_, dispatcher) = setup_dispatcher(key_pair); + let supports_isrc5 = dispatcher.supports_interface(ISRC5_ID); assert!(supports_isrc5); + let supports_isrc6 = dispatcher.supports_interface(ISRC6_ID); assert!(supports_isrc6); - let doesnt_support_0x123 = !dispatcher.supports_interface(0x123); + + let doesnt_support_0x123 = !dispatcher.supports_interface('DUMMY_INTERFACE_ID'); assert!(doesnt_support_0x123); } @@ -206,110 +244,120 @@ fn test_supports_interface() { #[test] fn test_validate_deploy() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); // `__validate_deploy__` does not directly use the passed arguments. Their // values are already integrated in the tx hash. The passed arguments in this // testing context are decoupled from the signature and have no effect on the test. - let is_valid = account.__validate_deploy__(CLASS_HASH(), SALT, PUBKEY); + let is_valid = account.__validate_deploy__(class_hash, SALT, key_pair.public_key); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_deploy_invalid_signature_data() { - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher_with_data(Option::Some(@data)); + let key_pair = KEY_PAIR(); + let mut data = SIGNED_TX_DATA(key_pair); + data.tx_hash += 1; + let (account, class_hash) = setup_dispatcher_with_data(key_pair, data); - account.__validate_deploy__(CLASS_HASH(), SALT, PUBKEY); + account.__validate_deploy__(class_hash, SALT, key_pair.public_key); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_deploy_invalid_signature_length() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); - let mut signature = array![0x1]; + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - testing::set_signature(signature.span()); + let invalid_len_sig = array!['INVALID_LEN']; + cheat_signature_global(invalid_len_sig.span()); - account.__validate_deploy__(CLASS_HASH(), SALT, PUBKEY); + account.__validate_deploy__(class_hash, SALT, key_pair.public_key); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_deploy_empty_signature() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); + let empty_sig = array![]; + cheat_signature_global(empty_sig.span()); - testing::set_signature(empty_sig.span()); - account.__validate_deploy__(CLASS_HASH(), SALT, PUBKEY); + account.__validate_deploy__(class_hash, SALT, key_pair.public_key); } #[test] fn test_validate_declare() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); // `__validate_declare__` does not directly use the class_hash argument. Its // value is already integrated in the tx hash. The class_hash argument in this // testing context is decoupled from the signature and has no effect on the test. - let is_valid = account.__validate_declare__(CLASS_HASH()); + let is_valid = account.__validate_declare__(class_hash); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_declare_invalid_signature_data() { - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher_with_data(Option::Some(@data)); + let key_pair = KEY_PAIR(); + let mut data = SIGNED_TX_DATA(key_pair); + data.tx_hash += 1; + let (account, class_hash) = setup_dispatcher_with_data(key_pair, data); - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_declare_invalid_signature_length() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); - let mut signature = array![0x1]; + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - testing::set_signature(signature.span()); + let invalid_len_sig = array!['INVALID_LEN']; + cheat_signature_global(invalid_len_sig.span()); - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_declare_empty_signature() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); - let empty_sig = array![]; + let key_pair = KEY_PAIR(); + let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - testing::set_signature(empty_sig.span()); + let empty_sig = array![]; + cheat_signature_global(empty_sig.span()); - account.__validate_declare__(CLASS_HASH()); + account.__validate_declare__(class_hash); } fn test_execute_with_version(version: Option) { - let data = SIGNED_TX_DATA(); - let account = setup_dispatcher_with_data(Option::Some(@data)); + let key_pair = KEY_PAIR(); + let data = SIGNED_TX_DATA(key_pair); + let (account, _) = setup_dispatcher_with_data(key_pair, data); let erc20 = deploy_erc20(account.contract_address, 1000); // Craft call and add to calls array let amount: u256 = 200; + let recipient = RECIPIENT(); let mut calldata = array![]; - calldata.append_serde(RECIPIENT()); + calldata.append_serde(recipient); calldata.append_serde(amount); let call = Call { to: erc20.contract_address, selector: selectors::transfer, calldata: calldata.span() }; - let mut calls = array![]; - calls.append(call); + let calls = array![call]; // Handle version for test - if version.is_some() { - testing::set_version(version.unwrap()); + if let Option::Some(version) = version { + cheat_transaction_version_global(version) } // Execute @@ -317,7 +365,7 @@ fn test_execute_with_version(version: Option) { // Assert that the transfer was successful assert_eq!(erc20.balance_of(account.contract_address), 800, "Should have remainder"); - assert_eq!(erc20.balance_of(RECIPIENT()), amount, "Should have transferred"); + assert_eq!(erc20.balance_of(recipient), amount, "Should have transferred"); // Test return value let mut call_serialized_retval = *ret.at(0); @@ -327,7 +375,7 @@ fn test_execute_with_version(version: Option) { #[test] fn test_execute() { - test_execute_with_version(Option::None(())); + test_execute_with_version(Option::None); } #[test] @@ -341,7 +389,7 @@ fn test_execute_query_version() { } #[test] -#[should_panic(expected: ('Account: invalid tx version', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid tx version',))] fn test_execute_invalid_query_version() { test_execute_with_version(Option::Some(QUERY_OFFSET)); } @@ -352,34 +400,37 @@ fn test_execute_future_query_version() { } #[test] -#[should_panic(expected: ('Account: invalid tx version', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid tx version',))] fn test_execute_invalid_version() { test_execute_with_version(Option::Some(MIN_TRANSACTION_VERSION - 1)); } #[test] fn test_validate() { - let calls = array![]; - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let key_pair = KEY_PAIR(); + let (account, _) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); + let calls = array![]; let is_valid = account.__validate__(calls); assert_eq!(is_valid, starknet::VALIDATED); } #[test] -#[should_panic(expected: ('Account: invalid signature', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid signature',))] fn test_validate_invalid() { - let calls = array![]; - let mut data = SIGNED_TX_DATA(); - data.transaction_hash += 1; - let account = setup_dispatcher_with_data(Option::Some(@data)); + let key_pair = KEY_PAIR(); + let mut data = SIGNED_TX_DATA(key_pair); + data.tx_hash += 1; + let (account, _) = setup_dispatcher_with_data(key_pair, data); + let calls = array![]; account.__validate__(calls); } #[test] fn test_multicall() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); + let key_pair = KEY_PAIR(); + let (account, _) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); let erc20 = deploy_erc20(account.contract_address, 1000); let recipient1 = RECIPIENT(); let recipient2 = OTHER(); @@ -403,7 +454,7 @@ fn test_multicall() { to: erc20.contract_address, selector: selectors::transfer, calldata: calldata2.span() }; - // Bundle calls and exeute + // Bundle calls and execute calls.append(call1); calls.append(call2); let ret = account.__execute__(calls); @@ -426,23 +477,23 @@ fn test_multicall() { #[test] fn test_multicall_zero_calls() { - let account = setup_dispatcher_with_data(Option::Some(@SIGNED_TX_DATA())); - let mut calls = array![]; + let key_pair = KEY_PAIR(); + let (account, _) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); + let calls = array![]; let response = account.__execute__(calls); assert!(response.is_empty()); } #[test] -#[should_panic(expected: ('Account: invalid caller', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Account: invalid caller',))] fn test_account_called_from_contract() { - let account = setup_dispatcher(); - let calls = array![]; - - testing::set_contract_address(account.contract_address); - testing::set_caller_address(CALLER()); + let key_pair = KEY_PAIR(); + let (account_address, dispatcher) = setup_dispatcher(key_pair); - account.__execute__(calls); + let calls = array![]; + start_cheat_caller_address(account_address, CALLER()); + dispatcher.__execute__(calls); } // @@ -450,89 +501,72 @@ fn test_account_called_from_contract() { // #[test] -#[should_panic(expected: ('Account: unauthorized', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Account: unauthorized',))] fn test_upgrade_access_control() { - let v1 = setup_dispatcher(); - v1.upgrade(CLASS_HASH_ZERO()); + let key_pair = KEY_PAIR(); + let (_, v1_dispatcher) = setup_dispatcher(key_pair); + + v1_dispatcher.upgrade(CLASS_HASH_ZERO()); } #[test] -#[should_panic(expected: ('Class hash cannot be zero', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Class hash cannot be zero',))] fn test_upgrade_with_class_hash_zero() { - let v1 = setup_dispatcher(); + let key_pair = KEY_PAIR(); + let (account_address, v1_dispatcher) = setup_dispatcher(key_pair); - set_contract_and_caller(v1.contract_address); - v1.upgrade(CLASS_HASH_ZERO()); + start_cheat_caller_address(account_address, account_address); + v1_dispatcher.upgrade(CLASS_HASH_ZERO()); } #[test] fn test_upgraded_event() { - let v1 = setup_dispatcher(); - let v2_class_hash = V2_CLASS_HASH(); + let key_pair = KEY_PAIR(); + let (account_address, v1_dispatcher) = setup_dispatcher(key_pair); + let mut spy = spy_events(); - set_contract_and_caller(v1.contract_address); - v1.upgrade(v2_class_hash); + let v2_class_hash = declare_v2_class(); + start_cheat_caller_address(account_address, account_address); + v1_dispatcher.upgrade(v2_class_hash); - assert_only_event_upgraded(v1.contract_address, v2_class_hash); + spy.assert_only_event_upgraded(account_address, v2_class_hash); } #[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +#[feature("safe_dispatcher")] fn test_v2_missing_camel_selector() { - let v1 = setup_dispatcher(); - let v2_class_hash = V2_CLASS_HASH(); + let key_pair = KEY_PAIR(); + let (account_address, v1_dispatcher) = setup_dispatcher(key_pair); + + let v2_class_hash = declare_v2_class(); + start_cheat_caller_address(account_address, account_address); + v1_dispatcher.upgrade(v2_class_hash); - set_contract_and_caller(v1.contract_address); - v1.upgrade(v2_class_hash); + let safe_dispatcher = AccountUpgradeableABISafeDispatcher { contract_address: account_address }; + let result = safe_dispatcher.getPublicKey(); - let dispatcher = AccountUpgradeableABIDispatcher { contract_address: v1.contract_address }; - dispatcher.getPublicKey(); + utils::assert_entrypoint_not_found_error(result, selector!("getPublicKey"), account_address) } #[test] fn test_state_persists_after_upgrade() { - let v1 = setup_dispatcher(); - let v2_class_hash = V2_CLASS_HASH(); + let key_pair = KEY_PAIR(); + let (account_address, v1_dispatcher) = setup_dispatcher(key_pair); - set_contract_and_caller(v1.contract_address); - let dispatcher = AccountUpgradeableABIDispatcher { contract_address: v1.contract_address }; + let new_key_pair = KEY_PAIR_2(); + let accept_ownership_sig = get_accept_ownership_signature( + account_address, key_pair.public_key, new_key_pair + ); + start_cheat_caller_address(account_address, account_address); + v1_dispatcher.set_public_key(new_key_pair.public_key, accept_ownership_sig); - dispatcher.set_public_key(NEW_PUBKEY, get_accept_ownership_signature()); + let expected_public_key = new_key_pair.public_key; + let camel_public_key = v1_dispatcher.getPublicKey(); + assert_eq!(camel_public_key, expected_public_key); - let camel_public_key = dispatcher.getPublicKey(); - assert_eq!(camel_public_key, NEW_PUBKEY); - - v1.upgrade(v2_class_hash); - let snake_public_key = dispatcher.get_public_key(); - - assert_eq!(snake_public_key, camel_public_key); -} - -// -// Helpers -// + let v2_class_hash = declare_v2_class(); + v1_dispatcher.upgrade(v2_class_hash); + let snake_public_key = v1_dispatcher.get_public_key(); -fn set_contract_and_caller(address: ContractAddress) { - testing::set_contract_address(address); - testing::set_caller_address(address); -} - -fn get_accept_ownership_signature() -> Span { - // 0xecfdac5cd0e60434b672a97ba94520b9acfe629d123a883005e45afa25ccea = - // PoseidonTrait::new() - // .update_with('StarkNet Message') - // .update_with('accept_ownership') - // .update_with(dispatcher.contract_address) - // .update_with(PUBKEY) - // .finalize(); - - // This signature was computed using starknet js sdk from the following values: - // - private_key: '1234' - // - public_key: 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7 - // - msg_hash: 0xecfdac5cd0e60434b672a97ba94520b9acfe629d123a883005e45afa25ccea - array![ - 0x379fcc17e39513c19b5d97143e919ec3a5d9f59d4ae80fef83e037bc9275240, - 0x7719ade3541834755ed48a4373a19872c4032937344d832e2743df677b0a43 - ] - .span() + assert_eq!(snake_public_key, expected_public_key); } diff --git a/src/tests/presets/test_erc1155.cairo b/src/tests/presets/test_erc1155.cairo index 57c597612..62ff34fbb 100644 --- a/src/tests/presets/test_erc1155.cairo +++ b/src/tests/presets/test_erc1155.cairo @@ -868,11 +868,9 @@ fn test_v2_missing_camel_selector() { v1.upgrade(v2_class_hash); let safe_dispatcher = IERC1155CamelSafeDispatcher { contract_address: v1.contract_address }; - let panic_data = safe_dispatcher.balanceOf(owner, TOKEN_ID).unwrap_err(); + let result = safe_dispatcher.balanceOf(owner, TOKEN_ID); - utils::assert_entrypoint_not_found_error( - panic_data, selector!("balanceOf"), v1.contract_address - ) + utils::assert_entrypoint_not_found_error(result, selector!("balanceOf"), v1.contract_address) } #[test] diff --git a/src/tests/presets/test_erc20.cairo b/src/tests/presets/test_erc20.cairo index 8d10d7ab8..5630256d9 100644 --- a/src/tests/presets/test_erc20.cairo +++ b/src/tests/presets/test_erc20.cairo @@ -480,11 +480,9 @@ fn test_v2_missing_camel_selector() { let safe_dispatcher = ERC20UpgradeableABISafeDispatcher { contract_address: v1.contract_address }; - let mut panic_data = safe_dispatcher.totalSupply().unwrap_err(); + let result = safe_dispatcher.totalSupply(); - utils::assert_entrypoint_not_found_error( - panic_data, selector!("totalSupply"), v1.contract_address - ) + utils::assert_entrypoint_not_found_error(result, selector!("totalSupply"), v1.contract_address) } #[test] diff --git a/src/tests/presets/test_eth_account.cairo b/src/tests/presets/test_eth_account.cairo index 81ea869ea..c30da1c7e 100644 --- a/src/tests/presets/test_eth_account.cairo +++ b/src/tests/presets/test_eth_account.cairo @@ -499,11 +499,9 @@ fn test_v2_missing_camel_selector() { let safe_dispatcher = EthAccountUpgradeableABISafeDispatcher { contract_address: v1.contract_address }; - let panic_data = safe_dispatcher.getPublicKey().unwrap_err(); + let result = safe_dispatcher.getPublicKey(); - utils::assert_entrypoint_not_found_error( - panic_data, selector!("getPublicKey"), v1.contract_address - ) + utils::assert_entrypoint_not_found_error(result, selector!("getPublicKey"), v1.contract_address) } #[test] diff --git a/src/tests/utils/common.cairo b/src/tests/utils/common.cairo index 853be448b..f453a32fb 100644 --- a/src/tests/utils/common.cairo +++ b/src/tests/utils/common.cairo @@ -1,5 +1,5 @@ use core::to_byte_array::FormatAsByteArray; -use starknet::ContractAddress; +use starknet::{ContractAddress, SyscallResult}; /// Converts panic data into a string (ByteArray). /// @@ -9,7 +9,7 @@ pub fn panic_data_to_byte_array(panic_data: Array) -> ByteArray { let mut panic_data = panic_data.span(); // Remove BYTE_ARRAY_MAGIC from the panic data. - panic_data.pop_front().unwrap(); + panic_data.pop_front().expect('Empty panic data provided'); match Serde::::deserialize(ref panic_data) { Option::Some(string) => string, @@ -36,15 +36,23 @@ pub impl IntoBase16String> of IntoBase16StringTrait { } } -/// Asserts that the panic data is an "Entrypoint not found" error, following the starknet foundry -/// emitted error format. -pub fn assert_entrypoint_not_found_error( - panic_data: Array, selector: felt252, contract_address: ContractAddress +/// Asserts that the syscall result of a call failed with an "Entrypoint not found" error, +/// following the starknet foundry emitted error format. +pub fn assert_entrypoint_not_found_error>( + result: SyscallResult, selector: felt252, contract_address: ContractAddress ) { - let expected_panic_message = format!( - "Entry point selector {} not found in contract {}", - selector.into_base_16_string(), - contract_address.into_base_16_string() - ); - assert!(panic_data_to_byte_array(panic_data) == expected_panic_message); + if let Result::Err(panic_data) = result { + let expected_panic_message = format!( + "Entry point selector {} not found in contract {}", + selector.into_base_16_string(), + contract_address.into_base_16_string() + ); + let actual_panic_message = panic_data_to_byte_array(panic_data); + assert!( + actual_panic_message == expected_panic_message, + "Got unexpected panic message: ${actual_panic_message}" + ); + } else { + panic!("${selector} call was expected to fail, but succeeded"); + } } diff --git a/src/tests/utils/deployment.cairo b/src/tests/utils/deployment.cairo index dae9a2071..2b50ab15f 100644 --- a/src/tests/utils/deployment.cairo +++ b/src/tests/utils/deployment.cairo @@ -1,7 +1,6 @@ use core::starknet::SyscallResultTrait; use openzeppelin::tests::utils::panic_data_to_byte_array; -use snforge_std::{declare, get_class_hash, ContractClass, ContractClassTrait}; -use snforge_std::{start_cheat_caller_address, stop_cheat_caller_address}; +use snforge_std::{ContractClass, ContractClassTrait}; use starknet::ContractAddress; pub fn deploy(contract_class: ContractClass, calldata: Array) -> ContractAddress { @@ -24,23 +23,26 @@ pub fn deploy_at( pub fn deploy_another_at( existing: ContractAddress, target_address: ContractAddress, calldata: Array ) { - let class_hash = get_class_hash(existing); + let class_hash = snforge_std::get_class_hash(existing); let contract_class = ContractClassTrait::new(class_hash); deploy_at(contract_class, target_address, calldata) } pub fn declare_class(contract_name: ByteArray) -> ContractClass { - declare(contract_name).unwrap_syscall() + match snforge_std::declare(contract_name) { + Result::Ok(contract_class) => contract_class, + Result::Err(panic_data) => panic!("{}", panic_data_to_byte_array(panic_data)) + } } pub fn declare_and_deploy(contract_name: ByteArray, calldata: Array) -> ContractAddress { - let contract_class = declare(contract_name).unwrap_syscall(); + let contract_class = declare_class(contract_name); deploy(contract_class, calldata) } pub fn declare_and_deploy_at( contract_name: ByteArray, target_address: ContractAddress, calldata: Array ) { - let contract_class = declare(contract_name).unwrap_syscall(); + let contract_class = declare_class(contract_name); deploy_at(contract_class, target_address, calldata) } From 6601f24d4fe8a7b51c2d166116461e2c8c11e274 Mon Sep 17 00:00:00 2001 From: Andrew Fleming Date: Wed, 31 Jul 2024 05:13:41 -0400 Subject: [PATCH 34/45] Bump scarb, merge changes from main in snforge migration (#1076) * Remove unnecessary `mut`, minor fixes (#1032) * clean up code * change array syntax * fix fmt * Improve SNIP12 examples (#1036) * docs: improve examples * refactor: remove empty line * Update docs/modules/ROOT/pages/guides/snip12.adoc Co-authored-by: Andrew Fleming --------- Co-authored-by: Andrew Fleming * Release v0.15.0-rc.0 (#1039) * feat: update CHANGELOG * Bump version to 0.15.0-rc.0 * docs: add missing header * feat: apply review suggestions --------- Co-authored-by: ericnordelo * Bump cairo to 2.7.0-rc.1 (#1025) * feat: migrate modules * feat: delete cairo_project.toml * feat: update tests * feat: apply review updates * fix: remove extra line * feat: add CHANGELOG entry * fix: CHANGELOG * Bump Scarb to 2.7.0-rc.2 (#1052) * bump scarb to 2.7.0-rc.2 * add changelog entry * update changelog entry * bump scarb in installation page * Add timelock component (#996) * start timelock comp draft * move timelock to own dir, finish drafting component * tmp: add utility impls * add timelock mock * add test mod for timelock * fix commnet * add constructor to timelock mock * set min_delay in initializer * start tests * fix fmt * fix schedule assertion * add schedule tests * fix fmt * remove unused import * fix errs, _before_call * start execute tests * fix fmt * fix after_call * add execute tests * add abi interface * add reentrancy mock for timelock * add tests for cancel and update_delay * fix hash_op test * add execute with predecessor test * add timelock utils, add operation_state debug impl * fix fmt * improve imports * improve _execute * add basic mock for tests * add tmp call struct * add batch fns to interface * add batch fns * refactor tests to use dedicated mock, add batch tests * fix fmt * remove use clause * add timelock mixin * fix interface name * improve event assertions * fix execute and schedule events * fix fmt * add safe token transfer tests * fix fmt * tidy up code * add descriptions to events * clean up code * inline CallPartialEq fns * start fn descriptions * remove comments * remove comment * fix fmt * add changelog entries * improve spacing * add line break to hash test * clean up tests * clean up tests * fix constants in attacker impl * add initializer helper, register access control support * add _before_call and _after_call tests * fix reentrant batch mock call * add _schedule and _execute tests * add timelock description * fix formatting * fix comments * fix comment * fmt * tidy up tests * remove batch helper fn * remove event from mocks * Apply suggestions from code review Co-authored-by: Eric Nordelo * update spdx * remove token receiver support * add additional cancel tests * Apply suggestions from code review Co-authored-by: Eric Nordelo * initializer: remove mut, use while loop * fix fmt * add assert_only_self fn * fix getter comments re: pending/waiting * add assert_only_role * add specific op errors * make event names consistent * fix test * remove serialization from HashCallImpl * remove unused components from mock * clean up code * update to 2.7.0-rc.1 * fix fmt * import Call from corelib * update spdx * fix fmt * move OperationState, derive debug * fix fmt * fix hash impls * add for loops * fix PartialEq, add tests * fix fmt * simplify mixin fns * switch Poseidon to Pedersen * make admin a req in initializer * update tests with admin * fix fmt * fix comment * undo changes * add no admin initializer test --------- Co-authored-by: Eric Nordelo * bump scarb to 2.7.0-rc.4 (#1064) * bump scarb to 2.7.0-rc.4 * add changelog * bump scarb in installation page * feat: update workflow and fix warning (#1066) * Add actionlint (#1067) * add actionlint for workflows * remove codecov and gitmodules * bump checkout to v4, add double quotes, fmt * bump md lint * re-add cairo version * group redirects * fix link in security * add local actionlint matcher json * re-add changelog entry * add tmp usc install to ci * fix ci --------- Co-authored-by: Eric Nordelo Co-authored-by: ericnordelo Co-authored-by: JChoy --- .codecov.yml | 11 - .github/actionlint-matcher.json | 17 + .github/workflows/actionlint.yml | 15 + .github/workflows/prepare-release.yml | 16 +- .github/workflows/test.yml | 11 +- .gitmodules | 3 - CHANGELOG.md | 21 + README.md | 8 +- SECURITY.md | 2 +- Scarb.lock | 2 +- Scarb.toml | 8 +- docs/antora.yml | 2 +- docs/modules/ROOT/pages/accounts.adoc | 2 - docs/modules/ROOT/pages/api/access.adoc | 6 +- docs/modules/ROOT/pages/api/account.adoc | 10 +- docs/modules/ROOT/pages/api/erc1155.adoc | 12 +- docs/modules/ROOT/pages/api/erc20.adoc | 11 +- docs/modules/ROOT/pages/api/erc721.adoc | 12 +- docs/modules/ROOT/pages/api/governance.adoc | 2 +- .../modules/ROOT/pages/api/introspection.adoc | 4 +- docs/modules/ROOT/pages/api/security.adoc | 6 +- docs/modules/ROOT/pages/api/upgrades.adoc | 4 +- docs/modules/ROOT/pages/api/utilities.adoc | 2 +- docs/modules/ROOT/pages/guides/snip12.adoc | 22 +- docs/modules/ROOT/pages/index.adoc | 10 +- docs/modules/ROOT/pages/presets.adoc | 2 +- docs/modules/ROOT/pages/udc.adoc | 2 +- docs/modules/ROOT/pages/upgrades.adoc | 2 +- .../ROOT/pages/utils/_class_hashes.adoc | 14 +- docs/modules/ROOT/pages/wizard.adoc | 2 +- src/access/accesscontrol/accesscontrol.cairo | 9 +- .../accesscontrol/dual_accesscontrol.cairo | 2 +- src/access/accesscontrol/interface.cairo | 2 +- src/access/ownable/dual_ownable.cairo | 4 +- src/access/ownable/interface.cairo | 2 +- src/access/ownable/ownable.cairo | 2 +- src/account/account.cairo | 6 +- src/account/dual_account.cairo | 2 +- src/account/dual_eth_account.cairo | 3 +- src/account/eth_account.cairo | 8 +- src/account/interface.cairo | 3 +- src/account/utils.cairo | 4 +- src/account/utils/secp256k1.cairo | 16 +- src/account/utils/signature.cairo | 2 +- src/cairo_project.toml | 2 - src/governance.cairo | 1 + src/governance/timelock.cairo | 9 + src/governance/timelock/interface.cairo | 69 + .../timelock/timelock_controller.cairo | 659 ++++++ src/governance/timelock/utils.cairo | 1 + .../timelock/utils/call_impls.cairo | 41 + src/governance/utils/interfaces/votes.cairo | 7 +- src/introspection/interface.cairo | 2 +- src/introspection/src5.cairo | 5 +- src/presets/account.cairo | 5 +- src/presets/erc1155.cairo | 2 +- src/presets/erc20.cairo | 2 +- src/presets/erc721.cairo | 2 +- src/presets/eth_account.cairo | 3 +- src/presets/interfaces/eth_account.cairo | 1 - src/presets/universal_deployer.cairo | 5 +- src/security/initializable.cairo | 2 +- src/security/pausable.cairo | 2 +- src/security/reentrancyguard.cairo | 5 +- src/tests.cairo | 2 + src/tests/access/test_ownable.cairo | 1 - src/tests/access/test_ownable_twostep.cairo | 1 - .../ethereum/test_dual_eth_account.cairo | 4 +- .../account/ethereum/test_eth_account.cairo | 4 +- src/tests/account/test_secp256k1.cairo | 50 +- src/tests/governance.cairo | 2 + src/tests/governance/test_timelock.cairo | 1799 +++++++++++++++++ src/tests/governance/test_utils.cairo | 146 ++ src/tests/mocks.cairo | 1 + src/tests/mocks/erc721_receiver_mocks.cairo | 2 +- src/tests/mocks/eth_account_mocks.cairo | 5 - src/tests/mocks/timelock_mocks.cairo | 151 ++ src/tests/presets/test_eth_account.cairo | 4 +- src/tests/security/test_reentrancyguard.cairo | 1 - src/tests/token/erc1155/test_erc1155.cairo | 1 - src/tests/token/erc20/test_erc20_votes.cairo | 5 +- src/tests/token/erc721/test_erc721.cairo | 1 - src/token/erc1155/dual1155.cairo | 2 +- src/token/erc1155/dual1155_receiver.cairo | 2 +- src/token/erc1155/erc1155.cairo | 53 +- src/token/erc1155/erc1155_receiver.cairo | 2 +- src/token/erc1155/interface.cairo | 2 +- src/token/erc20/dual20.cairo | 4 +- src/token/erc20/erc20.cairo | 17 +- src/token/erc20/extensions/erc20_votes.cairo | 28 +- src/token/erc20/interface.cairo | 2 +- src/token/erc721/dual721.cairo | 2 +- src/token/erc721/dual721_receiver.cairo | 2 +- src/token/erc721/erc721.cairo | 78 +- src/token/erc721/erc721_receiver.cairo | 2 +- src/token/erc721/interface.cairo | 2 +- src/upgrades/interface.cairo | 2 +- src/upgrades/upgradeable.cairo | 4 +- src/utils.cairo | 2 +- src/utils/cryptography/interface.cairo | 2 +- src/utils/cryptography/nonces.cairo | 12 +- src/utils/cryptography/snip12.cairo | 2 +- src/utils/deployments.cairo | 10 +- src/utils/deployments/interface.cairo | 2 +- src/utils/math.cairo | 2 +- src/utils/selectors.cairo | 2 +- src/utils/serde.cairo | 2 +- src/utils/structs/checkpoint.cairo | 16 +- src/utils/structs/storage_array.cairo | 2 +- src/utils/unwrap_and_cast.cairo | 2 +- 110 files changed, 3238 insertions(+), 333 deletions(-) delete mode 100644 .codecov.yml create mode 100644 .github/actionlint-matcher.json create mode 100644 .github/workflows/actionlint.yml delete mode 100644 .gitmodules delete mode 100644 src/cairo_project.toml create mode 100644 src/governance/timelock.cairo create mode 100644 src/governance/timelock/interface.cairo create mode 100644 src/governance/timelock/timelock_controller.cairo create mode 100644 src/governance/timelock/utils.cairo create mode 100644 src/governance/timelock/utils/call_impls.cairo create mode 100644 src/tests/governance.cairo create mode 100644 src/tests/governance/test_timelock.cairo create mode 100644 src/tests/governance/test_utils.cairo create mode 100644 src/tests/mocks/timelock_mocks.cairo diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index 54616a49c..000000000 --- a/.codecov.yml +++ /dev/null @@ -1,11 +0,0 @@ -comment: off -github_checks: - annotations: false -coverage: - status: - patch: - default: - target: 95% - project: - default: - threshold: 1% diff --git a/.github/actionlint-matcher.json b/.github/actionlint-matcher.json new file mode 100644 index 000000000..09211db2f --- /dev/null +++ b/.github/actionlint-matcher.json @@ -0,0 +1,17 @@ +{ + "problemMatcher": [ + { + "owner": "actionlint", + "pattern": [ + { + "regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*: (?:\\x1b\\[\\d+m)*(.+?)(?:\\x1b\\[\\d+m)* \\[(.+?)\\]$", + "file": 1, + "line": 2, + "column": 3, + "message": 4, + "code": 5 + } + ] + } + ] + } diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml new file mode 100644 index 000000000..667a77682 --- /dev/null +++ b/.github/workflows/actionlint.yml @@ -0,0 +1,15 @@ +name: Lint workflows + +on: + pull_request: + paths: + - '.github/**/*.ya?ml' + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Add problem matchers + run: echo "::add-matcher::.github/actionlint-matcher.json" + - uses: docker://rhysd/actionlint:latest diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 6b0481046..23a2a7f95 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -10,23 +10,27 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Extract current versions run: | CURRENT_VERSION=$(grep '^version = ' Scarb.toml | sed 's/version = "\(.*\)"/\1/') SCARB_VERSION=$(grep 'scarb-version = ' Scarb.toml | sed 's/scarb-version = "\(.*\)"/\1/') - echo "CURRENT_VERSION=$CURRENT_VERSION" >> $GITHUB_ENV - echo "SCARB_VERSION=$SCARB_VERSION" >> $GITHUB_ENV + CAIRO_VERSION=$(grep 'cairo-version = ' Scarb.toml | sed 's/cairo-version = "\(.*\)"/\1/') + { + echo "CURRENT_VERSION=$CURRENT_VERSION" + echo "SCARB_VERSION=$SCARB_VERSION" + echo "CAIRO_VERSION=$CAIRO_VERSION" + } >> "$GITHUB_ENV" - name: Extract new version number - run: echo "NEW_VERSION=${GITHUB_REF#refs/heads/release-v}" >> $GITHUB_ENV + run: echo "NEW_VERSION=${GITHUB_REF#refs/heads/release-v}" >> "$GITHUB_ENV" - name: Replace version in files run: | echo "Current version: $CURRENT_VERSION" echo "New version: $NEW_VERSION" - ESCAPED_CURRENT_VERSION=$(echo $CURRENT_VERSION | sed 's/\./\\./g') + ESCAPED_CURRENT_VERSION="${CURRENT_VERSION//\./\\.}" find . -type f -not -path '*/\.*' -not -path './CHANGELOG.md' -not -path './docs/package-lock.json' \ -not -path './RELEASING.md' -exec sed -i "s/$ESCAPED_CURRENT_VERSION/$NEW_VERSION/g" {} + @@ -43,7 +47,7 @@ jobs: - name: Update presets page run: | - class_hash get --json | sed -e '1,4d' | python3 scripts/get_hashes_page.py $SCARB_VERSION \ + class_hash get --json | sed -e '1,4d' | python3 scripts/get_hashes_page.py "$CAIRO_VERSION" \ > ./docs/modules/ROOT/pages/utils/_class_hashes.adoc - name: Auto-commit changes diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1d37a35d6..7e7d36e0b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,28 +11,31 @@ jobs: name: Lint and test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Extract scarb version run: | SCARB_VERSION=$(grep 'scarb-version = ' Scarb.toml | sed 's/scarb-version = "\(.*\)"/\1/') - echo "SCARB_VERSION=$SCARB_VERSION" >> $GITHUB_ENV + echo "SCARB_VERSION=$SCARB_VERSION" >> "$GITHUB_ENV" - uses: software-mansion/setup-scarb@v1 with: scarb-version: ${{ env.SCARB_VERSION }} - name: Extract foundry version run: | FOUNDRY_VERSION=$(grep 'snforge_std = ' Scarb.toml | sed 's/snforge_std = .\+ tag = "v\(.*\)".*/\1/') - echo "FOUNDRY_VERSION=$FOUNDRY_VERSION" >> $GITHUB_ENV + echo "FOUNDRY_VERSION=$FOUNDRY_VERSION" >> "$GITHUB_ENV" - uses: foundry-rs/setup-snfoundry@v3 with: starknet-foundry-version: ${{ env.FOUNDRY_VERSION }} - name: Markdown lint - uses: DavidAnson/markdownlint-cli2-action@5b7c9f74fec47e6b15667b2cc23c63dff11e449e # v9 + uses: DavidAnson/markdownlint-cli2-action@b4c9feab76d8025d1e83c653fa3990936df0e6c8 # v16 with: globs: | *.md !PULL_REQUEST_TEMPLATE.md - name: Cairo lint run: scarb fmt --check + - name: Temporary USC manually install + run: | + curl -L https://raw.githubusercontent.com/software-mansion/universal-sierra-compiler/master/scripts/install.sh | sh -s -- v2.2.0-rc.1 - name: Cairo test run: snforge test diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 269eb8546..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "cairo"] - path = cairo - url = https://github.com/starkware-libs/cairo.git diff --git a/CHANGELOG.md b/CHANGELOG.md index 562be9606..9589aca28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- TimelockController component (#996) +- HashCall implementation (#996) + +### Changed + +- Bump scarb to v2.7.0-rc.1 (#1025) +- Bump scarb to v2.7.0-rc.2 (#1052) +- Bump scarb to v2.7.0-rc.4 (#1064) + +## 0.15.0-rc.0 (2024-07-8) + +### Changed + +- `Trace`, `Checkpoint`, and `StorageArray` structs made public. + +### Changed (Breaking) + +- Removed `num_checkpoints` and `checkpoints` from `ERC20VotesABI`. + ## 0.14.0 (2024-06-14) ### Changed (Breaking) diff --git a/README.md b/README.md index b5750a91e..beee9ab5a 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Edit `scarb.toml` and add: ```toml [dependencies] -openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.14.0" } +openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.15.0-rc.0" } ``` Build the project to download it: @@ -105,7 +105,7 @@ mod MyToken { ### Unsupported -[`DualCase` dispatchers](https://docs.openzeppelin.com/contracts-cairo/0.14.0/interfaces#dualcase_dispatchers) rely on Sierra's ability to catch a revert to resume execution. Currently, Starknet live chains (testnets and mainnet) don't implement that behavior. Starknet's testing framework does support it. +[`DualCase` dispatchers](https://docs.openzeppelin.com/contracts-cairo/0.15.0-rc.0/interfaces#dualcase_dispatchers) rely on Sierra's ability to catch a revert to resume execution. Currently, Starknet live chains (testnets and mainnet) don't implement that behavior. Starknet's testing framework does support it. ## Learn @@ -155,8 +155,8 @@ git clone git@github.com:OpenZeppelin/cairo-contracts.git $ cd cairo-contracts $ scarb build -Compiling lib(openzeppelin) openzeppelin v0.14.0 (~/cairo-contracts/Scarb.toml) -Compiling starknet-contract(openzeppelin) openzeppelin v0.14.0 (~/cairo-contracts/Scarb.toml) +Compiling lib(openzeppelin) openzeppelin v0.15.0-rc.0 (~/cairo-contracts/Scarb.toml) +Compiling starknet-contract(openzeppelin) openzeppelin v0.15.0-rc.0 (~/cairo-contracts/Scarb.toml) Finished release target(s) in 16 seconds ``` diff --git a/SECURITY.md b/SECURITY.md index 8bd19014b..7084b6069 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -3,4 +3,4 @@ > ⚠️ Warning! ⚠️ > This project is still in a very early and experimental phase. It has never been audited nor thoroughly reviewed for security vulnerabilities. Do not use in production. -Please report any security issues you find to security@openzeppelin.com. +Please report any security issues you find to . diff --git a/Scarb.lock b/Scarb.lock index 524489827..8e9562d62 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "openzeppelin" -version = "0.14.0" +version = "0.15.0-rc.0" dependencies = [ "snforge_std", ] diff --git a/Scarb.toml b/Scarb.toml index 935224176..0c175288a 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,9 +1,9 @@ [package] name = "openzeppelin" -version = "0.14.0" +version = "0.15.0-rc.0" edition = "2023_11" -cairo-version = "2.6.4" -scarb-version = "2.6.5" +cairo-version = "2.7.0-rc.3" +scarb-version = "2.7.0-rc.4" authors = ["OpenZeppelin Community "] description = "OpenZeppelin Contracts written in Cairo for StarkNet, a decentralized ZK Rollup" documentation = "https://docs.openzeppelin.com/contracts-cairo" @@ -13,7 +13,7 @@ license-file = "LICENSE" keywords = ["openzeppelin", "starknet", "cairo", "contracts", "security", "standards"] [dependencies] -starknet = "2.6.4" +starknet = "2.7.0-rc.3" snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.26.0" } [lib] diff --git a/docs/antora.yml b/docs/antora.yml index 1e484920d..625262280 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -1,6 +1,6 @@ name: contracts-cairo title: Contracts for Cairo -version: 0.14.0 +version: 0.15.0-rc.0 nav: - modules/ROOT/nav.adoc asciidoc: diff --git a/docs/modules/ROOT/pages/accounts.adoc b/docs/modules/ROOT/pages/accounts.adoc index b6aaa2e48..bf064a01d 100644 --- a/docs/modules/ROOT/pages/accounts.adoc +++ b/docs/modules/ROOT/pages/accounts.adoc @@ -204,7 +204,6 @@ Here’s an example of a basic contract: mod MyEthAccount { use openzeppelin::account::EthAccountComponent; use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin::introspection::src5::SRC5Component; use starknet::ClassHash; @@ -389,7 +388,6 @@ First, let's take the example account we created before and deploy it: mod MyEthAccount { use openzeppelin::account::EthAccountComponent; use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin::introspection::src5::SRC5Component; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); diff --git a/docs/modules/ROOT/pages/api/access.adoc b/docs/modules/ROOT/pages/api/access.adoc index 5338692ce..1b362e728 100644 --- a/docs/modules/ROOT/pages/api/access.adoc +++ b/docs/modules/ROOT/pages/api/access.adoc @@ -20,7 +20,7 @@ assigned each to multiple accounts. [.contract] [[OwnableComponent]] -=== `++OwnableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/access/ownable/ownable.cairo[{github-icon},role=heading-link] +=== `++OwnableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/access/ownable/ownable.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::access::ownable::OwnableComponent; @@ -267,7 +267,7 @@ Emitted when the ownership is transferred. [.contract] [[IAccessControl]] -=== `++IAccessControl++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/access/accesscontrol/interface.cairo[{github-icon},role=heading-link] +=== `++IAccessControl++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/access/accesscontrol/interface.cairo[{github-icon},role=heading-link] :grant_role: xref:#IAccessControl-grant_role[grant_role] :revoke_role: xref:#IAccessControl-revoke_role[revoke_role] @@ -400,7 +400,7 @@ Emitted when `account` is revoked `role`. [.contract] [[AccessControlComponent]] -=== `++AccessControlComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/access/accesscontrol/accesscontrol.cairo[{github-icon},role=heading-link] +=== `++AccessControlComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/access/accesscontrol/accesscontrol.cairo[{github-icon},role=heading-link] :assert_only_role: xref:#AccessControlComponent-assert_only_role :grant_role: xref:#AccessControlComponent-grant_role[grant_role] diff --git a/docs/modules/ROOT/pages/api/account.adoc b/docs/modules/ROOT/pages/api/account.adoc index 04cd5e9f4..c5ece578d 100644 --- a/docs/modules/ROOT/pages/api/account.adoc +++ b/docs/modules/ROOT/pages/api/account.adoc @@ -12,7 +12,7 @@ include::../utils/_common.adoc[] [.contract] [[ISRC6]] -=== `++ISRC6++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/account/interface.cairo[{github-icon},role=heading-link] +=== `++ISRC6++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/account/interface.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::account::interface::ISRC6; @@ -65,7 +65,7 @@ Returns the short string `'VALID'` if valid, otherwise it reverts. [.contract] [[AccountComponent]] -=== `++AccountComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/account/account.cairo[{github-icon},role=heading-link] +=== `++AccountComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/account/account.cairo[{github-icon},role=heading-link] :OwnerAdded: xref:AccountComponent-OwnerAdded[OwnerAdded] :OwnerRemoved: xref:AccountComponent-OwnerRemoved[OwnerRemoved] @@ -315,7 +315,7 @@ Emitted when a `public_key` is removed. [.contract] [[EthAccountComponent]] -=== `++EthAccountComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/account/eth_account.cairo[{github-icon},role=heading-link] +=== `++EthAccountComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/account/eth_account.cairo[{github-icon},role=heading-link] :OwnerAdded: xref:EthAccountComponent-OwnerAdded[OwnerAdded] :OwnerRemoved: xref:EthAccountComponent-OwnerRemoved[OwnerRemoved] @@ -570,7 +570,7 @@ Emitted when a `public_key` is removed. [.contract] [[AccountUpgradeable]] -=== `++AccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets/account.cairo[{github-icon},role=heading-link] +=== `++AccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets/account.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::presets::AccountUpgradeable; @@ -631,7 +631,7 @@ Requirements: [.contract] [[EthAccountUpgradeable]] -=== `++EthAccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets/eth_account.cairo[{github-icon},role=heading-link] +=== `++EthAccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets/eth_account.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::presets::EthAccountUpgradeable; diff --git a/docs/modules/ROOT/pages/api/erc1155.adoc b/docs/modules/ROOT/pages/api/erc1155.adoc index 029cf84e3..20846ec46 100644 --- a/docs/modules/ROOT/pages/api/erc1155.adoc +++ b/docs/modules/ROOT/pages/api/erc1155.adoc @@ -16,7 +16,7 @@ TIP: For an overview of ERC1155, read our xref:erc1155.adoc[ERC1155 guide]. [.contract] [[IERC1155]] -=== `++IERC1155++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc1155/interface.cairo[{github-icon},role=heading-link] +=== `++IERC1155++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc1155/interface.cairo[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -126,7 +126,7 @@ Emitted when the token URI is updated to `value` for the `id` token. [.contract] [[IERC1155MetadataURI]] -=== `++IERC1155MetadataURI++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc1155/interface.cairo[{github-icon},role=heading-link] +=== `++IERC1155MetadataURI++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc1155/interface.cairo[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -156,7 +156,7 @@ Returns the Uniform Resource Identifier (URI) for the `token_id` token. [.contract] [[ERC1155Component]] -=== `++ERC1155Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc1155/erc1155.cairo[{github-icon},role=heading-link] +=== `++ERC1155Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc1155/erc1155.cairo[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -543,7 +543,7 @@ See <>. [.contract] [[IERC1155Receiver]] -=== `++IERC1155Receiver++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc1155/interface.cairo[{github-icon},role=heading-link] +=== `++IERC1155Receiver++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc1155/interface.cairo[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -583,7 +583,7 @@ via <> by [.contract] [[ERC1155ReceiverComponent]] -=== `++ERC1155ReceiverComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc1155/erc1155_receiver.cairo[{github-icon},role=heading-link] +=== `++ERC1155ReceiverComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc1155/erc1155_receiver.cairo[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -660,7 +660,7 @@ Registers the `IERC1155Receiver` interface ID as supported through introspection [.contract] [[ERC1155Upgradeable]] -=== `++ERC1155Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets/erc1155.cairo[{github-icon},role=heading-link] +=== `++ERC1155Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets/erc1155.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::presets::ERC1155; diff --git a/docs/modules/ROOT/pages/api/erc20.adoc b/docs/modules/ROOT/pages/api/erc20.adoc index 48e2f7349..05fe286fd 100644 --- a/docs/modules/ROOT/pages/api/erc20.adoc +++ b/docs/modules/ROOT/pages/api/erc20.adoc @@ -16,7 +16,7 @@ TIP: For an overview of ERC20, read our {erc20-guide}. [.contract] [[IERC20]] -=== `++IERC20++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc20/interface.cairo[{github-icon},role=heading-link] +=== `++IERC20++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc20/interface.cairo[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -114,7 +114,7 @@ Emitted when the allowance of a `spender` for an `owner` is set. [.contract] [[IERC20Metadata]] -=== `++IERC20Metadata++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc20/interface.cairo#L19[{github-icon},role=heading-link] +=== `++IERC20Metadata++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc20/interface.cairo#L19[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -162,7 +162,7 @@ NOTE: This information is only used for _display_ purposes: it in no way affects [.contract] [[ERC20Component]] -=== `++ERC20Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc20/erc20.cairo[{github-icon},role=heading-link] +=== `++ERC20Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc20/erc20.cairo[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -460,7 +460,7 @@ See <>. [.contract] [[ERC20VotesComponent]] -=== `++ERC20VotesComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc20/extensions/erc20_votes.cairo[{github-icon},role=heading-link] +=== `++ERC20VotesComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc20/extensions/erc20_votes.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::token::extensions::ERC20VotesComponent; @@ -506,6 +506,7 @@ By default, token balance does not account for voting power. This makes transfer * xref:#ERC20VotesComponent-_delegate[`++_delegate(self, account, delegatee)++`] * xref:#ERC20VotesComponent-move_delegate_votes[`++move_delegate_votes(self, from, to, amount)++`] * xref:#ERC20VotesComponent-transfer_voting_units[`++transfer_voting_units(self, from, to, amount)++`] +* xref:#ERC20VotesComponent-num_checkpoints[`++num_checkpoints(self, account)++`] * xref:#ERC20VotesComponent-checkpoints[`++checkpoints(self, account, pos)++`] * xref:#ERC20VotesComponent-get_voting_units[`++get_voting_units(self, account)++`] -- @@ -654,7 +655,7 @@ Emitted when `delegate` votes are updated from `previous_votes` to `new_votes`. [.contract] [[ERC20Upgradeable]] -=== `++ERC20Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets/erc20.cairo[{github-icon},role=heading-link] +=== `++ERC20Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets/erc20.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::presets::ERC20Upgradeable; diff --git a/docs/modules/ROOT/pages/api/erc721.adoc b/docs/modules/ROOT/pages/api/erc721.adoc index ecf4b7a97..09ab75d29 100644 --- a/docs/modules/ROOT/pages/api/erc721.adoc +++ b/docs/modules/ROOT/pages/api/erc721.adoc @@ -16,7 +16,7 @@ TIP: For an overview of ERC721, read our xref:erc721.adoc[ERC721 guide]. [.contract] [[IERC721]] -=== `++IERC721++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc721/interface.cairo#L13-L31[{github-icon},role=heading-link] +=== `++IERC721++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc721/interface.cairo#L13-L31[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -135,7 +135,7 @@ Emitted when `token_id` token is transferred from `from` to `to`. [.contract] [[IERC721Metadata]] -=== `++IERC721Metadata++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc721/interface.cairo#L54-L59[{github-icon},role=heading-link] +=== `++IERC721Metadata++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc721/interface.cairo#L54-L59[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -181,7 +181,7 @@ If the URI is not set for `token_id`, the return value will be an empty `ByteArr [.contract] [[ERC721Component]] -=== `++ERC721Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc721/erc721.cairo#L7[{github-icon},role=heading-link] +=== `++ERC721Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc721/erc721.cairo#L7[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -693,7 +693,7 @@ See <>. [.contract] [[IERC721Receiver]] -=== `++IERC721Receiver++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc721/interface.cairo#L70-L79[{github-icon},role=heading-link] +=== `++IERC721Receiver++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc721/interface.cairo#L70-L79[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -724,7 +724,7 @@ Whenever an IERC721 `token_id` token is transferred to this non-account contract [.contract] [[ERC721ReceiverComponent]] -=== `++ERC721ReceiverComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/token/erc721/erc721_receiver.cairo[{github-icon},role=heading-link] +=== `++ERC721ReceiverComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/token/erc721/erc721_receiver.cairo[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo @@ -790,7 +790,7 @@ Registers the `IERC721Receiver` interface ID as supported through introspection. [.contract] [[ERC721Upgradeable]] -=== `++ERC721Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets/erc721.cairo[{github-icon},role=heading-link] +=== `++ERC721Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets/erc721.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::presets::ERC721Upgradeable; diff --git a/docs/modules/ROOT/pages/api/governance.adoc b/docs/modules/ROOT/pages/api/governance.adoc index 1d2451eb2..997815023 100644 --- a/docs/modules/ROOT/pages/api/governance.adoc +++ b/docs/modules/ROOT/pages/api/governance.adoc @@ -8,7 +8,7 @@ Reference of interfaces and utilities related to Governance. [.contract] [[IVotes]] -=== `++IVotes++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/governance/utils/interfaces/votes.cairo[{github-icon},role=heading-link] +=== `++IVotes++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/governance/utils/interfaces/votes.cairo[{github-icon},role=heading-link] [.hljs-theme-dark] ```cairo diff --git a/docs/modules/ROOT/pages/api/introspection.adoc b/docs/modules/ROOT/pages/api/introspection.adoc index c1e35dcba..77fb3b2b9 100644 --- a/docs/modules/ROOT/pages/api/introspection.adoc +++ b/docs/modules/ROOT/pages/api/introspection.adoc @@ -10,7 +10,7 @@ Reference of interfaces and utilities related to https://en.wikipedia.org/wiki/T [.contract] [[ISRC5]] -=== `++ISRC5++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/introspection/interface.cairo#L7[{github-icon},role=heading-link] +=== `++ISRC5++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/introspection/interface.cairo#L7[{github-icon},role=heading-link] ```cairo use openzeppelin::introspection::interface::ISRC5; @@ -44,7 +44,7 @@ on how to compute this ID. [.contract] [[SRC5Component]] -=== `++SRC5Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/introspection/src5.cairo[{github-icon},role=heading-link] +=== `++SRC5Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/introspection/src5.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::introspection::src5::SRC5Component; diff --git a/docs/modules/ROOT/pages/api/security.adoc b/docs/modules/ROOT/pages/api/security.adoc index 02b137467..3a6558408 100644 --- a/docs/modules/ROOT/pages/api/security.adoc +++ b/docs/modules/ROOT/pages/api/security.adoc @@ -8,7 +8,7 @@ Reference of components, interfaces and utilities found in the library's `securi [.contract] [[InitializableComponent]] -=== `++InitializableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/security/initializable.cairo[{github-icon},role=heading-link] +=== `++InitializableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/security/initializable.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::security::InitializableComponent; @@ -58,7 +58,7 @@ Requirements: [.contract] [[PausableComponent]] -=== `++PausableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/security/pausable.cairo[{github-icon},role=heading-link] +=== `++PausableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/security/pausable.cairo[{github-icon},role=heading-link] :Paused: xref:PausableComponent-Paused[Paused] :Unpaused: xref:PausableComponent-Unpaused[Unpaused] @@ -163,7 +163,7 @@ Emitted when the contract is unpaused by `account`. [.contract] [[ReentrancyGuardComponent]] -=== `++ReentrancyGuardComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/security/reentrancyguard.cairo[{github-icon},role=heading-link] +=== `++ReentrancyGuardComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/security/reentrancyguard.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::security::ReentrancyGuardComponent; diff --git a/docs/modules/ROOT/pages/api/upgrades.adoc b/docs/modules/ROOT/pages/api/upgrades.adoc index c7673fbf2..08060dd87 100644 --- a/docs/modules/ROOT/pages/api/upgrades.adoc +++ b/docs/modules/ROOT/pages/api/upgrades.adoc @@ -9,7 +9,7 @@ Reference of interfaces and utilities related to upgradeability. [.contract] [[IUpgradeable]] -=== `++IUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/upgrades/interface.cairo#L3[{github-icon},role=heading-link] +=== `++IUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/upgrades/interface.cairo#L3[{github-icon},role=heading-link] :Upgraded: xref:UpgradeableComponent-Upgraded[Upgraded] @@ -38,7 +38,7 @@ NOTE: This function is usually protected by an xref:access.adoc[Access Control] [.contract] [[UpgradeableComponent]] -=== `++UpgradeableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/upgrades/upgradeable.cairo[{github-icon},role=heading-link] +=== `++UpgradeableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/upgrades/upgradeable.cairo[{github-icon},role=heading-link] ```cairo use openzeppelin::upgrades::upgradeable::UpgradeableComponent; diff --git a/docs/modules/ROOT/pages/api/utilities.adoc b/docs/modules/ROOT/pages/api/utilities.adoc index 3feaa991f..d103d311d 100644 --- a/docs/modules/ROOT/pages/api/utilities.adoc +++ b/docs/modules/ROOT/pages/api/utilities.adoc @@ -261,7 +261,7 @@ NOTE: `T` is a generic value matching different numeric implementations. use openzeppelin::utils::selectors; ``` -:selectors: https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/utils/selectors.cairo[selectors.cairo] +:selectors: https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/utils/selectors.cairo[selectors.cairo] Module containing constants matching multiple selectors used through the library. To see the full list of selectors, see {selectors}. diff --git a/docs/modules/ROOT/pages/guides/snip12.adoc b/docs/modules/ROOT/pages/guides/snip12.adoc index 1ad4c134e..fb919e065 100644 --- a/docs/modules/ROOT/pages/guides/snip12.adoc +++ b/docs/modules/ROOT/pages/guides/snip12.adoc @@ -163,9 +163,25 @@ impl SNIP12MetadataImpl of SNIP12Metadata { } ---- -NOTE: These params could be set in the contract constructor, but then two storage reads would be executed every time -a message hash needs to be generated, and this is unnecessary overhead. When Starknet implements immutable storage -set in constructor, that approach will be more efficient. +In the above example, no storage reads are required which avoids unnecessary extra gas costs, but in +some cases we may need to read from storage to get the domain separator values. This can be accomplished even when +the trait is not bounded to the ContractState, like this: + +[,cairo] +---- +use openzeppelin::utils::snip12::SNIP12Metadata; + +impl SNIP12MetadataImpl of SNIP12Metadata { + fn name() -> felt252 { + let state = unsafe_new_contract_state(); + + // Some logic to get the name from storage + state.erc20.name().at(0).unwrap().into() + } + + fn version() -> felt252 { 'v1' } +} +---- === 5. Generate the hash. diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 77a1f138e..41e20d036 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -20,9 +20,9 @@ before proceeding, and run the following command to check that the installation ---- $ scarb --version -scarb 2.6.5 (d49f54394 2024-06-11) -cairo: 2.6.4 (https://crates.io/crates/cairo-lang-compiler/2.6.4) -sierra: 1.5.0 +scarb 2.7.0-rc.4 (88bf93564 2024-07-19) +cairo: 2.7.0-rc.3 (https://crates.io/crates/cairo-lang-compiler/2.7.0-rc.3) +sierra: 1.6.0 ---- === Set up your project @@ -57,7 +57,7 @@ Install the library by declaring it as a dependency in the project's `Scarb.toml [,text] ---- [dependencies] -openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.14.0" } +openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.15.0-rc.0" } ---- WARNING: Make sure the tag matches the target release. @@ -113,4 +113,4 @@ You can now compile it: [,bash] ---- scarb build ----- \ No newline at end of file +---- diff --git a/docs/modules/ROOT/pages/presets.adoc b/docs/modules/ROOT/pages/presets.adoc index f0a3f8ce3..3f56743f1 100644 --- a/docs/modules/ROOT/pages/presets.adoc +++ b/docs/modules/ROOT/pages/presets.adoc @@ -53,7 +53,7 @@ TIP: {starkli} class-hash command can be used to compute the class hash from a S :setup_project: xref:index.adoc#set_up_your_project[setting up a project] :install_lib: xref:index.adoc#install the_library[installing the Contracts for Cairo library] -:presets_dir: link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/presets[presets directory] +:presets_dir: link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/presets[presets directory] These preset contracts are ready-to-deploy which means they should already be declared on the Sepolia network. Simply deploy the preset class hash and add the appropriate constructor arguments. diff --git a/docs/modules/ROOT/pages/udc.adoc b/docs/modules/ROOT/pages/udc.adoc index d0af0dd0c..fd30ce729 100644 --- a/docs/modules/ROOT/pages/udc.adoc +++ b/docs/modules/ROOT/pages/udc.adoc @@ -56,7 +56,7 @@ fn deploy() -> ContractAddress { >(); let salt = 1234567879; let from_zero = false; - let mut calldata = array![]; + let calldata = array![]; // The UDC returns the deployed contract address dispatcher.deploy_contract(class_hash, salt, from_zero, calldata.span()) diff --git a/docs/modules/ROOT/pages/upgrades.adoc b/docs/modules/ROOT/pages/upgrades.adoc index dff92c758..3f58469e0 100644 --- a/docs/modules/ROOT/pages/upgrades.adoc +++ b/docs/modules/ROOT/pages/upgrades.adoc @@ -1,7 +1,7 @@ :contract_classes: https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/contract-classes/[Contract Classes] :class_hash: https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash/[class hash] :replace_class_syscall: https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#replace_class[replace_class] -:upgradeable: https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.14.0/src/upgrades/upgradeable.cairo[Upgradeable] +:upgradeable: https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.15.0-rc.0/src/upgrades/upgradeable.cairo[Upgradeable] :ownable: xref:access.adoc#ownership_and_ownable[Ownable] :i_upgradeable: xref:api/upgrades.adoc#IUpgradeable[IUpgradeable] :library_calls: https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/system-calls-cairo1/#library_call[library calls] diff --git a/docs/modules/ROOT/pages/utils/_class_hashes.adoc b/docs/modules/ROOT/pages/utils/_class_hashes.adoc index 1ca009026..8c722bd41 100644 --- a/docs/modules/ROOT/pages/utils/_class_hashes.adoc +++ b/docs/modules/ROOT/pages/utils/_class_hashes.adoc @@ -1,13 +1,13 @@ // Version -:class-hash-cairo-version: https://crates.io/crates/cairo-lang-compiler/2.6.3[cairo 2.6.3] +:class-hash-cairo-version: https://crates.io/crates/cairo-lang-compiler/2.6.4[cairo 2.6.4] // Class Hashes -:ERC20Upgradeable-class-hash: 0x040b9e69e14ddc34a98ec8133c80807c144b818bc6cbf5a119d8f62535258142 -:ERC721Upgradeable-class-hash: 0x00f56255bf8db96498c71884407f3b623f20a5d507cbb7c41deeeb65a1bf8725 -:ERC1155Upgradeable-class-hash: 0x017baa69866decbb1ac5e6d5ef2e69b7d5dd7113111a8cc51a48f01854df571f -:AccountUpgradeable-class-hash: 0x00e2eb8f5672af4e6a4e8a8f1b44989685e668489b0a25437733756c5a34a1d6 -:EthAccountUpgradeable-class-hash: 0x0169e64bc8a60422da86e6cc821c498d2f8cba60888399ce4be86690aaa51e4a -:UniversalDeployer-class-hash: 0x0536e18e3e9820b48e0477e83e0a4d6d923ccddc06deb61585dfd7402dd40733 +:ERC20Upgradeable-class-hash: 0x02718db92cfa9342bd19306fb1d10cb5c61385293b4bdaac23c36577dd7ed882 +:ERC721Upgradeable-class-hash: 0x07e6fe2c473ea7018e3db87712497deae535694870d8265203212ddbdca1642d +:ERC1155Upgradeable-class-hash: 0x06cb57fea4ed34a68db38e3b2ca46b3ad39b123952b31e10e79c5ea3a1eb0a20 +:AccountUpgradeable-class-hash: 0x04343194a4a6082192502e132d9e7834b5d9bfc7a0c1dd990e95b66f85a66d46 +:EthAccountUpgradeable-class-hash: 0x02203673e728fa07de1c2ea60405399ffefaf875f1b7ae54e747659e1e216d94 +:UniversalDeployer-class-hash: 0x03a901e3f8d717544d07df0043dcdd6537c1ae4c046674599793783f73511155 // Presets page :presets-page: xref:presets.adoc[Sierra class hash] diff --git a/docs/modules/ROOT/pages/wizard.adoc b/docs/modules/ROOT/pages/wizard.adoc index c98a6b489..b18c0ddc4 100644 --- a/docs/modules/ROOT/pages/wizard.adoc +++ b/docs/modules/ROOT/pages/wizard.adoc @@ -10,5 +10,5 @@ NOTE: We strongly recommend checking the xref:components.adoc[Components] sectio ++++ - + ++++ diff --git a/src/access/accesscontrol/accesscontrol.cairo b/src/access/accesscontrol/accesscontrol.cairo index 3f320d988..891b3a270 100644 --- a/src/access/accesscontrol/accesscontrol.cairo +++ b/src/access/accesscontrol/accesscontrol.cairo @@ -13,11 +13,12 @@ pub mod AccessControlComponent { use openzeppelin::introspection::src5::SRC5Component; use starknet::ContractAddress; use starknet::get_caller_address; + use starknet::storage::Map; #[storage] struct Storage { - AccessControl_role_admin: LegacyMap, - AccessControl_role_member: LegacyMap<(felt252, ContractAddress), bool>, + AccessControl_role_admin: Map, + AccessControl_role_member: Map<(felt252, ContractAddress), bool>, } #[event] @@ -96,7 +97,7 @@ pub mod AccessControlComponent { fn grant_role( ref self: ComponentState, role: felt252, account: ContractAddress ) { - let admin = AccessControl::get_role_admin(@self, role); + let admin = Self::get_role_admin(@self, role); self.assert_only_role(admin); self._grant_role(role, account); } @@ -111,7 +112,7 @@ pub mod AccessControlComponent { fn revoke_role( ref self: ComponentState, role: felt252, account: ContractAddress ) { - let admin = AccessControl::get_role_admin(@self, role); + let admin = Self::get_role_admin(@self, role); self.assert_only_role(admin); self._revoke_role(role, account); } diff --git a/src/access/accesscontrol/dual_accesscontrol.cairo b/src/access/accesscontrol/dual_accesscontrol.cairo index b9cca51f9..82b4f9256 100644 --- a/src/access/accesscontrol/dual_accesscontrol.cairo +++ b/src/access/accesscontrol/dual_accesscontrol.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (access/accesscontrol/dual_accesscontrol.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (access/accesscontrol/dual_accesscontrol.cairo) use openzeppelin::utils::UnwrapAndCast; use openzeppelin::utils::selectors; diff --git a/src/access/accesscontrol/interface.cairo b/src/access/accesscontrol/interface.cairo index 8487b007f..9af3f87f7 100644 --- a/src/access/accesscontrol/interface.cairo +++ b/src/access/accesscontrol/interface.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (access/accesscontrol/interface.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (access/accesscontrol/interface.cairo) use starknet::ContractAddress; diff --git a/src/access/ownable/dual_ownable.cairo b/src/access/ownable/dual_ownable.cairo index d4ae86aa2..1695e3e2d 100644 --- a/src/access/ownable/dual_ownable.cairo +++ b/src/access/ownable/dual_ownable.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (access/ownable/dual_ownable.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (access/ownable/dual_ownable.cairo) use openzeppelin::utils::UnwrapAndCast; use openzeppelin::utils::selectors; @@ -42,7 +42,7 @@ impl DualCaseOwnableImpl of DualCaseOwnableTrait { } fn renounce_ownership(self: @DualCaseOwnable) { - let mut args = array![]; + let args = array![]; try_selector_with_fallback( *self.contract_address, diff --git a/src/access/ownable/interface.cairo b/src/access/ownable/interface.cairo index 591eb4fa7..2f6b11578 100644 --- a/src/access/ownable/interface.cairo +++ b/src/access/ownable/interface.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (access/ownable/interface.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (access/ownable/interface.cairo) use starknet::ContractAddress; diff --git a/src/access/ownable/ownable.cairo b/src/access/ownable/ownable.cairo index c60b214e1..8443a23ff 100644 --- a/src/access/ownable/ownable.cairo +++ b/src/access/ownable/ownable.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (access/ownable/ownable.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (access/ownable/ownable.cairo) /// # Ownable Component /// diff --git a/src/account/account.cairo b/src/account/account.cairo index c13192540..b63d756d4 100644 --- a/src/account/account.cairo +++ b/src/account/account.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (account/account.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (account/account.cairo) /// # Account Component /// @@ -327,8 +327,8 @@ pub mod AccountComponent { /// Validates that `new_owner` accepted the ownership of the contract. /// - /// WARNING: This function assumes that `current_owner` is the current owner of the contract, and - /// does not validate this assumption. + /// WARNING: This function assumes that `current_owner` is the current owner of the + /// contract, and does not validate this assumption. /// /// Requirements: /// diff --git a/src/account/dual_account.cairo b/src/account/dual_account.cairo index 3c0d33c14..dd9e4be34 100644 --- a/src/account/dual_account.cairo +++ b/src/account/dual_account.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (account/dual_account.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (account/dual_account.cairo) use openzeppelin::utils::UnwrapAndCast; use openzeppelin::utils::selectors; diff --git a/src/account/dual_eth_account.cairo b/src/account/dual_eth_account.cairo index eee086574..22cd39f9e 100644 --- a/src/account/dual_eth_account.cairo +++ b/src/account/dual_eth_account.cairo @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (account/dual_eth_account.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (account/dual_eth_account.cairo) use openzeppelin::account::interface::EthPublicKey; -use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin::utils::UnwrapAndCast; use openzeppelin::utils::selectors; use openzeppelin::utils::serde::SerializedAppend; diff --git a/src/account/eth_account.cairo b/src/account/eth_account.cairo index cb8082932..61eb038af 100644 --- a/src/account/eth_account.cairo +++ b/src/account/eth_account.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (account/eth_account.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (account/eth_account.cairo) /// # EthAccount Component /// @@ -12,7 +12,7 @@ pub mod EthAccountComponent { use core::starknet::secp256_trait::Secp256PointTrait; use openzeppelin::account::interface::EthPublicKey; use openzeppelin::account::interface; - use openzeppelin::account::utils::secp256k1::{Secp256k1PointSerde, Secp256k1PointStorePacking}; + use openzeppelin::account::utils::secp256k1::Secp256k1PointStorePacking; use openzeppelin::account::utils::{MIN_TRANSACTION_VERSION, QUERY_VERSION, QUERY_OFFSET}; use openzeppelin::account::utils::{execute_calls, is_valid_eth_signature}; use openzeppelin::introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; @@ -333,8 +333,8 @@ pub mod EthAccountComponent { /// Validates that `new_owner` accepted the ownership of the contract. /// - /// WARNING: This function assumes that `current_owner` is the current owner of the contract, and - /// does not validate this assumption. + /// WARNING: This function assumes that `current_owner` is the current owner of the + /// contract, and does not validate this assumption. /// /// Requirements: /// diff --git a/src/account/interface.cairo b/src/account/interface.cairo index 957a0e5e9..3b7e8f69d 100644 --- a/src/account/interface.cairo +++ b/src/account/interface.cairo @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (account/interface.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (account/interface.cairo) -use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use starknet::ContractAddress; use starknet::account::Call; diff --git a/src/account/utils.cairo b/src/account/utils.cairo index 8dfe7b49d..6fed1e68e 100644 --- a/src/account/utils.cairo +++ b/src/account/utils.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (account/utils.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (account/utils.cairo) pub mod secp256k1; pub mod signature; @@ -15,7 +15,7 @@ pub const QUERY_OFFSET: u256 = 0x100000000000000000000000000000000; pub const QUERY_VERSION: u256 = 0x100000000000000000000000000000001; pub fn execute_calls(mut calls: Array) -> Array> { - let mut res = ArrayTrait::new(); + let mut res = array![]; loop { match calls.pop_front() { Option::Some(call) => { diff --git a/src/account/utils/secp256k1.cairo b/src/account/utils/secp256k1.cairo index 084ee6ddc..fe4f00695 100644 --- a/src/account/utils/secp256k1.cairo +++ b/src/account/utils/secp256k1.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (account/utils/secp256k1.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (account/utils/secp256k1.cairo) use core::fmt::{Debug, Formatter, Error}; use starknet::SyscallResultTrait; @@ -11,7 +11,8 @@ use starknet::storage_access::StorePacking; /// /// The packing is done as follows: /// - First felt contains x.low (x being the x-coordinate of the point). -/// - Second felt contains x.high and the parity bit, at the least significant bits (2 * x.high + parity). +/// - Second felt contains x.high and the parity bit, at the least significant bits (2 * x.high + +/// parity). pub impl Secp256k1PointStorePacking of StorePacking { fn pack(value: Secp256k1Point) -> (felt252, felt252) { let (x, y) = value.get_coordinates().unwrap_syscall(); @@ -38,17 +39,6 @@ pub impl Secp256k1PointStorePacking of StorePacking { - fn serialize(self: @Secp256k1Point, ref output: Array) { - let point = (*self).get_coordinates().unwrap_syscall(); - point.serialize(ref output) - } - fn deserialize(ref serialized: Span) -> Option { - let (x, y) = Serde::<(u256, u256)>::deserialize(ref serialized)?; - Secp256Trait::secp256_ec_new_syscall(x, y).unwrap_syscall() - } -} - pub(crate) impl Secp256k1PointPartialEq of PartialEq { #[inline(always)] fn eq(lhs: @Secp256k1Point, rhs: @Secp256k1Point) -> bool { diff --git a/src/account/utils/signature.cairo b/src/account/utils/signature.cairo index 13caa8391..f247df83f 100644 --- a/src/account/utils/signature.cairo +++ b/src/account/utils/signature.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (account/utils/signature.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (account/utils/signature.cairo) use core::ecdsa::check_ecdsa_signature; use openzeppelin::account::interface::EthPublicKey; diff --git a/src/cairo_project.toml b/src/cairo_project.toml deleted file mode 100644 index badca57cd..000000000 --- a/src/cairo_project.toml +++ /dev/null @@ -1,2 +0,0 @@ -[crate_roots] -openzeppelin = "." diff --git a/src/governance.cairo b/src/governance.cairo index b5614dd82..01d740d38 100644 --- a/src/governance.cairo +++ b/src/governance.cairo @@ -1 +1,2 @@ +pub mod timelock; pub mod utils; diff --git a/src/governance/timelock.cairo b/src/governance/timelock.cairo new file mode 100644 index 000000000..0abcf6e3b --- /dev/null +++ b/src/governance/timelock.cairo @@ -0,0 +1,9 @@ +pub mod interface; +pub mod timelock_controller; +pub mod utils; + +pub use timelock_controller::OperationState; +pub use timelock_controller::TimelockControllerComponent::{ + PROPOSER_ROLE, CANCELLER_ROLE, EXECUTOR_ROLE +}; +pub use timelock_controller::TimelockControllerComponent; diff --git a/src/governance/timelock/interface.cairo b/src/governance/timelock/interface.cairo new file mode 100644 index 000000000..0c89d0c20 --- /dev/null +++ b/src/governance/timelock/interface.cairo @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (governance/timelock/interface.cairo) + +use openzeppelin::governance::timelock::OperationState; +use starknet::ContractAddress; +use starknet::account::Call; + +#[starknet::interface] +pub trait ITimelock { + fn is_operation(self: @TState, id: felt252) -> bool; + fn is_operation_pending(self: @TState, id: felt252) -> bool; + fn is_operation_ready(self: @TState, id: felt252) -> bool; + fn is_operation_done(self: @TState, id: felt252) -> bool; + fn get_timestamp(self: @TState, id: felt252) -> u64; + fn get_operation_state(self: @TState, id: felt252) -> OperationState; + fn get_min_delay(self: @TState) -> u64; + fn hash_operation(self: @TState, call: Call, predecessor: felt252, salt: felt252) -> felt252; + fn hash_operation_batch( + self: @TState, calls: Span, predecessor: felt252, salt: felt252 + ) -> felt252; + fn schedule(ref self: TState, call: Call, predecessor: felt252, salt: felt252, delay: u64); + fn schedule_batch( + ref self: TState, calls: Span, predecessor: felt252, salt: felt252, delay: u64 + ); + fn cancel(ref self: TState, id: felt252); + fn execute(ref self: TState, call: Call, predecessor: felt252, salt: felt252); + fn execute_batch(ref self: TState, calls: Span, predecessor: felt252, salt: felt252); + fn update_delay(ref self: TState, new_delay: u64); +} + +#[starknet::interface] +pub trait TimelockABI { + fn is_operation(self: @TState, id: felt252) -> bool; + fn is_operation_pending(self: @TState, id: felt252) -> bool; + fn is_operation_ready(self: @TState, id: felt252) -> bool; + fn is_operation_done(self: @TState, id: felt252) -> bool; + fn get_timestamp(self: @TState, id: felt252) -> u64; + fn get_operation_state(self: @TState, id: felt252) -> OperationState; + fn get_min_delay(self: @TState) -> u64; + fn hash_operation(self: @TState, call: Call, predecessor: felt252, salt: felt252) -> felt252; + fn hash_operation_batch( + self: @TState, calls: Span, predecessor: felt252, salt: felt252 + ) -> felt252; + fn schedule(ref self: TState, call: Call, predecessor: felt252, salt: felt252, delay: u64); + fn schedule_batch( + ref self: TState, calls: Span, predecessor: felt252, salt: felt252, delay: u64 + ); + fn cancel(ref self: TState, id: felt252); + fn execute(ref self: TState, call: Call, predecessor: felt252, salt: felt252); + fn execute_batch(ref self: TState, calls: Span, predecessor: felt252, salt: felt252); + fn update_delay(ref self: TState, new_delay: u64); + + // ISRC5 + fn supports_interface(self: @TState, interface_id: felt252) -> bool; + + // IAccessControl + fn has_role(self: @TState, role: felt252, account: ContractAddress) -> bool; + fn get_role_admin(self: @TState, role: felt252) -> felt252; + fn grant_role(ref self: TState, role: felt252, account: ContractAddress); + fn revoke_role(ref self: TState, role: felt252, account: ContractAddress); + fn renounce_role(ref self: TState, role: felt252, account: ContractAddress); + + // IAccessControlCamel + fn hasRole(self: @TState, role: felt252, account: ContractAddress) -> bool; + fn getRoleAdmin(self: @TState, role: felt252) -> felt252; + fn grantRole(ref self: TState, role: felt252, account: ContractAddress); + fn revokeRole(ref self: TState, role: felt252, account: ContractAddress); + fn renounceRole(ref self: TState, role: felt252, account: ContractAddress); +} diff --git a/src/governance/timelock/timelock_controller.cairo b/src/governance/timelock/timelock_controller.cairo new file mode 100644 index 000000000..494692025 --- /dev/null +++ b/src/governance/timelock/timelock_controller.cairo @@ -0,0 +1,659 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (governance/timelock/timelock_controller.cairo) + +/// # TimelockController Component +/// +/// Component that acts as a timelocked controller. When set as the owner of an `Ownable` smart +/// contract, it enforces a timelock on all `only_owner` maintenance operations. This gives time for +/// users of the controlled contract to exit before a potentially dangerous maintenance operation is +/// applied. +/// +/// By default, this component is self administered, meaning administration tasks have to go through +/// the timelock process. The proposer role is in charge of proposing operations. A common use case +/// is to position the timelock controller as the owner of a smart contract, with a multi-sig +/// or a DAO as the sole proposer. +#[starknet::component] +pub mod TimelockControllerComponent { + use core::hash::{HashStateTrait, HashStateExTrait}; + use core::num::traits::Zero; + use core::pedersen::PedersenTrait; + use openzeppelin::access::accesscontrol::AccessControlComponent::InternalTrait as AccessControlInternalTrait; + use openzeppelin::access::accesscontrol::AccessControlComponent::{ + AccessControlImpl, AccessControlCamelImpl + }; + use openzeppelin::access::accesscontrol::AccessControlComponent; + use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; + use openzeppelin::governance::timelock::interface::{ITimelock, TimelockABI}; + use openzeppelin::governance::timelock::utils::call_impls::{ + HashCallImpl, HashCallsImpl, CallPartialEq + }; + use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; + use openzeppelin::introspection::src5::SRC5Component; + use starknet::ContractAddress; + use starknet::SyscallResultTrait; + use starknet::account::Call; + use starknet::storage::Map; + use super::OperationState; + + // Constants + pub const PROPOSER_ROLE: felt252 = selector!("PROPOSER_ROLE"); + pub const EXECUTOR_ROLE: felt252 = selector!("EXECUTOR_ROLE"); + pub const CANCELLER_ROLE: felt252 = selector!("CANCELLER_ROLE"); + const DONE_TIMESTAMP: u64 = 1; + + #[storage] + struct Storage { + TimelockController_timestamps: Map, + TimelockController_min_delay: u64 + } + + #[event] + #[derive(Drop, PartialEq, starknet::Event)] + pub enum Event { + CallScheduled: CallScheduled, + CallExecuted: CallExecuted, + CallSalt: CallSalt, + CallCancelled: CallCancelled, + MinDelayChanged: MinDelayChanged + } + + /// Emitted when `call` is scheduled as part of operation `id`. + #[derive(Drop, PartialEq, starknet::Event)] + pub struct CallScheduled { + #[key] + pub id: felt252, + #[key] + pub index: felt252, + pub call: Call, + pub predecessor: felt252, + pub delay: u64 + } + + /// Emitted when `call` is performed as part of operation `id`. + #[derive(Drop, PartialEq, starknet::Event)] + pub struct CallExecuted { + #[key] + pub id: felt252, + #[key] + pub index: felt252, + pub call: Call + } + + /// Emitted when a new proposal is scheduled with non-zero salt. + #[derive(Drop, PartialEq, starknet::Event)] + pub struct CallSalt { + #[key] + pub id: felt252, + pub salt: felt252 + } + + /// Emitted when operation `id` is cancelled. + #[derive(Drop, PartialEq, starknet::Event)] + pub struct CallCancelled { + #[key] + pub id: felt252 + } + + /// Emitted when the minimum delay for future operations is modified. + #[derive(Drop, PartialEq, starknet::Event)] + pub struct MinDelayChanged { + pub old_duration: u64, + pub new_duration: u64 + } + + pub mod Errors { + pub const INVALID_OPERATION_LEN: felt252 = 'Timelock: invalid operation len'; + pub const INSUFFICIENT_DELAY: felt252 = 'Timelock: insufficient delay'; + pub const EXPECTED_UNSET_OPERATION: felt252 = 'Timelock: expected Unset op'; + pub const EXPECTED_PENDING_OPERATION: felt252 = 'Timelock: expected Pending op'; + pub const EXPECTED_READY_OPERATION: felt252 = 'Timelock: expected Ready op'; + pub const UNEXECUTED_PREDECESSOR: felt252 = 'Timelock: awaiting predecessor'; + pub const UNAUTHORIZED_CALLER: felt252 = 'Timelock: unauthorized caller'; + } + + #[embeddable_as(TimelockImpl)] + impl Timelock< + TContractState, + +HasComponent, + +SRC5Component::HasComponent, + +AccessControlComponent::HasComponent, + +Drop + > of ITimelock> { + /// Returns whether `id` corresponds to a registered operation. + /// This includes the OperationStates: Waiting, Ready, and Done. + fn is_operation(self: @ComponentState, id: felt252) -> bool { + Self::get_operation_state(self, id) != OperationState::Unset + } + + /// Returns whether the `id` OperationState is pending or not. + /// Note that a pending operation may be either Waiting or Ready. + fn is_operation_pending(self: @ComponentState, id: felt252) -> bool { + let state = Self::get_operation_state(self, id); + state == OperationState::Waiting || state == OperationState::Ready + } + + /// Returns whether the `id` OperationState is Ready or not. + fn is_operation_ready(self: @ComponentState, id: felt252) -> bool { + Self::get_operation_state(self, id) == OperationState::Ready + } + + /// Returns whether the `id` OperationState is Done or not. + fn is_operation_done(self: @ComponentState, id: felt252) -> bool { + Self::get_operation_state(self, id) == OperationState::Done + } + + /// Returns the timestamp at which `id` becomes Ready. + /// + /// NOTE: `0` means the OperationState is Unset and `1` means the OperationState + /// is Done. + fn get_timestamp(self: @ComponentState, id: felt252) -> u64 { + self.TimelockController_timestamps.read(id) + } + + /// Returns the OperationState for `id`. + fn get_operation_state( + self: @ComponentState, id: felt252 + ) -> OperationState { + let timestamp = Self::get_timestamp(self, id); + if (timestamp == 0) { + return OperationState::Unset; + } else if (timestamp == DONE_TIMESTAMP) { + return OperationState::Done; + } else if (timestamp > starknet::get_block_timestamp()) { + return OperationState::Waiting; + } else { + return OperationState::Ready; + } + } + + /// Returns the minimum delay in seconds for an operation to become valid. + /// This value can be changed by executing an operation that calls `update_delay`. + fn get_min_delay(self: @ComponentState) -> u64 { + self.TimelockController_min_delay.read() + } + + /// Returns the identifier of an operation containing a single transaction. + fn hash_operation( + self: @ComponentState, call: Call, predecessor: felt252, salt: felt252 + ) -> felt252 { + PedersenTrait::new(0) + .update_with(call) + .update_with(predecessor) + .update_with(salt) + .finalize() + } + + /// Returns the identifier of an operation containing a batch of transactions. + fn hash_operation_batch( + self: @ComponentState, + calls: Span, + predecessor: felt252, + salt: felt252 + ) -> felt252 { + PedersenTrait::new(0) + .update_with(calls) + .update_with(predecessor) + .update_with(salt) + .finalize() + } + + /// Schedule an operation containing a single transaction. + /// + /// Requirements: + /// + /// - the caller must have the `PROPOSER_ROLE` role. + /// + /// Emits `CallScheduled` event. + /// If `salt` is not zero, emits `CallSalt` event. + fn schedule( + ref self: ComponentState, + call: Call, + predecessor: felt252, + salt: felt252, + delay: u64 + ) { + self.assert_only_role(PROPOSER_ROLE); + + let id = Self::hash_operation(@self, call, predecessor, salt); + self._schedule(id, delay); + self.emit(CallScheduled { id, index: 0, call, predecessor, delay }); + + if salt != 0 { + self.emit(CallSalt { id, salt }); + } + } + + /// Schedule an operation containing a batch of transactions. + /// + /// Requirements: + /// + /// - the caller must have the `PROPOSER_ROLE` role. + /// + /// Emits one `CallScheduled` event for each transaction in the batch. + /// If `salt` is not zero, emits `CallSalt` event. + fn schedule_batch( + ref self: ComponentState, + calls: Span, + predecessor: felt252, + salt: felt252, + delay: u64 + ) { + self.assert_only_role(PROPOSER_ROLE); + + let id = Self::hash_operation_batch(@self, calls, predecessor, salt); + self._schedule(id, delay); + + let mut index = 0; + for call in calls { + self.emit(CallScheduled { id, index, call: *call, predecessor, delay }); + index += 1; + }; + + if salt != 0 { + self.emit(CallSalt { id, salt }); + } + } + + /// Cancel an operation. + /// + /// Requirements: + /// + /// - The caller must have the `CANCELLER_ROLE` role. + /// - `id` must be an operation. + /// + /// Emits a `CallCancelled` event. + fn cancel(ref self: ComponentState, id: felt252) { + self.assert_only_role(CANCELLER_ROLE); + assert(Self::is_operation_pending(@self, id), Errors::EXPECTED_PENDING_OPERATION); + + self.TimelockController_timestamps.write(id, 0); + self.emit(CallCancelled { id }); + } + + /// Execute a (Ready) operation containing a single Call. + /// + /// Requirements: + /// + /// - Caller must have `EXECUTOR_ROLE`. + /// - `id` must be in Ready OperationState. + /// - `predecessor` must either be `0` or in Done OperationState. + /// + /// NOTE: This function can reenter, but it doesn't pose a risk because `_after_call` + /// checks that the proposal is pending, thus any modifications to the operation during + /// reentrancy should be caught. + /// + /// Emits a `CallExecuted` event. + fn execute( + ref self: ComponentState, + call: Call, + predecessor: felt252, + salt: felt252 + ) { + self.assert_only_role_or_open_role(EXECUTOR_ROLE); + + let id = Self::hash_operation(@self, call, predecessor, salt); + self._before_call(id, predecessor); + self._execute(call); + self.emit(CallExecuted { id, index: 0, call }); + self._after_call(id); + } + + /// Execute a (Ready) operation containing a batch of Calls. + /// + /// Requirements: + /// + /// - Caller must have `EXECUTOR_ROLE`. + /// - `id` must be in Ready OperationState. + /// - `predecessor` must either be `0` or in Done OperationState. + /// + /// NOTE: This function can reenter, but it doesn't pose a risk because `_after_call` + /// checks that the proposal is pending, thus any modifications to the operation during + /// reentrancy should be caught. + /// + /// Emits a `CallExecuted` event for each Call. + fn execute_batch( + ref self: ComponentState, + calls: Span, + predecessor: felt252, + salt: felt252 + ) { + self.assert_only_role_or_open_role(EXECUTOR_ROLE); + + let id = Self::hash_operation_batch(@self, calls, predecessor, salt); + self._before_call(id, predecessor); + + let mut index = 0; + for call in calls { + self._execute(*call); + self.emit(CallExecuted { id, index, call: *call }); + index += 1; + }; + + self._after_call(id); + } + + /// Changes the minimum timelock duration for future operations. + /// + /// Requirements: + /// + /// - The caller must be the timelock itself. This can only be achieved by scheduling + /// and later executing an operation where the timelock is the target and the data + /// is the serialized call to this function. + /// + /// Emits a `MinDelayChanged` event. + fn update_delay(ref self: ComponentState, new_delay: u64) { + self.assert_only_self(); + + let min_delay = self.TimelockController_min_delay.read(); + self.emit(MinDelayChanged { old_duration: min_delay, new_duration: new_delay }); + + self.TimelockController_min_delay.write(new_delay); + } + } + + #[embeddable_as(TimelockMixinImpl)] + impl TimelockMixin< + TContractState, + +HasComponent, + impl SRC5: SRC5Component::HasComponent, + impl AccessControl: AccessControlComponent::HasComponent, + +Drop + > of TimelockABI> { + fn is_operation(self: @ComponentState, id: felt252) -> bool { + Timelock::is_operation(self, id) + } + + fn is_operation_pending(self: @ComponentState, id: felt252) -> bool { + Timelock::is_operation_pending(self, id) + } + + fn is_operation_ready(self: @ComponentState, id: felt252) -> bool { + Timelock::is_operation_ready(self, id) + } + + fn is_operation_done(self: @ComponentState, id: felt252) -> bool { + Timelock::is_operation_done(self, id) + } + + fn get_timestamp(self: @ComponentState, id: felt252) -> u64 { + Timelock::get_timestamp(self, id) + } + + fn get_operation_state( + self: @ComponentState, id: felt252 + ) -> OperationState { + Timelock::get_operation_state(self, id) + } + + fn get_min_delay(self: @ComponentState) -> u64 { + Timelock::get_min_delay(self) + } + + fn hash_operation( + self: @ComponentState, call: Call, predecessor: felt252, salt: felt252 + ) -> felt252 { + Timelock::hash_operation(self, call, predecessor, salt) + } + + fn hash_operation_batch( + self: @ComponentState, + calls: Span, + predecessor: felt252, + salt: felt252 + ) -> felt252 { + Timelock::hash_operation_batch(self, calls, predecessor, salt) + } + + fn schedule( + ref self: ComponentState, + call: Call, + predecessor: felt252, + salt: felt252, + delay: u64 + ) { + Timelock::schedule(ref self, call, predecessor, salt, delay); + } + + fn schedule_batch( + ref self: ComponentState, + calls: Span, + predecessor: felt252, + salt: felt252, + delay: u64 + ) { + Timelock::schedule_batch(ref self, calls, predecessor, salt, delay); + } + + fn cancel(ref self: ComponentState, id: felt252) { + Timelock::cancel(ref self, id); + } + + fn execute( + ref self: ComponentState, + call: Call, + predecessor: felt252, + salt: felt252 + ) { + Timelock::execute(ref self, call, predecessor, salt); + } + + fn execute_batch( + ref self: ComponentState, + calls: Span, + predecessor: felt252, + salt: felt252 + ) { + Timelock::execute_batch(ref self, calls, predecessor, salt); + } + + fn update_delay(ref self: ComponentState, new_delay: u64) { + Timelock::update_delay(ref self, new_delay); + } + + // ISRC5 + fn supports_interface( + self: @ComponentState, interface_id: felt252 + ) -> bool { + let src5 = get_dep_component!(self, SRC5); + src5.supports_interface(interface_id) + } + + // IAccessControl + fn has_role( + self: @ComponentState, role: felt252, account: ContractAddress + ) -> bool { + let access_control = get_dep_component!(self, AccessControl); + access_control.has_role(role, account) + } + + fn get_role_admin(self: @ComponentState, role: felt252) -> felt252 { + let access_control = get_dep_component!(self, AccessControl); + access_control.get_role_admin(role) + } + + fn grant_role( + ref self: ComponentState, role: felt252, account: ContractAddress + ) { + let mut access_control = get_dep_component_mut!(ref self, AccessControl); + access_control.grant_role(role, account); + } + + fn revoke_role( + ref self: ComponentState, role: felt252, account: ContractAddress + ) { + let mut access_control = get_dep_component_mut!(ref self, AccessControl); + access_control.revoke_role(role, account); + } + fn renounce_role( + ref self: ComponentState, role: felt252, account: ContractAddress + ) { + let mut access_control = get_dep_component_mut!(ref self, AccessControl); + access_control.renounce_role(role, account); + } + + // IAccessControlCamel + fn hasRole( + self: @ComponentState, role: felt252, account: ContractAddress + ) -> bool { + Self::has_role(self, role, account) + } + + fn getRoleAdmin(self: @ComponentState, role: felt252) -> felt252 { + Self::getRoleAdmin(self, role) + } + + fn grantRole( + ref self: ComponentState, role: felt252, account: ContractAddress + ) { + Self::grant_role(ref self, role, account); + } + + fn revokeRole( + ref self: ComponentState, role: felt252, account: ContractAddress + ) { + Self::revoke_role(ref self, role, account); + } + + fn renounceRole( + ref self: ComponentState, role: felt252, account: ContractAddress + ) { + Self::renounce_role(ref self, role, account); + } + } + + #[generate_trait] + pub impl InternalImpl< + TContractState, + +HasComponent, + impl SRC5: SRC5Component::HasComponent, + impl AccessControl: AccessControlComponent::HasComponent, + +Drop + > of InternalTrait { + /// Initializes the contract by registering support for SRC5 and AccessControl. + /// + /// This function also configures the contract with the following parameters: + /// + /// - `min_delay`: initial minimum delay in seconds for operations. + /// - `proposers`: accounts to be granted proposer and canceller roles. + /// - `executors`: accounts to be granted executor role. + /// - `admin`: optional account to be granted admin role; disable with zero address. + /// + /// WARNING: The optional admin can aid with initial configuration of roles after deployment + /// without being subject to delay, but this role should be subsequently renounced in favor + /// of administration through timelocked proposals. + /// + /// Emits two `RoleGranted` events for each account in `proposers` with `PROPOSER_ROLE` + /// admin `CANCELLER_ROLE` roles. + /// + /// Emits a `RoleGranted` event for each account in `executors` with `EXECUTOR_ROLE` role. + /// + /// May emit a `RoleGranted` event for `admin` with `DEFAULT_ADMIN_ROLE` role (if `admin` is + /// not zero). + /// + /// Emits `MinDelayChanged` event. + fn initializer( + ref self: ComponentState, + min_delay: u64, + proposers: Span, + executors: Span, + admin: ContractAddress + ) { + // Register access control ID and self as default admin + let mut access_component = get_dep_component_mut!(ref self, AccessControl); + access_component.initializer(); + access_component._grant_role(DEFAULT_ADMIN_ROLE, starknet::get_contract_address()); + + // Optional admin + if admin != Zero::zero() { + access_component._grant_role(DEFAULT_ADMIN_ROLE, admin) + }; + + // Register proposers and cancellers + for proposer in proposers { + access_component._grant_role(PROPOSER_ROLE, *proposer); + access_component._grant_role(CANCELLER_ROLE, *proposer); + }; + + // Register executors + for executor in executors { + access_component._grant_role(EXECUTOR_ROLE, *executor); + }; + + // Set minimum delay + self.TimelockController_min_delay.write(min_delay); + self.emit(MinDelayChanged { old_duration: 0, new_duration: min_delay }); + } + + /// Validates that the caller has the given `role`. + /// Otherwise it reverts. + fn assert_only_role(self: @ComponentState, role: felt252) { + let access_component = get_dep_component!(self, AccessControl); + access_component.assert_only_role(role); + } + + /// Validates that the caller has the given `role`. + /// If `role` is granted to the zero address, then this is considered an open role which + /// allows anyone to be the caller. + fn assert_only_role_or_open_role(self: @ComponentState, role: felt252) { + let access_component = get_dep_component!(self, AccessControl); + let is_role_open = access_component.has_role(role, Zero::zero()); + if !is_role_open { + access_component.assert_only_role(role); + } + } + + /// Validates that the caller is the timelock contract itself. + /// Otherwise it reverts. + fn assert_only_self(self: @ComponentState) { + let this = starknet::get_contract_address(); + let caller = starknet::get_caller_address(); + assert(caller == this, Errors::UNAUTHORIZED_CALLER); + } + + /// Private function that checks before execution of an operation's calls. + /// + /// Requirements: + /// + /// - `id` must be in the Ready OperationState. + /// - `predecessor` must either be zero or be in the Done OperationState. + fn _before_call(self: @ComponentState, id: felt252, predecessor: felt252) { + assert(Timelock::is_operation_ready(self, id), Errors::EXPECTED_READY_OPERATION); + assert( + predecessor == 0 || Timelock::is_operation_done(self, predecessor), + Errors::UNEXECUTED_PREDECESSOR + ); + } + + /// Private functions that checks after execution of an operation's calls. + /// + /// Requirements: + /// + /// - `id` must be in the Ready OperationState. + fn _after_call(ref self: ComponentState, id: felt252) { + assert(Timelock::is_operation_ready(@self, id), Errors::EXPECTED_READY_OPERATION); + self.TimelockController_timestamps.write(id, DONE_TIMESTAMP); + } + + /// Private function that schedules an operation that is to become valid after a given + /// `delay`. + fn _schedule(ref self: ComponentState, id: felt252, delay: u64) { + assert(!Timelock::is_operation(@self, id), Errors::EXPECTED_UNSET_OPERATION); + assert(Timelock::get_min_delay(@self) <= delay, Errors::INSUFFICIENT_DELAY); + self.TimelockController_timestamps.write(id, starknet::get_block_timestamp() + delay); + } + + /// Private function that executes an operation's calls. + fn _execute(ref self: ComponentState, call: Call) { + let Call { to, selector, calldata } = call; + starknet::syscalls::call_contract_syscall(to, selector, calldata).unwrap_syscall(); + } + } +} + +#[derive(Drop, Serde, PartialEq, Debug)] +pub enum OperationState { + Unset, + Waiting, + Ready, + Done +} diff --git a/src/governance/timelock/utils.cairo b/src/governance/timelock/utils.cairo new file mode 100644 index 000000000..0b626634e --- /dev/null +++ b/src/governance/timelock/utils.cairo @@ -0,0 +1 @@ +pub mod call_impls; diff --git a/src/governance/timelock/utils/call_impls.cairo b/src/governance/timelock/utils/call_impls.cairo new file mode 100644 index 000000000..428259e57 --- /dev/null +++ b/src/governance/timelock/utils/call_impls.cairo @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (governance/timelock/utils/call_impls.cairo) + +use core::hash::{HashStateTrait, HashStateExTrait, Hash}; +use starknet::account::Call; + +pub(crate) impl HashCallImpl, +Drop> of Hash { + fn update_state(mut state: S, value: Call) -> S { + let Call { to, selector, calldata } = value; + state = state.update_with(to).update_with(selector).update_with(calldata.len()); + for elem in calldata { + state = state.update_with(*elem); + }; + + state + } +} + +pub(crate) impl HashCallsImpl, +Drop> of Hash, S> { + fn update_state(mut state: S, value: Span) -> S { + state = state.update_with(value.len()); + for call in value { + state = state.update_with(*call); + }; + + state + } +} + +pub(crate) impl CallPartialEq of PartialEq { + #[inline(always)] + fn eq(lhs: @Call, rhs: @Call) -> bool { + let Call { to: l_to, selector: l_selector, calldata: l_calldata } = lhs; + let Call { to: r_to, selector: r_selector, calldata: r_calldata } = rhs; + l_to == r_to && l_selector == r_selector && l_calldata == r_calldata + } + #[inline(always)] + fn ne(lhs: @Call, rhs: @Call) -> bool { + !(lhs == rhs) + } +} diff --git a/src/governance/utils/interfaces/votes.cairo b/src/governance/utils/interfaces/votes.cairo index 44188130a..d55c481c2 100644 --- a/src/governance/utils/interfaces/votes.cairo +++ b/src/governance/utils/interfaces/votes.cairo @@ -11,9 +11,10 @@ pub trait IVotes { /// Returns the total supply of votes available at a specific moment in the past. /// - /// NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. - /// Votes that have not been delegated are still part of total supply, even though they would not participate in a - /// vote. + /// NOTE: This value is the sum of all available votes, which is not necessarily the sum of all + /// delegated votes. + /// Votes that have not been delegated are still part of total supply, even though they would + /// not participate in a vote. fn get_past_total_supply(self: @TState, timepoint: u64) -> u256; /// Returns the delegate that `account` has chosen. diff --git a/src/introspection/interface.cairo b/src/introspection/interface.cairo index bb0d6c9cf..0de388130 100644 --- a/src/introspection/interface.cairo +++ b/src/introspection/interface.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (introspection/interface.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (introspection/interface.cairo) pub const ISRC5_ID: felt252 = 0x3f918d17e5ee77373b56385708f855659a07f75997f365cf87748628532a055; diff --git a/src/introspection/src5.cairo b/src/introspection/src5.cairo index 4ac0d4b7e..530fb73b2 100644 --- a/src/introspection/src5.cairo +++ b/src/introspection/src5.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (introspection/src5.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (introspection/src5.cairo) /// # SRC5 Component /// @@ -7,10 +7,11 @@ #[starknet::component] pub mod SRC5Component { use openzeppelin::introspection::interface; + use starknet::storage::Map; #[storage] struct Storage { - SRC5_supported_interfaces: LegacyMap + SRC5_supported_interfaces: Map } pub mod Errors { diff --git a/src/presets/account.cairo b/src/presets/account.cairo index e9805bf3e..93cb2b5ef 100644 --- a/src/presets/account.cairo +++ b/src/presets/account.cairo @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (presets/account.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (presets/account.cairo) /// # Account Preset /// -/// OpenZeppelin's upgradeable account which can change its public key and declare, deploy, or call contracts. +/// OpenZeppelin's upgradeable account which can change its public key and declare, deploy, or call +/// contracts. #[starknet::contract(account)] pub(crate) mod AccountUpgradeable { use openzeppelin::account::AccountComponent; diff --git a/src/presets/erc1155.cairo b/src/presets/erc1155.cairo index 2552e7323..b24bdf100 100644 --- a/src/presets/erc1155.cairo +++ b/src/presets/erc1155.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (presets/erc1155.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (presets/erc1155.cairo) /// # ERC1155Upgradeable Preset /// diff --git a/src/presets/erc20.cairo b/src/presets/erc20.cairo index a12f43d2b..94506ba3e 100644 --- a/src/presets/erc20.cairo +++ b/src/presets/erc20.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (presets/erc20.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (presets/erc20.cairo) /// # ERC20 Preset /// diff --git a/src/presets/erc721.cairo b/src/presets/erc721.cairo index 91a469a6f..1359736f7 100644 --- a/src/presets/erc721.cairo +++ b/src/presets/erc721.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (presets/erc721.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (presets/erc721.cairo) /// # ERC721 Preset /// diff --git a/src/presets/eth_account.cairo b/src/presets/eth_account.cairo index f641904be..97bdbc8b4 100644 --- a/src/presets/eth_account.cairo +++ b/src/presets/eth_account.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (presets/eth_account.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (presets/eth_account.cairo) /// # EthAccount Preset /// @@ -9,7 +9,6 @@ pub(crate) mod EthAccountUpgradeable { use openzeppelin::account::EthAccountComponent; use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin::introspection::src5::SRC5Component; use openzeppelin::upgrades::UpgradeableComponent; use openzeppelin::upgrades::interface::IUpgradeable; diff --git a/src/presets/interfaces/eth_account.cairo b/src/presets/interfaces/eth_account.cairo index 9ee9ad22c..ab9af2f69 100644 --- a/src/presets/interfaces/eth_account.cairo +++ b/src/presets/interfaces/eth_account.cairo @@ -1,5 +1,4 @@ use openzeppelin::account::interface::EthPublicKey; -use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use starknet::account::Call; use starknet::{ContractAddress, ClassHash}; diff --git a/src/presets/universal_deployer.cairo b/src/presets/universal_deployer.cairo index 2d4f84070..2777a6107 100644 --- a/src/presets/universal_deployer.cairo +++ b/src/presets/universal_deployer.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (presets/universal_deployer.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (presets/universal_deployer.cairo) /// # UniversalDeployerContract Preset /// @@ -45,8 +45,7 @@ pub(crate) mod UniversalDeployer { let deployer: ContractAddress = get_caller_address(); let mut _salt: felt252 = salt; if !from_zero { - let mut hash_state = PoseidonTrait::new(); - _salt = hash_state.update_with(deployer).update_with(salt).finalize(); + _salt = PoseidonTrait::new().update_with(deployer).update_with(salt).finalize() } let (address, _) = starknet::syscalls::deploy_syscall( diff --git a/src/security/initializable.cairo b/src/security/initializable.cairo index b265bbc8a..11e7bdabb 100644 --- a/src/security/initializable.cairo +++ b/src/security/initializable.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (security/initializable.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (security/initializable.cairo) /// # Initializable Component /// diff --git a/src/security/pausable.cairo b/src/security/pausable.cairo index d10a201a5..0be0d3a43 100644 --- a/src/security/pausable.cairo +++ b/src/security/pausable.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (security/pausable.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (security/pausable.cairo) /// # Pausable Component /// diff --git a/src/security/reentrancyguard.cairo b/src/security/reentrancyguard.cairo index de43d6c0d..994e71762 100644 --- a/src/security/reentrancyguard.cairo +++ b/src/security/reentrancyguard.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (security/reentrancyguard.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (security/reentrancyguard.cairo) /// # ReentrancyGuard Component /// @@ -22,7 +22,8 @@ pub mod ReentrancyGuardComponent { pub impl InternalImpl< TContractState, +HasComponent > of InternalTrait { - /// Prevents a contract's function from calling itself or another protected function, directly or indirectly. + /// Prevents a contract's function from calling itself or another protected function, + /// directly or indirectly. fn start(ref self: ComponentState) { assert(!self.ReentrancyGuard_entered.read(), Errors::REENTRANT_CALL); self.ReentrancyGuard_entered.write(true); diff --git a/src/tests.cairo b/src/tests.cairo index fab03b247..6a1d8a06a 100644 --- a/src/tests.cairo +++ b/src/tests.cairo @@ -5,6 +5,8 @@ mod account; #[cfg(test)] mod cryptography; #[cfg(test)] +mod governance; +#[cfg(test)] mod introspection; mod mocks; #[cfg(test)] diff --git a/src/tests/access/test_ownable.cairo b/src/tests/access/test_ownable.cairo index 463406916..8a2d8ac7d 100644 --- a/src/tests/access/test_ownable.cairo +++ b/src/tests/access/test_ownable.cairo @@ -5,7 +5,6 @@ use openzeppelin::access::ownable::interface::{IOwnable, IOwnableCamelOnly}; use openzeppelin::tests::mocks::ownable_mocks::DualCaseOwnableMock; use openzeppelin::tests::utils::constants::{ZERO, OTHER, OWNER}; use snforge_std::{spy_events, test_address, start_cheat_caller_address}; -use starknet::storage::StorageMemberAccessTrait; use super::common::OwnableSpyHelpers; diff --git a/src/tests/access/test_ownable_twostep.cairo b/src/tests/access/test_ownable_twostep.cairo index 55b58b09a..60db61cc4 100644 --- a/src/tests/access/test_ownable_twostep.cairo +++ b/src/tests/access/test_ownable_twostep.cairo @@ -8,7 +8,6 @@ use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::utils::serde::SerializedAppend; use snforge_std::{EventSpy, spy_events, start_cheat_caller_address, test_address}; use starknet::ContractAddress; -use starknet::storage::StorageMemberAccessTrait; use super::common::OwnableSpyHelpers; diff --git a/src/tests/account/ethereum/test_dual_eth_account.cairo b/src/tests/account/ethereum/test_dual_eth_account.cairo index bad86716a..bde5c53f5 100644 --- a/src/tests/account/ethereum/test_dual_eth_account.cairo +++ b/src/tests/account/ethereum/test_dual_eth_account.cairo @@ -1,8 +1,6 @@ use openzeppelin::account::dual_eth_account::{DualCaseEthAccountABI, DualCaseEthAccount}; use openzeppelin::account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; -use openzeppelin::account::utils::secp256k1::{ - DebugSecp256k1Point, Secp256k1PointPartialEq, Secp256k1PointSerde -}; +use openzeppelin::account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; use openzeppelin::account::utils::signature::EthSignature; use openzeppelin::introspection::interface::ISRC5_ID; use openzeppelin::tests::utils::constants::secp256k1::KEY_PAIR; diff --git a/src/tests/account/ethereum/test_eth_account.cairo b/src/tests/account/ethereum/test_eth_account.cairo index 1f26956e0..4c1b50bff 100644 --- a/src/tests/account/ethereum/test_eth_account.cairo +++ b/src/tests/account/ethereum/test_eth_account.cairo @@ -4,9 +4,7 @@ use openzeppelin::account::EthAccountComponent::{PublicKeyCamelImpl, PublicKeyIm use openzeppelin::account::EthAccountComponent; use openzeppelin::account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; use openzeppelin::account::interface::{ISRC6, ISRC6_ID}; -use openzeppelin::account::utils::secp256k1::{ - DebugSecp256k1Point, Secp256k1PointPartialEq, Secp256k1PointSerde -}; +use openzeppelin::account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; use openzeppelin::account::utils::signature::EthSignature; use openzeppelin::introspection::interface::{ISRC5, ISRC5_ID}; use openzeppelin::tests::mocks::eth_account_mocks::DualCaseEthAccountMock; diff --git a/src/tests/account/test_secp256k1.cairo b/src/tests/account/test_secp256k1.cairo index b41160a3d..0fb43803c 100644 --- a/src/tests/account/test_secp256k1.cairo +++ b/src/tests/account/test_secp256k1.cairo @@ -1,6 +1,5 @@ use openzeppelin::account::utils::secp256k1::{ - DebugSecp256k1Point, Secp256k1PointSerde, Secp256k1PointPartialEq, - Secp256k1PointStorePacking as StorePacking + DebugSecp256k1Point, Secp256k1PointPartialEq, Secp256k1PointStorePacking as StorePacking }; use starknet::SyscallResultTrait; use starknet::secp256_trait::{Secp256Trait, Secp256PointTrait}; @@ -63,53 +62,6 @@ fn test_unpack_big_secp256k1_points() { assert_eq!(y, expected_y); } -#[test] -fn test_secp256k1_serialization() { - let (big_point_1, big_point_2) = get_points(); - - let mut serialized_point = array![]; - let mut expected_serialization = array![]; - - // Check point 1 - - big_point_1.serialize(ref serialized_point); - big_point_1.get_coordinates().unwrap_syscall().serialize(ref expected_serialization); - - assert!(serialized_point == expected_serialization); - - // Check point 2 - - big_point_2.serialize(ref serialized_point); - big_point_2.get_coordinates().unwrap_syscall().serialize(ref expected_serialization); - - assert!(serialized_point == expected_serialization); -} - -#[test] -fn test_secp256k1_deserialization() { - let (big_point_1, big_point_2) = get_points(); - - // Check point 1 - - let mut expected_serialization = array![]; - - big_point_1.get_coordinates().unwrap_syscall().serialize(ref expected_serialization); - let mut expected_serialization = expected_serialization.span(); - let deserialized_point = Secp256k1PointSerde::deserialize(ref expected_serialization).unwrap(); - - assert_eq!(big_point_1, deserialized_point); - - // Check point 2 - - let mut expected_serialization = array![]; - - big_point_2.get_coordinates().unwrap_syscall().serialize(ref expected_serialization); - let mut expected_serialization = expected_serialization.span(); - let deserialized_point = Secp256k1PointSerde::deserialize(ref expected_serialization).unwrap(); - - assert_eq!(big_point_2, deserialized_point); -} - #[test] fn test_partial_eq() { let (big_point_1, big_point_2) = get_points(); diff --git a/src/tests/governance.cairo b/src/tests/governance.cairo new file mode 100644 index 000000000..1d40503c0 --- /dev/null +++ b/src/tests/governance.cairo @@ -0,0 +1,2 @@ +//mod test_timelock; +mod test_utils; diff --git a/src/tests/governance/test_timelock.cairo b/src/tests/governance/test_timelock.cairo new file mode 100644 index 000000000..c654c2082 --- /dev/null +++ b/src/tests/governance/test_timelock.cairo @@ -0,0 +1,1799 @@ +use core::hash::{HashStateTrait, HashStateExTrait}; +use core::num::traits::Zero; +use core::pedersen::PedersenTrait; +use openzeppelin::access::accesscontrol::AccessControlComponent::{ + AccessControlImpl, InternalImpl as AccessControlInternalImpl +}; +use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; +use openzeppelin::access::accesscontrol::interface::IACCESSCONTROL_ID; +use openzeppelin::access::accesscontrol::interface::IAccessControl; +use openzeppelin::governance::timelock::OperationState; +use openzeppelin::governance::timelock::TimelockControllerComponent::{ + CallScheduled, CallExecuted, CallSalt, CallCancelled, MinDelayChanged +}; +use openzeppelin::governance::timelock::TimelockControllerComponent::{ + TimelockImpl, InternalImpl as TimelockInternalImpl +}; +use openzeppelin::governance::timelock::TimelockControllerComponent; +use openzeppelin::governance::timelock::interface::{ + TimelockABIDispatcher, TimelockABIDispatcherTrait +}; +use openzeppelin::governance::timelock::{PROPOSER_ROLE, EXECUTOR_ROLE, CANCELLER_ROLE}; +use openzeppelin::introspection::interface::ISRC5_ID; +use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; +use openzeppelin::tests::mocks::timelock_mocks::MockContract; +use openzeppelin::tests::mocks::timelock_mocks::{ + IMockContractDispatcher, IMockContractDispatcherTrait +}; +use openzeppelin::tests::mocks::timelock_mocks::{ + ITimelockAttackerDispatcher, ITimelockAttackerDispatcherTrait +}; +use openzeppelin::tests::mocks::timelock_mocks::{TimelockControllerMock, TimelockAttackerMock}; +use openzeppelin::tests::utils::constants::{ADMIN, ZERO, OTHER, SALT}; +use openzeppelin::tests::utils; +use openzeppelin::utils::selectors; +use openzeppelin::utils::serde::SerializedAppend; +use starknet::ContractAddress; +use starknet::account::Call; +use starknet::contract_address_const; +use starknet::testing; + +type ComponentState = + TimelockControllerComponent::ComponentState; + +fn CONTRACT_STATE() -> TimelockControllerMock::ContractState { + TimelockControllerMock::contract_state_for_testing() +} + +fn COMPONENT_STATE() -> ComponentState { + TimelockControllerComponent::component_state_for_testing() +} + +// +// Constants +// + +const MIN_DELAY: u64 = 1000; +const NEW_DELAY: u64 = 2000; +const VALUE: felt252 = 'VALUE'; +const NO_PREDECESSOR: felt252 = 0; + +// +// Addresses +// + +fn PROPOSER() -> ContractAddress { + contract_address_const::<'PROPOSER'>() +} + +fn EXECUTOR() -> ContractAddress { + contract_address_const::<'EXECUTOR'>() +} + +fn get_proposers() -> (ContractAddress, ContractAddress, ContractAddress) { + let p1 = contract_address_const::<'PROPOSER_1'>(); + let p2 = contract_address_const::<'PROPOSER_2'>(); + let p3 = contract_address_const::<'PROPOSER_3'>(); + (p1, p2, p3) +} + +fn get_executors() -> (ContractAddress, ContractAddress, ContractAddress) { + let e1 = contract_address_const::<'EXECUTOR_1'>(); + let e2 = contract_address_const::<'EXECUTOR_2'>(); + let e3 = contract_address_const::<'EXECUTOR_3'>(); + (e1, e2, e3) +} + +// +// Operations +// + +fn single_operation(target: ContractAddress) -> Call { + let mut calldata = array![]; + calldata.append_serde(VALUE); + + Call { to: target, selector: selector!("set_number"), calldata: calldata.span() } +} + +fn batched_operations(target: ContractAddress) -> Span { + let mut calls = array![]; + let call = single_operation(target); + calls.append(call); + calls.append(call); + calls.append(call); + + calls.span() +} + +fn failing_operation(target: ContractAddress) -> Call { + let mut calldata = array![]; + + Call { to: target, selector: selector!("failing_function"), calldata: calldata.span() } +} + +fn operation_with_bad_selector(target: ContractAddress) -> Call { + let mut calldata = array![]; + + Call { to: target, selector: selector!("bad_selector"), calldata: calldata.span() } +} + +// +// Dispatchers +// + +fn deploy_timelock() -> TimelockABIDispatcher { + let mut calldata = array![]; + + let proposers = array![PROPOSER()].span(); + let executors = array![EXECUTOR()].span(); + let admin = ADMIN(); + + calldata.append_serde(MIN_DELAY); + calldata.append_serde(proposers); + calldata.append_serde(executors); + calldata.append_serde(admin); + + let address = utils::deploy(TimelockControllerMock::TEST_CLASS_HASH, calldata); + // Events dropped: + // - 5 RoleGranted: self, proposer, canceller, executor, admin + // - MinDelayChanged + utils::drop_events(address, 6); + TimelockABIDispatcher { contract_address: address } +} + +fn deploy_mock_target() -> IMockContractDispatcher { + let mut calldata = array![]; + + let address = utils::deploy(MockContract::TEST_CLASS_HASH, calldata); + IMockContractDispatcher { contract_address: address } +} + +fn setup_dispatchers() -> (TimelockABIDispatcher, IMockContractDispatcher) { + let timelock = deploy_timelock(); + let target = deploy_mock_target(); + + (timelock, target) +} + +fn deploy_attacker() -> ITimelockAttackerDispatcher { + let mut calldata = array![]; + + let address = utils::deploy(TimelockAttackerMock::TEST_CLASS_HASH, calldata); + ITimelockAttackerDispatcher { contract_address: address } +} + +// +// hash_operation +// + +#[test] +fn test_hash_operation() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = 123; + let salt = SALT; + + // Set up call + let mut calldata = array![]; + calldata.append_serde(VALUE); + let mut call = Call { + to: target.contract_address, selector: selector!("set_number"), calldata: calldata.span() + }; + + // Hash operation + let hashed_operation = timelock.hash_operation(call, predecessor, salt); + + // Manually set hash elements + let mut expected_hash = PedersenTrait::new(0) + .update_with(target.contract_address) // call::to + .update_with(selector!("set_number")) // call::selector + .update_with(1) // call::calldata.len + .update_with(VALUE) // call::calldata::number + .update_with(predecessor) // predecessor + .update_with(salt) // salt + .finalize(); + + assert_eq!(hashed_operation, expected_hash); +} + +#[test] +fn test_hash_operation_batch() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = 123; + let salt = SALT; + + // Set up calls + let mut calldata = array![]; + calldata.append_serde(VALUE); + let mut call = Call { + to: target.contract_address, selector: selector!("set_number"), calldata: calldata.span() + }; + let calls = array![call, call, call].span(); + + // Hash operation + let hashed_operation = timelock.hash_operation_batch(calls, predecessor, salt); + + // Manually set hash elements + let mut expected_hash = PedersenTrait::new(0) + .update_with(3) // total number of Calls + .update_with(target.contract_address) // call::to + .update_with(selector!("set_number")) // call::selector + .update_with(1) // call::calldata.len + .update_with(VALUE) // call::calldata::number + .update_with(target.contract_address) // call::to + .update_with(selector!("set_number")) // call::selector + .update_with(1) // call::calldata.len + .update_with(VALUE) // call::calldata::number + .update_with(target.contract_address) // call::to + .update_with(selector!("set_number")) // call::selector + .update_with(1) // call::calldata.len + .update_with(VALUE) // call::calldata::number + .update_with(predecessor) // predecessor + .update_with(salt) // salt + .finalize(); + + assert_eq!(hashed_operation, expected_hash); +} + +// +// schedule +// + +fn schedule_from_proposer(salt: felt252) { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let delay = MIN_DELAY; + let mut salt = salt; + + // Set up call + let call = single_operation(target.contract_address); + let target_id = timelock.hash_operation(call, predecessor, salt); + assert_operation_state(timelock, OperationState::Unset, target_id); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); + + // Check timestamp + let operation_ts = timelock.get_timestamp(target_id); + let expected_ts = starknet::get_block_timestamp() + delay; + assert_eq!(operation_ts, expected_ts); + + // Check event(s) + let event_index = 0; + if salt != 0 { + assert_event_schedule( + timelock.contract_address, target_id, event_index, call, predecessor, delay + ); + assert_only_event_call_salt(timelock.contract_address, target_id, salt); + } else { + assert_only_event_schedule( + timelock.contract_address, target_id, event_index, call, predecessor, delay + ); + } +} + +#[test] +fn test_schedule_from_proposer_with_salt() { + let salt = SALT; + schedule_from_proposer(salt); +} + +#[test] +fn test_schedule_from_proposer_no_salt() { + let salt = 0; + schedule_from_proposer(salt); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Unset op', 'ENTRYPOINT_FAILED'))] +fn test_schedule_overwrite() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = SALT; + let delay = MIN_DELAY; + + let call = single_operation(target.contract_address); + + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); + timelock.schedule(call, predecessor, salt, delay); +} + +#[test] +#[should_panic(expected: ('Caller is missing role', 'ENTRYPOINT_FAILED'))] +fn test_schedule_unauthorized() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = SALT; + let delay = MIN_DELAY; + + let call = single_operation(target.contract_address); + + testing::set_contract_address(OTHER()); + timelock.schedule(call, predecessor, salt, delay); +} + +#[test] +#[should_panic(expected: ('Timelock: insufficient delay', 'ENTRYPOINT_FAILED'))] +fn test_schedule_bad_min_delay() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = SALT; + let bad_delay = MIN_DELAY - 1; + + let call = single_operation(target.contract_address); + + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, bad_delay); +} + +// +// schedule_batch +// + +fn schedule_batch_from_proposer(salt: felt252) { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let delay = MIN_DELAY; + let mut salt = salt; + + // Set up calls + let calls = batched_operations(target.contract_address); + let target_id = timelock.hash_operation_batch(calls, predecessor, salt); + assert_operation_state(timelock, OperationState::Unset, target_id); + + // Schedule batch + testing::set_contract_address(PROPOSER()); + timelock.schedule_batch(calls, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); + + // Check timestamp + let operation_ts = timelock.get_timestamp(target_id); + let expected_ts = starknet::get_block_timestamp() + delay; + assert_eq!(operation_ts, expected_ts); + + // Check events + if salt != 0 { + assert_events_schedule_batch( + timelock.contract_address, target_id, calls, predecessor, delay + ); + assert_only_event_call_salt(timelock.contract_address, target_id, salt); + } else { + assert_only_events_schedule_batch( + timelock.contract_address, target_id, calls, predecessor, delay + ); + } +} + +#[test] +fn test_schedule_batch_from_proposer_with_salt() { + let salt = SALT; + schedule_batch_from_proposer(salt); +} + +#[test] +fn test_schedule_batch_from_proposer_no_salt() { + let no_salt = 0; + schedule_batch_from_proposer(no_salt); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Unset op', 'ENTRYPOINT_FAILED'))] +fn test_schedule_batch_overwrite() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = SALT; + let delay = MIN_DELAY; + + let calls = batched_operations(target.contract_address); + + testing::set_contract_address(PROPOSER()); + timelock.schedule_batch(calls, predecessor, salt, delay); + timelock.schedule_batch(calls, predecessor, salt, delay); +} + +#[test] +#[should_panic(expected: ('Caller is missing role', 'ENTRYPOINT_FAILED'))] +fn test_schedule_batch_unauthorized() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = SALT; + let delay = MIN_DELAY; + + let calls = batched_operations(target.contract_address); + + testing::set_contract_address(OTHER()); + timelock.schedule_batch(calls, predecessor, salt, delay); +} + +#[test] +#[should_panic(expected: ('Timelock: insufficient delay', 'ENTRYPOINT_FAILED'))] +fn test_schedule_batch_bad_min_delay() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = SALT; + let bad_delay = MIN_DELAY - 1; + + let calls = batched_operations(target.contract_address); + + testing::set_contract_address(PROPOSER()); + timelock.schedule_batch(calls, predecessor, salt, bad_delay); +} + +// +// execute +// + +#[test] +#[should_panic(expected: ('Timelock: expected Ready op', 'ENTRYPOINT_FAILED'))] +fn test_execute_when_not_scheduled() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + + let call = single_operation(target.contract_address); + + testing::set_contract_address(EXECUTOR()); + timelock.execute(call, predecessor, salt); +} + +#[test] +fn test_execute_when_scheduled() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + let event_index = 0; + + // Set up call + let call = single_operation(target.contract_address); + let target_id = timelock.hash_operation(call, predecessor, salt); + assert_operation_state(timelock, OperationState::Unset, target_id); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); + assert_only_event_schedule( + timelock.contract_address, target_id, event_index, call, predecessor, delay + ); + assert_operation_state(timelock, OperationState::Waiting, target_id); + + // Fast-forward + testing::set_block_timestamp(delay); + assert_operation_state(timelock, OperationState::Ready, target_id); + + // Check initial target state + let check_target = target.get_number(); + assert_eq!(check_target, 0); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute(call, predecessor, salt); + + assert_operation_state(timelock, OperationState::Done, target_id); + assert_only_event_execute(timelock.contract_address, target_id, event_index, call); + + // Check target state updates + let check_target = target.get_number(); + assert_eq!(check_target, VALUE); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Ready op', 'ENTRYPOINT_FAILED'))] +fn test_execute_early() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + let call = single_operation(target.contract_address); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); + + // Fast-forward + let early_time = delay - 1; + testing::set_block_timestamp(early_time); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute(call, predecessor, salt); +} + +#[test] +#[should_panic(expected: ('Caller is missing role', 'ENTRYPOINT_FAILED'))] +fn test_execute_unauthorized() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + let call = single_operation(target.contract_address); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); + + // Fast-forward + testing::set_block_timestamp(delay); + + // Execute + testing::set_contract_address(OTHER()); + timelock.execute(call, predecessor, salt); +} + +#[test] +#[should_panic(expected: ('Expected failure', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED'))] +fn test_execute_failing_tx() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + // Set up call + let call = failing_operation(target.contract_address); + let target_id = timelock.hash_operation(call, predecessor, salt); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); + + // Fast-forward + testing::set_block_timestamp(delay); + assert_operation_state(timelock, OperationState::Ready, target_id); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute(call, predecessor, salt); +} + +#[test] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND', 'ENTRYPOINT_FAILED'))] +fn test_execute_bad_selector() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + // Set up call + let call = operation_with_bad_selector(target.contract_address); + let target_id = timelock.hash_operation(call, predecessor, salt); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); + + // Fast-forward + testing::set_block_timestamp(delay); + assert_operation_state(timelock, OperationState::Ready, target_id); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute(call, predecessor, salt); +} + +#[test] +#[should_panic( + expected: ( + 'Timelock: expected Ready op', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED' + ) +)] +fn test_execute_reentrant_call() { + let mut timelock = deploy_timelock(); + let mut attacker = deploy_attacker(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + let reentrant_call = Call { + to: attacker.contract_address, selector: selector!("reenter"), calldata: array![].span() + }; + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule(reentrant_call, predecessor, salt, delay); + + // Fast-forward + testing::set_block_timestamp(delay); + + // Grant executor role to attacker + testing::set_contract_address(ADMIN()); + timelock.grant_role(EXECUTOR_ROLE, attacker.contract_address); + + // Attempt reentrant call + testing::set_contract_address(EXECUTOR()); + timelock.execute(reentrant_call, predecessor, salt); +} + +#[test] +#[should_panic(expected: ('Timelock: awaiting predecessor', 'ENTRYPOINT_FAILED'))] +fn test_execute_before_dependency() { + let (mut timelock, mut target) = setup_dispatchers(); + let salt = 0; + let delay = MIN_DELAY; + + // Call 1 + let call_1 = single_operation(target.contract_address); + let predecessor_1 = NO_PREDECESSOR; + let target_id_1 = timelock.hash_operation(call_1, predecessor_1, salt); + + // Call 2 + let call_2 = single_operation(target.contract_address); + let predecessor_2 = target_id_1; + let target_id_2 = timelock.hash_operation(call_2, predecessor_2, salt); + + // Schedule call 1 + testing::set_contract_address(PROPOSER()); + timelock.schedule(call_1, predecessor_1, salt, delay); + + // Schedule call 2 + timelock.schedule(call_2, predecessor_2, salt, delay); + + // Fast-forward + testing::set_block_timestamp(delay); + assert_operation_state(timelock, OperationState::Ready, target_id_1); + assert_operation_state(timelock, OperationState::Ready, target_id_2); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute(call_2, predecessor_2, salt); +} + +#[test] +fn test_execute_after_dependency() { + let (mut timelock, mut target) = setup_dispatchers(); + let salt = 0; + let delay = MIN_DELAY; + let event_index = 0; + + // Call 1 + let call_1 = single_operation(target.contract_address); + let predecessor_1 = NO_PREDECESSOR; + let target_id_1 = timelock.hash_operation(call_1, predecessor_1, salt); + assert_operation_state(timelock, OperationState::Unset, target_id_1); + + // Call 2 + let call_2 = single_operation(target.contract_address); + let predecessor_2 = target_id_1; + let target_id_2 = timelock.hash_operation(call_2, predecessor_2, salt); + assert_operation_state(timelock, OperationState::Unset, target_id_2); + + // Schedule call 1 + testing::set_contract_address(PROPOSER()); + timelock.schedule(call_1, predecessor_1, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id_1); + assert_only_event_schedule( + timelock.contract_address, target_id_1, event_index, call_1, predecessor_1, delay + ); + + // Schedule call 2 + timelock.schedule(call_2, predecessor_2, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id_2); + assert_only_event_schedule( + timelock.contract_address, target_id_2, event_index, call_2, predecessor_2, delay + ); + + // Fast-forward + testing::set_block_timestamp(delay); + assert_operation_state(timelock, OperationState::Ready, target_id_1); + assert_operation_state(timelock, OperationState::Ready, target_id_2); + + // Execute call 1 + testing::set_contract_address(EXECUTOR()); + timelock.execute(call_1, predecessor_1, salt); + assert_operation_state(timelock, OperationState::Done, target_id_1); + assert_event_execute(timelock.contract_address, target_id_1, event_index, call_1); + + // Execute call 2 + timelock.execute(call_2, predecessor_2, salt); + assert_operation_state(timelock, OperationState::Done, target_id_2); + assert_only_event_execute(timelock.contract_address, target_id_2, event_index, call_2); +} + +// +// execute_batch +// + +#[test] +#[should_panic(expected: ('Timelock: expected Ready op', 'ENTRYPOINT_FAILED'))] +fn test_execute_batch_when_not_scheduled() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + + let calls = batched_operations(target.contract_address); + + testing::set_contract_address(EXECUTOR()); + timelock.execute_batch(calls, predecessor, salt); +} + +#[test] +fn test_execute_batch_when_scheduled() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + // Set up call + let calls = batched_operations(target.contract_address); + let target_id = timelock.hash_operation_batch(calls, predecessor, salt); + assert_operation_state(timelock, OperationState::Unset, target_id); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule_batch(calls, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); + assert_only_events_schedule_batch( + timelock.contract_address, target_id, calls, predecessor, delay + ); + + // Fast-forward + testing::set_block_timestamp(delay); + assert_operation_state(timelock, OperationState::Ready, target_id); + + // Check initial target state + let check_target = target.get_number(); + assert_eq!(check_target, 0); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute_batch(calls, predecessor, salt); + assert_operation_state(timelock, OperationState::Done, target_id); + assert_only_events_execute_batch(timelock.contract_address, target_id, calls); + + // Check target state updates + let check_target = target.get_number(); + assert_eq!(check_target, VALUE); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Ready op', 'ENTRYPOINT_FAILED'))] +fn test_execute_batch_early() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + let calls = batched_operations(target.contract_address); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule_batch(calls, predecessor, salt, delay); + + // Fast-forward + let early_time = delay - 1; + testing::set_block_timestamp(early_time); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute_batch(calls, predecessor, salt); +} + +#[test] +#[should_panic(expected: ('Caller is missing role', 'ENTRYPOINT_FAILED'))] +fn test_execute_batch_unauthorized() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + let calls = batched_operations(target.contract_address); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule_batch(calls, predecessor, salt, delay); + + // Fast-forward + testing::set_block_timestamp(delay); + + // Execute + testing::set_contract_address(OTHER()); + timelock.execute_batch(calls, predecessor, salt); +} + +#[test] +#[should_panic( + expected: ( + 'Timelock: expected Ready op', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED' + ) +)] +fn test_execute_batch_reentrant_call() { + let mut timelock = deploy_timelock(); + let mut attacker = deploy_attacker(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + let reentrant_call = Call { + to: attacker.contract_address, + selector: selector!("reenter_batch"), + calldata: array![].span() + }; + let calls = array![reentrant_call].span(); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule_batch(calls, predecessor, salt, delay); + + // Fast-forward + testing::set_block_timestamp(delay); + + // Grant executor role to attacker + testing::set_contract_address(ADMIN()); + timelock.grant_role(EXECUTOR_ROLE, attacker.contract_address); + + // Attempt reentrant call + testing::set_contract_address(EXECUTOR()); + timelock.execute_batch(calls, predecessor, salt); +} + +#[test] +#[should_panic(expected: ('Expected failure', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED'))] +fn test_execute_batch_partial_execution() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + let good_call = single_operation(target.contract_address); + let bad_call = failing_operation(target.contract_address); + let calls = array![good_call, bad_call].span(); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule_batch(calls, predecessor, salt, delay); + + // Fast-forward + testing::set_block_timestamp(delay); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute_batch(calls, predecessor, salt); +} + +#[test] +#[should_panic(expected: ('Timelock: awaiting predecessor', 'ENTRYPOINT_FAILED'))] +fn test_execute_batch_before_dependency() { + let (mut timelock, mut target) = setup_dispatchers(); + let salt = 0; + let delay = MIN_DELAY; + + // Calls 1 + let calls_1 = batched_operations(target.contract_address); + let predecessor_1 = NO_PREDECESSOR; + let target_id_1 = timelock.hash_operation_batch(calls_1, predecessor_1, salt); + + // Calls 2 + let calls_2 = batched_operations(target.contract_address); + let predecessor_2 = target_id_1; + + // Schedule calls 1 + testing::set_contract_address(PROPOSER()); + timelock.schedule_batch(calls_1, predecessor_1, salt, delay); + + // Schedule calls 2 + timelock.schedule_batch(calls_2, predecessor_2, salt, delay); + + // Fast-forward + testing::set_block_timestamp(delay); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute_batch(calls_2, predecessor_2, salt); +} + +#[test] +fn test_execute_batch_after_dependency() { + let (mut timelock, mut target) = setup_dispatchers(); + let salt = 0; + let delay = MIN_DELAY; + + // Calls 1 + let calls_1 = batched_operations(target.contract_address); + let predecessor_1 = NO_PREDECESSOR; + let target_id_1 = timelock.hash_operation_batch(calls_1, predecessor_1, salt); + assert_operation_state(timelock, OperationState::Unset, target_id_1); + + // Calls 2 + let calls_2 = batched_operations(target.contract_address); + let predecessor_2 = target_id_1; + let target_id_2 = timelock.hash_operation_batch(calls_2, predecessor_2, salt); + assert_operation_state(timelock, OperationState::Unset, target_id_2); + + // Schedule calls 1 + testing::set_contract_address(PROPOSER()); + timelock.schedule_batch(calls_1, predecessor_1, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id_1); + assert_only_events_schedule_batch( + timelock.contract_address, target_id_1, calls_1, predecessor_1, delay + ); + + // Schedule calls 2 + timelock.schedule_batch(calls_2, predecessor_2, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id_2); + assert_only_events_schedule_batch( + timelock.contract_address, target_id_2, calls_2, predecessor_2, delay + ); + + // Fast-forward + testing::set_block_timestamp(delay); + assert_operation_state(timelock, OperationState::Ready, target_id_1); + assert_operation_state(timelock, OperationState::Ready, target_id_2); + + // Execute calls 1 + testing::set_contract_address(EXECUTOR()); + timelock.execute_batch(calls_1, predecessor_1, salt); + assert_only_events_execute_batch(timelock.contract_address, target_id_1, calls_1); + assert_operation_state(timelock, OperationState::Done, target_id_1); + + // Execute calls 2 + timelock.execute_batch(calls_2, predecessor_2, salt); + assert_operation_state(timelock, OperationState::Done, target_id_2); + assert_only_events_execute_batch(timelock.contract_address, target_id_2, calls_2); +} + +// +// cancel +// + +fn cancel_from_canceller(operation_state: OperationState) { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + let event_index = 0; + + let call = single_operation(target.contract_address); + let target_id = timelock.hash_operation(call, predecessor, salt); + assert_operation_state(timelock, OperationState::Unset, target_id); + + // Schedule + testing::set_contract_address(PROPOSER()); // PROPOSER is also CANCELLER + timelock.schedule(call, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); + assert_only_event_schedule( + timelock.contract_address, target_id, event_index, call, predecessor, delay + ); + + if operation_state == OperationState::Ready { + // Fast-forward + testing::set_block_timestamp(delay); + assert_operation_state(timelock, OperationState::Ready, target_id); + } + + // Cancel + timelock.cancel(target_id); + assert_only_event_cancel(timelock.contract_address, target_id); + assert_operation_state(timelock, OperationState::Unset, target_id); +} + +#[test] +fn test_cancel_when_waiting() { + let waiting = OperationState::Waiting; + cancel_from_canceller(waiting); +} + +#[test] +fn test_cancel_when_ready() { + let ready = OperationState::Waiting; + cancel_from_canceller(ready); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Pending op', 'ENTRYPOINT_FAILED'))] +fn test_cancel_when_done() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + let call = single_operation(target.contract_address); + let target_id = timelock.hash_operation(call, predecessor, salt); + assert_operation_state(timelock, OperationState::Unset, target_id); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); + + // Fast-forward + testing::set_block_timestamp(delay); + assert_operation_state(timelock, OperationState::Ready, target_id); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute(call, predecessor, salt); + assert_operation_state(timelock, OperationState::Done, target_id); + + // Attempt cancel + testing::set_contract_address(PROPOSER()); // PROPOSER is also CANCELLER + timelock.cancel(target_id); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Pending op', 'ENTRYPOINT_FAILED'))] +fn test_cancel_when_unset() { + let (mut timelock, _) = setup_dispatchers(); + let invalid_id = 0; + + // PROPOSER is also CANCELLER + testing::set_contract_address(PROPOSER()); + timelock.cancel(invalid_id); +} + +#[test] +#[should_panic(expected: ('Caller is missing role', 'ENTRYPOINT_FAILED'))] +fn test_cancel_unauthorized() { + let (mut timelock, mut target) = setup_dispatchers(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + + let call = single_operation(target.contract_address); + let target_id = timelock.hash_operation(call, predecessor, salt); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); + + // Cancel + testing::set_contract_address(OTHER()); + timelock.cancel(target_id); +} + +// +// update_delay +// + +#[test] +#[should_panic(expected: ('Timelock: unauthorized caller', 'ENTRYPOINT_FAILED'))] +fn test_update_delay_unauthorized() { + let mut timelock = deploy_timelock(); + + timelock.update_delay(NEW_DELAY); +} + +#[test] +fn test_update_delay_scheduled() { + let mut timelock = deploy_timelock(); + let predecessor = NO_PREDECESSOR; + let salt = 0; + let delay = MIN_DELAY; + let event_index = 0; + + let call = Call { + to: timelock.contract_address, + selector: selector!("update_delay"), + calldata: array![NEW_DELAY.into()].span() + }; + let target_id = timelock.hash_operation(call, predecessor, salt); + + // Schedule + testing::set_contract_address(PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); + assert_only_event_schedule( + timelock.contract_address, target_id, event_index, call, predecessor, delay + ); + + // Fast-forward + testing::set_block_timestamp(delay); + + // Execute + testing::set_contract_address(EXECUTOR()); + timelock.execute(call, predecessor, salt); + assert_operation_state(timelock, OperationState::Done, target_id); + assert_event_delay(timelock.contract_address, MIN_DELAY, NEW_DELAY); + assert_only_event_execute(timelock.contract_address, target_id, event_index, call); + + // Check new minimum delay + let get_new_delay = timelock.get_min_delay(); + assert_eq!(get_new_delay, NEW_DELAY); +} + +// +// Internal +// + +// +// initializer +// + +#[test] +fn test_initializer_single_role_and_admin() { + let mut state = COMPONENT_STATE(); + let contract_state = CONTRACT_STATE(); + let min_delay = MIN_DELAY; + + let proposers = array![PROPOSER()].span(); + let executors = array![EXECUTOR()].span(); + let admin = ADMIN(); + + state.initializer(min_delay, proposers, executors, admin); + assert!(contract_state.has_role(PROPOSER_ROLE, *proposers.at(0))); + assert!(contract_state.has_role(CANCELLER_ROLE, *proposers.at(0))); + assert!(contract_state.has_role(EXECUTOR_ROLE, *executors.at(0))); + assert!(contract_state.has_role(DEFAULT_ADMIN_ROLE, admin)); +} + +#[test] +fn test_initializer_multiple_roles_and_admin() { + let mut state = COMPONENT_STATE(); + let contract_state = CONTRACT_STATE(); + let min_delay = MIN_DELAY; + + let (p1, p2, p3) = get_proposers(); + let mut proposers = array![p1, p2, p3].span(); + + let (e1, e2, e3) = get_executors(); + let mut executors = array![e1, e2, e3].span(); + + let admin = ADMIN(); + + state.initializer(min_delay, proposers, executors, admin); + + // Check assigned roles + assert!(contract_state.has_role(DEFAULT_ADMIN_ROLE, admin)); + + let mut index = 0; + loop { + if index == proposers.len() { + break; + } + + assert!(contract_state.has_role(PROPOSER_ROLE, *proposers.at(index))); + assert!(contract_state.has_role(CANCELLER_ROLE, *proposers.at(index))); + assert!(contract_state.has_role(EXECUTOR_ROLE, *executors.at(index))); + index += 1; + }; +} + +#[test] +fn test_initializer_no_admin() { + let mut state = COMPONENT_STATE(); + let contract_state = CONTRACT_STATE(); + let min_delay = MIN_DELAY; + + let proposers = array![PROPOSER()].span(); + let executors = array![EXECUTOR()].span(); + let admin_zero = ZERO(); + + // The initializer grants the timelock contract address the `DEFAULT_ADMIN_ROLE` + // therefore, we need to set the address since it's not deployed in this context + testing::set_contract_address(contract_address_const::<'TIMELOCK_ADDRESS'>()); + state.initializer(min_delay, proposers, executors, admin_zero); + + let admin_does_not_have_role = !contract_state.has_role(DEFAULT_ADMIN_ROLE, admin_zero); + assert!(admin_does_not_have_role); +} + +#[test] +fn test_initializer_supported_interfaces() { + let mut state = COMPONENT_STATE(); + let contract_state = CONTRACT_STATE(); + let min_delay = MIN_DELAY; + + let proposers = array![PROPOSER()].span(); + let executors = array![EXECUTOR()].span(); + let admin = ADMIN(); + + state.initializer(min_delay, proposers, executors, admin); + + // Check interface support + let supports_isrc5 = contract_state.src5.supports_interface(ISRC5_ID); + assert!(supports_isrc5); + + let supports_access_control = contract_state.src5.supports_interface(IACCESSCONTROL_ID); + assert!(supports_access_control); +} + +#[test] +fn test_initializer_min_delay() { + let mut state = COMPONENT_STATE(); + let min_delay = MIN_DELAY; + + let proposers = array![PROPOSER()].span(); + let executors = array![EXECUTOR()].span(); + let admin_zero = ZERO(); + + state.initializer(min_delay, proposers, executors, admin_zero); + + // Check minimum delay is set + let delay = state.get_min_delay(); + assert_eq!(delay, MIN_DELAY); + + // The initializer emits 4 `RoleGranted` events prior to `MinDelayChanged`: + // - Self administration + // - 1 proposer + // - 1 canceller + // - 1 executor + utils::drop_events(ZERO(), 4); + assert_only_event_delay_change(ZERO(), 0, MIN_DELAY); +} + +// +// assert_only_role_or_open_role +// + +#[test] +fn test_assert_only_role_or_open_role_when_has_role() { + let mut state = COMPONENT_STATE(); + let min_delay = MIN_DELAY; + + let proposers = array![PROPOSER()].span(); + let executors = array![EXECUTOR()].span(); + let admin = ADMIN(); + + state.initializer(min_delay, proposers, executors, admin); + + testing::set_caller_address(PROPOSER()); + state.assert_only_role_or_open_role(PROPOSER_ROLE); + + // PROPOSER == CANCELLER + testing::set_caller_address(PROPOSER()); + state.assert_only_role_or_open_role(CANCELLER_ROLE); + + testing::set_caller_address(EXECUTOR()); + state.assert_only_role_or_open_role(EXECUTOR_ROLE); +} + +#[test] +#[should_panic(expected: ('Caller is missing role',))] +fn test_assert_only_role_or_open_role_unauthorized() { + let mut state = COMPONENT_STATE(); + let min_delay = MIN_DELAY; + + let proposers = array![PROPOSER()].span(); + let executors = array![EXECUTOR()].span(); + let admin = ADMIN(); + + state.initializer(min_delay, proposers, executors, admin); + + testing::set_caller_address(OTHER()); + state.assert_only_role_or_open_role(PROPOSER_ROLE); +} + +#[test] +fn test_assert_only_role_or_open_role_with_open_role() { + let mut state = COMPONENT_STATE(); + let contract_state = CONTRACT_STATE(); + let min_delay = MIN_DELAY; + let open_role = ZERO(); + + let proposers = array![PROPOSER()].span(); + let executors = array![open_role].span(); + let admin = ADMIN(); + + state.initializer(min_delay, proposers, executors, admin); + + let is_open_role = contract_state.has_role(EXECUTOR_ROLE, open_role); + assert!(is_open_role); + + testing::set_caller_address(OTHER()); + state.assert_only_role_or_open_role(EXECUTOR_ROLE); +} + +// +// _before_call +// + +#[test] +fn test__before_call() { + let mut state = COMPONENT_STATE(); + let predecessor = NO_PREDECESSOR; + + // Mock targets + let target_id = 'TARGET_ID'; + let target_time = MIN_DELAY + starknet::get_block_timestamp(); + + // Set targets in storage + state.TimelockController_timestamps.write(target_id, target_time); + + // Fast-forward + testing::set_block_timestamp(target_time); + + state._before_call(target_id, predecessor); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Ready op',))] +fn test__before_call_nonexistent_operation() { + let mut state = COMPONENT_STATE(); + let predecessor = NO_PREDECESSOR; + + // Mock targets + let target_id = 'TARGET_ID'; + let not_scheduled = 0; + + // Set targets in storage + state.TimelockController_timestamps.write(target_id, not_scheduled); + + state._before_call(target_id, predecessor); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Ready op',))] +fn test__before_call_insufficient_time() { + let mut state = COMPONENT_STATE(); + let predecessor = NO_PREDECESSOR; + + // Mock targets + let target_id = 'TARGET_ID'; + let target_time = MIN_DELAY + starknet::get_block_timestamp(); + + // Set targets in storage + state.TimelockController_timestamps.write(target_id, target_time); + + // Fast-forward + testing::set_block_timestamp(target_time - 1); + + state._before_call(target_id, predecessor); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Ready op',))] +fn test__before_call_when_already_done() { + let mut state = COMPONENT_STATE(); + let predecessor = NO_PREDECESSOR; + + // Mock targets + let target_id = 'TARGET_ID'; + let done_time = 1; + + // Set targets in storage + state.TimelockController_timestamps.write(target_id, done_time); + + // Fast-forward + testing::set_block_timestamp(done_time); + + state._before_call(target_id, predecessor); +} + +#[test] +fn test__before_call_with_predecessor_done() { + let mut state = COMPONENT_STATE(); + + // Mock `Done` predecessor + let predecessor_id = 'DONE'; + let done_time = 1; + + // Mock targets + let target_id = 'TARGET_ID'; + let target_time = MIN_DELAY + starknet::get_block_timestamp(); + + // Set targets in storage + state.TimelockController_timestamps.write(predecessor_id, done_time); + state.TimelockController_timestamps.write(target_id, target_time); + + // Fast-forward + testing::set_block_timestamp(target_time); + + state._before_call(target_id, predecessor_id); +} + +#[test] +#[should_panic(expected: ('Timelock: awaiting predecessor',))] +fn test__before_call_with_predecessor_not_done() { + let mut state = COMPONENT_STATE(); + + // Mock awaiting predecessor + let predecessor_id = 'DONE'; + let not_done_time = 2; + + // Mock targets + let target_id = 'TARGET_ID'; + let target_time = MIN_DELAY + starknet::get_block_timestamp(); + + // Set targets in storage + state.TimelockController_timestamps.write(predecessor_id, not_done_time); + state.TimelockController_timestamps.write(target_id, target_time); + + // Fast-forward + testing::set_block_timestamp(target_time); + + state._before_call(target_id, predecessor_id); +} + +// +// _after_call +// + +#[test] +fn test__after_call() { + let mut state = COMPONENT_STATE(); + + // Mock targets + let target_id = 'TARGET_ID'; + let target_time = MIN_DELAY + starknet::get_block_timestamp(); + + // Set targets in storage + state.TimelockController_timestamps.write(target_id, target_time); + + // Fast-forward + testing::set_block_timestamp(target_time); + + state._after_call(target_id); + + // Check timestamp is set to done (1) + let done_ts = 1; + let is_done = state.TimelockController_timestamps.read(target_id); + assert_eq!(is_done, done_ts); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Ready op',))] +fn test__after_call_nonexistent_operation() { + let mut state = COMPONENT_STATE(); + + // Mock targets + let target_id = 'TARGET_ID'; + let not_scheduled = 0; + + // Set targets in storage + state.TimelockController_timestamps.write(target_id, not_scheduled); + + state._after_call(target_id); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Ready op',))] +fn test__after_call_insufficient_time() { + let mut state = COMPONENT_STATE(); + + // Mock targets + let target_id = 'TARGET_ID'; + let target_time = MIN_DELAY + starknet::get_block_timestamp(); + + // Set targets in storage + state.TimelockController_timestamps.write(target_id, target_time); + + // Fast-forward + testing::set_block_timestamp(target_time - 1); + + state._after_call(target_id); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Ready op',))] +fn test__after_call_already_done() { + let mut state = COMPONENT_STATE(); + + // Mock targets + let target_id = 'TARGET_ID'; + let done_time = 1; + + // Set targets in storage + state.TimelockController_timestamps.write(target_id, done_time); + + // Fast-forward + testing::set_block_timestamp(done_time); + + state._after_call(target_id); +} + +// +// _schedule +// + +#[test] +fn test__schedule() { + let mut state = COMPONENT_STATE(); + let mut target = deploy_mock_target(); + let predecessor = NO_PREDECESSOR; + let delay = MIN_DELAY; + let mut salt = 0; + + // Set up call + let call = single_operation(target.contract_address); + let target_id = state.hash_operation(call, predecessor, salt); + + // Schedule + state._schedule(target_id, delay); + + let actual_ts = state.TimelockController_timestamps.read(target_id); + let expected_ts = starknet::get_block_timestamp() + delay; + assert_eq!(actual_ts, expected_ts); +} + +#[test] +#[should_panic(expected: ('Timelock: expected Unset op',))] +fn test__schedule_overwrite() { + let mut state = COMPONENT_STATE(); + let mut target = deploy_mock_target(); + let predecessor = NO_PREDECESSOR; + let delay = MIN_DELAY; + let mut salt = 0; + + // Set up call + let call = single_operation(target.contract_address); + let target_id = state.hash_operation(call, predecessor, salt); + + // Schedule and overwrite + state._schedule(target_id, delay); + state._schedule(target_id, delay); +} + +#[test] +#[should_panic(expected: ('Timelock: insufficient delay',))] +fn test__schedule_bad_delay() { + let mut state = COMPONENT_STATE(); + let mut target = deploy_mock_target(); + let predecessor = NO_PREDECESSOR; + let mut salt = 0; + let delay = MIN_DELAY; + + // Set up call + let call = single_operation(target.contract_address); + let target_id = state.hash_operation(call, predecessor, salt); + + // Set min delay + state.TimelockController_min_delay.write(delay); + + // Schedule with bad delay + state._schedule(target_id, delay - 1); +} + +// +// _execute +// + +#[test] +fn test__execute() { + let mut state = COMPONENT_STATE(); + let mut target = deploy_mock_target(); + + // Set up call + let call = single_operation(target.contract_address); + + let storage_num = target.get_number(); + let expected_num = 0; + assert_eq!(storage_num, expected_num); + + // Execute + state._execute(call); + + let storage_num = target.get_number(); + let expected_num = VALUE; + assert_eq!(storage_num, expected_num); +} + +#[test] +#[should_panic(expected: ('Expected failure', 'ENTRYPOINT_FAILED',))] +fn test__execute_with_failing_tx() { + let mut state = COMPONENT_STATE(); + let mut target = deploy_mock_target(); + + // Set up call + let call = failing_operation(target.contract_address); + + // Execute failing tx + state._execute(call); +} + +#[test] +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] +fn test__execute_with_bad_selector() { + let mut state = COMPONENT_STATE(); + let mut target = deploy_mock_target(); + + // Set up call + let bad_selector_call = operation_with_bad_selector(target.contract_address); + + // Execute call with bad selector + state._execute(bad_selector_call); +} + +// +// Helpers +// + +fn assert_operation_state(timelock: TimelockABIDispatcher, exp_state: OperationState, id: felt252) { + let operation_state = timelock.get_operation_state(id); + assert_eq!(operation_state, exp_state); + + let is_operation = timelock.is_operation(id); + let is_pending = timelock.is_operation_pending(id); + let is_ready = timelock.is_operation_ready(id); + let is_done = timelock.is_operation_done(id); + + match exp_state { + OperationState::Unset => { + assert!(!is_operation); + assert!(!is_pending); + assert!(!is_ready); + assert!(!is_done); + }, + OperationState::Waiting => { + assert!(is_operation); + assert!(is_pending); + assert!(!is_ready); + assert!(!is_done); + }, + OperationState::Ready => { + assert!(is_operation); + assert!(is_pending); + assert!(is_ready); + assert!(!is_done); + }, + OperationState::Done => { + assert!(is_operation); + assert!(!is_pending); + assert!(!is_ready); + assert!(is_done); + } + }; +} + +// +// Event helpers +// + +// +// MinDelayChanged +// + +fn assert_event_delay_change(contract: ContractAddress, old_duration: u64, new_duration: u64) { + let event = utils::pop_log::(contract).unwrap(); + let expected = TimelockControllerComponent::Event::MinDelayChanged( + MinDelayChanged { old_duration, new_duration } + ); + assert!(event == expected); +} + +fn assert_only_event_delay_change(contract: ContractAddress, old_duration: u64, new_duration: u64) { + assert_event_delay_change(contract, old_duration, new_duration); + utils::assert_no_events_left(contract); +} + +// +// CallScheduled +// + +fn assert_event_schedule( + contract: ContractAddress, + id: felt252, + index: felt252, + call: Call, + predecessor: felt252, + delay: u64 +) { + let event = utils::pop_log::(contract).unwrap(); + let expected = TimelockControllerComponent::Event::CallScheduled( + CallScheduled { id, index, call, predecessor, delay } + ); + assert!(event == expected); + + // Check indexed keys + let mut indexed_keys = array![]; + indexed_keys.append_serde(selector!("CallScheduled")); + indexed_keys.append_serde(id); + indexed_keys.append_serde(index); + utils::assert_indexed_keys(event, indexed_keys.span()); +} + +fn assert_only_event_schedule( + contract: ContractAddress, + id: felt252, + index: felt252, + call: Call, + predecessor: felt252, + delay: u64 +) { + assert_event_schedule(contract, id, index, call, predecessor, delay); + utils::assert_no_events_left(contract); +} + +fn assert_events_schedule_batch( + contract: ContractAddress, id: felt252, calls: Span, predecessor: felt252, delay: u64 +) { + let mut i = 0; + loop { + if i == calls.len() { + break; + } + assert_event_schedule(contract, id, i.into(), *calls.at(i), predecessor, delay); + i += 1; + } +} + +fn assert_only_events_schedule_batch( + contract: ContractAddress, id: felt252, calls: Span, predecessor: felt252, delay: u64 +) { + assert_events_schedule_batch(contract, id, calls, predecessor, delay); + utils::assert_no_events_left(contract); +} + +// +// CallSalt +// + +fn assert_event_call_salt(contract: ContractAddress, id: felt252, salt: felt252) { + let event = utils::pop_log::(contract).unwrap(); + let expected = TimelockControllerComponent::Event::CallSalt(CallSalt { id, salt }); + assert!(event == expected); +} + +fn assert_only_event_call_salt(contract: ContractAddress, id: felt252, salt: felt252) { + assert_event_call_salt(contract, id, salt); + utils::assert_no_events_left(contract); +} + +// +// CallExecuted +// + +fn assert_event_execute(contract: ContractAddress, id: felt252, index: felt252, call: Call) { + let event = utils::pop_log::(contract).unwrap(); + let expected = TimelockControllerComponent::Event::CallExecuted( + CallExecuted { id, index, call } + ); + assert!(event == expected); + + // Check indexed keys + let mut indexed_keys = array![]; + indexed_keys.append_serde(selector!("CallExecuted")); + indexed_keys.append_serde(id); + indexed_keys.append_serde(index); + utils::assert_indexed_keys(event, indexed_keys.span()); +} + +fn assert_only_event_execute(contract: ContractAddress, id: felt252, index: felt252, call: Call) { + assert_event_execute(contract, id, index, call); + utils::assert_no_events_left(contract); +} + +fn assert_events_execute_batch(contract: ContractAddress, id: felt252, calls: Span) { + let mut i = 0; + loop { + if i == calls.len() { + break; + } + assert_event_execute(contract, id, i.into(), *calls.at(i)); + i += 1; + } +} + +fn assert_only_events_execute_batch(contract: ContractAddress, id: felt252, calls: Span) { + assert_events_execute_batch(contract, id, calls); + utils::assert_no_events_left(contract); +} + +// +// Cancelled +// + +fn assert_event_cancel(contract: ContractAddress, id: felt252) { + let event = utils::pop_log::(contract).unwrap(); + let expected = TimelockControllerComponent::Event::CallCancelled(CallCancelled { id }); + assert!(event == expected); + + // Check indexed keys + let mut indexed_keys = array![]; + indexed_keys.append_serde(selector!("CallCancelled")); + indexed_keys.append_serde(id); + utils::assert_indexed_keys(event, indexed_keys.span()); +} + +fn assert_only_event_cancel(contract: ContractAddress, id: felt252) { + assert_event_cancel(contract, id); + utils::assert_no_events_left(contract); +} + +// +// MinDelayChanged +// + +fn assert_event_delay(contract: ContractAddress, old_duration: u64, new_duration: u64) { + let event = utils::pop_log::(contract).unwrap(); + let expected = TimelockControllerComponent::Event::MinDelayChanged( + MinDelayChanged { old_duration, new_duration } + ); + assert!(event == expected); +} + +fn assert_only_event_delay(contract: ContractAddress, old_duration: u64, new_duration: u64) { + assert_event_delay(contract, old_duration, new_duration); + utils::assert_no_events_left(contract); +} diff --git a/src/tests/governance/test_utils.cairo b/src/tests/governance/test_utils.cairo new file mode 100644 index 000000000..874fe2615 --- /dev/null +++ b/src/tests/governance/test_utils.cairo @@ -0,0 +1,146 @@ +use openzeppelin::governance::timelock::utils::call_impls::CallPartialEq; +use starknet::account::Call; +use starknet::contract_address_const; + +// +// eq +// + +#[test] +fn test_eq_calls_no_calldata() { + let call_1 = Call { to: contract_address_const::<1>(), selector: 1, calldata: array![].span() }; + let call_2 = Call { to: contract_address_const::<1>(), selector: 1, calldata: array![].span() }; + assert_eq!(call_1, call_2); +} + +#[test] +fn test_eq_calls_with_calldata() { + let call_1 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2, 3].span() + }; + let call_2 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2, 3].span() + }; + assert_eq!(call_1, call_2); +} + +#[test] +#[should_panic] +fn test_eq_calls_ne_to() { + let call_1 = Call { to: contract_address_const::<1>(), selector: 1, calldata: array![].span() }; + let call_2 = Call { to: contract_address_const::<2>(), selector: 1, calldata: array![].span() }; + assert_eq!(call_1, call_2); +} + +#[test] +#[should_panic] +fn test_eq_calls_ne_selector() { + let call_1 = Call { to: contract_address_const::<1>(), selector: 1, calldata: array![].span() }; + let call_2 = Call { to: contract_address_const::<1>(), selector: 2, calldata: array![].span() }; + assert_eq!(call_1, call_2); +} + +#[test] +#[should_panic] +fn test_eq_calls_gt_calldata() { + let call_1 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1].span() + }; + let call_2 = Call { to: contract_address_const::<1>(), selector: 2, calldata: array![].span() }; + assert_eq!(call_1, call_2); +} + +#[test] +#[should_panic] +fn test_eq_calls_lt_calldata() { + let call_1 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1].span() + }; + let call_2 = Call { + to: contract_address_const::<1>(), selector: 2, calldata: array![1, 2].span() + }; + assert_eq!(call_1, call_2); +} + +#[test] +#[should_panic] +fn test_eq_calls_ne_calldata() { + let call_1 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2].span() + }; + let call_2 = Call { + to: contract_address_const::<1>(), selector: 2, calldata: array![2, 1].span() + }; + assert_eq!(call_1, call_2); +} + +// +// ne +// + +#[test] +fn test_ne_calls_to() { + let call_1 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2, 3].span() + }; + let call_2 = Call { + to: contract_address_const::<2>(), selector: 1, calldata: array![1, 2, 3].span() + }; + assert_ne!(call_1, call_2); +} + +#[test] +fn test_ne_calls_selector() { + let call_1 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2, 3].span() + }; + let call_2 = Call { + to: contract_address_const::<1>(), selector: 2, calldata: array![1, 2, 3].span() + }; + assert_ne!(call_1, call_2); +} + +#[test] +fn test_ne_calls_gt_calldata() { + let call_1 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2, 3].span() + }; + let call_2 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2].span() + }; + assert_ne!(call_1, call_2); +} + +#[test] +fn test_ne_calls_lt_calldata() { + let call_1 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2].span() + }; + let call_2 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2, 3].span() + }; + assert_ne!(call_1, call_2); +} + +#[test] +fn test_ne_calls_eq_len_calldata() { + let call_1 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2, 3].span() + }; + let call_2 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![3, 2, 1].span() + }; + assert_ne!(call_1, call_2); +} + +#[test] +#[should_panic] +fn test_ne_calls_when_eq() { + let call_1 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2, 3].span() + }; + let call_2 = Call { + to: contract_address_const::<1>(), selector: 1, calldata: array![1, 2, 3].span() + }; + assert_ne!(call_1, call_2); +} diff --git a/src/tests/mocks.cairo b/src/tests/mocks.cairo index 6e6e38156..daaf65baf 100644 --- a/src/tests/mocks.cairo +++ b/src/tests/mocks.cairo @@ -14,4 +14,5 @@ pub(crate) mod ownable_mocks; pub(crate) mod pausable_mocks; pub(crate) mod reentrancy_mocks; pub(crate) mod src5_mocks; +pub(crate) mod timelock_mocks; pub(crate) mod upgrades_mocks; diff --git a/src/tests/mocks/erc721_receiver_mocks.cairo b/src/tests/mocks/erc721_receiver_mocks.cairo index f496d0a9c..55ca3aebf 100644 --- a/src/tests/mocks/erc721_receiver_mocks.cairo +++ b/src/tests/mocks/erc721_receiver_mocks.cairo @@ -65,7 +65,7 @@ pub(crate) mod DualCaseERC721ReceiverMock { tokenId: u256, data: Span ) -> felt252 { - ExternalTrait::on_erc721_received(self, operator, from, tokenId, data) + Self::on_erc721_received(self, operator, from, tokenId, data) } } } diff --git a/src/tests/mocks/eth_account_mocks.cairo b/src/tests/mocks/eth_account_mocks.cairo index 687e5d68f..24161d3ba 100644 --- a/src/tests/mocks/eth_account_mocks.cairo +++ b/src/tests/mocks/eth_account_mocks.cairo @@ -2,7 +2,6 @@ pub(crate) mod DualCaseEthAccountMock { use openzeppelin::account::EthAccountComponent; use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin::introspection::src5::SRC5Component; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); @@ -47,7 +46,6 @@ pub(crate) mod DualCaseEthAccountMock { pub(crate) mod SnakeEthAccountMock { use openzeppelin::account::EthAccountComponent; use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin::introspection::src5::SRC5Component; component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); @@ -88,7 +86,6 @@ pub(crate) mod SnakeEthAccountMock { pub(crate) mod CamelEthAccountMock { use openzeppelin::account::EthAccountComponent; use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use openzeppelin::introspection::src5::SRC5Component; use starknet::account::Call; @@ -151,7 +148,6 @@ pub(crate) mod CamelEthAccountMock { #[starknet::contract] pub(crate) mod SnakeEthAccountPanicMock { use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use starknet::SyscallResultTrait; use starknet::secp256_trait::Secp256Trait; @@ -193,7 +189,6 @@ pub(crate) mod SnakeEthAccountPanicMock { #[starknet::contract] pub(crate) mod CamelEthAccountPanicMock { use openzeppelin::account::interface::EthPublicKey; - use openzeppelin::account::utils::secp256k1::Secp256k1PointSerde; use starknet::SyscallResultTrait; use starknet::secp256_trait::Secp256Trait; diff --git a/src/tests/mocks/timelock_mocks.cairo b/src/tests/mocks/timelock_mocks.cairo new file mode 100644 index 000000000..a60a9da19 --- /dev/null +++ b/src/tests/mocks/timelock_mocks.cairo @@ -0,0 +1,151 @@ +#[starknet::contract] +pub(crate) mod TimelockControllerMock { + use openzeppelin::access::accesscontrol::AccessControlComponent; + use openzeppelin::governance::timelock::TimelockControllerComponent; + use openzeppelin::introspection::src5::SRC5Component; + use starknet::ContractAddress; + + component!(path: AccessControlComponent, storage: access_control, event: AccessControlEvent); + component!(path: SRC5Component, storage: src5, event: SRC5Event); + component!(path: TimelockControllerComponent, storage: timelock, event: TimelockEvent); + + // Timelock Mixin + #[abi(embed_v0)] + impl TimelockMixinImpl = + TimelockControllerComponent::TimelockMixinImpl; + impl TimelockInternalImpl = TimelockControllerComponent::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + access_control: AccessControlComponent::Storage, + #[substorage(v0)] + src5: SRC5Component::Storage, + #[substorage(v0)] + timelock: TimelockControllerComponent::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + AccessControlEvent: AccessControlComponent::Event, + #[flat] + SRC5Event: SRC5Component::Event, + #[flat] + TimelockEvent: TimelockControllerComponent::Event + } + + #[constructor] + fn constructor( + ref self: ContractState, + min_delay: u64, + proposers: Span, + executors: Span, + admin: ContractAddress + ) { + self.timelock.initializer(min_delay, proposers, executors, admin); + } +} + +#[starknet::interface] +pub(crate) trait IMockContract { + fn set_number(ref self: TState, new_number: felt252); + fn get_number(self: @TState) -> felt252; + fn failing_function(self: @TState); +} + +#[starknet::contract] +pub(crate) mod MockContract { + use super::IMockContract; + + #[storage] + struct Storage { + number: felt252, + } + + #[abi(embed_v0)] + impl MockContractImpl of IMockContract { + fn set_number(ref self: ContractState, new_number: felt252) { + self.number.write(new_number); + } + + fn get_number(self: @ContractState) -> felt252 { + self.number.read() + } + + fn failing_function(self: @ContractState) { + core::panic_with_felt252('Expected failure'); + } + } +} + +#[starknet::interface] +pub(crate) trait ITimelockAttacker { + fn reenter(ref self: TState); + fn reenter_batch(ref self: TState); +} + +#[starknet::contract] +pub(crate) mod TimelockAttackerMock { + use openzeppelin::governance::timelock::interface::{ + ITimelockDispatcher, ITimelockDispatcherTrait + }; + use starknet::ContractAddress; + use starknet::account::Call; + use super::ITimelockAttacker; + + const NO_PREDECESSOR: felt252 = 0; + const NO_SALT: felt252 = 0; + + #[storage] + struct Storage { + balance: felt252, + count: felt252 + } + + #[abi(embed_v0)] + impl TimelockAttackerImpl of ITimelockAttacker { + fn reenter(ref self: ContractState) { + let new_balance = self.balance.read() + 1; + self.balance.write(new_balance); + + let sender = starknet::get_caller_address(); + let this = starknet::get_contract_address(); + + let current_count = self.count.read(); + if current_count != 2 { + self.count.write(current_count + 1); + + let reentrant_call = Call { + to: this, selector: selector!("reenter"), calldata: array![].span() + }; + + let timelock = ITimelockDispatcher { contract_address: sender }; + timelock.execute(reentrant_call, NO_PREDECESSOR, NO_SALT); + } + } + + fn reenter_batch(ref self: ContractState) { + let new_balance = self.balance.read() + 1; + self.balance.write(new_balance); + + let sender = starknet::get_caller_address(); + let this = starknet::get_contract_address(); + + let current_count = self.count.read(); + if current_count != 2 { + self.count.write(current_count + 1); + + let reentrant_call = Call { + to: this, selector: selector!("reenter_batch"), calldata: array![].span() + }; + + let calls = array![reentrant_call].span(); + + let timelock = ITimelockDispatcher { contract_address: sender }; + timelock.execute_batch(calls, NO_PREDECESSOR, NO_SALT); + } + } + } +} diff --git a/src/tests/presets/test_eth_account.cairo b/src/tests/presets/test_eth_account.cairo index c30da1c7e..231e26c5b 100644 --- a/src/tests/presets/test_eth_account.cairo +++ b/src/tests/presets/test_eth_account.cairo @@ -1,8 +1,6 @@ use core::num::traits::Zero; use openzeppelin::account::interface::ISRC6_ID; -use openzeppelin::account::utils::secp256k1::{ - DebugSecp256k1Point, Secp256k1PointSerde, Secp256k1PointPartialEq -}; +use openzeppelin::account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; use openzeppelin::introspection::interface::ISRC5_ID; use openzeppelin::presets::EthAccountUpgradeable; use openzeppelin::presets::interfaces::eth_account::{ diff --git a/src/tests/security/test_reentrancyguard.cairo b/src/tests/security/test_reentrancyguard.cairo index 4a12bc918..d6de45ef0 100644 --- a/src/tests/security/test_reentrancyguard.cairo +++ b/src/tests/security/test_reentrancyguard.cairo @@ -4,7 +4,6 @@ use openzeppelin::tests::mocks::reentrancy_mocks::{ ReentrancyMock, IReentrancyMockDispatcher, IReentrancyMockDispatcherTrait }; use openzeppelin::tests::utils; -use starknet::storage::StorageMemberAccessTrait; type ComponentState = ReentrancyGuardComponent::ComponentState; diff --git a/src/tests/token/erc1155/test_erc1155.cairo b/src/tests/token/erc1155/test_erc1155.cairo index 951de7b70..110d93b68 100644 --- a/src/tests/token/erc1155/test_erc1155.cairo +++ b/src/tests/token/erc1155/test_erc1155.cairo @@ -1,5 +1,4 @@ use core::num::traits::Zero; -use core::starknet::storage::StorageMemberAccessTrait; use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; use openzeppelin::introspection; use openzeppelin::tests::mocks::erc1155_mocks::DualCaseERC1155Mock; diff --git a/src/tests/token/erc20/test_erc20_votes.cairo b/src/tests/token/erc20/test_erc20_votes.cairo index 269ec1d44..21f0d8ba2 100644 --- a/src/tests/token/erc20/test_erc20_votes.cairo +++ b/src/tests/token/erc20/test_erc20_votes.cairo @@ -24,7 +24,6 @@ use snforge_std::{ use snforge_std::{EventSpy, EventSpyAssertionsTrait}; use starknet::ContractAddress; use starknet::contract_address_const; -use starknet::storage::{StorageMapMemberAccessTrait, StorageMemberAccessTrait}; // // Setup @@ -304,7 +303,7 @@ fn test_delegate_by_sig_invalid_signature() { #[test] fn test_num_checkpoints() { - let state = setup(); + let state = @setup(); let mut trace = state.ERC20Votes_delegate_checkpoints.read(OWNER()); trace.push('ts1', 0x111); @@ -322,7 +321,7 @@ fn test_num_checkpoints() { #[test] fn test_checkpoints() { - let state = setup(); + let state = @setup(); let mut trace = state.ERC20Votes_delegate_checkpoints.read(OWNER()); trace.push('ts1', 0x111); diff --git a/src/tests/token/erc721/test_erc721.cairo b/src/tests/token/erc721/test_erc721.cairo index 8055d9c17..b7fb9c996 100644 --- a/src/tests/token/erc721/test_erc721.cairo +++ b/src/tests/token/erc721/test_erc721.cairo @@ -14,7 +14,6 @@ use openzeppelin::token::erc721::ERC721Component; use openzeppelin::token::erc721; use snforge_std::{spy_events, test_address, start_cheat_caller_address}; use starknet::ContractAddress; -use starknet::storage::StorageMapMemberAccessTrait; use super::common::ERC721SpyHelpers; diff --git a/src/token/erc1155/dual1155.cairo b/src/token/erc1155/dual1155.cairo index b0aac8f8b..a6644df67 100644 --- a/src/token/erc1155/dual1155.cairo +++ b/src/token/erc1155/dual1155.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc1155/dual1155.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc1155/dual1155.cairo) use openzeppelin::utils::UnwrapAndCast; use openzeppelin::utils::selectors; diff --git a/src/token/erc1155/dual1155_receiver.cairo b/src/token/erc1155/dual1155_receiver.cairo index 24d35834f..e53df5d3c 100644 --- a/src/token/erc1155/dual1155_receiver.cairo +++ b/src/token/erc1155/dual1155_receiver.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc1155/dual1155_receiver.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc1155/dual1155_receiver.cairo) use openzeppelin::utils::UnwrapAndCast; use openzeppelin::utils::selectors; diff --git a/src/token/erc1155/erc1155.cairo b/src/token/erc1155/erc1155.cairo index 493207c40..f852af2a0 100644 --- a/src/token/erc1155/erc1155.cairo +++ b/src/token/erc1155/erc1155.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc1155/erc1155.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc1155/erc1155.cairo) use starknet::ContractAddress; @@ -21,11 +21,12 @@ pub mod ERC1155Component { use openzeppelin::token::erc1155::interface; use starknet::ContractAddress; use starknet::get_caller_address; + use starknet::storage::Map; #[storage] struct Storage { - ERC1155_balances: LegacyMap<(u256, ContractAddress), u256>, - ERC1155_operator_approvals: LegacyMap<(ContractAddress, ContractAddress), bool>, + ERC1155_balances: Map<(u256, ContractAddress), u256>, + ERC1155_operator_approvals: Map<(ContractAddress, ContractAddress), bool>, ERC1155_uri: ByteArray, } @@ -75,10 +76,11 @@ pub mod ERC1155Component { pub approved: bool } - /// Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. + /// Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic + /// URI. /// - /// If an `URI` event was emitted for `id`, the standard guarantees that `value` will equal the value - /// returned by `IERC1155MetadataURI::uri`. + /// If an `URI` event was emitted for `id`, the standard guarantees that `value` will equal the + /// value returned by `IERC1155MetadataURI::uri`. /// https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions #[derive(Drop, PartialEq, starknet::Event)] pub struct URI { @@ -158,19 +160,20 @@ pub mod ERC1155Component { break; } batch_balances - .append(ERC1155::balance_of(self, *accounts.at(index), *token_ids.at(index))); + .append(Self::balance_of(self, *accounts.at(index), *token_ids.at(index))); index += 1; }; batch_balances.span() } - /// Transfers ownership of `value` amount of `token_id` from `from` if `to` is either an account or `IERC1155Receiver`. + /// Transfers ownership of `value` amount of `token_id` from `from` if `to` is either an + /// account or `IERC1155Receiver`. /// /// `data` is additional data, it has no specified format and it is passed to `to`. /// - /// WARNING: This function can potentially allow a reentrancy attack when transferring tokens - /// to an untrusted contract, when invoking `on_ERC1155_received` on the receiver. + /// WARNING: This function can potentially allow a reentrancy attack when transferring + /// tokens to an untrusted contract, when invoking `on_ERC1155_received` on the receiver. /// Ensure to follow the checks-effects-interactions pattern and consider employing /// reentrancy guards when interacting with untrusted contracts. /// @@ -179,7 +182,8 @@ pub mod ERC1155Component { /// - Caller is either approved or the `token_id` owner. /// - `from` is not the zero address. /// - `to` is not the zero address. - /// - If `to` refers to a non-account contract, it must implement `IERC1155Receiver::on_ERC1155_received` + /// - If `to` refers to a non-account contract, it must implement + /// `IERC1155Receiver::on_ERC1155_received` /// and return the required magic value. /// /// Emits a `TransferSingle` event. @@ -193,13 +197,14 @@ pub mod ERC1155Component { ) { let token_ids = array![token_id].span(); let values = array![value].span(); - ERC1155::safe_batch_transfer_from(ref self, from, to, token_ids, values, data) + Self::safe_batch_transfer_from(ref self, from, to, token_ids, values, data) } /// Batched version of `safe_transfer_from`. /// - /// WARNING: This function can potentially allow a reentrancy attack when transferring tokens - /// to an untrusted contract, when invoking `on_ERC1155_batch_received` on the receiver. + /// WARNING: This function can potentially allow a reentrancy attack when transferring + /// tokens to an untrusted contract, when invoking `on_ERC1155_batch_received` on the + /// receiver. /// Ensure to follow the checks-effects-interactions pattern and consider employing /// reentrancy guards when interacting with untrusted contracts. /// @@ -209,10 +214,12 @@ pub mod ERC1155Component { /// - `from` is not the zero address. /// - `to` is not the zero address. /// - `token_ids` and `values` must have the same length. - /// - If `to` refers to a non-account contract, it must implement `IERC1155Receiver::on_ERC1155_batch_received` + /// - If `to` refers to a non-account contract, it must implement + /// `IERC1155Receiver::on_ERC1155_batch_received` /// and return the acceptance magic value. /// - /// Emits either a `TransferSingle` or a `TransferBatch` event, depending on the length of the array arguments. + /// Emits either a `TransferSingle` or a `TransferBatch` event, depending on the length of + /// the array arguments. fn safe_batch_transfer_from( ref self: ComponentState, from: starknet::ContractAddress, @@ -226,7 +233,7 @@ pub mod ERC1155Component { let operator = get_caller_address(); if from != operator { - assert(ERC1155::is_approved_for_all(@self, from, operator), Errors::UNAUTHORIZED); + assert(Self::is_approved_for_all(@self, from, operator), Errors::UNAUTHORIZED); } self.update_with_acceptance_check(from, to, token_ids, values, data); @@ -483,7 +490,8 @@ pub mod ERC1155Component { /// Requirements: /// /// - `to` cannot be the zero address. - /// - If `to` refers to a smart contract, it must implement `IERC1155Receiver::on_ERC1155_received` + /// - If `to` refers to a smart contract, it must implement + /// `IERC1155Receiver::on_ERC1155_received` /// and return the acceptance magic value. /// /// Emits a `TransferSingle` event. @@ -507,7 +515,8 @@ pub mod ERC1155Component { /// /// - `to` cannot be the zero address. /// - `token_ids` and `values` must have the same length. - /// - If `to` refers to a smart contract, it must implement `IERC1155Receiver::on_ERC1155_batch_received` + /// - If `to` refers to a smart contract, it must implement + /// `IERC1155Receiver::on_ERC1155_batch_received` /// and return the acceptance magic value. /// /// Emits a `TransferBatch` event. @@ -571,7 +580,8 @@ pub mod ERC1155Component { /// - `to` is either an account contract or supports the `IERC1155Receiver` interface. /// - `token_ids` and `values` must have the same length. /// - /// Emits a `TransferSingle` event if the arrays contain one element, and `TransferBatch` otherwise. + /// Emits a `TransferSingle` event if the arrays contain one element, and `TransferBatch` + /// otherwise. fn update_with_acceptance_check( ref self: ComponentState, from: ContractAddress, @@ -596,7 +606,8 @@ pub mod ERC1155Component { /// /// - `token_ids` and `values` must have the same length. /// - /// Emits a `TransferSingle` event if the arrays contain one element, and `TransferBatch` otherwise. + /// Emits a `TransferSingle` event if the arrays contain one element, and `TransferBatch` + /// otherwise. /// /// NOTE: This function can be extended using the `ERC1155HooksTrait`, to add /// functionality before and/or after the transfer, mint, or burn. diff --git a/src/token/erc1155/erc1155_receiver.cairo b/src/token/erc1155/erc1155_receiver.cairo index 48e7e7361..f9ac00b80 100644 --- a/src/token/erc1155/erc1155_receiver.cairo +++ b/src/token/erc1155/erc1155_receiver.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc1155/erc1155_receiver.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc1155/erc1155_receiver.cairo) /// # ERC1155Receiver Component /// diff --git a/src/token/erc1155/interface.cairo b/src/token/erc1155/interface.cairo index db7be1e27..6fb5bd109 100644 --- a/src/token/erc1155/interface.cairo +++ b/src/token/erc1155/interface.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc1155/interface.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc1155/interface.cairo) use starknet::ContractAddress; diff --git a/src/token/erc20/dual20.cairo b/src/token/erc20/dual20.cairo index 54b42697e..9165574d0 100644 --- a/src/token/erc20/dual20.cairo +++ b/src/token/erc20/dual20.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc20/dual20.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc20/dual20.cairo) use openzeppelin::utils::UnwrapAndCast; use openzeppelin::utils::selectors; @@ -48,7 +48,7 @@ impl DualCaseERC20Impl of DualCaseERC20Trait { } fn total_supply(self: @DualCaseERC20) -> u256 { - let mut args = array![]; + let args = array![]; try_selector_with_fallback( *self.contract_address, selectors::total_supply, selectors::totalSupply, args.span() ) diff --git a/src/token/erc20/erc20.cairo b/src/token/erc20/erc20.cairo index 4cd568375..6d8e0f3cf 100644 --- a/src/token/erc20/erc20.cairo +++ b/src/token/erc20/erc20.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc20/erc20.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc20/erc20.cairo) use starknet::ContractAddress; @@ -9,7 +9,8 @@ use starknet::ContractAddress; /// non-standard implementations that can be used to create an ERC20 contract. This /// component is agnostic regarding how tokens are created, which means that developers /// must create their own token distribution mechanism. -/// See [the documentation](https://docs.openzeppelin.com/contracts-cairo/0.14.0/guides/erc20-supply) +/// See [the documentation] +/// (https://docs.openzeppelin.com/contracts-cairo/0.15.0-rc.0/guides/erc20-supply) /// for examples. #[starknet::component] pub mod ERC20Component { @@ -18,14 +19,15 @@ pub mod ERC20Component { use openzeppelin::token::erc20::interface; use starknet::ContractAddress; use starknet::get_caller_address; + use starknet::storage::Map; #[storage] struct Storage { ERC20_name: ByteArray, ERC20_symbol: ByteArray, ERC20_total_supply: u256, - ERC20_balances: LegacyMap, - ERC20_allowances: LegacyMap<(ContractAddress, ContractAddress), u256>, + ERC20_balances: Map, + ERC20_allowances: Map<(ContractAddress, ContractAddress), u256>, } #[event] @@ -294,7 +296,8 @@ pub mod ERC20Component { TContractState, +HasComponent, impl Hooks: ERC20HooksTrait > of InternalTrait { /// Initializes the contract by setting the token name and symbol. - /// To prevent reinitialization, this should only be used inside of a contract's constructor. + /// To prevent reinitialization, this should only be used inside of a contract's + /// constructor. fn initializer( ref self: ComponentState, name: ByteArray, symbol: ByteArray ) { @@ -330,8 +333,8 @@ pub mod ERC20Component { } - /// Transfers an `amount` of tokens from `from` to `to`, or alternatively mints (or burns) if `from` (or `to`) is - /// the zero address. + /// Transfers an `amount` of tokens from `from` to `to`, or alternatively mints (or burns) + /// if `from` (or `to`) is the zero address. /// /// NOTE: This function can be extended using the `ERC20HooksTrait`, to add /// functionality before and/or after the transfer, mint, or burn. diff --git a/src/token/erc20/extensions/erc20_votes.cairo b/src/token/erc20/extensions/erc20_votes.cairo index 069fd626c..0a9d2f50b 100644 --- a/src/token/erc20/extensions/erc20_votes.cairo +++ b/src/token/erc20/extensions/erc20_votes.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc20/extensions/erc20_votes.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc20/extensions/erc20_votes.cairo) use core::hash::{Hash, HashStateTrait, HashStateExTrait}; use core::poseidon::PoseidonTrait; @@ -8,11 +8,12 @@ use starknet::ContractAddress; /// # ERC20Votes Component /// -/// The ERC20Votes component tracks voting units from ERC20 balances, which are a measure of voting power that can be -/// transferred, and provides a system of vote delegation, where an account can delegate its voting units to a sort of -/// "representative" that will pool delegated voting units from different accounts and can then use it to vote in -/// decisions. In fact, voting units MUST be delegated in order to count as actual votes, and an account has to -/// delegate those votes to itself if it wishes to participate in decisions and does not have a trusted representative. +/// The ERC20Votes component tracks voting units from ERC20 balances, which are a measure of voting +/// power that can be transferred, and provides a system of vote delegation, where an account can +/// delegate its voting units to a sort of "representative" that will pool delegated voting units +/// from different accounts and can then use it to vote in decisions. In fact, voting units MUST be +/// delegated in order to count as actual votes, and an account has to delegate those votes to +/// itself if it wishes to participate in decisions and does not have a trusted representative. #[starknet::component] pub mod ERC20VotesComponent { use core::num::traits::Zero; @@ -24,12 +25,13 @@ pub mod ERC20VotesComponent { use openzeppelin::utils::nonces::NoncesComponent; use openzeppelin::utils::structs::checkpoint::{Checkpoint, Trace, TraceTrait}; use starknet::ContractAddress; + use starknet::storage::Map; use super::{Delegation, OffchainMessageHash, SNIP12Metadata}; #[storage] struct Storage { - ERC20Votes_delegatee: LegacyMap, - ERC20Votes_delegate_checkpoints: LegacyMap, + ERC20Votes_delegatee: Map, + ERC20Votes_delegate_checkpoints: Map, ERC20Votes_total_checkpoints: Trace } @@ -101,9 +103,10 @@ pub mod ERC20VotesComponent { /// /// - `timepoint` must be in the past. /// - /// NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. - /// Votes that have not been delegated are still part of total supply, even though they would not participate in a - /// vote. + /// NOTE: This value is the sum of all available votes, which is not necessarily the sum of + /// all delegated votes. + /// Votes that have not been delegated are still part of total supply, even though they + /// would not participate in a vote. fn get_past_total_supply(self: @ComponentState, timepoint: u64) -> u256 { let current_timepoint = starknet::get_block_timestamp(); assert(timepoint < current_timepoint, Errors::FUTURE_LOOKUP); @@ -127,7 +130,8 @@ pub mod ERC20VotesComponent { self._delegate(sender, delegatee); } - /// Delegates votes from the sender to `delegatee` through a SNIP12 message signature validation. + /// Delegates votes from the sender to `delegatee` through a SNIP12 message signature + /// validation. /// /// Requirements: /// diff --git a/src/token/erc20/interface.cairo b/src/token/erc20/interface.cairo index 44c61694f..74ed4c817 100644 --- a/src/token/erc20/interface.cairo +++ b/src/token/erc20/interface.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc20/interface.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc20/interface.cairo) use openzeppelin::utils::structs::checkpoint::Checkpoint; use starknet::ContractAddress; diff --git a/src/token/erc721/dual721.cairo b/src/token/erc721/dual721.cairo index 4c710f588..7b57c787c 100644 --- a/src/token/erc721/dual721.cairo +++ b/src/token/erc721/dual721.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc721/dual721.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc721/dual721.cairo) use openzeppelin::utils::UnwrapAndCast; use openzeppelin::utils::selectors; diff --git a/src/token/erc721/dual721_receiver.cairo b/src/token/erc721/dual721_receiver.cairo index a41f9699b..bc6e74242 100644 --- a/src/token/erc721/dual721_receiver.cairo +++ b/src/token/erc721/dual721_receiver.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc721/dual721_receiver.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc721/dual721_receiver.cairo) use openzeppelin::utils::UnwrapAndCast; use openzeppelin::utils::selectors; diff --git a/src/token/erc721/erc721.cairo b/src/token/erc721/erc721.cairo index 6f838205a..476ac76ee 100644 --- a/src/token/erc721/erc721.cairo +++ b/src/token/erc721/erc721.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc721/erc721.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc721/erc721.cairo) use starknet::ContractAddress; @@ -21,15 +21,16 @@ pub mod ERC721Component { use openzeppelin::token::erc721::interface; use starknet::ContractAddress; use starknet::get_caller_address; + use starknet::storage::Map; #[storage] struct Storage { ERC721_name: ByteArray, ERC721_symbol: ByteArray, - ERC721_owners: LegacyMap, - ERC721_balances: LegacyMap, - ERC721_token_approvals: LegacyMap, - ERC721_operator_approvals: LegacyMap<(ContractAddress, ContractAddress), bool>, + ERC721_owners: Map, + ERC721_balances: Map, + ERC721_token_approvals: Map, + ERC721_operator_approvals: Map<(ContractAddress, ContractAddress), bool>, ERC721_base_uri: ByteArray } @@ -133,11 +134,13 @@ pub mod ERC721Component { self._require_owned(token_id) } - /// Transfers ownership of `token_id` from `from` if `to` is either an account or `IERC721Receiver`. + /// Transfers ownership of `token_id` from `from` if `to` is either an account or + /// `IERC721Receiver`. /// /// `data` is additional data, it has no specified format and it is sent in call to `to`. /// - /// WARNING: This method makes an external call to the recipient contract, which can lead to reentrancy vulnerabilities. + /// WARNING: This method makes an external call to the recipient contract, which can lead to + /// reentrancy vulnerabilities. /// /// Requirements: /// @@ -155,7 +158,7 @@ pub mod ERC721Component { token_id: u256, data: Span ) { - ERC721::transfer_from(ref self, from, to, token_id); + Self::transfer_from(ref self, from, to, token_id); assert( _check_on_erc721_received(from, to, token_id, data), Errors::SAFE_TRANSFER_FAILED ); @@ -163,7 +166,8 @@ pub mod ERC721Component { /// Transfers ownership of `token_id` from `from` to `to`. /// - /// WARNING: This method may lead to the loss of tokens if `to` is not aware of the ERC721 protocol. + /// WARNING: This method may lead to the loss of tokens if `to` is not aware of the ERC721 + /// protocol. /// /// Requirements: /// @@ -181,8 +185,9 @@ pub mod ERC721Component { ) { assert(!to.is_zero(), Errors::INVALID_RECEIVER); - // Setting an "auth" arguments enables the `_is_authorized` check which verifies that the token exists - // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here. + // Setting an "auth" arguments enables the `_is_authorized` check which verifies that + // the token exists (from != 0). Therefore, it is not needed to verify that the return + // value is not 0 here. let previous_owner = self.update(to, token_id, get_caller_address()); assert(from == previous_owner, Errors::INVALID_SENDER); @@ -499,7 +504,8 @@ pub mod ERC721Component { /// /// Internal function without access restriction. /// - /// WARNING: This method may lead to the loss of tokens if `to` is not aware of the ERC721 protocol. + /// WARNING: This method may lead to the loss of tokens if `to` is not aware of the ERC721 + /// protocol. /// /// Requirements: /// @@ -525,7 +531,8 @@ pub mod ERC721Component { /// Mints `token_id` and transfers it to `to`. /// Internal function without access restriction. /// - /// WARNING: This method may lead to the loss of tokens if `to` is not aware of the ERC721 protocol. + /// WARNING: This method may lead to the loss of tokens if `to` is not aware of the ERC721 + /// protocol. /// /// Requirements: /// @@ -541,11 +548,13 @@ pub mod ERC721Component { assert(previous_owner.is_zero(), Errors::ALREADY_MINTED); } - /// Transfers ownership of `token_id` from `from` if `to` is either an account or `IERC721Receiver`. + /// Transfers ownership of `token_id` from `from` if `to` is either an account or + /// `IERC721Receiver`. /// /// `data` is additional data, it has no specified format and it is sent in call to `to`. /// - /// WARNING: This method makes an external call to the recipient contract, which can lead to reentrancy vulnerabilities. + /// WARNING: This method makes an external call to the recipient contract, which can lead to + /// reentrancy vulnerabilities. /// /// Requirements: /// @@ -572,7 +581,8 @@ pub mod ERC721Component { /// /// `data` is additional data, it has no specified format and it is sent in call to `to`. /// - /// WARNING: This method makes an external call to the recipient contract, which can lead to reentrancy vulnerabilities. + /// WARNING: This method makes an external call to the recipient contract, which can lead to + /// reentrancy vulnerabilities. /// /// Requirements: /// @@ -608,11 +618,13 @@ pub mod ERC721Component { assert(!previous_owner.is_zero(), Errors::INVALID_TOKEN_ID); } - /// Transfers `token_id` from its current owner to `to`, or alternatively mints (or burns) if the current owner - /// (or `to`) is the zero address. Returns the owner of the `token_id` before the update. + /// Transfers `token_id` from its current owner to `to`, or alternatively mints (or burns) + /// if the current owner (or `to`) is the zero address. Returns the owner of the `token_id` + /// before the update. /// - /// The `auth` argument is optional. If the value passed is non-zero, then this function will check that - /// `auth` is either the owner of the token, or approved to operate on the token (by the owner). + /// The `auth` argument is optional. If the value passed is non-zero, then this function + /// will check that `auth` is either the owner of the token, or approved to operate on the + /// token (by the owner). /// /// Emits a `Transfer` event. /// @@ -671,8 +683,9 @@ pub mod ERC721Component { /// Approve `to` to operate on `token_id` /// - /// The `auth` argument is optional. If the value passed is non-zero, then this function will check that `auth` is - /// either the owner of the token, or approved to operate on all tokens held by this owner. + /// The `auth` argument is optional. If the value passed is non-zero, then this function + /// will check that `auth` is either the owner of the token, or approved to operate on all + /// tokens held by this owner. /// /// Emits an `Approval` event. fn _approve( @@ -684,10 +697,11 @@ pub mod ERC721Component { self._approve_with_optional_event(to, token_id, auth, true); } - /// Variant of `_approve` with an optional flag to enable or disable the `Approval` event. The event is not - /// emitted in the context of transfers. + /// Variant of `_approve` with an optional flag to enable or disable the `Approval` event. + /// The event is not emitted in the context of transfers. /// - /// WARNING: If `auth` is zero and `emit_event` is false, this function will not check that the token exists. + /// WARNING: If `auth` is zero and `emit_event` is false, this function will not check that + /// the token exists. /// /// Requirements: /// @@ -744,7 +758,8 @@ pub mod ERC721Component { /// Base URI for computing `token_uri`. /// - /// If set, the resulting URI for each token will be the concatenation of the base URI and the token ID. + /// If set, the resulting URI for each token will be the concatenation of the base URI and + /// the token ID. /// Returns an empty `ByteArray` if not set. fn _base_uri(self: @ComponentState) -> ByteArray { self.ERC721_base_uri.read() @@ -753,8 +768,8 @@ pub mod ERC721Component { /// Returns whether `spender` is allowed to manage `owner`'s tokens, or `token_id` in /// particular (ignoring whether it is owned by `owner`). /// - /// WARNING: This function assumes that `owner` is the actual owner of `token_id` and does not verify this - /// assumption. + /// WARNING: This function assumes that `owner` is the actual owner of `token_id` and does + /// not verify this assumption. fn _is_authorized( self: @ComponentState, owner: ContractAddress, @@ -769,7 +784,8 @@ pub mod ERC721Component { || spender == ERC721::get_approved(self, token_id)) } - /// Checks if `spender` can operate on `token_id`, assuming the provided `owner` is the actual owner. + /// Checks if `spender` can operate on `token_id`, assuming the provided `owner` is the + /// actual owner. /// /// Requirements: /// @@ -777,8 +793,8 @@ pub mod ERC721Component { /// - `spender` cannot be the zero address. /// - `spender` must be the owner of `token_id` or be approved to operate on it. /// - /// WARNING: This function assumes that `owner` is the actual owner of `token_id` and does not verify this - /// assumption. + /// WARNING: This function assumes that `owner` is the actual owner of `token_id` and does + /// not verify this assumption. fn _check_authorized( self: @ComponentState, owner: ContractAddress, diff --git a/src/token/erc721/erc721_receiver.cairo b/src/token/erc721/erc721_receiver.cairo index bbc8db4ff..693f4d6fa 100644 --- a/src/token/erc721/erc721_receiver.cairo +++ b/src/token/erc721/erc721_receiver.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc721/erc721_receiver.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc721/erc721_receiver.cairo) /// # ERC721Receiver Component /// diff --git a/src/token/erc721/interface.cairo b/src/token/erc721/interface.cairo index c821677d5..26f4cecac 100644 --- a/src/token/erc721/interface.cairo +++ b/src/token/erc721/interface.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (token/erc721/interface.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (token/erc721/interface.cairo) use starknet::ContractAddress; diff --git a/src/upgrades/interface.cairo b/src/upgrades/interface.cairo index 43233f751..cc011515e 100644 --- a/src/upgrades/interface.cairo +++ b/src/upgrades/interface.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (upgrades/interface.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (upgrades/interface.cairo) use starknet::ClassHash; diff --git a/src/upgrades/upgradeable.cairo b/src/upgrades/upgradeable.cairo index 443182d29..c78d25476 100644 --- a/src/upgrades/upgradeable.cairo +++ b/src/upgrades/upgradeable.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (upgrades/upgradeable.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (upgrades/upgradeable.cairo) /// # Upgradeable Component /// @@ -25,7 +25,7 @@ pub mod UpgradeableComponent { pub class_hash: ClassHash } - mod Errors { + pub mod Errors { pub const INVALID_CLASS: felt252 = 'Class hash cannot be zero'; } diff --git a/src/utils.cairo b/src/utils.cairo index 666ec68dc..530d909b3 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils.cairo) pub mod cryptography; pub mod deployments; diff --git a/src/utils/cryptography/interface.cairo b/src/utils/cryptography/interface.cairo index 54d22f4cb..a80966140 100644 --- a/src/utils/cryptography/interface.cairo +++ b/src/utils/cryptography/interface.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils/cryptography/interface.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/cryptography/interface.cairo) use starknet::ContractAddress; diff --git a/src/utils/cryptography/nonces.cairo b/src/utils/cryptography/nonces.cairo index 6358cefe6..40089d76a 100644 --- a/src/utils/cryptography/nonces.cairo +++ b/src/utils/cryptography/nonces.cairo @@ -1,17 +1,18 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils/cryptography/nonces.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/cryptography/nonces.cairo) #[starknet::component] pub mod NoncesComponent { use openzeppelin::utils::interfaces::INonces; use starknet::ContractAddress; + use starknet::storage::Map; #[storage] struct Storage { - Nonces_nonces: LegacyMap + Nonces_nonces: Map } - mod Errors { + pub mod Errors { pub const INVALID_NONCE: felt252 = 'Nonces: invalid nonce'; } @@ -31,8 +32,9 @@ pub mod NoncesComponent { > of InternalTrait { /// Consumes a nonce, returns the current value, and increments nonce. fn use_nonce(ref self: ComponentState, owner: ContractAddress) -> felt252 { - // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be - // decremented or reset. This guarantees that the nonce never overflows. + // For each account, the nonce has an initial value of 0, can only be incremented by + // one, and cannot be decremented or reset. This guarantees that the nonce never + // overflows. let nonce = self.Nonces_nonces.read(owner); self.Nonces_nonces.write(owner, nonce + 1); nonce diff --git a/src/utils/cryptography/snip12.cairo b/src/utils/cryptography/snip12.cairo index 9aa7dc7fe..0f09a51e2 100644 --- a/src/utils/cryptography/snip12.cairo +++ b/src/utils/cryptography/snip12.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils/cryptography/snip12.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/cryptography/snip12.cairo) use core::hash::{Hash, HashStateTrait, HashStateExTrait}; use core::poseidon::PoseidonTrait; diff --git a/src/utils/deployments.cairo b/src/utils/deployments.cairo index 16a1f0519..0ca55135c 100644 --- a/src/utils/deployments.cairo +++ b/src/utils/deployments.cairo @@ -15,8 +15,11 @@ const L2_ADDRESS_UPPER_BOUND: felt252 = const CONTRACT_ADDRESS_PREFIX: felt252 = 'STARKNET_CONTRACT_ADDRESS'; /// Returns the contract address from a `deploy_syscall`. -/// `deployer_address` should be the zero address if the deployment is origin-independent (deployed from zero). -/// For more information, see https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/contract-address/ +/// `deployer_address` should be the zero address if the deployment is origin-independent (deployed +/// from zero). +/// For more information, see +/// +/// https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/contract-address/ pub fn calculate_contract_address_from_deploy_syscall( salt: felt252, class_hash: ClassHash, @@ -65,7 +68,8 @@ pub struct DeployerInfo { } /// Returns the calculated contract address for contracts deployed through the UDC. -/// Origin-independent deployments (deployed from zero) should pass `Option::None` as `deployer_info`. +/// Origin-independent deployments (deployed from zero) should pass `Option::None` as +/// `deployer_info`. pub fn calculate_contract_address_from_udc( salt: felt252, class_hash: ClassHash, diff --git a/src/utils/deployments/interface.cairo b/src/utils/deployments/interface.cairo index c80f10e4f..10231a5a9 100644 --- a/src/utils/deployments/interface.cairo +++ b/src/utils/deployments/interface.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils/universal_deployer/interface.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/universal_deployer/interface.cairo) use starknet::ClassHash; use starknet::ContractAddress; diff --git a/src/utils/math.cairo b/src/utils/math.cairo index cc9960aef..7d80a075c 100644 --- a/src/utils/math.cairo +++ b/src/utils/math.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils/math.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/math.cairo) use core::traits::Into; diff --git a/src/utils/selectors.cairo b/src/utils/selectors.cairo index 61e9758e0..2fafd30e8 100644 --- a/src/utils/selectors.cairo +++ b/src/utils/selectors.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils/selectors.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/selectors.cairo) // // AccessControl diff --git a/src/utils/serde.cairo b/src/utils/serde.cairo index e08fe03d8..dfe6efcf3 100644 --- a/src/utils/serde.cairo +++ b/src/utils/serde.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils/serde.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/serde.cairo) pub trait SerializedAppend { fn append_serde(ref self: Array, value: T); diff --git a/src/utils/structs/checkpoint.cairo b/src/utils/structs/checkpoint.cairo index 0a55edf9a..ec2ec0ab4 100644 --- a/src/utils/structs/checkpoint.cairo +++ b/src/utils/structs/checkpoint.cairo @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils/structs/checkpoint.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/structs/checkpoint.cairo) -use core::integer::u32_sqrt; +use core::num::traits::Sqrt; use openzeppelin::utils::math; use starknet::storage_access::StorePacking; use super::storage_array::{StorageArray, StorageArrayTrait}; @@ -55,7 +55,7 @@ pub impl TraceImpl of TraceTrait { let mut high = len; if (len > 5) { - let mid = len - u32_sqrt(len).into(); + let mid = len - len.sqrt().into(); if (key < checkpoints.read_at(mid).key) { high = mid; } else { @@ -112,8 +112,8 @@ pub impl TraceImpl of TraceTrait { #[generate_trait] impl CheckpointImpl of CheckpointTrait { - /// Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, - /// or by updating the last one. + /// Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a + /// new checkpoint, or by updating the last one. fn _insert(ref self: StorageArray, key: u64, value: u256) -> (u256, u256) { let pos = self.len(); @@ -138,9 +138,9 @@ impl CheckpointImpl of CheckpointTrait { } } - /// Returns the index of the last (most recent) checkpoint with the key lower than or equal to the search key, - /// or `high` if there is none. `low` and `high` define a section where to do the search, with - /// inclusive `low` and exclusive `high`. + /// Returns the index of the last (most recent) checkpoint with the key lower than or equal to + /// the search key, or `high` if there is none. `low` and `high` define a section where to do + /// the search, with inclusive `low` and exclusive `high`. fn _upper_binary_lookup(self: @StorageArray, key: u64, low: u32, high: u32) -> u32 { let mut _low = low; let mut _high = high; diff --git a/src/utils/structs/storage_array.cairo b/src/utils/structs/storage_array.cairo index 7b890cf37..5a35dfd5e 100644 --- a/src/utils/structs/storage_array.cairo +++ b/src/utils/structs/storage_array.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils/structs/storage_array.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/structs/storage_array.cairo) use core::hash::{HashStateExTrait, HashStateTrait}; use core::poseidon::PoseidonTrait; diff --git a/src/utils/unwrap_and_cast.cairo b/src/utils/unwrap_and_cast.cairo index 775385cb1..0ab73c8f1 100644 --- a/src/utils/unwrap_and_cast.cairo +++ b/src/utils/unwrap_and_cast.cairo @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.14.0 (utils/unwrap_and_cast.cairo) +// OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (utils/unwrap_and_cast.cairo) use starknet::SyscallResult; use starknet::SyscallResultTrait; From e09af84c35a08295a6579d116288279a3000b68c Mon Sep 17 00:00:00 2001 From: Andrew Fleming Date: Wed, 31 Jul 2024 22:56:55 -0400 Subject: [PATCH 35/45] Migrate timelock tests (#1061) * Remove unnecessary `mut`, minor fixes (#1032) * clean up code * change array syntax * fix fmt * Improve SNIP12 examples (#1036) * docs: improve examples * refactor: remove empty line * Update docs/modules/ROOT/pages/guides/snip12.adoc Co-authored-by: Andrew Fleming --------- Co-authored-by: Andrew Fleming * Release v0.15.0-rc.0 (#1039) * feat: update CHANGELOG * Bump version to 0.15.0-rc.0 * docs: add missing header * feat: apply review suggestions --------- Co-authored-by: ericnordelo * Bump cairo to 2.7.0-rc.1 (#1025) * feat: migrate modules * feat: delete cairo_project.toml * feat: update tests * feat: apply review updates * fix: remove extra line * feat: add CHANGELOG entry * fix: CHANGELOG * Bump Scarb to 2.7.0-rc.2 (#1052) * bump scarb to 2.7.0-rc.2 * add changelog entry * update changelog entry * bump scarb in installation page * Add timelock component (#996) * start timelock comp draft * move timelock to own dir, finish drafting component * tmp: add utility impls * add timelock mock * add test mod for timelock * fix commnet * add constructor to timelock mock * set min_delay in initializer * start tests * fix fmt * fix schedule assertion * add schedule tests * fix fmt * remove unused import * fix errs, _before_call * start execute tests * fix fmt * fix after_call * add execute tests * add abi interface * add reentrancy mock for timelock * add tests for cancel and update_delay * fix hash_op test * add execute with predecessor test * add timelock utils, add operation_state debug impl * fix fmt * improve imports * improve _execute * add basic mock for tests * add tmp call struct * add batch fns to interface * add batch fns * refactor tests to use dedicated mock, add batch tests * fix fmt * remove use clause * add timelock mixin * fix interface name * improve event assertions * fix execute and schedule events * fix fmt * add safe token transfer tests * fix fmt * tidy up code * add descriptions to events * clean up code * inline CallPartialEq fns * start fn descriptions * remove comments * remove comment * fix fmt * add changelog entries * improve spacing * add line break to hash test * clean up tests * clean up tests * fix constants in attacker impl * add initializer helper, register access control support * add _before_call and _after_call tests * fix reentrant batch mock call * add _schedule and _execute tests * add timelock description * fix formatting * fix comments * fix comment * fmt * tidy up tests * remove batch helper fn * remove event from mocks * Apply suggestions from code review Co-authored-by: Eric Nordelo * update spdx * remove token receiver support * add additional cancel tests * Apply suggestions from code review Co-authored-by: Eric Nordelo * initializer: remove mut, use while loop * fix fmt * add assert_only_self fn * fix getter comments re: pending/waiting * add assert_only_role * add specific op errors * make event names consistent * fix test * remove serialization from HashCallImpl * remove unused components from mock * clean up code * update to 2.7.0-rc.1 * fix fmt * import Call from corelib * update spdx * fix fmt * move OperationState, derive debug * fix fmt * fix hash impls * add for loops * fix PartialEq, add tests * fix fmt * simplify mixin fns * switch Poseidon to Pedersen * make admin a req in initializer * update tests with admin * fix fmt * fix comment * undo changes * add no admin initializer test --------- Co-authored-by: Eric Nordelo * fix fmt * bump scarb to 2.7.0-rc.4 (#1064) * bump scarb to 2.7.0-rc.4 * add changelog * bump scarb in installation page * fix fmt * feat: update workflow and fix warning (#1066) * bump scarb * add tmp usc install in ci * fix changelog --------- Co-authored-by: Eric Nordelo Co-authored-by: ericnordelo Co-authored-by: JChoy --- src/tests/governance.cairo | 2 +- src/tests/governance/test_timelock.cairo | 695 ++++++++++++----------- 2 files changed, 365 insertions(+), 332 deletions(-) diff --git a/src/tests/governance.cairo b/src/tests/governance.cairo index 1d40503c0..3aa8297b3 100644 --- a/src/tests/governance.cairo +++ b/src/tests/governance.cairo @@ -1,2 +1,2 @@ -//mod test_timelock; +mod test_timelock; mod test_utils; diff --git a/src/tests/governance/test_timelock.cairo b/src/tests/governance/test_timelock.cairo index c654c2082..d3838ae21 100644 --- a/src/tests/governance/test_timelock.cairo +++ b/src/tests/governance/test_timelock.cairo @@ -29,14 +29,18 @@ use openzeppelin::tests::mocks::timelock_mocks::{ ITimelockAttackerDispatcher, ITimelockAttackerDispatcherTrait }; use openzeppelin::tests::mocks::timelock_mocks::{TimelockControllerMock, TimelockAttackerMock}; -use openzeppelin::tests::utils::constants::{ADMIN, ZERO, OTHER, SALT}; +use openzeppelin::tests::utils::constants::{ADMIN, ZERO, OTHER, SALT, FELT_VALUE as VALUE}; +use openzeppelin::tests::utils::events::EventSpyExt; use openzeppelin::tests::utils; -use openzeppelin::utils::selectors; use openzeppelin::utils::serde::SerializedAppend; +use snforge_std::EventSpy; +use snforge_std::{ + spy_events, test_address, start_cheat_caller_address, cheat_caller_address, + cheat_block_timestamp_global, CheatSpan +}; use starknet::ContractAddress; use starknet::account::Call; use starknet::contract_address_const; -use starknet::testing; type ComponentState = TimelockControllerComponent::ComponentState; @@ -55,7 +59,6 @@ fn COMPONENT_STATE() -> ComponentState { const MIN_DELAY: u64 = 1000; const NEW_DELAY: u64 = 2000; -const VALUE: felt252 = 'VALUE'; const NO_PREDECESSOR: felt252 = 0; // @@ -133,18 +136,14 @@ fn deploy_timelock() -> TimelockABIDispatcher { calldata.append_serde(executors); calldata.append_serde(admin); - let address = utils::deploy(TimelockControllerMock::TEST_CLASS_HASH, calldata); - // Events dropped: - // - 5 RoleGranted: self, proposer, canceller, executor, admin - // - MinDelayChanged - utils::drop_events(address, 6); + let address = utils::declare_and_deploy("TimelockControllerMock", calldata); TimelockABIDispatcher { contract_address: address } } fn deploy_mock_target() -> IMockContractDispatcher { let mut calldata = array![]; - let address = utils::deploy(MockContract::TEST_CLASS_HASH, calldata); + let address = utils::declare_and_deploy("MockContract", calldata); IMockContractDispatcher { contract_address: address } } @@ -158,7 +157,7 @@ fn setup_dispatchers() -> (TimelockABIDispatcher, IMockContractDispatcher) { fn deploy_attacker() -> ITimelockAttackerDispatcher { let mut calldata = array![]; - let address = utils::deploy(TimelockAttackerMock::TEST_CLASS_HASH, calldata); + let address = utils::declare_and_deploy("TimelockAttackerMock", calldata); ITimelockAttackerDispatcher { contract_address: address } } @@ -250,8 +249,10 @@ fn schedule_from_proposer(salt: felt252) { assert_operation_state(timelock, OperationState::Unset, target_id); // Schedule - testing::set_contract_address(PROPOSER()); + let mut spy = spy_events(); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule(call, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); // Check timestamp @@ -262,14 +263,16 @@ fn schedule_from_proposer(salt: felt252) { // Check event(s) let event_index = 0; if salt != 0 { - assert_event_schedule( - timelock.contract_address, target_id, event_index, call, predecessor, delay - ); - assert_only_event_call_salt(timelock.contract_address, target_id, salt); + spy + .assert_event_call_scheduled( + timelock.contract_address, target_id, event_index, call, predecessor, delay + ); + spy.assert_only_event_call_salt(timelock.contract_address, target_id, salt); } else { - assert_only_event_schedule( - timelock.contract_address, target_id, event_index, call, predecessor, delay - ); + spy + .assert_only_event_call_scheduled( + timelock.contract_address, target_id, event_index, call, predecessor, delay + ); } } @@ -286,7 +289,7 @@ fn test_schedule_from_proposer_no_salt() { } #[test] -#[should_panic(expected: ('Timelock: expected Unset op', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: expected Unset op',))] fn test_schedule_overwrite() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -295,13 +298,14 @@ fn test_schedule_overwrite() { let call = single_operation(target.contract_address); - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); + timelock.schedule(call, predecessor, salt, delay); timelock.schedule(call, predecessor, salt, delay); } #[test] -#[should_panic(expected: ('Caller is missing role', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is missing role',))] fn test_schedule_unauthorized() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -310,21 +314,21 @@ fn test_schedule_unauthorized() { let call = single_operation(target.contract_address); - testing::set_contract_address(OTHER()); + start_cheat_caller_address(timelock.contract_address, OTHER()); timelock.schedule(call, predecessor, salt, delay); } #[test] -#[should_panic(expected: ('Timelock: insufficient delay', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: insufficient delay',))] fn test_schedule_bad_min_delay() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; let salt = SALT; let bad_delay = MIN_DELAY - 1; - let call = single_operation(target.contract_address); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); - testing::set_contract_address(PROPOSER()); + let call = single_operation(target.contract_address); timelock.schedule(call, predecessor, salt, bad_delay); } @@ -344,8 +348,10 @@ fn schedule_batch_from_proposer(salt: felt252) { assert_operation_state(timelock, OperationState::Unset, target_id); // Schedule batch - testing::set_contract_address(PROPOSER()); + let mut spy = spy_events(); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule_batch(calls, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); // Check timestamp @@ -355,14 +361,16 @@ fn schedule_batch_from_proposer(salt: felt252) { // Check events if salt != 0 { - assert_events_schedule_batch( - timelock.contract_address, target_id, calls, predecessor, delay - ); - assert_only_event_call_salt(timelock.contract_address, target_id, salt); + spy + .assert_events_call_scheduled_batch( + timelock.contract_address, target_id, calls, predecessor, delay + ); + spy.assert_only_event_call_salt(timelock.contract_address, target_id, salt); } else { - assert_only_events_schedule_batch( - timelock.contract_address, target_id, calls, predecessor, delay - ); + spy + .assert_only_events_call_scheduled_batch( + timelock.contract_address, target_id, calls, predecessor, delay + ); } } @@ -379,7 +387,7 @@ fn test_schedule_batch_from_proposer_no_salt() { } #[test] -#[should_panic(expected: ('Timelock: expected Unset op', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: expected Unset op',))] fn test_schedule_batch_overwrite() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -388,36 +396,37 @@ fn test_schedule_batch_overwrite() { let calls = batched_operations(target.contract_address); - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); + timelock.schedule_batch(calls, predecessor, salt, delay); timelock.schedule_batch(calls, predecessor, salt, delay); } #[test] -#[should_panic(expected: ('Caller is missing role', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is missing role',))] fn test_schedule_batch_unauthorized() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; let salt = SALT; let delay = MIN_DELAY; - let calls = batched_operations(target.contract_address); + start_cheat_caller_address(timelock.contract_address, OTHER()); - testing::set_contract_address(OTHER()); + let calls = batched_operations(target.contract_address); timelock.schedule_batch(calls, predecessor, salt, delay); } #[test] -#[should_panic(expected: ('Timelock: insufficient delay', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: insufficient delay',))] fn test_schedule_batch_bad_min_delay() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; let salt = SALT; let bad_delay = MIN_DELAY - 1; - let calls = batched_operations(target.contract_address); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); - testing::set_contract_address(PROPOSER()); + let calls = batched_operations(target.contract_address); timelock.schedule_batch(calls, predecessor, salt, bad_delay); } @@ -426,15 +435,15 @@ fn test_schedule_batch_bad_min_delay() { // #[test] -#[should_panic(expected: ('Timelock: expected Ready op', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: expected Ready op',))] fn test_execute_when_not_scheduled() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; let salt = 0; - let call = single_operation(target.contract_address); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); - testing::set_contract_address(EXECUTOR()); + let call = single_operation(target.contract_address); timelock.execute(call, predecessor, salt); } @@ -444,7 +453,6 @@ fn test_execute_when_scheduled() { let predecessor = NO_PREDECESSOR; let salt = 0; let delay = MIN_DELAY; - let event_index = 0; // Set up call let call = single_operation(target.contract_address); @@ -452,15 +460,19 @@ fn test_execute_when_scheduled() { assert_operation_state(timelock, OperationState::Unset, target_id); // Schedule - testing::set_contract_address(PROPOSER()); + let mut spy = spy_events(); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule(call, predecessor, salt, delay); - assert_only_event_schedule( - timelock.contract_address, target_id, event_index, call, predecessor, delay - ); + + let event_index = 0; + spy + .assert_only_event_call_scheduled( + timelock.contract_address, target_id, event_index, call, predecessor, delay + ); assert_operation_state(timelock, OperationState::Waiting, target_id); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); assert_operation_state(timelock, OperationState::Ready, target_id); // Check initial target state @@ -468,11 +480,11 @@ fn test_execute_when_scheduled() { assert_eq!(check_target, 0); // Execute - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute(call, predecessor, salt); assert_operation_state(timelock, OperationState::Done, target_id); - assert_only_event_execute(timelock.contract_address, target_id, event_index, call); + spy.assert_only_event_call_executed(timelock.contract_address, target_id, event_index, call); // Check target state updates let check_target = target.get_number(); @@ -480,52 +492,52 @@ fn test_execute_when_scheduled() { } #[test] -#[should_panic(expected: ('Timelock: expected Ready op', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: expected Ready op',))] fn test_execute_early() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; let salt = 0; let delay = MIN_DELAY; - let call = single_operation(target.contract_address); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); // Schedule - testing::set_contract_address(PROPOSER()); + let call = single_operation(target.contract_address); timelock.schedule(call, predecessor, salt, delay); // Fast-forward let early_time = delay - 1; - testing::set_block_timestamp(early_time); + cheat_block_timestamp_global(early_time); // Execute - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute(call, predecessor, salt); } #[test] -#[should_panic(expected: ('Caller is missing role', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is missing role',))] fn test_execute_unauthorized() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; let salt = 0; let delay = MIN_DELAY; - let call = single_operation(target.contract_address); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); // Schedule - testing::set_contract_address(PROPOSER()); + let call = single_operation(target.contract_address); timelock.schedule(call, predecessor, salt, delay); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); // Execute - testing::set_contract_address(OTHER()); + start_cheat_caller_address(timelock.contract_address, OTHER()); timelock.execute(call, predecessor, salt); } #[test] -#[should_panic(expected: ('Expected failure', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Expected failure',))] fn test_execute_failing_tx() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -537,20 +549,21 @@ fn test_execute_failing_tx() { let target_id = timelock.hash_operation(call, predecessor, salt); // Schedule - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule(call, predecessor, salt, delay); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); assert_operation_state(timelock, OperationState::Ready, target_id); // Execute - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute(call, predecessor, salt); } #[test] -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND', 'ENTRYPOINT_FAILED'))] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. +#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test_execute_bad_selector() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -562,24 +575,20 @@ fn test_execute_bad_selector() { let target_id = timelock.hash_operation(call, predecessor, salt); // Schedule - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule(call, predecessor, salt, delay); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); assert_operation_state(timelock, OperationState::Ready, target_id); // Execute - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute(call, predecessor, salt); } #[test] -#[should_panic( - expected: ( - 'Timelock: expected Ready op', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED' - ) -)] +#[should_panic(expected: ('Timelock: expected Ready op',))] fn test_execute_reentrant_call() { let mut timelock = deploy_timelock(); let mut attacker = deploy_attacker(); @@ -592,23 +601,23 @@ fn test_execute_reentrant_call() { }; // Schedule - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule(reentrant_call, predecessor, salt, delay); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); // Grant executor role to attacker - testing::set_contract_address(ADMIN()); + start_cheat_caller_address(timelock.contract_address, ADMIN()); timelock.grant_role(EXECUTOR_ROLE, attacker.contract_address); // Attempt reentrant call - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute(reentrant_call, predecessor, salt); } #[test] -#[should_panic(expected: ('Timelock: awaiting predecessor', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: awaiting predecessor',))] fn test_execute_before_dependency() { let (mut timelock, mut target) = setup_dispatchers(); let salt = 0; @@ -625,19 +634,19 @@ fn test_execute_before_dependency() { let target_id_2 = timelock.hash_operation(call_2, predecessor_2, salt); // Schedule call 1 - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule(call_1, predecessor_1, salt, delay); // Schedule call 2 timelock.schedule(call_2, predecessor_2, salt, delay); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); assert_operation_state(timelock, OperationState::Ready, target_id_1); assert_operation_state(timelock, OperationState::Ready, target_id_2); // Execute - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute(call_2, predecessor_2, salt); } @@ -661,35 +670,42 @@ fn test_execute_after_dependency() { assert_operation_state(timelock, OperationState::Unset, target_id_2); // Schedule call 1 - testing::set_contract_address(PROPOSER()); + let mut spy = spy_events(); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule(call_1, predecessor_1, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id_1); - assert_only_event_schedule( - timelock.contract_address, target_id_1, event_index, call_1, predecessor_1, delay - ); + spy + .assert_only_event_call_scheduled( + timelock.contract_address, target_id_1, event_index, call_1, predecessor_1, delay + ); // Schedule call 2 timelock.schedule(call_2, predecessor_2, salt, delay); assert_operation_state(timelock, OperationState::Waiting, target_id_2); - assert_only_event_schedule( - timelock.contract_address, target_id_2, event_index, call_2, predecessor_2, delay - ); + spy + .assert_only_event_call_scheduled( + timelock.contract_address, target_id_2, event_index, call_2, predecessor_2, delay + ); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); assert_operation_state(timelock, OperationState::Ready, target_id_1); assert_operation_state(timelock, OperationState::Ready, target_id_2); // Execute call 1 - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute(call_1, predecessor_1, salt); assert_operation_state(timelock, OperationState::Done, target_id_1); - assert_event_execute(timelock.contract_address, target_id_1, event_index, call_1); + spy.assert_event_call_executed(timelock.contract_address, target_id_1, event_index, call_1); // Execute call 2 timelock.execute(call_2, predecessor_2, salt); assert_operation_state(timelock, OperationState::Done, target_id_2); - assert_only_event_execute(timelock.contract_address, target_id_2, event_index, call_2); + spy + .assert_only_event_call_executed( + timelock.contract_address, target_id_2, event_index, call_2 + ); } // @@ -697,7 +713,7 @@ fn test_execute_after_dependency() { // #[test] -#[should_panic(expected: ('Timelock: expected Ready op', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: expected Ready op',))] fn test_execute_batch_when_not_scheduled() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -705,7 +721,7 @@ fn test_execute_batch_when_not_scheduled() { let calls = batched_operations(target.contract_address); - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute_batch(calls, predecessor, salt); } @@ -722,15 +738,18 @@ fn test_execute_batch_when_scheduled() { assert_operation_state(timelock, OperationState::Unset, target_id); // Schedule - testing::set_contract_address(PROPOSER()); + let mut spy = spy_events(); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule_batch(calls, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); - assert_only_events_schedule_batch( - timelock.contract_address, target_id, calls, predecessor, delay - ); + spy + .assert_only_events_call_scheduled_batch( + timelock.contract_address, target_id, calls, predecessor, delay + ); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); assert_operation_state(timelock, OperationState::Ready, target_id); // Check initial target state @@ -738,10 +757,10 @@ fn test_execute_batch_when_scheduled() { assert_eq!(check_target, 0); // Execute - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute_batch(calls, predecessor, salt); assert_operation_state(timelock, OperationState::Done, target_id); - assert_only_events_execute_batch(timelock.contract_address, target_id, calls); + spy.assert_only_events_call_executed_batch(timelock.contract_address, target_id, calls); // Check target state updates let check_target = target.get_number(); @@ -749,7 +768,7 @@ fn test_execute_batch_when_scheduled() { } #[test] -#[should_panic(expected: ('Timelock: expected Ready op', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: expected Ready op',))] fn test_execute_batch_early() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -759,20 +778,20 @@ fn test_execute_batch_early() { let calls = batched_operations(target.contract_address); // Schedule - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule_batch(calls, predecessor, salt, delay); // Fast-forward let early_time = delay - 1; - testing::set_block_timestamp(early_time); + cheat_block_timestamp_global(early_time); // Execute - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute_batch(calls, predecessor, salt); } #[test] -#[should_panic(expected: ('Caller is missing role', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is missing role',))] fn test_execute_batch_unauthorized() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -782,23 +801,19 @@ fn test_execute_batch_unauthorized() { let calls = batched_operations(target.contract_address); // Schedule - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule_batch(calls, predecessor, salt, delay); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); // Execute - testing::set_contract_address(OTHER()); + start_cheat_caller_address(timelock.contract_address, OTHER()); timelock.execute_batch(calls, predecessor, salt); } #[test] -#[should_panic( - expected: ( - 'Timelock: expected Ready op', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED' - ) -)] +#[should_panic(expected: ('Timelock: expected Ready op',))] fn test_execute_batch_reentrant_call() { let mut timelock = deploy_timelock(); let mut attacker = deploy_attacker(); @@ -814,23 +829,23 @@ fn test_execute_batch_reentrant_call() { let calls = array![reentrant_call].span(); // Schedule - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule_batch(calls, predecessor, salt, delay); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); // Grant executor role to attacker - testing::set_contract_address(ADMIN()); + start_cheat_caller_address(timelock.contract_address, ADMIN()); timelock.grant_role(EXECUTOR_ROLE, attacker.contract_address); // Attempt reentrant call - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute_batch(calls, predecessor, salt); } #[test] -#[should_panic(expected: ('Expected failure', 'ENTRYPOINT_FAILED', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Expected failure',))] fn test_execute_batch_partial_execution() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -842,19 +857,19 @@ fn test_execute_batch_partial_execution() { let calls = array![good_call, bad_call].span(); // Schedule - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule_batch(calls, predecessor, salt, delay); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); // Execute - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute_batch(calls, predecessor, salt); } #[test] -#[should_panic(expected: ('Timelock: awaiting predecessor', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: awaiting predecessor',))] fn test_execute_batch_before_dependency() { let (mut timelock, mut target) = setup_dispatchers(); let salt = 0; @@ -870,17 +885,17 @@ fn test_execute_batch_before_dependency() { let predecessor_2 = target_id_1; // Schedule calls 1 - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule_batch(calls_1, predecessor_1, salt, delay); // Schedule calls 2 timelock.schedule_batch(calls_2, predecessor_2, salt, delay); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); // Execute - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute_batch(calls_2, predecessor_2, salt); } @@ -903,35 +918,42 @@ fn test_execute_batch_after_dependency() { assert_operation_state(timelock, OperationState::Unset, target_id_2); // Schedule calls 1 - testing::set_contract_address(PROPOSER()); + let mut spy = spy_events(); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule_batch(calls_1, predecessor_1, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id_1); - assert_only_events_schedule_batch( - timelock.contract_address, target_id_1, calls_1, predecessor_1, delay - ); + spy + .assert_only_events_call_scheduled_batch( + timelock.contract_address, target_id_1, calls_1, predecessor_1, delay + ); // Schedule calls 2 timelock.schedule_batch(calls_2, predecessor_2, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id_2); - assert_only_events_schedule_batch( - timelock.contract_address, target_id_2, calls_2, predecessor_2, delay - ); + spy + .assert_only_events_call_scheduled_batch( + timelock.contract_address, target_id_2, calls_2, predecessor_2, delay + ); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); assert_operation_state(timelock, OperationState::Ready, target_id_1); assert_operation_state(timelock, OperationState::Ready, target_id_2); // Execute calls 1 - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute_batch(calls_1, predecessor_1, salt); - assert_only_events_execute_batch(timelock.contract_address, target_id_1, calls_1); + + spy.assert_only_events_call_executed_batch(timelock.contract_address, target_id_1, calls_1); assert_operation_state(timelock, OperationState::Done, target_id_1); // Execute calls 2 timelock.execute_batch(calls_2, predecessor_2, salt); + assert_operation_state(timelock, OperationState::Done, target_id_2); - assert_only_events_execute_batch(timelock.contract_address, target_id_2, calls_2); + spy.assert_only_events_call_executed_batch(timelock.contract_address, target_id_2, calls_2); } // @@ -950,22 +972,26 @@ fn cancel_from_canceller(operation_state: OperationState) { assert_operation_state(timelock, OperationState::Unset, target_id); // Schedule - testing::set_contract_address(PROPOSER()); // PROPOSER is also CANCELLER + let mut spy = spy_events(); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); // PROPOSER is also CANCELLER timelock.schedule(call, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); - assert_only_event_schedule( - timelock.contract_address, target_id, event_index, call, predecessor, delay - ); + spy + .assert_only_event_call_scheduled( + timelock.contract_address, target_id, event_index, call, predecessor, delay + ); if operation_state == OperationState::Ready { // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); assert_operation_state(timelock, OperationState::Ready, target_id); } // Cancel timelock.cancel(target_id); - assert_only_event_cancel(timelock.contract_address, target_id); + + spy.assert_only_event_call_cancelled(timelock.contract_address, target_id); assert_operation_state(timelock, OperationState::Unset, target_id); } @@ -982,7 +1008,7 @@ fn test_cancel_when_ready() { } #[test] -#[should_panic(expected: ('Timelock: expected Pending op', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: expected Pending op',))] fn test_cancel_when_done() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -994,37 +1020,37 @@ fn test_cancel_when_done() { assert_operation_state(timelock, OperationState::Unset, target_id); // Schedule - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule(call, predecessor, salt, delay); assert_operation_state(timelock, OperationState::Waiting, target_id); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); assert_operation_state(timelock, OperationState::Ready, target_id); // Execute - testing::set_contract_address(EXECUTOR()); + start_cheat_caller_address(timelock.contract_address, EXECUTOR()); timelock.execute(call, predecessor, salt); assert_operation_state(timelock, OperationState::Done, target_id); // Attempt cancel - testing::set_contract_address(PROPOSER()); // PROPOSER is also CANCELLER + start_cheat_caller_address(timelock.contract_address, PROPOSER()); // PROPOSER is also CANCELLER timelock.cancel(target_id); } #[test] -#[should_panic(expected: ('Timelock: expected Pending op', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: expected Pending op',))] fn test_cancel_when_unset() { let (mut timelock, _) = setup_dispatchers(); let invalid_id = 0; // PROPOSER is also CANCELLER - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.cancel(invalid_id); } #[test] -#[should_panic(expected: ('Caller is missing role', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Caller is missing role',))] fn test_cancel_unauthorized() { let (mut timelock, mut target) = setup_dispatchers(); let predecessor = NO_PREDECESSOR; @@ -1035,11 +1061,11 @@ fn test_cancel_unauthorized() { let target_id = timelock.hash_operation(call, predecessor, salt); // Schedule - testing::set_contract_address(PROPOSER()); + start_cheat_caller_address(timelock.contract_address, PROPOSER()); timelock.schedule(call, predecessor, salt, delay); // Cancel - testing::set_contract_address(OTHER()); + start_cheat_caller_address(timelock.contract_address, OTHER()); timelock.cancel(target_id); } @@ -1048,7 +1074,7 @@ fn test_cancel_unauthorized() { // #[test] -#[should_panic(expected: ('Timelock: unauthorized caller', 'ENTRYPOINT_FAILED'))] +#[should_panic(expected: ('Timelock: unauthorized caller',))] fn test_update_delay_unauthorized() { let mut timelock = deploy_timelock(); @@ -1071,22 +1097,27 @@ fn test_update_delay_scheduled() { let target_id = timelock.hash_operation(call, predecessor, salt); // Schedule - testing::set_contract_address(PROPOSER()); + let mut spy = spy_events(); + cheat_caller_address(timelock.contract_address, PROPOSER(), CheatSpan::TargetCalls(1)); timelock.schedule(call, predecessor, salt, delay); + assert_operation_state(timelock, OperationState::Waiting, target_id); - assert_only_event_schedule( - timelock.contract_address, target_id, event_index, call, predecessor, delay - ); + spy + .assert_only_event_call_scheduled( + timelock.contract_address, target_id, event_index, call, predecessor, delay + ); // Fast-forward - testing::set_block_timestamp(delay); + cheat_block_timestamp_global(delay); // Execute - testing::set_contract_address(EXECUTOR()); + cheat_caller_address(timelock.contract_address, EXECUTOR(), CheatSpan::TargetCalls(1)); + timelock.execute(call, predecessor, salt); + assert_operation_state(timelock, OperationState::Done, target_id); - assert_event_delay(timelock.contract_address, MIN_DELAY, NEW_DELAY); - assert_only_event_execute(timelock.contract_address, target_id, event_index, call); + spy.assert_event_delay_changed(timelock.contract_address, MIN_DELAY, NEW_DELAY); + spy.assert_only_event_call_executed(timelock.contract_address, target_id, event_index, call); // Check new minimum delay let get_new_delay = timelock.get_min_delay(); @@ -1162,7 +1193,8 @@ fn test_initializer_no_admin() { // The initializer grants the timelock contract address the `DEFAULT_ADMIN_ROLE` // therefore, we need to set the address since it's not deployed in this context - testing::set_contract_address(contract_address_const::<'TIMELOCK_ADDRESS'>()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, contract_address_const::<'TIMELOCK_ADDRESS'>()); state.initializer(min_delay, proposers, executors, admin_zero); let admin_does_not_have_role = !contract_state.has_role(DEFAULT_ADMIN_ROLE, admin_zero); @@ -1198,6 +1230,7 @@ fn test_initializer_min_delay() { let executors = array![EXECUTOR()].span(); let admin_zero = ZERO(); + let mut spy = spy_events(); state.initializer(min_delay, proposers, executors, admin_zero); // Check minimum delay is set @@ -1205,12 +1238,12 @@ fn test_initializer_min_delay() { assert_eq!(delay, MIN_DELAY); // The initializer emits 4 `RoleGranted` events prior to `MinDelayChanged`: - // - Self administration + // - 1 Self administration // - 1 proposer // - 1 canceller // - 1 executor - utils::drop_events(ZERO(), 4); - assert_only_event_delay_change(ZERO(), 0, MIN_DELAY); + EventSpyExt::drop_n_events(ref spy, 4); + spy.assert_only_event_delay_changed(test_address(), 0, MIN_DELAY); } // @@ -1228,14 +1261,15 @@ fn test_assert_only_role_or_open_role_when_has_role() { state.initializer(min_delay, proposers, executors, admin); - testing::set_caller_address(PROPOSER()); - state.assert_only_role_or_open_role(PROPOSER_ROLE); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, PROPOSER()); + state.assert_only_role_or_open_role(PROPOSER_ROLE); // PROPOSER == CANCELLER - testing::set_caller_address(PROPOSER()); state.assert_only_role_or_open_role(CANCELLER_ROLE); - testing::set_caller_address(EXECUTOR()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, EXECUTOR()); state.assert_only_role_or_open_role(EXECUTOR_ROLE); } @@ -1251,7 +1285,9 @@ fn test_assert_only_role_or_open_role_unauthorized() { state.initializer(min_delay, proposers, executors, admin); - testing::set_caller_address(OTHER()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OTHER()); + state.assert_only_role_or_open_role(PROPOSER_ROLE); } @@ -1271,7 +1307,9 @@ fn test_assert_only_role_or_open_role_with_open_role() { let is_open_role = contract_state.has_role(EXECUTOR_ROLE, open_role); assert!(is_open_role); - testing::set_caller_address(OTHER()); + let contract_address = test_address(); + start_cheat_caller_address(contract_address, OTHER()); + state.assert_only_role_or_open_role(EXECUTOR_ROLE); } @@ -1292,7 +1330,7 @@ fn test__before_call() { state.TimelockController_timestamps.write(target_id, target_time); // Fast-forward - testing::set_block_timestamp(target_time); + cheat_block_timestamp_global(target_time); state._before_call(target_id, predecessor); } @@ -1327,7 +1365,7 @@ fn test__before_call_insufficient_time() { state.TimelockController_timestamps.write(target_id, target_time); // Fast-forward - testing::set_block_timestamp(target_time - 1); + cheat_block_timestamp_global(target_time - 1); state._before_call(target_id, predecessor); } @@ -1346,7 +1384,7 @@ fn test__before_call_when_already_done() { state.TimelockController_timestamps.write(target_id, done_time); // Fast-forward - testing::set_block_timestamp(done_time); + cheat_block_timestamp_global(done_time); state._before_call(target_id, predecessor); } @@ -1368,7 +1406,7 @@ fn test__before_call_with_predecessor_done() { state.TimelockController_timestamps.write(target_id, target_time); // Fast-forward - testing::set_block_timestamp(target_time); + cheat_block_timestamp_global(target_time); state._before_call(target_id, predecessor_id); } @@ -1391,7 +1429,7 @@ fn test__before_call_with_predecessor_not_done() { state.TimelockController_timestamps.write(target_id, target_time); // Fast-forward - testing::set_block_timestamp(target_time); + cheat_block_timestamp_global(target_time); state._before_call(target_id, predecessor_id); } @@ -1412,7 +1450,7 @@ fn test__after_call() { state.TimelockController_timestamps.write(target_id, target_time); // Fast-forward - testing::set_block_timestamp(target_time); + cheat_block_timestamp_global(target_time); state._after_call(target_id); @@ -1450,7 +1488,7 @@ fn test__after_call_insufficient_time() { state.TimelockController_timestamps.write(target_id, target_time); // Fast-forward - testing::set_block_timestamp(target_time - 1); + cheat_block_timestamp_global(target_time - 1); state._after_call(target_id); } @@ -1468,7 +1506,7 @@ fn test__after_call_already_done() { state.TimelockController_timestamps.write(target_id, done_time); // Fast-forward - testing::set_block_timestamp(done_time); + cheat_block_timestamp_global(done_time); state._after_call(target_id); } @@ -1560,7 +1598,7 @@ fn test__execute() { } #[test] -#[should_panic(expected: ('Expected failure', 'ENTRYPOINT_FAILED',))] +#[should_panic(expected: ('Expected failure',))] fn test__execute_with_failing_tx() { let mut state = COMPONENT_STATE(); let mut target = deploy_mock_target(); @@ -1573,6 +1611,7 @@ fn test__execute_with_failing_tx() { } #[test] +#[ignore] // REASON: should_panic attribute not fit for complex panic messages. #[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] fn test__execute_with_bad_selector() { let mut state = COMPONENT_STATE(); @@ -1630,170 +1669,164 @@ fn assert_operation_state(timelock: TimelockABIDispatcher, exp_state: OperationS // Event helpers // -// -// MinDelayChanged -// - -fn assert_event_delay_change(contract: ContractAddress, old_duration: u64, new_duration: u64) { - let event = utils::pop_log::(contract).unwrap(); - let expected = TimelockControllerComponent::Event::MinDelayChanged( - MinDelayChanged { old_duration, new_duration } - ); - assert!(event == expected); -} - -fn assert_only_event_delay_change(contract: ContractAddress, old_duration: u64, new_duration: u64) { - assert_event_delay_change(contract, old_duration, new_duration); - utils::assert_no_events_left(contract); -} - -// -// CallScheduled -// - -fn assert_event_schedule( - contract: ContractAddress, - id: felt252, - index: felt252, - call: Call, - predecessor: felt252, - delay: u64 -) { - let event = utils::pop_log::(contract).unwrap(); - let expected = TimelockControllerComponent::Event::CallScheduled( - CallScheduled { id, index, call, predecessor, delay } - ); - assert!(event == expected); - - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("CallScheduled")); - indexed_keys.append_serde(id); - indexed_keys.append_serde(index); - utils::assert_indexed_keys(event, indexed_keys.span()); -} - -fn assert_only_event_schedule( - contract: ContractAddress, - id: felt252, - index: felt252, - call: Call, - predecessor: felt252, - delay: u64 -) { - assert_event_schedule(contract, id, index, call, predecessor, delay); - utils::assert_no_events_left(contract); -} - -fn assert_events_schedule_batch( - contract: ContractAddress, id: felt252, calls: Span, predecessor: felt252, delay: u64 -) { - let mut i = 0; - loop { - if i == calls.len() { - break; - } - assert_event_schedule(contract, id, i.into(), *calls.at(i), predecessor, delay); - i += 1; +#[generate_trait] +pub(crate) impl TimelockSpyHelpersImpl of TimelockSpyHelpers { + // + // CallScheduled + // + + fn assert_event_call_scheduled( + ref self: EventSpy, + contract: ContractAddress, + id: felt252, + index: felt252, + call: Call, + predecessor: felt252, + delay: u64 + ) { + let expected = TimelockControllerComponent::Event::CallScheduled( + CallScheduled { id, index, call, predecessor, delay } + ); + self.assert_emitted_single(contract, expected); } -} -fn assert_only_events_schedule_batch( - contract: ContractAddress, id: felt252, calls: Span, predecessor: felt252, delay: u64 -) { - assert_events_schedule_batch(contract, id, calls, predecessor, delay); - utils::assert_no_events_left(contract); -} + fn assert_only_event_call_scheduled( + ref self: EventSpy, + contract: ContractAddress, + id: felt252, + index: felt252, + call: Call, + predecessor: felt252, + delay: u64 + ) { + self.assert_event_call_scheduled(contract, id, index, call, predecessor, delay); + self.assert_no_events_left_from(contract); + } -// -// CallSalt -// + fn assert_events_call_scheduled_batch( + ref self: EventSpy, + contract: ContractAddress, + id: felt252, + calls: Span, + predecessor: felt252, + delay: u64 + ) { + let mut i = 0; + loop { + if i == calls.len() { + break; + } + self + .assert_event_call_scheduled( + contract, id, i.into(), *calls.at(i), predecessor, delay + ); + i += 1; + }; + } -fn assert_event_call_salt(contract: ContractAddress, id: felt252, salt: felt252) { - let event = utils::pop_log::(contract).unwrap(); - let expected = TimelockControllerComponent::Event::CallSalt(CallSalt { id, salt }); - assert!(event == expected); -} + fn assert_only_events_call_scheduled_batch( + ref self: EventSpy, + contract: ContractAddress, + id: felt252, + calls: Span, + predecessor: felt252, + delay: u64 + ) { + self.assert_events_call_scheduled_batch(contract, id, calls, predecessor, delay); + self.assert_no_events_left_from(contract); + } -fn assert_only_event_call_salt(contract: ContractAddress, id: felt252, salt: felt252) { - assert_event_call_salt(contract, id, salt); - utils::assert_no_events_left(contract); -} + // + // CallSalt + // -// -// CallExecuted -// + fn assert_event_call_salt( + ref self: EventSpy, contract: ContractAddress, id: felt252, salt: felt252 + ) { + let expected = TimelockControllerComponent::Event::CallSalt(CallSalt { id, salt }); + self.assert_emitted_single(contract, expected); + } -fn assert_event_execute(contract: ContractAddress, id: felt252, index: felt252, call: Call) { - let event = utils::pop_log::(contract).unwrap(); - let expected = TimelockControllerComponent::Event::CallExecuted( - CallExecuted { id, index, call } - ); - assert!(event == expected); + fn assert_only_event_call_salt( + ref self: EventSpy, contract: ContractAddress, id: felt252, salt: felt252 + ) { + self.assert_event_call_salt(contract, id, salt); + self.assert_no_events_left_from(contract); + } - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("CallExecuted")); - indexed_keys.append_serde(id); - indexed_keys.append_serde(index); - utils::assert_indexed_keys(event, indexed_keys.span()); -} + // + // Cancelled + // -fn assert_only_event_execute(contract: ContractAddress, id: felt252, index: felt252, call: Call) { - assert_event_execute(contract, id, index, call); - utils::assert_no_events_left(contract); -} + fn assert_event_call_cancelled(ref self: EventSpy, contract: ContractAddress, id: felt252) { + let expected = TimelockControllerComponent::Event::CallCancelled(CallCancelled { id }); + self.assert_emitted_single(contract, expected); + } -fn assert_events_execute_batch(contract: ContractAddress, id: felt252, calls: Span) { - let mut i = 0; - loop { - if i == calls.len() { - break; - } - assert_event_execute(contract, id, i.into(), *calls.at(i)); - i += 1; + fn assert_only_event_call_cancelled( + ref self: EventSpy, contract: ContractAddress, id: felt252 + ) { + self.assert_event_call_cancelled(contract, id); + self.assert_no_events_left_from(contract); } -} -fn assert_only_events_execute_batch(contract: ContractAddress, id: felt252, calls: Span) { - assert_events_execute_batch(contract, id, calls); - utils::assert_no_events_left(contract); -} + // + // CallExecuted + // -// -// Cancelled -// + fn assert_event_call_executed( + ref self: EventSpy, contract: ContractAddress, id: felt252, index: felt252, call: Call + ) { + let expected = TimelockControllerComponent::Event::CallExecuted( + CallExecuted { id, index, call } + ); + self.assert_emitted_single(contract, expected); + } -fn assert_event_cancel(contract: ContractAddress, id: felt252) { - let event = utils::pop_log::(contract).unwrap(); - let expected = TimelockControllerComponent::Event::CallCancelled(CallCancelled { id }); - assert!(event == expected); + fn assert_only_event_call_executed( + ref self: EventSpy, contract: ContractAddress, id: felt252, index: felt252, call: Call + ) { + self.assert_event_call_executed(contract, id, index, call); + self.assert_no_events_left_from(contract); + } - // Check indexed keys - let mut indexed_keys = array![]; - indexed_keys.append_serde(selector!("CallCancelled")); - indexed_keys.append_serde(id); - utils::assert_indexed_keys(event, indexed_keys.span()); -} + fn assert_events_call_executed_batch( + ref self: EventSpy, contract: ContractAddress, id: felt252, calls: Span + ) { + let mut i = 0; + loop { + if i == calls.len() { + break; + } + self.assert_event_call_executed(contract, id, i.into(), *calls.at(i)); + i += 1; + } + } -fn assert_only_event_cancel(contract: ContractAddress, id: felt252) { - assert_event_cancel(contract, id); - utils::assert_no_events_left(contract); -} + fn assert_only_events_call_executed_batch( + ref self: EventSpy, contract: ContractAddress, id: felt252, calls: Span + ) { + self.assert_events_call_executed_batch(contract, id, calls); + self.assert_no_events_left_from(contract); + } -// -// MinDelayChanged -// + // + // MinDelayChanged + // -fn assert_event_delay(contract: ContractAddress, old_duration: u64, new_duration: u64) { - let event = utils::pop_log::(contract).unwrap(); - let expected = TimelockControllerComponent::Event::MinDelayChanged( - MinDelayChanged { old_duration, new_duration } - ); - assert!(event == expected); -} + fn assert_event_delay_changed( + ref self: EventSpy, contract: ContractAddress, old_duration: u64, new_duration: u64, + ) { + let expected = TimelockControllerComponent::Event::MinDelayChanged( + MinDelayChanged { old_duration, new_duration } + ); + self.assert_emitted_single(contract, expected); + } -fn assert_only_event_delay(contract: ContractAddress, old_duration: u64, new_duration: u64) { - assert_event_delay(contract, old_duration, new_duration); - utils::assert_no_events_left(contract); + fn assert_only_event_delay_changed( + ref self: EventSpy, contract: ContractAddress, old_duration: u64, new_duration: u64, + ) { + self.assert_event_delay_changed(contract, old_duration, new_duration); + self.assert_no_events_left_from(contract); + } } From fc8b3971b0e8c705d7b9218b2ab6934820b8d2f5 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 1 Aug 2024 13:48:10 +0200 Subject: [PATCH 36/45] Update docs/modules/ROOT/pages/components.adoc Co-authored-by: Andrew Fleming --- docs/modules/ROOT/pages/components.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/components.adoc b/docs/modules/ROOT/pages/components.adoc index 8d527b332..c2087c01a 100644 --- a/docs/modules/ROOT/pages/components.adoc +++ b/docs/modules/ROOT/pages/components.adoc @@ -254,7 +254,7 @@ Let's look at how a contract would integrate {ownable-component}: ---- #[starknet::contract] mod MyContract { - use openzeppelinaccess::ownable::OwnableComponent; + use openzeppelin::access::ownable::OwnableComponent; use starknet::ContractAddress; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); From 25c199b157560e51f540c123dfa96bad6bee75d3 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 1 Aug 2024 13:48:18 +0200 Subject: [PATCH 37/45] Update docs/modules/ROOT/pages/components.adoc Co-authored-by: Andrew Fleming --- docs/modules/ROOT/pages/components.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/components.adoc b/docs/modules/ROOT/pages/components.adoc index c2087c01a..33dbbe539 100644 --- a/docs/modules/ROOT/pages/components.adoc +++ b/docs/modules/ROOT/pages/components.adoc @@ -297,7 +297,7 @@ Creating a contract with `AccessControlComponent` should look like this: ---- #[starknet::contract] mod MyContract { - use openzeppelinaccess::accesscontrol::AccessControlComponent; + use openzeppelin::access::accesscontrol::AccessControlComponent; use openzeppelin::introspection::src5::SRC5Component; component!(path: AccessControlComponent, storage: accesscontrol, event: AccessControlEvent); From 493b42694ee6285feff5f346d6d079b75827595f Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 1 Aug 2024 14:11:09 +0200 Subject: [PATCH 38/45] feat: apply review updates --- .../accesscontrol/dual_accesscontrol.cairo | 6 +- packages/account/src/tests.cairo | 2 +- .../account/src/tests/mocks/erc20_mocks.cairo | 213 ------------- .../src/tests/mocks/account_mocks.cairo | 78 ----- .../src/tests/mocks/erc1155_mocks.cairo | 205 ------------ .../tests/mocks/erc1155_receiver_mocks.cairo | 154 --------- .../presets/src/tests/mocks/erc20_mocks.cairo | 174 ---------- .../src/tests/mocks/erc721_mocks.cairo | 297 ------------------ .../tests/mocks/erc721_receiver_mocks.cairo | 118 ------- .../src/tests/mocks/eth_account_mocks.cairo | 189 ----------- packages/token/src/erc1155/erc1155.cairo | 6 +- .../token/src/tests/mocks/account_mocks.cairo | 78 ----- 12 files changed, 7 insertions(+), 1513 deletions(-) diff --git a/packages/access/src/accesscontrol/dual_accesscontrol.cairo b/packages/access/src/accesscontrol/dual_accesscontrol.cairo index a792cc798..e6fdcc645 100644 --- a/packages/access/src/accesscontrol/dual_accesscontrol.cairo +++ b/packages/access/src/accesscontrol/dual_accesscontrol.cairo @@ -1,9 +1,9 @@ -use openzeppelin_utils::selectors; -use openzeppelin_utils::serde::SerializedAppend; -use openzeppelin_utils::try_selector_with_fallback; // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.15.0-rc.0 (access/accesscontrol/dual_accesscontrol.cairo) +use openzeppelin_utils::selectors; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::try_selector_with_fallback; use openzeppelin_utils::unwrap_and_cast::UnwrapAndCast; use starknet::ContractAddress; use starknet::SyscallResultTrait; diff --git a/packages/account/src/tests.cairo b/packages/account/src/tests.cairo index a35ada124..f358a8153 100644 --- a/packages/account/src/tests.cairo +++ b/packages/account/src/tests.cairo @@ -1,5 +1,5 @@ pub mod ethereum; -pub mod mocks; +pub(crate) mod mocks; pub mod starknet; #[cfg(test)] diff --git a/packages/account/src/tests/mocks/erc20_mocks.cairo b/packages/account/src/tests/mocks/erc20_mocks.cairo index 80a66d34f..8e24ff5f9 100644 --- a/packages/account/src/tests/mocks/erc20_mocks.cairo +++ b/packages/account/src/tests/mocks/erc20_mocks.cairo @@ -38,216 +38,3 @@ pub(crate) mod DualCaseERC20Mock { self.erc20.mint(recipient, initial_supply); } } - -#[starknet::contract] -pub(crate) mod SnakeERC20Mock { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - - #[abi(embed_v0)] - impl ERC20Impl = ERC20Component::ERC20Impl; - #[abi(embed_v0)] - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; - impl InternalImpl = ERC20Component::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - initial_supply: u256, - recipient: ContractAddress - ) { - self.erc20.initializer(name, symbol); - self.erc20.mint(recipient, initial_supply); - } -} - -#[starknet::contract] -pub(crate) mod CamelERC20Mock { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - - #[abi(embed_v0)] - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; - #[abi(embed_v0)] - impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; - - // `ERC20Impl` is not embedded because it would defeat the purpose of the - // mock. The `ERC20Impl` case-agnostic methods are manually exposed. - impl ERC20Impl = ERC20Component::ERC20Impl; - impl InternalImpl = ERC20Component::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - initial_supply: u256, - recipient: ContractAddress - ) { - self.erc20.initializer(name, symbol); - self.erc20.mint(recipient, initial_supply); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress - ) -> u256 { - self.erc20.allowance(owner, spender) - } - - #[external(v0)] - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { - self.erc20.transfer(recipient, amount) - } - - #[external(v0)] - fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool { - self.erc20.approve(spender, amount) - } - } -} - -/// Although these modules are designed to panic, functions -/// still need a valid return value. We chose: -/// -/// 3 for felt252, u8, and u256 -/// zero for ContractAddress -/// false for bool -#[starknet::contract] -pub(crate) mod SnakeERC20Panic { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn name(self: @ContractState) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn symbol(self: @ContractState) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn decimals(self: @ContractState) -> u8 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress - ) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn total_supply(self: @ContractState) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn transfer_from( - ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256 - ) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelERC20Panic { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn totalSupply(self: @ContractState) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn transferFrom( - ref self: ContractState, - sender: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) { - panic!("Some error"); - } - } -} diff --git a/packages/presets/src/tests/mocks/account_mocks.cairo b/packages/presets/src/tests/mocks/account_mocks.cairo index c2f7d9f57..a6bc34626 100644 --- a/packages/presets/src/tests/mocks/account_mocks.cairo +++ b/packages/presets/src/tests/mocks/account_mocks.cairo @@ -143,81 +143,3 @@ pub(crate) mod CamelAccountMock { } } } - -// Although these modules are designed to panic, functions -// still need a valid return value. We chose: -// -// 3 for felt252 -// false for bool - -#[starknet::contract] -pub(crate) mod SnakeAccountPanicMock { - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn set_public_key( - ref self: ContractState, new_public_key: felt252, signature: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn get_public_key(self: @ContractState) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn is_valid_signature( - self: @ContractState, hash: felt252, signature: Array - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelAccountPanicMock { - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn setPublicKey(ref self: ContractState, newPublicKey: felt252, signature: Span) { - panic!("Some error"); - } - - #[external(v0)] - fn getPublicKey(self: @ContractState) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn isValidSignature( - self: @ContractState, hash: felt252, signature: Array - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - panic!("Some error"); - false - } - } -} diff --git a/packages/presets/src/tests/mocks/erc1155_mocks.cairo b/packages/presets/src/tests/mocks/erc1155_mocks.cairo index 9d8d79181..3ddf1ee72 100644 --- a/packages/presets/src/tests/mocks/erc1155_mocks.cairo +++ b/packages/presets/src/tests/mocks/erc1155_mocks.cairo @@ -1,56 +1,3 @@ -#[starknet::contract] -pub(crate) mod DualCaseERC1155Mock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC1155 - #[abi(embed_v0)] - impl ERC1155Impl = ERC1155Component::ERC1155Impl; - #[abi(embed_v0)] - impl ERC1155MetadataURIImpl = - ERC1155Component::ERC1155MetadataURIImpl; - #[abi(embed_v0)] - impl ERC721Camel = ERC1155Component::ERC1155CamelImpl; - impl ERC1155InternalImpl = ERC1155Component::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc1155: ERC1155Component::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC1155Event: ERC1155Component::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - base_uri: ByteArray, - recipient: ContractAddress, - token_id: u256, - value: u256 - ) { - self.erc1155.initializer(base_uri); - self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); - } -} - #[starknet::contract] pub(crate) mod SnakeERC1155Mock { use openzeppelin_introspection::src5::SRC5Component; @@ -152,155 +99,3 @@ pub(crate) mod CamelERC1155Mock { self.erc1155.mint_with_acceptance_check(recipient, token_id, value, array![].span()); } } - -#[starknet::contract] -pub(crate) mod SnakeERC1155PanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn uri(self: @ContractState, token_id: u256) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn balance_of(self: @ContractState, account: ContractAddress, token_id: u256) -> u256 { - panic!("Some error"); - u256 { low: 3, high: 3 } - } - - #[external(v0)] - fn balance_of_batch( - self: @ContractState, accounts: Span, token_ids: Span - ) -> Span { - panic!("Some error"); - array![u256 { low: 3, high: 3 }].span() - } - - #[external(v0)] - fn safe_transfer_from( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - value: u256, - data: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn safe_batch_transfer_from( - ref self: ContractState, - from: starknet::ContractAddress, - to: starknet::ContractAddress, - token_ids: Span, - values: Span, - data: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn is_approved_for_all( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn set_approval_for_all( - ref self: ContractState, operator: ContractAddress, approved: bool - ) { - panic!("Some error"); - } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelERC1155PanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn uri(self: @ContractState, tokenId: u256) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn balanceOf(self: @ContractState, account: ContractAddress, tokenId: u256) -> u256 { - panic!("Some error"); - u256 { low: 3, high: 3 } - } - - #[external(v0)] - fn balanceOfBatch( - self: @ContractState, accounts: Span, token_ids: Span - ) -> Span { - panic!("Some error"); - array![u256 { low: 3, high: 3 }].span() - } - - #[external(v0)] - fn safeTransferFrom( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - tokenId: u256, - value: u256, - data: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn safeBatchTransferFrom( - ref self: ContractState, - from: starknet::ContractAddress, - to: starknet::ContractAddress, - token_ids: Span, - values: Span, - data: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn isApprovedForAll( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) { - panic!("Some error"); - } - - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - panic!("Some error"); - false - } - } -} diff --git a/packages/presets/src/tests/mocks/erc1155_receiver_mocks.cairo b/packages/presets/src/tests/mocks/erc1155_receiver_mocks.cairo index 34ec82649..23bf2ff78 100644 --- a/packages/presets/src/tests/mocks/erc1155_receiver_mocks.cairo +++ b/packages/presets/src/tests/mocks/erc1155_receiver_mocks.cairo @@ -1,45 +1,3 @@ -use openzeppelin_utils::test_utils::constants::SUCCESS; - -#[starknet::contract] -pub(crate) mod DualCaseERC1155ReceiverMock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::ERC1155ReceiverComponent; - use starknet::ContractAddress; - - component!(path: SRC5Component, storage: src5, event: SRC5Event); - component!( - path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent - ); - - // ERC1155Receiver Mixin - #[abi(embed_v0)] - impl ERC1155ReceiverMixinImpl = - ERC1155ReceiverComponent::ERC1155ReceiverMixinImpl; - impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc1155_receiver: ERC1155ReceiverComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState) { - self.erc1155_receiver.initializer(); - } -} - #[starknet::contract] pub(crate) mod SnakeERC1155ReceiverMock { use openzeppelin_introspection::src5::SRC5Component; @@ -83,115 +41,3 @@ pub(crate) mod SnakeERC1155ReceiverMock { self.erc1155_receiver.initializer(); } } - -#[starknet::contract] -pub(crate) mod CamelERC1155ReceiverMock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc1155::ERC1155ReceiverComponent; - use starknet::ContractAddress; - - component!(path: SRC5Component, storage: src5, event: SRC5Event); - component!( - path: ERC1155ReceiverComponent, storage: erc1155_receiver, event: ERC1155ReceiverEvent - ); - - // ERC1155Receiver - #[abi(embed_v0)] - impl ERC1155ReceiverCamelImpl = - ERC1155ReceiverComponent::ERC1155ReceiverCamelImpl; - impl ERC1155ReceiverInternalImpl = ERC1155ReceiverComponent::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc1155_receiver: ERC1155ReceiverComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC1155ReceiverEvent: ERC1155ReceiverComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState) { - self.erc1155_receiver.initializer(); - } -} - -#[starknet::contract] -pub(crate) mod SnakeERC1155ReceiverPanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[external(v0)] - fn on_erc1155_received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - token_id: u256, - value: u256, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn on_erc1155_batch_received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenIds: Span, - values: Span, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } -} - -#[starknet::contract] -pub(crate) mod CamelERC1155ReceiverPanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[external(v0)] - fn onERC1155Received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenId: u256, - value: u256, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn onERC1155BatchReceived( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenIds: Span, - values: Span, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } -} diff --git a/packages/presets/src/tests/mocks/erc20_mocks.cairo b/packages/presets/src/tests/mocks/erc20_mocks.cairo index 80a66d34f..856ecc97d 100644 --- a/packages/presets/src/tests/mocks/erc20_mocks.cairo +++ b/packages/presets/src/tests/mocks/erc20_mocks.cairo @@ -77,177 +77,3 @@ pub(crate) mod SnakeERC20Mock { self.erc20.mint(recipient, initial_supply); } } - -#[starknet::contract] -pub(crate) mod CamelERC20Mock { - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - - #[abi(embed_v0)] - impl ERC20MetadataImpl = ERC20Component::ERC20MetadataImpl; - #[abi(embed_v0)] - impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; - - // `ERC20Impl` is not embedded because it would defeat the purpose of the - // mock. The `ERC20Impl` case-agnostic methods are manually exposed. - impl ERC20Impl = ERC20Component::ERC20Impl; - impl InternalImpl = ERC20Component::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - initial_supply: u256, - recipient: ContractAddress - ) { - self.erc20.initializer(name, symbol); - self.erc20.mint(recipient, initial_supply); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress - ) -> u256 { - self.erc20.allowance(owner, spender) - } - - #[external(v0)] - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { - self.erc20.transfer(recipient, amount) - } - - #[external(v0)] - fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool { - self.erc20.approve(spender, amount) - } - } -} - -/// Although these modules are designed to panic, functions -/// still need a valid return value. We chose: -/// -/// 3 for felt252, u8, and u256 -/// zero for ContractAddress -/// false for bool -#[starknet::contract] -pub(crate) mod SnakeERC20Panic { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn name(self: @ContractState) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn symbol(self: @ContractState) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn decimals(self: @ContractState) -> u8 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn allowance( - self: @ContractState, owner: ContractAddress, spender: ContractAddress - ) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn total_supply(self: @ContractState) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn transfer_from( - ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256 - ) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelERC20Panic { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn totalSupply(self: @ContractState) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn transferFrom( - ref self: ContractState, - sender: ContractAddress, - recipient: ContractAddress, - amount: u256 - ) { - panic!("Some error"); - } - } -} diff --git a/packages/presets/src/tests/mocks/erc721_mocks.cairo b/packages/presets/src/tests/mocks/erc721_mocks.cairo index 05aaf81f2..3e84bbe93 100644 --- a/packages/presets/src/tests/mocks/erc721_mocks.cairo +++ b/packages/presets/src/tests/mocks/erc721_mocks.cairo @@ -1,59 +1,3 @@ -#[starknet::contract] -pub(crate) mod DualCaseERC721Mock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC721Component, storage: erc721, event: ERC721Event); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC721 - #[abi(embed_v0)] - impl ERC721Impl = ERC721Component::ERC721Impl; - #[abi(embed_v0)] - impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl; - #[abi(embed_v0)] - impl ERC721CamelOnly = ERC721Component::ERC721CamelOnlyImpl; - #[abi(embed_v0)] - impl ERC721MetadataCamelOnly = - ERC721Component::ERC721MetadataCamelOnlyImpl; - impl ERC721InternalImpl = ERC721Component::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc721: ERC721Component::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC721Event: ERC721Component::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - base_uri: ByteArray, - recipient: ContractAddress, - token_id: u256 - ) { - self.erc721.initializer(name, symbol, base_uri); - self.erc721.mint(recipient, token_id); - } -} - #[starknet::contract] pub(crate) mod SnakeERC721Mock { use openzeppelin_introspection::src5::SRC5Component; @@ -104,244 +48,3 @@ pub(crate) mod SnakeERC721Mock { self.erc721.mint(recipient, token_id); } } - -#[starknet::contract] -pub(crate) mod CamelERC721Mock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::ERC721Component::{ERC721Impl, ERC721MetadataImpl}; - use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; - use starknet::ContractAddress; - - component!(path: ERC721Component, storage: erc721, event: ERC721Event); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC721 - #[abi(embed_v0)] - impl ERC721CamelOnly = ERC721Component::ERC721CamelOnlyImpl; - #[abi(embed_v0)] - impl ERC721MetadataCamelOnly = - ERC721Component::ERC721MetadataCamelOnlyImpl; - impl ERC721InternalImpl = ERC721Component::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc721: ERC721Component::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC721Event: ERC721Component::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - base_uri: ByteArray, - recipient: ContractAddress, - token_id: u256 - ) { - self.erc721.initializer(name, symbol, base_uri); - self.erc721.mint(recipient, token_id); - } - - /// The following external methods are included because they are case-agnostic - /// and this contract should not embed the snake_case impl. - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn approve(ref self: ContractState, to: ContractAddress, tokenId: u256) { - self.erc721.approve(to, tokenId); - } - - #[external(v0)] - fn name(self: @ContractState) -> ByteArray { - self.erc721.name() - } - - #[external(v0)] - fn symbol(self: @ContractState) -> ByteArray { - self.erc721.symbol() - } - } -} - -/// Although these modules are designed to panic, functions -/// still need a valid return value. We chose: -/// -/// 3 for felt252 -/// zero for ContractAddress -/// u256 { 3, 3 } for u256 -#[starknet::contract] -pub(crate) mod SnakeERC721PanicMock { - use core::num::traits::Zero; - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn name(self: @ContractState) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn symbol(self: @ContractState) -> ByteArray { - panic!("Some error"); - "3" - } - - #[external(v0)] - fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) { - panic!("Some error"); - } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn token_uri(self: @ContractState, token_id: u256) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { - panic!("Some error"); - u256 { low: 3, high: 3 } - } - - #[external(v0)] - fn owner_of(self: @ContractState, token_id: u256) -> ContractAddress { - panic!("Some error"); - Zero::zero() - } - - #[external(v0)] - fn get_approved(self: @ContractState, token_id: u256) -> ContractAddress { - panic!("Some error"); - Zero::zero() - } - - #[external(v0)] - fn is_approved_for_all( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn set_approval_for_all( - ref self: ContractState, operator: ContractAddress, approved: bool - ) { - panic!("Some error"); - } - - #[external(v0)] - fn transfer_from( - ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256 - ) { - panic!("Some error"); - } - - #[external(v0)] - fn safe_transfer_from( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - data: Span - ) { - panic!("Some error"); - } - } -} - -#[starknet::contract] -pub(crate) mod CamelERC721PanicMock { - use core::num::traits::Zero; - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn tokenURI(self: @ContractState, tokenId: u256) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn balanceOf(self: @ContractState, account: ContractAddress) -> u256 { - panic!("Some error"); - u256 { low: 3, high: 3 } - } - - #[external(v0)] - fn ownerOf(self: @ContractState, tokenId: u256) -> ContractAddress { - panic!("Some error"); - Zero::zero() - } - - #[external(v0)] - fn getApproved(self: @ContractState, tokenId: u256) -> ContractAddress { - panic!("Some error"); - Zero::zero() - } - - #[external(v0)] - fn isApprovedForAll( - self: @ContractState, owner: ContractAddress, operator: ContractAddress - ) -> bool { - panic!("Some error"); - false - } - - #[external(v0)] - fn setApprovalForAll(ref self: ContractState, operator: ContractAddress, approved: bool) { - panic!("Some error"); - } - - #[external(v0)] - fn transferFrom( - ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256 - ) { - panic!("Some error"); - } - - #[external(v0)] - fn safeTransferFrom( - ref self: ContractState, - from: ContractAddress, - to: ContractAddress, - tokenId: u256, - data: Span - ) { - panic!("Some error"); - } - } -} diff --git a/packages/presets/src/tests/mocks/erc721_receiver_mocks.cairo b/packages/presets/src/tests/mocks/erc721_receiver_mocks.cairo index e321c0d58..fbf6e1b45 100644 --- a/packages/presets/src/tests/mocks/erc721_receiver_mocks.cairo +++ b/packages/presets/src/tests/mocks/erc721_receiver_mocks.cairo @@ -1,75 +1,5 @@ use openzeppelin_utils::test_utils::constants::SUCCESS; -#[starknet::contract] -pub(crate) mod DualCaseERC721ReceiverMock { - use openzeppelin_introspection::src5::SRC5Component; - use openzeppelin_token::erc721::ERC721ReceiverComponent; - use starknet::ContractAddress; - - component!(path: ERC721ReceiverComponent, storage: erc721_receiver, event: ERC721ReceiverEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - // ERC721Receiver - impl ERC721ReceiverImpl = ERC721ReceiverComponent::ERC721ReceiverImpl; - impl ERC721ReceiverInternalImpl = ERC721ReceiverComponent::InternalImpl; - - // SRC5 - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc721_receiver: ERC721ReceiverComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC721ReceiverEvent: ERC721ReceiverComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState) { - self.erc721_receiver.initializer(); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn on_erc721_received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - token_id: u256, - data: Span - ) -> felt252 { - if *data.at(0) == super::SUCCESS { - self.erc721_receiver.on_erc721_received(operator, from, token_id, data) - } else { - 0 - } - } - - #[external(v0)] - fn onERC721Received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenId: u256, - data: Span - ) -> felt252 { - Self::on_erc721_received(self, operator, from, tokenId, data) - } - } -} - #[starknet::contract] pub(crate) mod SnakeERC721ReceiverMock { use openzeppelin_introspection::src5::SRC5Component; @@ -187,51 +117,3 @@ pub(crate) mod CamelERC721ReceiverMock { } } } - -#[starknet::contract] -pub(crate) mod SnakeERC721ReceiverPanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn on_erc721_received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - token_id: u256, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } - } -} - -#[starknet::contract] -pub(crate) mod CamelERC721ReceiverPanicMock { - use starknet::ContractAddress; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn onERC721Received( - self: @ContractState, - operator: ContractAddress, - from: ContractAddress, - tokenId: u256, - data: Span - ) -> felt252 { - panic!("Some error"); - 3 - } - } -} diff --git a/packages/presets/src/tests/mocks/eth_account_mocks.cairo b/packages/presets/src/tests/mocks/eth_account_mocks.cairo index b230e524d..2dc299b06 100644 --- a/packages/presets/src/tests/mocks/eth_account_mocks.cairo +++ b/packages/presets/src/tests/mocks/eth_account_mocks.cairo @@ -1,47 +1,3 @@ -#[starknet::contract(account)] -pub(crate) mod DualCaseEthAccountMock { - use openzeppelin_account::EthAccountComponent; - use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_introspection::src5::SRC5Component; - - component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - #[abi(embed_v0)] - impl SRC6Impl = EthAccountComponent::SRC6Impl; - #[abi(embed_v0)] - impl SRC6CamelOnlyImpl = EthAccountComponent::SRC6CamelOnlyImpl; - #[abi(embed_v0)] - impl DeclarerImpl = EthAccountComponent::DeclarerImpl; - #[abi(embed_v0)] - impl DeployableImpl = EthAccountComponent::DeployableImpl; - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - eth_account: EthAccountComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - EthAccountEvent: EthAccountComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, public_key: EthPublicKey) { - self.eth_account.initializer(public_key); - } -} - #[starknet::contract(account)] pub(crate) mod SnakeEthAccountMock { use openzeppelin_account::EthAccountComponent; @@ -81,148 +37,3 @@ pub(crate) mod SnakeEthAccountMock { self.eth_account.initializer(public_key); } } - -#[starknet::contract(account)] -pub(crate) mod CamelEthAccountMock { - use openzeppelin_account::EthAccountComponent; - use openzeppelin_account::interface::EthPublicKey; - use openzeppelin_introspection::src5::SRC5Component; - use starknet::account::Call; - - component!(path: EthAccountComponent, storage: eth_account, event: EthAccountEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - #[abi(embed_v0)] - impl SRC6CamelOnlyImpl = EthAccountComponent::SRC6CamelOnlyImpl; - #[abi(embed_v0)] - impl PublicKeyCamelImpl = - EthAccountComponent::PublicKeyCamelImpl; - #[abi(embed_v0)] - impl SRC5Impl = SRC5Component::SRC5Impl; - impl SRC6Impl = EthAccountComponent::SRC6Impl; - impl EthAccountInternalImpl = EthAccountComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - eth_account: EthAccountComponent::Storage, - #[substorage(v0)] - src5: SRC5Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - EthAccountEvent: EthAccountComponent::Event, - #[flat] - SRC5Event: SRC5Component::Event - } - - #[constructor] - fn constructor(ref self: ContractState, publicKey: EthPublicKey) { - self.eth_account.initializer(publicKey); - } - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn __execute__(self: @ContractState, mut calls: Array) -> Array> { - self.eth_account.__execute__(calls) - } - - #[external(v0)] - fn __validate__(self: @ContractState, mut calls: Array) -> felt252 { - self.eth_account.__validate__(calls) - } - } -} - -// Although these modules are designed to panic, functions -// still need a valid return value. We chose: -// -// 3 for felt252 -// false for bool - -#[starknet::contract] -pub(crate) mod SnakeEthAccountPanicMock { - use openzeppelin_account::interface::EthPublicKey; - use starknet::SyscallResultTrait; - use starknet::secp256_trait::Secp256Trait; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn set_public_key( - ref self: ContractState, new_public_key: EthPublicKey, signature: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn get_public_key(self: @ContractState) -> EthPublicKey { - panic!("Some error"); - Secp256Trait::secp256_ec_new_syscall(3, 3).unwrap_syscall().unwrap() - } - - #[external(v0)] - fn is_valid_signature( - self: @ContractState, hash: felt252, signature: Array - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelEthAccountPanicMock { - use openzeppelin_account::interface::EthPublicKey; - use starknet::SyscallResultTrait; - use starknet::secp256_trait::Secp256Trait; - - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn setPublicKey( - ref self: ContractState, newPublicKey: EthPublicKey, signature: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn getPublicKey(self: @ContractState) -> EthPublicKey { - panic!("Some error"); - Secp256Trait::secp256_ec_new_syscall(3, 3).unwrap_syscall().unwrap() - } - - #[external(v0)] - fn isValidSignature( - self: @ContractState, hash: felt252, signature: Array - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - panic!("Some error"); - false - } - } -} diff --git a/packages/token/src/erc1155/erc1155.cairo b/packages/token/src/erc1155/erc1155.cairo index 4ed7fdc4f..d81e0eda4 100644 --- a/packages/token/src/erc1155/erc1155.cairo +++ b/packages/token/src/erc1155/erc1155.cairo @@ -10,6 +10,7 @@ use starknet::ContractAddress; #[starknet::component] pub mod ERC1155Component { use core::num::traits::Zero; + use openzeppelin_account::interface::ISRC6_ID; use openzeppelin_introspection::interface::{ISRC5Dispatcher, ISRC5DispatcherTrait}; use openzeppelin_introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; @@ -139,7 +140,6 @@ pub mod ERC1155Component { self.ERC1155_balances.read((token_id, account)) } - /// Returns a list of balances derived from the `accounts` and `token_ids` pairs. /// /// Requirements: @@ -690,7 +690,7 @@ pub mod ERC1155Component { get_caller_address(), from, token_id, value, data ) == interface::IERC1155_RECEIVER_ID } else { - src5_dispatcher.supports_interface(openzeppelin_account::interface::ISRC6_ID) + src5_dispatcher.supports_interface(ISRC6_ID) } } @@ -711,7 +711,7 @@ pub mod ERC1155Component { get_caller_address(), from, token_ids, values, data ) == interface::IERC1155_RECEIVER_ID } else { - src5_dispatcher.supports_interface(openzeppelin_account::interface::ISRC6_ID) + src5_dispatcher.supports_interface(ISRC6_ID) } } } diff --git a/packages/token/src/tests/mocks/account_mocks.cairo b/packages/token/src/tests/mocks/account_mocks.cairo index c2f7d9f57..a6bc34626 100644 --- a/packages/token/src/tests/mocks/account_mocks.cairo +++ b/packages/token/src/tests/mocks/account_mocks.cairo @@ -143,81 +143,3 @@ pub(crate) mod CamelAccountMock { } } } - -// Although these modules are designed to panic, functions -// still need a valid return value. We chose: -// -// 3 for felt252 -// false for bool - -#[starknet::contract] -pub(crate) mod SnakeAccountPanicMock { - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn set_public_key( - ref self: ContractState, new_public_key: felt252, signature: Span - ) { - panic!("Some error"); - } - - #[external(v0)] - fn get_public_key(self: @ContractState) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn is_valid_signature( - self: @ContractState, hash: felt252, signature: Array - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - panic!("Some error"); - false - } - } -} - -#[starknet::contract] -pub(crate) mod CamelAccountPanicMock { - #[storage] - struct Storage {} - - #[abi(per_item)] - #[generate_trait] - impl ExternalImpl of ExternalTrait { - #[external(v0)] - fn setPublicKey(ref self: ContractState, newPublicKey: felt252, signature: Span) { - panic!("Some error"); - } - - #[external(v0)] - fn getPublicKey(self: @ContractState) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn isValidSignature( - self: @ContractState, hash: felt252, signature: Array - ) -> felt252 { - panic!("Some error"); - 3 - } - - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - panic!("Some error"); - false - } - } -} From 530b087779bbcfea90957d08162c57b638d0239c Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 1 Aug 2024 14:33:24 +0200 Subject: [PATCH 39/45] feat: update governance package --- packages/governance/src/lib.cairo | 2 +- packages/governance/src/tests.cairo | 2 + .../src/tests/mocks/timelock_mocks.cairo | 8 ++-- .../governance/src/tests/test_timelock.cairo | 40 +++++++++---------- .../governance/src/tests/test_utils.cairo | 2 +- 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/packages/governance/src/lib.cairo b/packages/governance/src/lib.cairo index d1e6ccb58..852e24521 100644 --- a/packages/governance/src/lib.cairo +++ b/packages/governance/src/lib.cairo @@ -1,4 +1,4 @@ -#[cfg(test)] mod tests; + pub mod timelock; pub mod utils; diff --git a/packages/governance/src/tests.cairo b/packages/governance/src/tests.cairo index 883a2ac5d..221670eec 100644 --- a/packages/governance/src/tests.cairo +++ b/packages/governance/src/tests.cairo @@ -1,4 +1,6 @@ pub(crate) mod mocks; +#[cfg(test)] mod test_timelock; +#[cfg(test)] mod test_utils; diff --git a/packages/governance/src/tests/mocks/timelock_mocks.cairo b/packages/governance/src/tests/mocks/timelock_mocks.cairo index a60a9da19..810d88cac 100644 --- a/packages/governance/src/tests/mocks/timelock_mocks.cairo +++ b/packages/governance/src/tests/mocks/timelock_mocks.cairo @@ -1,8 +1,8 @@ #[starknet::contract] pub(crate) mod TimelockControllerMock { - use openzeppelin::access::accesscontrol::AccessControlComponent; - use openzeppelin::governance::timelock::TimelockControllerComponent; - use openzeppelin::introspection::src5::SRC5Component; + use openzeppelin_access::accesscontrol::AccessControlComponent; + use openzeppelin_governance::timelock::TimelockControllerComponent; + use openzeppelin_introspection::src5::SRC5Component; use starknet::ContractAddress; component!(path: AccessControlComponent, storage: access_control, event: AccessControlEvent); @@ -88,7 +88,7 @@ pub(crate) trait ITimelockAttacker { #[starknet::contract] pub(crate) mod TimelockAttackerMock { - use openzeppelin::governance::timelock::interface::{ + use openzeppelin_governance::timelock::interface::{ ITimelockDispatcher, ITimelockDispatcherTrait }; use starknet::ContractAddress; diff --git a/packages/governance/src/tests/test_timelock.cairo b/packages/governance/src/tests/test_timelock.cairo index d3838ae21..59265f1ff 100644 --- a/packages/governance/src/tests/test_timelock.cairo +++ b/packages/governance/src/tests/test_timelock.cairo @@ -1,38 +1,38 @@ use core::hash::{HashStateTrait, HashStateExTrait}; use core::num::traits::Zero; use core::pedersen::PedersenTrait; -use openzeppelin::access::accesscontrol::AccessControlComponent::{ +use openzeppelin_access::accesscontrol::AccessControlComponent::{ AccessControlImpl, InternalImpl as AccessControlInternalImpl }; -use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; -use openzeppelin::access::accesscontrol::interface::IACCESSCONTROL_ID; -use openzeppelin::access::accesscontrol::interface::IAccessControl; -use openzeppelin::governance::timelock::OperationState; -use openzeppelin::governance::timelock::TimelockControllerComponent::{ +use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; +use openzeppelin_access::accesscontrol::interface::IACCESSCONTROL_ID; +use openzeppelin_access::accesscontrol::interface::IAccessControl; +use openzeppelin_governance::timelock::OperationState; +use openzeppelin_governance::timelock::TimelockControllerComponent::{ CallScheduled, CallExecuted, CallSalt, CallCancelled, MinDelayChanged }; -use openzeppelin::governance::timelock::TimelockControllerComponent::{ +use openzeppelin_governance::timelock::TimelockControllerComponent::{ TimelockImpl, InternalImpl as TimelockInternalImpl }; -use openzeppelin::governance::timelock::TimelockControllerComponent; -use openzeppelin::governance::timelock::interface::{ +use openzeppelin_governance::timelock::TimelockControllerComponent; +use openzeppelin_governance::timelock::interface::{ TimelockABIDispatcher, TimelockABIDispatcherTrait }; -use openzeppelin::governance::timelock::{PROPOSER_ROLE, EXECUTOR_ROLE, CANCELLER_ROLE}; -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::introspection::src5::SRC5Component::SRC5Impl; -use openzeppelin::tests::mocks::timelock_mocks::MockContract; -use openzeppelin::tests::mocks::timelock_mocks::{ +use openzeppelin_governance::timelock::{PROPOSER_ROLE, EXECUTOR_ROLE, CANCELLER_ROLE}; +use openzeppelin_introspection::interface::ISRC5_ID; +use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; +use openzeppelin_governance::tests::mocks::timelock_mocks::MockContract; +use openzeppelin_governance::tests::mocks::timelock_mocks::{ IMockContractDispatcher, IMockContractDispatcherTrait }; -use openzeppelin::tests::mocks::timelock_mocks::{ +use openzeppelin_governance::tests::mocks::timelock_mocks::{ ITimelockAttackerDispatcher, ITimelockAttackerDispatcherTrait }; -use openzeppelin::tests::mocks::timelock_mocks::{TimelockControllerMock, TimelockAttackerMock}; -use openzeppelin::tests::utils::constants::{ADMIN, ZERO, OTHER, SALT, FELT_VALUE as VALUE}; -use openzeppelin::tests::utils::events::EventSpyExt; -use openzeppelin::tests::utils; -use openzeppelin::utils::serde::SerializedAppend; +use openzeppelin_governance::tests::mocks::timelock_mocks::{TimelockControllerMock, TimelockAttackerMock}; +use openzeppelin_utils::test_utils::constants::{ADMIN, ZERO, OTHER, SALT, FELT_VALUE as VALUE}; +use openzeppelin_utils::test_utils::events::EventSpyExt; +use openzeppelin_utils::test_utils as utils; +use openzeppelin_utils::serde::SerializedAppend; use snforge_std::EventSpy; use snforge_std::{ spy_events, test_address, start_cheat_caller_address, cheat_caller_address, diff --git a/packages/governance/src/tests/test_utils.cairo b/packages/governance/src/tests/test_utils.cairo index 874fe2615..f66bafa33 100644 --- a/packages/governance/src/tests/test_utils.cairo +++ b/packages/governance/src/tests/test_utils.cairo @@ -1,4 +1,4 @@ -use openzeppelin::governance::timelock::utils::call_impls::CallPartialEq; +use openzeppelin_governance::timelock::utils::call_impls::CallPartialEq; use starknet::account::Call; use starknet::contract_address_const; From 66e6d2f9b3fd25d11ef369cf0f93d8d598b3beef Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 1 Aug 2024 14:33:44 +0200 Subject: [PATCH 40/45] refactor: format files --- .../governance/src/tests/test_timelock.cairo | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/governance/src/tests/test_timelock.cairo b/packages/governance/src/tests/test_timelock.cairo index 59265f1ff..6ba38fff4 100644 --- a/packages/governance/src/tests/test_timelock.cairo +++ b/packages/governance/src/tests/test_timelock.cairo @@ -7,6 +7,16 @@ use openzeppelin_access::accesscontrol::AccessControlComponent::{ use openzeppelin_access::accesscontrol::DEFAULT_ADMIN_ROLE; use openzeppelin_access::accesscontrol::interface::IACCESSCONTROL_ID; use openzeppelin_access::accesscontrol::interface::IAccessControl; +use openzeppelin_governance::tests::mocks::timelock_mocks::MockContract; +use openzeppelin_governance::tests::mocks::timelock_mocks::{ + IMockContractDispatcher, IMockContractDispatcherTrait +}; +use openzeppelin_governance::tests::mocks::timelock_mocks::{ + ITimelockAttackerDispatcher, ITimelockAttackerDispatcherTrait +}; +use openzeppelin_governance::tests::mocks::timelock_mocks::{ + TimelockControllerMock, TimelockAttackerMock +}; use openzeppelin_governance::timelock::OperationState; use openzeppelin_governance::timelock::TimelockControllerComponent::{ CallScheduled, CallExecuted, CallSalt, CallCancelled, MinDelayChanged @@ -21,18 +31,10 @@ use openzeppelin_governance::timelock::interface::{ use openzeppelin_governance::timelock::{PROPOSER_ROLE, EXECUTOR_ROLE, CANCELLER_ROLE}; use openzeppelin_introspection::interface::ISRC5_ID; use openzeppelin_introspection::src5::SRC5Component::SRC5Impl; -use openzeppelin_governance::tests::mocks::timelock_mocks::MockContract; -use openzeppelin_governance::tests::mocks::timelock_mocks::{ - IMockContractDispatcher, IMockContractDispatcherTrait -}; -use openzeppelin_governance::tests::mocks::timelock_mocks::{ - ITimelockAttackerDispatcher, ITimelockAttackerDispatcherTrait -}; -use openzeppelin_governance::tests::mocks::timelock_mocks::{TimelockControllerMock, TimelockAttackerMock}; +use openzeppelin_utils::serde::SerializedAppend; +use openzeppelin_utils::test_utils as utils; use openzeppelin_utils::test_utils::constants::{ADMIN, ZERO, OTHER, SALT, FELT_VALUE as VALUE}; use openzeppelin_utils::test_utils::events::EventSpyExt; -use openzeppelin_utils::test_utils as utils; -use openzeppelin_utils::serde::SerializedAppend; use snforge_std::EventSpy; use snforge_std::{ spy_events, test_address, start_cheat_caller_address, cheat_caller_address, From 72bd08a18b5fa17e641a61c7bacc42255f20bc7f Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 1 Aug 2024 15:23:17 +0200 Subject: [PATCH 41/45] refactor: remove unused files --- src/governance.cairo | 2 -- src/tests.cairo | 21 --------------------- 2 files changed, 23 deletions(-) delete mode 100644 src/governance.cairo delete mode 100644 src/tests.cairo diff --git a/src/governance.cairo b/src/governance.cairo deleted file mode 100644 index 01d740d38..000000000 --- a/src/governance.cairo +++ /dev/null @@ -1,2 +0,0 @@ -pub mod timelock; -pub mod utils; diff --git a/src/tests.cairo b/src/tests.cairo deleted file mode 100644 index 6a1d8a06a..000000000 --- a/src/tests.cairo +++ /dev/null @@ -1,21 +0,0 @@ -#[cfg(test)] -mod access; -#[cfg(test)] -mod account; -#[cfg(test)] -mod cryptography; -#[cfg(test)] -mod governance; -#[cfg(test)] -mod introspection; -mod mocks; -#[cfg(test)] -mod presets; -#[cfg(test)] -mod security; -#[cfg(test)] -mod token; -#[cfg(test)] -mod upgrades; - -pub mod utils; From 44492c746b278a839bab1cd8329dd8d06132f4a2 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 1 Aug 2024 18:35:46 +0200 Subject: [PATCH 42/45] fix: workflow --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b23c28c55..96812a2af 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,6 +2,8 @@ name: Lint and test on: pull_request: + branches: + - main push: branches: - main From 97b4cac4abb71a8884e69ddc5f8b510ff1753c50 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 1 Aug 2024 21:02:24 +0200 Subject: [PATCH 43/45] refactor: remove warnings --- CHANGELOG.md | 1 + Scarb.lock | 3 --- Scarb.toml | 6 +++--- packages/presets/src/tests/test_erc20.cairo | 10 +++++----- packages/token/src/erc20/erc20.cairo | 4 ++-- packages/token/src/tests/erc20/test_erc20.cairo | 16 ++++++++-------- .../src/tests/erc20/test_erc20_votes.cairo | 14 +++++++------- packages/utils/src/structs/checkpoint.cairo | 17 ++++++++--------- src/tests/presets/test_erc20.cairo | 10 +++++----- 9 files changed, 39 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 761e3baa6..e2b941d27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bump scarb to v2.7.0-rc.1 (#1025) - Bump scarb to v2.7.0-rc.2 (#1052) - Bump scarb to v2.7.0-rc.4 (#1064) +- Bump scarb to v2.7.0 (#1065) ## 0.15.0-rc.0 (2024-07-8) diff --git a/Scarb.lock b/Scarb.lock index 74a9e18e8..11da63c54 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -5,7 +5,6 @@ version = 1 name = "openzeppelin" version = "0.15.0-rc.0" dependencies = [ -<<<<<<< HEAD "openzeppelin_access", "openzeppelin_account", "openzeppelin_governance", @@ -96,8 +95,6 @@ dependencies = [ name = "openzeppelin_utils" version = "0.15.0-rc.0" dependencies = [ -======= ->>>>>>> 8561d75fab0c8e1acfcf7a37d290db368ed6a01b "snforge_std", ] diff --git a/Scarb.toml b/Scarb.toml index 9ac8ca001..4025a6503 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -18,8 +18,8 @@ version.workspace = true [workspace.package] version = "0.15.0-rc.0" edition = "2023_11" -cairo-version = "2.7.0-rc.3" -scarb-version = "2.7.0-rc.4" +cairo-version = "2.7.0" +scarb-version = "2.7.0" authors = ["OpenZeppelin Community "] description = "OpenZeppelin Contracts written in Cairo for StarkNet, a decentralized ZK Rollup" documentation = "https://docs.openzeppelin.com/contracts-cairo" @@ -36,7 +36,7 @@ keywords = [ ] [workspace.dependencies] -starknet = "2.7.0-rc.3" +starknet = "2.7.0" snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.26.0" } [dependencies] diff --git a/packages/presets/src/tests/test_erc20.cairo b/packages/presets/src/tests/test_erc20.cairo index 367a6fd31..4b95a39c8 100644 --- a/packages/presets/src/tests/test_erc20.cairo +++ b/packages/presets/src/tests/test_erc20.cairo @@ -1,4 +1,4 @@ -use core::integer::BoundedInt; +use core::num::traits::Bounded; use core::num::traits::Zero; use openzeppelin_access::tests::common::OwnableSpyHelpers; use openzeppelin_presets::interfaces::erc20::{ @@ -206,13 +206,13 @@ fn test_transfer_from_doesnt_consume_infinite_allowance() { let (_, mut dispatcher) = setup_dispatcher(); start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), BoundedInt::max()); + dispatcher.approve(SPENDER(), Bounded::MAX); start_cheat_caller_address(dispatcher.contract_address, SPENDER()); dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); let allowance = dispatcher.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, BoundedInt::max(), "Should not decrease"); + assert_eq!(allowance, Bounded::MAX, "Should not decrease"); } #[test] @@ -269,13 +269,13 @@ fn test_transferFrom() { fn test_transferFrom_doesnt_consume_infinite_allowance() { let (_, mut dispatcher) = setup_dispatcher(); start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), BoundedInt::max()); + dispatcher.approve(SPENDER(), Bounded::MAX); start_cheat_caller_address(dispatcher.contract_address, SPENDER()); dispatcher.transferFrom(OWNER(), RECIPIENT(), VALUE); let allowance = dispatcher.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, BoundedInt::max(), "Should not decrease"); + assert_eq!(allowance, Bounded::MAX, "Should not decrease"); } #[test] diff --git a/packages/token/src/erc20/erc20.cairo b/packages/token/src/erc20/erc20.cairo index 0ebb6a9c8..005697b61 100644 --- a/packages/token/src/erc20/erc20.cairo +++ b/packages/token/src/erc20/erc20.cairo @@ -14,7 +14,7 @@ use starknet::ContractAddress; /// for examples. #[starknet::component] pub mod ERC20Component { - use core::integer::BoundedInt; + use core::num::traits::Bounded; use core::num::traits::Zero; use openzeppelin_token::erc20::interface; use starknet::ContractAddress; @@ -427,7 +427,7 @@ pub mod ERC20Component { amount: u256 ) { let current_allowance = self.ERC20_allowances.read((owner, spender)); - if current_allowance != BoundedInt::max() { + if current_allowance != Bounded::MAX { assert(current_allowance >= amount, Errors::INSUFFICIENT_ALLOWANCE); self._approve(owner, spender, current_allowance - amount); } diff --git a/packages/token/src/tests/erc20/test_erc20.cairo b/packages/token/src/tests/erc20/test_erc20.cairo index b87c72e8b..4e1fb023d 100644 --- a/packages/token/src/tests/erc20/test_erc20.cairo +++ b/packages/token/src/tests/erc20/test_erc20.cairo @@ -1,4 +1,4 @@ -use core::integer::BoundedInt; +use core::num::traits::Bounded; use openzeppelin_token::erc20::ERC20Component::{Approval, Transfer}; use openzeppelin_token::erc20::ERC20Component::{ERC20CamelOnlyImpl, ERC20Impl}; use openzeppelin_token::erc20::ERC20Component::{ERC20MetadataImpl, InternalImpl}; @@ -264,13 +264,13 @@ fn test_transfer_from() { fn test_transfer_from_doesnt_consume_infinite_allowance() { let mut state = setup(); start_cheat_caller_address(test_address(), OWNER()); - state.approve(SPENDER(), BoundedInt::max()); + state.approve(SPENDER(), Bounded::MAX); start_cheat_caller_address(test_address(), SPENDER()); state.transfer_from(OWNER(), RECIPIENT(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, BoundedInt::max()); + assert_eq!(allowance, Bounded::MAX); } #[test] @@ -331,13 +331,13 @@ fn test_transferFrom() { fn test_transferFrom_doesnt_consume_infinite_allowance() { let mut state = setup(); start_cheat_caller_address(test_address(), OWNER()); - state.approve(SPENDER(), BoundedInt::max()); + state.approve(SPENDER(), Bounded::MAX); start_cheat_caller_address(test_address(), SPENDER()); state.transferFrom(OWNER(), RECIPIENT(), VALUE); let allowance = state.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, BoundedInt::max()); + assert_eq!(allowance, Bounded::MAX); } #[test] @@ -393,13 +393,13 @@ fn test__spend_allowance_not_unlimited() { #[test] fn test__spend_allowance_unlimited() { let mut state = setup(); - state._approve(OWNER(), SPENDER(), BoundedInt::max()); + state._approve(OWNER(), SPENDER(), Bounded::MAX); - let max_minus_one: u256 = BoundedInt::max() - 1; + let max_minus_one: u256 = Bounded::MAX - 1; state._spend_allowance(OWNER(), SPENDER(), max_minus_one); let allowance = state.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, BoundedInt::max()); + assert_eq!(allowance, Bounded::MAX); } // diff --git a/packages/token/src/tests/erc20/test_erc20_votes.cairo b/packages/token/src/tests/erc20/test_erc20_votes.cairo index ec4c64e95..3a60cb2d7 100644 --- a/packages/token/src/tests/erc20/test_erc20_votes.cairo +++ b/packages/token/src/tests/erc20/test_erc20_votes.cairo @@ -1,4 +1,4 @@ -use core::integer::BoundedInt; +use core::num::traits::Bounded; use core::num::traits::Zero; use openzeppelin_token::erc20::ERC20Component::InternalImpl as ERC20Impl; use openzeppelin_token::erc20::extensions::ERC20VotesComponent::{ @@ -101,9 +101,9 @@ fn test_get_past_votes() { trace.push('ts3', 0x333); // Big numbers (high different from 0x0) - let big1: u256 = BoundedInt::::max().into() + 0x444; - let big2: u256 = BoundedInt::::max().into() + 0x666; - let big3: u256 = BoundedInt::::max().into() + 0x888; + let big1: u256 = Bounded::::MAX.into() + 0x444; + let big2: u256 = Bounded::::MAX.into() + 0x666; + let big3: u256 = Bounded::::MAX.into() + 0x888; trace.push('ts4', big1); trace.push('ts6', big2); trace.push('ts8', big3); @@ -135,9 +135,9 @@ fn test_get_past_total_supply() { trace.push('ts3', 0x333); // Big numbers (high different from 0x0) - let big1: u256 = BoundedInt::::max().into() + 0x444; - let big2: u256 = BoundedInt::::max().into() + 0x666; - let big3: u256 = BoundedInt::::max().into() + 0x888; + let big1: u256 = Bounded::::MAX.into() + 0x444; + let big2: u256 = Bounded::::MAX.into() + 0x666; + let big3: u256 = Bounded::::MAX.into() + 0x888; trace.push('ts4', big1); trace.push('ts6', big2); trace.push('ts8', big3); diff --git a/packages/utils/src/structs/checkpoint.cairo b/packages/utils/src/structs/checkpoint.cairo index caff302b4..d18eb7d83 100644 --- a/packages/utils/src/structs/checkpoint.cairo +++ b/packages/utils/src/structs/checkpoint.cairo @@ -198,7 +198,7 @@ impl CheckpointStorePacking of StorePacking { #[cfg(test)] mod test { - use core::integer::BoundedInt; + use core::num::traits::Bounded; use super::Checkpoint; use super::CheckpointStorePacking; use super::_2_POW_184; @@ -208,15 +208,15 @@ mod test { #[test] fn test_pack_big_key_and_value() { - let key = BoundedInt::max(); - let value = BoundedInt::max(); + let key = Bounded::MAX; + let value = Bounded::MAX; let checkpoint = Checkpoint { key, value }; let (key_and_low, high) = CheckpointStorePacking::pack(checkpoint); let expected_key: u256 = (key_and_low.into() / _2_POW_184.into()) & KEY_MASK; let expected_low: u256 = key_and_low.into() & LOW_MASK; - let expected_high: felt252 = BoundedInt::::max().into(); + let expected_high: felt252 = Bounded::::MAX.into(); assert_eq!(key.into(), expected_key); assert_eq!(value.low.into(), expected_low); @@ -225,14 +225,13 @@ mod test { #[test] fn test_unpack_big_key_and_value() { - let key_and_low = BoundedInt::::max().into() * _2_POW_184 - + BoundedInt::::max().into(); - let high = BoundedInt::::max().into(); + let key_and_low = Bounded::::MAX.into() * _2_POW_184 + Bounded::::MAX.into(); + let high = Bounded::::MAX.into(); let checkpoint = CheckpointStorePacking::unpack((key_and_low, high)); - let expected_key: u64 = BoundedInt::max(); - let expected_value: u256 = BoundedInt::max(); + let expected_key: u64 = Bounded::MAX; + let expected_value: u256 = Bounded::MAX; assert_eq!(checkpoint.key, expected_key); assert_eq!(checkpoint.value, expected_value); diff --git a/src/tests/presets/test_erc20.cairo b/src/tests/presets/test_erc20.cairo index 5630256d9..0ab311b6e 100644 --- a/src/tests/presets/test_erc20.cairo +++ b/src/tests/presets/test_erc20.cairo @@ -1,4 +1,4 @@ -use core::integer::BoundedInt; +use core::num::traits::Bounded; use core::num::traits::Zero; use openzeppelin::presets::interfaces::erc20::{ ERC20UpgradeableABISafeDispatcher, ERC20UpgradeableABISafeDispatcherTrait @@ -206,13 +206,13 @@ fn test_transfer_from_doesnt_consume_infinite_allowance() { let (_, mut dispatcher) = setup_dispatcher(); start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), BoundedInt::max()); + dispatcher.approve(SPENDER(), Bounded::MAX); start_cheat_caller_address(dispatcher.contract_address, SPENDER()); dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); let allowance = dispatcher.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, BoundedInt::max(), "Should not decrease"); + assert_eq!(allowance, Bounded::MAX, "Should not decrease"); } #[test] @@ -269,13 +269,13 @@ fn test_transferFrom() { fn test_transferFrom_doesnt_consume_infinite_allowance() { let (_, mut dispatcher) = setup_dispatcher(); start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), BoundedInt::max()); + dispatcher.approve(SPENDER(), Bounded::MAX); start_cheat_caller_address(dispatcher.contract_address, SPENDER()); dispatcher.transferFrom(OWNER(), RECIPIENT(), VALUE); let allowance = dispatcher.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, BoundedInt::max(), "Should not decrease"); + assert_eq!(allowance, Bounded::MAX, "Should not decrease"); } #[test] From d58c75189f734807193e5141a3647af20e920460 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Thu, 1 Aug 2024 21:04:35 +0200 Subject: [PATCH 44/45] feat: remove old tests --- src/tests.cairo | 21 - src/tests/access/common.cairo | 32 - src/tests/account/ethereum/common.cairo | 97 --- .../ethereum/test_dual_eth_account.cairo | 237 -------- src/tests/account/starknet/common.cairo | 74 --- src/tests/account/starknet/test_account.cairo | 531 ---------------- .../account/starknet/test_dual_account.cairo | 221 ------- src/tests/presets/test_account.cairo | 572 ------------------ src/tests/presets/test_erc20.cairo | 506 ---------------- .../presets/test_universal_deployer.cairo | 140 ----- src/tests/security/test_pausable.cairo | 154 ----- src/tests/token/erc1155/common.cairo | 129 ---- src/tests/token/erc20/common.cairo | 52 -- src/tests/token/erc721.cairo | 6 - src/tests/token/erc721/common.cairo | 76 --- src/tests/upgrades/common.cairo | 20 - src/tests/upgrades/test_upgradeable.cairo | 83 --- src/tests/utils.cairo | 15 - src/tests/utils/common.cairo | 58 -- src/tests/utils/constants.cairo | 148 ----- src/tests/utils/deployment.cairo | 48 -- src/tests/utils/events.cairo | 62 -- src/tests/utils/signing.cairo | 31 - 23 files changed, 3313 deletions(-) delete mode 100644 src/tests.cairo delete mode 100644 src/tests/access/common.cairo delete mode 100644 src/tests/account/ethereum/common.cairo delete mode 100644 src/tests/account/ethereum/test_dual_eth_account.cairo delete mode 100644 src/tests/account/starknet/common.cairo delete mode 100644 src/tests/account/starknet/test_account.cairo delete mode 100644 src/tests/account/starknet/test_dual_account.cairo delete mode 100644 src/tests/presets/test_account.cairo delete mode 100644 src/tests/presets/test_erc20.cairo delete mode 100644 src/tests/presets/test_universal_deployer.cairo delete mode 100644 src/tests/security/test_pausable.cairo delete mode 100644 src/tests/token/erc1155/common.cairo delete mode 100644 src/tests/token/erc20/common.cairo delete mode 100644 src/tests/token/erc721.cairo delete mode 100644 src/tests/token/erc721/common.cairo delete mode 100644 src/tests/upgrades/common.cairo delete mode 100644 src/tests/upgrades/test_upgradeable.cairo delete mode 100644 src/tests/utils.cairo delete mode 100644 src/tests/utils/common.cairo delete mode 100644 src/tests/utils/constants.cairo delete mode 100644 src/tests/utils/deployment.cairo delete mode 100644 src/tests/utils/events.cairo delete mode 100644 src/tests/utils/signing.cairo diff --git a/src/tests.cairo b/src/tests.cairo deleted file mode 100644 index 6a1d8a06a..000000000 --- a/src/tests.cairo +++ /dev/null @@ -1,21 +0,0 @@ -#[cfg(test)] -mod access; -#[cfg(test)] -mod account; -#[cfg(test)] -mod cryptography; -#[cfg(test)] -mod governance; -#[cfg(test)] -mod introspection; -mod mocks; -#[cfg(test)] -mod presets; -#[cfg(test)] -mod security; -#[cfg(test)] -mod token; -#[cfg(test)] -mod upgrades; - -pub mod utils; diff --git a/src/tests/access/common.cairo b/src/tests/access/common.cairo deleted file mode 100644 index 6836a3437..000000000 --- a/src/tests/access/common.cairo +++ /dev/null @@ -1,32 +0,0 @@ -use openzeppelin::access::ownable::OwnableComponent::OwnershipTransferred; -use openzeppelin::access::ownable::OwnableComponent; -use openzeppelin::tests::utils::EventSpyExt; -use openzeppelin::tests::utils; -use openzeppelin::utils::serde::SerializedAppend; -use snforge_std::EventSpy; -use starknet::ContractAddress; - -#[generate_trait] -pub(crate) impl OwnableSpyHelpersImpl of OwnableSpyHelpers { - fn assert_only_event_ownership_transferred( - ref self: EventSpy, - contract: ContractAddress, - previous_owner: ContractAddress, - new_owner: ContractAddress - ) { - self.assert_event_ownership_transferred(contract, previous_owner, new_owner); - self.assert_no_events_left_from(contract); - } - - fn assert_event_ownership_transferred( - ref self: EventSpy, - contract: ContractAddress, - previous_owner: ContractAddress, - new_owner: ContractAddress - ) { - let expected = OwnableComponent::Event::OwnershipTransferred( - OwnershipTransferred { previous_owner, new_owner } - ); - self.assert_emitted_single(contract, expected); - } -} diff --git a/src/tests/account/ethereum/common.cairo b/src/tests/account/ethereum/common.cairo deleted file mode 100644 index 58f9a809f..000000000 --- a/src/tests/account/ethereum/common.cairo +++ /dev/null @@ -1,97 +0,0 @@ -use core::hash::{HashStateTrait, HashStateExTrait}; -use core::poseidon::PoseidonTrait; -use core::poseidon::poseidon_hash_span; -use core::starknet::secp256_trait::Secp256PointTrait; -use openzeppelin::account::EthAccountComponent::{OwnerAdded, OwnerRemoved}; -use openzeppelin::account::EthAccountComponent; -use openzeppelin::account::interface::EthPublicKey; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin::tests::utils::constants::TRANSACTION_HASH; -use openzeppelin::tests::utils::constants::{NAME, SYMBOL}; -use openzeppelin::tests::utils::events::EventSpyExt; -use openzeppelin::tests::utils::signing::{Secp256k1KeyPair, Secp256k1KeyPairExt}; -use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin::utils::serde::SerializedAppend; -use snforge_std::EventSpy; -use snforge_std::signature::secp256k1_curve::Secp256k1CurveSignerImpl; -use starknet::{ContractAddress, SyscallResultTrait}; - -#[derive(Drop)] -pub(crate) struct SignedTransactionData { - pub(crate) private_key: u256, - pub(crate) public_key: EthPublicKey, - pub(crate) tx_hash: felt252, - pub(crate) signature: EthSignature -} - -pub(crate) fn SIGNED_TX_DATA(key_pair: Secp256k1KeyPair) -> SignedTransactionData { - let tx_hash = TRANSACTION_HASH; - let (r, s) = key_pair.sign(tx_hash.into()).unwrap(); - SignedTransactionData { - private_key: key_pair.secret_key, - public_key: key_pair.public_key, - tx_hash, - signature: EthSignature { r, s } - } -} - -pub(crate) fn get_accept_ownership_signature( - account_address: ContractAddress, current_owner: EthPublicKey, new_key_pair: Secp256k1KeyPair -) -> Span { - let msg_hash: u256 = PoseidonTrait::new() - .update_with('StarkNet Message') - .update_with('accept_ownership') - .update_with(account_address) - .update_with(current_owner.get_coordinates().unwrap_syscall()) - .finalize() - .into(); - - new_key_pair.serialized_sign(msg_hash).span() -} - -pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { - let mut calldata = array![]; - - calldata.append_serde(NAME()); - calldata.append_serde(SYMBOL()); - calldata.append_serde(initial_supply); - calldata.append_serde(recipient); - - let address = utils::declare_and_deploy("DualCaseERC20Mock", calldata); - IERC20Dispatcher { contract_address: address } -} - - -#[generate_trait] -pub(crate) impl EthAccountSpyHelpersImpl of EthAccountSpyHelpers { - fn assert_event_owner_removed( - ref self: EventSpy, contract: ContractAddress, public_key: EthPublicKey - ) { - let removed_owner_guid = get_guid_from_public_key(public_key); - let expected = EthAccountComponent::Event::OwnerRemoved( - OwnerRemoved { removed_owner_guid } - ); - self.assert_emitted_single(contract, expected); - } - - fn assert_event_owner_added( - ref self: EventSpy, contract: ContractAddress, public_key: EthPublicKey - ) { - let new_owner_guid = get_guid_from_public_key(public_key); - let expected = EthAccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_owner_added( - ref self: EventSpy, contract: ContractAddress, public_key: EthPublicKey - ) { - self.assert_event_owner_added(contract, public_key); - self.assert_no_events_left_from(contract); - } -} - -fn get_guid_from_public_key(public_key: EthPublicKey) -> felt252 { - let (x, y) = public_key.get_coordinates().unwrap_syscall(); - poseidon_hash_span(array![x.low.into(), x.high.into(), y.low.into(), y.high.into()].span()) -} diff --git a/src/tests/account/ethereum/test_dual_eth_account.cairo b/src/tests/account/ethereum/test_dual_eth_account.cairo deleted file mode 100644 index bde5c53f5..000000000 --- a/src/tests/account/ethereum/test_dual_eth_account.cairo +++ /dev/null @@ -1,237 +0,0 @@ -use openzeppelin::account::dual_eth_account::{DualCaseEthAccountABI, DualCaseEthAccount}; -use openzeppelin::account::interface::{EthAccountABIDispatcherTrait, EthAccountABIDispatcher}; -use openzeppelin::account::utils::secp256k1::{DebugSecp256k1Point, Secp256k1PointPartialEq}; -use openzeppelin::account::utils::signature::EthSignature; -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::tests::utils::constants::secp256k1::KEY_PAIR; -use openzeppelin::tests::utils::constants::{ETH_PUBKEY, NEW_ETH_PUBKEY, TRANSACTION_HASH}; -use openzeppelin::tests::utils::signing::Secp256k1KeyPairExt; -use openzeppelin::tests::utils; -use openzeppelin::utils::serde::SerializedAppend; -use snforge_std::start_cheat_caller_address; - -use super::common::get_accept_ownership_signature; - -// -// Setup -// - -fn setup_snake() -> (DualCaseEthAccount, EthAccountABIDispatcher) { - let mut calldata = array![]; - calldata.append_serde(ETH_PUBKEY()); - - let target = utils::declare_and_deploy("SnakeEthAccountMock", calldata); - ( - DualCaseEthAccount { contract_address: target }, - EthAccountABIDispatcher { contract_address: target } - ) -} - -fn setup_camel() -> (DualCaseEthAccount, EthAccountABIDispatcher) { - let mut calldata = array![]; - calldata.append_serde(ETH_PUBKEY()); - - let target = utils::declare_and_deploy("CamelEthAccountMock", calldata); - ( - DualCaseEthAccount { contract_address: target }, - EthAccountABIDispatcher { contract_address: target } - ) -} - -fn setup_non_account() -> DualCaseEthAccount { - let calldata = array![]; - let target = utils::declare_and_deploy("NonImplementingMock", calldata); - DualCaseEthAccount { contract_address: target } -} - -fn setup_account_panic() -> (DualCaseEthAccount, DualCaseEthAccount) { - let snake_target = utils::declare_and_deploy("SnakeEthAccountPanicMock", array![]); - let camel_target = utils::declare_and_deploy("CamelEthAccountPanicMock", array![]); - ( - DualCaseEthAccount { contract_address: snake_target }, - DualCaseEthAccount { contract_address: camel_target } - ) -} - -// -// snake_case target -// - -#[test] -fn test_dual_set_public_key() { - let (snake_dispatcher, target) = setup_snake(); - let contract_address = snake_dispatcher.contract_address; - - start_cheat_caller_address(contract_address, contract_address); - - let key_pair = KEY_PAIR(); - let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); - - snake_dispatcher.set_public_key(key_pair.public_key, signature); - assert_eq!(target.get_public_key(), key_pair.public_key); -} - -#[test] -#[ignore] // REASON: should_panic attribute not fit for complex panic messages. -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_set_public_key() { - let dispatcher = setup_non_account(); - dispatcher.set_public_key(NEW_ETH_PUBKEY(), array![].span()); -} - -#[test] -#[should_panic(expected: ("Some error",))] -fn test_dual_set_public_key_exists_and_panics() { - let (dispatcher, _) = setup_account_panic(); - dispatcher.set_public_key(NEW_ETH_PUBKEY(), array![].span()); -} - -#[test] -fn test_dual_get_public_key() { - let (snake_dispatcher, _) = setup_snake(); - assert_eq!(snake_dispatcher.get_public_key(), ETH_PUBKEY()); -} - -#[test] -#[ignore] // REASON: should_panic attribute not fit for complex panic messages. -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_get_public_key() { - let dispatcher = setup_non_account(); - dispatcher.get_public_key(); -} - -#[test] -#[should_panic(expected: ("Some error",))] -fn test_dual_get_public_key_exists_and_panics() { - let (dispatcher, _) = setup_account_panic(); - dispatcher.get_public_key(); -} - -#[test] -fn test_dual_is_valid_signature() { - let (snake_dispatcher, target) = setup_snake(); - let contract_address = snake_dispatcher.contract_address; - - start_cheat_caller_address(contract_address, contract_address); - let key_pair = KEY_PAIR(); - let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); - - target.set_public_key(key_pair.public_key, signature); - let serialized_signature = key_pair.serialized_sign(TRANSACTION_HASH.into()); - - let is_valid = snake_dispatcher.is_valid_signature(TRANSACTION_HASH, serialized_signature); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -#[ignore] // REASON: should_panic attribute not fit for complex panic messages. -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_is_valid_signature() { - let hash = 0x0; - let signature = array![]; - - let dispatcher = setup_non_account(); - dispatcher.is_valid_signature(hash, signature); -} - -#[test] -#[should_panic(expected: ("Some error",))] -fn test_dual_is_valid_signature_exists_and_panics() { - let hash = 0x0; - let signature = array![]; - - let (dispatcher, _) = setup_account_panic(); - dispatcher.is_valid_signature(hash, signature); -} - -#[test] -fn test_dual_supports_interface() { - let (snake_dispatcher, _) = setup_snake(); - assert!(snake_dispatcher.supports_interface(ISRC5_ID), "Should implement ISRC5"); -} - -#[test] -#[ignore] // REASON: should_panic attribute not fit for complex panic messages. -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_supports_interface() { - let dispatcher = setup_non_account(); - dispatcher.supports_interface(ISRC5_ID); -} - -#[test] -#[should_panic(expected: ("Some error",))] -fn test_dual_supports_interface_exists_and_panics() { - let (dispatcher, _) = setup_account_panic(); - dispatcher.supports_interface(ISRC5_ID); -} - -// -// camelCase target -// - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -fn test_dual_setPublicKey() { - let (camel_dispatcher, target) = setup_camel(); - let contract_address = camel_dispatcher.contract_address; - - start_cheat_caller_address(contract_address, contract_address); - - let key_pair = KEY_PAIR(); - let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); - - camel_dispatcher.set_public_key(key_pair.public_key, signature); - assert_eq!(target.getPublicKey(), key_pair.public_key); -} - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -#[should_panic(expected: ("Some error",))] -fn test_dual_setPublicKey_exists_and_panics() { - let (_, dispatcher) = setup_account_panic(); - dispatcher.set_public_key(NEW_ETH_PUBKEY(), array![].span()); -} - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -fn test_dual_getPublicKey() { - let (camel_dispatcher, _) = setup_camel(); - assert_eq!(camel_dispatcher.get_public_key(), ETH_PUBKEY()); -} - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -#[should_panic(expected: ("Some error",))] -fn test_dual_getPublicKey_exists_and_panics() { - let (_, dispatcher) = setup_account_panic(); - dispatcher.get_public_key(); -} - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -fn test_dual_isValidSignature() { - let (camel_dispatcher, target) = setup_camel(); - let contract_address = camel_dispatcher.contract_address; - - start_cheat_caller_address(contract_address, contract_address); - - let key_pair = KEY_PAIR(); - let signature = get_accept_ownership_signature(contract_address, ETH_PUBKEY(), key_pair); - - target.setPublicKey(key_pair.public_key, signature); - let serialized_signature = key_pair.serialized_sign(TRANSACTION_HASH.into()); - - let is_valid = camel_dispatcher.is_valid_signature(TRANSACTION_HASH, serialized_signature); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -#[should_panic(expected: ("Some error",))] -fn test_dual_isValidSignature_exists_and_panics() { - let hash = 0x0; - let signature = array![]; - - let (_, dispatcher) = setup_account_panic(); - dispatcher.is_valid_signature(hash, signature); -} diff --git a/src/tests/account/starknet/common.cairo b/src/tests/account/starknet/common.cairo deleted file mode 100644 index 26554ba33..000000000 --- a/src/tests/account/starknet/common.cairo +++ /dev/null @@ -1,74 +0,0 @@ -use core::hash::{HashStateTrait, HashStateExTrait}; -use core::poseidon::PoseidonTrait; -use openzeppelin::account::AccountComponent::{OwnerAdded, OwnerRemoved}; -use openzeppelin::account::AccountComponent; -use openzeppelin::tests::utils::constants::{NAME, SYMBOL, TRANSACTION_HASH}; -use openzeppelin::tests::utils::events::EventSpyExt; -use openzeppelin::tests::utils::signing::StarkKeyPair; -use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::IERC20Dispatcher; -use openzeppelin::utils::serde::SerializedAppend; -use snforge_std::EventSpy; -use snforge_std::signature::stark_curve::StarkCurveSignerImpl; -use starknet::ContractAddress; - -#[derive(Drop)] -pub(crate) struct SignedTransactionData { - pub(crate) tx_hash: felt252, - pub(crate) r: felt252, - pub(crate) s: felt252 -} - -pub(crate) fn SIGNED_TX_DATA(key_pair: StarkKeyPair) -> SignedTransactionData { - let tx_hash = TRANSACTION_HASH; - let (r, s) = key_pair.sign(tx_hash).unwrap(); - SignedTransactionData { tx_hash, r, s } -} - -pub(crate) fn deploy_erc20(recipient: ContractAddress, initial_supply: u256) -> IERC20Dispatcher { - let mut calldata = array![]; - calldata.append_serde(NAME()); - calldata.append_serde(SYMBOL()); - calldata.append_serde(initial_supply); - calldata.append_serde(recipient); - - let address = utils::declare_and_deploy("DualCaseERC20Mock", calldata); - IERC20Dispatcher { contract_address: address } -} - -pub(crate) fn get_accept_ownership_signature( - account_address: ContractAddress, current_public_key: felt252, new_key_pair: StarkKeyPair -) -> Span { - let msg_hash = PoseidonTrait::new() - .update_with('StarkNet Message') - .update_with('accept_ownership') - .update_with(account_address) - .update_with(current_public_key) - .finalize(); - let (sig_r, sig_s) = new_key_pair.sign(msg_hash).unwrap(); - array![sig_r, sig_s].span() -} - -#[generate_trait] -pub(crate) impl AccountSpyHelpersImpl of AccountSpyHelpers { - fn assert_event_owner_removed( - ref self: EventSpy, contract: ContractAddress, removed_owner_guid: felt252 - ) { - let expected = AccountComponent::Event::OwnerRemoved(OwnerRemoved { removed_owner_guid }); - self.assert_emitted_single(contract, expected); - } - - fn assert_event_owner_added( - ref self: EventSpy, contract: ContractAddress, new_owner_guid: felt252 - ) { - let expected = AccountComponent::Event::OwnerAdded(OwnerAdded { new_owner_guid }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_owner_added( - ref self: EventSpy, contract: ContractAddress, new_owner_guid: felt252 - ) { - self.assert_event_owner_added(contract, new_owner_guid); - self.assert_no_events_left_from(contract); - } -} diff --git a/src/tests/account/starknet/test_account.cairo b/src/tests/account/starknet/test_account.cairo deleted file mode 100644 index 7bfa8e377..000000000 --- a/src/tests/account/starknet/test_account.cairo +++ /dev/null @@ -1,531 +0,0 @@ -use core::num::traits::Zero; -use core::starknet::SyscallResultTrait; -use openzeppelin::account::AccountComponent::{InternalTrait, SRC6CamelOnlyImpl}; -use openzeppelin::account::AccountComponent::{PublicKeyCamelImpl, PublicKeyImpl}; -use openzeppelin::account::AccountComponent; -use openzeppelin::account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; -use openzeppelin::account::interface::{ISRC6, ISRC6_ID}; -use openzeppelin::introspection::interface::{ISRC5, ISRC5_ID}; -use openzeppelin::tests::mocks::account_mocks::DualCaseAccountMock; -use openzeppelin::tests::utils::constants::stark::{KEY_PAIR, KEY_PAIR_2}; -use openzeppelin::tests::utils::constants::{ - SALT, ZERO, OTHER, CALLER, RECIPIENT, QUERY_OFFSET, QUERY_VERSION, MIN_TRANSACTION_VERSION -}; -use openzeppelin::tests::utils::signing::StarkKeyPair; -use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use snforge_std::{ - cheat_signature_global, cheat_transaction_version_global, cheat_transaction_hash_global -}; -use snforge_std::{spy_events, declare, test_address, start_cheat_caller_address}; -use starknet::account::Call; -use starknet::{contract_address_const, ContractAddress, ClassHash}; - -use super::common::{AccountSpyHelpers, SignedTransactionData}; -use super::common::{deploy_erc20, SIGNED_TX_DATA, get_accept_ownership_signature}; - -// -// Setup -// - -type ComponentState = AccountComponent::ComponentState; - -fn CONTRACT_STATE() -> DualCaseAccountMock::ContractState { - DualCaseAccountMock::contract_state_for_testing() -} - -fn COMPONENT_STATE() -> ComponentState { - AccountComponent::component_state_for_testing() -} - -fn setup(key_pair: StarkKeyPair) -> ComponentState { - let mut state = COMPONENT_STATE(); - state.initializer(key_pair.public_key); - state -} - -fn setup_dispatcher( - key_pair: StarkKeyPair, data: SignedTransactionData -) -> (AccountABIDispatcher, felt252) { - let contract_class = declare("DualCaseAccountMock").unwrap_syscall(); - let calldata = array![key_pair.public_key]; - let address = utils::deploy(contract_class, calldata); - let dispatcher = AccountABIDispatcher { contract_address: address }; - - cheat_signature_global(array![data.r, data.s].span()); - cheat_transaction_hash_global(data.tx_hash); - cheat_transaction_version_global(MIN_TRANSACTION_VERSION); - start_cheat_caller_address(address, ZERO()); - - (dispatcher, contract_class.class_hash.into()) -} - -// -// is_valid_signature & isValidSignature -// - -#[test] -fn test_is_valid_signature() { - let mut state = COMPONENT_STATE(); - let key_pair = KEY_PAIR(); - let data = SIGNED_TX_DATA(key_pair); - - state._set_public_key(key_pair.public_key); - - let good_signature = array![data.r, data.s]; - let is_valid = state.is_valid_signature(data.tx_hash, good_signature); - assert_eq!(is_valid, starknet::VALIDATED); - - let bad_signature = array!['BAD', 'SIGNATURE']; - let is_valid = state.is_valid_signature(data.tx_hash, bad_signature); - assert!(is_valid.is_zero(), "Should reject invalid signature"); -} - -#[test] -fn test_isValidSignature() { - let mut state = COMPONENT_STATE(); - let key_pair = KEY_PAIR(); - let data = SIGNED_TX_DATA(key_pair); - - state._set_public_key(key_pair.public_key); - - let good_signature = array![data.r, data.s]; - let is_valid = state.isValidSignature(data.tx_hash, good_signature); - assert_eq!(is_valid, starknet::VALIDATED); - - let bad_signature = array!['BAD', 'SIGNATURE']; - let is_valid = state.isValidSignature(data.tx_hash, bad_signature); - assert!(is_valid.is_zero(), "Should reject invalid signature"); -} - -// -// Entry points -// - -#[test] -fn test_validate_deploy() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); - - // `__validate_deploy__` does not directly use the passed arguments. Their - // values are already integrated in the tx hash. The passed arguments in this - // testing context are decoupled from the signature and have no effect on the test. - let is_valid = account.__validate_deploy__(class_hash, SALT, key_pair.public_key); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_deploy_invalid_signature_data() { - let key_pair = KEY_PAIR(); - let mut data = SIGNED_TX_DATA(key_pair); - data.tx_hash += 1; - let (account, class_hash) = setup_dispatcher(key_pair, data); - - account.__validate_deploy__(class_hash, SALT, key_pair.public_key); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_deploy_invalid_signature_length() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); - let invalid_len_sig = array!['INVALID_LEN_SIG']; - cheat_signature_global(invalid_len_sig.span()); - - account.__validate_deploy__(class_hash, SALT, key_pair.public_key); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_deploy_empty_signature() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); - let empty_sig = array![]; - - cheat_signature_global(empty_sig.span()); - account.__validate_deploy__(class_hash, SALT, key_pair.public_key); -} - -#[test] -fn test_validate_declare() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); - - // `__validate_declare__` does not directly use the class_hash argument. Its - // value is already integrated in the tx hash. The class_hash argument in this - // testing context is decoupled from the signature and has no effect on the test. - let is_valid = account.__validate_declare__(class_hash); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_declare_invalid_signature_data() { - let key_pair = KEY_PAIR(); - let mut data = SIGNED_TX_DATA(key_pair); - data.tx_hash += 1; - let (account, class_hash) = setup_dispatcher(key_pair, data); - - account.__validate_declare__(class_hash); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_declare_invalid_signature_length() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); - let invalid_len_sig = array!['INVALID_LEN_SIG']; - cheat_signature_global(invalid_len_sig.span()); - - account.__validate_declare__(class_hash); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_declare_empty_signature() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); - let empty_sig = array![]; - cheat_signature_global(empty_sig.span()); - - account.__validate_declare__(class_hash); -} - -fn test_execute_with_version(version: Option) { - let key_pair = KEY_PAIR(); - let (account, _) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); - let erc20 = deploy_erc20(account.contract_address, 1000); - let recipient = RECIPIENT(); - - // Craft call and add to calls array - let mut calldata = array![]; - let amount: u256 = 200; - calldata.append_serde(recipient); - calldata.append_serde(amount); - let call = Call { - to: erc20.contract_address, selector: selectors::transfer, calldata: calldata.span() - }; - let calls = array![call]; - - // Handle version for test - if let Option::Some(version) = version { - cheat_transaction_version_global(version); - } - - // Execute - let ret = account.__execute__(calls); - - // Assert that the transfer was successful - assert_eq!(erc20.balance_of(account.contract_address), 800, "Should have remainder"); - assert_eq!(erc20.balance_of(recipient), amount, "Should have transferred"); - - // Test return value - let mut call_serialized_retval = *ret.at(0); - let call_retval = Serde::::deserialize(ref call_serialized_retval); - assert!(call_retval.unwrap()); -} - -#[test] -fn test_execute() { - test_execute_with_version(Option::None); -} - -#[test] -fn test_execute_future_version() { - test_execute_with_version(Option::Some(MIN_TRANSACTION_VERSION + 1)); -} - -#[test] -fn test_execute_query_version() { - test_execute_with_version(Option::Some(QUERY_VERSION)); -} - -#[test] -#[should_panic(expected: ('Account: invalid tx version',))] -fn test_execute_invalid_query_version() { - test_execute_with_version(Option::Some(QUERY_OFFSET)); -} - -#[test] -fn test_execute_future_query_version() { - test_execute_with_version(Option::Some(QUERY_VERSION + 1)); -} - -#[test] -#[should_panic(expected: ('Account: invalid tx version',))] -fn test_execute_invalid_version() { - test_execute_with_version(Option::Some(MIN_TRANSACTION_VERSION - 1)); -} - -#[test] -fn test_validate() { - let key_pair = KEY_PAIR(); - let (account, _) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); - let calls = array![]; - - let is_valid = account.__validate__(calls); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_invalid() { - let key_pair = KEY_PAIR(); - let mut data = SIGNED_TX_DATA(key_pair); - data.tx_hash += 1; - let (account, _) = setup_dispatcher(key_pair, data); - let calls = array![]; - - account.__validate__(calls); -} - -#[test] -fn test_multicall() { - let key_pair = KEY_PAIR(); - let (account, _) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); - let erc20 = deploy_erc20(account.contract_address, 1000); - let recipient1 = RECIPIENT(); - let recipient2 = OTHER(); - - // Craft call1 - let mut calldata1 = array![]; - let amount1: u256 = 300; - calldata1.append_serde(recipient1); - calldata1.append_serde(amount1); - let call1 = Call { - to: erc20.contract_address, selector: selectors::transfer, calldata: calldata1.span() - }; - - // Craft call2 - let mut calldata2 = array![]; - let amount2: u256 = 500; - calldata2.append_serde(recipient2); - calldata2.append_serde(amount2); - let call2 = Call { - to: erc20.contract_address, selector: selectors::transfer, calldata: calldata2.span() - }; - - // Bundle calls and execute - let calls = array![call1, call2]; - let ret = account.__execute__(calls); - - // Assert that the transfers were successful - assert_eq!(erc20.balance_of(account.contract_address), 200, "Should have remainder"); - assert_eq!(erc20.balance_of(recipient1), 300, "Should have transferred from call1"); - assert_eq!(erc20.balance_of(recipient2), 500, "Should have transferred from call2"); - - // Test return values - let mut call1_serialized_retval = *ret.at(0); - let mut call2_serialized_retval = *ret.at(1); - - let call1_retval = Serde::::deserialize(ref call1_serialized_retval); - assert!(call1_retval.unwrap()); - - let call2_retval = Serde::::deserialize(ref call2_serialized_retval); - assert!(call2_retval.unwrap()); -} - -#[test] -fn test_multicall_zero_calls() { - let key_pair = KEY_PAIR(); - let (account, _) = setup_dispatcher(key_pair, SIGNED_TX_DATA(key_pair)); - let calls = array![]; - - let response = account.__execute__(calls); - assert!(response.is_empty()); -} - -#[test] -#[should_panic(expected: ('Account: invalid caller',))] -fn test_account_called_from_contract() { - let state = setup(KEY_PAIR()); - let account_address = test_address(); - let calls = array![]; - - start_cheat_caller_address(account_address, CALLER()); - - state.__execute__(calls); -} - -// -// set_public_key & get_public_key -// - -#[test] -fn test_public_key_setter_and_getter() { - let mut state = COMPONENT_STATE(); - let account_address = test_address(); - let key_pair = KEY_PAIR(); - let new_key_pair = KEY_PAIR_2(); - start_cheat_caller_address(account_address, account_address); - - state._set_public_key(key_pair.public_key); - assert_eq!(state.get_public_key(), key_pair.public_key); - - // Set key - let mut spy = spy_events(); - let signature = get_accept_ownership_signature( - account_address, key_pair.public_key, new_key_pair - ); - state.set_public_key(new_key_pair.public_key, signature); - - spy.assert_event_owner_removed(account_address, key_pair.public_key); - spy.assert_only_event_owner_added(account_address, new_key_pair.public_key); - - assert_eq!(state.get_public_key(), new_key_pair.public_key); -} - -#[test] -#[should_panic(expected: ('Account: unauthorized',))] -fn test_public_key_setter_different_account() { - let mut state = COMPONENT_STATE(); - let account_address = test_address(); - let new_public_key = KEY_PAIR_2().public_key; - start_cheat_caller_address(account_address, CALLER()); - - state.set_public_key(new_public_key, array![].span()); -} - -// -// setPublicKey & getPublicKey -// - -#[test] -fn test_public_key_setter_and_getter_camel() { - let mut state = COMPONENT_STATE(); - let account_address = test_address(); - let key_pair = KEY_PAIR(); - let new_key_pair = KEY_PAIR_2(); - start_cheat_caller_address(account_address, account_address); - - state._set_public_key(key_pair.public_key); - assert_eq!(state.getPublicKey(), key_pair.public_key); - - // Set key - let mut spy = spy_events(); - let signature = get_accept_ownership_signature( - account_address, key_pair.public_key, new_key_pair - ); - state.setPublicKey(new_key_pair.public_key, signature); - - spy.assert_event_owner_removed(account_address, key_pair.public_key); - spy.assert_only_event_owner_added(account_address, new_key_pair.public_key); - - assert_eq!(state.getPublicKey(), new_key_pair.public_key); -} - -#[test] -#[should_panic(expected: ('Account: unauthorized',))] -fn test_public_key_setter_different_account_camel() { - let mut state = COMPONENT_STATE(); - let account_address = test_address(); - let new_public_key = KEY_PAIR_2().public_key; - start_cheat_caller_address(account_address, CALLER()); - - state.setPublicKey(new_public_key, array![].span()); -} - -// -// Test internals -// - -#[test] -fn test_initializer() { - let mut state = COMPONENT_STATE(); - let mock_state = CONTRACT_STATE(); - let account_address = test_address(); - let public_key = KEY_PAIR().public_key; - let mut spy = spy_events(); - - state.initializer(public_key); - spy.assert_only_event_owner_added(account_address, public_key); - - assert_eq!(state.get_public_key(), public_key); - - let supports_isrc5 = mock_state.supports_interface(ISRC5_ID); - assert!(supports_isrc5); - - let supports_isrc6 = mock_state.supports_interface(ISRC6_ID); - assert!(supports_isrc6); -} - -#[test] -fn test_assert_only_self_true() { - let mut state = COMPONENT_STATE(); - let account_address = test_address(); - start_cheat_caller_address(account_address, account_address); - - state.assert_only_self(); -} - -#[test] -#[should_panic(expected: ('Account: unauthorized',))] -fn test_assert_only_self_false() { - let mut state = COMPONENT_STATE(); - let account_address = test_address(); - start_cheat_caller_address(account_address, OTHER()); - - state.assert_only_self(); -} - -#[test] -fn test_assert_valid_new_owner() { - let key_pair = KEY_PAIR(); - let state = setup(key_pair); - let account_address = test_address(); - - let new_key_pair = KEY_PAIR_2(); - let signature = get_accept_ownership_signature( - account_address, key_pair.public_key, new_key_pair - ); - - state.assert_valid_new_owner(key_pair.public_key, new_key_pair.public_key, signature); -} - - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_assert_valid_new_owner_invalid_signature() { - let key_pair = KEY_PAIR(); - let state = setup(key_pair); - - let new_key_pair = KEY_PAIR_2(); - let bad_signature = array!['BAD', 'SIGNATURE']; - - state - .assert_valid_new_owner(key_pair.public_key, new_key_pair.public_key, bad_signature.span()); -} - -#[test] -fn test__is_valid_signature() { - let mut state = COMPONENT_STATE(); - let key_pair = KEY_PAIR(); - let data = SIGNED_TX_DATA(key_pair); - - state._set_public_key(key_pair.public_key); - - let good_signature = array![data.r, data.s]; - assert!(state._is_valid_signature(data.tx_hash, good_signature.span())); - - let bad_signature = array!['BAD', 'SIGNATURE']; - assert!(!state._is_valid_signature(data.tx_hash, bad_signature.span())); - - let invalid_length_signature = array!['SINGLE_ELEMENT']; - assert!(!state._is_valid_signature(data.tx_hash, invalid_length_signature.span())); -} - -#[test] -fn test__set_public_key() { - let mut state = COMPONENT_STATE(); - let mut spy = spy_events(); - let public_key = KEY_PAIR().public_key; - let account_address = test_address(); - - state._set_public_key(public_key); - - spy.assert_only_event_owner_added(account_address, public_key); - assert_eq!(state.get_public_key(), public_key); -} diff --git a/src/tests/account/starknet/test_dual_account.cairo b/src/tests/account/starknet/test_dual_account.cairo deleted file mode 100644 index ab0887896..000000000 --- a/src/tests/account/starknet/test_dual_account.cairo +++ /dev/null @@ -1,221 +0,0 @@ -use openzeppelin::account::dual_account::{DualCaseAccountABI, DualCaseAccount}; -use openzeppelin::account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher}; -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::tests::account::starknet::common::SIGNED_TX_DATA; -use openzeppelin::tests::utils::constants::TRANSACTION_HASH; -use openzeppelin::tests::utils::constants::stark::{KEY_PAIR, KEY_PAIR_2}; -use openzeppelin::tests::utils::signing::{StarkKeyPair, StarkKeyPairExt}; -use openzeppelin::tests::utils; -use snforge_std::{declare, start_cheat_caller_address}; - -use super::common::get_accept_ownership_signature; - -// -// Setup -// - -fn setup_snake(key_pair: StarkKeyPair) -> (DualCaseAccount, AccountABIDispatcher) { - let calldata = array![key_pair.public_key]; - let contract_address = utils::declare_and_deploy("SnakeAccountMock", calldata); - (DualCaseAccount { contract_address }, AccountABIDispatcher { contract_address }) -} - -fn setup_camel(key_pair: StarkKeyPair) -> (DualCaseAccount, AccountABIDispatcher) { - let calldata = array![key_pair.public_key]; - let contract_address = utils::declare_and_deploy("CamelAccountMock", calldata); - (DualCaseAccount { contract_address }, AccountABIDispatcher { contract_address }) -} - -fn setup_non_account() -> DualCaseAccount { - let calldata = array![]; - let contract_address = utils::declare_and_deploy("NonImplementingMock", calldata); - DualCaseAccount { contract_address } -} - -fn setup_account_panic() -> (DualCaseAccount, DualCaseAccount) { - let snake_target = utils::declare_and_deploy("SnakeAccountPanicMock", array![]); - let camel_target = utils::declare_and_deploy("CamelAccountPanicMock", array![]); - ( - DualCaseAccount { contract_address: snake_target }, - DualCaseAccount { contract_address: camel_target } - ) -} - -// -// snake_case target -// - -#[test] -fn test_dual_set_public_key() { - let key_pair = KEY_PAIR(); - let (snake_dispatcher, target) = setup_snake(key_pair); - let new_key_pair = KEY_PAIR_2(); - let signature = get_accept_ownership_signature( - snake_dispatcher.contract_address, key_pair.public_key, new_key_pair - ); - start_cheat_caller_address(target.contract_address, target.contract_address); - - snake_dispatcher.set_public_key(new_key_pair.public_key, signature); - - assert_eq!(target.get_public_key(), new_key_pair.public_key); -} - -#[test] -#[ignore] // REASON: should_panic attribute not fit for complex panic messages. -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_set_public_key() { - let dispatcher = setup_non_account(); - let new_public_key = KEY_PAIR_2().public_key; - dispatcher.set_public_key(new_public_key, array![].span()); -} - -#[test] -#[should_panic(expected: ("Some error",))] -fn test_dual_set_public_key_exists_and_panics() { - let (snake_dispatcher, _) = setup_account_panic(); - let new_public_key = KEY_PAIR_2().public_key; - snake_dispatcher.set_public_key(new_public_key, array![].span()); -} - -#[test] -fn test_dual_get_public_key() { - let key_pair = KEY_PAIR(); - let (snake_dispatcher, _) = setup_snake(key_pair); - let expected_public_key = key_pair.public_key; - assert_eq!(snake_dispatcher.get_public_key(), expected_public_key); -} - -#[test] -#[ignore] // REASON: should_panic attribute not fit for complex panic messages. -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_get_public_key() { - let dispatcher = setup_non_account(); - dispatcher.get_public_key(); -} - -#[test] -#[should_panic(expected: ("Some error",))] -fn test_dual_get_public_key_exists_and_panics() { - let (snake_dispatcher, _) = setup_account_panic(); - snake_dispatcher.get_public_key(); -} - -#[test] -fn test_dual_is_valid_signature() { - let key_pair = KEY_PAIR(); - let (snake_dispatcher, _) = setup_snake(key_pair); - let tx_hash = TRANSACTION_HASH; - let serialized_signature = key_pair.serialized_sign(tx_hash); - - let is_valid = snake_dispatcher.is_valid_signature(tx_hash, serialized_signature); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -#[ignore] // REASON: should_panic attribute not fit for complex panic messages. -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_is_valid_signature() { - let signature = array![]; - - let dispatcher = setup_non_account(); - dispatcher.is_valid_signature(TRANSACTION_HASH, signature); -} - -#[test] -#[should_panic(expected: ("Some error",))] -fn test_dual_is_valid_signature_exists_and_panics() { - let signature = array![]; - let (snake_dispatcher, _) = setup_account_panic(); - - snake_dispatcher.is_valid_signature(TRANSACTION_HASH, signature); -} - -#[test] -fn test_dual_supports_interface() { - let (snake_dispatcher, _) = setup_snake(KEY_PAIR()); - let supports_isrc5 = snake_dispatcher.supports_interface(ISRC5_ID); - assert!(supports_isrc5); -} - -#[test] -#[ignore] // REASON: should_panic attribute not fit for complex panic messages. -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_dual_no_supports_interface() { - let dispatcher = setup_non_account(); - dispatcher.supports_interface(ISRC5_ID); -} - -#[test] -#[should_panic(expected: ("Some error",))] -fn test_dual_supports_interface_exists_and_panics() { - let (snake_dispatcher, _) = setup_account_panic(); - snake_dispatcher.supports_interface(ISRC5_ID); -} - -// -// camelCase target -// - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -fn test_dual_setPublicKey() { - let key_pair = KEY_PAIR(); - let (camel_dispatcher, target) = setup_camel(key_pair); - let new_key_pair = KEY_PAIR_2(); - let signature = get_accept_ownership_signature( - camel_dispatcher.contract_address, key_pair.public_key, new_key_pair - ); - start_cheat_caller_address(target.contract_address, target.contract_address); - - camel_dispatcher.set_public_key(new_key_pair.public_key, signature); - - assert_eq!(target.getPublicKey(), new_key_pair.public_key); -} - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -#[should_panic(expected: ("Some error",))] -fn test_dual_setPublicKey_exists_and_panics() { - let (_, camel_dispatcher) = setup_account_panic(); - let new_public_key = KEY_PAIR_2().public_key; - camel_dispatcher.set_public_key(new_public_key, array![].span()); -} - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -fn test_dual_getPublicKey() { - let key_pair = KEY_PAIR(); - let (camel_dispatcher, _) = setup_camel(key_pair); - let expected_public_key = key_pair.public_key; - assert_eq!(camel_dispatcher.get_public_key(), expected_public_key); -} - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -#[should_panic(expected: ("Some error",))] -fn test_dual_getPublicKey_exists_and_panics() { - let (_, camel_dispatcher) = setup_account_panic(); - camel_dispatcher.get_public_key(); -} - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -fn test_dual_isValidSignature() { - let key_pair = KEY_PAIR(); - let (camel_dispatcher, _) = setup_camel(key_pair); - let tx_hash = TRANSACTION_HASH; - let serialized_signature = key_pair.serialized_sign(tx_hash); - - let is_valid = camel_dispatcher.is_valid_signature(tx_hash, serialized_signature); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -#[ignore] // REASON: foundry entrypoint_not_found error message inconsistent with mainnet. -#[should_panic(expected: ("Some error",))] -fn test_dual_isValidSignature_exists_and_panics() { - let signature = array![]; - - let (_, camel_dispatcher) = setup_account_panic(); - camel_dispatcher.is_valid_signature(TRANSACTION_HASH, signature); -} diff --git a/src/tests/presets/test_account.cairo b/src/tests/presets/test_account.cairo deleted file mode 100644 index 3aaf59543..000000000 --- a/src/tests/presets/test_account.cairo +++ /dev/null @@ -1,572 +0,0 @@ -use core::num::traits::Zero; -use openzeppelin::account::interface::ISRC6_ID; -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::presets::AccountUpgradeable; -use openzeppelin::presets::interfaces::account::{ - AccountUpgradeableABISafeDispatcher, AccountUpgradeableABISafeDispatcherTrait -}; -use openzeppelin::presets::interfaces::{ - AccountUpgradeableABIDispatcher, AccountUpgradeableABIDispatcherTrait -}; -use openzeppelin::tests::account::starknet::common::{ - get_accept_ownership_signature, deploy_erc20, SIGNED_TX_DATA, -}; -use openzeppelin::tests::account::starknet::common::{AccountSpyHelpers, SignedTransactionData}; -use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; -use openzeppelin::tests::utils::constants::stark::{KEY_PAIR, KEY_PAIR_2}; -use openzeppelin::tests::utils::constants::{ - SALT, QUERY_OFFSET, QUERY_VERSION, MIN_TRANSACTION_VERSION -}; -use openzeppelin::tests::utils::constants::{ZERO, CALLER, RECIPIENT, OTHER, CLASS_HASH_ZERO}; -use openzeppelin::tests::utils::signing::{StarkKeyPair, StarkKeyPairExt}; -use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; -use openzeppelin::utils::selectors; -use openzeppelin::utils::serde::SerializedAppend; -use snforge_std::{ - cheat_signature_global, cheat_transaction_version_global, cheat_transaction_hash_global -}; -use snforge_std::{spy_events, test_address, start_cheat_caller_address}; -use starknet::account::Call; -use starknet::{ContractAddress, ClassHash}; - -// -// Setup -// - -fn declare_v2_class() -> ClassHash { - utils::declare_class("SnakeAccountMock").class_hash -} - -fn setup_dispatcher(key_pair: StarkKeyPair) -> (ContractAddress, AccountUpgradeableABIDispatcher) { - let calldata = array![key_pair.public_key]; - let account_address = utils::declare_and_deploy("AccountUpgradeable", calldata); - let dispatcher = AccountUpgradeableABIDispatcher { contract_address: account_address }; - - (account_address, dispatcher) -} - -fn setup_dispatcher_with_data( - key_pair: StarkKeyPair, data: SignedTransactionData -) -> (AccountUpgradeableABIDispatcher, felt252) { - let account_class = utils::declare_class("AccountUpgradeable"); - let calldata = array![key_pair.public_key]; - let contract_address = utils::deploy(account_class, calldata); - let account_dispatcher = AccountUpgradeableABIDispatcher { contract_address }; - - cheat_signature_global(array![data.r, data.s].span()); - cheat_transaction_hash_global(data.tx_hash); - cheat_transaction_version_global(MIN_TRANSACTION_VERSION); - start_cheat_caller_address(contract_address, ZERO()); - - (account_dispatcher, account_class.class_hash.into()) -} - -// -// constructor -// - -#[test] -fn test_constructor() { - let mut state = AccountUpgradeable::contract_state_for_testing(); - let mut spy = spy_events(); - let key_pair = KEY_PAIR(); - let account_address = test_address(); - AccountUpgradeable::constructor(ref state, key_pair.public_key); - - spy.assert_only_event_owner_added(account_address, key_pair.public_key); - - let public_key = AccountUpgradeable::AccountMixinImpl::get_public_key(@state); - assert_eq!(public_key, key_pair.public_key); - - let supports_isrc5 = AccountUpgradeable::AccountMixinImpl::supports_interface(@state, ISRC5_ID); - assert!(supports_isrc5); - - let supports_isrc6 = AccountUpgradeable::AccountMixinImpl::supports_interface(@state, ISRC6_ID); - assert!(supports_isrc6); -} - -// -// set_public_key & setPublicKey -// - -#[test] -fn test_public_key_setter_and_getter() { - let key_pair = KEY_PAIR(); - let (account_address, dispatcher) = setup_dispatcher(key_pair); - let mut spy = spy_events(); - - let new_key_pair = KEY_PAIR_2(); - let signature = get_accept_ownership_signature( - account_address, key_pair.public_key, new_key_pair - ); - start_cheat_caller_address(account_address, account_address); - dispatcher.set_public_key(new_key_pair.public_key, signature); - - assert_eq!(dispatcher.get_public_key(), new_key_pair.public_key); - - spy.assert_event_owner_removed(dispatcher.contract_address, key_pair.public_key); - spy.assert_only_event_owner_added(dispatcher.contract_address, new_key_pair.public_key); -} - -#[test] -fn test_public_key_setter_and_getter_camel() { - let key_pair = KEY_PAIR(); - let (account_address, dispatcher) = setup_dispatcher(key_pair); - let mut spy = spy_events(); - - let new_key_pair = KEY_PAIR_2(); - let signature = get_accept_ownership_signature( - account_address, key_pair.public_key, new_key_pair - ); - start_cheat_caller_address(account_address, account_address); - dispatcher.setPublicKey(new_key_pair.public_key, signature); - - assert_eq!(dispatcher.getPublicKey(), new_key_pair.public_key); - - spy.assert_event_owner_removed(dispatcher.contract_address, key_pair.public_key); - spy.assert_only_event_owner_added(dispatcher.contract_address, new_key_pair.public_key); -} - -#[test] -#[should_panic(expected: ('Account: unauthorized',))] -fn test_set_public_key_different_account() { - let key_pair = KEY_PAIR(); - let (account_address, dispatcher) = setup_dispatcher(key_pair); - - let new_key_pair = KEY_PAIR_2(); - let signature = get_accept_ownership_signature( - account_address, key_pair.public_key, new_key_pair - ); - dispatcher.set_public_key(new_key_pair.public_key, signature); -} - -#[test] -#[should_panic(expected: ('Account: unauthorized',))] -fn test_setPublicKey_different_account() { - let key_pair = KEY_PAIR(); - let (account_address, dispatcher) = setup_dispatcher(key_pair); - - let new_key_pair = KEY_PAIR_2(); - let signature = get_accept_ownership_signature( - account_address, key_pair.public_key, new_key_pair - ); - dispatcher.setPublicKey(new_key_pair.public_key, signature); -} - -// -// is_valid_signature & isValidSignature -// - -fn is_valid_sig_dispatcher() -> (AccountUpgradeableABIDispatcher, felt252, Array) { - let key_pair = KEY_PAIR(); - let (_, dispatcher) = setup_dispatcher(key_pair); - - let data = SIGNED_TX_DATA(key_pair); - let signature = array![data.r, data.s]; - (dispatcher, data.tx_hash, signature) -} - -#[test] -fn test_is_valid_signature() { - let (dispatcher, hash, signature) = is_valid_sig_dispatcher(); - - let is_valid = dispatcher.is_valid_signature(hash, signature); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -fn test_is_valid_signature_bad_sig() { - let (dispatcher, tx_hash, _) = is_valid_sig_dispatcher(); - let bad_signature = array!['BAD', 'SIG']; - - let is_valid = dispatcher.is_valid_signature(tx_hash, bad_signature); - assert!(is_valid.is_zero(), "Should reject invalid signature"); -} - -#[test] -fn test_is_valid_signature_invalid_len_sig() { - let (dispatcher, tx_hash, _) = is_valid_sig_dispatcher(); - let invalid_len_sig = array!['INVALID_LEN']; - - let is_valid = dispatcher.is_valid_signature(tx_hash, invalid_len_sig); - assert!(is_valid.is_zero(), "Should reject signature of invalid length"); -} - -#[test] -fn test_isValidSignature() { - let (dispatcher, tx_hash, signature) = is_valid_sig_dispatcher(); - - let is_valid = dispatcher.isValidSignature(tx_hash, signature); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -fn test_isValidSignature_bad_sig() { - let (dispatcher, tx_hash, _) = is_valid_sig_dispatcher(); - let bad_signature = array!['BAD', 'SIG']; - - let is_valid = dispatcher.isValidSignature(tx_hash, bad_signature); - assert!(is_valid.is_zero(), "Should reject invalid signature"); -} - -#[test] -fn test_isValidSignature_invalid_len_sig() { - let (dispatcher, tx_hash, _) = is_valid_sig_dispatcher(); - let invalid_len_sig = array!['INVALID_LEN']; - - let is_valid = dispatcher.isValidSignature(tx_hash, invalid_len_sig); - assert!(is_valid.is_zero(), "Should reject signature of invalid length"); -} - -// -// supports_interface -// - -#[test] -fn test_supports_interface() { - let key_pair = KEY_PAIR(); - let (_, dispatcher) = setup_dispatcher(key_pair); - - let supports_isrc5 = dispatcher.supports_interface(ISRC5_ID); - assert!(supports_isrc5); - - let supports_isrc6 = dispatcher.supports_interface(ISRC6_ID); - assert!(supports_isrc6); - - let doesnt_support_0x123 = !dispatcher.supports_interface('DUMMY_INTERFACE_ID'); - assert!(doesnt_support_0x123); -} - -// -// Entry points -// - -#[test] -fn test_validate_deploy() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - - // `__validate_deploy__` does not directly use the passed arguments. Their - // values are already integrated in the tx hash. The passed arguments in this - // testing context are decoupled from the signature and have no effect on the test. - let is_valid = account.__validate_deploy__(class_hash, SALT, key_pair.public_key); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_deploy_invalid_signature_data() { - let key_pair = KEY_PAIR(); - let mut data = SIGNED_TX_DATA(key_pair); - data.tx_hash += 1; - let (account, class_hash) = setup_dispatcher_with_data(key_pair, data); - - account.__validate_deploy__(class_hash, SALT, key_pair.public_key); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_deploy_invalid_signature_length() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - - let invalid_len_sig = array!['INVALID_LEN']; - cheat_signature_global(invalid_len_sig.span()); - - account.__validate_deploy__(class_hash, SALT, key_pair.public_key); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_deploy_empty_signature() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - - let empty_sig = array![]; - cheat_signature_global(empty_sig.span()); - - account.__validate_deploy__(class_hash, SALT, key_pair.public_key); -} - -#[test] -fn test_validate_declare() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - - // `__validate_declare__` does not directly use the class_hash argument. Its - // value is already integrated in the tx hash. The class_hash argument in this - // testing context is decoupled from the signature and has no effect on the test. - let is_valid = account.__validate_declare__(class_hash); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_declare_invalid_signature_data() { - let key_pair = KEY_PAIR(); - let mut data = SIGNED_TX_DATA(key_pair); - data.tx_hash += 1; - let (account, class_hash) = setup_dispatcher_with_data(key_pair, data); - - account.__validate_declare__(class_hash); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_declare_invalid_signature_length() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - - let invalid_len_sig = array!['INVALID_LEN']; - cheat_signature_global(invalid_len_sig.span()); - - account.__validate_declare__(class_hash); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_declare_empty_signature() { - let key_pair = KEY_PAIR(); - let (account, class_hash) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - - let empty_sig = array![]; - cheat_signature_global(empty_sig.span()); - - account.__validate_declare__(class_hash); -} - -fn test_execute_with_version(version: Option) { - let key_pair = KEY_PAIR(); - let data = SIGNED_TX_DATA(key_pair); - let (account, _) = setup_dispatcher_with_data(key_pair, data); - let erc20 = deploy_erc20(account.contract_address, 1000); - - // Craft call and add to calls array - let amount: u256 = 200; - - let recipient = RECIPIENT(); - let mut calldata = array![]; - calldata.append_serde(recipient); - calldata.append_serde(amount); - - let call = Call { - to: erc20.contract_address, selector: selectors::transfer, calldata: calldata.span() - }; - let calls = array![call]; - - // Handle version for test - if let Option::Some(version) = version { - cheat_transaction_version_global(version) - } - - // Execute - let ret = account.__execute__(calls); - - // Assert that the transfer was successful - assert_eq!(erc20.balance_of(account.contract_address), 800, "Should have remainder"); - assert_eq!(erc20.balance_of(recipient), amount, "Should have transferred"); - - // Test return value - let mut call_serialized_retval = *ret.at(0); - let call_retval = Serde::::deserialize(ref call_serialized_retval); - assert!(call_retval.unwrap()); -} - -#[test] -fn test_execute() { - test_execute_with_version(Option::None); -} - -#[test] -fn test_execute_future_version() { - test_execute_with_version(Option::Some(MIN_TRANSACTION_VERSION + 1)); -} - -#[test] -fn test_execute_query_version() { - test_execute_with_version(Option::Some(QUERY_VERSION)); -} - -#[test] -#[should_panic(expected: ('Account: invalid tx version',))] -fn test_execute_invalid_query_version() { - test_execute_with_version(Option::Some(QUERY_OFFSET)); -} - -#[test] -fn test_execute_future_query_version() { - test_execute_with_version(Option::Some(QUERY_VERSION + 1)); -} - -#[test] -#[should_panic(expected: ('Account: invalid tx version',))] -fn test_execute_invalid_version() { - test_execute_with_version(Option::Some(MIN_TRANSACTION_VERSION - 1)); -} - -#[test] -fn test_validate() { - let key_pair = KEY_PAIR(); - let (account, _) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - - let calls = array![]; - let is_valid = account.__validate__(calls); - assert_eq!(is_valid, starknet::VALIDATED); -} - -#[test] -#[should_panic(expected: ('Account: invalid signature',))] -fn test_validate_invalid() { - let key_pair = KEY_PAIR(); - let mut data = SIGNED_TX_DATA(key_pair); - data.tx_hash += 1; - let (account, _) = setup_dispatcher_with_data(key_pair, data); - - let calls = array![]; - account.__validate__(calls); -} - -#[test] -fn test_multicall() { - let key_pair = KEY_PAIR(); - let (account, _) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - let erc20 = deploy_erc20(account.contract_address, 1000); - let recipient1 = RECIPIENT(); - let recipient2 = OTHER(); - let mut calls = array![]; - - // Craft call1 - let mut calldata1 = array![]; - let amount1: u256 = 300; - calldata1.append_serde(recipient1); - calldata1.append_serde(amount1); - let call1 = Call { - to: erc20.contract_address, selector: selectors::transfer, calldata: calldata1.span() - }; - - // Craft call2 - let mut calldata2 = array![]; - let amount2: u256 = 500; - calldata2.append_serde(recipient2); - calldata2.append_serde(amount2); - let call2 = Call { - to: erc20.contract_address, selector: selectors::transfer, calldata: calldata2.span() - }; - - // Bundle calls and execute - calls.append(call1); - calls.append(call2); - let ret = account.__execute__(calls); - - // Assert that the transfers were successful - assert_eq!(erc20.balance_of(account.contract_address), 200, "Should have remainder"); - assert_eq!(erc20.balance_of(recipient1), 300, "Should have transferred"); - assert_eq!(erc20.balance_of(recipient2), 500, "Should have transferred"); - - // Test return value - let mut call1_serialized_retval = *ret.at(0); - let mut call2_serialized_retval = *ret.at(1); - - let call1_retval = Serde::::deserialize(ref call1_serialized_retval); - assert!(call1_retval.unwrap()); - - let call2_retval = Serde::::deserialize(ref call2_serialized_retval); - assert!(call2_retval.unwrap()); -} - -#[test] -fn test_multicall_zero_calls() { - let key_pair = KEY_PAIR(); - let (account, _) = setup_dispatcher_with_data(key_pair, SIGNED_TX_DATA(key_pair)); - - let calls = array![]; - let response = account.__execute__(calls); - assert!(response.is_empty()); -} - -#[test] -#[should_panic(expected: ('Account: invalid caller',))] -fn test_account_called_from_contract() { - let key_pair = KEY_PAIR(); - let (account_address, dispatcher) = setup_dispatcher(key_pair); - - let calls = array![]; - start_cheat_caller_address(account_address, CALLER()); - dispatcher.__execute__(calls); -} - -// -// upgrade -// - -#[test] -#[should_panic(expected: ('Account: unauthorized',))] -fn test_upgrade_access_control() { - let key_pair = KEY_PAIR(); - let (_, v1_dispatcher) = setup_dispatcher(key_pair); - - v1_dispatcher.upgrade(CLASS_HASH_ZERO()); -} - -#[test] -#[should_panic(expected: ('Class hash cannot be zero',))] -fn test_upgrade_with_class_hash_zero() { - let key_pair = KEY_PAIR(); - let (account_address, v1_dispatcher) = setup_dispatcher(key_pair); - - start_cheat_caller_address(account_address, account_address); - v1_dispatcher.upgrade(CLASS_HASH_ZERO()); -} - -#[test] -fn test_upgraded_event() { - let key_pair = KEY_PAIR(); - let (account_address, v1_dispatcher) = setup_dispatcher(key_pair); - let mut spy = spy_events(); - - let v2_class_hash = declare_v2_class(); - start_cheat_caller_address(account_address, account_address); - v1_dispatcher.upgrade(v2_class_hash); - - spy.assert_only_event_upgraded(account_address, v2_class_hash); -} - -#[test] -#[feature("safe_dispatcher")] -fn test_v2_missing_camel_selector() { - let key_pair = KEY_PAIR(); - let (account_address, v1_dispatcher) = setup_dispatcher(key_pair); - - let v2_class_hash = declare_v2_class(); - start_cheat_caller_address(account_address, account_address); - v1_dispatcher.upgrade(v2_class_hash); - - let safe_dispatcher = AccountUpgradeableABISafeDispatcher { contract_address: account_address }; - let result = safe_dispatcher.getPublicKey(); - - utils::assert_entrypoint_not_found_error(result, selector!("getPublicKey"), account_address) -} - -#[test] -fn test_state_persists_after_upgrade() { - let key_pair = KEY_PAIR(); - let (account_address, v1_dispatcher) = setup_dispatcher(key_pair); - - let new_key_pair = KEY_PAIR_2(); - let accept_ownership_sig = get_accept_ownership_signature( - account_address, key_pair.public_key, new_key_pair - ); - start_cheat_caller_address(account_address, account_address); - v1_dispatcher.set_public_key(new_key_pair.public_key, accept_ownership_sig); - - let expected_public_key = new_key_pair.public_key; - let camel_public_key = v1_dispatcher.getPublicKey(); - assert_eq!(camel_public_key, expected_public_key); - - let v2_class_hash = declare_v2_class(); - v1_dispatcher.upgrade(v2_class_hash); - let snake_public_key = v1_dispatcher.get_public_key(); - - assert_eq!(snake_public_key, expected_public_key); -} diff --git a/src/tests/presets/test_erc20.cairo b/src/tests/presets/test_erc20.cairo deleted file mode 100644 index 0ab311b6e..000000000 --- a/src/tests/presets/test_erc20.cairo +++ /dev/null @@ -1,506 +0,0 @@ -use core::num::traits::Bounded; -use core::num::traits::Zero; -use openzeppelin::presets::interfaces::erc20::{ - ERC20UpgradeableABISafeDispatcher, ERC20UpgradeableABISafeDispatcherTrait -}; -use openzeppelin::presets::interfaces::{ - ERC20UpgradeableABIDispatcher, ERC20UpgradeableABIDispatcherTrait -}; -use openzeppelin::tests::access::common::OwnableSpyHelpers; -use openzeppelin::tests::token::erc20::common::ERC20SpyHelpers; -use openzeppelin::tests::upgrades::common::UpgradeableSpyHelpers; -use openzeppelin::tests::utils::common::IntoBase16String; -use openzeppelin::tests::utils::constants::{ - ZERO, OWNER, SPENDER, RECIPIENT, OTHER, NAME, SYMBOL, DECIMALS, SUPPLY, VALUE, CLASS_HASH_ZERO -}; -use openzeppelin::tests::utils::events::EventSpyExt; -use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin::utils::serde::SerializedAppend; -use snforge_std::{spy_events, EventSpy, start_cheat_caller_address}; -use starknet::ClassHash; - -fn V2_CLASS_HASH() -> ClassHash { - utils::declare_class("SnakeERC20Mock").class_hash -} - -// -// Setup -// - -fn setup_dispatcher_with_event() -> (EventSpy, ERC20UpgradeableABIDispatcher) { - let mut calldata = array![]; - - calldata.append_serde(NAME()); - calldata.append_serde(SYMBOL()); - calldata.append_serde(SUPPLY); - calldata.append_serde(OWNER()); - calldata.append_serde(OWNER()); - - let spy = spy_events(); - let address = utils::declare_and_deploy("ERC20Upgradeable", calldata); - (spy, ERC20UpgradeableABIDispatcher { contract_address: address }) -} - -fn setup_dispatcher() -> (EventSpy, ERC20UpgradeableABIDispatcher) { - let (mut spy, dispatcher) = setup_dispatcher_with_event(); - spy.drop_all_events(); - (spy, dispatcher) -} - -// -// constructor -// - -#[test] -fn test_constructor() { - let (mut spy, dispatcher) = setup_dispatcher_with_event(); - - assert_eq!(dispatcher.owner(), OWNER()); - spy.assert_event_ownership_transferred(dispatcher.contract_address, ZERO(), OWNER()); - - assert_eq!(dispatcher.name(), NAME()); - assert_eq!(dispatcher.symbol(), SYMBOL()); - assert_eq!(dispatcher.decimals(), DECIMALS); - assert_eq!(dispatcher.total_supply(), SUPPLY); - assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY); - spy.assert_only_event_transfer(dispatcher.contract_address, ZERO(), OWNER(), SUPPLY); -} - -// -// Getters -// - -#[test] -fn test_total_supply() { - let (_, dispatcher) = setup_dispatcher(); - - assert_eq!(dispatcher.total_supply(), SUPPLY); - assert_eq!(dispatcher.totalSupply(), SUPPLY); -} - -#[test] -fn test_balance_of() { - let (_, dispatcher) = setup_dispatcher(); - - assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY); - assert_eq!(dispatcher.balanceOf(OWNER()), SUPPLY); -} - -#[test] -fn test_allowance() { - let (_, mut dispatcher) = setup_dispatcher(); - - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), VALUE); - - let allowance = dispatcher.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, VALUE); -} - -// -// approve -// - -#[test] -fn test_approve() { - let (mut spy, mut dispatcher) = setup_dispatcher(); - let allowance = dispatcher.allowance(OWNER(), SPENDER()); - assert!(allowance.is_zero()); - - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - assert!(dispatcher.approve(SPENDER(), VALUE)); - - let allowance = dispatcher.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, VALUE); - - spy.assert_only_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), VALUE); -} - -#[test] -#[should_panic(expected: ('ERC20: approve from 0',))] -fn test_approve_from_zero() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, ZERO()); - dispatcher.approve(SPENDER(), VALUE); -} - -#[test] -#[should_panic(expected: ('ERC20: approve to 0',))] -fn test_approve_to_zero() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(Zero::zero(), VALUE); -} - -// -// transfer -// - -#[test] -fn test_transfer() { - let (mut spy, mut dispatcher) = setup_dispatcher(); - - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - assert!(dispatcher.transfer(RECIPIENT(), VALUE)); - - assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY - VALUE); - assert_eq!(dispatcher.balance_of(RECIPIENT()), VALUE); - assert_eq!(dispatcher.total_supply(), SUPPLY); - - spy.assert_only_event_transfer(dispatcher.contract_address, OWNER(), RECIPIENT(), VALUE); -} - -#[test] -#[should_panic(expected: ('ERC20: insufficient balance',))] -fn test_transfer_not_enough_balance() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - - let balance_plus_one = SUPPLY + 1; - dispatcher.transfer(RECIPIENT(), balance_plus_one); -} - -#[test] -#[should_panic(expected: ('ERC20: transfer from 0',))] -fn test_transfer_from_zero() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, ZERO()); - dispatcher.transfer(RECIPIENT(), VALUE); -} - -#[test] -#[should_panic(expected: ('ERC20: transfer to 0',))] -fn test_transfer_to_zero() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.transfer(ZERO(), VALUE); -} - -// -// transfer_from & transferFrom -// - -#[test] -fn test_transfer_from() { - let (mut spy, mut dispatcher) = setup_dispatcher(); - - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), VALUE); - spy.drop_event(); - - start_cheat_caller_address(dispatcher.contract_address, SPENDER()); - assert!(dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE)); - - spy.assert_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), 0); - spy.assert_only_event_transfer(dispatcher.contract_address, OWNER(), RECIPIENT(), VALUE); - - assert_eq!(dispatcher.balance_of(RECIPIENT()), VALUE); - assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY - VALUE); - assert_eq!(dispatcher.allowance(OWNER(), SPENDER()), 0); - assert_eq!(dispatcher.total_supply(), SUPPLY); -} - -#[test] -fn test_transfer_from_doesnt_consume_infinite_allowance() { - let (_, mut dispatcher) = setup_dispatcher(); - - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), Bounded::MAX); - - start_cheat_caller_address(dispatcher.contract_address, SPENDER()); - dispatcher.transfer_from(OWNER(), RECIPIENT(), VALUE); - - let allowance = dispatcher.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, Bounded::MAX, "Should not decrease"); -} - -#[test] -#[should_panic(expected: ('ERC20: insufficient allowance',))] -fn test_transfer_from_greater_than_allowance() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), VALUE); - - start_cheat_caller_address(dispatcher.contract_address, SPENDER()); - let allowance_plus_one = VALUE + 1; - dispatcher.transfer_from(OWNER(), RECIPIENT(), allowance_plus_one); -} - -#[test] -#[should_panic(expected: ('ERC20: transfer to 0',))] -fn test_transfer_from_to_zero_address() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), VALUE); - - start_cheat_caller_address(dispatcher.contract_address, SPENDER()); - dispatcher.transfer_from(OWNER(), Zero::zero(), VALUE); -} - -#[test] -#[should_panic(expected: ('ERC20: insufficient allowance',))] -fn test_transfer_from_from_zero_address() { - let (_, mut dispatcher) = setup_dispatcher(); - dispatcher.transfer_from(Zero::zero(), RECIPIENT(), VALUE); -} - -#[test] -fn test_transferFrom() { - let (mut spy, mut dispatcher) = setup_dispatcher(); - - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), VALUE); - spy.drop_event(); - - start_cheat_caller_address(dispatcher.contract_address, SPENDER()); - assert!(dispatcher.transferFrom(OWNER(), RECIPIENT(), VALUE)); - - spy.assert_event_approval(dispatcher.contract_address, OWNER(), SPENDER(), 0); - spy.assert_only_event_transfer(dispatcher.contract_address, OWNER(), RECIPIENT(), VALUE); - - assert_eq!(dispatcher.balance_of(RECIPIENT()), VALUE); - assert_eq!(dispatcher.balance_of(OWNER()), SUPPLY - VALUE); - assert_eq!(dispatcher.allowance(OWNER(), SPENDER()), 0); - assert_eq!(dispatcher.total_supply(), SUPPLY); -} - -#[test] -fn test_transferFrom_doesnt_consume_infinite_allowance() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), Bounded::MAX); - - start_cheat_caller_address(dispatcher.contract_address, SPENDER()); - dispatcher.transferFrom(OWNER(), RECIPIENT(), VALUE); - - let allowance = dispatcher.allowance(OWNER(), SPENDER()); - assert_eq!(allowance, Bounded::MAX, "Should not decrease"); -} - -#[test] -#[should_panic(expected: ('ERC20: insufficient allowance',))] -fn test_transferFrom_greater_than_allowance() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), VALUE); - - start_cheat_caller_address(dispatcher.contract_address, SPENDER()); - let allowance_plus_one = VALUE + 1; - dispatcher.transferFrom(OWNER(), RECIPIENT(), allowance_plus_one); -} - -#[test] -#[should_panic(expected: ('ERC20: transfer to 0',))] -fn test_transferFrom_to_zero_address() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.approve(SPENDER(), VALUE); - - start_cheat_caller_address(dispatcher.contract_address, SPENDER()); - dispatcher.transferFrom(OWNER(), Zero::zero(), VALUE); -} - -#[test] -#[should_panic(expected: ('ERC20: insufficient allowance',))] -fn test_transferFrom_from_zero_address() { - let (_, mut dispatcher) = setup_dispatcher(); - dispatcher.transferFrom(Zero::zero(), RECIPIENT(), VALUE); -} - -// -// transfer_ownership & transferOwnership -// - -#[test] -fn test_transfer_ownership() { - let (mut spy, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.transfer_ownership(OTHER()); - - spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), OTHER()); - assert_eq!(dispatcher.owner(), OTHER()); -} - -#[test] -#[should_panic(expected: ('New owner is the zero address',))] -fn test_transfer_ownership_to_zero() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.transfer_ownership(ZERO()); -} - -#[test] -#[should_panic(expected: ('Caller is the zero address',))] -fn test_transfer_ownership_from_zero() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, ZERO()); - dispatcher.transfer_ownership(OTHER()); -} - -#[test] -#[should_panic(expected: ('Caller is not the owner',))] -fn test_transfer_ownership_from_nonowner() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OTHER()); - dispatcher.transfer_ownership(OTHER()); -} - -#[test] -fn test_transferOwnership() { - let (mut spy, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.transferOwnership(OTHER()); - - spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), OTHER()); - assert_eq!(dispatcher.owner(), OTHER()); -} - -#[test] -#[should_panic(expected: ('New owner is the zero address',))] -fn test_transferOwnership_to_zero() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.transferOwnership(ZERO()); -} - -#[test] -#[should_panic(expected: ('Caller is the zero address',))] -fn test_transferOwnership_from_zero() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, ZERO()); - dispatcher.transferOwnership(OTHER()); -} - -#[test] -#[should_panic(expected: ('Caller is not the owner',))] -fn test_transferOwnership_from_nonowner() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OTHER()); - dispatcher.transferOwnership(OTHER()); -} - -// -// renounce_ownership & renounceOwnership -// - -#[test] -fn test_renounce_ownership() { - let (mut spy, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.renounce_ownership(); - - spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), ZERO()); - assert!(dispatcher.owner().is_zero()); -} - -#[test] -#[should_panic(expected: ('Caller is the zero address',))] -fn test_renounce_ownership_from_zero_address() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, ZERO()); - dispatcher.renounce_ownership(); -} - -#[test] -#[should_panic(expected: ('Caller is not the owner',))] -fn test_renounce_ownership_from_nonowner() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OTHER()); - dispatcher.renounce_ownership(); -} - -#[test] -fn test_renounceOwnership() { - let (mut spy, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OWNER()); - dispatcher.renounceOwnership(); - - spy.assert_event_ownership_transferred(dispatcher.contract_address, OWNER(), ZERO()); - assert!(dispatcher.owner().is_zero()); -} - -#[test] -#[should_panic(expected: ('Caller is the zero address',))] -fn test_renounceOwnership_from_zero_address() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, ZERO()); - dispatcher.renounceOwnership(); -} - -#[test] -#[should_panic(expected: ('Caller is not the owner',))] -fn test_renounceOwnership_from_nonowner() { - let (_, mut dispatcher) = setup_dispatcher(); - start_cheat_caller_address(dispatcher.contract_address, OTHER()); - dispatcher.renounceOwnership(); -} - -// -// upgrade -// - -#[test] -#[should_panic(expected: ('Caller is not the owner',))] -fn test_upgrade_unauthorized() { - let (_, mut v1) = setup_dispatcher(); - start_cheat_caller_address(v1.contract_address, OTHER()); - v1.upgrade(CLASS_HASH_ZERO()); -} - -#[test] -#[should_panic(expected: ('Class hash cannot be zero',))] -fn test_upgrade_with_class_hash_zero() { - let (_, mut v1) = setup_dispatcher(); - - start_cheat_caller_address(v1.contract_address, OWNER()); - v1.upgrade(CLASS_HASH_ZERO()); -} - -#[test] -fn test_upgraded_event() { - let (mut spy, mut v1) = setup_dispatcher(); - let v2_class_hash = V2_CLASS_HASH(); - - start_cheat_caller_address(v1.contract_address, OWNER()); - v1.upgrade(v2_class_hash); - - spy.assert_only_event_upgraded(v1.contract_address, v2_class_hash); -} - -#[test] -#[feature("safe_dispatcher")] -fn test_v2_missing_camel_selector() { - let (_, mut v1) = setup_dispatcher(); - let v2_class_hash = V2_CLASS_HASH(); - - start_cheat_caller_address(v1.contract_address, OWNER()); - v1.upgrade(v2_class_hash); - - let safe_dispatcher = ERC20UpgradeableABISafeDispatcher { - contract_address: v1.contract_address - }; - let result = safe_dispatcher.totalSupply(); - - utils::assert_entrypoint_not_found_error(result, selector!("totalSupply"), v1.contract_address) -} - -#[test] -fn test_state_persists_after_upgrade() { - let (_, mut v1) = setup_dispatcher(); - let v2_class_hash = V2_CLASS_HASH(); - - start_cheat_caller_address(v1.contract_address, OWNER()); - v1.transfer(RECIPIENT(), VALUE); - - // Check RECIPIENT balance v1 - let camel_balance = v1.balanceOf(RECIPIENT()); - assert_eq!(camel_balance, VALUE); - - v1.upgrade(v2_class_hash); - - // Check RECIPIENT balance v2 - let v2 = IERC20Dispatcher { contract_address: v1.contract_address }; - let snake_balance = v2.balance_of(RECIPIENT()); - assert_eq!(snake_balance, camel_balance); -} diff --git a/src/tests/presets/test_universal_deployer.cairo b/src/tests/presets/test_universal_deployer.cairo deleted file mode 100644 index e5874bcbc..000000000 --- a/src/tests/presets/test_universal_deployer.cairo +++ /dev/null @@ -1,140 +0,0 @@ -use openzeppelin::presets::universal_deployer::UniversalDeployer::ContractDeployed; -use openzeppelin::presets::universal_deployer::UniversalDeployer; -use openzeppelin::tests::utils::constants::{NAME, SYMBOL, SUPPLY, SALT, CALLER, RECIPIENT}; -use openzeppelin::tests::utils::events::EventSpyExt; -use openzeppelin::tests::utils; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin::utils::deployments::{DeployerInfo, calculate_contract_address_from_udc}; -use openzeppelin::utils::interfaces::{ - IUniversalDeployerDispatcher, IUniversalDeployerDispatcherTrait -}; -use openzeppelin::utils::serde::SerializedAppend; -use snforge_std::{EventSpy, spy_events, declare, start_cheat_caller_address}; -use starknet::{ClassHash, ContractAddress}; - - -fn ERC20_CLASS_HASH() -> ClassHash { - utils::declare_class("DualCaseERC20Mock").class_hash -} - -fn ERC20_CALLDATA() -> Span { - let mut calldata = array![]; - calldata.append_serde(NAME()); - calldata.append_serde(SYMBOL()); - calldata.append_serde(SUPPLY); - calldata.append_serde(RECIPIENT()); - calldata.span() -} - -fn deploy_udc() -> IUniversalDeployerDispatcher { - let mut calldata = array![]; - - let address = utils::declare_and_deploy("UniversalDeployer", calldata); - IUniversalDeployerDispatcher { contract_address: address } -} - -#[test] -fn test_deploy_from_zero() { - let udc = deploy_udc(); - let caller = CALLER(); - - // Deploy args - let erc20_class_hash = ERC20_CLASS_HASH(); - let salt = SALT; - let from_zero = true; - let erc20_calldata = ERC20_CALLDATA(); - - let mut spy = spy_events(); - start_cheat_caller_address(udc.contract_address, caller); - - // Check address - let expected_addr = calculate_contract_address_from_udc( - salt, erc20_class_hash, erc20_calldata, Option::None - ); - let deployed_addr = udc.deploy_contract(erc20_class_hash, salt, from_zero, erc20_calldata); - assert_eq!(expected_addr, deployed_addr); - - // Drop ERC20 event, check deploy event - spy.drop_event(); - spy - .assert_only_event_contract_deployed( - udc.contract_address, - deployed_addr, - caller, - from_zero, - erc20_class_hash, - erc20_calldata, - salt - ); - - // Check deployment - let erc20 = IERC20Dispatcher { contract_address: deployed_addr }; - let total_supply = erc20.total_supply(); - assert_eq!(total_supply, SUPPLY); -} - -#[test] -fn test_deploy_not_from_zero() { - let udc = deploy_udc(); - let caller = CALLER(); - - // Deploy args - let erc20_class_hash = ERC20_CLASS_HASH(); - let salt = SALT; - let from_zero = false; - let erc20_calldata = ERC20_CALLDATA(); - - let mut spy = spy_events(); - start_cheat_caller_address(udc.contract_address, caller); - - // Check address - let expected_addr = calculate_contract_address_from_udc( - salt, - erc20_class_hash, - erc20_calldata, - Option::Some(DeployerInfo { caller_address: caller, udc_address: udc.contract_address }) - ); - let deployed_addr = udc.deploy_contract(erc20_class_hash, salt, from_zero, erc20_calldata); - assert_eq!(expected_addr, deployed_addr); - - // Drop ERC20 event, check deploy event - spy.drop_event(); - spy - .assert_only_event_contract_deployed( - udc.contract_address, - deployed_addr, - caller, - from_zero, - erc20_class_hash, - erc20_calldata, - salt - ); - - // Check deployment - let erc20 = IERC20Dispatcher { contract_address: deployed_addr }; - let total_supply = erc20.total_supply(); - assert_eq!(total_supply, SUPPLY); -} - -// -// Helpers -// - -#[generate_trait] -impl UniversalDeployerHelpersImpl of UniversalDeployerSpyHelpers { - fn assert_only_event_contract_deployed( - ref self: EventSpy, - contract: ContractAddress, - address: ContractAddress, - deployer: ContractAddress, - from_zero: bool, - class_hash: ClassHash, - calldata: Span, - salt: felt252 - ) { - let expected = UniversalDeployer::Event::ContractDeployed( - ContractDeployed { address, deployer, from_zero, class_hash, calldata, salt } - ); - self.assert_only_event(contract, expected); - } -} diff --git a/src/tests/security/test_pausable.cairo b/src/tests/security/test_pausable.cairo deleted file mode 100644 index ea4ff3878..000000000 --- a/src/tests/security/test_pausable.cairo +++ /dev/null @@ -1,154 +0,0 @@ -use openzeppelin::security::PausableComponent::{InternalImpl, PausableImpl}; -use openzeppelin::security::PausableComponent::{Paused, Unpaused}; -use openzeppelin::security::PausableComponent; -use openzeppelin::tests::mocks::pausable_mocks::PausableMock; -use openzeppelin::tests::utils::constants::CALLER; -use openzeppelin::tests::utils::events::EventSpyExt; -use snforge_std::EventSpy; -use snforge_std::{spy_events, test_address, start_cheat_caller_address}; -use starknet::ContractAddress; - -type ComponentState = PausableComponent::ComponentState; - -fn COMPONENT_STATE() -> ComponentState { - PausableComponent::component_state_for_testing() -} - -// -// is_paused -// - -#[test] -fn test_is_paused() { - let mut state = COMPONENT_STATE(); - assert!(!state.is_paused()); - - state.pause(); - assert!(state.is_paused()); - - state.unpause(); - assert!(!state.is_paused()); -} - -// -// assert_paused -// - -#[test] -fn test_assert_paused_when_paused() { - let mut state = COMPONENT_STATE(); - state.pause(); - state.assert_paused(); -} - -#[test] -#[should_panic(expected: ('Pausable: not paused',))] -fn test_assert_paused_when_not_paused() { - let state = COMPONENT_STATE(); - state.assert_paused(); -} - -// -// assert_not_paused -// - -#[test] -#[should_panic(expected: ('Pausable: paused',))] -fn test_assert_not_paused_when_paused() { - let mut state = COMPONENT_STATE(); - state.pause(); - state.assert_not_paused(); -} - -#[test] -fn test_assert_not_paused_when_not_paused() { - let state = COMPONENT_STATE(); - state.assert_not_paused(); -} - -// -// pause -// - -#[test] -fn test_pause_when_unpaused() { - let mut state = COMPONENT_STATE(); - let contract_address = test_address(); - - let mut spy = spy_events(); - start_cheat_caller_address(contract_address, CALLER()); - state.pause(); - - spy.assert_only_event_paused(contract_address, CALLER()); - assert!(state.is_paused()); -} - -#[test] -#[should_panic(expected: ('Pausable: paused',))] -fn test_pause_when_paused() { - let mut state = COMPONENT_STATE(); - state.pause(); - state.pause(); -} - -// -// unpause -// - -#[test] -fn test_unpause_when_paused() { - let mut state = COMPONENT_STATE(); - let contract_address = test_address(); - - let mut spy = spy_events(); - start_cheat_caller_address(test_address(), CALLER()); - state.pause(); - state.unpause(); - - spy.assert_event_paused(contract_address, CALLER()); - spy.assert_only_event_unpaused(contract_address, CALLER()); - assert!(!state.is_paused()); -} - -#[test] -#[should_panic(expected: ('Pausable: not paused',))] -fn test_unpause_when_unpaused() { - let mut state = COMPONENT_STATE(); - assert!(!state.is_paused()); - state.unpause(); -} - -// -// Helpers -// - -#[generate_trait] -impl PausableSpyHelpersImpl of PausableSpyHelpers { - fn assert_event_paused( - ref self: EventSpy, contract: ContractAddress, account: ContractAddress - ) { - let expected = PausableComponent::Event::Paused(Paused { account }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_paused( - ref self: EventSpy, contract: ContractAddress, account: ContractAddress, - ) { - self.assert_event_paused(contract, account); - self.assert_no_events_left_from(contract); - } - - fn assert_event_unpaused( - ref self: EventSpy, contract: ContractAddress, account: ContractAddress - ) { - let expected = PausableComponent::Event::Unpaused(Unpaused { account }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_unpaused( - ref self: EventSpy, contract: ContractAddress, account: ContractAddress, - ) { - self.assert_event_unpaused(contract, account); - self.assert_no_events_left_from(contract); - } -} diff --git a/src/tests/token/erc1155/common.cairo b/src/tests/token/erc1155/common.cairo deleted file mode 100644 index 579b5931b..000000000 --- a/src/tests/token/erc1155/common.cairo +++ /dev/null @@ -1,129 +0,0 @@ -use openzeppelin::tests::utils::constants::{ - PUBKEY, TOKEN_ID, TOKEN_ID_2, TOKEN_VALUE, TOKEN_VALUE_2 -}; -use openzeppelin::tests::utils::events::EventSpyExt; -use openzeppelin::tests::utils; -use openzeppelin::token::erc1155::ERC1155Component::{TransferBatch, ApprovalForAll, TransferSingle}; -use openzeppelin::token::erc1155::ERC1155Component; -use snforge_std::EventSpy; -use starknet::ContractAddress; - - -pub(crate) fn setup_receiver() -> ContractAddress { - utils::declare_and_deploy("SnakeERC1155ReceiverMock", array![]) -} - -pub(crate) fn setup_camel_receiver() -> ContractAddress { - utils::declare_and_deploy("CamelERC1155ReceiverMock", array![]) -} - -pub(crate) fn setup_account() -> ContractAddress { - let calldata = array![PUBKEY]; - utils::declare_and_deploy("SnakeAccountMock", calldata) -} - -pub(crate) fn deploy_another_account_at( - existing: ContractAddress, target_address: ContractAddress -) { - let calldata = array![PUBKEY]; - utils::deploy_another_at(existing, target_address, calldata); -} - -pub(crate) fn setup_src5() -> ContractAddress { - utils::declare_and_deploy("SRC5Mock", array![]) -} - -pub(crate) fn get_ids_and_values() -> (Span, Span) { - let ids = array![TOKEN_ID, TOKEN_ID_2].span(); - let values = array![TOKEN_VALUE, TOKEN_VALUE_2].span(); - (ids, values) -} - -pub(crate) fn get_ids_and_split_values(split: u256) -> (Span, Span) { - let ids = array![TOKEN_ID, TOKEN_ID].span(); - let values = array![TOKEN_VALUE - split, split].span(); - (ids, values) -} - -#[generate_trait] -pub(crate) impl ERC1155SpyHelpersImpl of ERC1155SpyHelpers { - fn assert_event_approval_for_all( - ref self: EventSpy, - contract: ContractAddress, - owner: ContractAddress, - operator: ContractAddress, - approved: bool - ) { - let expected = ERC1155Component::Event::ApprovalForAll( - ApprovalForAll { owner, operator, approved } - ); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_approval_for_all( - ref self: EventSpy, - contract: ContractAddress, - owner: ContractAddress, - operator: ContractAddress, - approved: bool - ) { - self.assert_event_approval_for_all(contract, owner, operator, approved); - self.assert_no_events_left_from(contract); - } - - fn assert_event_transfer_single( - ref self: EventSpy, - contract: ContractAddress, - operator: ContractAddress, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - value: u256 - ) { - let expected = ERC1155Component::Event::TransferSingle( - TransferSingle { operator, from, to, id: token_id, value } - ); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_transfer_single( - ref self: EventSpy, - contract: ContractAddress, - operator: ContractAddress, - from: ContractAddress, - to: ContractAddress, - token_id: u256, - value: u256 - ) { - self.assert_event_transfer_single(contract, operator, from, to, token_id, value); - self.assert_no_events_left_from(contract); - } - - fn assert_event_transfer_batch( - ref self: EventSpy, - contract: ContractAddress, - operator: ContractAddress, - from: ContractAddress, - to: ContractAddress, - token_ids: Span, - values: Span - ) { - let expected = ERC1155Component::Event::TransferBatch( - TransferBatch { operator, from, to, ids: token_ids, values } - ); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_transfer_batch( - ref self: EventSpy, - contract: ContractAddress, - operator: ContractAddress, - from: ContractAddress, - to: ContractAddress, - token_ids: Span, - values: Span - ) { - self.assert_event_transfer_batch(contract, operator, from, to, token_ids, values); - self.assert_no_events_left_from(contract); - } -} diff --git a/src/tests/token/erc20/common.cairo b/src/tests/token/erc20/common.cairo deleted file mode 100644 index a50e5ff2e..000000000 --- a/src/tests/token/erc20/common.cairo +++ /dev/null @@ -1,52 +0,0 @@ -use openzeppelin::tests::utils::events::EventSpyExt; -use openzeppelin::token::erc20::ERC20Component::{Approval, Transfer}; -use openzeppelin::token::erc20::ERC20Component; -use snforge_std::EventSpy; -use starknet::ContractAddress; - -#[generate_trait] -pub(crate) impl ERC20SpyHelpersImpl of ERC20SpyHelpers { - fn assert_event_approval( - ref self: EventSpy, - contract: ContractAddress, - owner: ContractAddress, - spender: ContractAddress, - value: u256 - ) { - let expected = ERC20Component::Event::Approval(Approval { owner, spender, value }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_approval( - ref self: EventSpy, - contract: ContractAddress, - owner: ContractAddress, - spender: ContractAddress, - value: u256 - ) { - self.assert_event_approval(contract, owner, spender, value); - self.assert_no_events_left_from(contract); - } - - fn assert_event_transfer( - ref self: EventSpy, - contract: ContractAddress, - from: ContractAddress, - to: ContractAddress, - value: u256 - ) { - let expected = ERC20Component::Event::Transfer(Transfer { from, to, value }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_transfer( - ref self: EventSpy, - contract: ContractAddress, - from: ContractAddress, - to: ContractAddress, - value: u256 - ) { - self.assert_event_transfer(contract, from, to, value); - self.assert_no_events_left_from(contract); - } -} diff --git a/src/tests/token/erc721.cairo b/src/tests/token/erc721.cairo deleted file mode 100644 index d8b44e48b..000000000 --- a/src/tests/token/erc721.cairo +++ /dev/null @@ -1,6 +0,0 @@ -pub(crate) mod common; - -mod test_dual721; -mod test_dual721_receiver; -mod test_erc721; -mod test_erc721_receiver; diff --git a/src/tests/token/erc721/common.cairo b/src/tests/token/erc721/common.cairo deleted file mode 100644 index 97e94f886..000000000 --- a/src/tests/token/erc721/common.cairo +++ /dev/null @@ -1,76 +0,0 @@ -use openzeppelin::tests::utils::events::EventSpyExt; -use openzeppelin::token::erc721::ERC721Component::{Approval, ApprovalForAll, Transfer}; -use openzeppelin::token::erc721::ERC721Component; -use snforge_std::EventSpy; -use starknet::ContractAddress; - -#[generate_trait] -pub(crate) impl ERC721SpyHelpersImpl of ERC721SpyHelpers { - fn assert_event_approval_for_all( - ref self: EventSpy, - contract: ContractAddress, - owner: ContractAddress, - operator: ContractAddress, - approved: bool - ) { - let expected = ERC721Component::Event::ApprovalForAll( - ApprovalForAll { owner, operator, approved } - ); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_approval_for_all( - ref self: EventSpy, - contract: ContractAddress, - owner: ContractAddress, - operator: ContractAddress, - approved: bool - ) { - self.assert_event_approval_for_all(contract, owner, operator, approved); - self.assert_no_events_left_from(contract); - } - - fn assert_event_approval( - ref self: EventSpy, - contract: ContractAddress, - owner: ContractAddress, - approved: ContractAddress, - token_id: u256 - ) { - let expected = ERC721Component::Event::Approval(Approval { owner, approved, token_id }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_approval( - ref self: EventSpy, - contract: ContractAddress, - owner: ContractAddress, - approved: ContractAddress, - token_id: u256 - ) { - self.assert_event_approval(contract, owner, approved, token_id); - self.assert_no_events_left_from(contract); - } - - fn assert_event_transfer( - ref self: EventSpy, - contract: ContractAddress, - from: ContractAddress, - to: ContractAddress, - token_id: u256 - ) { - let expected = ERC721Component::Event::Transfer(Transfer { from, to, token_id }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_transfer( - ref self: EventSpy, - contract: ContractAddress, - from: ContractAddress, - to: ContractAddress, - token_id: u256 - ) { - self.assert_event_transfer(contract, from, to, token_id); - self.assert_no_events_left_from(contract); - } -} diff --git a/src/tests/upgrades/common.cairo b/src/tests/upgrades/common.cairo deleted file mode 100644 index 973f47c8b..000000000 --- a/src/tests/upgrades/common.cairo +++ /dev/null @@ -1,20 +0,0 @@ -use openzeppelin::tests::utils::events::EventSpyExt; -use openzeppelin::upgrades::UpgradeableComponent::Upgraded; -use openzeppelin::upgrades::UpgradeableComponent; -use snforge_std::{EventSpy, EventSpyAssertionsTrait}; -use starknet::{ContractAddress, ClassHash}; - -#[generate_trait] -pub(crate) impl UpgradeableSpyHelpersImpl of UpgradeableSpyHelpers { - fn assert_event_upgraded(ref self: EventSpy, contract: ContractAddress, class_hash: ClassHash) { - let expected = UpgradeableComponent::Event::Upgraded(Upgraded { class_hash }); - self.assert_emitted_single(contract, expected); - } - - fn assert_only_event_upgraded( - ref self: EventSpy, contract: ContractAddress, class_hash: ClassHash - ) { - self.assert_event_upgraded(contract, class_hash); - self.assert_no_events_left_from(contract); - } -} diff --git a/src/tests/upgrades/test_upgradeable.cairo b/src/tests/upgrades/test_upgradeable.cairo deleted file mode 100644 index d55c41f74..000000000 --- a/src/tests/upgrades/test_upgradeable.cairo +++ /dev/null @@ -1,83 +0,0 @@ -use openzeppelin::tests::mocks::upgrades_mocks::{IUpgradesV1Dispatcher, IUpgradesV1DispatcherTrait}; -use openzeppelin::tests::mocks::upgrades_mocks::{IUpgradesV2Dispatcher, IUpgradesV2DispatcherTrait}; -use openzeppelin::tests::utils::constants::{CLASS_HASH_ZERO, ZERO, FELT_VALUE as VALUE}; -use openzeppelin::tests::utils::events::EventSpyExt; -use openzeppelin::tests::utils::{declare_class, deploy}; -use openzeppelin::upgrades::UpgradeableComponent; -use snforge_std::{spy_events, ContractClass}; - -use super::common::UpgradeableSpyHelpers; - -// -// Setup -// - -fn setup_test() -> (IUpgradesV1Dispatcher, ContractClass) { - let v1_class = declare_class("UpgradesV1"); - let v2_class = declare_class("UpgradesV2"); - let v1_contract_address = deploy(v1_class, array![]); - let v1 = IUpgradesV1Dispatcher { contract_address: v1_contract_address }; - (v1, v2_class) -} - -// -// upgrade -// - -#[test] -#[should_panic(expected: ('Class hash cannot be zero',))] -fn test_upgrade_with_class_hash_zero() { - let (v1, _) = setup_test(); - v1.upgrade(CLASS_HASH_ZERO()); -} - -#[test] -fn test_upgraded_event() { - let (v1, v2_class) = setup_test(); - let mut spy = spy_events(); - - v1.upgrade(v2_class.class_hash); - - spy.assert_only_event_upgraded(v1.contract_address, v2_class.class_hash); -} - -#[test] -fn test_new_selector_after_upgrade() { - let (v1, v2_class) = setup_test(); - - v1.upgrade(v2_class.class_hash); - let v2 = IUpgradesV2Dispatcher { contract_address: v1.contract_address }; - - v2.set_value2(VALUE); - assert_eq!(v2.get_value2(), VALUE); -} - -#[test] -fn test_state_persists_after_upgrade() { - let (v1, v2_class) = setup_test(); - - v1.set_value(VALUE); - - v1.upgrade(v2_class.class_hash); - let v2 = IUpgradesV2Dispatcher { contract_address: v1.contract_address }; - - assert_eq!(v2.get_value(), VALUE); -} - -#[test] -fn test_remove_selector_passes_in_v1() { - let (v1, _) = setup_test(); - - v1.remove_selector(); -} - -#[test] -#[ignore] // REASON: should_panic attribute not fit for complex panic messages. -#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND',))] -fn test_remove_selector_fails_in_v2() { - let (v1, v2_class) = setup_test(); - - v1.upgrade(v2_class.class_hash); - // We use the v1 dispatcher because remove_selector is not in v2 interface - v1.remove_selector(); -} diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo deleted file mode 100644 index 597fa9659..000000000 --- a/src/tests/utils.cairo +++ /dev/null @@ -1,15 +0,0 @@ -pub mod common; -pub(crate) mod constants; -pub mod deployment; -pub mod events; -pub mod signing; - -pub use common::{ - panic_data_to_byte_array, to_base_16_string, IntoBase16StringTrait, - assert_entrypoint_not_found_error -}; -pub use deployment::{ - declare_class, declare_and_deploy, declare_and_deploy_at, deploy, deploy_at, deploy_another_at -}; - -pub use events::EventSpyExt; diff --git a/src/tests/utils/common.cairo b/src/tests/utils/common.cairo deleted file mode 100644 index f453a32fb..000000000 --- a/src/tests/utils/common.cairo +++ /dev/null @@ -1,58 +0,0 @@ -use core::to_byte_array::FormatAsByteArray; -use starknet::{ContractAddress, SyscallResult}; - -/// Converts panic data into a string (ByteArray). -/// -/// panic_data is expected to be a valid serialized byte array with an extra -/// felt252 at the beginning, which is the BYTE_ARRAY_MAGIC. -pub fn panic_data_to_byte_array(panic_data: Array) -> ByteArray { - let mut panic_data = panic_data.span(); - - // Remove BYTE_ARRAY_MAGIC from the panic data. - panic_data.pop_front().expect('Empty panic data provided'); - - match Serde::::deserialize(ref panic_data) { - Option::Some(string) => string, - Option::None => panic!("Failed to deserialize panic data."), - } -} - -/// Converts a felt252 to a base 16 string padded to 66 characters including the `0x` prefix. -pub fn to_base_16_string(value: felt252) -> ByteArray { - let mut string = value.format_as_byte_array(16); - let mut padding = 64 - string.len(); - - while padding > 0 { - string = "0" + string; - padding -= 1; - }; - format!("0x{}", string) -} - -#[generate_trait] -pub impl IntoBase16String> of IntoBase16StringTrait { - fn into_base_16_string(self: T) -> ByteArray { - to_base_16_string(self.into()) - } -} - -/// Asserts that the syscall result of a call failed with an "Entrypoint not found" error, -/// following the starknet foundry emitted error format. -pub fn assert_entrypoint_not_found_error>( - result: SyscallResult, selector: felt252, contract_address: ContractAddress -) { - if let Result::Err(panic_data) = result { - let expected_panic_message = format!( - "Entry point selector {} not found in contract {}", - selector.into_base_16_string(), - contract_address.into_base_16_string() - ); - let actual_panic_message = panic_data_to_byte_array(panic_data); - assert!( - actual_panic_message == expected_panic_message, - "Got unexpected panic message: ${actual_panic_message}" - ); - } else { - panic!("${selector} call was expected to fail, but succeeded"); - } -} diff --git a/src/tests/utils/constants.cairo b/src/tests/utils/constants.cairo deleted file mode 100644 index 4d8df0911..000000000 --- a/src/tests/utils/constants.cairo +++ /dev/null @@ -1,148 +0,0 @@ -use openzeppelin::account::interface::EthPublicKey; -use starknet::ClassHash; -use starknet::ContractAddress; -use starknet::SyscallResultTrait; -use starknet::class_hash::class_hash_const; -use starknet::contract_address_const; -use starknet::secp256_trait::Secp256Trait; - -pub(crate) const DECIMALS: u8 = 18_u8; -pub(crate) const SUPPLY: u256 = 2000; -pub(crate) const VALUE: u256 = 300; -pub(crate) const FELT_VALUE: felt252 = 'FELT_VALUE'; -pub(crate) const ROLE: felt252 = 'ROLE'; -pub(crate) const OTHER_ROLE: felt252 = 'OTHER_ROLE'; -pub(crate) const TOKEN_ID: u256 = 21; -pub(crate) const TOKEN_ID_2: u256 = 121; -pub(crate) const TOKEN_VALUE: u256 = 42; -pub(crate) const TOKEN_VALUE_2: u256 = 142; -pub(crate) const PUBKEY: felt252 = 'PUBKEY'; -pub(crate) const NEW_PUBKEY: felt252 = - 0x26da8d11938b76025862be14fdb8b28438827f73e75e86f7bfa38b196951fa7; -pub(crate) const DAPP_NAME: felt252 = 'DAPP_NAME'; -pub(crate) const DAPP_VERSION: felt252 = 'DAPP_VERSION'; -pub(crate) const SALT: felt252 = 'SALT'; -pub(crate) const SUCCESS: felt252 = 123123; -pub(crate) const FAILURE: felt252 = 456456; -pub(crate) const MIN_TRANSACTION_VERSION: felt252 = 1; -pub(crate) const TRANSACTION_HASH: felt252 = 'TRANSACTION_HASH'; -// 2**128 -pub(crate) const QUERY_OFFSET: felt252 = 0x100000000000000000000000000000000; -// QUERY_OFFSET + MIN_TRANSACTION_VERSION -pub(crate) const QUERY_VERSION: felt252 = 0x100000000000000000000000000000001; - -pub(crate) fn NAME() -> ByteArray { - "NAME" -} - -pub(crate) fn SYMBOL() -> ByteArray { - "SYMBOL" -} - -pub(crate) fn BASE_URI() -> ByteArray { - "https://api.example.com/v1/" -} - -pub(crate) fn BASE_URI_2() -> ByteArray { - "https://api.example.com/v2/" -} - -pub(crate) fn ETH_PUBKEY() -> EthPublicKey { - Secp256Trait::secp256_ec_get_point_from_x_syscall(3, false).unwrap_syscall().unwrap() -} - -pub(crate) fn NEW_ETH_PUBKEY() -> EthPublicKey { - Secp256Trait::secp256_ec_get_point_from_x_syscall(4, false).unwrap_syscall().unwrap() -} - -pub(crate) fn ADMIN() -> ContractAddress { - contract_address_const::<'ADMIN'>() -} - -pub(crate) fn AUTHORIZED() -> ContractAddress { - contract_address_const::<'AUTHORIZED'>() -} - -pub(crate) fn ZERO() -> ContractAddress { - contract_address_const::<0>() -} - -pub(crate) fn CLASS_HASH_ZERO() -> ClassHash { - class_hash_const::<0>() -} - -pub(crate) fn CALLER() -> ContractAddress { - contract_address_const::<'CALLER'>() -} - -pub(crate) fn OWNER() -> ContractAddress { - contract_address_const::<'OWNER'>() -} - -pub(crate) fn NEW_OWNER() -> ContractAddress { - contract_address_const::<'NEW_OWNER'>() -} - -pub(crate) fn OTHER() -> ContractAddress { - contract_address_const::<'OTHER'>() -} - -pub(crate) fn OTHER_ADMIN() -> ContractAddress { - contract_address_const::<'OTHER_ADMIN'>() -} - -pub(crate) fn SPENDER() -> ContractAddress { - contract_address_const::<'SPENDER'>() -} - -pub(crate) fn RECIPIENT() -> ContractAddress { - contract_address_const::<'RECIPIENT'>() -} - -pub(crate) fn OPERATOR() -> ContractAddress { - contract_address_const::<'OPERATOR'>() -} - -pub(crate) fn DATA(success: bool) -> Span { - let mut data = array![]; - if success { - data.append(SUCCESS); - } else { - data.append(FAILURE); - } - data.span() -} - -pub(crate) fn EMPTY_DATA() -> Span { - array![].span() -} - -// -// Signing keys -// - -pub(crate) mod secp256k1 { - use openzeppelin::tests::utils::signing::{Secp256k1KeyPair, get_secp256k1_keys_from}; - - pub(crate) fn KEY_PAIR() -> Secp256k1KeyPair { - let private_key = u256 { low: 'PRIVATE_LOW', high: 'PRIVATE_HIGH' }; - get_secp256k1_keys_from(private_key) - } - - pub(crate) fn KEY_PAIR_2() -> Secp256k1KeyPair { - let private_key = u256 { low: 'PRIVATE_LOW_2', high: 'PRIVATE_HIGH_2' }; - get_secp256k1_keys_from(private_key) - } -} - -pub(crate) mod stark { - use openzeppelin::tests::utils::signing::{StarkKeyPair, get_stark_keys_from}; - - pub(crate) fn KEY_PAIR() -> StarkKeyPair { - get_stark_keys_from('PRIVATE_KEY') - } - - pub(crate) fn KEY_PAIR_2() -> StarkKeyPair { - get_stark_keys_from('PRIVATE_KEY_2') - } -} diff --git a/src/tests/utils/deployment.cairo b/src/tests/utils/deployment.cairo deleted file mode 100644 index 2b50ab15f..000000000 --- a/src/tests/utils/deployment.cairo +++ /dev/null @@ -1,48 +0,0 @@ -use core::starknet::SyscallResultTrait; -use openzeppelin::tests::utils::panic_data_to_byte_array; -use snforge_std::{ContractClass, ContractClassTrait}; -use starknet::ContractAddress; - -pub fn deploy(contract_class: ContractClass, calldata: Array) -> ContractAddress { - match contract_class.deploy(@calldata) { - Result::Ok((contract_address, _)) => contract_address, - Result::Err(panic_data) => panic!("{}", panic_data_to_byte_array(panic_data)) - } -} - -pub fn deploy_at( - contract_class: ContractClass, contract_address: ContractAddress, calldata: Array -) { - match contract_class.deploy_at(@calldata, contract_address) { - Result::Ok(_) => (), - Result::Err(panic_data) => panic!("{}", panic_data_to_byte_array(panic_data)) - }; -} - -/// Deploys a contract from the class hash of another contract which is already deployed. -pub fn deploy_another_at( - existing: ContractAddress, target_address: ContractAddress, calldata: Array -) { - let class_hash = snforge_std::get_class_hash(existing); - let contract_class = ContractClassTrait::new(class_hash); - deploy_at(contract_class, target_address, calldata) -} - -pub fn declare_class(contract_name: ByteArray) -> ContractClass { - match snforge_std::declare(contract_name) { - Result::Ok(contract_class) => contract_class, - Result::Err(panic_data) => panic!("{}", panic_data_to_byte_array(panic_data)) - } -} - -pub fn declare_and_deploy(contract_name: ByteArray, calldata: Array) -> ContractAddress { - let contract_class = declare_class(contract_name); - deploy(contract_class, calldata) -} - -pub fn declare_and_deploy_at( - contract_name: ByteArray, target_address: ContractAddress, calldata: Array -) { - let contract_class = declare_class(contract_name); - deploy_at(contract_class, target_address, calldata) -} diff --git a/src/tests/utils/events.cairo b/src/tests/utils/events.cairo deleted file mode 100644 index 302d1a917..000000000 --- a/src/tests/utils/events.cairo +++ /dev/null @@ -1,62 +0,0 @@ -use snforge_std::{EventSpyTrait, EventSpy, EventSpyAssertionsTrait}; -use starknet::ContractAddress; - -#[generate_trait] -pub impl EventSpyExtImpl of EventSpyExt { - fn assert_only_event, +Drop>( - ref self: EventSpy, from_address: ContractAddress, event: T - ) { - self.assert_emitted_single(from_address, event); - self.assert_no_events_left_from(from_address); - } - - fn assert_emitted_single, +Drop>( - ref self: EventSpy, from_address: ContractAddress, expected_event: T - ) { - self.assert_emitted(@array![(from_address, expected_event)]); - self._event_offset += 1; - } - - fn drop_event(ref self: EventSpy) { - self.drop_n_events(1); - } - - fn drop_n_events(ref self: EventSpy, number_to_drop: u32) { - let events = self.get_events().events; - let len = events.len(); - assert!( - len >= number_to_drop, - "Not enough events to drop. ${len} events, ${number_to_drop} to drop" - ); - self._event_offset += number_to_drop; - } - - fn drop_all_events(ref self: EventSpy) { - let events = self.get_events().events; - self._event_offset += events.len(); - } - - fn assert_no_events_left(ref self: EventSpy) { - let events = self.get_events().events; - assert!(events.len() == 0, "Events remaining on queue"); - } - - fn assert_no_events_left_from(ref self: EventSpy, from_address: ContractAddress) { - assert!(self.count_events_from(from_address) == 0, "Events remaining on queue"); - } - - fn count_events_from(ref self: EventSpy, from_address: ContractAddress) -> u32 { - let mut result = 0; - let mut events = self.get_events().events; - let mut index = 0; - let length = events.len(); - while index < length { - let (from, _) = events.at(index); - if from_address == *from { - result += 1; - } - index += 1; - }; - result - } -} diff --git a/src/tests/utils/signing.cairo b/src/tests/utils/signing.cairo deleted file mode 100644 index 8b1e7ca44..000000000 --- a/src/tests/utils/signing.cairo +++ /dev/null @@ -1,31 +0,0 @@ -use snforge_std::signature::secp256k1_curve::{Secp256k1CurveSignerImpl, Secp256k1CurveKeyPairImpl}; -use snforge_std::signature::stark_curve::{StarkCurveSignerImpl, StarkCurveKeyPairImpl}; -use snforge_std::signature::{KeyPair, KeyPairTrait}; -use starknet::secp256k1::Secp256k1Point; - -pub type StarkKeyPair = KeyPair; -pub type Secp256k1KeyPair = KeyPair; - -pub fn get_stark_keys_from(private_key: felt252) -> StarkKeyPair { - StarkCurveKeyPairImpl::from_secret_key(private_key) -} - -pub fn get_secp256k1_keys_from(private_key: u256) -> Secp256k1KeyPair { - Secp256k1CurveKeyPairImpl::from_secret_key(private_key) -} - -#[generate_trait] -pub impl StarkKeyPairExt of StarkKeyPairExtTrait { - fn serialized_sign(self: StarkKeyPair, msg: felt252) -> Array { - let (r, s) = self.sign(msg).unwrap(); - array![r, s] - } -} - -#[generate_trait] -pub impl Secp256k1KeyPairExt of Secp256k1KeyPairExtTrait { - fn serialized_sign(self: Secp256k1KeyPair, msg: u256) -> Array { - let (r, s) = self.sign(msg).unwrap(); - array![r.low.into(), r.high.into(), s.low.into(), s.high.into()] - } -} From 3ecad56f097b1fc3c8fac8fcc2893a0537775e17 Mon Sep 17 00:00:00 2001 From: Eric Nordelo Date: Fri, 2 Aug 2024 14:27:03 +0200 Subject: [PATCH 45/45] fix: workflow for updating the presets page --- .github/workflows/prepare-release.yml | 9 ++++++--- scripts/get_hashes_page.py | 6 +++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 23a2a7f95..7ec9df76a 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -4,7 +4,7 @@ on: create: jobs: - update_version: + update_version_and_presets_page: if: github.ref_type == 'branch' && startsWith(github.ref, 'refs/heads/release-v') runs-on: ubuntu-latest @@ -45,12 +45,15 @@ jobs: with: version: "0.1.0" + - name: Build presets artifacts + run: scarb build -p openzeppelin_presets + - name: Update presets page run: | - class_hash get --json | sed -e '1,4d' | python3 scripts/get_hashes_page.py "$CAIRO_VERSION" \ + class_hash get --no-compile --json | python3 scripts/get_hashes_page.py "$CAIRO_VERSION" \ > ./docs/modules/ROOT/pages/utils/_class_hashes.adoc - name: Auto-commit changes uses: stefanzweifel/git-auto-commit-action@3ea6ae190baf489ba007f7c92608f33ce20ef04a #v4.16.0 with: - commit_message: Bump version to ${{ env.NEW_VERSION }} + commit_message: Bump version to ${{ env.NEW_VERSION }} and update presets page diff --git a/scripts/get_hashes_page.py b/scripts/get_hashes_page.py index 9ce7105f8..593e79704 100644 --- a/scripts/get_hashes_page.py +++ b/scripts/get_hashes_page.py @@ -34,6 +34,10 @@ def generate_doc_file(cmp_version, contracts): # Avoid the already added contracts in the known order if contract['name'] in KNOWN_ORDER: continue + # Avoid adding mocks + # TODO: remove this after mocks are removed from the artifacts built outside tests + if "Mock" in contract['name']: + continue hashes += f":{contract['name']}-class-hash: {normalize_len(contract['sierra'])}\n" footer = """// Presets page @@ -44,7 +48,7 @@ def generate_doc_file(cmp_version, contracts): def remove_prefix_from_names(contracts): for contract in contracts: - contract.update([("name", remove_prefix(contract['name'], 'openzeppelin_'))]) + contract.update([("name", remove_prefix(contract['name'], 'openzeppelin_presets_'))]) return contracts