Repository: OpenZeppelin/cairo-contracts (language: python)

Issue:
Remove DualDispatchers
**🧐 Motivation**
They are not supported on live networks and make our library more blotted. 

**📝 Details**
We've had `DualDispatchers` for a while now, and since they are not supported on live networks they haven't been adopted. They are an additional liability in our codebase and make the amount of LOC bigger for any security review. 


```[tasklist]
### Tasks
- [x] Remove access dual dispatchers
- [x] Remove account dual dispatchers
- [x] Remove erc20 dual dispatchers
- [x] Remove erc721 dual dispatchers
- [x] Remove erc1155 dual dispatchers
- [ ] docs and CHANGELOG
```



Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0312236cf..2079d48b1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 - Bump scarb to v2.8.3 (#1166)
 
+### Changed (Breaking)
+
+- Remove openzeppelin_utils::selectors (#1163)
+- Remove `DualCase dispatchers` (#1163)
+  - Remove `try_selector_with_fallback` from `openzeppelin_utils`
+  - Remove `unwrap_and_cast` module from `openzeppelin_utils`
+  - Remove `openzeppelin_access::accesscontrol::dual_accesscontrol`
+  - Remove `openzeppelin_access::ownable::dual_ownable`
+  - Remove `openzeppelin_account::dual_account`
+  - Remove `openzeppelin_account::dual_eth_account`
+  - Remove `openzeppelin_token::erc20::dual20`
+  - Remove `openzeppelin_token::erc721::dual721`
+  - Remove `openzeppelin_token::erc721::dual721_receiver`
+  - Remove `openzeppelin_token::erc1155::dual1155`
+  - Remove `openzeppelin_token::erc1155::dual1155_receiver`
+- `SRC9Component` now uses `ISRC6Dispatcher` instead of `DualCaseAccount` (#1163)
+- `ERC20VotesComponent` now uses `ISRC6Dispatcher` instead of `DualCaseAccount` (#1163)
+- `ERC721Component` now uses `IERC721ReceiverDispatcher` instead of `DualCaseERC721Receiver` (#1163)
+- `ERC1155Component` now uses `IERC1155ReceiverDispatcher` instead of `DualCaseERC1155Receiver` (#1163)
+
 ## 0.17.0 (2024-09-23)
 
 ### Added
diff --git a/README.md b/README.md
index 6e4d27302..1e1e9063f 100644
--- a/README.md
+++ b/README.md
@@ -110,10 +110,6 @@ mod MyToken {
 }
 ```
 
-### Unsupported
-
-[`DualCase` dispatchers](https://docs.openzeppelin.com/contracts-cairo/0.17.0/interfaces#dualcase_dispatchers) rely on Sierra's ability to catch a revert to resume execution. Currently, Starknet live chains (testnets and mainnet) don't implement that behavior. Starknet's testing framework does support it.
-
 ## Learn
 
 ### Documentation
diff --git a/docs/modules/ROOT/pages/api/utilities.adoc b/docs/modules/ROOT/pages/api/utilities.adoc
index 32a69935f..9e0802233 100644
--- a/docs/modules/ROOT/pages/api/utilities.adoc
+++ b/docs/modules/ROOT/pages/api/utilities.adoc
@@ -19,79 +19,13 @@ Module containing core utilities of the library.
 [.contract-index]
 .Members
 --
-.Functions
-* xref:#utils-try_selector_with_fallback[`++try_selector_with_fallback(target, selector, fallback, args)++`]
-
-.Traits
-* xref:#utils-UnwrapAndCast[`++UnwrapAndCast++`]
-
 .Inner modules
 * xref:#utils-cryptography[`++cryptography++`]
 * xref:#utils-deployments[`++deployments++`]
 * xref:#utils-math[`++math++`]
-* xref:#utils-selectors[`++selectors++`]
 * xref:#utils-serde[`++serde++`]
 --
 
-[#utils-Functions]
-==== Functions
-
-[.contract-item]
-[[utils-try_selector_with_fallback]]
-==== `[.contract-item-name]#++try_selector_with_fallback++#++(target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>) → SyscallResult<Span<felt252>>++` [.item-kind]#function#
-
-Tries to call a given selector on a given contract, and if it fails, tries to call a fallback selector.
-
-It was designed for falling back to the `camelCase` selector for backward compatibility in the
-case of a failure of the `snake_case` selector.
-
-Returns a `SyscallResult` with the result of the successful call.
-
-Note that:
-
-- If the first call succeeds, the second call is not attempted.
-
-- If the first call fails with an error different than `ENTRYPOINT_NOT_FOUND`, the error is returned
-without falling back to the second selector.
-
-- If the first call fails with `ENTRYPOINT_NOT_FOUND`, the second call is attempted, and if it fails its
-error is returned.
-
-WARNING: The fallback mechanism won't work on live chains (mainnet or testnets) until
-they implement panic handling in their runtime.
-
-[#utils-Traits]
-==== Traits
-
-[.contract-item]
-[[utils-UnwrapAndCast]]
-==== `[.contract-item-name]#++UnwrapAndCast++#` [.item-kind]#trait#
-
-Trait for exposing an `unwrap_and_cast` function to `SyscallResult` objects. This may be useful
-when unwrapping a syscall result to a type implementing the `Serde` trait, and you want to avoid the boilerplate of
-casting and unwrapping the result multiple times.
-
-Usage example:
-
-```cairo
-use openzeppelin_utils::selectors;
-use openzeppelin_utils::UnwrapAndCast;
-
-fn call_and_cast_to_bool(target: ContractAddress, args: Span<felt252>) -> bool {
-    try_selector_with_fallback(
-        target, selectors::has_role, selectors::hasRole, args
-    ).unwrap_and_cast()
-}
-
-fn call_and_cast_to_felt252(target: ContractAddress, args: Span<felt252>) -> felt252 {
-    try_selector_with_fallback(
-        target, selectors::get_role_admin, selectors::getRoleAdmin, args
-    ).unwrap_and_cast()
-}
-```
-
-Note that it can be automatically casted to any type implementing the `Serde` trait.
-
 [#utils-Inner-Modules]
 ==== Inner modules
 
@@ -113,12 +47,6 @@ See xref:#deployments[`openzeppelin_utils::deployments`].
 
 See xref:#math[`openzeppelin_utils::math`].
 
-[.contract-item]
-[[utils-selectors]]
-==== `[.contract-item-name]#++selectors++#` [.item-kind]#module#
-
-See xref:#selectors[`openzeppelin_utils::selectors`].
-
 [.contract-item]
 [[utils-serde]]
 ==== `[.contract-item-name]#++serde++#` [.item-kind]#module#
@@ -250,19 +178,6 @@ Returns the average of two values. The result is rounded down.
 
 NOTE: `T` is a generic value matching different numeric implementations.
 
-[.contract]
-[[selectors]]
-=== `++selectors++`
-
-```cairo
-use openzeppelin_utils::selectors;
-```
-
-:selectors: https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.17.0/packages/utils/src/selectors.cairo[selectors.cairo]
-
-Module containing constants matching multiple selectors used through the library.
-To see the full list of selectors, see {selectors}.
-
 [.contract]
 [[serde]]
 === `++serde++`
diff --git a/docs/modules/ROOT/pages/guides/snip12.adoc b/docs/modules/ROOT/pages/guides/snip12.adoc
index c9e51790c..6e2316067 100644
--- a/docs/modules/ROOT/pages/guides/snip12.adoc
+++ b/docs/modules/ROOT/pages/guides/snip12.adoc
@@ -241,12 +241,12 @@ TIP: The expected parameter for the `get_message_hash` function is the address o
 
 == Full Implementation
 
-:dualcase_dispatchers: xref:/interfaces#dualcase_dispatchers
+:isrc6_dispatcher: xref:/api/account#ISRC6
 :nonces: xref:/api/utilities#NoncesComponent
 
 Finally, the full implementation of the `CustomERC20` contract looks like this:
 
-NOTE: We are using the {dualcase_dispatchers}[`DualCaseAccount`] to verify the signature,
+NOTE: We are using the {isrc6_dispatcher}[`ISRC6Dispatcher`] to verify the signature,
 and the {nonces}[`NoncesComponent`] to handle nonces to prevent replay attacks.
 
 [,cairo]
@@ -278,7 +278,7 @@ impl StructHashImpl of StructHash<Message> {
 
 #[starknet::contract]
 mod CustomERC20 {
-    use openzeppelin_account::dual_account::{DualCaseAccount, DualCaseAccountTrait};
+    use openzeppelin_account::interface::{ISRC6Dispatcher, ISRC6DispatcherTrait};
     use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
     use openzeppelin_utils::cryptography::nonces::NoncesComponent;
     use starknet::ContractAddress;
@@ -348,7 +348,7 @@ mod CustomERC20 {
         let message = Message { recipient, amount, nonce, expiry };
         let hash = message.get_message_hash(owner);
 
-        let is_valid_signature_felt = DualCaseAccount { contract_address: owner }
+        let is_valid_signature_felt = ISRC6Dispatcher { contract_address: owner }
             .is_valid_signature(hash, signature);
 
         // Check either 'VALID' or true for backwards compatibility
diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc
index 9e6f5ecbb..59e49dd23 100644
--- a/docs/modules/ROOT/pages/index.adoc
+++ b/docs/modules/ROOT/pages/index.adoc
@@ -21,7 +21,7 @@ before proceeding, and run the following command to check that the installation
 ----
 $ scarb --version
 
-scarb 2.8.2 (a37b4cbfc 2024-09-09)
+scarb 2.8.3 (54938ce3b 2024-09-26)
 cairo: 2.8.2 (https://crates.io/crates/cairo-lang-compiler/2.8.2)
 sierra: 1.6.0
 ----
diff --git a/docs/modules/ROOT/pages/interfaces.adoc b/docs/modules/ROOT/pages/interfaces.adoc
index c01486d9f..8b4b8c10d 100644
--- a/docs/modules/ROOT/pages/interfaces.adoc
+++ b/docs/modules/ROOT/pages/interfaces.adoc
@@ -13,12 +13,13 @@ use openzeppelin_token::erc20::interface::IERC20;
 or
 
 ```cairo
-use openzeppelin_token::erc20::dual20::DualCaseERC20;
+use openzeppelin_token::erc20::interface::ERC20ABI;
 ```
 
 NOTE: For simplicity, we'll use ERC20 as example but the same concepts apply to other modules.
 
 == Interface traits
+
 The library offers three types of traits to implement or interact with contracts:
 
 === Standard traits
@@ -44,6 +45,9 @@ pub trait IERC20<TState> {
 
 They describe a contract's complete interface. This is useful to interface with a preset contract offered by this library, such as the ERC20 preset that includes functions from different traits such as `IERC20` and `IERC20Camel`.
 
+NOTE: The library offers an ABI trait for most components, providing all external function signatures
+even when most of the time all of them don't need to be implemented at the same time. This can be helpful when interacting with a contract implementing the component, instead of defining a new dispatcher.
+
 ```cairo
 #[starknet::interface]
 pub trait ERC20ABI<TState> {
@@ -72,34 +76,30 @@ pub trait ERC20ABI<TState> {
 ```
 
 === Dispatcher traits
-This is a utility trait to interface with contracts whose interface is unknown. Read more in the xref:#dualcase_dispatchers[DualCase Dispatchers] section.
 
-```cairo
-#[derive(Copy, Drop)]
-pub struct DualCaseERC20 {
-    contract_address: ContractAddress
-}
+:interacting-with-another-contract: https://book.cairo-lang.org/ch15-02-interacting-with-another-contract.html[Interacting with another contract]
 
-pub trait DualCaseERC20Trait {
-    fn name(self: @DualCaseERC20) -> ByteArray;
-    fn symbol(self: @DualCaseERC20) -> ByteArray;
-    fn decimals(self: @DualCaseERC20) -> u8;
-    fn total_supply(self: @DualCaseERC20) -> u256;
-    fn balance_of(self: @DualCaseERC20, account: ContractAddress) -> u256;
-    fn allowance(self: @DualCaseERC20, owner: ContractAddress, spender: ContractAddress) -> u256;
-    fn transfer(self: @DualCaseERC20, recipient: ContractAddress, amount: u256) -> bool;
-    fn transfer_from(
-        self: @DualCaseERC20, sender: ContractAddress, recipient: ContractAddress, amount: u256
-    ) -> bool;
-    fn approve(self: @DualCaseERC20, spender: ContractAddress, amount: u256) -> bool;
-}
+Traits annotated with `#[starknet::interface]` automatically generate a dispatcher that can be used to interact with contracts that implement the given interface. They can be imported by appending the `Dispatcher` and `DispatcherTrait` suffixes to the trait name, like this:
+
+```cairo
+use openzeppelin_token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait};
 ```
 
+Other types of dispatchers are also auto-generated from the annotated trait. See the
+{interacting-with-another-contract} section of the Cairo book for more information.
+
+NOTE: In the example, the `IERC20Dispatcher` is the one used to interact with contracts, but the
+`IERC20DispatcherTrait` needs to be in scope for the functions to be available.
+
 == Dual interfaces
 
+WARNING: `camelCase` functions are deprecated and maintained only for Backwards Compatibility.
+It's recommended to only use `snake_case` interfaces with contracts and components. The `camelCase` functions will be removed in
+future versions.
+
 Following the {great-interface-migration} plan, we added `snake_case` functions to all of our preexisting `camelCase` contracts with the goal of eventually dropping support for the latter.
 
-In short, we offer two types of interfaces and utilities to handle them:
+In short, the library offers two types of interfaces and utilities to handle them:
 
 1. `camelCase` interfaces, which are the ones we've been using so far.
 2. `snake_case` interfaces, which are the ones we're migrating to.
@@ -131,7 +131,7 @@ pub trait IERC20<TState> {
 
 === `IERC20Camel`
 
-On top of that, we also offer a `camelCase` version of the same interface:
+On top of that, the library also offers a `camelCase` version of the same interface:
 
 ```cairo
 #[starknet::interface]
@@ -149,42 +149,3 @@ pub trait IERC20Camel<TState> {
     fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;
 }
 ```
-
-== `DualCase` dispatchers
-
-WARNING: `DualCase` dispatchers are deprecated, and they will be removed from the library soon.
-
-WARNING: `DualCase` dispatchers won't work on live chains (`mainnet` or testnets) until they implement panic handling in their runtime. Dispatchers work fine in testing environments.
-
-In order to ease this transition, OpenZeppelin Contracts for Cairo offer what we call `DualCase` dispatchers such as `DualCaseERC721` or `DualCaseAccount`.
-
-These modules wrap a target contract with a compatibility layer to expose a `snake_case` interface no matter what casing the underlying contract uses.
-This way, an AMM wouldn't have problems integrating tokens independently of their interface.
-
-For example:
-
-```cairo
-let token = DualCaseERC20 { contract_address: target };
-token.transfer_from(OWNER(), RECIPIENT(), VALUE);
-```
-
-This is done by simply executing the `snake_case` version of the function (e.g. `transfer_from`) and falling back to the `camelCase` one (e.g. `transferFrom`) in case it reverts with `ENTRYPOINT_NOT_FOUND`, like this:
-
-```cairo
-fn try_selector_with_fallback(
-    target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>
-) -> SyscallResult<Span<felt252>> {
-    match call_contract_syscall(target, selector, args) {
-        Result::Ok(ret) => Result::Ok(ret),
-        Result::Err(errors) => {
-            if *errors.at(0) == 'ENTRYPOINT_NOT_FOUND' {
-                return call_contract_syscall(target, fallback, args);
-            } else {
-                Result::Err(errors)
-            }
-        }
-    }
-}
-```
-
-Trying the `snake_case` interface first renders `camelCase` calls a bit more expensive since a failed `snake_case` call will always happen before. This is a design choice to incentivize casing adoption/transition as per the {great-interface-migration}.
diff --git a/packages/utils/README.md b/packages/utils/README.md
index bb6cdc520..00d094f37 100644
--- a/packages/utils/README.md
+++ b/packages/utils/README.md
@@ -10,7 +10,6 @@ This crate provides components and libraries containing miscellaneous utilities.
 - [`cryptography`](https://docs.openzeppelin.com/contracts-cairo/0.17.0/api/utilities#cryptography)
 - [`deployments`](https://docs.openzeppelin.com/contracts-cairo/0.17.0/api/utilities#deployments)
 - [`math`](https://docs.openzeppelin.com/contracts-cairo/0.17.0/api/utilities#math)
-- [`selectors`](https://docs.openzeppelin.com/contracts-cairo/0.17.0/api/utilities#selectors)
 - [`serde`](https://docs.openzeppelin.com/contracts-cairo/0.17.0/api/utilities#serde)
 
 ### Cryptography
diff --git a/packages/utils/src/lib.cairo b/packages/utils/src/lib.cairo
index 074486181..2e96323af 100644
--- a/packages/utils/src/lib.cairo
+++ b/packages/utils/src/lib.cairo
@@ -5,32 +5,10 @@ pub mod cryptography;
 pub mod deployments;
 pub mod interfaces;
 pub mod math;
-pub mod selectors;
 pub mod serde;
 pub mod structs;
 
 #[cfg(test)]
 mod tests;
 
-pub mod unwrap_and_cast;
-
 pub use cryptography::{nonces, snip12};
-pub use unwrap_and_cast::UnwrapAndCast;
-use starknet::syscalls::call_contract_syscall;
-
-use starknet::{ContractAddress, SyscallResult};
-
-pub fn try_selector_with_fallback(
-    target: ContractAddress, selector: felt252, fallback: felt252, args: Span<felt252>
-) -> SyscallResult<Span<felt252>> {
-    match call_contract_syscall(target, selector, args) {
-        Result::Ok(ret) => Result::Ok(ret),
-        Result::Err(errors) => {
-            if *errors.at(0) == 'ENTRYPOINT_NOT_FOUND' {
-                return call_contract_syscall(target, fallback, args);
-            } else {
-                Result::Err(errors)
-            }
-        }
-    }
-}
diff --git a/packages/utils/src/selectors.cairo b/packages/utils/src/selectors.cairo
deleted file mode 100644
index 90281206e..000000000
--- a/packages/utils/src/selectors.cairo
+++ /dev/null
@@ -1,104 +0,0 @@
-// SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts for Cairo v0.17.0 (utils/selectors.cairo)
-
-//
-// AccessControl
-//
-
-pub const get_role_admin: felt252 = selector!("get_role_admin");
-pub const getRoleAdmin: felt252 = selector!("getRoleAdmin");
-pub const grant_role: felt252 = selector!("grant_role");
-pub const grantRole: felt252 = selector!("grantRole");
-pub const has_role: felt252 = selector!("has_role");
-pub const hasRole: felt252 = selector!("hasRole");
-pub const renounce_role: felt252 = selector!("renounce_role");
-pub const renounceRole: felt252 = selector!("renounceRole");
-pub const revoke_role: felt252 = selector!("revoke_role");
-pub const revokeRole: felt252 = selector!("revokeRole");
-
-//
-// Ownable
-//
-
-pub const owner: felt252 = selector!("owner");
-pub const transfer_ownership: felt252 = selector!("transfer_ownership");
-pub const transferOwnership: felt252 = selector!("transferOwnership");
-pub const renounce_ownership: felt252 = selector!("renounce_ownership");
-pub const renounceOwnership: felt252 = selector!("renounceOwnership");
-
-//
-// ERC721
-//
-
-pub const name: felt252 = selector!("name");
-pub const symbol: felt252 = selector!("symbol");
-pub const token_uri: felt252 = selector!("token_uri");
-pub const tokenURI: felt252 = selector!("tokenURI");
-pub const balance_of: felt252 = selector!("balance_of");
-pub const balanceOf: felt252 = selector!("balanceOf");
-pub const owner_of: felt252 = selector!("owner_of");
-pub const ownerOf: felt252 = selector!("ownerOf");
-pub const get_approved: felt252 = selector!("get_approved");
-pub const getApproved: felt252 = selector!("getApproved");
-pub const is_approved_for_all: felt252 = selector!("is_approved_for_all");
-pub const isApprovedForAll: felt252 = selector!("isApprovedForAll");
-pub const approve: felt252 = selector!("approve");
-pub const set_approval_for_all: felt252 = selector!("set_approval_for_all");
-pub const setApprovalForAll: felt252 = selector!("setApprovalForAll");
-pub const transfer_from: felt252 = selector!("transfer_from");
-pub const transferFrom: felt252 = selector!("transferFrom");
-pub const safe_transfer_from: felt252 = selector!("safe_transfer_from");
-pub const safeTransferFrom: felt252 = selector!("safeTransferFrom");
-
-//
-// ERC721Receiver
-//
-
-pub const on_erc721_received: felt252 = selector!("on_erc721_received");
-pub const onERC721Received: felt252 = selector!("onERC721Received");
-
-//
-// ERC1155
-//
-
-// The following ERC1155 selectors are already defined in ERC721 above:
-// balance_of, balanceOf, set_approval_for_all,
-// setApprovalForAll, safe_transfer_from, safeTransferFrom
-pub const uri: felt252 = selector!("uri");
-pub const balance_of_batch: felt252 = selector!("balance_of_batch");
-pub const balanceOfBatch: felt252 = selector!("balanceOfBatch");
-pub const safe_batch_transfer_from: felt252 = selector!("safe_batch_transfer_from");
-pub const safeBatchTransferFrom: felt252 = selector!("safeBatchTransferFrom");
-
-//
-// ERC1155Receiver
-//
-
-pub const on_erc1155_received: felt252 = selector!("on_erc1155_received");
-pub const onERC1155Received: felt252 = selector!("onERC1155Received");
-pub const on_erc1155_batch_received: felt252 = selector!("on_erc1155_batch_received");
-pub const onERC1155BatchReceived: felt252 = selector!("onERC1155BatchReceived");
-
-//
-// ERC20
-//
-
-// The following ERC20 selectors are already defined in ERC721 above:
-// name, symbol, balance_of, balanceOf, transfer_from, transferFrom, approve
-pub const decimals: felt252 = selector!("decimals");
-pub const total_supply: felt252 = selector!("total_supply");
-pub const totalSupply: felt252 = selector!("totalSupply");
-pub const allowance: felt252 = selector!("allowance");
-pub const transfer: felt252 = selector!("transfer");
-
-//
-// Account
-//
-
-pub const set_public_key: felt252 = selector!("set_public_key");
-pub const setPublicKey: felt252 = selector!("setPublicKey");
-pub const get_public_key: felt252 = selector!("get_public_key");
-pub const getPublicKey: felt252 = selector!("getPublicKey");
-pub const is_valid_signature: felt252 = selector!("is_valid_signature");
-pub const isValidSignature: felt252 = selector!("isValidSignature");
-pub const supports_interface: felt252 = selector!("supports_interface");
diff --git a/packages/utils/src/unwrap_and_cast.cairo b/packages/utils/src/unwrap_and_cast.cairo
deleted file mode 100644
index a21d36004..000000000
--- a/packages/utils/src/unwrap_and_cast.cairo
+++ /dev/null
@@ -1,16 +0,0 @@
-// SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts for Cairo v0.17.0 (utils/unwrap_and_cast.cairo)
-
-use starknet::SyscallResult;
-use starknet::SyscallResultTrait;
-
-pub trait UnwrapAndCast<T> {
-    fn unwrap_and_cast(self: SyscallResult<Span<felt252>>) -> T;
-}
-
-impl UnwrapAndCastSerde<T, +Serde<T>> of UnwrapAndCast<T> {
-    fn unwrap_and_cast(self: SyscallResult<Span<felt252>>) -> T {
-        let mut result = self.unwrap_syscall();
-        Serde::<T>::deserialize(ref result).unwrap()
-    }
-}


Test patch:
diff --git a/packages/presets/src/tests/test_account.cairo b/packages/presets/src/tests/test_account.cairo
index b38996e6d..541bd1757 100644
--- a/packages/presets/src/tests/test_account.cairo
+++ b/packages/presets/src/tests/test_account.cairo
@@ -19,7 +19,6 @@ use openzeppelin_testing::constants::{
 };
 use openzeppelin_testing::signing::StarkKeyPair;
 use openzeppelin_token::erc20::interface::IERC20DispatcherTrait;
-use openzeppelin_utils::selectors;
 use openzeppelin_utils::serde::SerializedAppend;
 use snforge_std::{
     start_cheat_signature_global, start_cheat_transaction_version_global,
@@ -350,7 +349,7 @@ fn test_execute_with_version(version: Option<felt252>) {
     calldata.append_serde(amount);
 
     let call = Call {
-        to: erc20.contract_address, selector: selectors::transfer, calldata: calldata.span()
+        to: erc20.contract_address, selector: selector!("transfer"), calldata: calldata.span()
     };
     let calls = array![call];
 
@@ -441,7 +440,7 @@ fn test_multicall() {
     calldata1.append_serde(recipient1);
     calldata1.append_serde(amount1);
     let call1 = Call {
-        to: erc20.contract_address, selector: selectors::transfer, calldata: calldata1.span()
+        to: erc20.contract_address, selector: selector!("transfer"), calldata: calldata1.span()
     };
 
     // Craft 2nd call
@@ -450,7 +449,7 @@ fn test_multicall() {
     calldata2.append_serde(recipient2);
     calldata2.append_serde(amount2);
     let call2 = Call {
-        to: erc20.contract_address, selector: selectors::transfer, calldata: calldata2.span()
+        to: erc20.contract_address, selector: selector!("transfer"), calldata: calldata2.span()
     };
 
     // Bundle calls and execute
diff --git a/packages/presets/src/tests/test_eth_account.cairo b/packages/presets/src/tests/test_eth_account.cairo
index cfb3f0c14..a46d39c64 100644
--- a/packages/presets/src/tests/test_eth_account.cairo
+++ b/packages/presets/src/tests/test_eth_account.cairo
@@ -21,7 +21,6 @@ use openzeppelin_testing::constants::{CLASS_HASH_ZERO, ZERO, RECIPIENT, CALLER,
 use openzeppelin_testing::constants::{SALT, QUERY_VERSION, MIN_TRANSACTION_VERSION};
 use openzeppelin_testing::signing::Secp256k1KeyPair;
 use openzeppelin_token::erc20::interface::IERC20DispatcherTrait;
-use openzeppelin_utils::selectors;
 use openzeppelin_utils::serde::SerializedAppend;
 use snforge_std::{
     start_cheat_signature_global, start_cheat_transaction_version_global,
@@ -328,7 +327,7 @@ fn test_execute_with_version(version: Option<felt252>) {
     calldata.append_serde(amount);
 
     let call = Call {
-        to: erc20.contract_address, selector: selectors::transfer, calldata: calldata.span()
+        to: erc20.contract_address, selector: selector!("transfer"), calldata: calldata.span()
     };
     let calls = array![call];
 
@@ -398,7 +397,7 @@ fn test_multicall() {
     calldata1.append_serde(recipient1);
     calldata1.append_serde(amount1);
     let call1 = Call {
-        to: erc20.contract_address, selector: selectors::transfer, calldata: calldata1.span()
+        to: erc20.contract_address, selector: selector!("transfer"), calldata: calldata1.span()
     };
 
     // Craft 2nd call
@@ -407,7 +406,7 @@ fn test_multicall() {
     calldata2.append_serde(recipient2);
     calldata2.append_serde(amount2);
     let call2 = Call {
-        to: erc20.contract_address, selector: selectors::transfer, calldata: calldata2.span()
+        to: erc20.contract_address, selector: selector!("transfer"), calldata: calldata2.span()
     };
 
     let calls = array![call1, call2];