diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1dccc55bf..c4b10d16c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v3 - uses: software-mansion/setup-scarb@v1 with: - scarb-version: "0.7.0" + scarb-version: "2.3.0-rc1" - name: Markdown lint uses: DavidAnson/markdownlint-cli2-action@5b7c9f74fec47e6b15667b2cc23c63dff11e449e # v9 with: diff --git a/Scarb.toml b/Scarb.toml index ae994cfbc..3c0ae199b 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,7 +1,7 @@ [package] name = "openzeppelin" version = "0.7.0" -cairo-version = "2.2.0" +cairo-version = "2.3.0-rc0" authors = ["OpenZeppelin Community "] description = "OpenZeppelin Contracts written in Cairo for StarkNet, a decentralized ZK Rollup" documentation = "https://docs.openzeppelin.com/contracts-cairo" @@ -11,7 +11,7 @@ license-file = "LICENSE" keywords = ["openzeppelin", "starknet", "cairo", "contracts", "security", "standards"] [dependencies] -starknet = ">=2.2.0" +starknet = "=2.3.0-rc0" [lib] @@ -19,3 +19,6 @@ starknet = ">=2.2.0" allowed-libfuncs-list.name = "experimental" sierra = true casm = false + +[tool.fmt] +sort-module-level-items = true diff --git a/docs/modules/ROOT/pages/api/introspection.adoc b/docs/modules/ROOT/pages/api/introspection.adoc index df597087c..94608fba7 100644 --- a/docs/modules/ROOT/pages/api/introspection.adoc +++ b/docs/modules/ROOT/pages/api/introspection.adoc @@ -50,10 +50,10 @@ on how to compute this ID. use openzeppelin::introspection::src5::SRC5; ``` -SRC5 contract implementation extending xref:ISRC5[`ISRC5`]. +SRC5 component extending xref:ISRC5[`ISRC5`]. [.contract-index] -.External Functions +.Embeddable Implementations -- .SRC5Impl @@ -69,8 +69,8 @@ SRC5 contract implementation extending xref:ISRC5[`ISRC5`]. * xref:#SRC5-deregister_interface[`++deregister_interface(self, interface_id)++`] -- -[#SRC5-External-Functions] -==== External Functions +[#SRC5-Embeddable-Functions] +==== Embeddable Functions [.contract-item] [[SRC5-supports_interface]] @@ -83,12 +83,12 @@ See xref:ISRC5-supports_interface[`ISRC5::supports_interface`]. [.contract-item] [[SRC5-register_interface]] -==== `[.contract-item-name]#++register_interface++#++(ref self: ContractState, interface_id: felt252)++` [.item-kind]#internal# +==== `[.contract-item-name]#++register_interface++#++(ref self: ComponentState, interface_id: felt252)++` [.item-kind]#internal# Registers support for the given `interface_id`. [.contract-item] [[SRC5-deregister_interface]] -==== `[.contract-item-name]#++deregister_interface++#++(ref self: ContractState, interface_id: felt252)++` [.item-kind]#internal# +==== `[.contract-item-name]#++deregister_interface++#++(ref self: ComponentState, interface_id: felt252)++` [.item-kind]#internal# Deregisters support for the given `interface_id`. diff --git a/docs/modules/ROOT/pages/introspection.adoc b/docs/modules/ROOT/pages/introspection.adoc index 9c162374b..8eee8a939 100644 --- a/docs/modules/ROOT/pages/introspection.adoc +++ b/docs/modules/ROOT/pages/introspection.adoc @@ -35,24 +35,37 @@ extended function selectors. There are tools such as {src5-rs} that can help wit === Registering interfaces -For a contract to declare its support for a given interface, the contract should import the SRC5 module and -register its support. It's recommended to register interface support upon contract deployment through a constructor -either directly or indirectly (as an initializer) like this: +For a contract to declare its support for a given interface, we recommend using the SRC5 component to register support upon contract deployment through a constructor either directly or indirectly (as an initializer) like this: [,javascript] ---- #[starknet::contract] mod MyContract { use openzeppelin::account::interface; - use openzeppelin::introspection::src5::SRC5; + use openzeppelin::introspection::src5::SRC5 as src5_component; + + component!(path: src5_component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5Impl = src5_component::SRC5Impl; + impl InternalImpl = src5_component::InternalImpl; #[storage] - struct Storage {} + struct Storage { + #[substorage(v0)] + src5: src5_component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + SRC5Event: src5_component::Event + } #[constructor] fn constructor(ref self: ContractState) { - let mut unsafe_state = SRC5::unsafe_new_contract_state(); - SRC5::InternalImpl::register_interface(ref unsafe_state, interface::ISRC6_ID); + // Register the contract's support for the ISRC6 interface + self.src5.register_interface(interface::ISRC6_ID); } (...) @@ -70,7 +83,6 @@ mod MyContract { use openzeppelin::account::interface; use openzeppelin::introspection::interface::ISRC5DispatcherTrait; use openzeppelin::introspection::interface::ISRC5Dispatcher; - use openzeppelin::introspection::src5::SRC5; use starknet::ContractAddress; #[storage] diff --git a/src/access/accesscontrol/accesscontrol.cairo b/src/access/accesscontrol/accesscontrol.cairo index cd7cdde3a..beb7fffc5 100644 --- a/src/access/accesscontrol/accesscontrol.cairo +++ b/src/access/accesscontrol/accesscontrol.cairo @@ -4,17 +4,24 @@ #[starknet::contract] mod AccessControl { use openzeppelin::access::accesscontrol::interface; - use openzeppelin::introspection::interface::ISRC5; - use openzeppelin::introspection::interface::ISRC5Camel; - use openzeppelin::introspection::src5::SRC5; - use openzeppelin::introspection::src5::unsafe_state as src5_state; + use openzeppelin::introspection::src5::SRC5 as src5_component; use starknet::ContractAddress; use starknet::get_caller_address; + component!(path: src5_component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5Impl = src5_component::SRC5Impl; + #[abi(embed_v0)] + impl SRC5CamelImpl = src5_component::SRC5CamelImpl; + impl SRC5InternalImpl = src5_component::InternalImpl; + #[storage] struct Storage { AccessControl_role_admin: LegacyMap, AccessControl_role_member: LegacyMap<(felt252, ContractAddress), bool>, + #[substorage(v0)] + src5: src5_component::Storage } #[event] @@ -23,6 +30,7 @@ mod AccessControl { RoleGranted: RoleGranted, RoleRevoked: RoleRevoked, RoleAdminChanged: RoleAdminChanged, + SRC5Event: src5_component::Event } /// Emitted when `account` is granted `role`. @@ -64,20 +72,6 @@ mod AccessControl { const MISSING_ROLE: felt252 = 'Caller is missing role'; } - #[external(v0)] - impl SRC5Impl of ISRC5 { - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - SRC5::SRC5Impl::supports_interface(@src5_state(), interface_id) - } - } - - #[external(v0)] - impl SRC5CamelImpl of ISRC5Camel { - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - SRC5::SRC5CamelImpl::supportsInterface(@src5_state(), interfaceId) - } - } - #[external(v0)] impl AccessControlImpl of interface::IAccessControl { fn has_role(self: @ContractState, role: felt252, account: ContractAddress) -> bool { @@ -137,8 +131,7 @@ mod AccessControl { #[generate_trait] impl InternalImpl of InternalTrait { fn initializer(ref self: ContractState) { - let mut unsafe_state = src5_state(); - SRC5::InternalImpl::register_interface(ref unsafe_state, interface::IACCESSCONTROL_ID); + self.src5.register_interface(interface::IACCESSCONTROL_ID); } fn assert_only_role(self: @ContractState, role: felt252) { diff --git a/src/account/account.cairo b/src/account/account.cairo index ef73ef44a..30160dfbe 100644 --- a/src/account/account.cairo +++ b/src/account/account.cairo @@ -14,12 +14,8 @@ trait PublicKeyCamelTrait { #[starknet::contract] mod Account { use ecdsa::check_ecdsa_signature; - use openzeppelin::account::interface; - use openzeppelin::introspection::interface::ISRC5; - use openzeppelin::introspection::interface::ISRC5Camel; - use openzeppelin::introspection::src5::SRC5; - use openzeppelin::introspection::src5::unsafe_state as src5_state; + use openzeppelin::introspection::src5::SRC5 as src5_component; use starknet::account::Call; use starknet::get_caller_address; use starknet::get_contract_address; @@ -29,9 +25,19 @@ mod Account { // 2**128 + TRANSACTION_VERSION const QUERY_VERSION: felt252 = 0x100000000000000000000000000000001; + component!(path: src5_component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5Impl = src5_component::SRC5Impl; + #[abi(embed_v0)] + impl SRC5CamelImpl = src5_component::SRC5CamelImpl; + impl SRC5InternalImpl = src5_component::InternalImpl; + #[storage] struct Storage { - Account_public_key: felt252 + Account_public_key: felt252, + #[substorage(v0)] + src5: src5_component::Storage } #[event] @@ -39,6 +45,7 @@ mod Account { enum Event { OwnerAdded: OwnerAdded, OwnerRemoved: OwnerRemoved, + SRC5Event: src5_component::Event } #[derive(Drop, starknet::Event)] @@ -116,20 +123,6 @@ mod Account { } } - #[external(v0)] - impl SRC5Impl of ISRC5 { - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - SRC5::SRC5Impl::supports_interface(@src5_state(), interface_id) - } - } - - #[external(v0)] - impl SRC5CamelImpl of ISRC5Camel { - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - SRC5::SRC5CamelImpl::supportsInterface(@src5_state(), interfaceId) - } - } - #[external(v0)] impl PublicKeyImpl of super::PublicKeyTrait { fn get_public_key(self: @ContractState) -> felt252 { @@ -171,8 +164,7 @@ mod Account { #[generate_trait] impl InternalImpl of InternalTrait { fn initializer(ref self: ContractState, _public_key: felt252) { - let mut unsafe_state = src5_state(); - SRC5::InternalImpl::register_interface(ref unsafe_state, interface::ISRC6_ID); + self.src5.register_interface(interface::ISRC6_ID); self._set_public_key(_public_key); } @@ -204,14 +196,12 @@ mod Account { } } - #[internal] fn assert_only_self() { let caller = get_caller_address(); let self = get_contract_address(); assert(self == caller, Errors::UNAUTHORIZED); } - #[private] fn _execute_calls(mut calls: Array) -> Array> { let mut res = ArrayTrait::new(); loop { @@ -220,15 +210,12 @@ mod Account { let _res = _execute_single_call(call); res.append(_res); }, - Option::None(_) => { - break (); - }, + Option::None(_) => { break (); }, }; }; res } - #[private] fn _execute_single_call(call: Call) -> Span { let Call{to, selector, calldata } = call; starknet::call_contract_syscall(to, selector, calldata.span()).unwrap() diff --git a/src/introspection/src5.cairo b/src/introspection/src5.cairo index ec8ec85b5..461d04c4b 100644 --- a/src/introspection/src5.cairo +++ b/src/introspection/src5.cairo @@ -1,7 +1,10 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts for Cairo v0.7.0 (introspection/src5.cairo) -#[starknet::contract] +/// # SRC5 Component +/// +/// The SRC5 component allows contracts to expose the interfaces they implement. +#[starknet::component] mod SRC5 { use openzeppelin::introspection::interface; @@ -14,9 +17,14 @@ mod SRC5 { const INVALID_ID: felt252 = 'SRC5: invalid id'; } - #[external(v0)] - impl SRC5Impl of interface::ISRC5 { - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { + #[embeddable_as(SRC5Impl)] + impl SRC5< + TContractState, +HasComponent + > of interface::ISRC5> { + /// Returns whether the contract implements the given interface. + fn supports_interface( + self: @ComponentState, interface_id: felt252 + ) -> bool { if interface_id == interface::ISRC5_ID { return true; } @@ -24,27 +32,28 @@ mod SRC5 { } } - #[external(v0)] - impl SRC5CamelImpl of interface::ISRC5Camel { - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - SRC5Impl::supports_interface(self, interfaceId) + #[embeddable_as(SRC5CamelImpl)] + impl SRC5Camel< + TContractState, +HasComponent + > of interface::ISRC5Camel> { + fn supportsInterface(self: @ComponentState, interfaceId: felt252) -> bool { + self.supports_interface(interfaceId) } } #[generate_trait] - impl InternalImpl of InternalTrait { - fn register_interface(ref self: ContractState, interface_id: felt252) { + impl InternalImpl< + TContractState, +HasComponent + > of InternalTrait { + /// Registers the given interface as supported by the contract. + fn register_interface(ref self: ComponentState, interface_id: felt252) { self.SRC5_supported_interfaces.write(interface_id, true); } - fn deregister_interface(ref self: ContractState, interface_id: felt252) { + /// Deregisters the given interface as supported by the contract. + fn deregister_interface(ref self: ComponentState, interface_id: felt252) { assert(interface_id != interface::ISRC5_ID, Errors::INVALID_ID); self.SRC5_supported_interfaces.write(interface_id, false); } } } - -#[inline(always)] -fn unsafe_state() -> SRC5::ContractState { - SRC5::unsafe_new_contract_state() -} diff --git a/src/lib.cairo b/src/lib.cairo index ea35f72ca..71de24d54 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -2,9 +2,8 @@ mod access; mod account; mod introspection; mod security; +#[cfg(test)] +mod tests; mod token; mod upgrades; mod utils; - -#[cfg(test)] -mod tests; diff --git a/src/tests/access/test_dual_accesscontrol.cairo b/src/tests/access/test_dual_accesscontrol.cairo index b7f922963..5a666a6db 100644 --- a/src/tests/access/test_dual_accesscontrol.cairo +++ b/src/tests/access/test_dual_accesscontrol.cairo @@ -1,16 +1,16 @@ use openzeppelin::access::accesscontrol::DEFAULT_ADMIN_ROLE; +use openzeppelin::access::accesscontrol::dual_accesscontrol::DualCaseAccessControl; +use openzeppelin::access::accesscontrol::dual_accesscontrol::DualCaseAccessControlTrait; use openzeppelin::access::accesscontrol::interface::IACCESSCONTROL_ID; -use openzeppelin::access::accesscontrol::interface::IAccessControlDispatcherTrait; -use openzeppelin::access::accesscontrol::interface::IAccessControlDispatcher; -use openzeppelin::access::accesscontrol::interface::IAccessControlCamelDispatcherTrait; use openzeppelin::access::accesscontrol::interface::IAccessControlCamelDispatcher; -use openzeppelin::access::accesscontrol::dual_accesscontrol::DualCaseAccessControlTrait; -use openzeppelin::access::accesscontrol::dual_accesscontrol::DualCaseAccessControl; -use openzeppelin::tests::mocks::snake_accesscontrol_mock::SnakeAccessControlMock; -use openzeppelin::tests::mocks::camel_accesscontrol_mock::CamelAccessControlMock; -use openzeppelin::tests::mocks::accesscontrol_panic_mock::SnakeAccessControlPanicMock; +use openzeppelin::access::accesscontrol::interface::IAccessControlCamelDispatcherTrait; +use openzeppelin::access::accesscontrol::interface::IAccessControlDispatcher; +use openzeppelin::access::accesscontrol::interface::IAccessControlDispatcherTrait; use openzeppelin::tests::mocks::accesscontrol_panic_mock::CamelAccessControlPanicMock; +use openzeppelin::tests::mocks::accesscontrol_panic_mock::SnakeAccessControlPanicMock; +use openzeppelin::tests::mocks::camel_accesscontrol_mock::CamelAccessControlMock; use openzeppelin::tests::mocks::non_implementing_mock::NonImplementingMock; +use openzeppelin::tests::mocks::snake_accesscontrol_mock::SnakeAccessControlMock; use openzeppelin::tests::utils::constants::{ADMIN, AUTHORIZED, ROLE}; use openzeppelin::tests::utils; use openzeppelin::utils::serde::SerializedAppend; diff --git a/src/tests/access/test_ownable.cairo b/src/tests/access/test_ownable.cairo index 8bb58ac01..292bda3de 100644 --- a/src/tests/access/test_ownable.cairo +++ b/src/tests/access/test_ownable.cairo @@ -1,8 +1,8 @@ use openzeppelin::access::ownable::Ownable::InternalImpl; use openzeppelin::access::ownable::Ownable::OwnableCamelOnlyImpl; use openzeppelin::access::ownable::Ownable::OwnableImpl; -use openzeppelin::access::ownable::Ownable::OwnershipTransferred; use openzeppelin::access::ownable::Ownable::Ownable_owner::InternalContractMemberStateTrait; +use openzeppelin::access::ownable::Ownable::OwnershipTransferred; use openzeppelin::access::ownable::Ownable; use openzeppelin::tests::utils::constants::{ZERO, OTHER, OWNER}; use openzeppelin::tests::utils; diff --git a/src/tests/account/test_account.cairo b/src/tests/account/test_account.cairo index cef5a31e3..012277f4b 100644 --- a/src/tests/account/test_account.cairo +++ b/src/tests/account/test_account.cairo @@ -2,14 +2,14 @@ use openzeppelin::account::Account::OwnerAdded; use openzeppelin::account::Account::OwnerRemoved; use openzeppelin::account::Account::PublicKeyCamelImpl; use openzeppelin::account::Account::PublicKeyImpl; +use openzeppelin::account::Account::{TRANSACTION_VERSION, QUERY_VERSION}; use openzeppelin::account::Account; use openzeppelin::account::AccountABIDispatcher; use openzeppelin::account::AccountABIDispatcherTrait; -use openzeppelin::account::Account::{TRANSACTION_VERSION, QUERY_VERSION}; use openzeppelin::account::interface::ISRC6_ID; use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::tests::utils; use openzeppelin::tests::utils::constants::ZERO; +use openzeppelin::tests::utils; use openzeppelin::token::erc20::ERC20; use openzeppelin::token::erc20::interface::IERC20Dispatcher; use openzeppelin::token::erc20::interface::IERC20DispatcherTrait; diff --git a/src/tests/introspection/test_src5.cairo b/src/tests/introspection/test_src5.cairo index a8ca2b699..7c8023d29 100644 --- a/src/tests/introspection/test_src5.cairo +++ b/src/tests/introspection/test_src5.cairo @@ -1,25 +1,26 @@ -use openzeppelin::introspection::interface::ISRC5_ID; -use openzeppelin::introspection::src5::SRC5::InternalImpl; -use openzeppelin::introspection::src5::SRC5::SRC5Impl; -use openzeppelin::introspection::src5::SRC5; +use openzeppelin::introspection::interface::{ISRC5_ID, ISRC5}; +use openzeppelin::introspection::src5::SRC5::InternalTrait; +use openzeppelin::tests::mocks::src5_mocks::DualCaseSRC5Mock; const OTHER_ID: felt252 = 0x12345678; -fn STATE() -> SRC5::ContractState { - SRC5::contract_state_for_testing() +fn STATE() -> DualCaseSRC5Mock::ContractState { + DualCaseSRC5Mock::contract_state_for_testing() } #[test] #[available_gas(2000000)] fn test_default_behavior() { - let supports_default_interface = SRC5Impl::supports_interface(@STATE(), ISRC5_ID); + let state = @STATE(); + let supports_default_interface = state.src5.supports_interface(ISRC5_ID); assert(supports_default_interface, 'Should support base interface'); } #[test] #[available_gas(2000000)] fn test_not_registered_interface() { - let supports_unregistered_interface = SRC5Impl::supports_interface(@STATE(), OTHER_ID); + let state = @STATE(); + let supports_unregistered_interface = state.src5.supports_interface(OTHER_ID); assert(!supports_unregistered_interface, 'Should not support unregistered'); } @@ -27,8 +28,8 @@ fn test_not_registered_interface() { #[available_gas(2000000)] fn test_register_interface() { let mut state = STATE(); - InternalImpl::register_interface(ref state, OTHER_ID); - let supports_new_interface = SRC5Impl::supports_interface(@state, OTHER_ID); + state.src5.register_interface(OTHER_ID); + let supports_new_interface = state.src5.supports_interface(OTHER_ID); assert(supports_new_interface, 'Should support new interface'); } @@ -36,9 +37,9 @@ fn test_register_interface() { #[available_gas(2000000)] fn test_deregister_interface() { let mut state = STATE(); - InternalImpl::register_interface(ref state, OTHER_ID); - InternalImpl::deregister_interface(ref state, OTHER_ID); - let supports_old_interface = SRC5Impl::supports_interface(@state, OTHER_ID); + state.src5.register_interface(OTHER_ID); + state.src5.deregister_interface(OTHER_ID); + let supports_old_interface = state.src5.supports_interface(OTHER_ID); assert(!supports_old_interface, 'Should not support interface'); } @@ -47,5 +48,5 @@ fn test_deregister_interface() { #[should_panic(expected: ('SRC5: invalid id',))] fn test_deregister_default_interface() { let mut state = STATE(); - InternalImpl::deregister_interface(ref state, ISRC5_ID); + state.src5.deregister_interface(ISRC5_ID); } diff --git a/src/tests/mocks/dual721_receiver_mocks.cairo b/src/tests/mocks/dual721_receiver_mocks.cairo index a6e4f5f2a..ff0d65f3e 100644 --- a/src/tests/mocks/dual721_receiver_mocks.cairo +++ b/src/tests/mocks/dual721_receiver_mocks.cairo @@ -4,18 +4,32 @@ use openzeppelin::tests::mocks::erc721_receiver::ERC721Receiver; #[starknet::contract] mod SnakeERC721ReceiverMock { + use openzeppelin::introspection::src5::SRC5 as src5_component; use starknet::ContractAddress; use super::ERC721Receiver; use super::IERC721_RECEIVER_ID; - use super::SRC5; + + component!(path: src5_component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5Impl = src5_component::SRC5Impl; + impl InternalImpl = src5_component::InternalImpl; #[storage] - struct Storage {} + struct Storage { + #[substorage(v0)] + src5: src5_component::Storage, + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + SRC5Event: src5_component::Event + } #[constructor] fn constructor(ref self: ContractState) { - let mut unsafe_state = SRC5::unsafe_new_contract_state(); - SRC5::InternalImpl::register_interface(ref unsafe_state, IERC721_RECEIVER_ID); + self.src5.register_interface(IERC721_RECEIVER_ID); } #[external(v0)] @@ -29,28 +43,36 @@ mod SnakeERC721ReceiverMock { let unsafe_state = ERC721Receiver::unsafe_new_contract_state(); ERC721Receiver::on_erc721_received(@unsafe_state, operator, from, token_id, data) } - - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - let unsafe_state = ERC721Receiver::unsafe_new_contract_state(); - ERC721Receiver::supports_interface(@unsafe_state, interface_id) - } } #[starknet::contract] mod CamelERC721ReceiverMock { + use openzeppelin::introspection::src5::SRC5 as src5_component; use starknet::ContractAddress; use super::ERC721Receiver; use super::IERC721_RECEIVER_ID; - use super::SRC5; + + component!(path: src5_component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5CamelImpl = src5_component::SRC5CamelImpl; + impl InternalImpl = src5_component::InternalImpl; #[storage] - struct Storage {} + struct Storage { + #[substorage(v0)] + src5: src5_component::Storage, + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + SRC5Event: src5_component::Event + } #[constructor] fn constructor(ref self: ContractState) { - let mut unsafe_state = SRC5::unsafe_new_contract_state(); - SRC5::InternalImpl::register_interface(ref unsafe_state, IERC721_RECEIVER_ID); + self.src5.register_interface(IERC721_RECEIVER_ID); } #[external(v0)] @@ -64,12 +86,6 @@ mod CamelERC721ReceiverMock { let unsafe_state = ERC721Receiver::unsafe_new_contract_state(); ERC721Receiver::on_erc721_received(@unsafe_state, operator, from, tokenId, data) } - - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - let unsafe_state = ERC721Receiver::unsafe_new_contract_state(); - ERC721Receiver::supportsInterface(@unsafe_state, interfaceId) - } } #[starknet::contract] diff --git a/src/tests/mocks/erc721_receiver.cairo b/src/tests/mocks/erc721_receiver.cairo index 240246019..13f3037d4 100644 --- a/src/tests/mocks/erc721_receiver.cairo +++ b/src/tests/mocks/erc721_receiver.cairo @@ -4,33 +4,36 @@ use openzeppelin::tests::utils::constants::{FAILURE, SUCCESS}; mod ERC721Receiver { use openzeppelin::introspection::interface::ISRC5; use openzeppelin::introspection::interface::ISRC5Camel; + use openzeppelin::introspection::src5::SRC5 as src5_component; use openzeppelin::introspection::src5::SRC5; use openzeppelin::token::erc721::interface::IERC721Receiver; use openzeppelin::token::erc721::interface::IERC721ReceiverCamel; use openzeppelin::token::erc721::interface::IERC721_RECEIVER_ID; use starknet::ContractAddress; - #[storage] - struct Storage {} + component!(path: src5_component, storage: src5, event: SRC5Event); - #[constructor] - fn constructor(ref self: ContractState) { - let mut unsafe_state = SRC5::unsafe_new_contract_state(); - SRC5::InternalImpl::register_interface(ref unsafe_state, IERC721_RECEIVER_ID); + #[abi(embed_v0)] + impl SRC5Impl = src5_component::SRC5Impl; + #[abi(embed_v0)] + impl SRC5CamelImpl = src5_component::SRC5CamelImpl; + impl InternalImpl = src5_component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + src5: src5_component::Storage, } - impl ISRC5Impl of ISRC5 { - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - let unsafe_state = SRC5::unsafe_new_contract_state(); - SRC5::SRC5Impl::supports_interface(@unsafe_state, interface_id) - } + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + SRC5Event: src5_component::Event } - impl ISRC5CamelImpl of ISRC5Camel { - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - let unsafe_state = SRC5::unsafe_new_contract_state(); - SRC5::SRC5CamelImpl::supportsInterface(@unsafe_state, interfaceId) - } + #[constructor] + fn constructor(ref self: ContractState) { + self.src5.register_interface(IERC721_RECEIVER_ID); } impl ERC721ReceiverImpl of IERC721Receiver { @@ -61,16 +64,6 @@ mod ERC721Receiver { } } - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - ISRC5Impl::supports_interface(self, interface_id) - } - - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - ISRC5CamelImpl::supportsInterface(self, interfaceId) - } - #[external(v0)] fn on_erc721_received( self: @ContractState, diff --git a/src/tests/mocks/src5_mocks.cairo b/src/tests/mocks/src5_mocks.cairo index cebdd0910..d325d39e9 100644 --- a/src/tests/mocks/src5_mocks.cairo +++ b/src/tests/mocks/src5_mocks.cairo @@ -1,26 +1,71 @@ use openzeppelin::introspection::src5::SRC5; +#[starknet::contract] +mod DualCaseSRC5Mock { + use openzeppelin::introspection::src5::SRC5 as src5_component; + + component!(path: src5_component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5Impl = src5_component::SRC5Impl; + #[abi(embed_v0)] + impl SRC5CamelOnlyImpl = src5_component::SRC5CamelImpl; + impl InternalImpl = src5_component::InternalImpl; + + #[storage] + struct Storage { + #[substorage(v0)] + src5: src5_component::Storage + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + SRC5Event: src5_component::Event + } +} + #[starknet::contract] mod SnakeSRC5Mock { + use openzeppelin::introspection::src5::SRC5 as src5_component; + + component!(path: src5_component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5Impl = src5_component::SRC5Impl; + #[storage] - struct Storage {} + struct Storage { + #[substorage(v0)] + src5: src5_component::Storage + } - #[external(v0)] - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - let unsafe_state = super::SRC5::unsafe_new_contract_state(); - super::SRC5::SRC5Impl::supports_interface(@unsafe_state, interface_id) + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + SRC5Event: src5_component::Event } } #[starknet::contract] mod CamelSRC5Mock { + use openzeppelin::introspection::src5::SRC5 as src5_component; + + component!(path: src5_component, storage: src5, event: SRC5Event); + + #[abi(embed_v0)] + impl SRC5CamelImpl = src5_component::SRC5CamelImpl; + #[storage] - struct Storage {} + struct Storage { + #[substorage(v0)] + src5: src5_component::Storage + } - #[external(v0)] - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - let unsafe_state = super::SRC5::unsafe_new_contract_state(); - super::SRC5::SRC5CamelImpl::supportsInterface(@unsafe_state, interfaceId) + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + SRC5Event: src5_component::Event } } diff --git a/src/tests/mocks/upgrades_v1.cairo b/src/tests/mocks/upgrades_v1.cairo index b7391bc28..9391d37dc 100644 --- a/src/tests/mocks/upgrades_v1.cairo +++ b/src/tests/mocks/upgrades_v1.cairo @@ -20,11 +20,10 @@ trait UpgradesV1Trait { #[starknet::contract] mod UpgradesV1 { - use array::ArrayTrait; - use starknet::ClassHash; - use starknet::ContractAddress; use openzeppelin::upgrades::interface::IUpgradeable; use openzeppelin::upgrades::upgradeable::Upgradeable; + use starknet::ClassHash; + use starknet::ContractAddress; #[storage] struct Storage { diff --git a/src/tests/mocks/upgrades_v2.cairo b/src/tests/mocks/upgrades_v2.cairo index 69e4ec55f..6db611764 100644 --- a/src/tests/mocks/upgrades_v2.cairo +++ b/src/tests/mocks/upgrades_v2.cairo @@ -22,11 +22,10 @@ trait UpgradesV2Trait { #[starknet::contract] mod UpgradesV2 { - use array::ArrayTrait; - use starknet::ClassHash; - use starknet::ContractAddress; use openzeppelin::upgrades::interface::IUpgradeable; use openzeppelin::upgrades::upgradeable::Upgradeable; + use starknet::ClassHash; + use starknet::ContractAddress; #[storage] struct Storage { diff --git a/src/tests/security/test_pausable.cairo b/src/tests/security/test_pausable.cairo index faf1fcfc6..f1aff256e 100644 --- a/src/tests/security/test_pausable.cairo +++ b/src/tests/security/test_pausable.cairo @@ -5,8 +5,8 @@ use openzeppelin::security::pausable::Pausable::Unpaused; use openzeppelin::security::pausable::Pausable; use openzeppelin::tests::utils::constants::{CALLER, ZERO}; use openzeppelin::tests::utils; -use starknet::contract_address_const; use starknet::ContractAddress; +use starknet::contract_address_const; use starknet::testing; // diff --git a/src/tests/token/test_erc721.cairo b/src/tests/token/test_erc721.cairo index c0eb59bea..9b9016e95 100644 --- a/src/tests/token/test_erc721.cairo +++ b/src/tests/token/test_erc721.cairo @@ -21,8 +21,8 @@ use openzeppelin::token::erc721::ERC721::{ use openzeppelin::token::erc721::ERC721; use openzeppelin::token::erc721; use openzeppelin::utils::serde::SerializedAppend; -use starknet::contract_address_const; use starknet::ContractAddress; +use starknet::contract_address_const; use starknet::testing; // diff --git a/src/tests/upgrades/test_upgradeable.cairo b/src/tests/upgrades/test_upgradeable.cairo index fff1d8ed6..51eec586a 100644 --- a/src/tests/upgrades/test_upgradeable.cairo +++ b/src/tests/upgrades/test_upgradeable.cairo @@ -1,8 +1,8 @@ use openzeppelin::tests::mocks::upgrades_v1::IUpgradesV1Dispatcher; use openzeppelin::tests::mocks::upgrades_v1::IUpgradesV1DispatcherTrait; +use openzeppelin::tests::mocks::upgrades_v1::UpgradesV1; use openzeppelin::tests::mocks::upgrades_v2::IUpgradesV2Dispatcher; use openzeppelin::tests::mocks::upgrades_v2::IUpgradesV2DispatcherTrait; -use openzeppelin::tests::mocks::upgrades_v1::UpgradesV1; use openzeppelin::tests::mocks::upgrades_v2::UpgradesV2; use openzeppelin::tests::utils::constants::{CLASS_HASH_ZERO, ZERO}; use openzeppelin::tests::utils; diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo index 74ce5893a..2c429c5a3 100644 --- a/src/tests/utils.cairo +++ b/src/tests/utils.cairo @@ -1,10 +1,5 @@ mod constants; -use array::ArrayTrait; -use array::SpanTrait; -use core::result::ResultTrait; -use option::OptionTrait; -use starknet::class_hash::Felt252TryIntoClassHash; use starknet::ContractAddress; use starknet::testing; diff --git a/src/token/erc721/erc721.cairo b/src/token/erc721/erc721.cairo index 8572f50c8..baa9765cd 100644 --- a/src/token/erc721/erc721.cairo +++ b/src/token/erc721/erc721.cairo @@ -6,16 +6,20 @@ mod ERC721 { use openzeppelin::account; use openzeppelin::introspection::dual_src5::DualCaseSRC5; use openzeppelin::introspection::dual_src5::DualCaseSRC5Trait; - use openzeppelin::introspection::interface::ISRC5; - use openzeppelin::introspection::interface::ISRC5Camel; - use openzeppelin::introspection::src5::unsafe_state as src5_state; - use openzeppelin::introspection::src5; + use openzeppelin::introspection::src5::SRC5 as src5_component; use openzeppelin::token::erc721::dual721_receiver::DualCaseERC721Receiver; use openzeppelin::token::erc721::dual721_receiver::DualCaseERC721ReceiverTrait; use openzeppelin::token::erc721::interface; use starknet::ContractAddress; use starknet::get_caller_address; + component!(path: src5_component, storage: src5, event: SRC5Event); + #[abi(embed_v0)] + impl SRC5Impl = src5_component::SRC5Impl; + #[abi(embed_v0)] + impl SRC5CamelImpl = src5_component::SRC5CamelImpl; + impl SRC5InternalImpl = src5_component::InternalImpl; + #[storage] struct Storage { ERC721_name: felt252, @@ -25,6 +29,8 @@ mod ERC721 { ERC721_token_approvals: LegacyMap, ERC721_operator_approvals: LegacyMap<(ContractAddress, ContractAddress), bool>, ERC721_token_uri: LegacyMap, + #[substorage(v0)] + src5: src5_component::Storage } #[event] @@ -32,7 +38,8 @@ mod ERC721 { enum Event { Transfer: Transfer, Approval: Approval, - ApprovalForAll: ApprovalForAll + ApprovalForAll: ApprovalForAll, + SRC5Event: src5_component::Event } #[derive(Drop, starknet::Event)] @@ -93,20 +100,6 @@ mod ERC721 { // External // - #[external(v0)] - impl SRC5Impl of ISRC5 { - fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { - src5::SRC5::SRC5Impl::supports_interface(@src5_state(), interface_id) - } - } - - #[external(v0)] - impl SRC5CamelImpl of ISRC5Camel { - fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { - src5::SRC5::SRC5CamelImpl::supportsInterface(@src5_state(), interfaceId) - } - } - #[external(v0)] impl ERC721MetadataImpl of interface::IERC721Metadata { fn name(self: @ContractState) -> felt252 { @@ -244,11 +237,8 @@ mod ERC721 { self.ERC721_name.write(name); self.ERC721_symbol.write(symbol); - let mut unsafe_state = src5_state(); - src5::SRC5::InternalImpl::register_interface(ref unsafe_state, interface::IERC721_ID); - src5::SRC5::InternalImpl::register_interface( - ref unsafe_state, interface::IERC721_METADATA_ID - ); + self.src5.register_interface(interface::IERC721_ID); + self.src5.register_interface(interface::IERC721_METADATA_ID); } fn _owner_of(self: @ContractState, token_id: u256) -> ContractAddress { @@ -360,7 +350,6 @@ mod ERC721 { } } - #[internal] fn _check_on_erc721_received( from: ContractAddress, to: ContractAddress, token_id: u256, data: Span ) -> bool { diff --git a/src/upgrades.cairo b/src/upgrades.cairo index 9530af29a..f0e4647c0 100644 --- a/src/upgrades.cairo +++ b/src/upgrades.cairo @@ -1,4 +1,4 @@ -mod upgradeable; mod interface; +mod upgradeable; use upgradeable::Upgradeable;