Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion content/contracts-cairo/2.x/wizard.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ contract and learn about the components offered in OpenZeppelin Contracts for Ca
We strongly recommend checking the [Components](./components) section to understand how to extend from our library.
</Callout>

<OZWizard lang="cairo" version="2.0.0" />
import { UMBRELLA_VERSION } from "./utils/constants.js";

<OZWizard lang="cairo" version={UMBRELLA_VERSION} />
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ The most common and basic form of access control is the concept of ownership: th
of a contract and can do administrative tasks on it.
This approach is perfectly reasonable for contracts that have a single administrative user.

OpenZeppelin Contracts for Cairo provides [OwnableComponent](/contracts-cairo/alpha/api/access#OwnableComponent) for implementing ownership in your contracts.
OpenZeppelin Contracts for Cairo provides [OwnableComponent](/contracts-cairo/3.x/api/access#OwnableComponent) for implementing ownership in your contracts.

### Usage

Integrating this component into a contract first requires assigning an owner.
The implementing contract’s constructor should set the initial owner by passing the owner’s address to Ownable’s
[`initializer`](/contracts-cairo/alpha/api/access#OwnableComponent-initializer) like this:
[`initializer`](/contracts-cairo/3.x/api/access#OwnableComponent-initializer) like this:

```rust
#[starknet::contract]
Expand Down Expand Up @@ -106,7 +106,7 @@ will no longer be callable!
### Two step transfer

The component also offers a more robust way of transferring ownership via the
[OwnableTwoStepImpl](/contracts-cairo/alpha/api/access#OwnableComponent-Embeddable-Impls-OwnableTwoStepImpl) implementation. A two step transfer mechanism helps
[OwnableTwoStepImpl](/contracts-cairo/3.x/api/access#OwnableComponent-Embeddable-Impls-OwnableTwoStepImpl) implementation. A two step transfer mechanism helps
to prevent unintended and irreversible owner transfers. Simply replace the `OwnableMixinImpl`
with its respective two step variant:

Expand Down Expand Up @@ -146,7 +146,7 @@ flexibility in this regard.

In essence, we will be defining multiple roles, each allowed to perform different sets of actions.
An account may have, for example, 'moderator', 'minter' or 'admin' roles, which you will then check for
instead of simply using [`assert_only_owner`](/contracts-cairo/alpha/api/access#OwnableComponent-assert_only_owner). This check can be enforced through [`assert_only_role`](/contracts-cairo/alpha/api/access#AccessControlComponent-assert_only_role).
instead of simply using [`assert_only_owner`](/contracts-cairo/3.x/api/access#OwnableComponent-assert_only_owner). This check can be enforced through [`assert_only_role`](/contracts-cairo/3.x/api/access#AccessControlComponent-assert_only_role).
Separately, you will be able to define rules for how accounts can be granted a role, have it revoked, and more.

Most software uses access control systems that are role-based: some users are regular users, some may be supervisors
Expand All @@ -158,7 +158,7 @@ For each role that you want to define, you will create a new _role identifier_ t
check if an account has that role. See [Creating role identifiers](#creating-role-identifiers) for information
on creating identifiers.

Here’s a simple example of implementing [AccessControl](/contracts-cairo/alpha/api/access#AccessControlComponent) on a portion of an ERC20 token contract which defines
Here’s a simple example of implementing [AccessControl](/contracts-cairo/3.x/api/access#AccessControlComponent) on a portion of an ERC20 token contract which defines
and sets a 'minter' role:

```rust
Expand Down Expand Up @@ -242,12 +242,12 @@ mod MyContract {
```

<Callout type='warn'>
Make sure you fully understand how [AccessControl](/contracts-cairo/alpha/api/access#AccessControlComponent) works before
Make sure you fully understand how [AccessControl](/contracts-cairo/3.x/api/access#AccessControlComponent) works before
using it on your system, or copy-pasting the examples from this guide.
</Callout>

While clear and explicit, this isn’t anything we wouldn’t have been able to achieve with
[Ownable](/contracts-cairo/alpha/api/access#OwnableComponent). Where [AccessControl](/contracts-cairo/alpha/api/access#AccessControlComponent) shines the most is in scenarios where granular
[Ownable](/contracts-cairo/3.x/api/access#OwnableComponent). Where [AccessControl](/contracts-cairo/3.x/api/access#AccessControlComponent) shines the most is in scenarios where granular
permissions are required, which can be implemented by defining _multiple_ roles.

Let’s augment our ERC20 token example by also defining a 'burner' role, which lets accounts destroy tokens:
Expand Down Expand Up @@ -350,16 +350,16 @@ security practice. Note that each account may still have more than one role, if

### Granting and revoking roles

The ERC20 token example above uses [`_grant_role`](/contracts-cairo/alpha/api/access#AccessControlComponent-_grant_role),
The ERC20 token example above uses [`_grant_role`](/contracts-cairo/3.x/api/access#AccessControlComponent-_grant_role),
an `internal` function that is useful when programmatically assigning
roles (such as during construction). But what if we later want to grant the 'minter' role to additional accounts?

By default, **accounts with a role cannot grant it or revoke it from other accounts**: all having a role does is making
the [`assert_only_role`](/contracts-cairo/alpha/api/access#AccessControlComponent-assert_only_role) check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.
the [`assert_only_role`](/contracts-cairo/3.x/api/access#AccessControlComponent-assert_only_role) check pass. To grant and revoke roles dynamically, you will need help from the role’s _admin_.

Every role has an associated admin role, which grants permission to call the
[`grant_role`](/contracts-cairo/alpha/api/access#AccessControlComponent-grant_role) and
[`revoke_role`](/contracts-cairo/alpha/api/access#AccessControlComponent-revoke_role) functions.
[`grant_role`](/contracts-cairo/3.x/api/access#AccessControlComponent-grant_role) and
[`revoke_role`](/contracts-cairo/3.x/api/access#AccessControlComponent-revoke_role) functions.
A role can be granted or revoked by using these if the calling account has the corresponding admin role.
Multiple roles may have the same admin role to make management easier.
A role’s admin can even be the same role itself, which would cause accounts with that role to be able
Expand All @@ -369,9 +369,9 @@ This mechanism can be used to create complex permissioning structures resembling
provides an easy way to manage simpler applications. `AccessControl` includes a special role with the role identifier
of `0`, called `DEFAULT_ADMIN_ROLE`, which acts as the **default admin role for all roles**.
An account with this role will be able to manage any other role, unless
[`set_role_admin`](/contracts-cairo/alpha/api/access#AccessControlComponent-set_role_admin) is used to select a new admin role.
[`set_role_admin`](/contracts-cairo/3.x/api/access#AccessControlComponent-set_role_admin) is used to select a new admin role.

Since it is the admin for all roles by default, and in fact it is also its own admin, this role carries significant risk. To mitigate this risk we provide [AccessControlDefaultAdminRules](/contracts-cairo/alpha/api/access#AccessControlDefaultAdminRulesComponent), a recommended extension of AccessControl that adds a number of enforced security measures for this role: the admin is restricted to a single account, with a 2-step transfer procedure with a delay in between steps.
Since it is the admin for all roles by default, and in fact it is also its own admin, this role carries significant risk. To mitigate this risk we provide [AccessControlDefaultAdminRules](/contracts-cairo/3.x/api/access#AccessControlDefaultAdminRulesComponent), a recommended extension of AccessControl that adds a number of enforced security measures for this role: the admin is restricted to a single account, with a 2-step transfer procedure with a delay in between steps.

Let’s take a look at the ERC20 token example, this time taking advantage of the default admin role:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ A more detailed discussion on the topic can be found in
[Starknet Shaman’s forum](https://community.starknet.io/t/starknet-account-abstraction-model-part-1/781).

<Callout>
For detailed information on the usage and implementation check the [API Reference](/contracts-cairo/alpha/api/account) section.
For detailed information on the usage and implementation check the [API Reference](/contracts-cairo/3.x/api/account) section.
</Callout>

## What is an account?
Expand Down Expand Up @@ -97,11 +97,11 @@ Starknet native account abstraction pattern allows for the creation of custom ac
usually most account implementations validate transactions using the [Stark curve](https://docs.starknet.io/learn/protocol/cryptography#the-stark-curve) which is the most efficient way
of validating signatures since it is a STARK-friendly curve.

OpenZeppelin Contracts for Cairo provides [AccountComponent](/contracts-cairo/alpha/api/account#AccountComponent) for implementing this validation scheme.
OpenZeppelin Contracts for Cairo provides [AccountComponent](/contracts-cairo/3.x/api/account#AccountComponent) for implementing this validation scheme.

### Usage

Constructing an account contract requires integrating both [AccountComponent](/contracts-cairo/alpha/api/account#AccountComponent) and [SRC5Component](/contracts-cairo/alpha/api/introspection#SRC5Component). The contract should also set up the constructor to initialize the public key that will be used as the account’s signer. Here’s an example of a basic contract:
Constructing an account contract requires integrating both [AccountComponent](/contracts-cairo/3.x/api/account#AccountComponent) and [SRC5Component](/contracts-cairo/3.x/api/introspection#SRC5Component). The contract should also set up the constructor to initialize the public key that will be used as the account’s signer. Here’s an example of a basic contract:

```rust
#[starknet::contract(account)]
Expand Down Expand Up @@ -180,11 +180,11 @@ pub trait AccountABI {
## Ethereum Account

Besides the Stark-curve account, OpenZeppelin Contracts for Cairo also offers Ethereum-flavored accounts that use the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1) curve for signature validation.
For this the [EthAccountComponent](/contracts-cairo/alpha/api/account#EthAccountComponent) must be used.
For this the [EthAccountComponent](/contracts-cairo/3.x/api/account#EthAccountComponent) must be used.

### Usage

Constructing a secp256k1 account contract also requires integrating both [EthAccountComponent](/contracts-cairo/alpha/api/account#EthAccountComponent) and [SRC5Component](/contracts-cairo/alpha/api/introspection#SRC5Component).
Constructing a secp256k1 account contract also requires integrating both [EthAccountComponent](/contracts-cairo/3.x/api/account#EthAccountComponent) and [SRC5Component](/contracts-cairo/3.x/api/introspection#SRC5Component).
The contract should also set up the constructor to initialize the public key that will be used as the account’s signer.
Here’s an example of a basic contract:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ Functions
- [`change_default_admin_delay(new_delay)`](#IAccessControlDefaultAdminRules-change_default_admin_delay)
- [`rollback_default_admin_delay()`](#IAccessControlDefaultAdminRules-rollback_default_admin_delay)
- [`default_admin_delay_increase_wait()`](#IAccessControlDefaultAdminRules-default_admin_delay_increase_wait)
- [`maximum_default_admin_transfer_delay()`](#IAccessControlDefaultAdminRules-maximum_default_admin_transfer_delay)

Events

Expand Down Expand Up @@ -401,11 +402,25 @@ May emit a [DefaultAdminDelayChangeCanceled](#IAccessControlDefaultAdminRules-De
id="IAccessControlDefaultAdminRules-default_admin_delay_increase_wait"
kind="external"
>
Maximum time in seconds for an increase to [default\_admin\_delay](#IAccessControlDefaultAdminRules-default_admin_delay) (that is scheduled using [change\_default\_admin\_delay](#IAccessControlDefaultAdminRules-change_default_admin_delay)) to take effect. Defaults to 5 days.

When the [default\_admin\_delay](#IAccessControlDefaultAdminRules-default_admin_delay) is scheduled to be increased, it goes into effect after the new delay has passed with the purpose of giving enough time for reverting any accidental change (i.e. using milliseconds instead of seconds) that may lock the contract. However, to avoid excessive schedules, the wait is capped by this function and it can be overridden for a custom [default\_admin\_delay](#IAccessControlDefaultAdminRules-default_admin_delay) increase scheduling.
Maximum time in seconds for an increase to [default\_admin\_delay](#IAccessControlDefaultAdminRules-default_admin_delay) (that is scheduled using [change\_default\_admin\_delay](#IAccessControlDefaultAdminRules-change_default_admin_delay)) to take effect.

<Callout type='warn'>
Make sure to add a reasonable amount of time while overriding this value, otherwise, there’s a risk of setting a high new delay that goes into effect almost immediately without the possibility of human intervention in the case of an input error (e.g. set milliseconds instead of seconds).
</Callout>

Consider carefully the value set for `MAXIMUM_DEFAULT_ADMIN_TRANSFER_DELAY` too, since it will affect how fast you can recover from an accidental delay increase.
</APIItem>

<APIItem
functionSignature="maximum_default_admin_transfer_delay() → u64"
id="IAccessControlDefaultAdminRules-maximum_default_admin_transfer_delay"
kind="external"
>
Maximum time in seconds for a `default_admin` transfer delay.

<Callout type='warn'>
If `MAXIMUM_DEFAULT_ADMIN_TRANSFER_DELAY` is set too high, you might be unable to recover from an accidental delay increase for an extended period. Too low, and it unnecessarily restricts how much security delay you can impose for `default_admin` transfers. As a best practice, consider setting it in the 30-60 day range for a good balance between security and recoverability.
</Callout>
</APIItem>

#### Events [!toc] [#IAccessControlDefaultAdminRules-Events]
Expand Down Expand Up @@ -1148,6 +1163,7 @@ Embeddable Implementations
- [`change_default_admin_delay(self, new_delay)`](#IAccessControlDefaultAdminRules-change_default_admin_delay)
- [`rollback_default_admin_delay(self)`](#IAccessControlDefaultAdminRules-rollback_default_admin_delay)
- [`default_admin_delay_increase_wait(self)`](#IAccessControlDefaultAdminRules-default_admin_delay_increase_wait)
- [`maximum_default_admin_transfer_delay(self)`](#IAccessControlDefaultAdminRules-maximum_default_admin_transfer_delay)

#### AccessControlImpl [!toc] [#AccessControlDefaultAdminRulesComponent-Embeddable-Impls-AccessControlImpl]

Expand Down Expand Up @@ -1368,6 +1384,18 @@ Make sure to add a reasonable amount of time while overriding this value, otherw
</Callout>
</APIItem>

<APIItem
functionSignature="maximum_default_admin_transfer_delay(self: @ContractState) → u64"
id="AccessControlDefaultAdminRulesComponent-maximum_default_admin_transfer_delay"
kind="external"
>
Maximum time in seconds for a `default_admin` transfer delay.

<Callout type='warn'>
If `MAXIMUM_DEFAULT_ADMIN_TRANSFER_DELAY` is set too high, you might be unable to recover from an accidental delay increase for an extended period. Too low, and it unnecessarily restricts how much security delay you can impose for `default_admin` transfers. As a best practice, consider setting it in the 30-60 day range for a good balance between security and recoverability.
</Callout>
</APIItem>

<APIItem
functionSignature="has_role(self: @ContractState, role: felt252, account: ContractAddress) → bool"
id="AccessControlDefaultAdminRulesComponent-has_role"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,8 @@ Allows contracts to hook logic into deposit and withdraw transactions. This is w

ERC4626 preview methods must be inclusive of any entry or exit fees. Fees are calculated using [FeeConfigTrait](#ERC4626Component-FeeConfigTrait) methods and automatically adjust the final asset and share amounts. Fee transfers are handled in `ERC4626HooksTrait` methods.

When a vault implements fees on deposits or withdrawals (either in shares or assets), fee transfers must be handled in these hooks by library clients. This creates a non-atomic operation flow consisting of multiple state-changing steps: transferring assets, minting or burning shares, and transferring (or minting) fees. Between these steps, the vault's state is temporarily inconsistent: the asset-to-share conversion rate does not accurately reflect the vault's final state until all steps have completed. Therefore, it is critical to avoid making any external calls (including to the vault contract itself) or querying conversion rates during hook execution.

Special care must be taken when calling external contracts in these hooks. In that case, consider implementing reentrancy protections. For example, in the `withdraw` flow, the `withdraw_limit` is checked **before** the `before_withdraw` hook is invoked. If this hook performs a reentrant call that invokes `withdraw` again, the subsequent check on `withdraw_limit` will be done before the first withdrawal's core logic (e.g., burning shares and transferring assets) is executed. This could lead to bypassing withdrawal constraints or draining funds.

See the [ERC4626AssetsFeesMock](https://github.com/OpenZeppelin/cairo-contracts/tree/main/packages/test_common/src/mocks/erc4626.cairo#L253) and [ERC4626SharesFeesMock](https://github.com/OpenZeppelin/cairo-contracts/tree/main/packages/test_common/src/mocks/erc4626.cairo#L426) examples.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ Whether a proposal needs to be queued before execution. This indicates if the pr
Delay between when a proposal is created and when the vote starts. The unit this duration is expressed in depends on the clock (see [ERC-6372](https://eips.ethereum.org/EIPS/eip-6372)) this contract uses.

This can be increased to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.

While this function returns a u64 value, timepoints must fit into u48 according to the EIP-6372 specification. Consequently this value must fit in a u48 (when added to the current clock).
</APIItem>

<APIItem
Expand Down Expand Up @@ -1674,6 +1676,7 @@ Cast a vote.
Requirements:

- The proposal must be active.
- The current timepoint must be greater than the proposal's snapshot timepoint.

Emits a [VoteCast](#GovernorComponent-VoteCast) event.
</APIItem>
Expand All @@ -1688,6 +1691,7 @@ Cast a vote with a `reason`.
Requirements:

- The proposal must be active.
- The current timepoint must be greater than the proposal's snapshot timepoint.

Emits a [VoteCast](#GovernorComponent-VoteCast) event.
</APIItem>
Expand All @@ -1702,6 +1706,7 @@ Cast a vote with a `reason` and additional serialized `params`.
Requirements:

- The proposal must be active.
- The current timepoint must be greater than the proposal's snapshot timepoint.

Emits either:

Expand All @@ -1719,6 +1724,7 @@ Cast a vote using the `voter`'s signature.
Requirements:

- The proposal must be active.
- The current timepoint must be greater than the proposal's snapshot timepoint.
- The nonce in the signed message must match the account's current nonce.
- `voter` must implement `SRC6::is_valid_signature`.
- `signature` must be valid for the message hash.
Expand All @@ -1736,6 +1742,7 @@ Cast a vote with a `reason` and additional serialized `params` using the `voter`
Requirements:

- The proposal must be active.
- The current timepoint must be greater than the proposal's snapshot timepoint.
- The nonce in the signed message must match the account's current nonce.
- `voter` must implement `SRC6::is_valid_signature`.
- `signature` must be valid for the message hash.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This module provides:

To use it as a standalone package, you can add it in your `Scarb.toml` as follows:

`openzeppelin_merkle_tree = "3.0.0-alpha.1"`
`openzeppelin_merkle_tree = "3.0.0"`

## [](#modules)Modules

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ Returns the current timepoint determined by the contract's operational mode, int
Requirements:

- This function MUST always be non-decreasing.

While this function returns a u64 value, timepoints must fit into u48 according to the EIP-6372 specification.
</APIItem>

<APIItem
Expand Down
Loading
Loading