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()] - } -}