diff --git a/CHANGELOG.md b/CHANGELOG.md index b5fabf9c9..1ce5304eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Changed + +- Decoupled openzeppelin_utils version from the umbrella package (#1531) +- Removed openzeppelin_governance dependency on openzeppelin_account (#1531) +- Removed openzeppelin_token dependency on openzeppelin_account (#1531) + +### Changed (Breaking) + +- Removed `execute_single_call`, `execute_calls` and `assert_valid_signature` from openzeppelin_account::utils (#1531) + ## 3.0.0-alpha.2 (2025-09-10) ### Added diff --git a/Scarb.lock b/Scarb.lock index 4dfd5a50f..1fee63273 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -64,7 +64,6 @@ name = "openzeppelin_governance" version = "3.0.0-alpha.2" dependencies = [ "openzeppelin_access", - "openzeppelin_account", "openzeppelin_interfaces", "openzeppelin_introspection", "openzeppelin_test_common", @@ -76,7 +75,7 @@ dependencies = [ [[package]] name = "openzeppelin_interfaces" -version = "2.1.0" +version = "2.1.0-alpha.0" dependencies = [ "snforge_std", ] @@ -161,7 +160,6 @@ name = "openzeppelin_token" version = "3.0.0-alpha.2" dependencies = [ "openzeppelin_access", - "openzeppelin_account", "openzeppelin_interfaces", "openzeppelin_introspection", "openzeppelin_test_common", @@ -181,7 +179,7 @@ dependencies = [ [[package]] name = "openzeppelin_utils" -version = "3.0.0-alpha.2" +version = "3.1.0-alpha.0" dependencies = [ "openzeppelin_interfaces", "openzeppelin_test_common", diff --git a/Scarb.toml b/Scarb.toml index 8df1e0f52..86976bc70 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -43,8 +43,8 @@ keywords = [ ] [workspace.dependencies] -assert_macros = "2.12.0" -starknet = "2.12.0" +assert_macros = "2.12.2" +starknet = "2.12.2" snforge_std = "0.50.0" [dependencies] diff --git a/docs/modules/ROOT/pages/api/utilities.adoc b/docs/modules/ROOT/pages/api/utilities.adoc index 01c712321..f87367e2e 100644 --- a/docs/modules/ROOT/pages/api/utilities.adoc +++ b/docs/modules/ROOT/pages/api/utilities.adoc @@ -1,10 +1,23 @@ = Utilities +include::../utils/_common.adoc[] + :deploy_syscall: link:https://docs.starknet.io/architecture-and-concepts/smart-contracts/system-calls-cairo1/#deploy[deploy_syscall] :eip6372: link:https://eips.ethereum.org/EIPS/eip-6372[EIP-6372] This crate provides miscellaneous components and libraries containing utility functions to handle common tasks. +[IMPORTANT] +==== +This API reference is for the `openzeppelin_utils` package version `v{current_openzeppelin_utils_version}`. + +The `openzeppelin` package is an umbrella (meta) package that aggregates all library subpackages. Prior to v3.x, the umbrella and its subpackages were +versioned in lockstep—their versions always matched. Starting with v3.x, following the introduction of `openzeppelin_interfaces`, the umbrella is +versioned independently from some of the subpackages. + +See the xref:../index.adoc#versioning_of_the_sub_packages[Versioning of the sub-packages] section for more information. +==== + == Core [.contract] diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 23148e647..ffaa439a8 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -23,8 +23,8 @@ before proceeding, and run the following command to check that the installation ---- $ scarb --version -scarb 2.12.0 (639d0a65e 2025-08-04) -cairo: 2.12.0 (https://crates.io/crates/cairo-lang-compiler/2.12.0) +scarb 2.12.2 (dc0dbfd50 2025-09-15) +cairo: 2.12.2 (https://crates.io/crates/cairo-lang-compiler/2.12.2) sierra: 1.7.0 ---- @@ -59,13 +59,9 @@ Scarb.toml src [IMPORTANT] ==== -The `openzeppelin` package is an umbrella package that includes all the packages in the library. -Before version `3.x.x`, the `openzeppelin` and its sub-packages -were versioned together meaning that the version of the `openzeppelin` -package was the same as the version of the sub-packages. - -Starting from version `3.x.x`, with the introduction of the `openzeppelin_interfaces` package, -the `openzeppelin` package is versioned independently from the sub-packages. +The `openzeppelin` package is an umbrella (meta) package that aggregates all library subpackages. Prior to v3.x, the umbrella and its subpackages were +versioned in lockstep—their versions always matched. Starting with v3.x, following the introduction of `openzeppelin_interfaces`, the umbrella is +versioned independently from some of the subpackages. See the {versioning} section for more information. ==== @@ -109,7 +105,9 @@ openzeppelin_presets = "3.0.0-alpha.2" openzeppelin_security = "3.0.0-alpha.2" openzeppelin_token = "3.0.0-alpha.2" openzeppelin_upgrades = "3.0.0-alpha.2" -openzeppelin_utils = "3.0.0-alpha.2" + +openzeppelin_interfaces = "{current_openzeppelin_interfaces_version}" +openzeppelin_utils = "{current_openzeppelin_utils_version}" ---- == Basic usage diff --git a/docs/modules/ROOT/pages/utils/_common.adoc b/docs/modules/ROOT/pages/utils/_common.adoc index ce4beffdf..b5f574649 100644 --- a/docs/modules/ROOT/pages/utils/_common.adoc +++ b/docs/modules/ROOT/pages/utils/_common.adoc @@ -6,4 +6,5 @@ :immutable-config: xref:components.adoc#immutable_config[Immutable Component Config] // Variables -:current_openzeppelin_interfaces_version: 2.1.0 \ No newline at end of file +:current_openzeppelin_interfaces_version: 2.1.0-alpha.0 +:current_openzeppelin_utils_version: 3.1.0-alpha.0 diff --git a/packages/account/src/account.cairo b/packages/account/src/account.cairo index 196040003..77df3f1ca 100644 --- a/packages/account/src/account.cairo +++ b/packages/account/src/account.cairo @@ -14,9 +14,10 @@ pub mod AccountComponent { use openzeppelin_introspection::src5::SRC5Component::{ InternalTrait as SRC5InternalTrait, SRC5Impl, }; + use openzeppelin_utils::execution::execute_single_call; use starknet::account::Call; use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; - use crate::utils::{execute_single_call, is_tx_version_valid, is_valid_stark_signature}; + use crate::utils::{is_tx_version_valid, is_valid_stark_signature}; #[storage] pub struct Storage { diff --git a/packages/account/src/eth_account.cairo b/packages/account/src/eth_account.cairo index f41596a83..ba6e033c4 100644 --- a/packages/account/src/eth_account.cairo +++ b/packages/account/src/eth_account.cairo @@ -15,12 +15,13 @@ pub mod EthAccountComponent { use openzeppelin_introspection::src5::SRC5Component::{ InternalTrait as SRC5InternalTrait, SRC5Impl, }; + use openzeppelin_utils::execution::execute_single_call; use starknet::SyscallResultTrait; use starknet::account::Call; use starknet::secp256_trait::Secp256PointTrait; use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; use crate::utils::secp256_point::Secp256PointStorePacking; - use crate::utils::{execute_single_call, is_tx_version_valid, is_valid_eth_signature}; + use crate::utils::{is_tx_version_valid, is_valid_eth_signature}; #[storage] pub struct Storage { diff --git a/packages/account/src/extensions/src9/src9.cairo b/packages/account/src/extensions/src9/src9.cairo index d167c0454..54bc3de97 100644 --- a/packages/account/src/extensions/src9/src9.cairo +++ b/packages/account/src/extensions/src9/src9.cairo @@ -15,9 +15,9 @@ pub mod SRC9Component { use openzeppelin_introspection::src5::SRC5Component; use openzeppelin_introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait; use openzeppelin_utils::cryptography::snip12::{OffchainMessageHash, SNIP12Metadata}; + use openzeppelin_utils::execution::{assert_valid_signature, execute_calls}; use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; use crate::extensions::src9::snip12_utils::OutsideExecutionStructHash; - use crate::utils::{assert_valid_signature, execute_calls}; #[storage] pub struct Storage { diff --git a/packages/account/src/tests.cairo b/packages/account/src/tests.cairo index 97f0f3dba..1d84fc250 100644 --- a/packages/account/src/tests.cairo +++ b/packages/account/src/tests.cairo @@ -4,4 +4,3 @@ mod test_account; mod test_eth_account; mod test_secp256_point; mod test_signature; -mod test_utils; diff --git a/packages/account/src/utils.cairo b/packages/account/src/utils.cairo index 9848ccd84..ef0cbbe98 100644 --- a/packages/account/src/utils.cairo +++ b/packages/account/src/utils.cairo @@ -3,50 +3,14 @@ pub mod secp256_point; pub mod signature; -use openzeppelin_interfaces::accounts::{ISRC6Dispatcher, ISRC6DispatcherTrait}; pub use signature::{is_valid_eth_signature, is_valid_p256_signature, is_valid_stark_signature}; -use starknet::account::Call; -use starknet::{ContractAddress, SyscallResultTrait}; pub const MIN_TRANSACTION_VERSION: u256 = 1; pub const QUERY_OFFSET: u256 = 0x100000000000000000000000000000000; // QUERY_OFFSET + TRANSACTION_VERSION pub const QUERY_VERSION: u256 = 0x100000000000000000000000000000001; -/// Executes a list of calls and returns the return values. -pub fn execute_calls(calls: Span) -> Array> { - let mut res = array![]; - for call in calls { - res.append(execute_single_call(call)); - } - res -} - -/// Executes a single call and returns the return value. -pub fn execute_single_call(call: @Call) -> Span { - let Call { to, selector, calldata } = *call; - starknet::syscalls::call_contract_syscall(to, selector, calldata).unwrap_syscall() -} - -/// Validates a signature using SRC6 `is_valid_signature` and asserts it's valid. -/// Checks both 'VALID' (starknet::VALIDATED) and true (1) for backwards compatibility. -pub fn assert_valid_signature( - signer: ContractAddress, - hash: felt252, - signature: Span, - invalid_signature_error: felt252, -) { - let is_valid_signature_felt = ISRC6Dispatcher { contract_address: signer } - .is_valid_signature(hash, signature.into()); - - // Check either 'VALID' or true for backwards compatibility - let is_valid_signature = is_valid_signature_felt == starknet::VALIDATED - || is_valid_signature_felt == 1; - - assert(is_valid_signature, invalid_signature_error); -} - /// If the transaction is a simulation (version >= `QUERY_OFFSET`), it must be /// greater than or equal to `QUERY_OFFSET` + `MIN_TRANSACTION_VERSION` to be considered valid. /// Otherwise, it must be greater than or equal to `MIN_TRANSACTION_VERSION`. diff --git a/packages/governance/Scarb.toml b/packages/governance/Scarb.toml index 6a2c5ca5a..c2c40bb38 100644 --- a/packages/governance/Scarb.toml +++ b/packages/governance/Scarb.toml @@ -27,7 +27,6 @@ starknet.workspace = true openzeppelin_access = { path = "../access" } openzeppelin_interfaces = { path = "../interfaces" } openzeppelin_introspection = { path = "../introspection" } -openzeppelin_account = { path = "../account" } openzeppelin_token = { path= "../token" } openzeppelin_utils = { path = "../utils" } diff --git a/packages/governance/src/governor/governor.cairo b/packages/governance/src/governor/governor.cairo index 25eab8ec2..7875d3871 100644 --- a/packages/governance/src/governor/governor.cairo +++ b/packages/governance/src/governor/governor.cairo @@ -10,12 +10,12 @@ pub mod GovernorComponent { use core::num::traits::Zero; use core::pedersen::PedersenTrait; use core::traits::PartialEq; - use openzeppelin_account::utils::assert_valid_signature; use openzeppelin_interfaces::governor::{IGOVERNOR_ID, IGovernor, ProposalState}; use openzeppelin_introspection::src5::SRC5Component; use openzeppelin_introspection::src5::SRC5Component::InternalImpl as SRC5InternalImpl; use openzeppelin_utils::bytearray::ByteArrayExtTrait; use openzeppelin_utils::cryptography::snip12::{OffchainMessageHash, SNIP12Metadata}; + use openzeppelin_utils::execution::assert_valid_signature; use starknet::account::Call; use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess}; use starknet::{ContractAddress, SyscallResultTrait}; diff --git a/packages/governance/src/votes/votes.cairo b/packages/governance/src/votes/votes.cairo index d55deaf52..74be1de29 100644 --- a/packages/governance/src/votes/votes.cairo +++ b/packages/governance/src/votes/votes.cairo @@ -25,7 +25,6 @@ #[starknet::component] pub mod VotesComponent { use core::num::traits::Zero; - use openzeppelin_account::utils::assert_valid_signature; use openzeppelin_interfaces::erc20::IERC20; use openzeppelin_interfaces::erc721::IERC721; use openzeppelin_interfaces::votes::IVotes; @@ -34,6 +33,7 @@ pub mod VotesComponent { use openzeppelin_token::erc721::ERC721Component; use openzeppelin_utils::contract_clock::ERC6372Clock; use openzeppelin_utils::cryptography::snip12::{OffchainMessageHash, SNIP12Metadata}; + use openzeppelin_utils::execution::assert_valid_signature; use openzeppelin_utils::nonces::NoncesComponent; use openzeppelin_utils::nonces::NoncesComponent::InternalTrait as NoncesInternalTrait; use openzeppelin_utils::structs::checkpoint::{Checkpoint, Trace, TraceTrait}; diff --git a/packages/interfaces/CHANGELOG.md b/packages/interfaces/CHANGELOG.md new file mode 100644 index 000000000..9ee5ecdc6 --- /dev/null +++ b/packages/interfaces/CHANGELOG.md @@ -0,0 +1,15 @@ + + +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 2.1.0-alpha.0 (2025-09-17) + +### Added + +- Moved interfaces, ABIs and dispatchers into `openzeppelin_interfaces` (#1463) + - Some structs and types that were defined inside interface files were also moved \ No newline at end of file diff --git a/packages/interfaces/Scarb.toml b/packages/interfaces/Scarb.toml index 5a2e6a134..2f8133a06 100644 --- a/packages/interfaces/Scarb.toml +++ b/packages/interfaces/Scarb.toml @@ -1,7 +1,7 @@ [package] name = "openzeppelin_interfaces" -version = "2.1.0" +version = "2.1.0-alpha.0" readme = "README.md" keywords = [ "openzeppelin", diff --git a/packages/token/Scarb.toml b/packages/token/Scarb.toml index 60d5bc03b..aac06ba58 100644 --- a/packages/token/Scarb.toml +++ b/packages/token/Scarb.toml @@ -26,7 +26,6 @@ scarb.workspace = true [dependencies] starknet.workspace = true openzeppelin_access = { path = "../access" } -openzeppelin_account = { path = "../account" } openzeppelin_interfaces = { path = "../interfaces" } openzeppelin_introspection = { path = "../introspection" } openzeppelin_utils = { path = "../utils" } diff --git a/packages/token/src/erc20/erc20.cairo b/packages/token/src/erc20/erc20.cairo index c7b0f0bae..0c1ba4665 100644 --- a/packages/token/src/erc20/erc20.cairo +++ b/packages/token/src/erc20/erc20.cairo @@ -13,13 +13,13 @@ #[starknet::component] pub mod ERC20Component { use core::num::traits::{Bounded, Zero}; - use openzeppelin_account::utils::assert_valid_signature; use openzeppelin_interfaces::erc20 as interface; use openzeppelin_interfaces::nonces::INonces; use openzeppelin_interfaces::snip12::ISNIP12Metadata; use openzeppelin_utils::cryptography::snip12::{ OffchainMessageHash, SNIP12Metadata, StarknetDomain, StructHash, }; + use openzeppelin_utils::execution::assert_valid_signature; use openzeppelin_utils::nonces::NoncesComponent; use openzeppelin_utils::nonces::NoncesComponent::InternalTrait as NoncesInternalTrait; use starknet::ContractAddress; diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md new file mode 100644 index 000000000..b4f55fd2b --- /dev/null +++ b/packages/utils/CHANGELOG.md @@ -0,0 +1,18 @@ + + +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 3.1.0-alpha.0 (2025-09-17) + +### Added + +- `execution` module including `execute_single_call`, `execute_calls` and `assert_valid_signature` (#1531) + +### Changed + +- Decoupled version from the umbrella package (#1531) diff --git a/packages/utils/README.md b/packages/utils/README.md index 635e1e403..a41628f04 100644 --- a/packages/utils/README.md +++ b/packages/utils/README.md @@ -9,6 +9,7 @@ This crate provides components and libraries containing miscellaneous utilities. - [`utils`](https://docs.openzeppelin.com/contracts-cairo/3.0.0-alpha.2/api/utilities#utils) - [`cryptography`](https://docs.openzeppelin.com/contracts-cairo/3.0.0-alpha.2/api/utilities#cryptography) - [`deployments`](https://docs.openzeppelin.com/contracts-cairo/3.0.0-alpha.2/api/utilities#deployments) +- [`execution`] (https://docs.openzeppelin.com/contracts-cairo/3.0.0-alpha.2/api/utilities#execution) - [`math`](https://docs.openzeppelin.com/contracts-cairo/3.0.0-alpha.2/api/utilities#math) - [`serde`](https://docs.openzeppelin.com/contracts-cairo/3.0.0-alpha.2/api/utilities#serde) diff --git a/packages/utils/Scarb.toml b/packages/utils/Scarb.toml index 2329302b9..5b2c8959b 100644 --- a/packages/utils/Scarb.toml +++ b/packages/utils/Scarb.toml @@ -1,6 +1,7 @@ [package] name = "openzeppelin_utils" +version = "3.1.0-alpha.0" readme = "README.md" keywords = [ "openzeppelin", @@ -9,7 +10,6 @@ keywords = [ "standards", "utils" ] -version.workspace = true edition.workspace = true cairo-version.workspace = true scarb-version.workspace = true @@ -42,3 +42,9 @@ fuzzing = [] allowed-libfuncs-list.name = "experimental" sierra = true casm = false + +[[test]] +name = "openzeppelin_utils_unittest" +build-external-contracts = [ + "openzeppelin_test_common::mocks::account::DualCaseAccountMock", +] diff --git a/packages/utils/src/execution.cairo b/packages/utils/src/execution.cairo new file mode 100644 index 000000000..af084d494 --- /dev/null +++ b/packages/utils/src/execution.cairo @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts for Cairo v3.0.0-alpha.2 (utils/src/execution.cairo) + +use openzeppelin_interfaces::accounts::{ISRC6Dispatcher, ISRC6DispatcherTrait}; +use starknet::account::Call; +use starknet::{ContractAddress, SyscallResultTrait}; + +/// Executes a list of calls and returns the return values. +pub fn execute_calls(calls: Span) -> Array> { + let mut res = array![]; + for call in calls { + res.append(execute_single_call(call)); + } + res +} + +/// Executes a single call and returns the return value. +pub fn execute_single_call(call: @Call) -> Span { + let Call { to, selector, calldata } = *call; + starknet::syscalls::call_contract_syscall(to, selector, calldata).unwrap_syscall() +} + +/// Validates a signature using SRC6 `is_valid_signature` and asserts it's valid. +/// Checks both 'VALID' (starknet::VALIDATED) and true (1) for backwards compatibility. +pub fn assert_valid_signature( + signer: ContractAddress, + hash: felt252, + signature: Span, + invalid_signature_error: felt252, +) { + let is_valid_signature_felt = ISRC6Dispatcher { contract_address: signer } + .is_valid_signature(hash, signature.into()); + + // Check either 'VALID' or true for backwards compatibility + let is_valid_signature = is_valid_signature_felt == starknet::VALIDATED + || is_valid_signature_felt == 1; + + assert(is_valid_signature, invalid_signature_error); +} diff --git a/packages/utils/src/lib.cairo b/packages/utils/src/lib.cairo index 3950b8852..c8fbd6d22 100644 --- a/packages/utils/src/lib.cairo +++ b/packages/utils/src/lib.cairo @@ -2,6 +2,7 @@ pub mod bytearray; pub mod contract_clock; pub mod cryptography; pub mod deployments; +pub mod execution; pub mod math; pub mod serde; pub mod structs; diff --git a/packages/utils/src/tests.cairo b/packages/utils/src/tests.cairo index 81ae04f74..3716a4cb7 100644 --- a/packages/utils/src/tests.cairo +++ b/packages/utils/src/tests.cairo @@ -1,4 +1,5 @@ mod test_checkpoint; +mod test_execution; #[cfg(feature: 'fuzzing')] mod test_fuzz_checkpoint; #[cfg(feature: 'fuzzing')] diff --git a/packages/account/src/tests/test_utils.cairo b/packages/utils/src/tests/test_execution.cairo similarity index 97% rename from packages/account/src/tests/test_utils.cairo rename to packages/utils/src/tests/test_execution.cairo index 5c21654f0..6b96f3a5f 100644 --- a/packages/account/src/tests/test_utils.cairo +++ b/packages/utils/src/tests/test_execution.cairo @@ -2,7 +2,7 @@ use openzeppelin_testing::constants::{TRANSACTION_HASH, stark}; use openzeppelin_testing::declare_and_deploy; use openzeppelin_testing::signing::SerializedSigning; use starknet::ContractAddress; -use crate::utils::assert_valid_signature; +use crate::execution::assert_valid_signature; // // Setup diff --git a/scripts/benchmarking/benchmark.py b/scripts/benchmarking/benchmark.py index 9e0675538..fe86f613f 100644 --- a/scripts/benchmarking/benchmark.py +++ b/scripts/benchmarking/benchmark.py @@ -51,7 +51,7 @@ def get_sierra_contract_class_size(json_path): def benchmark_contracts(target_dir): results = {BYTECODE_KEY: {}, CONTRACT_CLASS_KEY: {}} - for file in os.listdir(target_dir): + for file in sorted(os.listdir(target_dir)): if file.endswith(".compiled_contract_class.json"): path = os.path.join(target_dir, file) try: