diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 073041b0a..e5d984603 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -12,16 +12,10 @@ jobs: - name: Checkout repository uses: actions/checkout@v7 - - name: Extract current versions + - name: Extract current version run: | CURRENT_VERSION=$(grep '^version = ' Scarb.toml | sed 's/version = "\(.*\)"/\1/') - SCARB_VERSION=$(grep 'scarb-version = ' Scarb.toml | sed 's/scarb-version = "\(.*\)"/\1/') - CAIRO_VERSION=$(grep 'cairo-version = ' Scarb.toml | sed 's/cairo-version = "\(.*\)"/\1/') - { - echo "CURRENT_VERSION=$CURRENT_VERSION" - echo "SCARB_VERSION=$SCARB_VERSION" - echo "CAIRO_VERSION=$CAIRO_VERSION" - } >> "$GITHUB_ENV" + echo "CURRENT_VERSION=$CURRENT_VERSION" >> "$GITHUB_ENV" - name: Extract new version number run: echo "NEW_VERSION=${GITHUB_REF#refs/heads/release-v}" >> "$GITHUB_ENV" @@ -38,21 +32,7 @@ jobs: -not -path './audits/*' \ -exec sed -i "s/$ESCAPED_CURRENT_VERSION/$NEW_VERSION/g" {} + - - name: Setup scarb - uses: software-mansion/setup-scarb@v1 - id: setup_scarb - with: - scarb-version: ${{ env.SCARB_VERSION }} - - - name: Setup class_hash - uses: ericnordelo/setup-class-hash@c14dd33506c3eb8e1acfe2ade9f82585f5acf28c - with: - version: "0.2.0" - - - name: Build presets artifacts - run: scarb --release build -p openzeppelin_presets - - name: Auto-commit changes uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d #v7.2.0 with: - commit_message: Bump version to ${{ env.NEW_VERSION }} and update presets page + commit_message: Bump version to ${{ env.NEW_VERSION }} diff --git a/.gitignore b/.gitignore index 7c5877656..1df45648a 100644 --- a/.gitignore +++ b/.gitignore @@ -81,9 +81,6 @@ instance/ # Scrapy stuff: .scrapy -# Sphinx documentation -docs/_build/ - # Jupyter Notebook .ipynb_checkpoints @@ -144,8 +141,5 @@ dmypy.json # node **/node_modules/ -# docs -docs/build/ - # vscode .vscode/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0ace0a1e0..75f21f94c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,7 +37,7 @@ As a contributor, you are expected to fork this repository, work on your own for git checkout -b fix/some-bug-short-description-#123 ``` -3. Make your changes, add your files, and [update the documentation](#documentation). Make sure to update the [CHANGELOG](CHANGELOG.md) (*[learn how](https://keepachangelog.com/en/1.1.0/)*). +3. Make your changes, add your files, and [update the corresponding documentation](#documentation). Make sure to update the [CHANGELOG](CHANGELOG.md) (*[learn how](https://keepachangelog.com/en/1.1.0/)*). 4. Commit and push to your fork. @@ -68,27 +68,17 @@ As a contributor, you are expected to fork this repository, work on your own for ## Documentation -Before submitting the PR, you must update the corresponding documentation entries in the docs folder. In the future we may use something similar to solidity-docgen to automatically generate docs, but for now we are updating .adoc entries manually. +Documentation for Contracts for Cairo is maintained in the [OpenZeppelin Documentation repository](https://github.com/OpenZeppelin/docs/tree/main/content/contracts-cairo). When a contribution changes documented behavior, update the corresponding documentation in that repository. -NOTE: When the scarb version is bumped, the *Overview* page *Installation* section must be updated accordingly. +### Preset class hashes -If you want to run the documentation UI locally: +To generate the JavaScript constants used by the preset documentation, make sure `scarb` and `starkli` are installed and configured, then run: -1. Change directory into docs inside the project and run npm install. +```bash +python3 scripts/generate_class_hashes.py +``` - ```bash - cd docs && npm i - ``` - -2. Build the docs and run the local server (default to localhost:8080). This will watch for changes in the docs/module folder, and update the UI accordingly. - - ```bash - npm run docs:watch - ``` - -## Class hashes - -Every time there's a language bump or a change in a preset or component used by one, new class hashes should be checked and updated in the presets doc page. +The script builds the `openzeppelin_presets` release artifacts and prints the `CLASS_HASH_SCARB_VERSION` and `CLASS_HASHES` constants for every current preset. Copy them into the corresponding `content/contracts-cairo//utils/constants.js` file in the documentation repository and update the preset table when its entries change. Pass `--no-build` to reuse existing release artifacts. ## Integration tests diff --git a/docs/antora.yml b/docs/antora.yml deleted file mode 100644 index 8dc35df0b..000000000 --- a/docs/antora.yml +++ /dev/null @@ -1,8 +0,0 @@ -name: contracts-cairo -title: Contracts for Cairo -version: 4.0.0-alpha.1 -nav: - - modules/ROOT/nav.adoc -asciidoc: - attributes: - page-sidebar-collapse-default: 'Access,Accounts,Finance,Governance,Introspection,Security,ERC20,ERC721,ERC1155,ERC4626,ERC6909,Upgrades,Universal Deployer Contract' diff --git a/docs/modules/ROOT/pages/api/access.adoc b/docs/modules/ROOT/pages/api/access.adoc deleted file mode 100644 index edf31f62c..000000000 --- a/docs/modules/ROOT/pages/api/access.adoc +++ /dev/null @@ -1,1748 +0,0 @@ -:github-icon: pass:[] -:AccessControl: xref:AccessControlComponent[AccessControl] -:Ownable: xref:OwnableComponent[Ownable] -:src5: https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md[SRC5] -:inner-src5: xref:api/introspection.adoc#ISRC5[SRC5 ID] -:set_role_admin: xref:#AccessControlComponent-set_role_admin[set_role_admin] -:_grant_role: xref:#AccessControlComponent-_grant_role[_grant_role] -:_grant_role_with_delay: xref:#AccessControlComponent-_grant_role_with_delay[_grant_role_with_delay] - -= Access Control - -include::../utils/_common.adoc[] - -This crate provides ways to restrict who can access the functions of a contract or when they can do it. - -- {Ownable} is a simple mechanism with a single "owner" role that can be assigned to a single account. -This mechanism can be useful in simple scenarios, but fine grained access needs are likely to outgrow it. -- {AccessControl} provides a general role based access control mechanism. Multiple hierarchical roles can be created and -assigned each to multiple accounts. - -== Interfaces - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_access` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[IAccessControl]] -=== `++IAccessControl++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/access/accesscontrol.cairo[{github-icon},role=heading-link] - -:grant_role: xref:#IAccessControl-grant_role[grant_role] -:revoke_role: xref:#IAccessControl-revoke_role[revoke_role] -:RoleGranted: xref:#IAccessControl-RoleGranted[RoleGranted] -:RoleRevoked: xref:#IAccessControl-RoleRevoked[RoleRevoked] -:RoleAdminChanged: xref:#IAccessControl-RoleAdminChanged[RoleAdminChanged] - -```cairo -use openzeppelin_interfaces::accesscontrol::IAccessControl; -``` - -External interface of AccessControl. - -[.contract-index] -.{inner-src5} --- -0x23700be02858dbe2ac4dc9c9f66d0b6b0ed81ec7f970ca6844500a56ff61751 --- - -[.contract-index] -.Functions --- -* xref:IAccessControl-has_role[`++has_role(role, account)++`] -* xref:IAccessControl-get_role_admin[`++get_role_admin(role)++`] -* xref:IAccessControl-grant_role[`++grant_role(role, account)++`] -* xref:IAccessControl-revoke_role[`++revoke_role(role, account)++`] -* xref:IAccessControl-renounce_role[`++renounce_role(role, account)++`] --- - -[.contract-index] -.Events --- -* xref:IAccessControl-RoleAdminChanged[`++RoleAdminChanged(role, previous_admin_role, new_admin_role)++`] -* xref:IAccessControl-RoleGranted[`++RoleGranted(role, account, sender)++`] -* xref:IAccessControl-RoleRevoked[`++RoleRevoked(role, account, sender)++`] - --- - -[#IAccessControl-Functions] -==== Functions - -[.contract-item] -[[IAccessControl-has_role]] -==== `[.contract-item-name]#++has_role++#++(role: felt252, account: ContractAddress) → bool++` [.item-kind]#external# - -Returns whether `account` can act as `role`. - -[.contract-item] -[[IAccessControl-get_role_admin]] -==== `[.contract-item-name]#++get_role_admin++#++(role: felt252) → felt252++` [.item-kind]#external# - -Returns the admin role that controls `role`. See {grant_role} and -{revoke_role}. - -To change a role's admin, use {set_role_admin}. - -[.contract-item] -[[IAccessControl-grant_role]] -==== `[.contract-item-name]#++grant_role++#++(role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Grants `role` to `account`. - -If `account` had not been already granted `role`, emits a {RoleGranted} -event. - -Requirements: - -- the caller must have ``role``'s admin role. - -[.contract-item] -[[IAccessControl-revoke_role]] -==== `[.contract-item-name]#++revoke_role++#++(role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Revokes `role` from `account`. - -If `account` had been granted `role`, emits a {RoleRevoked} event. - -Requirements: - -- the caller must have ``role``'s admin role. - -[.contract-item] -[[IAccessControl-renounce_role]] -==== `[.contract-item-name]#++renounce_role++#++(role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Revokes `role` from the calling account. - -Roles are often managed via {grant_role} and {revoke_role}. This function's -purpose is to provide a mechanism for accounts to lose their privileges -if they are compromised (such as when a trusted device is misplaced). - -If the calling account had been granted `role`, emits a {RoleRevoked} -event. - -Requirements: - -- the caller must be `account`. - -[#IAccessControl-Events] -==== Events - -[.contract-item] -[[IAccessControl-RoleAdminChanged]] -==== `[.contract-item-name]#++RoleAdminChanged++#++(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)++` [.item-kind]#event# - -Emitted when `new_admin_role` is set as ``role``'s admin role, replacing `previous_admin_role` - -`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite -{RoleAdminChanged} not being emitted signaling this. - -[.contract-item] -[[IAccessControl-RoleGranted]] -==== `[.contract-item-name]#++RoleGranted++#++(role: felt252, account: ContractAddress, sender: ContractAddress)++` [.item-kind]#event# - -Emitted when `account` is granted `role`. - -`sender` is the account that originated the contract call, an account with the admin role -or the deployer address if `_grant_role` is called from the constructor. - -[.contract-item] -[[IAccessControl-RoleRevoked]] -==== `[.contract-item-name]#++RoleRevoked++#++(role: felt252, account: ContractAddress, sender: ContractAddress)++` [.item-kind]#event# - -Emitted when `account` is revoked `role`. - -`sender` is the account that originated the contract call: - -- if using `revoke_role`, it is the admin role bearer. -- if using `renounce_role`, it is the role bearer (i.e. `account`). - -[.contract] -[[IAccessControlWithDelay]] -=== `++IAccessControlWithDelay++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/access/accesscontrol.cairo[{github-icon},role=heading-link] - -:grant_role_with_delay: xref:#IAccessControlWithDelay-grant_role_with_delay[grant_role_with_delay] -:RoleGrantedWithDelay: xref:#IAccessControlWithDelay-RoleGrantedWithDelay[RoleGrantedWithDelay] - -```cairo -use openzeppelin_interfaces::accesscontrol::IAccessControlWithDelay; -``` - -External interface for the extended `AccessControlWithDelay` functionality. - -[.contract-index] -.Functions --- -* xref:IAccessControlWithDelay-get_role_status[`++get_role_status(role, account)++`] -* xref:IAccessControlWithDelay-grant_role_with_delay[`++grant_role_with_delay(role, account, delay)++`] --- - -[.contract-index] -.Events --- -* xref:IAccessControlWithDelay-RoleGrantedWithDelay[`++RoleGrantedWithDelay(role, account, sender, delay)++`] - --- - -[#IAccessControlWithDelay-Functions] -==== Functions - -[.contract-item] -[[IAccessControlWithDelay-get_role_status]] -==== `[.contract-item-name]#++get_role_status++#++(role: felt252, account: ContractAddress) → RoleStatus++` [.item-kind]#external# - -Returns the account's status for the given role. -The possible statuses are: - -- `NotGranted`: the role has not been granted to the account. -- `Delayed`: The role has been granted to the account but is not yet active due to a -time delay. -- `Effective`: the role has been granted to the account and is currently active. - -[.contract-item] -[[IAccessControlWithDelay-grant_role_with_delay]] -==== `[.contract-item-name]#++grant_role_with_delay++#++(role: felt252, account: ContractAddress, delay: u64)++` [.item-kind]#external# - -Attempts to grant `role` to `account` with the specified activation delay. - -Requirements: - -- The caller must have ``role``'s admin role. -- delay must be greater than 0. -- the `role` must not be already effective for `account`. - -May emit a {RoleGrantedWithDelay} event. - -[#IAccessControlWithDelay-Events] -==== Events - -[.contract-item] -[[IAccessControlWithDelay-RoleGrantedWithDelay]] -==== `[.contract-item-name]#++RoleGrantedWithDelay++#++(role: felt252, account: ContractAddress, sender: ContractAddress, delay: u64)++` [.item-kind]#event# - -Emitted when `account` is granted `role` with a delay. - -`sender` is the account that originated the contract call, an account with the admin role -or the deployer address if {_grant_role_with_delay} is called from the constructor. - -[.contract] -[[IAccessControlDefaultAdminRules]] -=== `++IAccessControlDefaultAdminRules++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/access/accesscontrol_default_admin_rules.cairo[{github-icon},role=heading-link] - -:grant_role: xref:#IAccessControl-grant_role[grant_role] - -```cairo -use openzeppelin_interfaces::accesscontrol_default_admin_rules::IAccessControlDefaultAdminRules; -``` - -External interface of AccessControlDefaultAdminRules declared to support {src5} detection. - -[.contract-index] -.{inner-src5} --- -0x3509b3083c9586afe5dae781146b0608c3846870510f8d4d21ae38676cc33eb --- - -[.contract-index] -.Functions --- -* xref:IAccessControlDefaultAdminRules-default_admin[`++default_admin()++`] -* xref:IAccessControlDefaultAdminRules-pending_default_admin[`++pending_default_admin()++`] -* xref:IAccessControlDefaultAdminRules-default_admin_delay[`++default_admin_delay()++`] -* xref:IAccessControlDefaultAdminRules-pending_default_admin_delay[`++pending_default_admin_delay()++`] -* xref:IAccessControlDefaultAdminRules-begin_default_admin_transfer[`++begin_default_admin_transfer(new_admin)++`] -* xref:IAccessControlDefaultAdminRules-cancel_default_admin_transfer[`++cancel_default_admin_transfer()++`] -* xref:IAccessControlDefaultAdminRules-accept_default_admin_transfer[`++accept_default_admin_transfer()++`] -* xref:IAccessControlDefaultAdminRules-change_default_admin_delay[`++change_default_admin_delay(new_delay)++`] -* xref:IAccessControlDefaultAdminRules-rollback_default_admin_delay[`++rollback_default_admin_delay()++`] -* xref:IAccessControlDefaultAdminRules-default_admin_delay_increase_wait[`++default_admin_delay_increase_wait()++`] --- - -[.contract-index] -.Events --- -* xref:IAccessControlDefaultAdminRules-DefaultAdminTransferScheduled[`++DefaultAdminTransferScheduled(new_admin, accept_schedule)++`] -* xref:IAccessControlDefaultAdminRules-DefaultAdminTransferCanceled[`++DefaultAdminTransferCanceled()++`] -* xref:IAccessControlDefaultAdminRules-DefaultAdminDelayChangeScheduled[`++DefaultAdminDelayChangeScheduled(new_delay, effect_schedule)++`] -* xref:IAccessControlDefaultAdminRules-DefaultAdminDelayChangeCanceled[`++DefaultAdminDelayChangeCanceled()++`] --- - -:default_admin_transfer_scheduled: xref:IAccessControlDefaultAdminRules-DefaultAdminTransferScheduled[DefaultAdminTransferScheduled] -:default_admin_transfer_canceled: xref:IAccessControlDefaultAdminRules-DefaultAdminTransferCanceled[DefaultAdminTransferCanceled] -:default_admin_delay_change_scheduled: xref:IAccessControlDefaultAdminRules-DefaultAdminDelayChangeScheduled[DefaultAdminDelayChangeScheduled] -:default_admin_delay_change_canceled: xref:IAccessControlDefaultAdminRules-DefaultAdminDelayChangeCanceled[DefaultAdminDelayChangeCanceled] - -:default_admin: xref:IAccessControlDefaultAdminRules-default_admin[default_admin] -:pending_default_admin: xref:IAccessControlDefaultAdminRules-pending_default_admin[pending_default_admin] -:default_admin_delay: xref:IAccessControlDefaultAdminRules-default_admin_delay[default_admin_delay] -:pending_default_admin_delay: xref:IAccessControlDefaultAdminRules-pending_default_admin_delay[pending_default_admin_delay] -:begin_default_admin_transfer: xref:IAccessControlDefaultAdminRules-begin_default_admin_transfer[begin_default_admin_transfer] -:cancel_default_admin_transfer: xref:IAccessControlDefaultAdminRules-cancel_default_admin_transfer[cancel_default_admin_transfer] -:accept_default_admin_transfer: xref:IAccessControlDefaultAdminRules-accept_default_admin_transfer[accept_default_admin_transfer] -:change_default_admin_delay: xref:IAccessControlDefaultAdminRules-change_default_admin_delay[change_default_admin_delay] -:rollback_default_admin_delay: xref:IAccessControlDefaultAdminRules-rollback_default_admin_delay[rollback_default_admin_delay] -:default_admin_delay_increase_wait: xref:IAccessControlDefaultAdminRules-default_admin_delay_increase_wait[default_admin_delay_increase_wait] - -[#IAccessControlDefaultAdminRules-Functions] -==== Functions - -[.contract-item] -[[IAccessControlDefaultAdminRules-default_admin]] -==== `[.contract-item-name]#++default_admin++#++() → ContractAddress++` [.item-kind]#external# - -Returns the address of the current `DEFAULT_ADMIN_ROLE` holder. - -[.contract-item] -[[IAccessControlDefaultAdminRules-pending_default_admin]] -==== `[.contract-item-name]#++pending_default_admin++#++() → (ContractAddress, u64)++` [.item-kind]#external# - -Returns a tuple of a `new_admin` and an `accept_schedule`. - -After the `accept_schedule` passes, the `new_admin` will be able to accept the -`default_admin` role by calling {accept_default_admin_transfer}, completing the role -transfer. - -A zero value only in `accept_schedule` indicates no pending admin transfer. - -NOTE: A zero address `new_admin` means that `default_admin` is being renounced. - -[.contract-item] -[[IAccessControlDefaultAdminRules-default_admin_delay]] -==== `[.contract-item-name]#++default_admin_delay++#++() → u64++` [.item-kind]#external# - -Returns the delay required to schedule the acceptance of a `default_admin` transfer started. - -This delay will be added to the current timestamp when calling -{begin_default_admin_transfer} to set the acceptance schedule. - -NOTE: If a delay change has been scheduled, it will take effect as soon as the schedule -passes, making this function return the new delay. - -See {change_default_admin_delay}. - -[.contract-item] -[[IAccessControlDefaultAdminRules-pending_default_admin_delay]] -==== `[.contract-item-name]#++pending_default_admin_delay++#++() → (u64, u64)++` [.item-kind]#external# - -Returns a tuple of `new_delay` and an `effect_schedule`. - -After the `effect_schedule` passes, the `new_delay` will get into effect immediately for -every new `default_admin` transfer started with {begin_default_admin_transfer}. - -A zero value only in `effect_schedule` indicates no pending delay change. - -NOTE: A zero value only for `new_delay` means that the next {default_admin_delay} -will be zero after the effect schedule. - -[.contract-item] -[[IAccessControlDefaultAdminRules-begin_default_admin_transfer]] -==== `[.contract-item-name]#++begin_default_admin_transfer++#++(new_admin)++` [.item-kind]#external# - -Starts a `default_admin` transfer by setting a {pending_default_admin} scheduled for -acceptance after the current timestamp plus a {default_admin_delay}. - -Requirements: - -- Only can be called by the current `default_admin`. - -Emits a {default_admin_transfer_scheduled} event. - -[.contract-item] -[[IAccessControlDefaultAdminRules-cancel_default_admin_transfer]] -==== `[.contract-item-name]#++cancel_default_admin_transfer++#++()++` [.item-kind]#external# - -Cancels a `default_admin` transfer previously started with {begin_default_admin_transfer}. - -A {pending_default_admin} not yet accepted can also be cancelled with this function. - -Requirements: - -- Only can be called by the current `default_admin`. - -May emit a {default_admin_transfer_canceled} event. - -[.contract-item] -[[IAccessControlDefaultAdminRules-accept_default_admin_transfer]] -==== `[.contract-item-name]#++accept_default_admin_transfer++#++()++` [.item-kind]#external# - -Completes a `default_admin` transfer previously started with {begin_default_admin_transfer}. - -After calling the function: - -- `DEFAULT_ADMIN_ROLE` must be granted to the caller. -- `DEFAULT_ADMIN_ROLE` must be revoked from the previous holder. -- {pending_default_admin} must be reset to zero value. - -Requirements: - -- Only can be called by the {pending_default_admin}'s `new_admin`. -- The {pending_default_admin}'s `accept_schedule` should've passed. - -[.contract-item] -[[IAccessControlDefaultAdminRules-change_default_admin_delay]] -==== `[.contract-item-name]#++change_default_admin_delay++#++(new_delay)++` [.item-kind]#external# - -Initiates a {default_admin_delay} update by setting a {pending_default_admin_delay} -scheduled to take effect after the current timestamp plus a {default_admin_delay}. - -This function guarantees that any call to {begin_default_admin_transfer} done between the -timestamp this method is called and the {pending_default_admin_delay} effect schedule will -use the current {default_admin_delay} set before calling. - -The {pending_default_admin_delay}'s effect schedule is defined in a way that waiting until -the schedule and then calling {begin_default_admin_transfer} with the new delay will take at -least the same as another `default_admin` complete transfer (including acceptance). - -The schedule is designed for two scenarios: - -- When the delay is changed for a larger one the schedule is `block.timestamp + new delay` -capped by {default_admin_delay_increase_wait}. -- When the delay is changed for a shorter one, the schedule is `block.timestamp + (current -delay - new delay)`. - -A {pending_default_admin_delay} that never got into effect will be canceled in favor of a -new scheduled change. - -Requirements: - -- Only can be called by the current `default_admin`. - -Emits a {default_admin_delay_change_scheduled} event and may emit a -{default_admin_delay_change_canceled} event. - -[.contract-item] -[[IAccessControlDefaultAdminRules-rollback_default_admin_delay]] -==== `[.contract-item-name]#++rollback_default_admin_delay++#++()++` [.item-kind]#external# - -Cancels a scheduled {default_admin_delay} change. - -Requirements: - -- Only can be called by the current `default_admin`. - -May emit a {default_admin_delay_change_canceled} event. - -[.contract-item] -[[IAccessControlDefaultAdminRules-default_admin_delay_increase_wait]] -==== `[.contract-item-name]#++default_admin_delay_increase_wait++#++() → u64++` [.item-kind]#external# - -Maximum time in seconds for an increase to {default_admin_delay} (that is scheduled using -{change_default_admin_delay}) to take effect. Defaults to 5 days. - -When the {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} increase -scheduling. - -IMPORTANT: 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). - -[#IAccessControlDefaultAdminRules-Events] -==== Events - -[.contract-item] -[[IAccessControlDefaultAdminRules-DefaultAdminTransferScheduled]] -==== `[.contract-item-name]#++DefaultAdminTransferScheduled++#++(new_admin: ContractAddress, accept_schedule: u64)++` [.item-kind]#event# - -Emitted when a `default_admin` transfer is started. - -Sets `new_admin` as the next address to become the `default_admin` by calling -{accept_default_admin_transfer} only after `accept_schedule` passes. - -[.contract-item] -[[IAccessControlDefaultAdminRules-DefaultAdminTransferCanceled]] -==== `[.contract-item-name]#++DefaultAdminTransferCanceled++#++()++` [.item-kind]#event# - -Emitted when a {pending_default_admin} is reset if it was never -accepted, regardless of its schedule. - -[.contract-item] -[[IAccessControlDefaultAdminRules-DefaultAdminDelayChangeScheduled]] -==== `[.contract-item-name]#++DefaultAdminDelayChangeScheduled++#++(new_delay: u64, effect_schedule: u64)++` [.item-kind]#event# - -Emitted when a {default_admin_delay} change is started. - -Sets `new_delay` as the next delay to be applied between default admins transfers -after `effect_schedule` has passed. - -[.contract-item] -[[IAccessControlDefaultAdminRules-DefaultAdminDelayChangeCanceled]] - -Emitted when a {pending_default_admin_delay} is reset if its schedule didn't pass. - -== Core - -[.contract] -[[OwnableComponent]] -=== `++OwnableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/access/src/ownable/ownable.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_access::ownable::OwnableComponent; -``` - -`Ownable` provides a basic access control mechanism where an account - (an owner) can be granted exclusive access to specific functions. - -This module includes the internal `assert_only_owner` to restrict a function to be used only by the owner. - -[.contract-index#OwnableComponent-Mixin-Impl] -.{mixin-impls} - --- -.OwnableMixinImpl - -* xref:#OwnableComponent-Embeddable-Impls-OwnableImpl[`++OwnableImpl++`] -* xref:#OwnableComponent-Embeddable-Impls-OwnableCamelOnlyImpl[`++OwnableCamelOnlyImpl++`] - -.OwnableTwoStepMixinImpl - -* xref:#OwnableComponent-Embeddable-Impls-OwnableTwoStepImpl[`++OwnableTwoStepImpl++`] -* xref:#OwnableComponent-Embeddable-Impls-OwnableTwoStepCamelOnlyImpl[`++OwnableTwoStepCamelOnlyImpl++`] --- - -[.contract-index#OwnableComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#OwnableComponent-Embeddable-Impls-OwnableImpl] -.OwnableImpl - -* xref:OwnableComponent-owner[`++owner(self)++`] -* xref:OwnableComponent-transfer_ownership[`++transfer_ownership(self, new_owner)++`] -* xref:OwnableComponent-renounce_ownership[`++renounce_ownership(self)++`] - -[.sub-index#OwnableComponent-Embeddable-Impls-OwnableTwoStepImpl] -.OwnableTwoStepImpl - -* xref:OwnableComponent-two-step-owner[`++owner(self)++`] -* xref:OwnableComponent-two-step-pending_owner[`++pending_owner(self)++`] -* xref:OwnableComponent-two-step-accept_ownership[`++accept_ownership(self)++`] -* xref:OwnableComponent-two-step-transfer_ownership[`++transfer_ownership(self, new_owner)++`] -* xref:OwnableComponent-two-step-renounce_ownership[`++renounce_ownership(self)++`] - -[.sub-index#OwnableComponent-Embeddable-Impls-OwnableCamelOnlyImpl] -.OwnableCamelOnlyImpl - -* xref:OwnableComponent-transferOwnership[`++transferOwnership(self, newOwner)++`] -* xref:OwnableComponent-renounceOwnership[`++renounceOwnership(self)++`] - -[.sub-index#OwnableComponent-Embeddable-Impls-OwnableTwoStepCamelOnlyImpl] -.OwnableTwoStepCamelOnlyImpl - -* xref:OwnableComponent-two-step-pendingOwner[`++pendingOwner(self)++`] -* xref:OwnableComponent-two-step-acceptOwnership[`++acceptOwnership(self)++`] -* xref:OwnableComponent-two-step-transferOwnership[`++transferOwnership(self, new_owner)++`] -* xref:OwnableComponent-two-step-renounceOwnership[`++renounceOwnership(self)++`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:OwnableComponent-initializer[`++initializer(self, owner)++`] -* xref:OwnableComponent-assert_only_owner[`++assert_only_owner(self)++`] -* xref:OwnableComponent-_transfer_ownership[`++_transfer_ownership(self, new_owner)++`] -* xref:OwnableComponent-_propose_owner[`++_propose_owner(self, new_owner)++`] --- - -[.contract-index] -.Events --- -* xref:OwnableComponent-OwnershipTransferStarted[`++OwnershipTransferStarted(previous_owner, new_owner)++`] -* xref:OwnableComponent-OwnershipTransferred[`++OwnershipTransferred(previous_owner, new_owner)++`] --- - -[#OwnableComponent-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[OwnableComponent-owner]] -==== `[.contract-item-name]#++owner++#++(self: @ContractState) → ContractAddress++` [.item-kind]#external# -// tag::owner[] -Returns the address of the current owner. -// end::owner[] - -[.contract-item] -[[OwnableComponent-transfer_ownership]] -==== `[.contract-item-name]#++transfer_ownership++#++(ref self: ContractState, new_owner: ContractAddress)++` [.item-kind]#external# - -Transfers ownership of the contract to a new account (`new_owner`). -Can only be called by the current owner. - -Emits an xref:OwnableComponent-OwnershipTransferred[OwnershipTransferred] event. - -[.contract-item] -[[OwnableComponent-renounce_ownership]] -==== `[.contract-item-name]#++renounce_ownership++#++(ref self: ContractState)++` [.item-kind]#external# -// tag::renounce_ownership[] -Leaves the contract without owner. It will not be possible to call -`assert_only_owner` functions anymore. Can only be called by the current owner. - -NOTE: Renouncing ownership will leave the contract without an owner, -thereby removing any functionality that is only available to the owner. -//end::renounce_ownership[] - -[#OwnableComponent-Embeddable-Functions-Two-Step] -==== Embeddable functions (two step transfer) - -[.contract-item] -[[OwnableComponent-two-step-owner]] -==== `[.contract-item-name]#++owner++#++(self: @ContractState) → ContractAddress++` [.item-kind]#external# -include::./access.adoc[tag=owner] - -[.contract-item] -[[OwnableComponent-two-step-pending_owner]] -==== `[.contract-item-name]#++pending_owner++#++(self: @ContractState) → ContractAddress++` [.item-kind]#external# - -Returns the address of the pending owner. - -[.contract-item] -[[OwnableComponent-two-step-accept_ownership]] -==== `[.contract-item-name]#++accept_ownership++#++(ref self: ContractState)++` [.item-kind]#external# - -Transfers ownership of the contract to the pending owner. -Can only be called by the pending owner. -Resets pending owner to zero address. - -Emits an xref:OwnableComponent-OwnershipTransferred[OwnershipTransferred] event. - -[.contract-item] -[[OwnableComponent-two-step-transfer_ownership]] -==== `[.contract-item-name]#++transfer_ownership++#++(ref self: ContractState, new_owner: ContractAddress)++` [.item-kind]#external# - -Starts the two step ownership transfer process, by setting the pending owner. Setting `new_owner` to the zero address is allowed, this can be used to cancel an initiated ownership transfer. - -Can only be called by the current owner. - -Emits an xref:OwnableComponent-OwnershipTransferStarted[OwnershipTransferStarted] event. - -[.contract-item] -[[OwnableComponent-two-step-renounce_ownership]] -==== `[.contract-item-name]#++renounce_ownership++#++(ref self: ContractState)++` [.item-kind]#external# -include::./access.adoc[tag=renounce_ownership] - -[.contract-item] -[[OwnableComponent-transferOwnership]] -==== `[.contract-item-name]#++transferOwnership++#++(ref self: ContractState, newOwner: ContractAddress)++` [.item-kind]#external# - -See xref:OwnableComponent-transfer_ownership[transfer_ownership]. - -[.contract-item] -[[OwnableComponent-renounceOwnership]] -==== `[.contract-item-name]#++renounceOwnership++#++(ref self: ContractState)++` [.item-kind]#external# - -See xref:OwnableComponent-renounce_ownership[renounce_ownership]. - -[.contract-item] -[[OwnableComponent-two-step-pendingOwner]] -==== `[.contract-item-name]#++pendingOwner++#++(self: @ContractState)++` [.item-kind]#external# - -See xref:OwnableComponent-two-step-pending_owner[pending_owner]. - -[.contract-item] -[[OwnableComponent-two-step-acceptOwnership]] -==== `[.contract-item-name]#++acceptOwnership++#++(self: @ContractState)++` [.item-kind]#external# - -See xref:OwnableComponent-two-step-accept_ownership[accept_ownership]. - -[.contract-item] -[[OwnableComponent-two-step-transferOwnership]] -==== `[.contract-item-name]#++transferOwnership++#++(self: @ContractState)++` [.item-kind]#external# - -See xref:OwnableComponent-two-step-transfer_ownership[transfer_ownership]. - -[.contract-item] -[[OwnableComponent-two-step-renounceOwnership]] -==== `[.contract-item-name]#++renounceOwnership++#++(self: @ContractState)++` [.item-kind]#external# - -See xref:OwnableComponent-two-step-renounce_ownership[renounce_ownership]. - -[#OwnableComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[OwnableComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, owner: ContractAddress)++` [.item-kind]#internal# - -Initializes the contract and sets `owner` as the initial owner. - -Requirements: - -- `owner` cannot be the zero address. - -Emits an xref:OwnableComponent-OwnershipTransferred[OwnershipTransferred] event. - -[.contract-item] -[[OwnableComponent-assert_only_owner]] -==== `[.contract-item-name]#++assert_only_owner++#++(self: @ContractState)++` [.item-kind]#internal# - -Panics if called by any account other than the owner. - -[.contract-item] -[[OwnableComponent-_transfer_ownership]] -==== `[.contract-item-name]#++_transfer_ownership++#++(ref self: ContractState, new_owner: ContractAddress)++` [.item-kind]#internal# - -Transfers ownership of the contract to a new account (`new_owner`). -Internal function without access restriction. - -Emits an xref:OwnableComponent-OwnershipTransferred[OwnershipTransferred] event. - -[.contract-item] -[[OwnableComponent-_propose_owner]] -==== `[.contract-item-name]#++_propose_owner++#++(ref self: ContractState, new_owner: ContractAddress)++` [.item-kind]#internal# - -Sets a new pending owner in a two step transfer. - -Internal function without access restriction. - -Emits an xref:OwnableComponent-OwnershipTransferStarted[OwnershipTransferStarted] event. - -[#OwnableComponent-Events] -==== Events - -[.contract-item] -[[OwnableComponent-OwnershipTransferStarted]] -==== `[.contract-item-name]#++OwnershipTransferStarted++#++(previous_owner: ContractAddress, new_owner: ContractAddress)++` [.item-kind]#event# - -Emitted when the pending owner is updated. - -[.contract-item] -[[OwnableComponent-OwnershipTransferred]] -==== `[.contract-item-name]#++OwnershipTransferred++#++(previous_owner: ContractAddress, new_owner: ContractAddress)++` [.item-kind]#event# - -Emitted when the ownership is transferred. - -[.contract] -[[AccessControlComponent]] -=== `++AccessControlComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/access/src/accesscontrol/accesscontrol.cairo[{github-icon},role=heading-link] - -:assert_only_role: xref:#AccessControlComponent-assert_only_role -:grant_role: xref:#AccessControlComponent-grant_role[grant_role] -:revoke_role: xref:#AccessControlComponent-revoke_role[revoke_role] - -```cairo -use openzeppelin_access::accesscontrol::AccessControlComponent; -``` - -Component that allows contracts to implement role-based access control mechanisms. -Roles are referred to by their `felt252` identifier: - -```cairo -const MY_ROLE: felt252 = selector!("MY_ROLE"); -``` - -Roles can be used to represent a set of permissions. To restrict access to a -function call, use {assert_only_role}[`assert_only_role`]: - -```cairo -(...) - -#[external(v0)] -fn foo(ref self: ContractState) { - self.accesscontrol.assert_only_role(MY_ROLE); - - // Do something -} -``` - -Roles can be granted and revoked dynamically via the {grant_role}, {grant_role_with_delay} and -{revoke_role} functions. Each role has an associated admin role, and only -accounts that have a role's admin role can call {grant_role}, {grant_role_with_delay} and {revoke_role}. - -By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means -that only accounts with this role will be able to grant or revoke other -roles. More complex role relationships can be created by using -{set_role_admin}. - -:AccessControlDefaultAdminRulesComponent: xref:#AccessControlDefaultAdminRulesComponent[AccessControlDefaultAdminRulesComponent] - -WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to -grant and revoke this role. Extra precautions should be taken to secure -accounts that have been granted it. See {AccessControlDefaultAdminRulesComponent}. - -[.contract-index#AccessControl-Mixin-Impl] -.{mixin-impls} - --- -.AccessControlMixinImpl - -* xref:#AccessControlComponent-Embeddable-Impls-AccessControlImpl[`++AccessControlImpl++`] -* xref:#AccessControlComponent-Embeddable-Impls-AccessControlCamelImpl[`++AccessControlCamelImpl++`] -* xref:#AccessControlComponent-Embeddable-Impls-AccessControlWithDelayImpl[`++AccessControlWithDelayImpl++`] -* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls[`++SRC5Impl++`] --- - -[.contract-index#AccessControlComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#AccessControlComponent-Embeddable-Impls-AccessControlImpl] -.AccessControlImpl - -* xref:#AccessControlComponent-has_role[`++has_role(self, role, account)++`] -* xref:#AccessControlComponent-get_role_admin[`++get_role_admin(self, role)++`] -* xref:#AccessControlComponent-grant_role[`++grant_role(self, role, account)++`] -* xref:#AccessControlComponent-revoke_role[`++revoke_role(self, role, account)++`] -* xref:#AccessControlComponent-renounce_role[`++renounce_role(self, role, account)++`] - -[.sub-index#AccessControlComponent-Embeddable-Impls-AccessControlCamelImpl] -.AccessControlCamelImpl - -* xref:#AccessControlComponent-hasRole[`++hasRole(self, role, account)++`] -* xref:#AccessControlComponent-getRoleAdmin[`++getRoleAdmin(self, role)++`] -* xref:#AccessControlComponent-grantRole[`++grantRole(self, role, account)++`] -* xref:#AccessControlComponent-revokeRole[`++revokeRole(self, role, account)++`] -* xref:#AccessControlComponent-renounceRole[`++renounceRole(self, role, account)++`] - -[.sub-index#AccessControlComponent-Embeddable-Impls-AccessControlWithDelayImpl] -.AccessControlWithDelayImpl - -* xref:#AccessControlComponent-get_role_status[`++get_role_status(self, role, account)++`] -* xref:#AccessControlComponent-grant_role_with_delay[`++grant_role_with_delay(self, role, account, delay)++`] - -.SRC5Impl -* xref:api/introspection.adoc#ISRC5-supports_interface[`supports_interface(self, interface_id: felt252)`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#AccessControlComponent-initializer[`++initializer(self)++`] -* xref:#AccessControlComponent-assert_only_role[`++assert_only_role(self, role)++`] -* xref:#AccessControlComponent-is_role_effective[`++is_role_effective(self, role, account)++`] -* xref:#AccessControlComponent-resolve_role_status[`++resolve_role_status(self, role, account)++`] -* xref:#AccessControlComponent-is_role_granted[`++is_role_granted(self, role, account)++`] -* xref:#AccessControlComponent-set_role_admin[`++set_role_admin(self, role, admin_role)++`] -* xref:#AccessControlComponent-_grant_role[`++_grant_role(self, role, account)++`] -* xref:#AccessControlComponent-_grant_role_with_delay[`++_grant_role_with_delay(self, role, account, delay)++`] -* xref:#AccessControlComponent-_revoke_role[`++_revoke_role(self, role, account)++`] --- - -[.contract-index] -.Events --- -.IAccessControl -* xref:#AccessControlComponent-RoleAdminChanged[`++RoleAdminChanged(role, previous_admin_role, new_admin_role)++`] -* xref:#AccessControlComponent-RoleGranted[`++RoleGranted(role, account, sender)++`] -* xref:#AccessControlComponent-RoleRevoked[`++RoleRevoked(role, account, sender)++`] - -.IAccessControlWithDelay -* xref:#AccessControlComponent-RoleGrantedWithDelay[`++RoleGrantedWithDelay(role, account, sender, delay)++`] --- - -[#AccessControlComponent-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[AccessControlComponent-has_role]] -==== `[.contract-item-name]#++has_role++#++(self: @ContractState, role: felt252, account: ContractAddress) → bool++` [.item-kind]#external# - -Returns whether `account` can act as `role`. - -[.contract-item] -[[AccessControlComponent-get_role_admin]] -==== `[.contract-item-name]#++get_role_admin++#++(self: @ContractState, role: felt252) → felt252++` [.item-kind]#external# - -Returns the admin role that controls `role`. See {grant_role} and -{revoke_role}. - -To change a role's admin, use {set_role_admin}. - -[.contract-item] -[[AccessControlComponent-get_role_status]] -==== `[.contract-item-name]#++get_role_status++#++(self: @ContractState, role: felt252, account: ContractAddress) → RoleStatus++` [.item-kind]#external# - -Returns the account's status for the given role. - -The possible statuses are: - -- `NotGranted`: the role has not been granted to the account. -- `Delayed`: The role has been granted to the account but is not yet active due to a -time delay. -- `Effective`: the role has been granted to the account and is currently active. - -[.contract-item] -[[AccessControlComponent-grant_role]] -==== `[.contract-item-name]#++grant_role++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Grants `role` to `account`. - -If `account` had not been already granted `role`, emits a {RoleGranted} -event. - -Requirements: - -- the caller must have ``role``'s admin role. - -May emit a {RoleGranted} event. - -[.contract-item] -[[AccessControlComponent-grant_role_with_delay]] -==== `[.contract-item-name]#++grant_role_with_delay++#++(ref self: ContractState, role: felt252, account: ContractAddress, delay: u64)++` [.item-kind]#external# - -Attempts to grant `role` to `account` with the specified activation delay. - -Requirements: - -- The caller must have `role`'s admin role. -- delay must be greater than 0. -- the `role` must not be already effective for `account`. - -May emit a {RoleGrantedWithDelay} event. - -[.contract-item] -[[AccessControlComponent-revoke_role]] -==== `[.contract-item-name]#++revoke_role++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Revokes `role` from `account`. - -If `account` had been granted `role`, emits a {RoleRevoked} event. - -Requirements: - -- the caller must have ``role``'s admin role. - -May emit a {RoleRevoked} event. - -[.contract-item] -[[AccessControlComponent-renounce_role]] -==== `[.contract-item-name]#++renounce_role++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Revokes `role` from the calling account. - -Roles are often managed via {grant_role} and {revoke_role}. This function's -purpose is to provide a mechanism for accounts to lose their privileges -if they are compromised (such as when a trusted device is misplaced). - -If the calling account had been revoked `role`, emits a {RoleRevoked} -event. - -Requirements: - -- the caller must be `account`. - -May emit a {RoleRevoked} event. - -[.contract-item] -[[AccessControlComponent-supports_interface]] -==== `[.contract-item-name]#++supports_interface++#++(self: @ContractState, interface_id: felt252) → bool++` [.item-kind]#external# - -See xref:api/introspection.adoc#ISRC5-supports_interface[ISRC5::supports_interface]. - -[.contract-item] -[[AccessControlComponent-hasRole]] -==== `[.contract-item-name]#++hasRole++#++(self: @ContractState, role: felt252, account: ContractAddress) → bool++` [.item-kind]#external# - -See xref:AccessControlComponent-has_role[has_role]. - -[.contract-item] -[[AccessControlComponent-getRoleAdmin]] -==== `[.contract-item-name]#++getRoleAdmin++#++(self: @ContractState, role: felt252) → felt252++` [.item-kind]#external# - -See xref:AccessControlComponent-get_role_admin[get_role_admin]. - -[.contract-item] -[[AccessControlComponent-grantRole]] -==== `[.contract-item-name]#++grantRole++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -See xref:AccessControlComponent-grant_role[grant_role]. - -[.contract-item] -[[AccessControlComponent-revokeRole]] -==== `[.contract-item-name]#++revokeRole++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -See xref:AccessControlComponent-revoke_role[revoke_role]. - -[.contract-item] -[[AccessControlComponent-renounceRole]] -==== `[.contract-item-name]#++renounceRole++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -See xref:AccessControlComponent-renounce_role[renounce_role]. - -[#AccessControlComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[AccessControlComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState)++` [.item-kind]#internal# - -Initializes the contract by registering the xref:#IAccessControl[IAccessControl] interface ID. - -[.contract-item] -[[AccessControlComponent-assert_only_role]] -==== `[.contract-item-name]#++assert_only_role++#++(self: @ContractState, role: felt252)++` [.item-kind]#internal# - -Validates that the caller can act as the given role. Otherwise it panics. - -[.contract-item] -[[AccessControlComponent-is_role_effective]] -==== `[.contract-item-name]#++is_role_effective++#++(self: @ContractState, role: felt252, account: ContractAddress) → bool++` [.item-kind]#internal# - -Returns whether the account can act as the given role. - -The account can act as the role if it is active and the `effective_from` time is before -or equal to the current time. - -NOTE: If the `effective_from` timepoint is 0, the role is effective immediately. -This is backwards compatible with implementations that didn't use delays but -a single boolean flag. - -[.contract-item] -[[AccessControlComponent-resolve_role_status]] -==== `[.contract-item-name]#++resolve_role_status++#++(self: @ContractState, role: felt252, account: ContractAddress) → RoleStatus++` [.item-kind]#internal# - -Returns the account's status for the given role. - -The possible statuses are: - -- `NotGranted`: the role has not been granted to the account. -- `Delayed`: The role has been granted to the account but is not yet active due to a -time delay. -- `Effective`: the role has been granted to the account and is currently active. - -[.contract-item] -[[AccessControlComponent-is_role_granted]] -==== `[.contract-item-name]#++is_role_granted++#++(self: @ContractState, role: felt252, account: ContractAddress) → bool++` [.item-kind]#internal# - -Returns whether the account has the given role granted. - -NOTE: The account may not be able to act as the role yet, if a delay was set and has not -passed yet. Use `is_role_effective` to check if the account can act as the role. - -[.contract-item] -[[AccessControlComponent-set_role_admin]] -==== `[.contract-item-name]#++set_role_admin++#++(ref self: ContractState, role: felt252, admin_role: felt252)++` [.item-kind]#internal# - -Sets `admin_role` as ``role``'s admin role. - -Internal function without access restriction. - -Emits a {RoleAdminChanged} event. - -[.contract-item] -[[AccessControlComponent-_grant_role]] -==== `[.contract-item-name]#++_grant_role++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#internal# - -Attempts to grant `role` to `account`. The function does nothing if `role` is already -effective for `account`. If `role` has been granted to `account`, but is not yet active -due to a time delay, the delay is removed and `role` becomes effective immediately. - -Internal function without access restriction. - -May emit a {RoleGranted} event. - -[.contract-item] -[[AccessControlComponent-_grant_role_with_delay]] -==== `[.contract-item-name]#++_grant_role_with_delay++#++(ref self: ContractState, role: felt252, account: ContractAddress, delay: u64)++` [.item-kind]#internal# - -Attempts to grant `role` to `account` with the specified activation delay. - -The role will become effective after the given delay has passed. If the role is already -active (`Effective`) for the account, the function will panic. If the role has been -granted but is not yet active (being in the `Delayed` state), the existing delay will be -overwritten with the new `delay`. - -Internal function without access restriction. - -Requirements: - -- delay must be greater than 0. -- the `role` must not be already effective for `account`. - -May emit a {RoleGrantedWithDelay} event. - -[.contract-item] -[[AccessControlComponent-_revoke_role]] -==== `[.contract-item-name]#++_revoke_role++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#internal# - -Revokes `role` from `account`. - -Internal function without access restriction. - -May emit a {RoleRevoked} event. - -[#AccessControlComponent-Events] -==== Events - -[.contract-item] -[[AccessControlComponent-RoleAdminChanged]] -==== `[.contract-item-name]#++RoleAdminChanged++#++(role: felt252, previous_admin_role: ContractAddress, new_admin_role: ContractAddress)++` [.item-kind]#event# - -See xref:IAccessControl-RoleAdminChanged[IAccessControl::RoleAdminChanged]. - -[.contract-item] -[[AccessControlComponent-RoleGranted]] -==== `[.contract-item-name]#++RoleGranted++#++(role: felt252, account: ContractAddress, sender: ContractAddress)++` [.item-kind]#event# - -See xref:IAccessControl-RoleGranted[IAccessControl::RoleGranted]. - -[.contract-item] -[[AccessControlComponent-RoleGrantedWithDelay]] -==== `[.contract-item-name]#++RoleGrantedWithDelay++#++(role: felt252, account: ContractAddress, sender: ContractAddress, delay: u64)++` [.item-kind]#event# - -See xref:IAccessControlWithDelay-RoleGrantedWithDelay[IAccessControlWithDelay::RoleGrantedWithDelay]. - -[.contract-item] -[[AccessControlComponent-RoleRevoked]] -==== `[.contract-item-name]#++RoleRevoked++#++(role: felt252, account: ContractAddress, sender: ContractAddress)++` [.item-kind]#event# - -See xref:IAccessControl-RoleRevoked[IAccessControl::RoleRevoked]. - -== Extensions - -[.contract] -[[AccessControlDefaultAdminRulesComponent]] -=== `++AccessControlDefaultAdminRulesComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/access/src/accesscontrol/extensions/accesscontrol_default_admin_rules.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_access::accesscontrol::extensions::AccessControlDefaultAdminRulesComponent; -``` - -Extension of {AccessControl} that allows specifying special rules to manage the `DEFAULT_ADMIN_ROLE` holder, -which is a sensitive role with special permissions over other roles that may potentially have -privileged rights in the system. - -If a specific role doesn’t have an admin role assigned, the holder of the `DEFAULT_ADMIN_ROLE` will -have the ability to grant it and revoke it. - -This contract implements the following risk mitigations on top of {AccessControl}: - -- Only one account holds the `DEFAULT_ADMIN_ROLE` since deployment until it’s potentially renounced. - -- Enforces a 2-step process to transfer the `DEFAULT_ADMIN_ROLE` to another account. - -- Enforces a configurable delay between the two steps, with the ability to cancel before the transfer is accepted. - -- The delay can be changed by scheduling, see {change_default_admin_delay}. - -- It is not possible to use another role to manage the `DEFAULT_ADMIN_ROLE`. - -[.contract-index#AccessControlDefaultAdminRules-Mixin-Impl] -.{mixin-impls} - --- -.AccessControlMixinImpl - -* xref:#AccessControlDefaultAdminRulesComponent-Embeddable-Impls-AccessControlDefaultAdminRulesImpl[`++AccessControlDefaultAdminRulesImpl++`] -* xref:#AccessControlDefaultAdminRulesComponent-Embeddable-Impls-AccessControlImpl[`++AccessControlImpl++`] -* xref:#AccessControlDefaultAdminRulesComponent-Embeddable-Impls-AccessControlCamelImpl[`++AccessControlCamelImpl++`] -* xref:#AccessControlDefaultAdminRulesComponent-Embeddable-Impls-AccessControlWithDelayImpl[`++AccessControlWithDelayImpl++`] -* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls[`++SRC5Impl++`] --- - -[.contract-index#AccessControlDefaultAdminRulesComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#AccessControlDefaultAdminRulesComponent-Embeddable-Impls-AccessControlDefaultAdminRulesImpl] -.AccessControlDefaultAdminRulesImpl - -* xref:#IAccessControlDefaultAdminRules-default_admin[`++default_admin(self)++`] -* xref:#IAccessControlDefaultAdminRules-pending_default_admin[`++pending_default_admin(self)++`] -* xref:#IAccessControlDefaultAdminRules-default_admin_delay[`++default_admin_delay(self)++`] -* xref:#IAccessControlDefaultAdminRules-pending_default_admin_delay[`++pending_default_admin_delay(self)++`] -* xref:#IAccessControlDefaultAdminRules-begin_default_admin_transfer[`++begin_default_admin_transfer(self, new_admin)++`] -* xref:#IAccessControlDefaultAdminRules-cancel_default_admin_transfer[`++cancel_default_admin_transfer(self)++`] -* xref:#IAccessControlDefaultAdminRules-accept_default_admin_transfer[`++accept_default_admin_transfer(self)++`] -* xref:#IAccessControlDefaultAdminRules-change_default_admin_delay[`++change_default_admin_delay(self, new_delay)++`] -* xref:#IAccessControlDefaultAdminRules-rollback_default_admin_delay[`++rollback_default_admin_delay(self)++`] -* xref:#IAccessControlDefaultAdminRules-default_admin_delay_increase_wait[`++default_admin_delay_increase_wait(self)++`] - -[.sub-index#AccessControlDefaultAdminRulesComponent-Embeddable-Impls-AccessControlImpl] -.AccessControlImpl - -* xref:#AccessControlDefaultAdminRulesComponent-has_role[`++has_role(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-get_role_admin[`++get_role_admin(self, role)++`] -* xref:#AccessControlDefaultAdminRulesComponent-grant_role[`++grant_role(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-revoke_role[`++revoke_role(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-renounce_role[`++renounce_role(self, role, account)++`] - -[.sub-index#AccessControlDefaultAdminRulesComponent-Embeddable-Impls-AccessControlCamelImpl] -.AccessControlCamelImpl - -* xref:#AccessControlDefaultAdminRulesComponent-hasRole[`++hasRole(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-getRoleAdmin[`++getRoleAdmin(self, role)++`] -* xref:#AccessControlDefaultAdminRulesComponent-grantRole[`++grantRole(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-revokeRole[`++revokeRole(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-renounceRole[`++renounceRole(self, role, account)++`] - -[.sub-index#AccessControlDefaultAdminRulesComponent-Embeddable-Impls-AccessControlWithDelayImpl] -.AccessControlWithDelayImpl - -* xref:#AccessControlDefaultAdminRulesComponent-get_role_status[`++get_role_status(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-grant_role_with_delay[`++grant_role_with_delay(self, role, account, delay)++`] - -.SRC5Impl -* xref:api/introspection.adoc#ISRC5-supports_interface[`supports_interface(self, interface_id: felt252)`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#AccessControlDefaultAdminRulesComponent-initializer[`++initializer(self, initial_delay, initial_default_admin)++`] -* xref:#AccessControlDefaultAdminRulesComponent-assert_only_role[`++assert_only_role(self, role)++`] -* xref:#AccessControlDefaultAdminRulesComponent-is_role_effective[`++is_role_effective(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-resolve_role_status[`++resolve_role_status(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-is_role_granted[`++is_role_granted(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-set_role_admin[`++set_role_admin(self, role, admin_role)++`] -* xref:#AccessControlDefaultAdminRulesComponent-_grant_role[`++_grant_role(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-_grant_role_with_delay[`++_grant_role_with_delay(self, role, account, delay)++`] -* xref:#AccessControlDefaultAdminRulesComponent-_revoke_role[`++_revoke_role(self, role, account)++`] -* xref:#AccessControlDefaultAdminRulesComponent-set_pending_default_admin[`++set_pending_default_admin(self, new_admin, new_schedule)++`] -* xref:#AccessControlDefaultAdminRulesComponent-set_pending_delay[`++set_pending_delay(self, new_delay, new_schedule)++`] -* xref:#AccessControlDefaultAdminRulesComponent-delay_change_wait[`++delay_change_wait(self, new_delay)++`] --- - -[.contract-index] -.Events --- -.IAccessControl -* xref:#AccessControlDefaultAdminRulesComponent-RoleAdminChanged[`++RoleAdminChanged(role, previous_admin_role, new_admin_role)++`] -* xref:#AccessControlDefaultAdminRulesComponent-RoleGranted[`++RoleGranted(role, account, sender)++`] -* xref:#AccessControlDefaultAdminRulesComponent-RoleRevoked[`++RoleRevoked(role, account, sender)++`] - -.IAccessControlWithDelay -* xref:#AccessControlDefaultAdminRulesComponent-RoleGrantedWithDelay[`++RoleGrantedWithDelay(role, account, sender, delay)++`] - -.IAccessControlDefaultAdminRules -* xref:#AccessControlDefaultAdminRulesComponent-DefaultAdminTransferScheduled[`++DefaultAdminTransferScheduled(new_admin, accept_schedule)++`] -* xref:#AccessControlDefaultAdminRulesComponent-DefaultAdminTransferCanceled[`++DefaultAdminTransferCanceled()++`] -* xref:#AccessControlDefaultAdminRulesComponent-DefaultAdminDelayChangeScheduled[`++DefaultAdminDelayChangeScheduled(new_delay, effect_schedule)++`] -* xref:#AccessControlDefaultAdminRulesComponent-DefaultAdminDelayChangeCanceled[`++DefaultAdminDelayChangeCanceled()++`] --- - -:default_admin_transfer_scheduled: xref:AccessControlDefaultAdminRulesComponent-DefaultAdminTransferScheduled[DefaultAdminTransferScheduled] -:default_admin_transfer_canceled: xref:AccessControlDefaultAdminRulesComponent-DefaultAdminTransferCanceled[DefaultAdminTransferCanceled] -:default_admin_delay_change_scheduled: xref:AccessControlDefaultAdminRulesComponent-DefaultAdminDelayChangeScheduled[DefaultAdminDelayChangeScheduled] -:default_admin_delay_change_canceled: xref:AccessControlDefaultAdminRulesComponent-DefaultAdminDelayChangeCanceled[DefaultAdminDelayChangeCanceled] - -:RoleGranted: xref:AccessControlDefaultAdminRulesComponent-RoleGranted[RoleGranted] -:RoleGrantedWithDelay: xref:AccessControlDefaultAdminRulesComponent-RoleGrantedWithDelay[RoleGrantedWithDelay] -:RoleRevoked: xref:AccessControlDefaultAdminRulesComponent-RoleRevoked[RoleRevoked] -:RoleAdminChanged: xref:AccessControlDefaultAdminRulesComponent-RoleAdminChanged[RoleAdminChanged] - -:default_admin: xref:AccessControlDefaultAdminRulesComponent-default_admin[default_admin] -:pending_default_admin: xref:AccessControlDefaultAdminRulesComponent-pending_default_admin[pending_default_admin] -:default_admin_delay: xref:AccessControlDefaultAdminRulesComponent-default_admin_delay[default_admin_delay] -:pending_default_admin_delay: xref:AccessControlDefaultAdminRulesComponent-pending_default_admin_delay[pending_default_admin_delay] -:begin_default_admin_transfer: xref:AccessControlDefaultAdminRulesComponent-begin_default_admin_transfer[begin_default_admin_transfer] -:cancel_default_admin_transfer: xref:AccessControlDefaultAdminRulesComponent-cancel_default_admin_transfer[cancel_default_admin_transfer] -:accept_default_admin_transfer: xref:AccessControlDefaultAdminRulesComponent-accept_default_admin_transfer[accept_default_admin_transfer] -:change_default_admin_delay: xref:AccessControlDefaultAdminRulesComponent-change_default_admin_delay[change_default_admin_delay] -:rollback_default_admin_delay: xref:AccessControlDefaultAdminRulesComponent-rollback_default_admin_delay[rollback_default_admin_delay] -:default_admin_delay_increase_wait: xref:AccessControlDefaultAdminRulesComponent-default_admin_delay_increase_wait[default_admin_delay_increase_wait] - -[#AccessControlDefaultAdminRulesComponent-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-default_admin]] -==== `[.contract-item-name]#++default_admin++#++(self: @ContractState) → ContractAddress++` [.item-kind]#external# - -Returns the address of the current `DEFAULT_ADMIN_ROLE` holder. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-pending_default_admin]] -==== `[.contract-item-name]#++pending_default_admin++#++(self: @ContractState) → (ContractAddress, u64)++` [.item-kind]#external# - -Returns a tuple of a `new_admin` and an `accept_schedule`. - -After the `accept_schedule` passes, the `new_admin` will be able to accept the -`default_admin` role by calling {accept_default_admin_transfer}, completing the role -transfer. - -A zero value only in `accept_schedule` indicates no pending admin transfer. - -NOTE: A zero address `new_admin` means that `default_admin` is being renounced. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-default_admin_delay]] -==== `[.contract-item-name]#++default_admin_delay++#++(self: @ContractState) → u64++` [.item-kind]#external# - -Returns the delay required to schedule the acceptance of a `default_admin` transfer -started. - -This delay will be added to the current timestamp when calling -{begin_default_admin_transfer} to set the acceptance schedule. - -NOTE: If a delay change has been scheduled, it will take effect as soon as the schedule -passes, making this function returns the new delay. - -See {change_default_admin_delay}. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-pending_default_admin_delay]] -==== `[.contract-item-name]#++pending_default_admin_delay++#++(self: @ContractState) → (u64, u64)++` [.item-kind]#external# - -Returns a tuple of `new_delay` and an `effect_schedule`. - -After the `effect_schedule` passes, the `new_delay` will get into effect immediately for -every new `default_admin` transfer started with {begin_default_admin_transfer}. - -A zero value only in `effect_schedule` indicates no pending delay change. - -NOTE: A zero value only for `new_delay` means that the next {default_admin_delay} -will be zero after the effect schedule. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-begin_default_admin_transfer]] -==== `[.contract-item-name]#++begin_default_admin_transfer++#++(ref self: ContractState, new_admin: ContractAddress)++` [.item-kind]#external# - -Starts a `default_admin` transfer by setting a {pending_default_admin} scheduled for -acceptance after the current timestamp plus a {default_admin_delay}. - -Requirements: - -- Only can be called by the current `default_admin`. - -Emits a {default_admin_transfer_scheduled} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-cancel_default_admin_transfer]] -==== `[.contract-item-name]#++cancel_default_admin_transfer++#++(ref self: ContractState)++` [.item-kind]#external# - -Cancels a `default_admin` transfer previously started with {begin_default_admin_transfer}. - -A {pending_default_admin} not yet accepted can also be cancelled with this function. - -Requirements: - -- Only can be called by the current `default_admin`. - -May emit a {default_admin_transfer_canceled} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-accept_default_admin_transfer]] -==== `[.contract-item-name]#++accept_default_admin_transfer++#++(ref self: ContractState)++` [.item-kind]#external# - -Completes a `default_admin` transfer previously started with {begin_default_admin_transfer}. - -After calling the function: - -- `DEFAULT_ADMIN_ROLE` must be granted to the caller. -- `DEFAULT_ADMIN_ROLE` must be revoked from the previous holder. -- {pending_default_admin} must be reset to zero values. - -Requirements: - -- Only can be called by the {pending_default_admin}'s `new_admin`. -- The {pending_default_admin}'s `accept_schedule` should've passed. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-change_default_admin_delay]] -==== `[.contract-item-name]#++change_default_admin_delay++#++(ref self: ContractState, new_delay: u64)++` [.item-kind]#external# - -Initiates a {default_admin_delay} update by setting a {pending_default_admin_delay} -scheduled for getting into effect after the current timestamp plus a -{default_admin_delay}. - -This function guarantees that any call to {begin_default_admin_transfer} done between -the timestamp this method is called and the {pending_default_admin_delay} effect -schedule will use the current {default_admin_delay} -set before calling. - -The {pending_default_admin_delay}'s effect schedule is defined in a way that waiting -until the schedule and then calling {begin_default_admin_transfer} with the new delay -will take at least the same as another `default_admin` -complete transfer (including acceptance). - -The schedule is designed for two scenarios: - -- When the delay is changed for a larger one the schedule is `block.timestamp + -new delay` capped by {default_admin_delay_increase_wait}. -- When the delay is changed for a shorter one, the schedule is `block.timestamp + -(current delay - new delay)`. - -A {pending_default_admin_delay} that never got into effect will be canceled in favor of -a new scheduled change. - -Requirements: - -- Only can be called by the current `default_admin`. - -Emits a {default_admin_delay_change_scheduled} event and may emit a -{default_admin_delay_change_canceled} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-rollback_default_admin_delay]] -==== `[.contract-item-name]#++rollback_default_admin_delay++#++(ref self: ContractState)++` [.item-kind]#external# - -Cancels a scheduled {default_admin_delay} change. - -Requirements: - -- Only can be called by the current `default_admin`. - -May emit a {default_admin_delay_change_canceled} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-default_admin_delay_increase_wait]] -==== `[.contract-item-name]#++default_admin_delay_increase_wait++#++(self: @ContractState) → u64++` [.item-kind]#external# - -Maximum time in seconds for an increase to {default_admin_delay} (that is scheduled -using {change_default_admin_delay}) to take effect. Defaults to 5 days. - -When the {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} increase -scheduling. - -IMPORTANT: 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 -(eg. set milliseconds instead of seconds). - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-has_role]] -==== `[.contract-item-name]#++has_role++#++(self: @ContractState, role: felt252, account: ContractAddress) → bool++` [.item-kind]#external# - -Returns whether `account` can act as `role`. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-get_role_admin]] -==== `[.contract-item-name]#++get_role_admin++#++(self: @ContractState, role: felt252) → felt252++` [.item-kind]#external# - -Returns the admin role that controls `role`. See {grant_role} and -{revoke_role}. - -To change a role's admin, use {set_role_admin}. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-get_role_status]] -==== `[.contract-item-name]#++get_role_status++#++(self: @ContractState, role: felt252, account: ContractAddress) → RoleStatus++` [.item-kind]#external# - -Returns the account's status for the given role. - -The possible statuses are: - -- `NotGranted`: the role has not been granted to the account. -- `Delayed`: The role has been granted to the account but is not yet active due to a -time delay. -- `Effective`: the role has been granted to the account and is currently active. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-grant_role]] -==== `[.contract-item-name]#++grant_role++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Grants `role` to `account`. - -If `account` had not been already granted `role`, emits a {RoleGranted} -event. - -Requirements: - -- the caller must have ``role``'s admin role. - -May emit a {RoleGranted} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-grant_role_with_delay]] -==== `[.contract-item-name]#++grant_role_with_delay++#++(ref self: ContractState, role: felt252, account: ContractAddress, delay: u64)++` [.item-kind]#external# - -Attempts to grant `role` to `account` with the specified activation delay. - -Requirements: - -- The caller must have `role`'s admin role. -- delay must be greater than 0. -- the `role` must not be already effective for `account`. - -May emit a {RoleGrantedWithDelay} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-revoke_role]] -==== `[.contract-item-name]#++revoke_role++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Revokes `role` from `account`. - -If `account` had been granted `role`, emits a {RoleRevoked} event. - -Requirements: - -- the caller must have ``role``'s admin role. - -May emit a {RoleRevoked} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-renounce_role]] -==== `[.contract-item-name]#++renounce_role++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Revokes `role` from the calling account. - -Roles are often managed via {grant_role} and {revoke_role}. This function's -purpose is to provide a mechanism for accounts to lose their privileges -if they are compromised (such as when a trusted device is misplaced). - -If the calling account had been revoked `role`, emits a {RoleRevoked} -event. - -Requirements: - -- the caller must be `account`. - -May emit a {RoleRevoked} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-supports_interface]] -==== `[.contract-item-name]#++supports_interface++#++(self: @ContractState, interface_id: felt252) → bool++` [.item-kind]#external# - -See xref:api/introspection.adoc#ISRC5-supports_interface[ISRC5::supports_interface]. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-hasRole]] -==== `[.contract-item-name]#++hasRole++#++(self: @ContractState, role: felt252, account: ContractAddress) → bool++` [.item-kind]#external# - -See xref:AccessControlDefaultAdminRulesComponent-has_role[has_role]. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-getRoleAdmin]] -==== `[.contract-item-name]#++getRoleAdmin++#++(self: @ContractState, role: felt252) → felt252++` [.item-kind]#external# - -See xref:AccessControlDefaultAdminRulesComponent-get_role_admin[get_role_admin]. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-grantRole]] -==== `[.contract-item-name]#++grantRole++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -See xref:AccessControlDefaultAdminRulesComponent-grant_role[grant_role]. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-revokeRole]] -==== `[.contract-item-name]#++revokeRole++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -See xref:AccessControlDefaultAdminRulesComponent-revoke_role[revoke_role]. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-renounceRole]] -==== `[.contract-item-name]#++renounceRole++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -See xref:AccessControlDefaultAdminRulesComponent-renounce_role[renounce_role]. - -[#AccessControlDefaultAdminRulesComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, initial_delay: u64, initial_default_admin: ContractAddress)++` [.item-kind]#external# - -Initializes the contract by registering the IAccessControl interface ID and -setting the initial delay and default admin. - -Requirements: - -- `initial_default_admin` must not be the zero address. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-assert_only_role]] -==== `[.contract-item-name]#++assert_only_role++#++(self: @ContractState, role: felt252)++` [.item-kind]#external# - -Validates that the caller can act as the given role. Otherwise it panics. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-is_role_effective]] -==== `[.contract-item-name]#++is_role_effective++#++(self: @ContractState, role: felt252, account: ContractAddress) → bool++` [.item-kind]#external# - -Returns whether the account can act as the given role. - -The account can act as the role if it is active and the `effective_from` time is before -or equal to the current time. - -NOTE: If the `effective_from` timepoint is 0, the role is effective immediately. -This is backwards compatible with implementations that didn't use delays but -a single boolean flag. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-resolve_role_status]] -==== `[.contract-item-name]#++resolve_role_status++#++(self: @ContractState, role: felt252, account: ContractAddress) → RoleStatus++` [.item-kind]#external# - -Returns the account's status for the given role. - -The possible statuses are: - -- `NotGranted`: the role has not been granted to the account. -- `Delayed`: The role has been granted to the account but is not yet active due to a -time delay. -- `Effective`: the role has been granted to the account and is currently active. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-is_role_granted]] -==== `[.contract-item-name]#++is_role_granted++#++(self: @ContractState, role: felt252, account: ContractAddress) → bool++` [.item-kind]#external# - -Returns whether the account has the given role granted. - -NOTE: The account may not be able to act as the role yet, if a delay was set and has not -passed yet. Use {is_role_effective} to check if the account can act as the role. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-set_role_admin]] -==== `[.contract-item-name]#++set_role_admin++#++(ref self: ContractState, role: felt252, admin_role: felt252)++` [.item-kind]#external# - -Sets `admin_role` as `role`'s admin role. - -Internal function without access restriction. - -Requirements: - -- `role` must not be `DEFAULT_ADMIN_ROLE`. - -Emits a {RoleAdminChanged} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-_grant_role]] -==== `[.contract-item-name]#++_grant_role++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Attempts to grant `role` to `account`. The function does nothing if `role` is already -effective for `account`. If `role` has been granted to `account`, but is not yet active -due to a time delay, the delay is removed and `role` becomes effective immediately. - -Internal function without access restriction. - -For `DEFAULT_ADMIN_ROLE`, it only allows granting if there isn't already a -`default_admin` -or if the role has been previously renounced. - -NOTE: Exposing this function through another mechanism may make the `DEFAULT_ADMIN_ROLE` -assignable again. Make sure to guarantee this is the expected behavior in your -implementation. - -May emit a {RoleGranted} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-_grant_role_with_delay]] -==== `[.contract-item-name]#++_grant_role_with_delay++#++(ref self: ContractState, role: felt252, account: ContractAddress, delay: u64)++` [.item-kind]#external# - -Attempts to grant `role` to `account` with the specified activation delay. - -The role will become effective after the given delay has passed. If the role is already -active (`Effective`) for the account, the function will panic. If the role has been -granted but is not yet active (being in the `Delayed` state), the existing delay will be -overwritten with the new `delay`. - -Internal function without access restriction. - -Requirements: - -- `delay` must be greater than 0. -- the `role` must not be already effective for `account`. -- `role` must not be `DEFAULT_ADMIN_ROLE`. - -May emit a {RoleGrantedWithDelay} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-_revoke_role]] -==== `[.contract-item-name]#++_revoke_role++#++(ref self: ContractState, role: felt252, account: ContractAddress)++` [.item-kind]#external# - -Attempts to revoke `role` from `account`. The function does nothing if `role` is not -effective for `account`. If `role` has been revoked from `account`, but is still active -due to a time delay, the delay is removed and `role` becomes inactive immediately. - -Internal function without access restriction. - -May emit a {RoleRevoked} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-set_pending_default_admin]] -==== `[.contract-item-name]#++set_pending_default_admin++#++(ref self: ContractState, new_admin: ContractAddress, new_schedule: u64)++` [.item-kind]#external# - -Setter of the tuple for pending admin and its schedule. - -May emit a {DefaultAdminTransferCanceled} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-set_pending_delay]] -==== `[.contract-item-name]#++set_pending_delay++#++(ref self: ContractState, new_delay: u64, new_schedule: u64)++` [.item-kind]#external# - -Setter of the tuple for pending delay and its schedule. - -May emit a {DefaultAdminDelayChangeCanceled} event. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-delay_change_wait]] -==== `[.contract-item-name]#++delay_change_wait++#++(self: @ContractState, new_delay: u64) → u64++` [.item-kind]#external# - -Returns the amount of seconds to wait after the `new_delay` will -become the new `default_admin_delay`. - -The value returned guarantees that if the delay is reduced, it will go into effect -after a wait that honors the previously set delay. - -See {default_admin_delay_increase_wait}. - -[#AccessControlDefaultAdminRulesComponent-Events] -==== Events - -[.contract-item] -[#AccessControlDefaultAdminRulesComponent-RoleAdminChanged] -==== `[.contract-item-name]#++RoleAdminChanged++#++(role: felt252, previous_admin_role: felt252, new_admin_role: felt252)++` [.item-kind]#event# - -Emitted when `new_admin_role` is set as `role`'s admin role, replacing `previous_admin_role` - -`DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite -`RoleAdminChanged` not being emitted signaling this. - -[.contract-item] -[#AccessControlDefaultAdminRulesComponent-RoleGranted] -==== `[.contract-item-name]#++RoleGranted++#++(role: felt252, account: ContractAddress, sender: ContractAddress)++` [.item-kind]#event# - -Emitted when `account` is granted `role`. - -`sender` is the account that originated the contract call, an account with the admin role -or the deployer address if `_grant_role` is called from the constructor. - -[.contract-item] -[#AccessControlDefaultAdminRulesComponent-RoleRevoked] -==== `[.contract-item-name]#++RoleRevoked++#++(role: felt252, account: ContractAddress, sender: ContractAddress)++` [.item-kind]#event# - -Emitted when `role` is revoked for `account`. - -`sender` is the account that originated the contract call: - -- If using `revoke_role`, it is the admin role bearer. -- If using `renounce_role`, it is the role bearer (i.e. `account`). - -[.contract-item] -[#AccessControlDefaultAdminRulesComponent-RoleGrantedWithDelay] -==== `[.contract-item-name]#++RoleGrantedWithDelay++#++(role: felt252, account: ContractAddress, sender: ContractAddress, delay: u64)++` [.item-kind]#event# - -Emitted when `account` is granted `role` with a delay. - -`sender` is the account that originated the contract call, an account with the admin role -or the deployer address if `_grant_role_with_delay` is called from the constructor. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-DefaultAdminTransferScheduled]] -==== `[.contract-item-name]#++DefaultAdminTransferScheduled++#++(new_admin: ContractAddress, accept_schedule: u64)++` [.item-kind]#event# - -Emitted when a `default_admin` transfer is started. - -Sets `new_admin` as the next address to become the `default_admin` by calling -{accept_default_admin_transfer} only after `accept_schedule` passes. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-DefaultAdminTransferCanceled]] -==== `[.contract-item-name]#++DefaultAdminTransferCanceled++#++()++` [.item-kind]#event# - -Emitted when a {pending_default_admin} is reset if it was never -accepted, regardless of its schedule. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-DefaultAdminDelayChangeScheduled]] -==== `[.contract-item-name]#++DefaultAdminDelayChangeScheduled++#++(new_delay: u64, effect_schedule: u64)++` [.item-kind]#event# - -Emitted when a {default_admin_delay} change is started. - -Sets `new_delay` as the next delay to be applied between default admins transfers -after `effect_schedule` has passed. - -[.contract-item] -[[AccessControlDefaultAdminRulesComponent-DefaultAdminDelayChangeCanceled]] - -Emitted when a {pending_default_admin_delay} is reset if its schedule didn't pass. diff --git a/docs/modules/ROOT/pages/api/account.adoc b/docs/modules/ROOT/pages/api/account.adoc deleted file mode 100644 index 941515eda..000000000 --- a/docs/modules/ROOT/pages/api/account.adoc +++ /dev/null @@ -1,830 +0,0 @@ -:github-icon: pass:[] -:snip6: https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-6.md[SNIP-6] -:snip9: https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-9.md[SNIP-9] -:snip12: https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md[SNIP-12] -:inner-src5: xref:api/introspection.adoc#ISRC5[SRC5 ID] - -= Account - -This crate provides components to implement account contracts that can be used for interacting with the network. - -== Interfaces - -include::../utils/_common.adoc[] - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_account` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[ISRC6]] -=== `++ISRC6++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/account/accounts.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_interfaces::accounts::ISRC6; -``` - -Interface of the SRC6 Standard Account as defined in the {snip6}. - -[.contract-index] -.{inner-src5} --- -0x2ceccef7f994940b3962a6c67e0ba4fcd37df7d131417c604f91e03caecc1cd --- - -[.contract-index] -.Functions --- -* xref:#ISRC6-\\__execute__[`++__execute__(calls)++`] -* xref:#ISRC6-\\__validate__[`++__validate__(calls)++`] -* xref:#ISRC6-is_valid_signature[`++is_valid_signature(hash, signature)++`] --- - -[#ISRC6-Functions] -==== Functions - -[.contract-item] -[[ISRC6-__execute__]] -==== `[.contract-item-name]#++__execute__++#++(calls: Array)++` [.item-kind]#external# - -Executes the list of calls as a transaction after validation. - -NOTE: The `Call` struct is defined in https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/account.cairo#L3[corelib]. - -[.contract-item] -[[ISRC6-__validate__]] -==== `[.contract-item-name]#++__validate__++#++(calls: Array) → felt252++` [.item-kind]#external# - -Validates a transaction before execution. - -Returns the short string `'VALID'` if valid, otherwise it reverts. - -[.contract-item] -[[ISRC6-is_valid_signature]] -==== `[.contract-item-name]#++is_valid_signature++#++(hash: felt252, signature: Array) → felt252++` [.item-kind]#external# - -Validates whether a signature is valid or not for the given message hash. - -Returns the short string `'VALID'` if valid, otherwise it reverts. - -[.contract] -[[ISRC9_V2]] -=== `++ISRC9_V2++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/account/src9.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_interfaces::src9::ISRC9_V2; -``` - -Interface of the SRC9 Standard as defined in the {snip9}. - -[.contract-index] -.{inner-src5} --- -0x1d1144bb2138366ff28d8e9ab57456b1d332ac42196230c3a602003c89872 --- - -[.contract-index] -.Functions --- -* xref:#ISRC9_V2-execute_from_outside_v2[`++execute_from_outside_v2(outside_execution, signature)++`] -* xref:#ISRC9_V2-is_valid_outside_execution_nonce[`++is_valid_outside_execution_nonce(nonce)++`] --- - -[#ISRC9_V2-Functions] -==== Functions - -[.contract-item] -[[ISRC9_V2-execute_from_outside_v2]] -==== `[.contract-item-name]#++execute_from_outside_v2++#++(outside_execution: OutsideExecution, signature: Span,) → Array>++` [.item-kind]#external# - -Allows anyone to submit a transaction on behalf of the account as long as they have the relevant signatures. - -This method allows reentrancy. A call to `\\__execute__` or `execute_from_outside_v2` can trigger -another nested transaction to `execute_from_outside_v2` thus the implementation MUST verify -that the provided `signature` matches the hash of `outside_execution` and that `nonce` was -not already used. - -The implementation should expect version to be set to 2 in the domain separator. - -Arguments: - -- `outside_execution` - The parameters of the transaction to execute. -- `signature` - A valid signature on the {snip12} message encoding of `outside_execution`. - -[.contract-item] -[[ISRC9_V2-is_valid_outside_execution_nonce]] -==== `[.contract-item-name]#++is_valid_outside_execution_nonce++#++(nonce: felt252) → bool++` [.item-kind]#external# - -Get the status of a given nonce. `true` if the nonce is available to use. - -== Core - -[.contract] -[[AccountComponent]] -=== `++AccountComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/account/src/account.cairo[{github-icon},role=heading-link] - -:OwnerAdded: xref:AccountComponent-OwnerAdded[OwnerAdded] -:OwnerRemoved: xref:AccountComponent-OwnerRemoved[OwnerRemoved] -:starknet-curve: https://docs.starknet.io/architecture-and-concepts/cryptography/#stark-curve[Starknet curve] - -```cairo -use openzeppelin_account::AccountComponent; -``` -Account component implementing xref:ISRC6[`ISRC6`] for signatures over the {starknet-curve}. - -NOTE: {src5-component-required-note} - -[.contract-index#AccountComponent-Embeddable-Mixin-Impl] -.{mixin-impls} - --- -.AccountMixinImpl - -* xref:#AccountComponent-Embeddable-Impls-SRC6Impl[`++SRC6Impl++`] -* xref:#AccountComponent-Embeddable-Impls-DeclarerImpl[`++DeclarerImpl++`] -* xref:#AccountComponent-Embeddable-Impls-DeployableImpl[`++DeployableImpl++`] -* xref:#AccountComponent-Embeddable-Impls-PublicKeyImpl[`++PublicKeyImpl++`] -* xref:#AccountComponent-Embeddable-Impls-SRC6CamelOnlyImpl[`++SRC6CamelOnlyImpl++`] -* xref:#AccountComponent-Embeddable-Impls-PublicKeyCamelImpl[`++PublicKeyCamelImpl++`] -* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls[`++SRC5Impl++`] --- - -[.contract-index#AccountComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#AccountComponent-Embeddable-Impls-SRC6Impl] -.SRC6Impl - -* xref:#AccountComponent-\\__execute__[`++__execute__(self, calls)++`] -* xref:#AccountComponent-\\__validate__[`++__validate__(self, calls)++`] -* xref:#AccountComponent-is_valid_signature[`++is_valid_signature(self, hash, signature)++`] - -[.sub-index#AccountComponent-Embeddable-Impls-DeclarerImpl] -.DeclarerImpl - -* xref:#AccountComponent-\\__validate_declare__[`++__validate_declare__(self, class_hash)++`] - -[.sub-index#AccountComponent-Embeddable-Impls-DeployableImpl] -.DeployableImpl - -* xref:#AccountComponent-\\__validate_deploy__[`++__validate_deploy__(self, hash, signature)++`] - -[.sub-index#AccountComponent-Embeddable-Impls-PublicKeyImpl] -.PublicKeyImpl - -* xref:#AccountComponent-get_public_key[`++get_public_key(self)++`] -* xref:#AccountComponent-set_public_key[`++set_public_key(self, new_public_key, signature)++`] - -[.sub-index#AccountComponent-Embeddable-Impls-SRC6CamelOnlyImpl] -.SRC6CamelOnlyImpl - -* xref:#AccountComponent-isValidSignature[`++isValidSignature(self, hash, signature)++`] - -[.sub-index#AccountComponent-Embeddable-Impls-PublicKeyCamelImpl] -.PublicKeyCamelImpl - -* xref:#AccountComponent-getPublicKey[`++getPublicKey(self)++`] -* xref:#AccountComponent-setPublicKey[`++setPublicKey(self, newPublicKey, signature)++`] - -.SRC5Impl -* xref:api/introspection.adoc#ISRC5-supports_interface[`supports_interface(self, interface_id: felt252)`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#AccountComponent-initializer[`++initializer(self, public_key)++`] -* xref:#AccountComponent-assert_only_self[`++assert_only_self(self)++`] -* xref:#AccountComponent-assert_valid_new_owner[`++assert_valid_new_owner(self, current_owner, new_owner, signature)++`] -* xref:#AccountComponent-validate_transaction[`++validate_transaction(self)++`] -* xref:#AccountComponent-_set_public_key[`++_set_public_key(self, new_public_key)++`] -* xref:#AccountComponent-_is_valid_signature[`++_is_valid_signature(self, hash, signature)++`] --- - -[.contract-index] -.Events --- -* xref:#AccountComponent-OwnerAdded[`++OwnerAdded(new_owner_guid)++`] -* xref:#AccountComponent-OwnerRemoved[`++OwnerRemoved(removed_owner_guid)++`] --- - -[#AccountComponent-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[AccountComponent-__execute__]] -==== `[.contract-item-name]#++__execute__++#++(self: @ContractState, calls: Array)++` [.item-kind]#external# - -See xref:ISRC6-\\__execute__[ISRC6::\\__execute__]. - -[.contract-item] -[[AccountComponent-__validate__]] -==== `[.contract-item-name]#++__validate__++#++(self: @ContractState, calls: Array) → felt252++` [.item-kind]#external# - -See xref:ISRC6-\\__validate__[ISRC6::\\__validate__]. - -[.contract-item] -[[AccountComponent-is_valid_signature]] -==== `[.contract-item-name]#++is_valid_signature++#++(self: @ContractState, hash: felt252, signature: Array) → felt252++` [.item-kind]#external# - -See xref:ISRC6-is_valid_signature[ISRC6::is_valid_signature]. - -[.contract-item] -[[AccountComponent-__validate_declare__]] -==== `[.contract-item-name]#++__validate_declare__++#++(self: @ContractState, class_hash: felt252) → felt252++` [.item-kind]#external# - -Validates a https://docs.starknet.io/architecture-and-concepts/network-architecture/transactions/#declare-transaction[`Declare` transaction]. - -Returns the short string `'VALID'` if valid, otherwise it reverts. - -[.contract-item] -[[AccountComponent-__validate_deploy__]] -==== `[.contract-item-name]#++__validate_deploy__++#++(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, public_key: felt252) → felt252++` [.item-kind]#external# - -Validates a https://docs.starknet.io/architecture-and-concepts/network-architecture/transactions/#deploy_account_transaction[`DeployAccount` transaction]. -See xref:/guides/deployment.adoc[Counterfactual Deployments]. - -Returns the short string `'VALID'` if valid, otherwise it reverts. - -[.contract-item] -[[AccountComponent-get_public_key]] -==== `[.contract-item-name]#++get_public_key++#++(self: @ContractState)++ → felt252` [.item-kind]#external# - -Returns the current public key of the account. - -[.contract-item] -[[AccountComponent-set_public_key]] -==== `[.contract-item-name]#++set_public_key++#++(ref self: ContractState, new_public_key: felt252, signature: Span)++` [.item-kind]#external# - -Sets a new public key for the account. Only accessible by the account calling itself through `\\__execute__`. - -Requirements: - -- The caller must be the contract itself. -- The signature must be valid for the new owner. - -Emits both an {OwnerRemoved} and an {OwnerAdded} event. - -[NOTE] -==== -The message to be signed is computed in Cairo as follows: - -```javascript -let message_hash = PoseidonTrait::new() - .update_with('StarkNet Message') - .update_with('accept_ownership') - .update_with(get_contract_address()) - .update_with(current_owner) - .finalize(); -``` -==== - -[.contract-item] -[[AccountComponent-isValidSignature]] -==== `[.contract-item-name]#++isValidSignature++#++(self: @ContractState, hash: felt252, signature: Array) → felt252++` [.item-kind]#external# - -See xref:ISRC6-is_valid_signature[ISRC6::is_valid_signature]. - -[.contract-item] -[[AccountComponent-getPublicKey]] -==== `[.contract-item-name]#++getPublicKey++#++(self: @ContractState)++ → felt252` [.item-kind]#external# - -See xref:AccountComponent-get_public_key[get_public_key]. - -[.contract-item] -[[AccountComponent-setPublicKey]] -==== `[.contract-item-name]#++setPublicKey++#++(ref self: ContractState, newPublicKey: felt252, signature: Span)++` [.item-kind]#external# - -See xref:AccountComponent-set_public_key[set_public_key]. - -[#AccountComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[AccountComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ComponentState, public_key: felt252)++` [.item-kind]#internal# - -Initializes the account with the given public key, and registers the `ISRC6` interface ID. - -Emits an {OwnerAdded} event. - -[.contract-item] -[[AccountComponent-assert_only_self]] -==== `[.contract-item-name]#++assert_only_self++#++(self: @ComponentState)++` [.item-kind]#internal# - -Validates that the caller is the account itself. Otherwise it reverts. - -[.contract-item] -[[AccountComponent-assert_valid_new_owner]] -==== `[.contract-item-name]#++assert_valid_new_owner++#++(self: @ComponentState, current_owner: felt252, new_owner: felt252, signature: Span)++` [.item-kind]#internal# - -Validates that `new_owner` accepted the ownership of the contract through a signature. - -Requirements: - -- `signature` must be valid for the new owner. - -WARNING: This function assumes that `current_owner` is the current owner of the contract, and -does not validate this assumption. - -[.contract-item] -[[AccountComponent-validate_transaction]] -==== `[.contract-item-name]#++validate_transaction++#++(self: @ComponentState)++ → felt252` [.item-kind]#internal# - -Validates a transaction signature from the -https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61[global context]. - -Returns the short string `'VALID'` if valid, otherwise it reverts. - -[.contract-item] -[[AccountComponent-_set_public_key]] -==== `[.contract-item-name]#++_set_public_key++#++(ref self: ComponentState, new_public_key: felt252)++` [.item-kind]#internal# - -Set the public key without validating the caller. - -Emits an {OwnerAdded} event. - -CAUTION: The usage of this method outside the `set_public_key` function is discouraged. - -[.contract-item] -[[AccountComponent-_is_valid_signature]] -==== `[.contract-item-name]#++_is_valid_signature++#++(self: @ComponentState, hash: felt252, signature: Span)++ → bool` [.item-kind]#internal# - -Validates the provided `signature` for the `hash`, using the account's current public key. - -[#AccountComponent-Events] -==== Events - -[.contract-item] -[[AccountComponent-OwnerAdded]] -==== `[.contract-item-name]#++OwnerAdded++#++(new_owner_guid: felt252)++` [.item-kind]#event# - -Emitted when a `public_key` is added. - -[.contract-item] -[[AccountComponent-OwnerRemoved]] -==== `[.contract-item-name]#++OwnerRemoved++#++(removed_owner_guid: felt252)++` [.item-kind]#event# - -Emitted when a `public_key` is removed. - -[.contract] -[[EthAccountComponent]] -=== `++EthAccountComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/account/src/eth_account.cairo[{github-icon},role=heading-link] - -:OwnerAdded: xref:EthAccountComponent-OwnerAdded[OwnerAdded] -:OwnerRemoved: xref:EthAccountComponent-OwnerRemoved[OwnerRemoved] -:secp256k1-curve: https://en.bitcoin.it/wiki/Secp256k1[Secp256k1 curve] - -```cairo -use openzeppelin_account::eth_account::EthAccountComponent; -``` -Account component implementing xref:ISRC6[`ISRC6`] for signatures over the {secp256k1-curve}. - -NOTE: {src5-component-required-note} - -NOTE: The `EthPublicKey` type is an alias for `starknet::secp256k1::Secp256k1Point`. - -[.contract-index#EthAccountComponent-Embeddable-Mixin-Impl] -.{mixin-impls} - --- -.EthAccountMixinImpl - -* xref:#EthAccountComponent-Embeddable-Impls-SRC6Impl[`++SRC6Impl++`] -* xref:#EthAccountComponent-Embeddable-Impls-DeclarerImpl[`++DeclarerImpl++`] -* xref:#EthAccountComponent-Embeddable-Impls-DeployableImpl[`++DeployableImpl++`] -* xref:#EthAccountComponent-Embeddable-Impls-PublicKeyImpl[`++PublicKeyImpl++`] -* xref:#EthAccountComponent-Embeddable-Impls-SRC6CamelOnlyImpl[`++SRC6CamelOnlyImpl++`] -* xref:#EthAccountComponent-Embeddable-Impls-PublicKeyCamelImpl[`++PublicKeyCamelImpl++`] -* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls[`++SRC5Impl++`] --- - -[.contract-index#EthAccountComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#EthAccountComponent-Embeddable-Impls-SRC6Impl] -.SRC6Impl - -* xref:#EthAccountComponent-\\__execute__[`++__execute__(self, calls)++`] -* xref:#EthAccountComponent-\\__validate__[`++__validate__(self, calls)++`] -* xref:#EthAccountComponent-is_valid_signature[`++is_valid_signature(self, hash, signature)++`] - -[.sub-index#EthAccountComponent-Embeddable-Impls-DeclarerImpl] -.DeclarerImpl - -* xref:#EthAccountComponent-\\__validate_declare__[`++__validate_declare__(self, class_hash)++`] - -[.sub-index#EthAccountComponent-Embeddable-Impls-DeployableImpl] -.DeployableImpl - -* xref:#EthAccountComponent-\\__validate_deploy__[`++__validate_deploy__(self, hash, signature)++`] - -[.sub-index#EthAccountComponent-Embeddable-Impls-PublicKeyImpl] -.PublicKeyImpl - -* xref:#EthAccountComponent-get_public_key[`++get_public_key(self)++`] -* xref:#EthAccountComponent-set_public_key[`++set_public_key(self, new_public_key, signature)++`] - -[.sub-index#EthAccountComponent-Embeddable-Impls-SRC6CamelOnlyImpl] -.SRC6CamelOnlyImpl - -* xref:#EthAccountComponent-isValidSignature[`++isValidSignature(self, hash, signature)++`] - -[.sub-index#EthAccountComponent-Embeddable-Impls-PublicKeyCamelImpl] -.PublicKeyCamelImpl - -* xref:#EthAccountComponent-getPublicKey[`++getPublicKey(self)++`] -* xref:#EthAccountComponent-setPublicKey[`++setPublicKey(self, newPublicKey, signature)++`] - -.SRC5Impl -* xref:api/introspection.adoc#ISRC5-supports_interface[`supports_interface(self, interface_id: felt252)`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#EthAccountComponent-initializer[`++initializer(self, public_key)++`] -* xref:#EthAccountComponent-assert_only_self[`++assert_only_self(self)++`] -* xref:#EthAccountComponent-assert_valid_new_owner[`++assert_valid_new_owner(self, current_owner, new_owner, signature)++`] -* xref:#EthAccountComponent-validate_transaction[`++validate_transaction(self)++`] -* xref:#EthAccountComponent-_set_public_key[`++_set_public_key(self, new_public_key)++`] -* xref:#EthAccountComponent-_is_valid_signature[`++_is_valid_signature(self, hash, signature)++`] --- - -[.contract-index] -.Events --- -* xref:#EthAccountComponent-OwnerAdded[`++OwnerAdded(new_owner_guid)++`] -* xref:#EthAccountComponent-OwnerRemoved[`++OwnerRemoved(removed_owner_guid)++`] --- - -[#EthAccountComponent-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[EthAccountComponent-__execute__]] -==== `[.contract-item-name]#++__execute__++#++(self: @ContractState, calls: Array)++` [.item-kind]#external# - -See xref:ISRC6-\\__execute__[ISRC6::\\__execute__]. - -[.contract-item] -[[EthAccountComponent-__validate__]] -==== `[.contract-item-name]#++__validate__++#++(self: @ContractState, calls: Array) → felt252++` [.item-kind]#external# - -See xref:ISRC6-\\__validate__[ISRC6::\\__validate__]. - -[.contract-item] -[[EthAccountComponent-is_valid_signature]] -==== `[.contract-item-name]#++is_valid_signature++#++(self: @ContractState, hash: felt252, signature: Array) → felt252++` [.item-kind]#external# - -See xref:ISRC6-is_valid_signature[ISRC6::is_valid_signature]. - -[.contract-item] -[[EthAccountComponent-__validate_declare__]] -==== `[.contract-item-name]#++__validate_declare__++#++(self: @ContractState, class_hash: felt252) → felt252++` [.item-kind]#external# - -Validates a https://docs.starknet.io/architecture-and-concepts/network-architecture/transactions/#declare-transaction[`Declare` transaction]. - -Returns the short string `'VALID'` if valid, otherwise it reverts. - -[.contract-item] -[[EthAccountComponent-__validate_deploy__]] -==== `[.contract-item-name]#++__validate_deploy__++#++(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, public_key: EthPublicKey) → felt252++` [.item-kind]#external# - -Validates a https://docs.starknet.io/architecture-and-concepts/network-architecture/transactions/#deploy_account_transaction[`DeployAccount` transaction]. -See xref:/guides/deployment.adoc[Counterfactual Deployments]. - -Returns the short string `'VALID'` if valid, otherwise it reverts. - -[.contract-item] -[[EthAccountComponent-get_public_key]] -==== `[.contract-item-name]#++get_public_key++#++(self: @ContractState)++ → EthPublicKey` [.item-kind]#external# - -Returns the current public key of the account. - -[.contract-item] -[[EthAccountComponent-set_public_key]] -==== `[.contract-item-name]#++set_public_key++#++(ref self: ContractState, new_public_key: EthPublicKey, signature: Span)++` [.item-kind]#external# - -Sets a new public key for the account. Only accessible by the account calling itself through `\\__execute__`. - -Requirements: - -- The caller must be the contract itself. -- The signature must be valid for the new owner. - -Emits both an {OwnerRemoved} and an {OwnerAdded} event. - -[NOTE] -==== -The message to be signed is computed in Cairo as follows: -```javascript -let message_hash = PoseidonTrait::new() - .update_with('StarkNet Message') - .update_with('accept_ownership') - .update_with(get_contract_address()) - .update_with(current_owner.get_coordinates().unwrap_syscall()) - .finalize(); -``` -==== - -[.contract-item] -[[EthAccountComponent-isValidSignature]] -==== `[.contract-item-name]#++isValidSignature++#++(self: @ContractState, hash: felt252, signature: Array) → felt252++` [.item-kind]#external# - -See xref:ISRC6-is_valid_signature[ISRC6::is_valid_signature]. - -[.contract-item] -[[EthAccountComponent-getPublicKey]] -==== `[.contract-item-name]#++getPublicKey++#++(self: @ContractState)++ → EthPublicKey` [.item-kind]#external# - -See xref:EthAccountComponent-get_public_key[get_public_key]. - -[.contract-item] -[[EthAccountComponent-setPublicKey]] -==== `[.contract-item-name]#++setPublicKey++#++(ref self: ContractState, newPublicKey: EthPublicKey, signature: Span)++` [.item-kind]#external# - -See xref:EthAccountComponent-set_public_key[set_public_key]. - -[#EthAccountComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[EthAccountComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ComponentState, public_key: EthPublicKey)++` [.item-kind]#internal# - -Initializes the account with the given public key, and registers the `ISRC6` interface ID. - -Emits an {OwnerAdded} event. - -[.contract-item] -[[EthAccountComponent-assert_only_self]] -==== `[.contract-item-name]#++assert_only_self++#++(self: @ComponentState)++` [.item-kind]#internal# - -Validates that the caller is the account itself. Otherwise it reverts. - -[.contract-item] -[[EthAccountComponent-assert_valid_new_owner]] -==== `[.contract-item-name]#++assert_valid_new_owner++#++(self: @ComponentState, current_owner: EthPublicKey, new_owner: EthPublicKey, signature: Span)++` [.item-kind]#internal# - -Validates that `new_owner` accepted the ownership of the contract through a signature. - -Requirements: - -- The signature must be valid for the `new_owner`. - -WARNING: This function assumes that `current_owner` is the current owner of the contract, and -does not validate this assumption. - -[.contract-item] -[[EthAccountComponent-validate_transaction]] -==== `[.contract-item-name]#++validate_transaction++#++(self: @ComponentState)++ → felt252` [.item-kind]#internal# - -Validates a transaction signature from the -https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61[global context]. - -Returns the short string `'VALID'` if valid, otherwise it reverts. - -[.contract-item] -[[EthAccountComponent-_set_public_key]] -==== `[.contract-item-name]#++_set_public_key++#++(ref self: ComponentState, new_public_key: EthPublicKey)++` [.item-kind]#internal# - -Set the public key without validating the caller. - -Emits an {OwnerAdded} event. - -CAUTION: The usage of this method outside the `set_public_key` function is discouraged. - -[.contract-item] -[[EthAccountComponent-_is_valid_signature]] -==== `[.contract-item-name]#++_is_valid_signature++#++(self: @ComponentState, hash: felt252, signature: Span)++ → bool` [.item-kind]#internal# - -Validates the provided `signature` for the `hash`, using the account's current public key. - -[#EthAccountComponent-Events] -==== Events - -NOTE: The `guid` is computed as the hash of the public key, using the poseidon hash function. - -[.contract-item] -[[EthAccountComponent-OwnerAdded]] -==== `[.contract-item-name]#++OwnerAdded++#++(new_owner_guid: felt252)++` [.item-kind]#event# - -Emitted when a `public_key` is added. - -[.contract-item] -[[EthAccountComponent-OwnerRemoved]] -==== `[.contract-item-name]#++OwnerRemoved++#++(removed_owner_guid: felt252)++` [.item-kind]#event# - -Emitted when a `public_key` is removed. - -== Extensions - -[.contract] -[[SRC9Component]] -=== `++SRC9Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/account/src/extensions/src9/src9.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_account::extensions::SRC9Component; -``` - -OutsideExecution component implementing xref:ISRC9_V2[`ISRC9_V2`]. - -NOTE: This component is signature-agnostic, meaning it can be integrated into any account contract, as long as the -account implements the ISRC6 interface. - -[.contract-index#SRC9Component-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#SRC9Component-Embeddable-Impls-OutsideExecutionV2Impl] -.OutsideExecutionV2Impl - -* xref:#SRC9Component-execute_from_outside_v2[`++execute_from_outside_v2(self, outside_execution, signature)++`] -* xref:#SRC9Component-is_valid_outside_execution_nonce[`++is_valid_outside_execution_nonce(self, nonce)++`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#SRC9Component-initializer[`++initializer(self)++`] --- - -[#SRC9Component-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[SRC9Component-execute_from_outside_v2]] -==== `[.contract-item-name]#++execute_from_outside_v2++#++(ref self: ContractState, outside_execution: OutsideExecution, signature: Span) → Array>++` [.item-kind]#external# - -Allows anyone to submit a transaction on behalf of the account as long as they -have the relevant signatures. - -This method allows reentrancy. A call to `\\__execute__` or `execute_from_outside_v2` can -trigger another nested transaction to `execute_from_outside_v2`. This implementation -verifies that the provided `signature` matches the hash of `outside_execution` and that -`nonce` was not already used. - -Arguments: - -- `outside_execution` - The parameters of the transaction to execute. -- `signature` - A valid signature on the {snip12} message encoding of -`outside_execution`. - -Requirements: - -- The caller must be the `outside_execution.caller` unless 'ANY_CALLER' is used. -- The current time must be within the `outside_execution.execute_after` and `outside_execution.execute_before` span. -- The `outside_execution.nonce` must not be used before. -- The `signature` must be valid. - -[.contract-item] -[[SRC9Component-is_valid_outside_execution_nonce]] -==== `[.contract-item-name]#++is_valid_outside_execution_nonce++#++(self: @ContractState, nonce: felt252) → bool++` [.item-kind]#external# - -Returns the status of a given nonce. `true` if the nonce is available to use. - -[#SRC9Component-Internal-Functions] -==== Internal functions - -[.contract-item] -[[SRC9Component-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ComponentState)++` [.item-kind]#internal# - -Initializes the account by registering the `ISRC9_V2` interface ID. - -== Presets - -[.contract] -[[AccountUpgradeable]] -=== `++AccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/presets/src/account.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_presets::AccountUpgradeable; -``` - -Upgradeable account which can change its public key and declare, deploy, or call -contracts. Supports outside execution by implementing xref:#SRC9Component[SRC9]. - -include::../utils/_class_hashes.adoc[] - -[.contract-index] -.{presets-page} --- -{AccountUpgradeable-class-hash} --- - -[.contract-index] -.Constructor --- -* xref:#AccountUpgradeable-constructor[`++constructor(self, public_key)++`] --- - -[.contract-index] -.Embedded Implementations --- -.AccountComponent -* xref:#AccountComponent-Embeddable-Mixin-Impl[`++AccountMixinImpl++`] - -.SRC9Component -* xref:#SRC9Component-Embeddable-Impls-OutsideExecutionV2Impl[`++OutsideExecutionV2Impl++`] --- - -[.contract-index] -.External Functions --- -* xref:#AccountUpgradeable-upgrade[`++upgrade(self, new_class_hash)++`] --- - -[#AccountUpgradeable-constructor-section] -==== Constructor - -[.contract-item] -[[AccountUpgradeable-constructor]] -==== `[.contract-item-name]#++constructor++#++(ref self: ContractState, public_key: felt252)++` [.item-kind]#constructor# - -Sets the account `public_key` and registers the interfaces the contract supports. - -[#AccountUpgradeable-external-functions] -==== External functions - -[.contract-item] -[[AccountUpgradeable-upgrade]] -==== `[.contract-item-name]#++upgrade++#++(ref self: ContractState, new_class_hash: ClassHash)++` [.item-kind]#external# - -Upgrades the contract to a new implementation given by `new_class_hash`. - -Requirements: - -- The caller is the account contract itself. -- `new_class_hash` cannot be zero. - -[.contract] -[[EthAccountUpgradeable]] -=== `++EthAccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/presets/src/eth_account.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_presets::EthAccountUpgradeable; -``` - -Upgradeable account which can change its public key and declare, deploy, or call contracts, using Ethereum -signing keys. Supports outside execution by implementing xref:#SRC9Component[SRC9]. - -NOTE: The `EthPublicKey` type is an alias for `starknet::secp256k1::Secp256k1Point`. - -include::../utils/_class_hashes.adoc[] - -[.contract-index] -.{presets-page} --- -{EthAccountUpgradeable-class-hash} --- - -[.contract-index] -.Constructor --- -* xref:#EthAccountUpgradeable-constructor[`++constructor(self, public_key)++`] --- - -[.contract-index] -.Embedded Implementations --- -.EthAccountComponent -* xref:#EthAccountComponent-Embeddable-Mixin-Impl[`++EthAccountMixinImpl++`] - -.SRC9Component -* xref:#SRC9Component-Embeddable-Impls-OutsideExecutionV2Impl[`++OutsideExecutionV2Impl++`] --- - -[.contract-index] -.External Functions --- -* xref:#EthAccountUpgradeable-upgrade[`++upgrade(self, new_class_hash)++`] --- - -[#EthAccountUpgradeable-constructor-section] -==== Constructor - -[.contract-item] -[[EthAccountUpgradeable-constructor]] -==== `[.contract-item-name]#++constructor++#++(ref self: ContractState, public_key: EthPublicKey)++` [.item-kind]#constructor# - -Sets the account `public_key` and registers the interfaces the contract supports. - -[#EthAccountUpgradeable-external-functions] -==== External functions - -[.contract-item] -[[EthAccountUpgradeable-upgrade]] -==== `[.contract-item-name]#++upgrade++#++(ref self: ContractState, new_class_hash: ClassHash)++` [.item-kind]#external# - -Upgrades the contract to a new implementation given by `new_class_hash`. - -Requirements: - -- The caller is the account contract itself. -- `new_class_hash` cannot be zero. diff --git a/docs/modules/ROOT/pages/api/erc1155.adoc b/docs/modules/ROOT/pages/api/erc1155.adoc deleted file mode 100644 index 9676cb265..000000000 --- a/docs/modules/ROOT/pages/api/erc1155.adoc +++ /dev/null @@ -1,751 +0,0 @@ -:github-icon: pass:[] -:eip1155: https://eips.ethereum.org/EIPS/eip-1155[EIP1155] -:eip1155-metadata: https://eips.ethereum.org/EIPS/eip-1155#metadata -:receiving-tokens: xref:/erc1155.adoc#receiving_tokens[Receiving tokens] -:inner-src5: xref:api/introspection.adoc#ISRC5[SRC5 ID] - -= ERC1155 - -include::../utils/_common.adoc[] - -This module provides interfaces, presets, and utilities related to ERC1155 contracts. - -TIP: For an overview of ERC1155, read our xref:erc1155.adoc[ERC1155 guide]. - -== Interfaces - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_token` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[IERC1155]] -=== `++IERC1155++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc1155.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc1155::IERC1155; -``` -Interface of the IERC1155 standard as defined in {eip1155}. - -[.contract-index] -.{inner-src5} --- -0x6114a8f75559e1b39fcba08ce02961a1aa082d9256a158dd3e64964e4b1b52 --- - -[.contract-index] -.Functions --- -* xref:#IERC1155-balance_of[`++balance_of(account, token_id)++`] -* xref:#IERC1155-balance_of_batch[`++balance_of_batch(accounts, token_ids)++`] -* xref:#IERC1155-safe_transfer_from[`++safe_transfer_from(from, to, token_id, value, data)++`] -* xref:#IERC1155-safe_batch_transfer_from[`++safe_batch_transfer_from(from, to, token_ids, values, data)++`] -* xref:#IERC1155-set_approval_for_all[`++set_approval_for_all(operator, approved)++`] -* xref:#IERC1155-is_approved_for_all[`++is_approved_for_all(owner, operator)++`] --- - -[.contract-index] -.Events --- -* xref:#IERC1155-TransferSingle[`++TransferSingle(operator, from, to, id, value)++`] -* xref:#IERC1155-TransferBatch[`++TransferBatch(operator, from, to, ids, values)++`] -* xref:#IERC1155-ApprovalForAll[`++ApprovalForAll(owner, operator, approved)++`] -* xref:#IERC1155-URI[`++URI(value, id)++`] --- - -==== Functions - -[.contract-item] -[[IERC1155-balance_of]] -==== `[.contract-item-name]#++balance_of++#++(account: ContractAddress, token_id: u256) → u256++` [.item-kind]#external# - -Returns the amount of `token_id` tokens owned by `account`. - -[.contract-item] -[[IERC1155-balance_of_batch]] -==== `[.contract-item-name]#++balance_of_batch++#++(accounts: Span, token_ids: Span) → Span++` [.item-kind]#external# - -Returns a list of balances derived from the `accounts` and `token_ids` pairs. - -[.contract-item] -[[IERC1155-safe_transfer_from]] -==== `[.contract-item-name]#++safe_transfer_from++#++(from: ContractAddress, to: ContractAddress, token_id: u256, value: u256, data: Span)++` [.item-kind]#external# - -Transfers ownership of `value` amount of `token_id` from `from` if `to` is either `IERC1155Receiver` or an account. - -`data` is additional data, it has no specified format and it is passed to `to`. - -Emits a <> event. - -[.contract-item] -[[IERC1155-safe_batch_transfer_from]] -==== `[.contract-item-name]#++safe_batch_transfer_from++#++(from: ContractAddress, to: ContractAddress, token_ids: Span, values: Span, data: Span)++` [.item-kind]#external# - -Transfers ownership of `token_ids` and `values` pairs from `from` if `to` is either `IERC1155Receiver` or an account. - -`data` is additional data, it has no specified format and it is passed to `to`. - -Emits a <> event. - -[.contract-item] -[[IERC1155-set_approval_for_all]] -==== `[.contract-item-name]#++set_approval_for_all++#++(operator: ContractAddress, approved: bool)++` [.item-kind]#external# - -Enables or disables approval for `operator` to manage all of the caller's assets. - -Emits an <> event. - -[.contract-item] -[[IERC1155-is_approved_for_all]] -==== `[.contract-item-name]#++is_approved_for_all++#++(owner: ContractAddress, operator: ContractAddress) -> bool++` [.item-kind]#external# - -Queries if `operator` is an authorized operator for `owner`. - -==== Events - -[.contract-item] -[[IERC1155-TransferSingle]] -==== `[.contract-item-name]#++TransferSingle++#++(operator: ContractAddress, from: ContractAddress, to: ContractAddress, id: u256, value: u256)++` [.item-kind]#event# - -Emitted when `value` amount of `id` token is transferred from `from` to `to` through `operator`. - -[.contract-item] -[[IERC1155-TransferBatch]] -==== `[.contract-item-name]#++TransferBatch++#++(operator: ContractAddress, from: ContractAddress, to: ContractAddress, ids: Span, values: Span)++` [.item-kind]#event# - -Emitted when a batch of `values` amount of `ids` tokens are transferred from `from` to `to` through `operator`. - -[.contract-item] -[[IERC1155-ApprovalForAll]] -==== `[.contract-item-name]#++ApprovalForAll++#++(owner: ContractAddress, operator: ContractAddress, approved: bool)++` [.item-kind]#event# - -Emitted when `owner` enables or disables `operator` to manage all of the owner's assets. - -[.contract-item] -[[IERC1155-URI]] -==== `[.contract-item-name]#++URI++#++(value: ByteArray, id: u256)++` [.item-kind]#event# - -Emitted when the token URI is updated to `value` for the `id` token. - -[.contract] -[[IERC1155MetadataURI]] -=== `++IERC1155MetadataURI++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc1155.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc1155::IERC1155MetadataURI; -``` -Interface for the optional metadata function in {eip1155-metadata}[EIP1155]. - -[.contract-index] -.{inner-src5} --- -0xcabe2400d5fe509e1735ba9bad205ba5f3ca6e062da406f72f113feb889ef7 --- - -[.contract-index] -.Functions --- -* xref:#IERC1155MetadataURI-uri[`++uri(token_id)++`] --- - -==== Functions - -[.contract-item] -[[IERC1155MetadataURI-uri]] -==== `[.contract-item-name]#++uri++#++(token_id: u256) -> ByteArray++` [.item-kind]#external# - -Returns the Uniform Resource Identifier (URI) for the `token_id` token. - -[.contract] -[[IERC1155Receiver]] -=== `++IERC1155Receiver++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc1155.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc1155::IERC1155Receiver; -``` - -Interface for contracts that support receiving token transfers from `ERC1155` contracts. - -[.contract-index] -.{inner-src5} --- -0x15e8665b5af20040c3af1670509df02eb916375cdf7d8cbaf7bd553a257515e --- - -[.contract-index] -.Functions --- -* xref:#IERC1155Receiver-on_erc1155_received[`++on_erc1155_received(operator, from, token_id, value, data)++`] -* xref:#IERC1155Receiver-on_erc1155_batch_received[`++on_erc1155_batch_received(operator, from, token_ids, values, data)++`] --- - -==== Functions - -[.contract-item] -[[IERC1155Receiver-on_erc1155_received]] -==== `[.contract-item-name]#++on_erc1155_received++#++(operator: ContractAddress, from: ContractAddress, token_id: u256, value: u256, data Span) -> felt252++` [.item-kind]#external# - -This function is called whenever an ERC1155 `token_id` token is transferred to this `IERC1155Receiver` implementer -via <> by `operator` from `from`. - -[.contract-item] -[[IERC1155Receiver-on_erc1155_batch_received]] -==== `[.contract-item-name]#++on_erc1155_batch_received++#++(operator: ContractAddress, from: ContractAddress, token_ids: Span, values: Span, data Span) -> felt252++` [.item-kind]#external# - -This function is called whenever multiple ERC1155 `token_ids` tokens are transferred to this `IERC1155Receiver` implementer -via <> by `operator` from `from`. - -== Core - -[.contract] -[[ERC1155Component]] -=== `++ERC1155Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/token/src/erc1155/erc1155.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_token::erc1155::ERC1155Component; -``` - -ERC1155 component implementing <> and <>. - -NOTE: {src5-component-required-note} - -NOTE: See xref:#ERC1155Component-Hooks[Hooks] to understand how are hooks used. - -[.contract-index] -.Hooks --- -[.sub-index#ERC1155Component-ERC1155HooksTrait] -.ERC1155HooksTrait -* xref:#ERC1155Component-before_update[`++before_update(self, from, to, token_ids, values)++`] -* xref:#ERC1155Component-after_update[`++after_update(self, from, to, token_ids, values)++`] --- - -[.contract-index#ERC1155Component-Embeddable-Mixin-Impl] -.{mixin-impls} - --- -.ERC1155MixinImpl -* xref:#ERC1155Component-Embeddable-Impls-ERC1155Impl[`++ERC1155Impl++`] -* xref:#ERC1155Component-Embeddable-Impls-ERC1155MetadataURIImpl[`++ERC1155MetadataURIImpl++`] -* xref:#ERC1155Component-Embeddable-Impls-ERC1155CamelImpl[`++ERC1155CamelImpl++`] -* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls-SRC5Impl[`++SRC5Impl++`] --- - -[.contract-index#ERC1155Component-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#ERC1155Component-Embeddable-Impls-ERC1155Impl] -.ERC1155Impl -* xref:#ERC1155Component-balance_of[`++balance_of(self, account, token_id)++`] -* xref:#ERC1155Component-balance_of_batch[`++balance_of_batch(self, accounts, token_ids)++`] -* xref:#ERC1155Component-safe_transfer_from[`++safe_transfer_from(self, from, to, token_id, value, data)++`] -* xref:#ERC1155Component-safe_batch_transfer_from[`++safe_batch_transfer_from(self, from, to, token_ids, values, data)++`] -* xref:#ERC1155Component-set_approval_for_all[`++set_approval_for_all(self, operator, approved)++`] -* xref:#ERC1155Component-is_approved_for_all[`++is_approved_for_all(self, owner, operator)++`] - -[.sub-index#ERC1155Component-Embeddable-Impls-ERC1155MetadataURIImpl] -.ERC1155MetadataURIImpl -* xref:#ERC1155Component-uri[`++uri(self, token_id)++`] - -[.sub-index#ERC1155Component-Embeddable-Impls-ERC1155CamelImpl] -.ERC1155CamelImpl -* xref:#ERC1155Component-balanceOf[`++balanceOf(self, account, tokenId)++`] -* xref:#ERC1155Component-balanceOfBatch[`++balanceOfBatch(self, accounts, tokenIds)++`] -* xref:#ERC1155Component-safeTransferFrom[`++safeTransferFrom(self, from, to, tokenId, value, data)++`] -* xref:#ERC1155Component-safeBatchTransferFrom[`++safeBatchTransferFrom(self, from, to, tokenIds, values, data)++`] -* xref:#ERC1155Component-setApprovalForAll[`++setApprovalForAll(self, operator, approved)++`] -* xref:#ERC1155Component-isApprovedForAll[`++isApprovedForAll(self, owner, operator)++`] --- - -[.contract-index] -.Internal Functions --- -.InternalImpl -* xref:#ERC1155Component-initializer[`++initializer(self, base_uri)++`] -* xref:#ERC1155Component-initializer_no_metadata[`++initializer_no_metadata(self)++`] -* xref:#ERC1155Component-mint_with_acceptance_check[`++mint_with_acceptance_check(self, to, token_id, value, data)++`] -* xref:#ERC1155Component-batch_mint_with_acceptance_check[`++batch_mint_with_acceptance_check(self, to, token_ids, values, data)++`] -* xref:#ERC1155Component-burn[`++burn(self, from, token_id, value)++`] -* xref:#ERC1155Component-batch_burn[`++batch_burn(self, from, token_ids, values)++`] -* xref:#ERC1155Component-update_with_acceptance_check[`++update_with_acceptance_check(self, from, to, token_ids, values, data)++`] -* xref:#ERC1155Component-update[`++update(self, from, to, token_ids, values)++`] -* xref:#ERC1155Component-_set_base_uri[`++_set_base_uri(self, base_uri)++`] --- - -[.contract-index] -.Events --- -.IERC1155 -* xref:#ERC1155Component-TransferSingle[`++TransferSingle(operator, from, to, id, value)++`] -* xref:#ERC1155Component-TransferBatch[`++TransferBatch(operator, from, to, ids, values)++`] -* xref:#ERC1155Component-ApprovalForAll[`++ApprovalForAll(owner, operator, approved)++`] -* xref:#ERC1155Component-URI[`++URI(value, id)++`] --- - -[#ERC1155Component-Hooks] -==== Hooks - -Hooks are functions which implementations can extend the functionality of the component source code. Every contract -using ERC1155Component is expected to provide an implementation of the ERC1155HooksTrait. For basic token contracts, an -empty implementation with no logic must be provided. - -TIP: You can use `openzeppelin_token::erc1155::ERC1155HooksEmptyImpl` which is already available as part of the library -for this purpose. - -[.contract-item] -[[ERC1155Component-before_update]] -==== `[.contract-item-name]#++before_update++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span, values: Span)++` [.item-kind]#hook# - -Function executed at the beginning of the xref:#ERC1155Component-update[update] function prior to any other logic. - -[.contract-item] -[[ERC1155Component-after_update]] -==== `[.contract-item-name]#++after_update++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span, values: Span)++` [.item-kind]#hook# - -Function executed at the end of the xref:#ERC1155Component-update[update] function. - -==== Embeddable functions - -[.contract-item] -[[ERC1155Component-balance_of]] -==== `[.contract-item-name]#++balance_of++#++(self: @ContractState, account: ContractAddress, token_id: u256) → u256++` [.item-kind]#external# - -Returns the amount of `token_id` tokens owned by `account`. - -[.contract-item] -[[ERC1155Component-balance_of_batch]] -==== `[.contract-item-name]#++balance_of_batch++#++(self: @ContractState, accounts: Span, token_ids: Span) → Span++` [.item-kind]#external# - -Returns a list of balances derived from the `accounts` and `token_ids` pairs. - -Requirements: - -- `token_ids` and `accounts` must have the same length. - -[.contract-item] -[[ERC1155Component-safe_transfer_from]] -==== `[.contract-item-name]#++safe_transfer_from++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, value: u256, data: Span)++` [.item-kind]#external# - -Transfers ownership of `value` amount of `token_id` from `from` if `to` is either an account or `IERC1155Receiver`. - -`data` is additional data, it has no specified format and it is passed to `to`. - -WARNING: This function can potentially allow a reentrancy attack when transferring tokens -to an untrusted contract, when invoking `on_ERC1155_received` on the receiver. -Ensure to follow the checks-effects-interactions pattern and consider employing -reentrancy guards when interacting with untrusted contracts. - -Requirements: - -- Caller is either approved or the `token_id` owner. -- `from` is not the zero address. -- `to` is not the zero address. -- If `to` refers to a non-account contract, it must implement `IERC1155Receiver::on_ERC1155_received` - and return the required magic value. - -Emits a <> event. - -[.contract-item] -[[ERC1155Component-safe_batch_transfer_from]] -==== `[.contract-item-name]#++safe_batch_transfer_from++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span, values: Span, data: Span)++` [.item-kind]#external# - -Transfers ownership of `values` and `token_ids` pairs from `from` if `to` is either an account or `IERC1155Receiver`. - -`data` is additional data, it has no specified format and it is passed to `to`. - -WARNING: This function can potentially allow a reentrancy attack when transferring tokens -to an untrusted contract, when invoking `on_ERC1155_batch_received` on the receiver. -Ensure to follow the checks-effects-interactions pattern and consider employing -reentrancy guards when interacting with untrusted contracts. - -Requirements: - -- Caller is either approved or the `token_id` owner. -- `from` is not the zero address. -- `to` is not the zero address. -- `token_ids` and `values` must have the same length. -- If `to` refers to a non-account contract, it must implement `IERC1155Receiver::on_ERC1155_batch_received` - and return the acceptance magic value. - -Emits a <> event if the arrays contain one element, -and <> otherwise. - -[.contract-item] -[[ERC1155Component-set_approval_for_all]] -==== `[.contract-item-name]#++set_approval_for_all++#++(ref self: ContractState, operator: ContractAddress, approved: bool)++` [.item-kind]#external# - -Enables or disables approval for `operator` to manage all of the callers assets. - -Requirements: - -- `operator` cannot be the caller. - -Emits an <> event. - -[.contract-item] -[[ERC1155Component-is_approved_for_all]] -==== `[.contract-item-name]#++is_approved_for_all++#++(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool++` [.item-kind]#external# - -Queries if `operator` is an authorized operator for `owner`. - -[.contract-item] -[[ERC1155Component-uri]] -==== `[.contract-item-name]#++uri++#++(self: @ContractState, token_id: u256) -> ByteArray++` [.item-kind]#external# - -This implementation returns the same URI for *all* token types. It relies -on the token type ID substitution mechanism -{eip1155-metadata}[specified in the EIP]. - -Clients calling this function must replace the `\{id\}` substring with the -actual token type ID. - -[.contract-item] -[[ERC1155Component-balanceOf]] -==== `[.contract-item-name]#++balanceOf++#++(self: @ContractState, account: ContractAddress, tokenId: u256) → u256++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC1155Component-balanceOfBatch]] -==== `[.contract-item-name]#++balanceOfBatch++#++(self: @ContractState, accounts: Span, tokenIds: Span) → Span++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC1155Component-safeTransferFrom]] -==== `[.contract-item-name]#++safeTransferFrom++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256, value: u256, data: Span)++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC1155Component-safeBatchTransferFrom]] -==== `[.contract-item-name]#++safeBatchTransferFrom++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenIds: Span, values: Span, data: Span)++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC1155Component-setApprovalForAll]] -==== `[.contract-item-name]#++setApprovalForAll++#++(ref self: ContractState, operator: ContractAddress, approved: bool)++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC1155Component-isApprovedForAll]] -==== `[.contract-item-name]#++isApprovedForAll++#++(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool++` [.item-kind]#external# - -See <>. - -==== Internal functions - -[.contract-item] -[[ERC1155Component-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, base_uri: ByteArray)++` [.item-kind]#internal# - -Initializes the contract by setting the token's base URI as `base_uri`, and registering the supported interfaces. -This should only be used inside the contract's constructor. - -WARNING: Most ERC1155 contracts expose the <> interface which is what this initializer is meant to support. -If the contract DOES NOT expose the <> interface, meaning tokens do not have a URI, -the contract must instead use <> in the constructor. -Failure to abide by these instructions can lead to unexpected issues especially with UIs. - -[.contract-item] -[[ERC1155Component-initializer_no_metadata]] -==== `[.contract-item-name]#++initializer_no_metadata++#++(ref self: ContractState)++` [.item-kind]#internal# - -Initializes the contract with no metadata by registering only the IERC1155 interface. - -WARNING: This initializer should ONLY be used during construction in the very -specific instance when the contract does NOT expose the <> interface. -Initializing a contract with this initializer means that tokens will not have a URI. - -[.contract-item] -[[ERC1155Component-mint_with_acceptance_check]] -==== `[.contract-item-name]#++mint_with_acceptance_check++#++(ref self: ContractState, to: ContractAddress, token_id: u256, value: u256, data: Span)++` [.item-kind]#internal# - -Creates a `value` amount of tokens of type `token_id`, and assigns them to `to`. - -Requirements: - -- `to` cannot be the zero address. -- If `to` refers to a smart contract, it must implement `IERC1155Receiver::on_ERC1155_received` -and return the acceptance magic value. - -Emits a <> event. - -[.contract-item] -[[ERC1155Component-batch_mint_with_acceptance_check]] -==== `[.contract-item-name]#++batch_mint_with_acceptance_check++#++(ref self: ContractState, to: ContractAddress, token_ids: Span, values: Span, data: Span)++` [.item-kind]#internal# - -Batched version of <>. - -Requirements: - -- `to` cannot be the zero address. -- `token_ids` and `values` must have the same length. -- If `to` refers to a smart contract, it must implement `IERC1155Receiver::on_ERC1155_batch_received` -and return the acceptance magic value. - -Emits a <> event. - -[.contract-item] -[[ERC1155Component-burn]] -==== `[.contract-item-name]#++burn++#++(ref self: ContractState, from: ContractAddress, token_id: u256, value: u256)++` [.item-kind]#internal# - -Destroys a `value` amount of tokens of type `token_id` from `from`. - -Requirements: - -- `from` cannot be the zero address. -- `from` must have at least `value` amount of tokens of type `token_id`. - -Emits a <> event. - -[.contract-item] -[[ERC1155Component-batch_burn]] -==== `[.contract-item-name]#++batch_burn++#++(ref self: ContractState, from: ContractAddress, token_ids: Span, values: Span)++` [.item-kind]#internal# - -Batched version of <>. - -Requirements: - -- `from` cannot be the zero address. -- `from` must have at least `value` amount of tokens of type `token_id`. -- `token_ids` and `values` must have the same length. - -Emits a <> event. - -[.contract-item] -[[ERC1155Component-update_with_acceptance_check]] -==== `[.contract-item-name]#++update_with_acceptance_check++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span, values: Span, data: Span)++` [.item-kind]#internal# - -Version of `update` that performs the token acceptance check by calling -`onERC1155Received` or `onERC1155BatchReceived` in the receiver if -it implements `IERC1155Receiver`, otherwise by checking if it is an account. - -Requirements: - -- `to` is either an account contract or supports the `IERC1155Receiver` interface. -- `token_ids` and `values` must have the same length. - -Emits a <> event if the arrays contain one element, -and <> otherwise. - -[.contract-item] -[[ERC1155Component-update]] -==== `[.contract-item-name]#++update++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_ids: Span, values: Span)++` [.item-kind]#internal# - -Transfers a `value` amount of tokens of type `id` from `from` to `to`. -Will mint (or burn) if `from` (or `to`) is the zero address. - -Requirements: - -- `token_ids` and `values` must have the same length. - -Emits a <> event if the arrays contain one element, -and <> otherwise. - -NOTE: This function can be extended using the xref:ERC1155Component-ERC1155HooksTrait[ERC1155HooksTrait], to add -functionality before and/or after the transfer, mint, or burn. - -NOTE: The ERC1155 acceptance check is not performed in this function. -See <> instead. - -[.contract-item] -[[ERC1155Component-_set_base_uri]] -==== `[.contract-item-name]#++_set_base_uri++#++(ref self: ContractState, base_uri: ByteArray)++` [.item-kind]#internal# - -Sets a new URI for all token types, by relying on the token type ID -substitution mechanism -{eip1155-metadata}[specified in the EIP]. - -By this mechanism, any occurrence of the `\{id\}` substring in either the -URI or any of the values in the JSON file at said URI will be replaced by -clients with the token type ID. - -For example, the pass:[https://token-cdn-domain/\{id\}.json] URI would be -interpreted by clients as -pass:[https://token-cdn-domain/000000000000...000000000000004cce0.json] -for token type ID `0x4cce0`. - -Because these URIs cannot be meaningfully represented by the `URI` event, -this function emits no events. - -==== Events - -[.contract-item] -[[ERC1155Component-TransferSingle]] -==== `[.contract-item-name]#++TransferSingle++#++(operator: ContractAddress, from: ContractAddress, to: ContractAddress, id: u256, value: u256)++` [.item-kind]#event# - -See <>. - -[.contract-item] -[[ERC1155Component-TransferBatch]] -==== `[.contract-item-name]#++TransferBatch++#++(operator: ContractAddress, from: ContractAddress, to: ContractAddress, ids: Span, values: Span)++` [.item-kind]#event# - -See <>. - -[.contract-item] -[[ERC1155Component-ApprovalForAll]] -==== `[.contract-item-name]#++ApprovalForAll++#++(owner: ContractAddress, operator: ContractAddress, approved: bool)++` [.item-kind]#event# - -See <>. - -[.contract-item] -[[ERC1155Component-URI]] -==== `[.contract-item-name]#++URI++#++(value: ByteArray, id: u256)++` [.item-kind]#event# - -See <>. - -[.contract] -[[ERC1155ReceiverComponent]] -=== `++ERC1155ReceiverComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/token/src/erc1155/erc1155_receiver.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_token::erc1155::ERC1155ReceiverComponent; -``` - -ERC1155Receiver component implementing <>. - -NOTE: {src5-component-required-note} - -[.contract-index#ERC1155ReceiverComponent-Embeddable-Mixin-Impl] -.{mixin-impls} --- -.ERC1155MixinImpl -* xref:#ERC1155ReceiverComponent-Embeddable-Impls-ERC1155ReceiverImpl[`++ERC1155ReceiverImpl++`] -* xref:#ERC1155ReceiverComponent-Embeddable-Impls-ERC1155ReceiverCamelImpl[`++ERC1155ReceiverCamelImpl++`] -* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls-SRC5Impl[`++SRC5Impl++`] --- - -[.contract-index#ERC1155ReceiverComponent-Embeddable-Impls] -.Embeddable Implementations --- -.ERC1155ReceiverImpl -* xref:#ERC1155ReceiverComponent-on_erc1155_received[`++on_erc1155_received(self, operator, from, token_id, value, data)++`] -* xref:#ERC1155ReceiverComponent-on_erc1155_batch_received[`++on_erc1155_batch_received(self, operator, from, token_ids, values, data)++`] - -.ERC1155ReceiverCamelImpl -* xref:#ERC1155ReceiverComponent-onERC1155Received[`++onERC1155Received(self, operator, from, tokenId, value, data)++`] -* xref:#ERC1155ReceiverComponent-onERC1155BatchReceived[`++onERC1155BatchReceived(self, operator, from, tokenIds, values, data)++`] --- - -[.contract-index] -.Internal Functions --- -.InternalImpl -* xref:#ERC1155ReceiverComponent-initializer[`++initializer(self)++`] --- - -==== Embeddable functions - -[.contract-item] -[[ERC1155ReceiverComponent-on_erc1155_received]] -==== `[.contract-item-name]#++on_erc1155_received++#++(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_id: u256, value: u256, data Span) -> felt252++` [.item-kind]#external# - -Returns the `IERC1155Receiver` interface ID. - -[.contract-item] -[[ERC1155ReceiverComponent-on_erc1155_batch_received]] -==== `[.contract-item-name]#++on_erc1155_batch_received++#++(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_ids: Span, values: Span, data Span) -> felt252++` [.item-kind]#external# - -Returns the `IERC1155Receiver` interface ID. - -[.contract-item] -[[ERC1155ReceiverComponent-onERC1155Received]] -==== `[.contract-item-name]#++onERC1155Received++#++(self: @ContractState, operator: ContractAddress, from: ContractAddress, tokenId: u256, value: u256, data Span) -> felt252++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC1155ReceiverComponent-onERC1155BatchReceived]] -==== `[.contract-item-name]#++onERC1155BatchReceived++#++(self: @ContractState, operator: ContractAddress, from: ContractAddress, tokenIds: Span, values: Span, data Span) -> felt252++` [.item-kind]#external# - -See <>. - -==== Internal functions - -[.contract-item] -[[ERC1155ReceiverComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState)++` [.item-kind]#internal# - -Registers the `IERC1155Receiver` interface ID as supported through introspection. - -== Presets - -[.contract] -[[ERC1155Upgradeable]] -=== `++ERC1155Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/presets/src/erc1155.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_presets::ERC1155; -``` - -Upgradeable ERC1155 contract leveraging xref:#ERC1155Component[ERC1155Component]. - -include::../utils/_class_hashes.adoc[] - -[.contract-index] -.{presets-page} --- -{ERC1155Upgradeable-class-hash} --- - -[.contract-index] -.Constructor --- -* xref:#ERC1155Upgradeable-constructor[`++constructor(self, base_uri, recipient, token_ids, values, owner)++`] --- - -[.contract-index] -.Embedded Implementations --- -.ERC1155Component - -* xref:#ERC1155Component-Embeddable-Mixin-Impl[`++ERC1155MixinImpl++`] - -.OwnableMixinImpl - -* xref:/api/access.adoc#OwnableComponent-Mixin-Impl[`++OwnableMixinImpl++`] --- - -[.contract-index] -.External Functions --- -* xref:#ERC1155Upgradeable-upgrade[`++upgrade(self, new_class_hash)++`] --- - -[#ERC1155Upgradeable-constructor-section] -==== Constructor - -[.contract-item] -[[ERC1155Upgradeable-constructor]] -==== `[.contract-item-name]#++constructor++#++(ref self: ContractState, base_uri: ByteArray, recipient: ContractAddress, token_ids: Span, values: Span, owner: ContractAddress)++` [.item-kind]#constructor# - -Sets the `base_uri` for all tokens and registers the supported interfaces. -Mints the `values` for `token_ids` tokens to `recipient`. -Assigns `owner` as the contract owner with permissions to upgrade. - -Requirements: - -- `to` is either an account contract (supporting ISRC6) or - supports the `IERC1155Receiver` interface. -- `token_ids` and `values` must have the same length. - -[#ERC1155Upgradeable-external-functions] -==== External Functions - -[.contract-item] -[[ERC1155Upgradeable-upgrade]] -==== `[.contract-item-name]#++upgrade++#++(ref self: ContractState, new_class_hash: ClassHash)++` [.item-kind]#external# - -Upgrades the contract to a new implementation given by `new_class_hash`. - -Requirements: - -- The caller is the contract owner. -- `new_class_hash` cannot be zero. diff --git a/docs/modules/ROOT/pages/api/erc20.adoc b/docs/modules/ROOT/pages/api/erc20.adoc deleted file mode 100644 index ce8c38f3b..000000000 --- a/docs/modules/ROOT/pages/api/erc20.adoc +++ /dev/null @@ -1,1610 +0,0 @@ -:github-icon: pass:[] -:eip20: https://eips.ethereum.org/EIPS/eip-20[EIP-20] -:erc20-guide: xref:erc20.adoc[ERC20 guide] -:casing-discussion: https://github.com/OpenZeppelin/cairo-contracts/discussions/34[here] -:custom-decimals: xref:/erc20.adoc#customizing_decimals[Customizing decimals] -:snip-12: https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md[SNIP12] -:snip12-metadata: xref:api/utilities.adoc#snip12[SNIP12Metadata] -:eip-2612: https://eips.ethereum.org/EIPS/eip-2612[EIP-2612] -:eip4626: https://eips.ethereum.org/EIPS/eip-4626[EIP-4626] - -= ERC20 - -include::../utils/_common.adoc[] - -This module provides interfaces, presets, and utilities related to ERC20 contracts. - -TIP: For an overview of ERC20, read our {erc20-guide}. - -== Interfaces - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_token` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[IERC20]] -=== `++IERC20++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc20.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc20::IERC20; -``` - -Interface of the IERC20 standard as defined in {eip20}. - -[.contract-index] -.Functions --- -* xref:#IERC20-total_supply[`++total_supply()++`] -* xref:#IERC20-balance_of[`++balance_of(account)++`] -* xref:#IERC20-allowance[`++allowance(owner, spender)++`] -* xref:#IERC20-transfer[`++transfer(recipient, amount)++`] -* xref:#IERC20-transfer_from[`++transfer_from(sender, recipient, amount)++`] -* xref:#IERC20-approve[`++approve(spender, amount)++`] --- - -[.contract-index] -.Events --- -* xref:#IERC20-Transfer[`++Transfer(from, to, value)++`] -* xref:#IERC20-Approval[`++Approval(owner, spender, value)++`] --- - -[#IERC20-Functions] -==== Functions - -[.contract-item] -[[IERC20-total_supply]] -==== `[.contract-item-name]#++total_supply++#++() → u256++` [.item-kind]#external# - -Returns the amount of tokens in existence. - -[.contract-item] -[[IERC20-balance_of]] -==== `[.contract-item-name]#++balance_of++#++(account: ContractAddress) → u256++` [.item-kind]#external# - -Returns the amount of tokens owned by `account`. - -[.contract-item] -[[IERC20-allowance]] -==== `[.contract-item-name]#++allowance++#++(owner: ContractAddress, spender: ContractAddress) → u256++` [.item-kind]#external# - -Returns the remaining number of tokens that `spender` is allowed to spend on behalf of `owner` through <>. This is zero by default. - -This value changes when <> or <> are called. - -[.contract-item] -[[IERC20-transfer]] -==== `[.contract-item-name]#++transfer++#++(recipient: ContractAddress, amount: u256) → bool++` [.item-kind]#external# - -Moves `amount` tokens from the caller's token balance to `to`. -Returns `true` on success, reverts otherwise. - -Emits a <> event. - -[.contract-item] -[[IERC20-transfer_from]] -==== `[.contract-item-name]#++transfer_from++#++(sender: ContractAddress, recipient: ContractAddress, amount: u256) → bool++` [.item-kind]#external# - -Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. -`amount` is then deducted from the caller's allowance. -Returns `true` on success, reverts otherwise. - -Emits a <> event. - -[.contract-item] -[[IERC20-approve]] -==== `[.contract-item-name]#++approve++#++(spender: ContractAddress, amount: u256) → bool++` [.item-kind]#external# - -Sets `amount` as the allowance of `spender` over the caller's tokens. -Returns `true` on success, reverts otherwise. - -Emits an <> event. - -[#IERC20-Events] -==== Events - -[.contract-item] -[[IERC20-Transfer]] -==== `[.contract-item-name]#++Transfer++#++(from: ContractAddress, to: ContractAddress, value: u256)++` [.item-kind]#event# - -Emitted when `value` tokens are moved from one address (`from`) to another (`to`). - -Note that `value` may be zero. - -[.contract-item] -[[IERC20-Approval]] -==== `[.contract-item-name]#++Approval++#++(owner: ContractAddress, spender: ContractAddress, value: u256)++` [.item-kind]#event# - -Emitted when the allowance of a `spender` for an `owner` is set. -`value` is the new allowance. - -[.contract] -[[IERC20Metadata]] -=== `++IERC20Metadata++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc20.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc20::IERC20Metadata; -``` - -Interface for the optional metadata functions in {eip20}. - -[.contract-index] -.Functions --- -* xref:#IERC20Metadata-name[`++name()++`] -* xref:#IERC20Metadata-symbol[`++symbol()++`] -* xref:#IERC20Metadata-decimals[`++decimals()++`] --- - -[#IERC20Metadata-Functions] -==== Functions - -[.contract-item] -[[IERC20Metadata-name]] -==== `[.contract-item-name]#++name++#++() → ByteArray++` [.item-kind]#external# - -Returns the name of the token. - -[.contract-item] -[[IERC20Metadata-symbol]] -==== `[.contract-item-name]#++symbol++#++() → ByteArray++` [.item-kind]#external# - -Returns the ticker symbol of the token. - -[.contract-item] -[[IERC20Metadata-decimals]] -==== `[.contract-item-name]#++decimals++#++() → u8++` [.item-kind]#external# - -Returns the number of decimals the token uses - e.g. `8` means to divide the token amount by `100000000` to get its user-readable representation. - -For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). - -Tokens usually opt for a value of `18`, imitating the relationship between Ether and Wei. -This is the default value returned by this function. -To create a custom decimals implementation, see {custom-decimals}. - -NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract. - -[.contract] -[[IERC20Permit]] -=== `++IERC20Permit++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc20.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc20::IERC20Permit; -``` - -Interface of the ERC20Permit standard to support gasless token approvals as defined in {eip-2612}. - -[.contract-index] -.Functions --- -* xref:#IERC20Permit-permit[`++permit(owner, spender, amount, deadline, signature)++`] -* xref:#IERC20Permit-nonces[`++nonces(owner)++`] -* xref:#IERC20Permit-DOMAIN_SEPARATOR[`++DOMAIN_SEPARATOR()++`] --- - -[#IERC20Permit-Functions] -==== Functions - -[.contract-item] -[[IERC20Permit-permit]] -==== `[.contract-item-name]#++permit++#++(owner: ContractAddress, spender: ContractAddress, amount: u256, deadline: u64, signature: Span)++` [.item-kind]#external# - -Sets `amount` as the allowance of `spender` over ``owner``'s tokens after validating the signature. - -[.contract-item] -[[IERC20Permit-nonces]] -==== `[.contract-item-name]#++nonces++#++(owner: ContractAddress) → felt252++` [.item-kind]#external# - -Returns the current nonce of `owner`. A nonce value must be included -whenever a signature for `permit` call is generated. - -[.contract-item] -[[IERC20Permit-DOMAIN_SEPARATOR]] -==== `[.contract-item-name]#++DOMAIN_SEPARATOR++#++() → felt252++` [.item-kind]#external# - -Returns the domain separator used in generating a message hash for `permit` signature. -The domain hashing logic follows the {snip-12} standard. - -[.contract] -[[IERC4626]] -=== `++IERC4626++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc4626.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc4626::IERC4626; -``` - -Interface of the IERC4626 standard as defined in {eip4626}. - -[.contract-index] -.Functions --- -* xref:#IERC4626-asset[`++asset()++`] -* xref:#IERC4626-total_assets[`++total_assets()++`] -* xref:#IERC4626-convert_to_shares[`++convert_to_shares(assets)++`] -* xref:#IERC4626-convert_to_assets[`++convert_to_assets(shares)++`] -* xref:#IERC4626-max_deposit[`++max_deposit(receiver)++`] -* xref:#IERC4626-preview_deposit[`++preview_deposit(assets)++`] -* xref:#IERC4626-deposit[`++deposit(assets, receiver)++`] -* xref:#IERC4626-max_mint[`++max_mint(receiver)++`] -* xref:#IERC4626-preview_mint[`++preview_mint(shares)++`] -* xref:#IERC4626-mint[`++mint(shares, receiver)++`] -* xref:#IERC4626-max_withdraw[`++max_withdraw(owner)++`] -* xref:#IERC4626-preview_withdraw[`++preview_withdraw(assets)++`] -* xref:#IERC4626-withdraw[`++withdraw(assets, receiver, owner)++`] -* xref:#IERC4626-max_redeem[`++max_redeem(owner)++`] -* xref:#IERC4626-preview_redeem[`++preview_redeem(shares)++`] -* xref:#IERC4626-redeem[`++redeem(shares, receiver, owner)++`] --- - -[.contract-index] -.Events --- -* xref:#IERC4626-Deposit[`++Deposit(sender, owner, assets, shares)++`] -* xref:#IERC4626-Withdraw[`++Withdraw(sender, receiver, owner, assets, shares)++`] --- - -[#IERC4626-Functions] -==== Functions - -[.contract-item] -[[IERC4626-asset]] -==== `[.contract-item-name]#++asset++#++() → ContractAddress++` [.item-kind]#external# - -Returns the address of the underlying token used for the Vault for accounting, depositing, -and withdrawing. - -Requirements: - -- MUST be an ERC20 token contract. -- MUST NOT panic. - -[.contract-item] -[[IERC4626-total_assets]] -==== `[.contract-item-name]#++total_assets++#++() → u256++` [.item-kind]#external# - -Returns the total amount of the underlying asset that is “managed” by Vault. - -Requirements: - -- SHOULD include any compounding that occurs from yield. -- MUST be inclusive of any fees that are charged against assets in the Vault. -- MUST NOT panic. - -[.contract-item] -[[IERC4626-convert_to_shares]] -==== `[.contract-item-name]#++convert_to_shares++#++(assets: u256) → u256++` [.item-kind]#external# - -Returns the amount of shares that the Vault would exchange for the amount of `assets` -provided irrespective of slippage or fees. - -Requirements: - -- MUST NOT be inclusive of any fees that are charged against assets in the Vault. -- MUST NOT show any variations depending on the caller. -- MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. -- MUST NOT panic unless due to integer overflow caused by an unreasonably large input. -- MUST round down towards 0. - -NOTE: This calculation MAY NOT reflect the "per-user" price-per-share, and instead should -reflect the "average-user's" price-per-share, meaning what the average user should expect to -see when exchanging to and from. - -[.contract-item] -[[IERC4626-convert_to_assets]] -==== `[.contract-item-name]#++convert_to_assets++#++(shares: u256) → u256++` [.item-kind]#external# - -Returns the amount of assets that the Vault would exchange for the amount of `shares` -provided irrespective of slippage or fees. - -Requirements: - -- MUST NOT be inclusive of any fees that are charged against assets in the Vault. -- MUST NOT show any variations depending on the caller. -- MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. -- MUST NOT panic unless due to integer overflow caused by an unreasonably large input. -- MUST round down towards 0. - -NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead -should reflect the “average-user’s” price-per-share, meaning what the average user -should expect to see when exchanging to and from. - -[.contract-item] -[[IERC4626-max_deposit]] -==== `[.contract-item-name]#++max_deposit++#++(receiver: ContractAddress) → u256++` [.item-kind]#external# - -Returns the maximum amount of the underlying asset that can be deposited into the Vault for -`receiver`, through a deposit call. - -Requirements: - -- MUST return a limited value if receiver is subject to some deposit limit. -- MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be - deposited. -- MUST NOT panic. - -[.contract-item] -[[IERC4626-preview_deposit]] -==== `[.contract-item-name]#++preview_deposit++#++(assets: u256) → u256++` [.item-kind]#external# - -Allows an on-chain or off-chain user to simulate the effects of their deposit at the current -block, given current on-chain conditions. - -Requirements: - -- MUST return as close to and no more than the exact amount of Vault shares that would be - minted in a deposit call in the same transaction i.e. <> should return the same or more - shares as `preview_deposit` if called in the same transaction. -- MUST NOT account for deposit limits like those returned from <> and should always - act as though the deposit would be accepted, regardless if the user has enough tokens - approved, etc. -- MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit - fees. -- MUST NOT panic. - -NOTE: Any unfavorable discrepancy between <> and `preview_deposit` -SHOULD be considered slippage in share price or some other type of condition, meaning the -depositor will lose assets by depositing. - -[.contract-item] -[[IERC4626-deposit]] -==== `[.contract-item-name]#++deposit++#++(assets: u256, receiver: ContractAddress) → u256++` [.item-kind]#external# - -Mints Vault shares to `receiver` by depositing exactly amount of `assets`. - -Requirements: - -- MUST emit the <> event. -- MAY support an additional flow in which the underlying tokens are owned by the Vault - contract before the deposit execution, and are accounted for during deposit. -- MUST panic if all of assets cannot be deposited (due to deposit limit being reached, - slippage, the user not approving enough underlying tokens to the Vault contract, etc). - -NOTE: Most implementations will require pre-approval of the Vault with the Vault’s -underlying asset token. - -[.contract-item] -[[IERC4626-max_mint]] -==== `[.contract-item-name]#++max_mint++#++(receiver: ContractAddress) → u256++` [.item-kind]#external# - -Returns the maximum amount of the Vault shares that can be minted for the receiver, through -a mint call. - -Requirements: - -- MUST return a limited value if receiver is subject to some mint limit. -- MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be - minted. -- MUST NOT panic. - -[.contract-item] -[[IERC4626-preview_mint]] -==== `[.contract-item-name]#++preview_mint++#++(shares: u256) → u256++` [.item-kind]#external# - -Allows an on-chain or off-chain user to simulate the effects of their mint at the current -block, given current on-chain conditions. - -Requirements: - -- MUST return as close to and no fewer than the exact amount of assets that would be deposited - in a `mint` call in the same transaction. I.e. <> should return the same or fewer assets - as `preview_mint` if called in the same transaction. -- MUST NOT account for mint limits like those returned from <> and should always act - as though the mint would be accepted, regardless if the user has enough tokens approved, - etc. -- MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit - fees. -- MUST NOT panic. - -NOTE: Any unfavorable discrepancy between <> and -`preview_mint` SHOULD be considered slippage in share price or some other type of condition, -meaning the depositor will lose assets by minting. - -[.contract-item] -[[IERC4626-mint]] -==== `[.contract-item-name]#++mint++#++(shares: u256, receiver: ContractAddress) → u256++` [.item-kind]#external# - -Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. - -Requirements: - -- MUST emit the <> event. -- MAY support an additional flow in which the underlying tokens are owned by the Vault - contract before the mint execution, and are accounted for during mint. -- MUST panic if all of shares cannot be minted (due to deposit limit being reached, slippage, - the user not approving enough underlying tokens to the Vault contract, etc). - -NOTE: Most implementations will require pre-approval of the Vault with the Vault’s -underlying asset token. - -[.contract-item] -[[IERC4626-max_withdraw]] -==== `[.contract-item-name]#++max_withdraw++#++(owner: ContractAddress) → u256++` [.item-kind]#external# - -Returns the maximum amount of the underlying asset that can be withdrawn from the owner -balance in the Vault, through a withdraw call. - -Requirements: - -- MUST return a limited value if owner is subject to some withdrawal limit or timelock. -- MUST NOT panic. - -[.contract-item] -[[IERC4626-preview_withdraw]] -==== `[.contract-item-name]#++preview_withdraw++#++(assets: u256) → u256++` [.item-kind]#external# - -Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the -current block, given current on-chain conditions. - -Requirements: - -- MUST return as close to and no fewer than the exact amount of Vault shares that would be - burned in a withdraw call in the same transaction i.e. <> should return the same or - fewer shares as `preview_withdraw` if called in the same transaction. -- MUST NOT account for withdrawal limits like those returned from <> and should - always act as though the withdrawal would be accepted, regardless if the user has enough - shares, etc. -- MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of - withdrawal fees. -- MUST NOT panic. - -NOTE: Any unfavorable discrepancy between <> and `preview_withdraw` -SHOULD be considered slippage in share price or some other type of condition, meaning the -depositor will lose assets by depositing. - -[.contract-item] -[[IERC4626-withdraw]] -==== `[.contract-item-name]#++withdraw++#++(assets: u256, receiver: ContractAddress, owner: ContractAddress) → u256++` [.item-kind]#external# - -Burns shares from owner and sends exactly assets of underlying tokens to receiver. - -Requirements: - -- MUST emit the <> event. -- MAY support an additional flow in which the underlying tokens are owned by the Vault - contract before the withdraw execution, and are accounted for during withdraw. -- MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, - slippage, the owner not having enough shares, etc). - -NOTE: Some implementations will require pre-requesting to the Vault before a withdrawal -may be performed. -Those methods should be performed separately. - -[.contract-item] -[[IERC4626-max_redeem]] -==== `[.contract-item-name]#++max_redeem++#++(owner: ContractAddress) → u256++` [.item-kind]#external# - -Returns the maximum amount of Vault shares that can be redeemed from the owner balance in -the Vault, through a redeem call. - -Requirements: - -- MUST return a limited value if owner is subject to some withdrawal limit or timelock. -- MUST return `ERC20::balance_of(owner)` if `owner` is not subject to any withdrawal limit or - timelock. -- MUST NOT panic. - -[.contract-item] -[[IERC4626-preview_redeem]] -==== `[.contract-item-name]#++preview_redeem++#++(shares: u256) → u256++` [.item-kind]#external# - -Allows an on-chain or off-chain user to simulate the effects of their redeemption at the -current block, given current on-chain conditions. - -Requirements: - -- MUST return as close to and no more than the exact amount of assets that would be withdrawn - in a redeem call in the same transaction i.e. <> should return the same or more assets - as preview_redeem if called in the same transaction. -- MUST NOT account for redemption limits like those returned from <> and should always - act as though the redemption would be accepted, regardless if the user has enough shares, - etc. -- MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of - withdrawal fees. -- MUST NOT panic. - -NOTE: Any unfavorable discrepancy between <> and `preview_redeem` SHOULD be -considered slippage in share price or some other type of condition, meaning the depositor -will lose assets by redeeming. - -[.contract-item] -[[IERC4626-redeem]] -==== `[.contract-item-name]#++redeem++#++(shares: u256, receiver: ContractAddress, owner: ContractAddress) → u256++` [.item-kind]#external# - -Burns exactly shares from owner and sends assets of underlying tokens to receiver. - -Requirements: - -- MUST emit the <> event. -- MAY support an additional flow in which the underlying tokens are owned by the Vault - contract before the redeem execution, and are accounted for during redeem. -- MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, - slippage, the owner not having enough shares, etc). - -NOTE: Some implementations will require pre-requesting to the Vault before a withdrawal may be performed. -Those methods should be performed separately. - -[#IERC4626-Events] -==== Events - -[.contract-item] -[[IERC4626-Deposit]] -==== `[.contract-item-name]#++Deposit++#++(sender: ContractAddress, owner: ContractAddress, assets: u256, shares: u256)++` [.item-kind]#event# - -Emitted when `sender` exchanges `assets` for `shares` and transfers those -`shares` to `owner`. - -[.contract-item] -[[IERC4626-Withdraw]] -==== `[.contract-item-name]#++Withdraw++#++(sender: ContractAddress, receiver: ContractAddress, owner: ContractAddress, assets: u256, shares: u256)++` [.item-kind]#event# - -Emitted when `sender` exchanges `shares`, owned by `owner`, for `assets` and transfers -those `assets` to `receiver`. - -== Core - -[.contract] -[[ERC20Component]] -=== `++ERC20Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/token/src/erc20/erc20.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_token::erc20::ERC20Component; -``` -ERC20 component extending <> and <>. - -NOTE: See xref:#ERC20Component-Hooks[Hooks] to understand how are hooks used. - -[.contract-index] -.Hooks --- -[.sub-index#ERC20Component-ERC20HooksTrait] -.ERC20HooksTrait -* xref:#ERC20Component-before_update[`++before_update(self, from, recipient, amount)++`] -* xref:#ERC20Component-after_update[`++after_update(self, from, recipient, amount)++`] --- - -[.contract-index#ERC20Component-Embeddable-Mixin-Impl] -.{mixin-impls} --- -.ERC20MixinImpl -* xref:#ERC20Component-Embeddable-Impls-ERC20Impl[`++ERC20Impl++`] -* xref:#ERC20Component-Embeddable-Impls-ERC20MetadataImpl[`++ERC20MetadataImpl++`] -* xref:#ERC20Component-Embeddable-Impls-ERC20CamelOnlyImpl[`++ERC20CamelOnlyImpl++`] --- - -[.contract-index#ERC20Component-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#ERC20Component-Embeddable-Impls-ERC20Impl] -.ERC20Impl -* xref:#ERC20Component-total_supply[`++total_supply(self)++`] -* xref:#ERC20Component-balance_of[`++balance_of(self, account)++`] -* xref:#ERC20Component-allowance[`++allowance(self, owner, spender)++`] -* xref:#ERC20Component-transfer[`++transfer(self, recipient, amount)++`] -* xref:#ERC20Component-transfer_from[`++transfer_from(self, sender, recipient, amount)++`] -* xref:#ERC20Component-approve[`++approve(self, spender, amount)++`] - -[.sub-index#ERC20Component-Embeddable-Impls-ERC20MetadataImpl] -.ERC20MetadataImpl -* xref:#ERC20Component-name[`++name(self)++`] -* xref:#ERC20Component-symbol[`++symbol(self)++`] -* xref:#ERC20Component-decimals[`++decimals(self)++`] - -[.sub-index#ERC20Component-Embeddable-Impls-ERC20CamelOnlyImpl] -.ERC20CamelOnlyImpl -* xref:#ERC20Component-totalSupply[`++totalSupply(self)++`] -* xref:#ERC20Component-balanceOf[`++balanceOf(self, account)++`] -* xref:#ERC20Component-transferFrom[`++transferFrom(self, sender, recipient, amount)++`] - -[.sub-index#ERC20Component-Embeddable-Impls-ERC20PermitImpl] -.ERC20PermitImpl -* xref:#ERC20Component-permit[`++permit(self, owner, spender, amount, deadline, signature)++`] -* xref:#ERC20Component-nonces[`++nonces(self, owner)++`] -* xref:#ERC20Component-DOMAIN_SEPARATOR[`++DOMAIN_SEPARATOR(self)++`] - -[.sub-index#ERC20Component-Embeddable-Impls-SNIP12MetadataExternalImpl] -.SNIP12MetadataExternalImpl -* xref:#ERC20Component-snip12_metadata[`++snip12_metadata(self)++`] --- - -[.contract-index] -.Internal implementations --- -.InternalImpl -* xref:#ERC20Component-initializer[`++initializer(self, name, symbol)++`] -* xref:#ERC20Component-mint[`++mint(self, recipient, amount)++`] -* xref:#ERC20Component-burn[`++burn(self, account, amount)++`] -* xref:#ERC20Component-update[`++update(self, from, to, amount)++`] -* xref:#ERC20Component-_transfer[`++_transfer(self, sender, recipient, amount)++`] -* xref:#ERC20Component-_approve[`++_approve(self, owner, spender, amount)++`] -* xref:#ERC20Component-_spend_allowance[`++_spend_allowance(self, owner, spender, amount)++`] --- - -[.contract-index] -.Events --- -* xref:#ERC20Component-Transfer[`++Transfer(from, to, value)++`] -* xref:#ERC20Component-Approval[`++Approval(owner, spender, value)++`] --- - -[#ERC20Component-Hooks] -==== Hooks - -Hooks are functions which implementations can extend the functionality of the component source code. Every contract -using ERC20Component is expected to provide an implementation of the ERC20HooksTrait. For basic token contracts, an -empty implementation with no logic must be provided. - -TIP: You can use `openzeppelin_token::erc20::ERC20HooksEmptyImpl` which is already available as part of the library -for this purpose. - -[.contract-item] -[[ERC20Component-before_update]] -==== `[.contract-item-name]#++before_update++#++(ref self: ContractState, from: ContractAddress, recipient: ContractAddress, amount: u256)++` [.item-kind]#hook# - -Function executed at the beginning of the xref:#ERC20Component-update[update] function prior to any other logic. - -[.contract-item] -[[ERC20Component-after_update]] -==== `[.contract-item-name]#++after_update++#++(ref self: ContractState, from: ContractAddress, recipient: ContractAddress, amount: u256)++` [.item-kind]#hook# - -Function executed at the end of the xref:#ERC20Component-update[update] function. - -[#ERC20Component-Embeddable-functions] -==== Embeddable functions - -[.contract-item] -[[ERC20Component-total_supply]] -==== `[.contract-item-name]#++total_supply++#++(@self: ContractState) → u256++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC20Component-balance_of]] -==== `[.contract-item-name]#++balance_of++#++(@self: ContractState, account: ContractAddress) → u256++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC20Component-allowance]] -==== `[.contract-item-name]#++allowance++#++(@self: ContractState, owner: ContractAddress, spender: ContractAddress) → u256++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC20Component-transfer]] -==== `[.contract-item-name]#++transfer++#++(ref self: ContractState, recipient: ContractAddress, amount: u256) → bool++` [.item-kind]#external# - -See <>. - -Requirements: - -- `recipient` cannot be the zero address. -- The caller must have a balance of at least `amount`. - -[.contract-item] -[[ERC20Component-transfer_from]] -==== `[.contract-item-name]#++transfer_from++#++(ref self: ContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256) → bool++` [.item-kind]#external# - -See <>. - -Requirements: - -- `sender` cannot be the zero address. -- `sender` must have a balance of at least `amount`. -- `recipient` cannot be the zero address. -- The caller must have allowance for ``sender``'s tokens of at least `amount`. - -[.contract-item] -[[ERC20Component-approve]] -==== `[.contract-item-name]#++approve++#++(ref self: ContractState, spender: ContractAddress, amount: u256) → bool++` [.item-kind]#external# - -See <>. - -Requirements: - -- `spender` cannot be the zero address. - -[.contract-item] -[[ERC20Component-name]] -==== `[.contract-item-name]#++name++#++() → ByteArray++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC20Component-symbol]] -==== `[.contract-item-name]#++symbol++#++() → ByteArray++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC20Component-decimals]] -==== `[.contract-item-name]#++decimals++#++() → u8++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC20Component-totalSupply]] -==== `[.contract-item-name]#++totalSupply++#++(self: @ContractState) → u256++` [.item-kind]#external# - -See <>. - -Supports the Cairo v0 convention of writing external methods in camelCase as discussed {casing-discussion}. - -[.contract-item] -[[ERC20Component-balanceOf]] -==== `[.contract-item-name]#++balanceOf++#++(self: @ContractState, account: ContractAddress) → u256++` [.item-kind]#external# - -See <>. - -Supports the Cairo v0 convention of writing external methods in camelCase as discussed {casing-discussion}. - -[.contract-item] -[[ERC20Component-transferFrom]] -==== `[.contract-item-name]#++transferFrom++#++(ref self: ContractState, sender: ContractAddress, recipient: ContractAddress) → bool++` [.item-kind]#external# - -See <>. - -Supports the Cairo v0 convention of writing external methods in camelCase as discussed {casing-discussion}. - -[.contract-item] -[[ERC20Component-permit]] -==== `[.contract-item-name]#++permit++#++(ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256, deadline: u64, signature: Span) → bool++` [.item-kind]#external# - -Sets `amount` as the allowance of `spender` over ``owner``'s tokens after validating the -signature. - -Requirements: - -- `owner` is a deployed account contract. -- `spender` is not the zero address. -- `deadline` is not a timestamp in the past. -- `signature` is a valid signature that can be validated with a call to `owner` account. -- `signature` must use the current nonce of the `owner`. - -Emits an <> event. -Every successful call increases `owner`'s nonce by one. - -[.contract-item] -[[ERC20Component-nonces]] -==== `[.contract-item-name]#++nonces++#++(self: @ContractState, owner: ContractAddress) → felt252++` [.item-kind]#external# - -Returns the current nonce of `owner`. A nonce value must be included -whenever a signature for `permit` call is generated. - -[.contract-item] -[[ERC20Component-DOMAIN_SEPARATOR]] -==== `[.contract-item-name]#++DOMAIN_SEPARATOR++#++(self: @ContractState) → felt252++` [.item-kind]#external# - -Returns the domain separator used in generating a message hash for `permit` signature. -The domain hashing logic follows the {snip-12} standard. - -[.contract-item] -[[ERC20Component-snip12_metadata]] -==== `[.contract-item-name]#++snip12_metadata++#++(self: @ContractState) → (felt252, felt252)++` [.item-kind]#external# - -Returns the domain name and version used to generate the message hash for permit signature. - -The returned tuple contains: - -- `t.0`: The name used in the {snip12-metadata} implementation. -- `t.1`: The version used in the {snip12-metadata} implementation. - -[#ERC20Component-Internal-functions] -==== Internal functions - -[.contract-item] -[[ERC20Component-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, name: ByteArray, symbol: ByteArray)++` [.item-kind]#internal# - -Initializes the contract by setting the token name and symbol. -This should be used inside of the contract's constructor. - -[.contract-item] -[[ERC20Component-mint]] -==== `[.contract-item-name]#++mint++#++(ref self: ContractState, recipient: ContractAddress, amount: u256)++` [.item-kind]#internal# - -Creates an `amount` number of tokens and assigns them to `recipient`. - -Emits a <> event with `from` being the zero address. - -Requirements: - -- `recipient` cannot be the zero address. - -[.contract-item] -[[ERC20Component-burn]] -==== `[.contract-item-name]#++burn++#++(ref self: ContractState, account: ContractAddress, amount: u256)++` [.item-kind]#internal# - -Destroys `amount` number of tokens from `account`. - -Emits a <> event with `to` set to the zero address. - -Requirements: - -- `account` cannot be the zero address. - -[.contract-item] -[[ERC20Component-update]] -==== `[.contract-item-name]#++update++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256)++` [.item-kind]#internal# - -Transfers an `amount` of tokens from `from` to `to`, or alternatively mints (or burns) if `from` (or `to`) is -the zero address. - -NOTE: This function can be extended using the xref:ERC20Component-ERC20HooksTrait[ERC20HooksTrait], to add -functionality before and/or after the transfer, mint, or burn. - -Emits a <> event. - -[.contract-item] -[[ERC20Component-_transfer]] -==== `[.contract-item-name]#++_transfer++#++(ref self: ContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256)++` [.item-kind]#internal# - -Moves `amount` of tokens from `from` to `to`. - -This internal function does not check for access permissions but can be useful as a building block, for example to implement automatic token fees, slashing mechanisms, etc. - -Emits a <> event. - -Requirements: - -- `from` cannot be the zero address. -- `to` cannot be the zero address. -- `from` must have a balance of at least `amount`. - -[.contract-item] -[[ERC20Component-_approve]] -==== `[.contract-item-name]#++_approve++#++(ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256)++` [.item-kind]#internal# - -Sets `amount` as the allowance of `spender` over ``owner``'s tokens. - -This internal function does not check for access permissions but can be useful as a building block, for example to implement automatic allowances on behalf of other addresses. - -Emits an <> event. - -Requirements: - -- `owner` cannot be the zero address. -- `spender` cannot be the zero address. - -[.contract-item] -[[ERC20Component-_spend_allowance]] -==== `[.contract-item-name]#++_spend_allowance++#++(ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256)++` [.item-kind]#internal# - -Updates ``owner``'s allowance for `spender` based on spent `amount`. - -This internal function does not update the allowance value in the case of infinite allowance. - -Possibly emits an <> event. - -[#ERC20Component-Events] -==== Events - -[.contract-item] -[[ERC20Component-Transfer]] -==== `[.contract-item-name]#++Transfer++#++(from: ContractAddress, to: ContractAddress, value: u256)++` [.item-kind]#event# - -See <>. - -[.contract-item] -[[ERC20Component-Approval]] -==== `[.contract-item-name]#++Approval++#++(owner: ContractAddress, spender: ContractAddress, value: u256)++` [.item-kind]#event# - -See <>. - -== Extensions - -[.contract] -[[ERC4626Component]] -=== `++ERC4626Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/token/src/erc20/extensions/erc4626/interface.cairo#L19[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_token::erc20::extensions::erc4626::ERC4626Component; -``` - -Extension of ERC20 that implements the <> interface which allows the minting and burning of "shares" in exchange for an underlying "asset." -The component leverages traits to configure fees, limits, and decimals. - -[.contract-index] -.{immutable-config} --- -.constants -* xref:#ERC4626Component-IC-UNDERLYING_DECIMALS[`++UNDERLYING_DECIMALS++`] -* xref:#ERC4626Component-IC-DECIMALS_OFFSET[`++DECIMALS_OFFSET++`] - -.functions -* xref:#ERC4626Component-IC-validate[`++validate()++`] --- - -[.contract-index] -.Hooks --- -[.sub-index#ERC4626Component-FeeConfigTrait] -.FeeConfigTrait -* xref:#ERC4626Component-calculate_deposit_fee[`++calculate_deposit_fee(self, assets, shares)++`] -* xref:#ERC4626Component-calculate_mint_fee[`++calculate_mint_fee(self, assets, shares)++`] -* xref:#ERC4626Component-calculate_withdraw_fee[`++calculate_withdraw_fee(self, assets, shares)++`] -* xref:#ERC4626Component-calculate_redeem_fee[`++calculate_redeem_fee(self, assets, shares)++`] - -[.sub-index#ERC4626Component-LimitConfigTrait] -.LimitConfigTrait -* xref:#ERC4626Component-deposit_limit[`++deposit_limit(self, receiver)++`] -* xref:#ERC4626Component-mint_limit[`++mint_limit(self, receiver)++`] -* xref:#ERC4626Component-withdraw_limit[`++withdraw_limit(self, owner)++`] -* xref:#ERC4626Component-redeem_limit[`++redeem_limit(self, owner)++`] - -[.sub-index#ERC4626Component-ERC4626HooksTrait] -.ERC4626HooksTrait -* xref:#ERC4626Component-before_deposit[`++before_deposit(self, caller, receiver, assets, shares, fee)++`] -* xref:#ERC4626Component-after_deposit[`++after_deposit(self, caller, receiver, assets, shares, fee)++`] -* xref:#ERC4626Component-before_withdraw[`++before_withdraw(self, caller, receiver, owner, assets, shares, fee)++`] -* xref:#ERC4626Component-after_withdraw[`++after_withdraw(self, caller, receiver, owner, assets, shares, fee)++`] - -[.sub-index#ERC4626Component-AssetsManagementTrait] -.AssetsManagementTrait -* xref:#ERC4626Component-get_total_assets[`++get_total_assets(self)++`] -* xref:#ERC4626Component-transfer_assets_in[`++transfer_assets_in(self, from, assets)++`] -* xref:#ERC4626Component-transfer_assets_out[`++transfer_assets_out(self, to, assets)++`] --- - -[.contract-index#ERC4626Component-Embeddable-Impls] -.Embeddable Implementations --- - -.ERC4626Impl -* xref:#ERC4626Component-asset[`++asset(self)++`] -* xref:#ERC4626Component-total_assets[`++total_assets(self)++`] -* xref:#ERC4626Component-convert_to_shares[`++convert_to_shares(self, assets)++`] -* xref:#ERC4626Component-convert_to_assets[`++convert_to_assets(self, shares)++`] -* xref:#ERC4626Component-max_deposit[`++max_deposit(self, receiver)++`] -* xref:#ERC4626Component-preview_deposit[`++preview_deposit(self, assets)++`] -* xref:#ERC4626Component-deposit[`++deposit(self, assets, receiver)++`] -* xref:#ERC4626Component-max_mint[`++max_mint(self, receiver)++`] -* xref:#ERC4626Component-preview_mint[`++preview_mint(self, shares)++`] -* xref:#ERC4626Component-mint[`++mint(self, shares, receiver)++`] -* xref:#ERC4626Component-max_withdraw[`++max_withdraw(self, owner)++`] -* xref:#ERC4626Component-preview_withdraw[`++preview_withdraw(self, assets)++`] -* xref:#ERC4626Component-withdraw[`++withdraw(self, assets, receiver, owner)++`] -* xref:#ERC4626Component-max_redeem[`++max_redeem(self, owner)++`] -* xref:#ERC4626Component-preview_redeem[`++preview_redeem(self, shares)++`] -* xref:#ERC4626Component-redeem[`++redeem(self, shares, receiver, owner)++`] - -.ERC20Impl -* xref:#ERC20Component-total_supply[`++total_supply(self)++`] -* xref:#ERC20Component-balance_of[`++balance_of(self, account)++`] -* xref:#ERC20Component-allowance[`++allowance(self, owner, spender)++`] -* xref:#ERC20Component-transfer[`++transfer(self, recipient, amount)++`] -* xref:#ERC20Component-transfer_from[`++transfer_from(self, sender, recipient, amount)++`] -* xref:#ERC20Component-approve[`++approve(self, spender, amount)++`] - -.ERC4626MetadataImpl -* xref:#ERC4626Component-name[`++name(self)++`] -* xref:#ERC4626Component-symbol[`++symbol(self)++`] -* xref:#ERC4626Component-decimals[`++decimals(self)++`] - --- - -[.contract-index] -.Internal functions --- -.InternalImpl -* xref:#ERC4626Component-initializer[`++initializer(self, asset_address)++`] -* xref:#ERC4626Component-_deposit[`++_deposit(self, caller, receiver, assets, shares)++`] -* xref:#ERC4626Component-_withdraw[`++_withdraw(self, caller, receiver, owner, assets, shares)++`] -* xref:#ERC4626Component-_convert_to_shares[`++_convert_to_shares(self, assets, rounding)++`] -* xref:#ERC4626Component-_convert_to_assets[`++_convert_to_assets(self, shares, rounding)++`] --- - -[#ERC4626Component-Immutable-Config] -==== Immutable Config - -[.contract-item] -[[ERC4626Component-IC-UNDERLYING_DECIMALS]] -==== `[.contract-item-name]#++UNDERLYING_DECIMALS:++#++ u128++` [.item-kind]#constant# - -Should match the underlying asset's decimals. -The default value is `18`. - -[.contract-item] -[[ERC4626Component-IC-DECIMALS_OFFSET]] -==== `[.contract-item-name]#++DECIMALS_OFFSET:++#++ u128++` [.item-kind]#constant# - -Corresponds to the representational offset between `UNDERLYING_DECIMALS` and the vault decimals. -The greater the offset, the more expensive it is for attackers to execute an inflation attack. - -[.contract-item] -[[ERC4626Component-IC-validate]] -==== `[.contract-item-name]#++validate++#++()++` [.item-kind]#internal# - -Validates the given implementation of the contract's configuration. - -Requirements: - -- `UNDERLYING_DECIMALS` + `DECIMALS_OFFSET` cannot exceed 255 (max u8). - -NOTE: This function is called by the contract's initializer. - -[#ERC4626Component-Hooks] -==== Hooks - -Hooks are functions which implementations can extend the functionality of the component source code. -Every contract using ERC4626Component is expected to provide an implementation of the ERC4626HooksTrait. -For basic token contracts, an empty implementation with no logic must be provided. - -TIP: You can use `openzeppelin_token::erc20::extensions::erc4626::ERC4626EmptyHooks` which is already available as part of the library for this purpose. - -==== FeeConfigTrait - -:asset-fees-mock: https://github.com/OpenZeppelin/cairo-contracts/tree/main/packages/test_common/src/mocks/erc4626.cairo#L253[ERC4626AssetsFeesMock] -:share-fees-mock: https://github.com/OpenZeppelin/cairo-contracts/tree/main/packages/test_common/src/mocks/erc4626.cairo#L426[ERC4626SharesFeesMock] - -The logic for calculating entry and exit fees is expected to be defined at the contract level. -Defaults to no entry or exit fees. - -NOTE: The FeeConfigTrait hooks directly into the preview methods of the ERC4626 component. -The preview methods must return as close to the exact amount of shares or assets as possible -if the actual (previewed) operation occurred in the same transaction (according to {eip4626} spec). -All operations use their corresponding preview method as the value of assets or shares being -moved to or from the user. -The fees calculated in FeeConfigTrait are used to adjust the final asset and share amounts used -in both the preview and the actual operations. - -NOTE: To transfer fees, this trait needs to be coordinated with `ERC4626Component::ERC4626Hooks`. - -See implementation examples: - -- Contract charging fees in assets: {asset-fees-mock} -- Contract charging fees in shares: {share-fees-mock} - -[.contract-item] -[[ERC4626Component-calculate_deposit_fee]] -==== `[.contract-item-name]#++calculate_deposit_fee++#++(self: @ContractState, assets: u256, shares: u256) → Option++` [.item-kind]#hook# - -Calculates the entry fee for a deposit during <>. The returned fee affects -the final asset and share amounts. Fees are not transferred automatically and must be handled -in the <> hook: asset fees should be transferred from the vault's management to -the fee recipient, while share fees should be minted to the fee recipient. - -[.contract-item] -[[ERC4626Component-calculate_mint_fee]] -==== `[.contract-item-name]#++calculate_mint_fee++#++(self: @ContractState, assets: u256, shares: u256) → Option++` [.item-kind]#hook# - -Calculates the entry fee for a mint during <>. The returned fee affects -the final asset and share amounts. Fees are not transferred automatically and must be handled -in the <> hook: asset fees should be transferred from the vault's management to -the fee recipient, while share fees should be minted to the fee recipient. - -[.contract-item] -[[ERC4626Component-calculate_withdraw_fee]] -==== `[.contract-item-name]#++calculate_withdraw_fee++#++(self: @ContractState, assets: u256, shares: u256) → Option++` [.item-kind]#hook# - -Calculates the exit fee for a withdraw during <>. The returned fee affects -the final asset and share amounts. Fees are not transferred automatically and must be handled -in the <> hook: asset fees should be transferred from the vault's management to -the fee recipient, while share fees should be transferred from the owner to the fee recipient. - -[.contract-item] -[[ERC4626Component-calculate_redeem_fee]] -==== `[.contract-item-name]#++calculate_redeem_fee++#++(self: @ContractState, assets: u256, shares: u256) → Option++` [.item-kind]#hook# - -Calculates the exit fee for a redeem during <>. The returned fee affects -the final asset and share amounts. Fees are not transferred automatically and must be handled -in the <> hook: asset fees should be transferred from the vault's management to -the fee recipient, while share fees should be transferred from the owner to the fee recipient. - -==== LimitConfigTrait - -Sets limits to the target exchange type and is expected to be defined at the contract -level. These limits correspond directly to the `max_` i.e. `deposit_limit` -> `max_deposit`. - -NOTE: The {eip4626} spec states that the `max_` methods must take into account all -global and user-specific limits. -If an operation is disabled (even temporarily), the corresponding limit MUST be `0` -and MUST NOT panic. - -[.contract-item] -[[ERC4626Component-deposit_limit]] -==== `[.contract-item-name]#++deposit_limit++#++(ref self: ContractState, receiver: ContractAddress) → Option++` [.item-kind]#hook# - -The max deposit allowed. - -Defaults (`Option::None`) to 2 ** 256 - 1. - -[.contract-item] -[[ERC4626Component-mint_limit]] -==== `[.contract-item-name]#++mint_limit++#++(ref self: ContractState, receiver: ContractAddress) → Option++` [.item-kind]#hook# - -The max mint allowed. - -Defaults (`Option::None`) to 2 ** 256 - 1. - -[.contract-item] -[[ERC4626Component-withdraw_limit]] -==== `[.contract-item-name]#++withdraw_limit++#++(ref self: ContractState, owner: ContractAddress) → Option++` [.item-kind]#hook# - -The max withdraw allowed. - -Defaults (`Option::None`) to the full asset balance of `owner` converted from shares. - -[.contract-item] -[[ERC4626Component-redeem_limit]] -==== `[.contract-item-name]#++redeem_limit++#++(ref self: ContractState, owner: ContractAddress) → Option++` [.item-kind]#hook# - -The max redeem allowed. - -Defaults (`Option::None`) to the full asset balance of `owner`. - -==== ERC4626HooksTrait - -Allows contracts to hook logic into deposit and withdraw transactions. -This is where contracts can transfer fees. - -NOTE: ERC4626 preview methods must be inclusive of any entry or exit fees. -Fees are calculated using <> methods and automatically adjust the final -asset and share amounts. Fee transfers are handled in `ERC4626HooksTrait` methods. - -CAUTION: 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 {asset-fees-mock} and {share-fees-mock} examples. - -[.contract-item] -[[ERC4626Component-before_deposit]] -==== `[.contract-item-name]#++before_deposit++#++(ref self: ContractState, caller: ContractAddress, receiver: ContractAddress, assets: u256, shares: u256, fee: Option)++` [.item-kind]#hook# - -Hooks into xref:#ERC4626Component-_deposit[_deposit]. - -Executes logic before transferring assets and minting shares. -The fee is calculated via <>. Assets and shares -represent the actual amounts the user will spend and receive, respectively. -Asset fees are included in assets; share fees are excluded from shares. - -[.contract-item] -[[ERC4626Component-after_deposit]] -==== `[.contract-item-name]#++after_deposit++#++(ref self: ContractState, caller: ContractAddress, receiver: ContractAddress, assets: u256, shares: u256, fee: Option)++` [.item-kind]#hook# - -Hooks into xref:#ERC4626Component-_deposit[_deposit]. - -Executes logic after transferring assets and minting shares. -The fee is calculated via <>. Assets and shares -represent the actual amounts the user will spend and receive, respectively. -Asset fees are included in assets; share fees are excluded from shares. - -[.contract-item] -[[ERC4626Component-before_withdraw]] -==== `[.contract-item-name]#++before_withdraw++#++(ref self: ContractState, caller: ContractAddress, receiver: ContractAddress, owner: ContractAddress, assets: u256, shares: u256, fee: Option)++` [.item-kind]#hook# - -Hooks into xref:#ERC4626Component-_withdraw[_withdraw]. - -Executes logic before burning shares and transferring assets. -The fee is calculated via <>. Assets and shares -represent the actual amounts the user will receive and spend, respectively. -Asset fees are excluded from assets; share fees are included in shares. - -[.contract-item] -[[ERC4626Component-after_withdraw]] -==== `[.contract-item-name]#++after_withdraw++#++(ref self: ContractState, caller: ContractAddress, receiver: ContractAddress, owner: ContractAddress, assets: u256, shares: u256, fee: Option)++` [.item-kind]#hook# - -Hooks into xref:#ERC4626Component-_withdraw[_withdraw]. - -Executes logic after burning shares and transferring assets. -The fee is calculated via <>. Assets and shares -represent the actual amounts the user will receive and spend, respectively. -Asset fees are excluded from assets; share fees are included in shares. - -==== AssetsManagementTrait - -Defines how the ERC4626 vault manages its underlying assets. This trait provides the core asset -management functionality for the vault, abstracting the actual storage and transfer mechanisms. -It enables two primary implementation patterns: - -1. **Self-managed assets**: The vault contract holds assets directly on its own address. - This is the default behavior provided by `ERC4626SelfAssetsManagement` implementation. - -2. **External vault**: Assets are managed by an external contract, allowing - for more complex asset management strategies. The exact implementation is expected to be - defined by the contract implementing the ERC4626 component. - -The trait methods are called during deposit, withdrawal, and total assets calculations, -ensuring that the vault's share pricing remains accurate regardless of the underlying -asset management strategy. - -CAUTION: Implementations must ensure that `get_total_assets` returns the actual amount -of assets that can be withdrawn by users. Inaccurate reporting can lead to incorrect -share valuations and potential economic attacks. - -:ERC4626SelfAssetsManagement: https://github.com/OpenZeppelin/cairo-contracts/tree/main/packages/token/src/erc20/extensions/erc4626/erc4626.cairo#L760[ERC4626SelfAssetsManagement] -:ERC4626ExternalAssetsManagement: https://github.com/OpenZeppelin/cairo-contracts/tree/main/packages/test_common/src/mocks/erc4626.cairo#L92[ERC4626ExternalAssetsManagement] - -See implementation examples: - -- Self-managed vault: {ERC4626SelfAssetsManagement}. -- External vault: {ERC4626ExternalAssetsManagement}. - -[.contract-item] -[[ERC4626Component-get_total_assets]] -==== `[.contract-item-name]#++get_total_assets++#++(self: @ContractState) → u256++` [.item-kind]#hook# - -Returns the total amount of underlying assets under the vault's management. -Used for share price calculations and determining the vault's total value. - -This method should return the actual amount of assets that the vault controls -and that can be used to satisfy withdrawal requests. For self-managed vaults, -this is typically the vault contract's token balance. For external vaults, -this should include any assets deposited in external protocols, minus any -that are locked or unredeemable. - -The accuracy of this method is critical for proper vault operation: -- Overreporting can lead to share dilution and user losses. -- Underreporting can lead to share inflation and potential economic attacks. - -[.contract-item] -[[ERC4626Component-transfer_assets_in]] -==== `[.contract-item-name]#++transfer_assets_in++#++(ref self: ContractState, from: ContractAddress, assets: u256)++` [.item-kind]#hook# - -Transfers assets from an external address into the vault's management. -Called during `deposit` and `mint` operations. - -This method should handle the actual transfer of underlying assets from the `from` -address into the vault's control. For self-managed vaults, this typically means -transferring tokens to the vault contract's address. For external vaults, this -might involve transferring into an external contract. - -Requirements: - -- MUST transfer exactly `assets` amount of the underlying token. -- SHOULD revert if the transfer fails or insufficient allowance/balance. - -[.contract-item] -[[ERC4626Component-transfer_assets_out]] -==== `[.contract-item-name]#++transfer_assets_out++#++(ref self: ContractState, to: ContractAddress, assets: u256)++` [.item-kind]#hook# - -Transfers assets from the vault's management to an external address. -Called during withdraw and redeem operations. - -This method should handle the actual transfer of underlying assets from the vault's -control to the `to` address. For self-managed vaults, this typically means -transferring tokens from the vault contract's address. For external vaults, this -might involve withdrawing from an external contract first. - -Requirements: - -- MUST transfer exactly `assets` amount of the underlying token. -- SHOULD revert if insufficient assets are available or transfer fails. - -==== Embeddable functions - -[.contract-item] -[[ERC4626Component-asset]] -==== `[.contract-item-name]#++asset++#++(self: @ContractState) → ContractAddress++` [.item-kind]#external# - -Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. - -[.contract-item] -[[ERC4626Component-total_assets]] -==== `[.contract-item-name]#++total_assets++#++(self: @ContractState) → u256++` [.item-kind]#external# - -Returns the total amount of the underlying asset that is “managed” by Vault. - -[.contract-item] -[[ERC4626Component-convert_to_shares]] -==== `[.contract-item-name]#++convert_to_shares++#++(self: @ContractState, assets: u256) → u256++` [.item-kind]#external# - -Returns the amount of shares that the Vault would exchange for the amount of assets provided irrespective of slippage or fees. - -NOTE: As per the {eip4626} spec, this may panic _only_ if there's an overflow from an unreasonably large input. - -[.contract-item] -[[ERC4626Component-convert_to_assets]] -==== `[.contract-item-name]#++convert_to_assets++#++(self: @ContractState, shares: u256) → u256++` [.item-kind]#external# - -Returns the amount of assets that the Vault would exchange for the amount of shares provided irrespective of slippage or fees. - -NOTE: As per the {eip4626} spec, this may panic _only_ if there's an overflow from an unreasonably large input. - -[.contract-item] -[[ERC4626Component-max_deposit]] -==== `[.contract-item-name]#++max_deposit++#++(self: @ContractState, receiver: ContractAddress) → u256++` [.item-kind]#external# - -Returns the maximum amount of the underlying asset that can be deposited into the Vault for the `receiver`, through a <> call. - -The default max deposit value is 2 ** 256 - 1. - -This can be changed in the implementing contract by defining custom logic in -<>. - -[.contract-item] -[[ERC4626Component-preview_deposit]] -==== `[.contract-item-name]#++preview_deposit++#++(self: @ContractState, assets: u256) → u256++` [.item-kind]#external# - -Allows an on-chain or off-chain user to simulate the effects of their deposit at the -current block, given current on-chain conditions. - -The default deposit preview value is the full amount of shares. -This can be changed to account for fees, for example, in the implementing contract by -defining custom logic in <>. - -NOTE: This method must be inclusive of entry fees to be compliant with the {eip4626} spec. - -[.contract-item] -[[ERC4626Component-deposit]] -==== `[.contract-item-name]#++deposit++#++(ref self: ContractState, assets: u256, receiver: ContractAddress) → u256++` [.item-kind]#external# - -Mints Vault shares to `receiver` by depositing exactly `assets` of underlying tokens. -Returns the amount of newly-minted shares. - -Requirements: - -- `assets` is less than or equal to the max deposit amount for `receiver`. - -Emits a <> event. - -[.contract-item] -[[ERC4626Component-max_mint]] -==== `[.contract-item-name]#++max_mint++#++(self: @ContractState, receiver: ContractAddress) → u256++` [.item-kind]#external# - -Returns the maximum amount of the Vault shares that can be minted for `receiver` through -a <> call. - -The default max mint value is 2 ** 256 - 1. - -This can be changed in the implementing contract by defining custom logic in <>. - -[.contract-item] -[[ERC4626Component-preview_mint]] -==== `[.contract-item-name]#++preview_mint++#++(self: @ContractState, shares: u256) → u256++` [.item-kind]#external# - -Allows an on-chain or off-chain user to simulate the effects of their mint at the -current block, given current on-chain conditions. - -The default mint preview value is the full amount of assets. -This can be changed to account for fees, for example, in the implementing contract by -defining custom logic in <>. - -NOTE: This method must be inclusive of entry fees to be compliant with the {eip4626} spec. - -[.contract-item] -[[ERC4626Component-mint]] -==== `[.contract-item-name]#++mint++#++(self: @ContractState, shares: u256, receiver: ContractAddress) → u256++` [.item-kind]#external# - -Mints exactly Vault `shares` to `receiver` by depositing amount of underlying tokens. -Returns the amount deposited assets. - -Requirements: - -- `shares` is less than or equal to the max shares amount for `receiver`. - -Emits a <> event. - -[.contract-item] -[[ERC4626Component-max_withdraw]] -==== `[.contract-item-name]#++max_withdraw++#++(self: @ContractState, owner: ContractAddress) → u256++` [.item-kind]#external# - -Returns the maximum amount of the underlying asset that can be withdrawn from the owner -balance in the Vault, through a <> call. - -The default max withdraw value is the full balance of assets for `owner` (converted from shares). -This can be changed in the implementing contract by defining custom logic in <>. - -NOTE: With customized limits, the maximum withdraw amount will either be the custom limit itself -or ``owner``'s total asset balance, whichever value is less. - -[.contract-item] -[[ERC4626Component-preview_withdraw]] -==== `[.contract-item-name]#++preview_withdraw++#++(self: @ContractState, assets: u256) → u256++` [.item-kind]#external# - -Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the -current block, given current on-chain conditions. - -The default withdraw preview value is the full amount of shares. -This can be changed to account for fees, for example, in the implementing contract by defining custom logic in <>. - -NOTE: This method must be inclusive of exit fees to be compliant with the {eip4626} spec. - -[.contract-item] -[[ERC4626Component-withdraw]] -==== `[.contract-item-name]#++withdraw++#++(self: @ContractState, assets: u256, receiver: ContractAddress, owner: ContractAddress) → u256++` [.item-kind]#external# - -Burns shares from `owner` and sends exactly `assets` of underlying tokens to `receiver`. - -Requirements: - -- `assets` is less than or equal to the max withdraw amount of `owner`. - -Emits a <> event. - -[.contract-item] -[[ERC4626Component-max_redeem]] -==== `[.contract-item-name]#++max_redeem++#++(self: @ContractState, owner: ContractAddress) → u256++` [.item-kind]#external# - -Returns the maximum amount of Vault shares that can be redeemed from the owner balance -in the Vault, through a <> call. - -The default max redeem value is the full balance of assets for `owner`. -This can be changed in the implementing contract by defining custom logic in <>. - -NOTE: With customized limits, the maximum redeem amount will either be the custom limit itself -or ``owner``'s total asset balance, whichever value is less. - -[.contract-item] -[[ERC4626Component-preview_redeem]] -==== `[.contract-item-name]#++preview_redeem++#++(self: @ContractState, shares: u256) → u256++` [.item-kind]#external# - -Allows an on-chain or off-chain user to simulate the effects of their redeemption at the -current block, given current on-chain conditions. - -The default redeem preview value is the full amount of assets. -This can be changed to account for fees, for example, in the implementing contract by defining custom logic in <>. - -NOTE: This method must be inclusive of exit fees to be compliant with the {eip4626} spec. - -[.contract-item] -[[ERC4626Component-redeem]] -==== `[.contract-item-name]#++redeem++#++(self: @ContractState, shares: u256, receiver: ContractAddress, owner: ContractAddress) → u256++` [.item-kind]#external# - -Burns exactly `shares` from `owner` and sends assets of underlying tokens to `receiver`. - -Requirements: - -- `shares` is less than or equal to the max redeem amount of `owner`. - -Emits a <> event. - -[.contract-item] -[[ERC4626Component-name]] -==== `[.contract-item-name]#++name++#++(self: @ContractState) → ByteArray++` [.item-kind]#external# - -Returns the name of the token. - -[.contract-item] -[[ERC4626Component-symbol]] -==== `[.contract-item-name]#++symbol++#++(self: @ContractState) → ByteArray++` [.item-kind]#external# - -Returns the ticker symbol of the token, usually a shorter version of the name. - -[.contract-item] -[[ERC4626Component-decimals]] -==== `[.contract-item-name]#++decimals++#++(self: @ContractState) → u8++` [.item-kind]#external# - -Returns the cumulative number of decimals which includes both `UNDERLYING_DECIMALS` and `OFFSET_DECIMALS`. -Both of which must be defined in the <> inside the implementing contract. - -==== Internal functions - -[.contract-item] -[[ERC4626Component-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, asset_address: ContractAddress)++` [.item-kind]#internal# - -Validates the <> constants and sets the `asset_address` to the vault. -This should be set in the contract's constructor. - -Requirements: - -- `asset_address` cannot be the zero address. - -[.contract-item] -[[ERC4626Component-_deposit]] -==== `[.contract-item-name]#++_deposit++#++(ref self: ContractState, caller: ContractAddress, receiver: ContractAddress, assets: u256, shares: u256)++` [.item-kind]#internal# - -Internal logic for <> and <>. - -Transfers `assets` from `caller` to the Vault contract then mints `shares` to -`receiver`. -Fees can be transferred in the `ERC4626Hooks::after_deposit` hook which is executed -after assets are transferred and shares are minted. - -Requirements: - -- <> must return true. - -Emits two <> events (`ERC20::mint` and `ERC20::transfer_from`). - -Emits a <> event. - -[.contract-item] -[[ERC4626Component-_withdraw]] -==== `[.contract-item-name]#++_withdraw++#++(ref self: ContractState, caller: ContractAddress, receiver: ContractAddress, owner: ContractAddress, assets: u256, shares: u256)++` [.item-kind]#internal# - -Internal logic for <> and <>. - -Burns `shares` from `owner` and then transfers `assets` to `receiver`. -Fees can be transferred in the `ERC4626Hooks::before_withdraw` hook which is executed -before shares are burned and assets are transferred. - -Requirements: - -- <> must return true. - -Emits two <> events (`ERC20::burn` and `ERC20::transfer`). - -Emits a <> event. - -[.contract-item] -[[ERC4626Component-_convert_to_shares]] -==== `[.contract-item-name]#++_convert_to_shares++#++(self: @ContractState, assets: u256, rounding: Rounding) -> u256++` [.item-kind]#internal# - -Internal conversion function (from assets to shares) with support for `rounding` direction. - -[.contract-item] -[[ERC4626Component-_convert_to_assets]] -==== `[.contract-item-name]#++_convert_to_assets++#++(self: @ContractState, shares: u256, rounding: Rounding) -> u256++` [.item-kind]#internal# - -Internal conversion function (from shares to assets) with support for `rounding` direction. - -== Presets - -[.contract] -[[ERC20Upgradeable]] -=== `++ERC20Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/presets/src/erc20.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_presets::ERC20Upgradeable; -``` - -Upgradeable ERC20 contract leveraging xref:#ERC20Component[ERC20Component] with a fixed-supply mechanism for token distribution. - -include::../utils/_class_hashes.adoc[] - -[.contract-index] -.{presets-page} --- -{ERC20Upgradeable-class-hash} --- - -[.contract-index] -.Constructor --- -* xref:#ERC20Upgradeable-constructor[`++constructor(self, name, symbol, fixed_supply, recipient, owner)++`] --- - -[.contract-index] -.Embedded Implementations --- -.ERC20MixinImpl - -* xref:#ERC20Component-Embeddable-Mixin-Impl[`++ERC20MixinImpl++`] - -.OwnableMixinImpl - -* xref:/api/access.adoc#OwnableComponent-Mixin-Impl[`++OwnableMixinImpl++`] --- - -[.contract-index] -.External Functions --- -* xref:#ERC20Upgradeable-upgrade[`++upgrade(self, new_class_hash)++`] --- - -[#ERC20Upgradeable-constructor-section] -==== Constructor - -[.contract-item] -[[ERC20Upgradeable-constructor]] -==== `[.contract-item-name]#++constructor++#++(ref self: ContractState, name: ByteArray, symbol: ByteArray, fixed_supply: u256, recipient: ContractAddress, owner: ContractAddress)++` [.item-kind]#constructor# - -Sets the `name` and `symbol` and mints `fixed_supply` tokens to `recipient`. -Assigns `owner` as the contract owner with permissions to upgrade. - -[#ERC20Upgradeable-external-functions] -==== External functions - -[.contract-item] -[[ERC20Upgradeable-upgrade]] -==== `[.contract-item-name]#++upgrade++#++(ref self: ContractState, new_class_hash: ClassHash)++` [.item-kind]#external# - -Upgrades the contract to a new implementation given by `new_class_hash`. - -Requirements: - -- The caller is the contract owner. -- `new_class_hash` cannot be zero. diff --git a/docs/modules/ROOT/pages/api/erc6909.adoc b/docs/modules/ROOT/pages/api/erc6909.adoc deleted file mode 100644 index 11af2c3fd..000000000 --- a/docs/modules/ROOT/pages/api/erc6909.adoc +++ /dev/null @@ -1,805 +0,0 @@ -:github-icon: pass:[] -:eip6909: https://eips.ethereum.org/EIPS/eip-6909[EIP6909] -:inner-src5: xref:api/introspection.adoc#ISRC5[SRC5 ID] - -= ERC6909 - -include::../utils/_common.adoc[] - -This module provides interfaces, presets, and utilities related to ERC6909 contracts. - -TIP: For an overview of ERC6909, read our xref:erc6909.adoc[ERC6909 guide]. - -== Interfaces - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_token` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[IERC6909]] -=== `++IERC6909++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1-alpha.3/packages/interfaces/src/token/erc6909.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc6909::IERC6909; -``` - -Interface of the IERC6909 minimal multi-token standard as defined in {eip6909}. - -[.contract-index] -.{inner-src5} --- -0xd5aa138060489fd9c4592f77a16011cc5615ce4d292ee1f7873ae65c43b6bb --- - -[.contract-index] -.Functions --- -* xref:#IERC6909-balance_of[`++balance_of(owner, id)++`] -* xref:#IERC6909-allowance[`++allowance(owner, spender, id)++`] -* xref:#IERC6909-is_operator[`++is_operator(owner, spender)++`] -* xref:#IERC6909-transfer[`++transfer(receiver, id, amount)++`] -* xref:#IERC6909-transfer_from[`++transfer_from(sender, receiver, id, amount)++`] -* xref:#IERC6909-approve[`++approve(spender, id, amount)++`] -* xref:#IERC6909-set_operator[`++set_operator(spender, approved)++`] --- - -[.contract-index] -.Events --- -* xref:#IERC6909-Transfer[`++Transfer(caller, sender, receiver, id, amount)++`] -* xref:#IERC6909-Approval[`++Approval(owner, spender, id, amount)++`] -* xref:#IERC6909-OperatorSet[`++OperatorSet(owner, spender, approved)++`] --- - -==== Functions - -[.contract-item] -[[IERC6909-balance_of]] -==== `[.contract-item-name]#++balance_of++#++(owner: ContractAddress, id: u256) → u256++` [.item-kind]#external# - -Returns the amount of `id` tokens owned by `owner`. - -[.contract-item] -[[IERC6909-allowance]] -==== `[.contract-item-name]#++allowance++#++(owner: ContractAddress, spender: ContractAddress, id: u256) → u256++` [.item-kind]#external# - -Returns the remaining number of `id` tokens that `spender` is allowed to spend on behalf of `owner` -through <>. - -[.contract-item] -[[IERC6909-is_operator]] -==== `[.contract-item-name]#++is_operator++#++(owner: ContractAddress, spender: ContractAddress) → bool++` [.item-kind]#external# - -Returns `true` if `spender` is approved by `owner` as an operator over all token IDs. - -[.contract-item] -[[IERC6909-transfer]] -==== `[.contract-item-name]#++transfer++#++(receiver: ContractAddress, id: u256, amount: u256) → bool++` [.item-kind]#external# - -Transfers `amount` of token `id` from the caller to `receiver`. - -Emits a <> event. - -[.contract-item] -[[IERC6909-transfer_from]] -==== `[.contract-item-name]#++transfer_from++#++(sender: ContractAddress, receiver: ContractAddress, id: u256, amount: u256) → bool++` [.item-kind]#external# - -Transfers `amount` of token `id` from `sender` to `receiver`, deducting from the caller's allowance if required. - -Emits a <> event. - -[.contract-item] -[[IERC6909-approve]] -==== `[.contract-item-name]#++approve++#++(spender: ContractAddress, id: u256, amount: u256) → bool++` [.item-kind]#external# - -Sets `amount` as the allowance of `spender` over the caller's tokens of ID `id`. - -Emits an <> event. - -[.contract-item] -[[IERC6909-set_operator]] -==== `[.contract-item-name]#++set_operator++#++(spender: ContractAddress, approved: bool) → bool++` [.item-kind]#external# - -Sets or unsets `spender` as an operator for the caller, granting or revoking permission to transfer -any of the caller's token IDs. - -Emits an <> event. - -==== Events - -[.contract-item] -[[IERC6909-Transfer]] -==== `[.contract-item-name]#++Transfer++#++(caller: ContractAddress, sender: ContractAddress, receiver: ContractAddress, id: u256, amount: u256)++` [.item-kind]#event# - -Emitted when `amount` tokens of ID `id` are moved from `sender` to `receiver` by `caller`. - -[.contract-item] -[[IERC6909-Approval]] -==== `[.contract-item-name]#++Approval++#++(owner: ContractAddress, spender: ContractAddress, id: u256, amount: u256)++` [.item-kind]#event# - -Emitted when the allowance of `spender` for `owner` is set to `amount` for token `id`. - -[.contract-item] -[[IERC6909-OperatorSet]] -==== `[.contract-item-name]#++OperatorSet++#++(owner: ContractAddress, spender: ContractAddress, approved: bool)++` [.item-kind]#event# - -Emitted when `owner` enables or disables `spender` as an operator over all token IDs. - -[.contract] -[[IERC6909ContentUri]] -=== `++IERC6909ContentUri++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1-alpha.3/packages/interfaces/src/token/erc6909.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc6909::IERC6909ContentUri; -``` - -Interface for contract-level and token-level URIs in {eip6909}. - -[.contract-index] -.{inner-src5} --- -0x356efd8b40a01c1525c7d0ecafbe3b82a47df564fdd496727effe6336526f05 --- - -[.contract-index] -.Functions --- -* xref:#IERC6909ContentUri-contract_uri[`++contract_uri()++`] -* xref:#IERC6909ContentUri-token_uri[`++token_uri(id)++`] --- - -==== Functions - -[.contract-item] -[[IERC6909ContentUri-contract_uri]] -==== `[.contract-item-name]#++contract_uri++#++() → ByteArray++` [.item-kind]#external# - -Returns the contract-level URI. - -[.contract-item] -[[IERC6909ContentUri-token_uri]] -==== `[.contract-item-name]#++token_uri++#++(id: u256) → ByteArray++` [.item-kind]#external# - -Returns the token-level URI for token `id`. - -[.contract] -[[IERC6909Metadata]] -=== `++IERC6909Metadata++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1-alpha.3/packages/interfaces/src/token/erc6909.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc6909::IERC6909Metadata; -``` - -Interface for per-token metadata in {eip6909}. - -[.contract-index] -.{inner-src5} --- -0x19aa0b778d120d5294054319458ee8886514766411c50dceddd9463712d6011 --- - -[.contract-index] -.Functions --- -* xref:#IERC6909Metadata-name[`++name(id)++`] -* xref:#IERC6909Metadata-symbol[`++symbol(id)++`] -* xref:#IERC6909Metadata-decimals[`++decimals(id)++`] --- - -==== Functions - -[.contract-item] -[[IERC6909Metadata-name]] -==== `[.contract-item-name]#++name++#++(id: u256) → ByteArray++` [.item-kind]#external# - -Returns the name of token `id`. - -[.contract-item] -[[IERC6909Metadata-symbol]] -==== `[.contract-item-name]#++symbol++#++(id: u256) → ByteArray++` [.item-kind]#external# - -Returns the symbol of token `id`. - -[.contract-item] -[[IERC6909Metadata-decimals]] -==== `[.contract-item-name]#++decimals++#++(id: u256) → u8++` [.item-kind]#external# - -Returns the number of decimals of token `id`. - -[.contract] -[[IERC6909TokenSupply]] -=== `++IERC6909TokenSupply++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1-alpha.3/packages/interfaces/src/token/erc6909.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc6909::IERC6909TokenSupply; -``` - -Interface for querying per-token total supply in {eip6909}. - -[.contract-index] -.{inner-src5} --- -0x3a632c15cb93b574eb9166de70521abbeab5c2eb4fdab9930729bba8658c41 --- - -[.contract-index] -.Functions --- -* xref:#IERC6909TokenSupply-total_supply[`++total_supply(id)++`] --- - -==== Functions - -[.contract-item] -[[IERC6909TokenSupply-total_supply]] -==== `[.contract-item-name]#++total_supply++#++(id: u256) → u256++` [.item-kind]#external# - -Returns the total supply of token `id`. - -== Core - -[.contract] -[[ERC6909Component]] -=== `++ERC6909Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1-alpha.3/packages/token/src/erc6909/erc6909.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_token::erc6909::ERC6909Component; -``` - -ERC6909 component implementing <>. - -NOTE: {src5-component-required-note} - -NOTE: See xref:#ERC6909Component-Hooks[Hooks] to understand how hooks are used. - -[.contract-index] -.Hooks --- -[.sub-index#ERC6909Component-ERC6909HooksTrait] -.ERC6909HooksTrait -* xref:#ERC6909Component-before_update[`++before_update(self, from, recipient, id, amount)++`] -* xref:#ERC6909Component-after_update[`++after_update(self, from, recipient, id, amount)++`] --- - -[.contract-index#ERC6909Component-Embeddable-Mixin-Impl] -.{mixin-impls} --- -.ERC6909Impl -* xref:#ERC6909Component-Embeddable-Impls-ERC6909Impl[`++ERC6909Impl++`] -* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls-SRC5Impl[`++SRC5Impl++`] --- - -[.contract-index#ERC6909Component-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#ERC6909Component-Embeddable-Impls-ERC6909Impl] -.ERC6909Impl -* xref:#ERC6909Component-balance_of[`++balance_of(self, owner, id)++`] -* xref:#ERC6909Component-allowance[`++allowance(self, owner, spender, id)++`] -* xref:#ERC6909Component-is_operator[`++is_operator(self, owner, spender)++`] -* xref:#ERC6909Component-transfer[`++transfer(self, receiver, id, amount)++`] -* xref:#ERC6909Component-transfer_from[`++transfer_from(self, sender, receiver, id, amount)++`] -* xref:#ERC6909Component-approve[`++approve(self, spender, id, amount)++`] -* xref:#ERC6909Component-set_operator[`++set_operator(self, spender, approved)++`] --- - -[.contract-index] -.Internal functions --- -.InternalImpl -* xref:#ERC6909Component-initializer[`++initializer(self)++`] -* xref:#ERC6909Component-mint[`++mint(self, receiver, id, amount)++`] -* xref:#ERC6909Component-burn[`++burn(self, account, id, amount)++`] -* xref:#ERC6909Component-update[`++update(self, sender, receiver, id, amount)++`] -* xref:#ERC6909Component-_set_operator[`++_set_operator(self, owner, spender, approved)++`] -* xref:#ERC6909Component-_spend_allowance[`++_spend_allowance(self, owner, spender, id, amount)++`] -* xref:#ERC6909Component-_approve[`++_approve(self, owner, spender, id, amount)++`] -* xref:#ERC6909Component-_transfer[`++_transfer(self, sender, receiver, id, amount)++`] --- - -[.contract-index] -.Events --- -.IERC6909 -* xref:#ERC6909Component-Transfer[`++Transfer(caller, sender, receiver, id, amount)++`] -* xref:#ERC6909Component-Approval[`++Approval(owner, spender, id, amount)++`] -* xref:#ERC6909Component-OperatorSet[`++OperatorSet(owner, spender, approved)++`] --- - -[#ERC6909Component-Hooks] -==== Hooks - -Hooks are functions which implementations can use to extend the functionality of the component source code. -Every contract using `ERC6909Component` is expected to provide an implementation of the `ERC6909HooksTrait`. -For basic token contracts, an empty implementation with no logic must be provided. - -TIP: You can use `openzeppelin_token::erc6909::ERC6909HooksEmptyImpl` which is already available as part of -the library for this purpose. - -[.contract-item] -[[ERC6909Component-before_update]] -==== `[.contract-item-name]#++before_update++#++(ref self: ContractState, from: ContractAddress, recipient: ContractAddress, id: u256, amount: u256)++` [.item-kind]#hook# - -Function executed at the beginning of the xref:#ERC6909Component-update[update] function prior to any other logic. - -[.contract-item] -[[ERC6909Component-after_update]] -==== `[.contract-item-name]#++after_update++#++(ref self: ContractState, from: ContractAddress, recipient: ContractAddress, id: u256, amount: u256)++` [.item-kind]#hook# - -Function executed at the end of the xref:#ERC6909Component-update[update] function. - -==== Embeddable functions - -[.contract-item] -[[ERC6909Component-balance_of]] -==== `[.contract-item-name]#++balance_of++#++(self: @ContractState, owner: ContractAddress, id: u256) → u256++` [.item-kind]#external# - -Returns the amount of `id` tokens owned by `owner`. - -[.contract-item] -[[ERC6909Component-allowance]] -==== `[.contract-item-name]#++allowance++#++(self: @ContractState, owner: ContractAddress, spender: ContractAddress, id: u256) → u256++` [.item-kind]#external# - -Returns the remaining number of `id` tokens that `spender` is allowed to spend on behalf of `owner` -through <>. - -[.contract-item] -[[ERC6909Component-is_operator]] -==== `[.contract-item-name]#++is_operator++#++(self: @ContractState, owner: ContractAddress, spender: ContractAddress) → bool++` [.item-kind]#external# - -Returns `true` if `spender` is approved by `owner` as an operator over all token IDs. - -[.contract-item] -[[ERC6909Component-transfer]] -==== `[.contract-item-name]#++transfer++#++(ref self: ContractState, receiver: ContractAddress, id: u256, amount: u256) → bool++` [.item-kind]#external# - -Transfers `amount` of token `id` from the caller to `receiver`. - -Requirements: - -- `receiver` is not the zero address. - -Emits a <> event. - -[.contract-item] -[[ERC6909Component-transfer_from]] -==== `[.contract-item-name]#++transfer_from++#++(ref self: ContractState, sender: ContractAddress, receiver: ContractAddress, id: u256, amount: u256) → bool++` [.item-kind]#external# - -Transfers `amount` of token `id` from `sender` to `receiver`, deducting from the caller's allowance -for `sender` and `id` if applicable. - -Requirements: - -- Caller is either `sender`, an operator for `sender`, or has sufficient allowance. -- `sender` is not the zero address. -- `receiver` is not the zero address. -- `sender` must have at least a balance of `amount` for token `id`. - -Emits a <> event. - -[.contract-item] -[[ERC6909Component-approve]] -==== `[.contract-item-name]#++approve++#++(ref self: ContractState, spender: ContractAddress, id: u256, amount: u256) → bool++` [.item-kind]#external# - -Sets `amount` as the allowance of `spender` over the caller's tokens of token `id`. - -Requirements: - -- `spender` is not the zero address. - -Emits an <> event. - -[.contract-item] -[[ERC6909Component-set_operator]] -==== `[.contract-item-name]#++set_operator++#++(ref self: ContractState, spender: ContractAddress, approved: bool) → bool++` [.item-kind]#external# - -Sets or unsets `spender` as an operator for the caller, granting or revoking permission to transfer -any of the caller's token IDs. - -Requirements: - -- `spender` is not the zero address. - -Emits an <> event. - -==== Internal functions - -[.contract-item] -[[ERC6909Component-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState)++` [.item-kind]#internal# - -Initializes the contract by registering the IERC6909 interface ID as supported through introspection. - -This should only be used inside the contract's constructor. - -[.contract-item] -[[ERC6909Component-mint]] -==== `[.contract-item-name]#++mint++#++(ref self: ContractState, receiver: ContractAddress, id: u256, amount: u256)++` [.item-kind]#internal# - -Mints `amount` tokens of token ID `id` to `receiver`. - -Requirements: - -- `receiver` is not the zero address. - -Emits a <> event with `sender` set to the zero address. - -[.contract-item] -[[ERC6909Component-burn]] -==== `[.contract-item-name]#++burn++#++(ref self: ContractState, account: ContractAddress, id: u256, amount: u256)++` [.item-kind]#internal# - -Destroys `amount` tokens of ID `id` from `account`. - -Requirements: - -- `account` is not the zero address. -- `account` must have at least a balance of `amount` for token `id`. - -Emits a <> event with `receiver` set to the zero address. - -[.contract-item] -[[ERC6909Component-update]] -==== `[.contract-item-name]#++update++#++(ref self: ContractState, sender: ContractAddress, receiver: ContractAddress, id: u256, amount: u256)++` [.item-kind]#internal# - -Transfers `amount` tokens of ID `id` from `sender` to `receiver`, or alternatively mints (or burns) -if `sender` (or `receiver`) is the zero address. - -This function can be extended using the xref:#ERC6909Component-ERC6909HooksTrait[ERC6909HooksTrait], to add -functionality before and/or after the transfer, mint, or burn. - -The implementation does not track per-token total supply; this logic is delegated to extensions. - -Emits a <> event. - -[.contract-item] -[[ERC6909Component-_set_operator]] -==== `[.contract-item-name]#++_set_operator++#++(ref self: ContractState, owner: ContractAddress, spender: ContractAddress, approved: bool)++` [.item-kind]#internal# - -Sets or unsets `spender` as an operator for `owner`. - -Emits an <> event. - -[.contract-item] -[[ERC6909Component-_spend_allowance]] -==== `[.contract-item-name]#++_spend_allowance++#++(ref self: ContractState, owner: ContractAddress, spender: ContractAddress, id: u256, amount: u256)++` [.item-kind]#internal# - -Updates `owner`'s allowance for `spender` and token `id` based on `amount` spent. - -Spenders that have been set as operators for `owner` are not subject to allowance restrictions. -If the current allowance is set to the maximum value, it is treated as infinite and is not reduced. - -Requirements: - -- If not infinite and not an operator, the allowance must be at least `amount`. - -[.contract-item] -[[ERC6909Component-_approve]] -==== `[.contract-item-name]#++_approve++#++(ref self: ContractState, owner: ContractAddress, spender: ContractAddress, id: u256, amount: u256)++` [.item-kind]#internal# - -Internal method that sets `amount` as the allowance of `spender` over `owner`'s tokens of token `id`. - -Requirements: - -- `owner` is not the zero address. -- `spender` is not the zero address. - -Emits an <> event. - -[.contract-item] -[[ERC6909Component-_transfer]] -==== `[.contract-item-name]#++_transfer++#++(ref self: ContractState, sender: ContractAddress, receiver: ContractAddress, id: u256, amount: u256)++` [.item-kind]#internal# - -Internal method that moves `amount` tokens of ID `id` from `sender` to `receiver`. - -Requirements: - -- `sender` is not the zero address. -- `receiver` is not the zero address. -- `sender` must have at least a balance of `amount` for token `id`. - -Emits a <> event. - -==== Events - -[.contract-item] -[[ERC6909Component-Transfer]] -==== `[.contract-item-name]#++Transfer++#++(caller: ContractAddress, sender: ContractAddress, receiver: ContractAddress, id: u256, amount: u256)++` [.item-kind]#event# - -See <>. - -[.contract-item] -[[ERC6909Component-Approval]] -==== `[.contract-item-name]#++Approval++#++(owner: ContractAddress, spender: ContractAddress, id: u256, amount: u256)++` [.item-kind]#event# - -See <>. - -[.contract-item] -[[ERC6909Component-OperatorSet]] -==== `[.contract-item-name]#++OperatorSet++#++(owner: ContractAddress, spender: ContractAddress, approved: bool)++` [.item-kind]#event# - -See <>. - -== Extensions - -[.contract] -[[ERC6909ContentURIComponent]] -=== `++ERC6909ContentURIComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1-alpha.3/packages/token/src/erc6909/extensions/erc6909_content_uri.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_token::erc6909::extensions::ERC6909ContentURIComponent; -``` - -ERC6909ContentURI component implementing <>. - -NOTE: Implementing xref:#ERC6909Component[ERC6909Component] is a requirement for this component to be implemented. - -[.contract-index#ERC6909ContentURIComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#ERC6909ContentURIComponent-Embeddable-Impls-ERC6909ContentURIImpl] -.ERC6909ContentURIImpl -* xref:#ERC6909ContentURIComponent-contract_uri[`++contract_uri(self)++`] -* xref:#ERC6909ContentURIComponent-token_uri[`++token_uri(self, id)++`] --- - -[.contract-index] -.Internal functions --- -.InternalImpl -* xref:#ERC6909ContentURIComponent-initializer[`++initializer(self)++`] -* xref:#ERC6909ContentURIComponent-set_contract_uri[`++set_contract_uri(self, contract_uri)++`] -* xref:#ERC6909ContentURIComponent-set_token_uri[`++set_token_uri(self, id, token_uri)++`] --- - -[.contract-index] -.Events --- -* xref:#ERC6909ContentURIComponent-ContractURIUpdated[`++ContractURIUpdated()++`] -* xref:#ERC6909ContentURIComponent-URI[`++URI(value, id)++`] --- - -==== Embeddable functions - -[.contract-item] -[[ERC6909ContentURIComponent-contract_uri]] -==== `[.contract-item-name]#++contract_uri++#++(self: @ContractState) → ByteArray++` [.item-kind]#external# - -Returns the contract-level URI. - -[.contract-item] -[[ERC6909ContentURIComponent-token_uri]] -==== `[.contract-item-name]#++token_uri++#++(self: @ContractState, id: u256) → ByteArray++` [.item-kind]#external# - -Returns the token-level URI for token `id`. -If no URI has been set for the token, the return value will be an empty `ByteArray`. - -==== Internal functions - -[.contract-item] -[[ERC6909ContentURIComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState)++` [.item-kind]#internal# - -Initializes the component by registering the IERC6909ContentUri interface ID as supported through introspection. - -This should be used inside the contract's constructor. - -[.contract-item] -[[ERC6909ContentURIComponent-set_contract_uri]] -==== `[.contract-item-name]#++set_contract_uri++#++(ref self: ContractState, contract_uri: ByteArray)++` [.item-kind]#internal# - -Sets the contract-level URI to `contract_uri`. - -Emits a <> event. - -[.contract-item] -[[ERC6909ContentURIComponent-set_token_uri]] -==== `[.contract-item-name]#++set_token_uri++#++(ref self: ContractState, id: u256, token_uri: ByteArray)++` [.item-kind]#internal# - -Sets the token-level URI for token `id` to `token_uri`. - -Emits a <> event. - -==== Events - -[.contract-item] -[[ERC6909ContentURIComponent-ContractURIUpdated]] -==== `[.contract-item-name]#++ContractURIUpdated++#++()++` [.item-kind]#event# - -Emitted when the contract URI is changed. -See https://eips.ethereum.org/EIPS/eip-7572[ERC-7572] for details. - -[.contract-item] -[[ERC6909ContentURIComponent-URI]] -==== `[.contract-item-name]#++URI++#++(value: ByteArray, id: u256)++` [.item-kind]#event# - -Emitted when the URI for token `id` is changed to `value`. - -[.contract] -[[ERC6909MetadataComponent]] -=== `++ERC6909MetadataComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1-alpha.3/packages/token/src/erc6909/extensions/erc6909_metadata.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_token::erc6909::extensions::ERC6909MetadataComponent; -``` - -ERC6909Metadata component implementing <>. - -This extension allows contracts to associate name, symbol, and decimals metadata with each token ID. - -NOTE: Implementing xref:#ERC6909Component[ERC6909Component] is a requirement for this component to be implemented. - -[.contract-index#ERC6909MetadataComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#ERC6909MetadataComponent-Embeddable-Impls-ERC6909MetadataImpl] -.ERC6909MetadataImpl -* xref:#ERC6909MetadataComponent-name[`++name(self, id)++`] -* xref:#ERC6909MetadataComponent-symbol[`++symbol(self, id)++`] -* xref:#ERC6909MetadataComponent-decimals[`++decimals(self, id)++`] --- - -[.contract-index] -.Internal functions --- -.InternalImpl -* xref:#ERC6909MetadataComponent-initializer[`++initializer(self, id, name, symbol, decimals)++`] -* xref:#ERC6909MetadataComponent-set_token_name[`++set_token_name(self, id, name)++`] -* xref:#ERC6909MetadataComponent-set_token_symbol[`++set_token_symbol(self, id, symbol)++`] -* xref:#ERC6909MetadataComponent-set_token_decimals[`++set_token_decimals(self, id, decimals)++`] --- - -[.contract-index] -.Events --- -* xref:#ERC6909MetadataComponent-ERC6909NameUpdated[`++ERC6909NameUpdated(id, new_name)++`] -* xref:#ERC6909MetadataComponent-ERC6909SymbolUpdated[`++ERC6909SymbolUpdated(id, new_symbol)++`] -* xref:#ERC6909MetadataComponent-ERC6909DecimalsUpdated[`++ERC6909DecimalsUpdated(id, new_decimals)++`] --- - -==== Embeddable functions - -[.contract-item] -[[ERC6909MetadataComponent-name]] -==== `[.contract-item-name]#++name++#++(self: @ContractState, id: u256) → ByteArray++` [.item-kind]#external# - -Returns the name of token `id`. - -[.contract-item] -[[ERC6909MetadataComponent-symbol]] -==== `[.contract-item-name]#++symbol++#++(self: @ContractState, id: u256) → ByteArray++` [.item-kind]#external# - -Returns the symbol of token `id`. - -[.contract-item] -[[ERC6909MetadataComponent-decimals]] -==== `[.contract-item-name]#++decimals++#++(self: @ContractState, id: u256) → u8++` [.item-kind]#external# - -Returns the number of decimals of token `id`. - -==== Internal functions - -[.contract-item] -[[ERC6909MetadataComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, id: u256, name: ByteArray, symbol: ByteArray, decimals: u8)++` [.item-kind]#internal# - -Initializes the component by registering the IERC6909Metadata interface ID as supported -through introspection and setting the initial token metadata. - -This should be used inside the contract's constructor. - -[.contract-item] -[[ERC6909MetadataComponent-set_token_name]] -==== `[.contract-item-name]#++set_token_name++#++(ref self: ContractState, id: u256, name: ByteArray)++` [.item-kind]#internal# - -Sets the name for token `id`. - -Emits an <> event. - -[.contract-item] -[[ERC6909MetadataComponent-set_token_symbol]] -==== `[.contract-item-name]#++set_token_symbol++#++(ref self: ContractState, id: u256, symbol: ByteArray)++` [.item-kind]#internal# - -Sets the symbol for token `id`. - -Emits an <> event. - -[.contract-item] -[[ERC6909MetadataComponent-set_token_decimals]] -==== `[.contract-item-name]#++set_token_decimals++#++(ref self: ContractState, id: u256, decimals: u8)++` [.item-kind]#internal# - -Sets the decimals for token `id`. - -Emits an <> event. - -==== Events - -[.contract-item] -[[ERC6909MetadataComponent-ERC6909NameUpdated]] -==== `[.contract-item-name]#++ERC6909NameUpdated++#++(id: u256, new_name: ByteArray)++` [.item-kind]#event# - -Emitted when the name of the token of type `id` was updated to `new_name`. - -[.contract-item] -[[ERC6909MetadataComponent-ERC6909SymbolUpdated]] -==== `[.contract-item-name]#++ERC6909SymbolUpdated++#++(id: u256, new_symbol: ByteArray)++` [.item-kind]#event# - -Emitted when the symbol for the token of type `id` was updated to `new_symbol`. - -[.contract-item] -[[ERC6909MetadataComponent-ERC6909DecimalsUpdated]] -==== `[.contract-item-name]#++ERC6909DecimalsUpdated++#++(id: u256, new_decimals: u8)++` [.item-kind]#event# - -Emitted when the decimals value for token of type `id` was updated to `new_decimals`. - -[.contract] -[[ERC6909TokenSupplyComponent]] -=== `++ERC6909TokenSupplyComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1-alpha.3/packages/token/src/erc6909/extensions/erc6909_token_supply.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_token::erc6909::extensions::ERC6909TokenSupplyComponent; -``` - -ERC6909TokenSupply component implementing <>. - -This extension allows contracts to track the total supply for each token ID. - -NOTE: Implementing xref:#ERC6909Component[ERC6909Component] is a requirement for this component to be implemented. -To properly track total supply, this extension expects its helper -xref:#ERC6909TokenSupplyComponent-update_token_supply[update_token_supply] to be used from the ERC6909 hooks -during mints and burns. - -[.contract-index#ERC6909TokenSupplyComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#ERC6909TokenSupplyComponent-Embeddable-Impls-ERC6909TokenSupplyImpl] -.ERC6909TokenSupplyImpl -* xref:#ERC6909TokenSupplyComponent-total_supply[`++total_supply(self, id)++`] --- - -[.contract-index] -.Internal functions --- -.InternalImpl -* xref:#ERC6909TokenSupplyComponent-initializer[`++initializer(self)++`] -* xref:#ERC6909TokenSupplyComponent-update_token_supply[`++update_token_supply(self, sender, receiver, id, amount)++`] --- - -[#ERC6909TokenSupplyComponent-Embeddable-functions] -==== Embeddable functions - -[.contract-item] -[[ERC6909TokenSupplyComponent-total_supply]] -==== `[.contract-item-name]#++total_supply++#++(self: @ContractState, id: u256) → u256++` [.item-kind]#external# - -Returns the total supply of token `id`. - -[#ERC6909TokenSupplyComponent-Internal-functions] -==== Internal functions - -[.contract-item] -[[ERC6909TokenSupplyComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState)++` [.item-kind]#internal# - -Initializes the component by registering the IERC6909TokenSupply interface ID as supported -through introspection. - -This should be used inside the contract's constructor. - -[.contract-item] -[[ERC6909TokenSupplyComponent-update_token_supply]] -==== `[.contract-item-name]#++update_token_supply++#++(ref self: ContractState, sender: ContractAddress, receiver: ContractAddress, id: u256, amount: u256)++` [.item-kind]#internal# - -Updates the total supply of token `id`. - -When `sender` is the zero address, `amount` is added to the total supply (mint). -When `receiver` is the zero address, `amount` is subtracted from the total supply (burn). - -This helper is intended to be called from the ERC6909 hooks during mint and burn operations. diff --git a/docs/modules/ROOT/pages/api/erc721.adoc b/docs/modules/ROOT/pages/api/erc721.adoc deleted file mode 100644 index b1ed0e4b1..000000000 --- a/docs/modules/ROOT/pages/api/erc721.adoc +++ /dev/null @@ -1,1078 +0,0 @@ -:github-icon: pass:[] -:eip721: https://eips.ethereum.org/EIPS/eip-721[EIP721] -:receiving-tokens: xref:/erc721.adoc#receiving_tokens[Receiving Tokens] -:casing-discussion: https://github.com/OpenZeppelin/cairo-contracts/discussions/34[here] -:inner-src5: xref:api/introspection.adoc#ISRC5[SRC5 ID] - -= ERC721 - -include::../utils/_common.adoc[] - -This module provides interfaces, presets, and utilities related to ERC721 contracts. - -TIP: For an overview of ERC721, read our xref:erc721.adoc[ERC721 guide]. - -== Interfaces - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_token` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[IERC721]] -=== `++IERC721++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc721.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc721::IERC721; -``` - -Interface of the IERC721 standard as defined in {eip721}. - -[.contract-index] -.{inner-src5} --- -0x33eb2f84c309543403fd69f0d0f363781ef06ef6faeb0131ff16ea3175bd943 --- - -[.contract-index] -.Functions --- -* xref:#IERC721-balance_of[`++balance_of(account)++`] -* xref:#IERC721-owner_of[`++owner_of(token_id)++`] -* xref:#IERC721-safe_transfer_from[`++safe_transfer_from(from, to, token_id, data)++`] -* xref:#IERC721-transfer_from[`++transfer_from(from, to, token_id)++`] -* xref:#IERC721-approve[`++approve(to, token_id)++`] -* xref:#IERC721-set_approval_for_all[`++set_approval_for_all(operator, approved)++`] -* xref:#IERC721-get_approved[`++get_approved(token_id)++`] -* xref:#IERC721-is_approved_for_all[`++is_approved_for_all(owner, operator)++`] --- - -[.contract-index] -.Events --- -* xref:#IERC721-Approval[`++Approval(owner, approved, token_id)++`] -* xref:#IERC721-ApprovalForAll[`++ApprovalForAll(owner, operator, approved)++`] -* xref:#IERC721-Transfer[`++Transfer(from, to, token_id)++`] --- - -==== Functions - -[.contract-item] -[[IERC721-balance_of]] -==== `[.contract-item-name]#++balance_of++#++(account: ContractAddress) → u256++` [.item-kind]#external# - -Returns the number of NFTs owned by `account`. - -[.contract-item] -[[IERC721-owner_of]] -==== `[.contract-item-name]#++owner_of++#++(token_id: u256) → ContractAddress++` [.item-kind]#external# - -Returns the owner address of `token_id`. - -[.contract-item] -[[IERC721-safe_transfer_from]] -==== `[.contract-item-name]#++safe_transfer_from++#++(from: ContractAddress, to: ContractAddress, token_id: u256, data: Span)++` [.item-kind]#external# - -Transfer ownership of `token_id` from `from` to `to`, checking first that `to` is aware of the ERC721 protocol to prevent tokens being locked forever. -For information regarding how contracts communicate their awareness of the ERC721 protocol, see {receiving-tokens}. - -Emits a <> event. - -[.contract-item] -[[IERC721-transfer_from]] -==== `[.contract-item-name]#++transfer_from++#++(from: ContractAddress, to: ContractAddress, token_id: u256)++` [.item-kind]#external# - -Transfer ownership of `token_id` from `from` to `to`. - -Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 transfers or else they may be permanently lost. -Usage of <> prevents loss, though the caller must understand this adds an external call which potentially creates a reentrancy vulnerability. - -Emits a <> event. - -[.contract-item] -[[IERC721-approve]] -==== `[.contract-item-name]#++approve++#++(to: ContractAddress, token_id: u256)++` [.item-kind]#external# - -Change or reaffirm the approved address for an NFT. - -Emits an <> event. - -[.contract-item] -[[IERC721-set_approval_for_all]] -==== `[.contract-item-name]#++set_approval_for_all++#++(operator: ContractAddress, approved: bool)++` [.item-kind]#external# - -Enable or disable approval for `operator` to manage all of the caller's assets. - -Emits an <> event. - -[.contract-item] -[[IERC721-get_approved]] -==== `[.contract-item-name]#++get_approved++#++(token_id: u256) -> u256++` [.item-kind]#external# - -Returns the address approved for `token_id`. - -[.contract-item] -[[IERC721-is_approved_for_all]] -==== `[.contract-item-name]#++is_approved_for_all++#++(owner: ContractAddress, operator: ContractAddress) -> bool++` [.item-kind]#external# - -Query if `operator` is an authorized operator for `owner`. - -==== Events - -[.contract-item] -[[IERC721-Approval]] -==== `[.contract-item-name]#++Approval++#++(owner: ContractAddress, approved: ContractAddress, token_id: u256)++` [.item-kind]#event# - -Emitted when `owner` enables `approved` to manage the `token_id` token. - -[.contract-item] -[[IERC721-ApprovalForAll]] -==== `[.contract-item-name]#++ApprovalForAll++#++(owner: ContractAddress, operator: ContractAddress, approved: bool)++` [.item-kind]#event# - -Emitted when `owner` enables or disables `operator` to manage the `token_id` token. - -[.contract-item] -[[IERC721-Transfer]] -==== `[.contract-item-name]#++Transfer++#++(from: ContractAddress, to: ContractAddress, token_id: u256)++` [.item-kind]#event# - -Emitted when `token_id` token is transferred from `from` to `to`. - -[.contract] -[[IERC721Metadata]] -=== `++IERC721Metadata++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc721.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc721::IERC721Metadata; -``` - -Interface for the optional metadata functions in {eip721}. - -[.contract-index] -.{inner-src5} --- -0xabbcd595a567dce909050a1038e055daccb3c42af06f0add544fa90ee91f25 --- - -[.contract-index] -.Functions --- -* xref:#IERC721Metadata-name[`++name()++`] -* xref:#IERC721Metadata-symbol[`++symbol()++`] -* xref:#IERC721Metadata-token_uri[`++token_uri(token_id)++`] --- - -==== Functions - -[.contract-item] -[[IERC721Metadata-name]] -==== `[.contract-item-name]#++name++#++() -> ByteArray++` [.item-kind]#external# - -Returns the NFT name. - -[.contract-item] -[[IERC721Metadata-symbol]] -==== `[.contract-item-name]#++symbol++#++() -> ByteArray++` [.item-kind]#external# - -Returns the NFT ticker symbol. - -[.contract-item] -[[IERC721Metadata-token_uri]] -==== `[.contract-item-name]#++token_uri++#++(token_id: u256) -> ByteArray++` [.item-kind]#external# - -Returns the Uniform Resource Identifier (URI) for the `token_id` token. -If the URI is not set for `token_id`, the return value will be an empty `ByteArray`. - -[.contract] -[[IERC721Receiver]] -=== `++IERC721Receiver++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc721.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc721::IERC721Receiver; -``` - -Interface for contracts that support receiving `safe_transfer_from` transfers. - -[.contract-index] -.{inner-src5} --- -0x3a0dff5f70d80458ad14ae37bb182a728e3c8cdda0402a5daa86620bdf910bc --- - -[.contract-index] -.Functions --- -* xref:#IERC721Receiver-on_erc721_received[`++on_erc721_received(operator, from, token_id, data)++`] --- - -==== Functions - -[.contract-item] -[[IERC721Receiver-on_erc721_received]] -==== `[.contract-item-name]#++on_erc721_received++#++(operator: ContractAddress, from: ContractAddress, token_id: u256, data: Span) -> felt252++` [.item-kind]#external# - -Whenever an IERC721 `token_id` token is transferred to this non-account contract via <> by `operator` from `from`, this function is called. - -[.contract] -[[IERC721Enumerable]] -=== `++IERC721Enumerable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc721.cairo[{github-icon},role=heading-link] - -Interface for the optional enumerable functions in {eip721}. - -[.contract-index] -.{inner-src5} --- -0x16bc0f502eeaf65ce0b3acb5eea656e2f26979ce6750e8502a82f377e538c87 --- - -[.contract-index] -.Functions --- -* xref:#IERC721Enumerable-total_supply[`++total_supply()++`] -* xref:#IERC721Enumerable-token_by_index[`++token_by_index(index)++`] -* xref:#IERC721Enumerable-token_of_owner_by_index[`++token_of_owner_by_index(owner, index)++`] --- - -==== Functions - -[.contract-item] -[[IERC721Enumerable-total_supply]] -==== `[.contract-item-name]#++total_supply++#++() -> u256++` [.item-kind]#external# - -Returns the total amount of tokens stored by the contract. - -[.contract-item] -[[IERC721Enumerable-token_by_index]] -==== `[.contract-item-name]#++token_by_index++#++(index: u256) -> u256++` [.item-kind]#external# - -Returns a token id at a given `index` of all the tokens stored by the contract. -Use along with xref:#IERC721Enumerable-total_supply[IERC721Enumerable::total_supply] to enumerate all tokens. - -[.contract-item] -[[IERC721Enumerable-token_of_owner_by_index]] -==== `[.contract-item-name]#++token_of_owner_by_index++#++(owner: ContractAddress, index: u256) -> u256++` [.item-kind]#external# - -Returns the token id owned by `owner` at a given `index` of its token list. -Use along with xref:#IERC721-balance_of[IERC721::balance_of] to enumerate all of ``owner``'s tokens. - -== Core - -[.contract] -[[ERC721Component]] -=== `++ERC721Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/token/src/erc721/erc721.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_token::erc721::ERC721Component; -``` - -ERC721 component implementing <> and <>. - -NOTE: {src5-component-required-note} - -NOTE: See xref:#ERC721Component-Hooks[Hooks] to understand how are hooks used. - -[.contract-index] -.Hooks --- -[.sub-index#ERC721Component-ERC721HooksTrait] -.ERC721HooksTrait -* xref:#ERC721Component-before_update[`++before_update(self, to, token_id, auth)++`] -* xref:#ERC721Component-after_update[`++after_update(self, to, token_id, auth)++`] --- - -[.contract-index#ERC721Component-Embeddable-Mixin-Impl] -.{mixin-impls} - --- -.ERC721MixinImpl -* xref:#ERC721Component-Embeddable-Impls-ERC721Impl[`++ERC721Impl++`] -* xref:#ERC721Component-Embeddable-Impls-ERC721MetadataImpl[`++ERC721MetadataImpl++`] -* xref:#ERC721Component-Embeddable-Impls-ERC721CamelOnlyImpl[`++ERC721CamelOnlyImpl++`] -* xref:#ERC721Component-Embeddable-Impls-ERC721MetadataCamelOnlyImpl[`++ERC721MetadataCamelOnlyImpl++`] -* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls[`++SRC5Impl++`] --- - -[.contract-index#ERC721Component-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#ERC721Component-Embeddable-Impls-ERC721Impl] -.ERC721Impl -* xref:#ERC721Component-balance_of[`++balance_of(self, account)++`] -* xref:#ERC721Component-owner_of[`++owner_of(self, token_id)++`] -* xref:#ERC721Component-safe_transfer_from[`++safe_transfer_from(self, from, to, token_id, data)++`] -* xref:#ERC721Component-transfer_from[`++transfer_from(self, from, to, token_id)++`] -* xref:#ERC721Component-approve[`++approve(self, to, token_id)++`] -* xref:#ERC721Component-set_approval_for_all[`++set_approval_for_all(self, operator, approved)++`] -* xref:#ERC721Component-get_approved[`++get_approved(self, token_id)++`] -* xref:#ERC721Component-is_approved_for_all[`++is_approved_for_all(self, owner, operator)++`] - -[.sub-index#ERC721Component-Embeddable-Impls-ERC721MetadataImpl] -.ERC721MetadataImpl -* xref:#ERC721Component-name[`++name(self)++`] -* xref:#ERC721Component-symbol[`++symbol(self)++`] -* xref:#ERC721Component-token_uri[`++token_uri(self, token_id)++`] - -[.sub-index#ERC721Component-Embeddable-Impls-ERC721CamelOnlyImpl] -.ERC721CamelOnlyImpl -* xref:#ERC721Component-balanceOf[`++balanceOf(self, account)++`] -* xref:#ERC721Component-ownerOf[`++ownerOf(self, tokenId)++`] -* xref:#ERC721Component-safeTransferFrom[`++safeTransferFrom(self, from, to, tokenId, data)++`] -* xref:#ERC721Component-transferFrom[`++transferFrom(self, from, to, tokenId)++`] -* xref:#ERC721Component-setApprovalForAll[`++setApprovalForAll(self, operator, approved)++`] -* xref:#ERC721Component-getApproved[`++getApproved(self, tokenId)++`] -* xref:#ERC721Component-isApprovedForAll[`++isApprovedForAll(self, owner, operator)++`] - -[.sub-index#ERC721Component-Embeddable-Impls-ERC721MetadataCamelOnlyImpl] -.ERC721MetadataCamelOnlyImpl -* xref:#ERC721Component-tokenURI[`++tokenURI(self, tokenId)++`] - -.SRC5Impl -* xref:api/introspection.adoc#ISRC5-supports_interface[`supports_interface(self, interface_id: felt252)`] --- - -[.contract-index] -.Internal functions --- -.InternalImpl -* xref:#ERC721Component-initializer[`++initializer(self, name, symbol, base_uri)++`] -* xref:#ERC721Component-initializer_no_metadata[`++initializer_no_metadata(self)++`] -* xref:#ERC721Component-exists[`++exists(self, token_id)++`] -* xref:#ERC721Component-transfer[`++transfer(self, from, to, token_id)++`] -* xref:#ERC721Component-mint[`++mint(self, to, token_id)++`] -* xref:#ERC721Component-safe_transfer[`++safe_transfer(self, from, to, token_id, data)++`] -* xref:#ERC721Component-safe_mint[`++safe_mint(self, to, token_id, data)++`] -* xref:#ERC721Component-burn[`++burn(self, token_id)++`] -* xref:#ERC721Component-update[`++update(self, to, token_id, auth)++`] -* xref:#ERC721Component-_owner_of[`++_owner_of(self, token_id)++`] -* xref:#ERC721Component-_require_owned[`++_require_owned(self, token_id)++`] -* xref:#ERC721Component-_approve[`++_approve(self, to, token_id, auth)++`] -* xref:#ERC721Component-_approve_with_optional_event[`++_approve_with_optional_event(self, to, token_id, auth, emit_event)++`] -* xref:#ERC721Component-_set_approval_for_all[`++_set_approval_for_all(self, owner, operator, approved)++`] -* xref:#ERC721Component-_set_base_uri[`++_set_base_uri(self, base_uri)++`] -* xref:#ERC721Component-_base_uri[`++_base_uri(self)++`] -* xref:#ERC721Component-_is_authorized[`++_is_authorized(self, owner, spender, token_id)++`] -* xref:#ERC721Component-_check_authorized[`++_check_authorized(self, owner, spender, token_id)++`] --- - -[.contract-index] -.Events --- -.IERC721 -* xref:#ERC721Component-Approval[`++Approval(owner, approved, token_id)++`] -* xref:#ERC721Component-ApprovalForAll[`++ApprovalForAll(owner, operator, approved)++`] -* xref:#ERC721Component-Transfer[`++Transfer(from, to, token_id)++`] --- - -[#ERC721Component-Hooks] -==== Hooks - -Hooks are functions which implementations can extend the functionality of the component source code. Every contract -using ERC721Component is expected to provide an implementation of the ERC721HooksTrait. For basic token contracts, an -empty implementation with no logic must be provided. - -TIP: You can use `openzeppelin_token::erc721::ERC721HooksEmptyImpl` which is already available as part of the library -for this purpose. - -[.contract-item] -[[ERC721Component-before_update]] -==== `[.contract-item-name]#++before_update++#++(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)++` [.item-kind]#hook# - -Function executed at the beginning of the xref:#ERC721Component-update[update] function prior to any other logic. - -[.contract-item] -[[ERC721Component-after_update]] -==== `[.contract-item-name]#++after_update++#++(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)++` [.item-kind]#hook# - -Function executed at the end of the xref:#ERC721Component-update[update] function. - -==== Embeddable functions - -[.contract-item] -[[ERC721Component-balance_of]] -==== `[.contract-item-name]#++balance_of++#++(self: @ContractState, account: ContractAddress) → u256++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-owner_of]] -==== `[.contract-item-name]#++owner_of++#++(self: @ContractState, token_id: u256) → ContractAddress++` [.item-kind]#external# - -See <>. - -Requirements: - -- `token_id` exists. - -[.contract-item] -[[ERC721Component-safe_transfer_from]] -==== `[.contract-item-name]#++safe_transfer_from++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, data: Span)++` [.item-kind]#external# - -See <>. - -Requirements: - -- Caller is either approved or the `token_id` owner. -- `to` is not the zero address. -- `from` is not the zero address. -- `token_id` exists. -- `to` is either an account contract or supports the <> interface. - -[.contract-item] -[[ERC721Component-transfer_from]] -==== `[.contract-item-name]#++transfer_from++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256)++` [.item-kind]#external# - -See <>. - -Requirements: - -- Caller either approved or the `token_id` owner. -- `to` is not the zero address. -- `from` is not the zero address. -- `token_id` exists. - -[.contract-item] -[[ERC721Component-approve]] -==== `[.contract-item-name]#++approve++#++(ref self: ContractState, to: ContractAddress, token_id: u256)++` [.item-kind]#external# - -See <>. - -Requirements: - -- The caller is either an approved operator or the `token_id` owner. -- `to` cannot be the token owner or the zero address. -- `token_id` exists. - -[.contract-item] -[[ERC721Component-set_approval_for_all]] -==== `[.contract-item-name]#++set_approval_for_all++#++(ref self: ContractState, operator: ContractAddress, approved: bool)++` [.item-kind]#external# - -See <>. - -Requirements: - -- `operator` is not the zero address. - -[.contract-item] -[[ERC721Component-get_approved]] -==== `[.contract-item-name]#++get_approved++#++(self: @ContractState, token_id: u256) -> u256++` [.item-kind]#external# - -See <>. - -Requirements: - -- `token_id` exists. - -[.contract-item] -[[ERC721Component-is_approved_for_all]] -==== `[.contract-item-name]#++is_approved_for_all++#++(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-name]] -==== `[.contract-item-name]#++name++#++(self: @ContractState) -> ByteArray++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-symbol]] -==== `[.contract-item-name]#++symbol++#++(self: @ContractState) -> ByteArray++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-token_uri]] -==== `[.contract-item-name]#++token_uri++#++(self: @ContractState, token_id: u256) -> ByteArray++` [.item-kind]#external# - -Returns the Uniform Resource Identifier (URI) for the `token_id` token. -If a base URI is set, the resulting URI for each token will be the concatenation of the base URI and the token ID. -For example, the base URI pass:[https://token-cdn-domain/] would be returned as pass:[https://token-cdn-domain/123] for token ID `123`. - -If the URI is not set for `token_id`, the return value will be an empty `ByteArray`. - -[.contract-item] -[[ERC721Component-balanceOf]] -==== `[.contract-item-name]#++balanceOf++#++(self: @ContractState, account: ContractAddress) -> u256++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-ownerOf]] -==== `[.contract-item-name]#++ownerOf++#++(self: @ContractState, tokenId: u256) -> ContractAddress++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-safeTransferFrom]] -==== `[.contract-item-name]#++safeTransferFrom++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256, data: Span)++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-transferFrom]] -==== `[.contract-item-name]#++transferFrom++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, tokenId: u256)++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-setApprovalForAll]] -==== `[.contract-item-name]#++setApprovalForAll++#++(ref self: ContractState, operator: ContractAddress, approved: bool)++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-getApproved]] -==== `[.contract-item-name]#++getApproved++#++(self: @ContractState, tokenId: u256) -> ContractAddress++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-isApprovedForAll]] -==== `[.contract-item-name]#++isApprovedForAll++#++(self: @ContractState, owner: ContractAddress, operator: ContractAddress) -> bool++` [.item-kind]#external# - -See <>. - -[.contract-item] -[[ERC721Component-tokenURI]] -==== `[.contract-item-name]#++tokenURI++#++(self: @ContractState, tokenId: u256) -> ByteArray++` [.item-kind]#external# - -See <>. - -==== Internal functions - -[.contract-item] -[[ERC721Component-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, name: ByteArray, symbol: ByteArray, base_uri: ByteArray)++` [.item-kind]#internal# - -Initializes the contract by setting the token name and symbol. -This should be used inside the contract's constructor. - -WARNING: Most ERC721 contracts expose the <> interface which -is what this initializer is meant to support. -If the contract DOES NOT expose the <> interface, -meaning the token does not have a name, symbol, or URI, -the contract must instead use <> in the constructor. -Failure to abide by these instructions can lead to unexpected issues especially with -UIs. - -[.contract-item] -[[ERC721Component-initializer_no_metadata]] -==== `[.contract-item-name]#++initializer_no_metadata++#++(ref self: ContractState)++` [.item-kind]#internal# - -Initializes the contract with no metadata by registering only the IERC721 interface. - -WARNING: This initializer should ONLY be used during construction in the very -specific instance when the contract does NOT expose the <> interface. -Initializing a contract with this initializer means that tokens will not -have a name, symbol, or URI. - -[.contract-item] -[[ERC721Component-exists]] -==== `[.contract-item-name]#++exists++#++(self: @ContractState, token_id: u256) -> bool++` [.item-kind]#internal# - -Internal function that returns whether `token_id` exists. - -Tokens start existing when they are minted (<>), and stop existing when they are burned (<>). - -[.contract-item] -[[ERC721Component-transfer]] -==== `[.contract-item-name]#++transfer++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256)++` [.item-kind]#internal# - -Transfers `token_id` from `from` to `to`. - -Internal function without access restriction. - -WARNING: This method may lead to the loss of tokens if `to` is not aware of the ERC721 protocol. - -Requirements: - -- `to` is not the zero address. -- `from` is the token owner. -- `token_id` exists. - -Emits a <> event. - -[.contract-item] -[[ERC721Component-mint]] -==== `[.contract-item-name]#++mint++#++(ref self: ContractState, to: ContractAddress, token_id: u256)++` [.item-kind]#internal# - -Mints `token_id` and transfers it to `to`. -Internal function without access restriction. - -WARNING: This method may lead to the loss of tokens if `to` is not aware of the ERC721 protocol. - -Requirements: - -- `to` is not the zero address. -- `token_id` does not exist. - -Emits a <> event. - -[.contract-item] -[[ERC721Component-safe_transfer]] -==== `[.contract-item-name]#++safe_transfer++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, token_id: u256, data: Span)++` [.item-kind]#internal# - -Transfers ownership of `token_id` from `from` if `to` is either an account or `IERC721Receiver`. - -`data` is additional data, it has no specified format and is forwarded in `IERC721Receiver::on_erc721_received` to `to`. - -WARNING: This method makes an external call to the recipient contract, which can lead to reentrancy vulnerabilities. - -Requirements: - -- `to` cannot be the zero address. -- `from` must be the token owner. -- `token_id` exists. -- `to` is either an account contract or supports the `IERC721Receiver` interface. - -Emits a <> event. - -[.contract-item] -[[ERC721Component-safe_mint]] -==== `[.contract-item-name]#++safe_mint++#++(ref self: ContractState, to: ContractAddress, token_id: u256, data: Span)++` [.item-kind]#internal# - -Mints `token_id` if `to` is either an account or `IERC721Receiver`. - -`data` is additional data, it has no specified format and is forwarded in `IERC721Receiver::on_erc721_received` to `to`. - -WARNING: This method makes an external call to the recipient contract, which can lead to reentrancy vulnerabilities. - -Requirements: - -- `token_id` does not exist. -- `to` is either an account contract or supports the `IERC721Receiver` interface. - -Emits a <> event. - -[.contract-item] -[[ERC721Component-burn]] -==== `[.contract-item-name]#++burn++#++(ref self: ContractState, token_id: u256)++` [.item-kind]#internal# - -Destroys `token_id`. The approval is cleared when the token is burned. - -This internal function does not check if the caller is authorized -to operate on the token. - -Requirements: - -- `token_id` exists. - -Emits a <> event. - -[.contract-item] -[[ERC721Component-update]] -==== `[.contract-item-name]#++update++#++(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)++` [.item-kind]#internal# - -Transfers `token_id` from its current owner to `to`, or alternatively mints (or burns) if the current owner -(or `to`) is the zero address. Returns the owner of the `token_id` before the update. - -The `auth` argument is optional. If the value passed is non-zero, then this function will check that -`auth` is either the owner of the token, or approved to operate on the token (by the owner). - -Emits a <> event. - -NOTE: This function can be extended using the `ERC721HooksTrait`, to add -functionality before and/or after the transfer, mint, or burn. - -[.contract-item] -[[ERC721Component-_owner_of]] -==== `[.contract-item-name]#++_owner_of++#++(self: @ContractState, token_id: felt252) -> ContractAddress++` [.item-kind]#internal# - -Internal function that returns the owner address of `token_id`. - -[.contract-item] -[[ERC721Component-_require_owned]] -==== `[.contract-item-name]#++_require_owned++#++(self: @ContractState, token_id: felt252) -> ContractAddress++` [.item-kind]#internal# - -Version of xref:#ERC721Component-_owner_of[_owner_of] that panics if owner is the zero address. - -[.contract-item] -[[ERC721Component-_approve]] -==== `[.contract-item-name]#++_approve++#++(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress)++` [.item-kind]#internal# - -Approve `to` to operate on `token_id` - -The `auth` argument is optional. If the value passed is non-zero, then this function will check that `auth` is -either the owner of the token, or approved to operate on all tokens held by this owner. - -Emits an <> event. - -[.contract-item] -[[ERC721Component-_approve_with_optional_event]] -==== `[.contract-item-name]#++_approve_with_optional_event++#++(ref self: ContractState, to: ContractAddress, token_id: u256, auth: ContractAddress, emit_event: bool)++` [.item-kind]#internal# - -Variant of xref:#ERC721Component-_approve[_approve] with an optional flag to enable or disable the `Approval` event. -The event is not emitted in the context of transfers. - -WARNING: If `auth` is zero and `emit_event` is false, this function will not check that the token exists. - -Requirements: - -- if `auth` is non-zero, it must be either the owner of the token or approved to -operate on all of its tokens. - -May emit an <> event. - -[.contract-item] -[[ERC721Component-_set_approval_for_all]] -==== `[.contract-item-name]#++_set_approval_for_all++#++(ref self: ContractState, owner: ContractAddress, operator: ContractAddress, approved: bool)++` [.item-kind]#internal# - -Enables or disables approval for `operator` to manage -all of the `owner` assets. - -Requirements: - -- `operator` is not the zero address. - -Emits an <> event. - -[.contract-item] -[[ERC721Component-_set_base_uri]] -==== `[.contract-item-name]#++_set_base_uri++#++(ref self: ContractState, base_uri: ByteArray)++` [.item-kind]#internal# - -Internal function that sets the `base_uri`. - -[.contract-item] -[[ERC721Component-_base_uri]] -==== `[.contract-item-name]#++_base_uri++#++(self: @ContractState) -> ByteArray++` [.item-kind]#internal# - -Base URI for computing <>. - -If set, the resulting URI for each token will be the concatenation of the base URI and the token ID. -Returns an empty `ByteArray` if not set. - -[.contract-item] -[[ERC721Component-_is_authorized]] -==== `[.contract-item-name]#++_is_authorized++#++(self: @ContractState, owner: ContractAddress, spender: ContractAddress, token_id: u256) -> bool++` [.item-kind]#internal# - -Returns whether `spender` is allowed to manage ``owner``'s tokens, or `token_id` in -particular (ignoring whether it is owned by `owner`). - -WARNING: This function assumes that `owner` is the actual owner of `token_id` and does not verify this -assumption. - -[.contract-item] -[[ERC721Component-_check_authorized]] -==== `[.contract-item-name]#++_check_authorized++#++(self: @ContractState, owner: ContractAddress, spender: ContractAddress, token_id: u256) -> bool++` [.item-kind]#internal# - -Checks if `spender` can operate on `token_id`, assuming the provided `owner` is the actual owner. - -Requirements: - -- `owner` cannot be the zero address. -- `spender` cannot be the zero address. -- `spender` must be the owner of `token_id` or be approved to operate on it. - -WARNING: This function assumes that `owner` is the actual owner of `token_id` and does not verify this -assumption. - -==== Events - -[.contract-item] -[[ERC721Component-Approval]] -==== `[.contract-item-name]#++Approval++#++(owner: ContractAddress, approved: ContractAddress, token_id: u256)++` [.item-kind]#event# - -See <>. - -[.contract-item] -[[ERC721Component-ApprovalForAll]] -==== `[.contract-item-name]#++ApprovalForAll++#++(owner: ContractAddress, operator: ContractAddress, approved: bool)++` [.item-kind]#event# - -See <>. - -[.contract-item] -[[ERC721Component-Transfer]] -==== `[.contract-item-name]#++Transfer++#++(from: ContractAddress, to: ContractAddress, token_id: u256)++` [.item-kind]#event# - -See <>. - -[.contract] -[[ERC721ReceiverComponent]] -=== `++ERC721ReceiverComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/token/src/erc721/erc721_receiver.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_token::erc721::ERC721ReceiverComponent; -``` - -ERC721Receiver component implementing <>. - -NOTE: {src5-component-required-note} - -[.contract-index#ERC721ReceiverComponent-Embeddable-Mixin-Impl] -.{mixin-impls} - --- -.ERCReceiverMixinImpl -* xref:#ERC721ReceiverComponent-Embeddable-Impls-ERC721ReceiverImpl[`++ERC721ReceiverImpl++`] -* xref:#ERC721ReceiverComponent-Embeddable-Impls-ERC721ReceiverCamelImpl[`++ERC721ReceiverCamelImpl++`] -* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls[`++SRC5Impl++`] --- - -[.contract-index#ERC721ReceiverComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#ERC721ReceiverComponent-Embeddable-Impls-ERC721ReceiverImpl] -.ERC721ReceiverImpl -* xref:#ERC721ReceiverComponent-on_erc721_received[`++on_erc721_received(self, operator, from, token_id, data)++`] - -[.sub-index#ERC721ReceiverComponent-Embeddable-Impls-ERC721ReceiverCamelImpl] -.ERC721ReceiverCamelImpl -* xref:#ERC721ReceiverComponent-onERC721Received[`++onERC721Received(self, operator, from, tokenId, data)++`] --- - -[.contract-index] -.Internal Functions --- -.InternalImpl -* xref:#ERC721ReceiverComponent-initializer[`++initializer(self)++`] --- - -==== Embeddable functions - -[.contract-item] -[[ERC721ReceiverComponent-on_erc721_received]] -==== `[.contract-item-name]#++on_erc721_received++#++(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_id: u256, data Span) -> felt252++` [.item-kind]#external# - -Returns the `IERC721Receiver` interface ID. - -[.contract-item] -[[ERC721ReceiverComponent-onERC721Received]] -==== `[.contract-item-name]#++onERC721Received++#++(self: @ContractState, operator: ContractAddress, from: ContractAddress, token_id: u256, data Span) -> felt252++` [.item-kind]#external# - -See <>. - -==== Internal functions - -[.contract-item] -[[ERC721ReceiverComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState)++` [.item-kind]#internal# - -Registers the `IERC721Receiver` interface ID as supported through introspection. - -== Extensions - -[.contract] -[[ERC721EnumerableComponent]] -=== `++ERC721EnumerableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/token/src/erc721/extensions/erc721_enumerable.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_token::erc721::extensions::ERC721EnumerableComponent; -``` - -Extension of ERC721 as defined in the EIP that adds enumerability of all the token ids in the contract as well as all token ids owned by each account. -This extension allows contracts to publish their entire list of NFTs and make them discoverable. - -NOTE: Implementing xref:#ERC721Component[ERC721Component] is a requirement for this component to be implemented. - -To properly track token ids, this extension requires that the xref:#ERC721EnumerableComponent-before_update[ERC721EnumerableComponent::before_update] function is called before every transfer, mint, or burn operation. -For this, the xref:ERC721Component-before_update[ERC721HooksTrait::before_update] hook must be used. -Here's how the hook should be implemented in a contract: - -```[,cairo] -#[starknet::contract] -mod ERC721EnumerableContract { - (...) - - component!(path: ERC721Component, storage: erc721, event: ERC721Event); - component!(path: ERC721EnumerableComponent, storage: erc721_enumerable, event: ERC721EnumerableEvent); - component!(path: SRC5Component, storage: src5, event: SRC5Event); - - impl ERC721HooksImpl of ERC721Component::ERC721HooksTrait { - fn before_update( - ref self: ERC721Component::ComponentState, - to: ContractAddress, - token_id: u256, - auth: ContractAddress - ) { - let mut contract_state = self.get_contract_mut(); - contract_state.erc721_enumerable.before_update(to, token_id); - } - } -} -``` - -[.contract-index#ERC721EnumerableComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#ERC721EnumerableComponent-Embeddable-Impls-ERC721EnumerableImpl] -.ERC721EnumerableImpl -* xref:#ERC721EnumerableComponent-total_supply[`++total_supply(self)++`] -* xref:#ERC721EnumerableComponent-token_by_index[`++token_by_index(self, index)++`] -* xref:#ERC721EnumerableComponent-token_of_owner_by_index[`++token_of_owner_by_index(self, address, index)++`] --- - -[.contract-index] -.Internal functions --- -.InternalImpl -* xref:#ERC721EnumerableComponent-initializer[`++initializer(self)++`] -* xref:#ERC721EnumerableComponent-before_update[`++before_update(self, to, token_id)++`] -* xref:#ERC721EnumerableComponent-all_tokens_of_owner[`++all_tokens_of_owner(self, owner)++`] -* xref:#ERC721EnumerableComponent-_add_token_to_owner_enumeration[`++_add_token_to_owner_enumeration(self, to, token_id)++`] -* xref:#ERC721EnumerableComponent-_add_token_to_all_tokens_enumeration[`++_add_token_to_all_tokens_enumeration(self, token_id)++`] -* xref:#ERC721EnumerableComponent-_remove_token_from_owner_enumeration[`++_remove_token_from_owner_enumeration(self, from, token_id)++`] -* xref:#ERC721EnumerableComponent-_remove_token_from_all_tokens_enumeration[`++_remove_token_from_all_tokens_enumeration(self, token_id)++`] --- - -[#ERC721EnumerableComponent-Embeddable-functions] -==== Embeddable functions - -[.contract-item] -[[ERC721EnumerableComponent-total_supply]] -==== `[.contract-item-name]#++total_supply++#++(self: @ContractState) → u256++` [.item-kind]#external# - -Returns the current amount of votes that `account` has. - -[.contract-item] -[[ERC721EnumerableComponent-token_by_index]] -==== `[.contract-item-name]#++token_by_index++#++(self: @ContractState, index: u256) → u256++` [.item-kind]#external# - -See xref:#IERC721Enumerable-token_by_index[IERC721Enumerable::token_by_index]. - -Requirements: - -- `index` is less than the total token supply. - -[.contract-item] -[[ERC721EnumerableComponent-token_of_owner_by_index]] -==== `[.contract-item-name]#++token_of_owner_by_index++#++(self: @ContractState, owner: ContractAddress, index: u256) → u256++` [.item-kind]#external# - -See xref:#IERC721Enumerable-token_of_owner_by_index[IERC721Enumerable::token_of_owner_by_index]. - -Requirements: - -- `index` is less than ``owner``'s token balance. -- `owner` is not the zero address. - -[#ERC721EnumerableComponent-Internal-functions] -==== Internal functions - -[.contract-item] -[[ERC721EnumerableComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState)++` [.item-kind]#internal# - -Registers the `IERC721Enumerable` interface ID as supported through introspection. - -[.contract-item] -[[ERC721EnumerableComponent-before_update]] -==== `[.contract-item-name]#++before_update++#++(ref self: ContractState, to: ContractAddress, token_id: u256)++` [.item-kind]#internal# - -Updates the ownership and token-tracking data structures. - -When a token is minted (or burned), `token_id` is added to (or removed from) the token-tracking structures. - -When a token is transferred, minted, or burned, the ownership-tracking data structures reflect the change in ownership of `token_id`. - -This must be added to the implementing contract's xref:ERC721Component-before_update[ERC721HooksTrait::before_update] hook. - -[.contract-item] -[[ERC721EnumerableComponent-all_tokens_of_owner]] -==== `[.contract-item-name]#++all_tokens_of_owner++#++(self: @ContractState, owner: ContractAddress) → Span++` [.item-kind]#internal# - -Returns a list of all token ids owned by the specified `owner`. -This function provides a more efficient alternative to calling `ERC721::balance_of` -and iterating through tokens with `ERC721Enumerable::token_of_owner_by_index`. - -Requirements: - -- `owner` is not the zero address. - -[.contract-item] -[[ERC721EnumerableComponent-_add_token_to_owner_enumeration]] -==== `[.contract-item-name]#++_add_token_to_owner_enumeration++#++(ref self: ContractState, to: ContractAddress, token_id: u256)++` [.item-kind]#internal# - -Adds token to this extension's ownership-tracking data structures. - -[.contract-item] -[[ERC721EnumerableComponent-_add_token_to_all_tokens_enumeration]] -==== `[.contract-item-name]#++_add_token_to_all_tokens_enumeration++#++(ref self: ContractState, token_id: u256)++` [.item-kind]#internal# - -Adds token to this extension's token-tracking data structures. - -[.contract-item] -[[ERC721EnumerableComponent-_remove_token_from_owner_enumeration]] -==== `[.contract-item-name]#++_remove_token_from_owner_enumeration++#++(ref self: ContractState, from: ContractAddress, token_id: u256)++` [.item-kind]#internal# - -Removes a token from this extension's ownership-tracking data structures. - -This has 0(1) time complexity but alters the indexed order of owned tokens by swapping `token_id` and the index thereof with the last token id and the index thereof e.g. removing `1` from `[1, 2, 3, 4]` results in `[4, 2, 3]`. - -[.contract-item] -[[ERC721EnumerableComponent-_remove_token_from_all_tokens_enumeration]] -==== `[.contract-item-name]#++_remove_token_from_all_tokens_enumeration++#++(ref self: ContractState, token_id: u256)++` [.item-kind]#internal# - -Removes `token_id` from this extension's token-tracking data structures. - -This has 0(1) time complexity but alters the indexed order by swapping `token_id` and the index thereof with the last token id and the index thereof e.g. removing `1` from `[1, 2, 3, 4]` results in `[4, 2, 3]`. - -== Presets - -[.contract] -[[ERC721Upgradeable]] -=== `++ERC721Upgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/presets/src/erc721.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_presets::ERC721Upgradeable; -``` - -Upgradeable ERC721 contract leveraging xref:#ERC721Component[ERC721Component]. - -include::../utils/_class_hashes.adoc[] - -[.contract-index] -.{presets-page} --- -{ERC721Upgradeable-class-hash} --- - -[.contract-index] -.Constructor --- -* xref:#ERC721Upgradeable-constructor[`++constructor(self, name, symbol, recipient, token_ids, base_uri, owner)++`] --- - -[.contract-index] -.Embedded Implementations --- -.ERC721MixinImpl - -* xref:#ERC721Component-Embeddable-Mixin-Impl[`++ERC721MixinImpl++`] - -.OwnableMixinImpl - -* xref:/api/access.adoc#OwnableComponent-Mixin-Impl[`++OwnableMixinImpl++`] --- - -[.contract-index] -.External Functions --- -* xref:#ERC721Upgradeable-upgrade[`++upgrade(self, new_class_hash)++`] --- - -[#ERC721Upgradeable-constructor-section] -==== Constructor - -[.contract-item] -[[ERC721Upgradeable-constructor]] -==== `[.contract-item-name]#++constructor++#++(ref self: ContractState, name: ByteArray, symbol: ByteArray, recipient: ContractAddress, token_ids: Span, base_uri: ByteArray, owner: ContractAddress)++` [.item-kind]#constructor# - -Sets the `name` and `symbol`. -Mints `token_ids` tokens to `recipient` and sets the `base_uri`. -Assigns `owner` as the contract owner with permissions to upgrade. - -[#ERC721Upgradeable-external-functions] -==== External functions - -[.contract-item] -[[ERC721Upgradeable-upgrade]] -==== `[.contract-item-name]#++upgrade++#++(ref self: ContractState, new_class_hash: ClassHash)++` [.item-kind]#external# - -Upgrades the contract to a new implementation given by `new_class_hash`. - -Requirements: - -- The caller is the contract owner. -- `new_class_hash` cannot be zero. diff --git a/docs/modules/ROOT/pages/api/finance.adoc b/docs/modules/ROOT/pages/api/finance.adoc deleted file mode 100755 index f2c0956b5..000000000 --- a/docs/modules/ROOT/pages/api/finance.adoc +++ /dev/null @@ -1,312 +0,0 @@ -:github-icon: pass:[] -:vesting-component: xref:VestingComponent[VestingComponent] -:ownable-component: xref:api/access.adoc#OwnableComponent[OwnableComponent] -:vesting-schedule: xref:api/finance.adoc#VestingComponent-Vesting-Schedule[VestingSchedule] -:AmountReleased: xref:IVesting-AmountReleased[AmountReleased] - -= Finance - -This crate includes primitives for financial systems. - -== Interfaces - -include::../utils/_common.adoc[] - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_finance` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[IVesting]] -=== `++IVesting++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/finance/vesting.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::vesting::IVesting; -``` - -Common interface for contracts implementing the vesting functionality. - -[.contract-index] -.Functions --- -* xref:#IVesting-start[`++start()++`] -* xref:#IVesting-cliff[`++cliff()++`] -* xref:#IVesting-duration[`++duration()++`] -* xref:#IVesting-end[`++end()++`] -* xref:#IVesting-released[`++released(token)++`] -* xref:#IVesting-releasable[`++releasable(token)++`] -* xref:#IVesting-vested_amount[`++vested_amount(token, timestamp)++`] -* xref:#IVesting-release[`++release(token)++`] --- - -[.contract-index] -.Events --- -* xref:#IVesting-AmountReleased[`++AmountReleased(token, amount)++`] --- - -[#IVesting-Functions] -==== Functions - -[.contract-item] -[[IVesting-start]] -==== `[.contract-item-name]#++start++#++() → u64++` [.item-kind]#external# - -Returns the timestamp marking the beginning of the vesting period. - -[.contract-item] -[[IVesting-cliff]] -==== `[.contract-item-name]#++cliff++#++() → u64++` [.item-kind]#external# - -Returns the timestamp marking the end of the cliff period. - -[.contract-item] -[[IVesting-duration]] -==== `[.contract-item-name]#++duration++#++() → u64++` [.item-kind]#external# - -Returns the total duration of the vesting period. - -[.contract-item] -[[IVesting-end]] -==== `[.contract-item-name]#++end++#++() → u64++` [.item-kind]#external# - -Returns the timestamp marking the end of the vesting period. - -[.contract-item] -[[IVesting-released]] -==== `[.contract-item-name]#++released++#++(token: ContractAddress) → u256++` [.item-kind]#external# - -Returns the already released amount for a given `token`. - -[.contract-item] -[[IVesting-releasable]] -==== `[.contract-item-name]#++releasable++#++(token: ContractAddress) → u256++` [.item-kind]#external# - -Returns the amount of a given `token` that can be released at the time of the call. - -[.contract-item] -[[IVesting-vested_amount]] -==== `[.contract-item-name]#++vested_amount++#++(token: ContractAddress, timestamp: u64) → u256++` [.item-kind]#external# - -Returns the total vested amount of a specified `token` at a given `timestamp`. - -[.contract-item] -[[IVesting-release]] -==== `[.contract-item-name]#++release++#++(token: ContractAddress) → u256++` [.item-kind]#external# - -Releases the amount of a given `token` that has already vested and returns that amount. - -May emit an {AmountReleased} event. - -[#IVesting-Events] -==== Events - -[.contract-item] -[[IVesting-AmountReleased]] -==== `[.contract-item-name]#++AmountReleased++#++(token: ContractAddress, amount: u256)++` [.item-kind]#event# - -Emitted when vested tokens are released to the beneficiary. - -== Vesting - -[.contract] -[[VestingComponent]] -=== `++VestingComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/finance/src/vesting/vesting.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_finance::vesting::VestingComponent; -``` - -Vesting component implementing the xref:IVesting[`IVesting`] interface. - -[.contract-index] -.Vesting Schedule Trait Implementations --- -.functions -* xref:#VestingComponent-calculate_vested_amount[`++calculate_vested_amount(self, token, total_allocation, -timestamp, start, duration, cliff)++`] --- - -[.contract-index#VestingComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#VestingComponent-Embeddable-Impls-VestingImpl] -.VestingImpl -* xref:#VestingComponent-start[`++start(self)++`] -* xref:#VestingComponent-cliff[`++cliff(self)++`] -* xref:#VestingComponent-duration[`++duration(self)++`] -* xref:#VestingComponent-end[`++end(self)++`] -* xref:#VestingComponent-released[`++released(self, token)++`] -* xref:#VestingComponent-releasable[`++releasable(self, token)++`] -* xref:#VestingComponent-vested_amount[`++vested_amount(self, token, timestamp)++`] -* xref:#VestingComponent-release[`++release(self, token)++`] --- - -[.contract-index] -.Internal implementations --- -.InternalImpl -* xref:#VestingComponent-initializer[`++initializer(self, start, duration, cliff_duration)++`] -* xref:#VestingComponent-resolve_vested_amount[`++resolve_vested_amount(self, token, timestamp)++`] --- - -[#VestingComponent-Vesting-Schedule] -==== VestingSchedule trait - -A trait that defines the logic for calculating the vested amount based on a given timestamp. - -NOTE: You can read more about the trait's purpose and how to use it xref:finance.adoc#vesting_schedule[here]. - -[.contract-item] -[[VestingComponent-calculate_vested_amount]] -==== `[.contract-item-name]#++calculate_vested_amount++#++(self: @ContractState, token: ContractAddress, total_allocation: u256, timestamp: u64, start: u64, duration: u64, cliff: u64) → u256++` [.item-kind]#internal# - -Calculates and returns the vested amount at a given `timestamp` based on the core vesting parameters. - -[#VestingComponent-Functions] -==== Functions - -[.contract-item] -[[VestingComponent-start]] -==== `[.contract-item-name]#++start++#++(self: @ContractState) → u64++` [.item-kind]#external# - -Returns the timestamp marking the beginning of the vesting period. - -[.contract-item] -[[VestingComponent-cliff]] -==== `[.contract-item-name]#++cliff++#++(self: @ContractState) → u64++` [.item-kind]#external# - -Returns the timestamp marking the end of the cliff period. - -[.contract-item] -[[VestingComponent-duration]] -==== `[.contract-item-name]#++duration++#++(self: @ContractState) → u64++` [.item-kind]#external# - -Returns the total duration of the vesting period. - -[.contract-item] -[[VestingComponent-end]] -==== `[.contract-item-name]#++end++#++(self: @ContractState) → u64++` [.item-kind]#external# - -Returns the timestamp marking the end of the vesting period. - -[.contract-item] -[[VestingComponent-released]] -==== `[.contract-item-name]#++released++#++(self: @ContractState, token: ContractAddress) → u256++` [.item-kind]#external# - -Returns the already released amount for a given `token`. - -[.contract-item] -[[VestingComponent-releasable]] -==== `[.contract-item-name]#++releasable++#++(self: @ContractState, token: ContractAddress) → u256++` [.item-kind]#external# - -Returns the amount of a given `token` that can be released at the time of the call. - -[.contract-item] -[[VestingComponent-vested_amount]] -==== `[.contract-item-name]#++vested_amount++#++(self: @ContractState, token: ContractAddress, timestamp: u64) → u256++` [.item-kind]#external# - -Returns the total vested amount of a specified `token` at a given `timestamp`. - -[.contract-item] -[[VestingComponent-release]] -==== `[.contract-item-name]#++release++#++(ref self: ContractState, token: ContractAddress) → u256++` [.item-kind]#external# - -Releases the amount of a given `token` that has already vested and returns that amount. - -NOTE: If the releasable amount is zero, this function won't emit the event -or attempt to transfer the tokens. - -Requirements: - -- `transfer` call to the `token` must return `true` indicating a successful transfer. - -May emit an {AmountReleased} event. - -[#VestingComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[VestingComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, start: u64, duration: u64, cliff_duration: u64)++` [.item-kind]#internal# - -Initializes the component by setting the vesting `start`, `duration` and `cliff_duration`. To prevent -reinitialization, this should only be used inside of a contract's constructor. - -Requirements: - -- `cliff_duration` must be less than or equal to `duration`. - -[.contract-item] -[[VestingComponent-resolve_vested_amount]] -==== `[.contract-item-name]#++resolve_vested_amount++#++(self: @ContractState, token: ContractAddress, timestamp: u64) → u256++` [.item-kind]#internal# - -Returns the vested amount that's calculated using the {vesting-schedule} trait implementation. - -[.contract] -[[LinearVestingSchedule]] -=== `++LinearVestingSchedule++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/finance/src/vesting/vesting.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_finance::vesting::LinearVestingSchedule; -``` - -Defines the logic for calculating the vested amount, incorporating a cliff period. -It returns 0 before the cliff ends. After the cliff period, the vested amount returned -is directly proportional to the time passed since the start of the vesting schedule. - -== Presets - -[.contract] -[[VestingWallet]] -=== `++VestingWallet++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/presets/src/vesting.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin::presets::VestingWallet; -``` - -A non-upgradable contract leveraging {vesting-component} and {ownable-component}. - -NOTE: The contract is intentionally designed to be non-upgradable to ensure that neither the vesting initiator -nor the vesting beneficiary can modify the vesting schedule without the consent of the other party. - -include::../utils/_class_hashes.adoc[] - -[.contract-index] -.{presets-page} --- -{VestingWallet-class-hash} --- - -[.contract-index] -.Constructor --- -* xref:#VestingWallet-constructor[`++constructor(self, beneficiary, start, duration, cliff_duration)++`] --- - -[.contract-index] -.Embedded Implementations --- -.VestingComponent - -* xref:#VestingComponent-Embeddable-Impls-VestingImpl[`++VestingImpl++`] - -.OwnableComponent - -* xref:/api/access.adoc#OwnableComponent-Mixin-Impl[`++OwnableMixinImpl++`] --- - -[#VestingWallet-constructor-section] -==== Constructor - -[.contract-item] -[[VestingWallet-constructor]] -==== `[.contract-item-name]#++constructor++#++(ref self: ContractState, beneficiary: ContractAddress, start: u64, duration: u64, cliff_duration: u64)++` [.item-kind]#constructor# - -Initializes the vesting component by setting the vesting `start`, `duration` and `cliff_duration`. Assigns `beneficiary` as the contract owner and the vesting beneficiary. - -Requirements: - -- `cliff_duration` must be less than or equal to `duration`. diff --git a/docs/modules/ROOT/pages/api/governance.adoc b/docs/modules/ROOT/pages/api/governance.adoc deleted file mode 100644 index 79dbdf0ad..000000000 --- a/docs/modules/ROOT/pages/api/governance.adoc +++ /dev/null @@ -1,3794 +0,0 @@ -:github-icon: pass:[] -:IAccessControl-RoleGranted: xref:api/access.adoc#IAccessControl-RoleGranted[IAccessControl::RoleGranted] -:VotesComponent-DelegateChanged: xref:VotesComponent-DelegateChanged[DelegateChanged] -:VotesComponent-DelegateVotesChanged: xref:VotesComponent-DelegateVotesChanged[DelegateVotesChanged] -:VotingUnitsTrait: xref:VotingUnitsTrait[VotingUnitsTrait] -:VotesComponent: xref:VotesComponent[VotesComponent] -:IVotes: xref:IVotes[IVotes] -:governor: xref:governance/governor.adoc[Governor] -:inner-src5: xref:api/introspection.adoc#ISRC5[SRC5 ID] -:GovernorComponent: xref:#GovernorComponent[GovernorComponent] -:TimelockControllerComponent: xref:#TimelockControllerComponent[TimelockControllerComponent] -:ERC-6372: https://eips.ethereum.org/EIPS/eip-6372[ERC-6372] -:ERC-6372-clock: https://eips.ethereum.org/EIPS/eip-6372#clock[ERC-6372#clock] -:ERC-6372-clock-mode: https://eips.ethereum.org/EIPS/eip-6372#clock_mode[ERC-6372#CLOCK_MODE] -:SNIP-12: https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-12.md[SNIP-12] - -= Governance - -include::../utils/_common.adoc[] - -This crate includes primitives for on-chain governance. - -== Interfaces - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_governance` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[IGovernor]] -=== `++IGovernor++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/governance/governor.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::governor::IGovernor; -``` - -Interface of a governor contract. - -[.contract-index] -.{inner-src5} --- -0x1100a1f8546595b5bd75a6cd8fcc5b015370655e66f275963321c5cd0357ac9 --- - -[.contract-index] -.Functions --- -* xref:#IGovernor-name[`++name()++`] -* xref:#IGovernor-version[`++version()++`] -* xref:#IGovernor-COUNTING_MODE[`++COUNTING_MODE()++`] -* xref:#IGovernor-hash_proposal[`++hash_proposal(calls, description_hash)++`] -* xref:#IGovernor-state[`++state(proposal_id)++`] -* xref:#IGovernor-proposal_threshold[`++proposal_threshold()++`] -* xref:#IGovernor-proposal_snapshot[`++proposal_snapshot(proposal_id)++`] -* xref:#IGovernor-proposal_deadline[`++proposal_deadline(proposal_id)++`] -* xref:#IGovernor-proposal_proposer[`++proposal_proposer(proposal_id)++`] -* xref:#IGovernor-proposal_eta[`++proposal_eta(proposal_id)++`] -* xref:#IGovernor-proposal_needs_queuing[`++proposal_needs_queuing(proposal_id)++`] -* xref:#IGovernor-voting_delay[`++voting_delay()++`] -* xref:#IGovernor-voting_period[`++voting_period()++`] -* xref:#IGovernor-quorum[`++quorum(timepoint)++`] -* xref:#IGovernor-get_votes[`++get_votes(account, timepoint)++`] -* xref:#IGovernor-get_votes_with_params[`++get_votes_with_params(account, timepoint, params)++`] -* xref:#IGovernor-has_voted[`++has_voted(proposal_id, account)++`] -* xref:#IGovernor-propose[`++propose(calls, description)++`] -* xref:#IGovernor-queue[`++queue(calls, description_hash)++`] -* xref:#IGovernor-execute[`++execute(calls, description_hash)++`] -* xref:#IGovernor-cancel[`++cancel(proposal_id, description_hash)++`] -* xref:#IGovernor-cast_vote[`++cast_vote(proposal_id, support)++`] -* xref:#IGovernor-cast_vote_with_reason[`++cast_vote_with_reason(proposal_id, support, reason)++`] -* xref:#IGovernor-cast_vote_with_reason_and_params[`++cast_vote_with_reason_and_params(proposal_id, support, reason, params)++`] -* xref:#IGovernor-cast_vote_by_sig[`++cast_vote_by_sig(proposal_id, support, reason, signature)++`] -* xref:#IGovernor-cast_vote_with_reason_and_params_by_sig[`++cast_vote_with_reason_and_params_by_sig(proposal_id, support, reason, params, signature)++`] -* xref:#IGovernor-nonces[`++nonces(voter)++`] -* xref:#IGovernor-relay[`++relay(call)++`] --- - -[.contract-index] -.Events --- -* xref:#IGovernor-ProposalCreated[`++ProposalCreated(proposal_id, proposer, calls, signatures, vote_start, vote_end, description)++`] -* xref:#IGovernor-ProposalQueued[`++ProposalQueued(proposal_id, eta_seconds)++`] -* xref:#IGovernor-ProposalExecuted[`++ProposalExecuted(proposal_id)++`] -* xref:#IGovernor-ProposalCanceled[`++ProposalCanceled(proposal_id)++`] -* xref:#IGovernor-VoteCast[`++VoteCast(voter, proposal_id, support, weight, reason)++`] -* xref:#IGovernor-VoteCastWithParams[`++VoteCastWithParams(voter, proposal_id, support, weight, reason, params)++`] --- - -[#IGovernor-Functions] -==== Functions - -[.contract-item] -[[IGovernor-name]] -==== `[.contract-item-name]#++name++#++() → felt252++` [.item-kind]#external# - -Name of the governor instance (used in building the {SNIP-12} domain separator). - -[.contract-item] -[[IGovernor-version]] -==== `[.contract-item-name]#++version++#++() → felt252++` [.item-kind]#external# - -Version of the governor instance (used in building {SNIP-12} domain separator). - -[.contract-item] -[[IGovernor-COUNTING_MODE]] -==== `[.contract-item-name]#++COUNTING_MODE++#++() → ByteArray++` [.item-kind]#external# - -A description of the possible `support` values for `cast_vote` and the way these votes are counted, meant to be consumed by UIs -to show correct vote options and interpret the results. The string is a URL-encoded sequence of key-value pairs -that each describe one aspect, for example `support=bravo&quorum=for,abstain`. - -There are 2 standard keys: `support` and `quorum`. - -- `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in -`GovernorBravo`. -- `quorum=bravo` means that only For votes are counted towards quorum. -- `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum. - -If a counting module makes use of encoded `params`, it should include this under a `params` -key with a unique name that describes the behavior. For example: - -- `params=fractional` might refer to a scheme where votes are divided fractionally between -for/against/abstain. -- `params=erc721` might refer to a scheme where specific NFTs are delegated to vote. - -NOTE: The string can be decoded by the standard https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`] -JavaScript class. - -[.contract-item] -[[IGovernor-hash_proposal]] -==== `[.contract-item-name]#++hash_proposal++#++(calls: Span, description_hash: felt252) → felt252++` [.item-kind]#external# - -Hashing function used to (re)build the proposal id from the proposal details. - -[.contract-item] -[[IGovernor-state]] -==== `[.contract-item-name]#++state++#++(proposal_id: felt252) → ProposalState++` [.item-kind]#external# - -Returns the state of a proposal, given its id. - -[.contract-item] -[[IGovernor-proposal_threshold]] -==== `[.contract-item-name]#++proposal_threshold++#++() → u256++` [.item-kind]#external# - -The number of votes required in order for a voter to become a proposer. - -[.contract-item] -[[IGovernor-proposal_snapshot]] -==== `[.contract-item-name]#++proposal_snapshot++#++(proposal_id: felt252) → u64++` [.item-kind]#external# - -Timepoint used to retrieve user's votes and quorum. If using block number, the snapshot is performed at the -end of this block. Hence, voting for this proposal starts at the beginning of the following block. - -[.contract-item] -[[IGovernor-proposal_deadline]] -==== `[.contract-item-name]#++proposal_deadline++#++(proposal_id: felt252) → u64++` [.item-kind]#external# - -Timepoint at which votes close. If using block number, votes close at the end of this block, so -it is possible to cast a vote during this block. - -[.contract-item] -[[IGovernor-proposal_proposer]] -==== `[.contract-item-name]#++proposal_proposer++#++(proposal_id: felt252) → ContractAddress++` [.item-kind]#external# - -The account that created a proposal. - -[.contract-item] -[[IGovernor-proposal_eta]] -==== `[.contract-item-name]#++proposal_eta++#++(proposal_id: felt252) → u64++` [.item-kind]#external# - -The time when a queued proposal becomes executable ("ETA"). Unlike `proposal_snapshot` and -`proposal_deadline`, this doesn't use the governor clock, and instead relies on the -executor's clock which may be different. In most cases this will be a timestamp. - -[.contract-item] -[[IGovernor-proposal_needs_queuing]] -==== `[.contract-item-name]#++proposal_needs_queuing++#++(proposal_id: felt252) → bool++` [.item-kind]#external# - -Whether a proposal needs to be queued before execution. This indicates if the proposal needs to go through a timelock. - -[.contract-item] -[[IGovernor-voting_delay]] -==== `[.contract-item-name]#++voting_delay++#++() → u64++` [.item-kind]#external# - -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}) 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. - -[.contract-item] -[[IGovernor-voting_period]] -==== `[.contract-item-name]#++voting_period++#++() → u64++` [.item-kind]#external# - -Delay between when a vote starts and when it ends. The unit this duration is expressed in depends on -the clock (see {ERC-6372}) this contract uses. - -NOTE: The `voting_delay` can delay the start of the vote. This must be considered when -setting the voting duration compared to the voting delay. - -NOTE: This value is stored when the proposal is submitted so that possible changes to the -value do not affect proposals that have already been submitted. - -[.contract-item] -[[IGovernor-quorum]] -==== `[.contract-item-name]#++quorum++#++(timepoint: u64) → u256++` [.item-kind]#external# - -Minimum number of votes required for a proposal to be successful. - -NOTE: The `timepoint` parameter corresponds to the snapshot used for counting vote. This -allows the quorum to scale depending on values such as the total supply of a token at this -timepoint. - -[.contract-item] -[[IGovernor-get_votes]] -==== `[.contract-item-name]#++get_votes++#++(account: ContractAddress, timepoint: u64) → u256++` [.item-kind]#external# - -Returns the voting power of an `account` at a specific `timepoint`. - -NOTE: This can be implemented in a number of ways, for example by reading the delegated -balance from one (or multiple) `ERC20Votes` tokens. - -[.contract-item] -[[IGovernor-get_votes_with_params]] -==== `[.contract-item-name]#++get_votes_with_params++#++(account: ContractAddress, timepoint: u64, params: Span) → u256++` [.item-kind]#external# - -Returns the voting power of an `account` at a specific `timepoint`, given additional encoded parameters. - -[.contract-item] -[[IGovernor-has_voted]] -==== `[.contract-item-name]#++has_voted++#++(proposal_id: felt252, account: ContractAddress) → bool++` [.item-kind]#external# - -Returns whether an `account` has cast a vote on a proposal. - -[.contract-item] -[[IGovernor-propose]] -==== `[.contract-item-name]#++propose++#++(calls: Span, description: ByteArray) → felt252++` [.item-kind]#external# - -Creates a new proposal. Vote starts after a delay specified by `voting_delay` and lasts for a duration specified by `voting_period`. - -NOTE: The state of the Governor and targets may change between the proposal creation and its execution. -This may be the result of third party actions on the targeted contracts, or other governor proposals. -For example, the balance of this contract could be updated or its access control permissions may be -modified, possibly compromising the proposal's ability to execute successfully (e.g. the governor -doesn't have enough value to cover a proposal with multiple transfers). - -Returns the id of the proposal. - -[.contract-item] -[[IGovernor-queue]] -==== `[.contract-item-name]#++queue++#++(calls: Span, description_hash: felt252) → felt252++` [.item-kind]#external# - -Queue a proposal. Some governors require this step to be performed before execution can -happen. If queuing is not necessary, this function may revert. - -Queuing a proposal requires the quorum to be reached, the vote to be successful, and the -deadline to be reached. - -Returns the id of the proposal. - -[.contract-item] -[[IGovernor-execute]] -==== `[.contract-item-name]#++execute++#++(calls: span, description_hash: felt252) → felt252++` [.item-kind]#external# - -Execute a successful proposal. This requires the quorum to be reached, the vote to be -successful, and the deadline to be reached. Depending on the governor it might also be -required that the proposal was queued and that some delay passed. - -NOTE: Some modules can modify the requirements for execution, for example by adding an -additional timelock (See `timelock_controller`). - -Returns the id of the proposal. - -[.contract-item] -[[IGovernor-cancel]] -==== `[.contract-item-name]#++cancel++#++(calls: Span, description_hash: felt252) → felt252++` [.item-kind]#external# - -Cancel a proposal. A proposal is cancellable by the proposer, but only while it is Pending -state, i.e. before the vote starts. - -Returns the id of the proposal. - -[.contract-item] -[[IGovernor-cast_vote]] -==== `[.contract-item-name]#++cast_vote++#++(proposal_id: felt252, support: u8) → u256++` [.item-kind]#external# - -Cast a vote on a proposal. - -Returns the weight of the vote. - -[.contract-item] -[[IGovernor-cast_vote_with_reason]] -==== `[.contract-item-name]#++cast_vote_with_reason++#++(proposal_id: felt252, support: u8, reason: ByteArray) → u256++` [.item-kind]#external# - -Cast a vote on a proposal with a `reason`. - -Returns the weight of the vote. - -[.contract-item] -[[IGovernor-cast_vote_with_reason_and_params]] -==== `[.contract-item-name]#++cast_vote_with_reason_and_params++#++(proposal_id: felt252, support: u8, reason: ByteArray, params: Span) → u256++` [.item-kind]#external# - -Cast a vote on a proposal with a reason and additional encoded parameters. - -Returns the weight of the vote. - -[.contract-item] -[[IGovernor-cast_vote_by_sig]] -==== `[.contract-item-name]#++cast_vote_by_sig++#++(proposal_id: felt252, support: u8, voter: ContractAddress, signature: Span) → u256++` [.item-kind]#external# - -Cast a vote on a proposal using the voter's signature. - -Returns the weight of the vote. - -[.contract-item] -[[IGovernor-cast_vote_with_reason_and_params_by_sig]] -==== `[.contract-item-name]#++cast_vote_with_reason_and_params_by_sig++#++(proposal_id: felt252, support: u8, voter: ContractAddress, reason: ByteArray, params: Span, signature: Span) → u256++` [.item-kind]#external# - -Cast a vote on a proposal with a reason and additional encoded parameters using the ``voter``'s signature. - -Returns the weight of the vote. - -[.contract-item] -[[IGovernor-nonces]] -==== `[.contract-item-name]#++nonces++#++(voter: ContractAddress) → felt252++` [.item-kind]#external# - -Returns the next unused nonce for an address. - -[.contract-item] -[[IGovernor-relay]] -==== `[.contract-item-name]#++relay++#++(call: Call)++` [.item-kind]#external# - -Relays a transaction or function call to an arbitrary target. - -In cases where the governance executor is some contract other than the governor itself, like -when using a timelock, this function can be invoked in a governance proposal to recover -tokens that were sent to the governor contract by mistake. - -NOTE: If the executor is simply the governor itself, use of `relay` is redundant. - -[#IGovernor-Events] -==== Events - -[.contract-item] -[[IGovernor-ProposalCreated]] -==== `[.contract-item-name]#++ProposalCreated++#++(proposal_id: felt252, proposer: ContractAddress, calls: Span, signatures: Span>, vote_start: u64, vote_end: u64, description: ByteArray)++` [.item-kind]#event# - -Emitted when a proposal is created. - -[.contract-item] -[[IGovernor-ProposalQueued]] -==== `[.contract-item-name]#++ProposalQueued++#++(proposal_id: felt252, eta_seconds: u64)++` [.item-kind]#event# - -Emitted when a proposal is queued. - -[.contract-item] -[[IGovernor-ProposalExecuted]] -==== `[.contract-item-name]#++ProposalExecuted++#++(proposal_id: felt252)++` [.item-kind]#event# - -Emitted when a proposal is executed. - -[.contract-item] -[[IGovernor-ProposalCanceled]] -==== `[.contract-item-name]#++ProposalCanceled++#++(proposal_id: felt252)++` [.item-kind]#event# - -Emitted when a proposal is canceled. - -[.contract-item] -[[IGovernor-VoteCast]] -==== `[.contract-item-name]#++VoteCast++#++(voter: ContractAddress, proposal_id: felt252, support: u8, weight: u256, reason: ByteArray)++` [.item-kind]#event# - -Emitted when a vote is cast. - -[.contract-item] -[[IGovernor-VoteCastWithParams]] -==== `[.contract-item-name]#++VoteCastWithParams++#++(voter: ContractAddress, proposal_id: felt252, support: u8, weight: u256, reason: ByteArray, params: Span)++` [.item-kind]#event# - -Emitted when a vote is cast with params. - -[.contract] -[[IMultisig]] -=== `++IMultisig++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/governance/multisig.cairo[{github-icon},role=heading-link] - -:IMultisig-CallSalt: xref:IMultisig-CallSalt[CallSalt] -:IMultisig-SignerAdded: xref:IMultisig-SignerAdded[SignerAdded] -:IMultisig-SignerRemoved: xref:IMultisig-SignerRemoved[SignerRemoved] -:IMultisig-QuorumUpdated: xref:IMultisig-QuorumUpdated[QuorumUpdated] -:IMultisig-TransactionSubmitted: xref:IMultisig-TransactionSubmitted[TransactionSubmitted] -:IMultisig-TransactionConfirmed: xref:IMultisig-TransactionConfirmed[TransactionConfirmed] -:IMultisig-ConfirmationRevoked: xref:IMultisig-ConfirmationRevoked[ConfirmationRevoked] -:IMultisig-TransactionExecuted: xref:IMultisig-TransactionExecuted[TransactionExecuted] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::multisig::IMultisig; -``` - -Interface of a multisig contract. - -[.contract-index] -.Functions --- -* xref:#IMultisig-get_quorum[`++get_quorum()++`] -* xref:#IMultisig-is_signer[`++is_signer(signer)++`] -* xref:#IMultisig-get_signers[`++get_signers()++`] -* xref:#IMultisig-is_confirmed[`++is_confirmed(id)++`] -* xref:#IMultisig-is_confirmed_by[`++is_confirmed_by(id, signer)++`] -* xref:#IMultisig-is_executed[`++is_executed(id)++`] -* xref:#IMultisig-get_submitted_block[`++get_submitted_block(id)++`] -* xref:#IMultisig-get_transaction_state[`++get_transaction_state(id)++`] -* xref:#IMultisig-get_transaction_confirmations[`++get_transaction_confirmations(id)++`] -* xref:#IMultisig-hash_transaction[`++hash_transaction(to, selector, calldata, salt)++`] -* xref:#IMultisig-hash_transaction_batch[`++hash_transaction_batch(calls, salt)++`] -* xref:#IMultisig-add_signers[`++add_signers(new_quorum, signers_to_add)++`] -* xref:#IMultisig-remove_signers[`++remove_signers(new_quorum, signers_to_remove)++`] -* xref:#IMultisig-replace_signer[`++replace_signer(signer_to_remove, signer_to_add)++`] -* xref:#IMultisig-change_quorum[`++change_quorum(new_quorum)++`] -* xref:#IMultisig-submit_transaction[`++submit_transaction(to, selector, calldata, salt)++`] -* xref:#IMultisig-submit_transaction_batch[`++submit_transaction_batch(calls, salt)++`] -* xref:#IMultisig-confirm_transaction[`++confirm_transaction(id)++`] -* xref:#IMultisig-revoke_confirmation[`++revoke_confirmation(id)++`] -* xref:#IMultisig-execute_transaction[`++execute_transaction(to, selector, calldata, salt)++`] -* xref:#IMultisig-execute_transaction_batch[`++execute_transaction_batch(calls, salt)++`] --- - -[.contract-index] -.Events --- -* xref:#IMultisig-SignerAdded[`++SignerAdded(signer)++`] -* xref:#IMultisig-SignerRemoved[`++SignerRemoved(signer)++`] -* xref:#IMultisig-QuorumUpdated[`++QuorumUpdated(old_quorum, new_quorum)++`] -* xref:#IMultisig-TransactionSubmitted[`++TransactionSubmitted(id, signer)++`] -* xref:#IMultisig-TransactionConfirmed[`++TransactionConfirmed(id, signer)++`] -* xref:#IMultisig-ConfirmationRevoked[`++ConfirmationRevoked(id, signer)++`] -* xref:#IMultisig-TransactionExecuted[`++TransactionExecuted(id)++`] -* xref:#IMultisig-CallSalt[`++CallSalt(id, salt)++`] --- - -[#IMultisig-Functions] -==== Functions - -[.contract-item] -[[IMultisig-get_quorum]] -==== `[.contract-item-name]#++get_quorum++#++() → u32++` [.item-kind]#external# - -Returns the current quorum value. The quorum is the minimum number of confirmations required to approve a transaction. - -[.contract-item] -[[IMultisig-is_signer]] -==== `[.contract-item-name]#++is_signer++#++(signer: ContractAddress) → bool++` [.item-kind]#external# - -Returns whether the given `signer` is registered. Only registered signers can submit, confirm, or execute transactions. - -[.contract-item] -[[IMultisig-get_signers]] -==== `[.contract-item-name]#++get_signers++#++() → Span++` [.item-kind]#external# - -Returns the list of all current signers. - -[.contract-item] -[[IMultisig-is_confirmed]] -==== `[.contract-item-name]#++is_confirmed++#++(id: TransactionID) → bool++` [.item-kind]#external# - -Returns whether the transaction with the given `id` has been confirmed. - -[.contract-item] -[[IMultisig-is_confirmed_by]] -==== `[.contract-item-name]#++is_confirmed_by++#++(id: TransactionID, signer: ContractAddress) → bool++` [.item-kind]#external# - -Returns whether the transaction with the given `id` has been confirmed by the specified `signer`. - -[.contract-item] -[[IMultisig-is_executed]] -==== `[.contract-item-name]#++is_executed++#++(id: TransactionID) → bool++` [.item-kind]#external# - -Returns whether the transaction with the given `id` has been executed. - -[.contract-item] -[[IMultisig-get_submitted_block]] -==== `[.contract-item-name]#++get_submitted_block++#++(id: TransactionID) → u64++` [.item-kind]#external# - -Returns the block number when the transaction with the given `id` was submitted. - -[.contract-item] -[[IMultisig-get_transaction_state]] -==== `[.contract-item-name]#++get_transaction_state++#++(id: TransactionID) → TransactionState++` [.item-kind]#external# - -Returns the current state of the transaction with the given `id`. - -[.contract-item] -[[IMultisig-get_transaction_confirmations]] -==== `[.contract-item-name]#++get_transaction_confirmations++#++(id: TransactionID) → u32++` [.item-kind]#external# - -Returns the number of confirmations from registered signers for the transaction with the specified `id`. - -[.contract-item] -[[IMultisig-hash_transaction]] -==== `[.contract-item-name]#++hash_transaction++#++(to: ContractAddress, selector: felt252, calldata: Span, salt: felt252) → TransactionID++` [.item-kind]#external# - -Returns the computed identifier of a transaction containing a single call. - -[.contract-item] -[[IMultisig-hash_transaction_batch]] -==== `[.contract-item-name]#++hash_transaction_batch++#++(calls: Span, salt: felt252) → TransactionID++` [.item-kind]#external# - -Returns the computed identifier of a transaction containing a batch of calls. - -[.contract-item] -[[IMultisig-add_signers]] -==== `[.contract-item-name]#++add_signers++#++(new_quorum: u32, signers_to_add: Span)++` [.item-kind]#external# - -Adds new signers and updates the quorum. - -Requirements: - -- The caller must be the contract itself. -- `new_quorum` must be less than or equal to the total number of signers after addition. - -Emits a {IMultisig-SignerAdded} event for each signer added. - -Emits a {IMultisig-QuorumUpdated} event if the quorum changes. - -[.contract-item] -[[IMultisig-remove_signers]] -==== `[.contract-item-name]#++remove_signers++#++(new_quorum: u32, signers_to_remove: Span)++` [.item-kind]#external# - -Removes signers and updates the quorum. - -Requirements: - -- The caller must be the contract itself. -- `new_quorum` must be less than or equal to the total number of signers after removal. - -Emits a {IMultisig-SignerRemoved} event for each signer removed. - -Emits a {IMultisig-QuorumUpdated} event if the quorum changes. - -[.contract-item] -[[IMultisig-replace_signer]] -==== `[.contract-item-name]#++replace_signer++#++(signer_to_remove: ContractAddress, signer_to_add: ContractAddress)++` [.item-kind]#external# - -Replaces an existing signer with a new signer. - -Requirements: - -- The caller must be the contract itself. -- `signer_to_remove` must be an existing signer. -- `signer_to_add` must not be an existing signer. - -Emits a {IMultisig-SignerRemoved} event for the removed signer. - -Emits a {IMultisig-SignerAdded} event for the new signer. - -[.contract-item] -[[IMultisig-change_quorum]] -==== `[.contract-item-name]#++change_quorum++#++(new_quorum: u32)++` [.item-kind]#external# - -Updates the quorum value to `new_quorum` if it differs from the current quorum. - -Requirements: - -- The caller must be the contract itself. -- `new_quorum` must be non-zero. -- `new_quorum` must be less than or equal to the total number of signers. - -Emits a {IMultisig-QuorumUpdated} event if the quorum changes. - -[.contract-item] -[[IMultisig-submit_transaction]] -==== `[.contract-item-name]#++submit_transaction++#++(to: ContractAddress, selector: felt252, calldata: Span, salt: felt252) → TransactionID++` [.item-kind]#external# - -Submits a new transaction for confirmation. - -Requirements: - -- The caller must be a registered signer. -- The transaction must not have been submitted before. - -Emits a {IMultisig-TransactionSubmitted} event. - -Emits a {IMultisig-CallSalt} event if `salt` is not zero. - -[.contract-item] -[[IMultisig-submit_transaction_batch]] -==== `[.contract-item-name]#++submit_transaction_batch++#++(calls: Span, salt: felt252) → TransactionID++` [.item-kind]#external# - -Submits a new batch transaction for confirmation. - -Requirements: - -- The caller must be a registered signer. -- The transaction must not have been submitted before. - -Emits a {IMultisig-TransactionSubmitted} event. - -Emits a {IMultisig-CallSalt} event if `salt` is not zero. - -[.contract-item] -[[IMultisig-confirm_transaction]] -==== `[.contract-item-name]#++confirm_transaction++#++(id: TransactionID)++` [.item-kind]#external# - -Confirms a transaction with the given `id`. - -Requirements: - -- The caller must be a registered signer. -- The transaction must exist and not be executed. -- The caller must not have already confirmed the transaction. - -Emits a {IMultisig-TransactionConfirmed} event. - -[.contract-item] -[[IMultisig-revoke_confirmation]] -==== `[.contract-item-name]#++revoke_confirmation++#++(id: TransactionID)++` [.item-kind]#external# - -Revokes a previous confirmation for a transaction with the given `id`. - -Requirements: - -- The transaction must exist and not be executed. -- The caller must have previously confirmed the transaction. - -Emits a {IMultisig-ConfirmationRevoked} event. - -[.contract-item] -[[IMultisig-execute_transaction]] -==== `[.contract-item-name]#++execute_transaction++#++(to: ContractAddress, selector: felt252, calldata: Span, salt: felt252)++` [.item-kind]#external# - -Executes a confirmed transaction. - -Requirements: - -- The caller must be a registered signer. -- The transaction must be confirmed and not yet executed. - -Emits a {IMultisig-TransactionExecuted} event. - -[.contract-item] -[[IMultisig-execute_transaction_batch]] -==== `[.contract-item-name]#++execute_transaction_batch++#++(calls: Span, salt: felt252)++` [.item-kind]#external# - -Executes a confirmed batch transaction. - -Requirements: - -- The caller must be a registered signer. -- The transaction must be confirmed and not yet executed. - -Emits a {IMultisig-TransactionExecuted} event. - -[#IMultisig-Events] -==== Events - -[.contract-item] -[[IMultisig-SignerAdded]] -==== `[.contract-item-name]#++SignerAdded++#++(signer: ContractAddress)++` [.item-kind]#event# - -Emitted when a new `signer` is added. - -[.contract-item] -[[IMultisig-SignerRemoved]] -==== `[.contract-item-name]#++SignerRemoved++#++(signer: ContractAddress)++` [.item-kind]#event# - -Emitted when a `signer` is removed. - -[.contract-item] -[[IMultisig-QuorumUpdated]] -==== `[.contract-item-name]#++QuorumUpdated++#++(old_quorum: u32, new_quorum: u32)++` [.item-kind]#event# - -Emitted when the `quorum` value is updated. - -[.contract-item] -[[IMultisig-TransactionSubmitted]] -==== `[.contract-item-name]#++TransactionSubmitted++#++(id: TransactionID, signer: ContractAddress)++` [.item-kind]#event# - -Emitted when a new transaction is submitted by a `signer`. - -[.contract-item] -[[IMultisig-TransactionConfirmed]] -==== `[.contract-item-name]#++TransactionConfirmed++#++(id: TransactionID, signer: ContractAddress)++` [.item-kind]#event# - -Emitted when a transaction is confirmed by a `signer`. - -[.contract-item] -[[IMultisig-ConfirmationRevoked]] -==== `[.contract-item-name]#++ConfirmationRevoked++#++(id: TransactionID, signer: ContractAddress)++` [.item-kind]#event# - -Emitted when a `signer` revokes his confirmation. - -[.contract-item] -[[IMultisig-TransactionExecuted]] -==== `[.contract-item-name]#++TransactionExecuted++#++(id: TransactionID)++` [.item-kind]#event# - -Emitted when a transaction is executed. - -[.contract-item] -[[IMultisig-CallSalt]] -==== `[.contract-item-name]#++CallSalt++#++(id: felt252, salt: felt252)++` [.item-kind]#event# - -Emitted when a new transaction is submitted with non-zero salt. - -[.contract] -[[ITimelock]] -=== `++ITimelock++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/governance/timelock.cairo[{github-icon},role=heading-link] - -:ITimelock-CallScheduled: xref:ITimelock-CallScheduled[CallScheduled] -:ITimelock-CallExecuted: xref:ITimelock-CallExecuted[CallExecuted] -:ITimelock-CallSalt: xref:ITimelock-CallSalt[CallSalt] -:ITimelock-CallCancelled: xref:ITimelock-CallCancelled[CallCancelled] -:ITimelock-MinDelayChanged: xref:ITimelock-MinDelayChanged[MinDelayChanged] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::timelock::ITimelock; -``` - -Interface of a timelock contract. - -[.contract-index] -.Functions --- -* xref:#ITimelock-is_operation[`++is_operation(id)++`] -* xref:#ITimelock-is_operation_pending[`++is_operation_pending(id)++`] -* xref:#ITimelock-is_operation_ready[`++is_operation_ready(id)++`] -* xref:#ITimelock-is_operation_done[`++is_operation_done(id)++`] -* xref:#ITimelock-get_timestamp[`++get_timestamp(id)++`] -* xref:#ITimelock-get_operation_state[`++get_operation_state(id)++`] -* xref:#ITimelock-get_min_delay[`++get_min_delay()++`] -* xref:#ITimelock-hash_operation[`++hash_operation(call, predecessor, salt)++`] -* xref:#ITimelock-hash_operation_batch[`++hash_operation_batch(calls, predecessor, salt)++`] -* xref:#ITimelock-schedule[`++schedule(call, predecessor, salt, delay)++`] -* xref:#ITimelock-schedule_batch[`++schedule_batch(calls, predecessor, salt, delay)++`] -* xref:#ITimelock-cancel[`++cancel(id)++`] -* xref:#ITimelock-execute[`++execute(call, predecessor, salt)++`] -* xref:#ITimelock-execute_batch[`++execute_batch(calls, predecessor, salt)++`] -* xref:#ITimelock-update_delay[`++update_delay(new_delay)++`] --- - -[.contract-index] -.Events --- -* xref:#ITimelock-CallScheduled[`++CallScheduled(id, index, call, predecessor, delay)++`] -* xref:#ITimelock-CallExecuted[`++CallExecuted(id, index, call)++`] -* xref:#ITimelock-CallSalt[`++CallSalt(id, salt)++`] -* xref:#ITimelock-CallCancelled[`++CallCancelled(id)++`] -* xref:#ITimelock-MinDelayChanged[`++MinDelayChanged(old_duration, new_duration)++`] --- - -[#ITimelock-Functions] -==== Functions - -[.contract-item] -[[ITimelock-is_operation]] -==== `[.contract-item-name]#++is_operation++#++(id: felt252) → bool++` [.item-kind]#external# - -Returns whether `id` corresponds to a registered operation. -This includes the OperationStates: `Waiting`, `Ready`, and `Done`. - -[.contract-item] -[[ITimelock-is_operation_pending]] -==== `[.contract-item-name]#++is_operation_pending++#++(id: felt252) → bool++` [.item-kind]#external# - -Returns whether the `id` OperationState is pending or not. -Note that a pending operation may be either `Waiting` or `Ready`. - -[.contract-item] -[[ITimelock-is_operation_ready]] -==== `[.contract-item-name]#++is_operation_ready++#++(id: felt252) → bool++` [.item-kind]#external# - -Returns whether the `id` OperationState is `Ready` or not. - -[.contract-item] -[[ITimelock-is_operation_done]] -==== `[.contract-item-name]#++is_operation_done++#++(id: felt252) → bool++` [.item-kind]#external# - -Returns whether the `id` OperationState is `Done` or not. - -[.contract-item] -[[ITimelock-get_timestamp]] -==== `[.contract-item-name]#++get_timestamp++#++(id: felt252) → u64++` [.item-kind]#external# - -Returns the timestamp at which `id` becomes `Ready`. - -NOTE: `0` means the OperationState is `Unset` and `1` means the OperationState -is `Done`. - -[.contract-item] -[[ITimelock-get_operation_state]] -==== `[.contract-item-name]#++get_operation_state++#++(id: felt252) → OperationState++` [.item-kind]#external# - -Returns the current state of the operation with the given `id`. - -The possible states are: - -- `Unset`: the operation has not been scheduled or has been canceled. -- `Waiting`: the operation has been scheduled and is pending the scheduled delay. -- `Ready`: the timer has expired, and the operation is eligible for execution. -- `Done`: the operation has been executed. - -[.contract-item] -[[ITimelock-get_min_delay]] -==== `[.contract-item-name]#++get_min_delay++#++() → u64++` [.item-kind]#external# - -Returns the minimum delay in seconds for an operation to become valid. -This value can be changed by executing an operation that calls `update_delay`. - -[.contract-item] -[[ITimelock-hash_operation]] -==== `[.contract-item-name]#++hash_operation++#++(call: Call, predecessor: felt252, salt: felt252)++` [.item-kind]#external# - -Returns the identifier of an operation containing a single transaction. - -[.contract-item] -[[ITimelock-hash_operation_batch]] -==== `[.contract-item-name]#++hash_operation_batch++#++(calls: Span, predecessor: felt252, salt: felt252)++` [.item-kind]#external# - -Returns the identifier of an operation containing a batch of transactions. - -[.contract-item] -[[ITimelock-schedule]] -==== `[.contract-item-name]#++schedule++#++(call: Call, predecessor: felt252, salt: felt252, delay: u64)++` [.item-kind]#external# - -Schedule an operation containing a single transaction. - -Requirements: - -- The caller must have the `PROPOSER_ROLE` role. - -Emits {ITimelock-CallScheduled} event. -Emits {ITimelock-CallSalt} event if `salt` is not zero. - -[.contract-item] -[[ITimelock-schedule_batch]] -==== `[.contract-item-name]#++schedule_batch++#++(calls: Span, predecessor: felt252, salt: felt252, delay: u64)++` [.item-kind]#external# - -Schedule an operation containing a batch of transactions. - -Requirements: - -- The caller must have the `PROPOSER_ROLE` role. - -Emits one {ITimelock-CallScheduled} event for each transaction in the batch. -Emits {ITimelock-CallSalt} event if `salt` is not zero. - -[.contract-item] -[[ITimelock-cancel]] -==== `[.contract-item-name]#++cancel++#++(id: felt252)++` [.item-kind]#external# - -Cancels an operation. A canceled operation returns to `Unset` OperationState. - -Requirements: - -- The caller must have the `CANCELLER_ROLE` role. -- `id` must be a pending operation. - -Emits a {ITimelock-CallCancelled} event. - -[.contract-item] -[[ITimelock-execute]] -==== `[.contract-item-name]#++execute++#++(call: Call, predecessor: felt252, salt: felt252)++` [.item-kind]#external# - -Execute a (Ready) operation containing a single Call. - -Requirements: - -- Caller must have `EXECUTOR_ROLE`. -- `id` must be in Ready OperationState. -- `predecessor` must either be `0` or in Done OperationState. - -Emits a {ITimelock-CallExecuted} event. - -NOTE: This function can reenter, but it doesn't pose a risk because <> -checks that the proposal is pending, thus any modifications to the operation during -reentrancy should be caught. - -[.contract-item] -[[ITimelock-execute_batch]] -==== `[.contract-item-name]#++execute_batch++#++(calls: Span, predecessor: felt252, salt: felt252)++` [.item-kind]#external# - -Execute a (Ready) operation containing a batch of Calls. - -Requirements: - -- Caller must have `EXECUTOR_ROLE`. -- `id` must be in Ready OperationState. -- `predecessor` must either be `0` or in Done OperationState. - -Emits a {ITimelock-CallExecuted} event for each Call. - -NOTE: This function can reenter, but it doesn't pose a risk because `_after_call` -checks that the proposal is pending, thus any modifications to the operation during -reentrancy should be caught. - -[.contract-item] -[[ITimelock-update_delay]] -==== `[.contract-item-name]#++update_delay++#++(new_delay: u64)++` [.item-kind]#external# - -Changes the minimum timelock duration for future operations. - -Requirements: - -- The caller must be the timelock itself. This can only be achieved by scheduling -and later executing an operation where the timelock is the target and the data -is the serialized call to this function. - -Emits a {ITimelock-MinDelayChanged} event. - -[#ITimelock-Events] -==== Events - -[.contract-item] -[[ITimelock-CallScheduled]] -==== `[.contract-item-name]#++CallScheduled++#++(id: felt252, index: felt252, call: Call, predecessor: felt252, delay: u64)++` [.item-kind]#event# - -Emitted when `call` is scheduled as part of operation `id`. - -[.contract-item] -[[ITimelock-CallExecuted]] -==== `[.contract-item-name]#++CallExecuted++#++(id: felt252, index: felt252, call: Call)++` [.item-kind]#event# - -Emitted when `call` is performed as part of operation `id`. - -[.contract-item] -[[ITimelock-CallSalt]] -==== `[.contract-item-name]#++CallSalt++#++(id: felt252, salt: felt252)++` [.item-kind]#event# - -Emitted when a new proposal is scheduled with non-zero salt. - -[.contract-item] -[[ITimelock-CallCancelled]] -==== `[.contract-item-name]#++CallCancelled++#++(id: felt252)++` [.item-kind]#event# - -Emitted when operation `id` is cancelled. - -[.contract-item] -[[ITimelock-MinDelayChanged]] -==== `[.contract-item-name]#++MinDelayChanged++#++(old_duration: u64, new_duration: u64)++` [.item-kind]#event# - -Emitted when the minimum delay for future operations is modified. - -[.contract] -[[IVotes]] -=== `++IVotes++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/governance/votes.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::votes::IVotes; -``` - -Common interface for Votes-enabled contracts. - -[.contract-index] -.Functions --- -* xref:#IVotes-get_votes[`++get_votes(account)++`] -* xref:#IVotes-get_past_votes[`++get_past_votes(account, timepoint)++`] -* xref:#IVotes-get_past_total_supply[`++get_past_total_supply(timepoint)++`] -* xref:#IVotes-delegates[`++delegates(account)++`] -* xref:#IVotes-delegate[`++delegate(delegatee)++`] -* xref:#IVotes-delegate_by_sig[`++delegate_by_sig(delegator, delegatee, nonce, expiry, signature)++`] -* xref:#IVotes-clock[`++clock()++`] -* xref:#IVotes-CLOCK_MODE[`++CLOCK_MODE()++`] --- - -[#IVotes-Functions] -==== Functions - -[.contract-item] -[[IVotes-get_votes]] -==== `[.contract-item-name]#++get_votes++#++(account: ContractAddress) → u256++` [.item-kind]#external# - -Returns the current amount of votes that `account` has. - -[.contract-item] -[[IVotes-get_past_votes]] -==== `[.contract-item-name]#++get_past_votes++#++(account: ContractAddress, timepoint: u64) → u256++` [.item-kind]#external# - -Returns the amount of votes that `account` had at a specific moment in the past. - -[.contract-item] -[[IVotes-get_past_total_supply]] -==== `[.contract-item-name]#++get_past_total_supply++#++(timepoint: u64) → u256++` [.item-kind]#external# - -Returns the total supply of votes available at a specific moment in the past. - -NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. -Votes that have not been delegated are still part of total supply, even though they would not participate in a -vote. - -[.contract-item] -[[IVotes-delegates]] -==== `[.contract-item-name]#++delegates++#++(account: ContractAddress) → ContractAddress++` [.item-kind]#external# - -Returns the delegate that `account` has chosen. - -[.contract-item] -[[IVotes-delegate]] -==== `[.contract-item-name]#++delegate++#++(delegatee: ContractAddress)++` [.item-kind]#external# - -Delegates votes from the sender to `delegatee`. - -[.contract-item] -[[IVotes-delegate_by_sig]] -==== `[.contract-item-name]#++delegate_by_sig++#++(delegator: ContractAddress, delegatee: ContractAddress, nonce: felt252, expiry: u64, signature: Span)++` [.item-kind]#external# - -Delegates votes from `delegator` to `delegatee` through a {SNIP-12} message signature validation. - -[.contract-item] -[[IVotes-clock]] -==== `[.contract-item-name]#++clock++#++() → u64++` [.item-kind]#external# - -Returns the current timepoint determined by the contract’s operational mode, intended for use in time-sensitive logic. -See {ERC-6372-clock}. - -Requirements: - -- This function MUST always be non-decreasing. - -[.contract-item] -[[IVotes-CLOCK_MODE]] -==== `[.contract-item-name]#++CLOCK_MODE++#++() → u64++` [.item-kind]#external# - -Returns a description of the clock the contract is operating in. -See {ERC-6372-clock-mode}. - -Requirements: - -- The output MUST be formatted like a URL query string, decodable in standard JavaScript. - -== Governor - -This modular system of Governor components allows the deployment of easily customizable on-chain voting protocols. - -TIP: For a walkthrough of how to implement a Governor, check the {governor} page. - -:ProposalCreated: xref:GovernorComponent-ProposalCreated[ProposalCreated] -:ProposalExecuted: xref:GovernorComponent-ProposalExecuted[ProposalExecuted] -:ProposalQueued: xref:GovernorComponent-ProposalQueued[ProposalQueued] -:ProposalCanceled: xref:GovernorComponent-ProposalCanceled[ProposalCanceled] -:VoteCast: xref:GovernorComponent-VoteCast[VoteCast] -:VoteCastWithParams: xref:GovernorComponent-VoteCastWithParams[VoteCastWithParams] -:component-extensions: xref:#governor_extensions[component extensions] - -[.contract] -[[GovernorComponent]] -=== `++GovernorComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/governance/src/governor/governor.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_governance::governor::GovernorComponent; -``` - -Core of the governance system. - -NOTE: The extension traits presented below are what make the GovernorComponent a modular and configurable system. The embeddable -and internal implementations depends on these trait. They can be implemented locally in the contract, or through the provided library -{component-extensions}. - -NOTE: {src5-component-required-note} - -[.contract-index#GovernorComponent-Extensions-Traits-Traits] -.Extensions traits --- -[.sub-index#GovernorComponent-Extensions-Traits-GovernorSettingsTrait] -.GovernorSettingsTrait - -* xref:#GovernorComponent-GovernorSettingsTrait-voting_delay[`++voting_delay(self)++`] -* xref:#GovernorComponent-GovernorSettingsTrait-voting_period[`++voting_period(self)++`] -* xref:#GovernorComponent-GovernorSettingsTrait-proposal_threshold[`++proposal_threshold(self)++`] - -[.sub-index#GovernorComponent-Extensions-Traits-GovernorQuorumTrait] -.GovernorQuorumTrait - -* xref:#GovernorComponent-GovernorQuorumTrait-quorum[`++quorum(self, timepoint)++`] - -[.sub-index#GovernorComponent-Extensions-Traits-GovernorCountingTrait] -.GovernorCountingTrait - -* xref:#GovernorComponent-GovernorCountingTrait-counting_mode[`++counting_mode(self)++`] -* xref:#GovernorComponent-GovernorCountingTrait-count_vote[`++count_vote(self, proposal_id, account, support, total_weight, params)++`] -* xref:#GovernorComponent-GovernorCountingTrait-has_voted[`++has_voted(self, proposal_id, account)++`] -* xref:#GovernorComponent-GovernorCountingTrait-quorum_reached[`++quorum_reached(self, proposal_id)++`] -* xref:#GovernorComponent-GovernorCountingTrait-vote_succeeded[`++vote_succeeded(self, proposal_id)++`] - -[.sub-index#GovernorComponent-Extensions-Traits-GovernorVotesTrait] -.GovernorVotesTrait - -* xref:#GovernorComponent-GovernorVotesTrait-clock[`++clock(self)++`] -* xref:#GovernorComponent-GovernorVotesTrait-CLOCK_MODE[`++CLOCK_MODE(self)++`] -* xref:#GovernorComponent-GovernorVotesTrait-get_votes[`++get_votes(self, account, timepoint, params)++`] - -[.sub-index#GovernorComponent-Extensions-Traits-GovernorExecutionTrait] -.GovernorExecutionTrait - -* xref:#GovernorComponent-GovernorExecutionTrait-state[`++state(self, proposal_id)++`] -* xref:#GovernorComponent-GovernorExecutionTrait-executor[`++executor(self)++`] -* xref:#GovernorComponent-GovernorExecutionTrait-execute_operations[`++execute_operations(self, proposal_id, calls, description_hash)++`] -* xref:#GovernorComponent-GovernorExecutionTrait-queue_operations[`++queue_operations(self, proposal_id, calls, description_hash)++`] -* xref:#GovernorComponent-GovernorExecutionTrait-proposal_needs_queuing[`++proposal_needs_queuing(self, proposal_id)++`] -* xref:#GovernorComponent-GovernorExecutionTrait-cancel_operations[`++cancel_operations(self, proposal_id, description_hash)++`] --- - -[.contract-index#GovernorComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#GovernorComponent-Embeddable-Impls-GovernorImpl] -.GovernorImpl - -* xref:#GovernorComponent-name[`++name(self)++`] -* xref:#GovernorComponent-version[`++version(self)++`] -* xref:#GovernorComponent-COUNTING_MODE[`++COUNTING_MODE(self)++`] -* xref:#GovernorComponent-hash_proposal[`++hash_proposal(self, calls, description_hash)++`] -* xref:#GovernorComponent-state[`++state(self, proposal_id)++`] -* xref:#GovernorComponent-proposal_threshold[`++proposal_threshold(self)++`] -* xref:#GovernorComponent-proposal_snapshot[`++proposal_snapshot(self, proposal_id)++`] -* xref:#GovernorComponent-proposal_deadline[`++proposal_deadline(self, proposal_id)++`] -* xref:#GovernorComponent-proposal_proposer[`++proposal_proposer(self, proposal_id)++`] -* xref:#GovernorComponent-proposal_eta[`++proposal_eta(self, proposal_id)++`] -* xref:#GovernorComponent-proposal_needs_queuing[`++proposal_needs_queuing(self, proposal_id)++`] -* xref:#GovernorComponent-voting_delay[`++voting_delay(self)++`] -* xref:#GovernorComponent-voting_period[`++voting_period(self)++`] -* xref:#GovernorComponent-quorum[`++quorum(self, timepoint)++`] -* xref:#GovernorComponent-get_votes[`++get_votes(self, account, timepoint)++`] -* xref:#GovernorComponent-get_votes_with_params[`++get_votes_with_params(self, account, timepoint, params)++`] -* xref:#GovernorComponent-has_voted[`++has_voted(self, proposal_id, account)++`] -* xref:#GovernorComponent-propose[`++propose(self, calls, description)++`] -* xref:#GovernorComponent-queue[`++queue(self, calls, description_hash)++`] -* xref:#GovernorComponent-execute[`++execute(self, calls, description_hash)++`] -* xref:#GovernorComponent-cancel[`++cancel(self, proposal_id, description_hash)++`] -* xref:#GovernorComponent-cast_vote[`++cast_vote(self, proposal_id, support)++`] -* xref:#GovernorComponent-cast_vote_with_reason[`++cast_vote_with_reason(self, proposal_id, support, reason)++`] -* xref:#GovernorComponent-cast_vote_with_reason_and_params[`++cast_vote_with_reason_and_params(self, proposal_id, support, reason, params)++`] -* xref:#GovernorComponent-cast_vote_by_sig[`++cast_vote_by_sig(self, proposal_id, support, reason, signature)++`] -* xref:#GovernorComponent-cast_vote_with_reason_and_params_by_sig[`++cast_vote_with_reason_and_params_by_sig(self, proposal_id, support, reason, params, signature)++`] -* xref:#GovernorComponent-nonces[`++nonces(self, voter)++`] -* xref:#GovernorComponent-relay[`++relay(self, call)++`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#GovernorComponent-initializer[`++initializer(self)++`] -* xref:#GovernorComponent-get_proposal[`++get_proposal(self, proposal_id)++`] -* xref:#GovernorComponent-is_valid_description_for_proposer[`++is_valid_description_for_proposer(self, proposer, description)++`] -* xref:#GovernorComponent-_hash_proposal[`++_hash_proposal(self, calls, description_hash)++`] -* xref:#GovernorComponent-_proposal_snapshot[`++_proposal_snapshot(self, proposal_id)++`] -* xref:#GovernorComponent-_proposal_deadline[`++_proposal_deadline(self, proposal_id)++`] -* xref:#GovernorComponent-_proposal_proposer[`++_proposal_proposer(self, proposal_id)++`] -* xref:#GovernorComponent-_proposal_eta[`++_proposal_eta(self, proposal_id)++`] - -.InternalExtendedImpl - -* xref:#GovernorComponent-assert_only_governance[`++assert_only_governance(self)++`] -* xref:#GovernorComponent-validate_state[`++validate_state(self, proposal_id, allowed_states)++`] -* xref:#GovernorComponent-use_nonce[`++use_nonce(self, voter)++`] -* xref:#GovernorComponent-_get_votes[`++_get_votes(self, account, timepoint, params)++`] -* xref:#GovernorComponent-_proposal_threshold[`++_proposal_threshold(self)++`] -* xref:#GovernorComponent-_state[`++_state(self, proposal_id)++`] -* xref:#GovernorComponent-_propose[`++_propose(self, calls, description, proposer)++`] -* xref:#GovernorComponent-_cancel[`++_cancel(self, proposal_id, description_hash)++`] -* xref:#GovernorComponent-_count_vote[`++_count_vote(self, proposal_id, account, support, total_weight, params)++`] -* xref:#GovernorComponent-_cast_vote[`++_cast_vote(self, proposal_id, voter, support, reason, params)++`] --- - -[.contract-index] -.Events --- -* xref:#GovernorComponent-ProposalCreated[`++ProposalCreated(proposal_id, proposer, calls, signatures, vote_start, vote_end, description)++`] -* xref:#GovernorComponent-ProposalQueued[`++ProposalQueued(proposal_id)++`] -* xref:#GovernorComponent-ProposalExecuted[`++ProposalExecuted(proposal_id)++`] -* xref:#GovernorComponent-ProposalCanceled[`++ProposalCanceled(proposal_id)++`] -* xref:#GovernorComponent-VoteCast[`++VoteCast(voter, proposal_id, support, weight, reason)++`] -* xref:#GovernorComponent-VoteCastWithParams[`++VoteCastWithParams(voter, proposal_id, support, weight, reason, params)++`] --- - -[#GovernorComponent-Extensions-Traits] -==== Extensions traits functions - -[.contract-item] -[[GovernorComponent-GovernorSettingsTrait-voting_delay]] -==== `[.contract-item-name]#++voting_delay++#++(self: @ContractState) → u64++` [.item-kind]#extension# - -Must return the delay, in number of timepoints, between when the proposal is created and when the vote starts. This can be -increased to leave time for users to buy voting power, or delegate it, before the voting of a -proposal starts. - -[.contract-item] -[[GovernorComponent-GovernorSettingsTrait-voting_period]] -==== `[.contract-item-name]#++voting_period++#++(self: @ContractState) → u64++` [.item-kind]#extension# - -Must return the delay, in number of timepoints, between the vote start and vote end. - -[.contract-item] -[[GovernorComponent-GovernorSettingsTrait-proposal_threshold]] -==== `[.contract-item-name]#++proposal_threshold++#++(self: @ContractState) → u256++` [.item-kind]#extension# - -Must return the minimum number of votes that an account must have to create a proposal. - -[.contract-item] -[[GovernorComponent-GovernorQuorumTrait-quorum]] -==== `[.contract-item-name]#++quorum++#++(self: @ContractState, timepoint: u64) → u256++` [.item-kind]#extension# - -Must return the minimum number of votes required for a proposal to succeed. - -[.contract-item] -[[GovernorComponent-GovernorCountingTrait-counting_mode]] -==== `[.contract-item-name]#++counting_mode++#++(self: @ContractState) → ByteArray++` [.item-kind]#extension# - -Must return a description of the possible `support` values for `cast_vote` and the way these votes are counted, -meant to be consumed by UIs to show correct vote options and interpret the results. -See <> for more details. - -[.contract-item] -[[GovernorComponent-GovernorCountingTrait-count_vote]] -==== `[.contract-item-name]#++count_vote++#++(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, total_weight: u256, params: Span) → u256++` [.item-kind]#extension# - -Must register a vote for `proposal_id` by `account` with a given `support`, voting `weight` and voting `params`. - -NOTE: Support is generic and can represent various things depending on the voting system used. - -[.contract-item] -[[GovernorComponent-GovernorCountingTrait-has_voted]] -==== `[.contract-item-name]#++has_voted++#++(self: @ContractState, proposal_id: felt252, account: ContractAddress) → bool++` [.item-kind]#extension# - -Must return whether an account has cast a vote on a proposal. - -[.contract-item] -[[GovernorComponent-GovernorCountingTrait-quorum_reached]] -==== `[.contract-item-name]#++quorum_reached++#++(self: @ContractState, proposal_id: felt252) → bool++` [.item-kind]#extension# - -Must return whether the minimum quorum has been reached for a proposal. - -[.contract-item] -[[GovernorComponent-GovernorCountingTrait-vote_succeeded]] -==== `[.contract-item-name]#++vote_succeeded++#++(self: @ContractState, proposal_id: felt252) → bool++` [.item-kind]#extension# - -Must return whether a proposal has succeeded or not. - -[.contract-item] -[[GovernorComponent-GovernorVotesTrait-clock]] -==== `[.contract-item-name]#++clock++#++(self: @ContractState) → u64++` [.item-kind]#extension# - -Returns the current timepoint determined by the governor's operational mode, intended for use in time-sensitive logic. -See {ERC-6372-clock}. - -Requirements: - -- This function MUST always be non-decreasing. - -[.contract-item] -[[GovernorComponent-GovernorVotesTrait-CLOCK_MODE]] -==== `[.contract-item-name]#++CLOCK_MODE++#++(self: @ContractState) → ByteArray++` [.item-kind]#extension# - -Returns a description of the clock the governor is operating in. -See {ERC-6372-clock-mode}. - -Requirements: - -- The output MUST be formatted like a URL query string, decodable in standard JavaScript. - -[.contract-item] -[[GovernorComponent-GovernorVotesTrait-get_votes]] -==== `[.contract-item-name]#++get_votes++#++(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span) → u256++` [.item-kind]#extension# - -Must return the voting power of an account at a specific timepoint with the given parameters. - -[.contract-item] -[[GovernorComponent-GovernorExecutionTrait-state]] -==== `[.contract-item-name]#++state++#++(self: @ContractState, proposal_id: felt252) → ProposalState++` [.item-kind]#extension# - -Must return the state of a proposal at the current time. - -The state can be either: - -- `Pending`: The proposal does not exist yet. -- `Active`: The proposal is active. -- `Canceled`: The proposal has been canceled. -- `Defeated`: The proposal has been defeated. -- `Succeeded`: The proposal has succeeded. -- `Queued`: The proposal has been queued. -- `Executed`: The proposal has been executed. - -[.contract-item] -[[GovernorComponent-GovernorExecutionTrait-executor]] -==== `[.contract-item-name]#++executor++#++(self: @ContractState) → ContractAddress++` [.item-kind]#internal# - -Must return the address through which the governor executes action. -Should be used to specify whether the module execute actions through another contract -such as a timelock. - -NOTE: MUST be the governor itself, or an instance of TimelockController with the -governor as the only proposer, canceller, and executor. - -WARNING: When the executor is not the governor itself (i.e. a timelock), it can call -functions that are restricted with the `assert_only_governance` guard, and also -potentially execute transactions on behalf of the governor. Because of this, this module -is designed to work with the TimelockController as the unique potential external -executor. - -[.contract-item] -[[GovernorComponent-GovernorExecutionTrait-execute_operations]] -==== `[.contract-item-name]#++execute_operations++#++(ref self: ContractState, proposal_id: felt252, calls: Span)++` [.item-kind]#internal# - -Execution mechanism. Can be used to modify the way operations are executed (for example adding a vault/timelock). - -[.contract-item] -[[GovernorComponent-GovernorExecutionTrait-queue_operations]] -==== `[.contract-item-name]#++queue_operations++#++(ref self: ContractState, proposal_id: felt252, calls: Span)++` [.item-kind]#internal# - -Queuing mechanism. Can be used to modify the way queuing is -performed (for example adding a vault/timelock). - -Requirements: - -- Must return a timestamp that describes the expected ETA for execution. If the returned -value is 0, the core will consider queueing did not succeed, and the public `queue` -function will revert. - -[.contract-item] -[[GovernorComponent-GovernorExecutionTrait-proposal_needs_queuing]] -==== `[.contract-item-name]#++proposal_needs_queuing++#++(self: @ContractState) → bool++` [.item-kind]#internal# - -Must return whether proposals need to be queued before execution. This usually indicates if the proposal needs to go through a timelock. - -[.contract-item] -[[GovernorComponent-GovernorExecutionTrait-cancel_operations]] -==== `[.contract-item-name]#++cancel_operations++#++(ref self: ContractState, proposal_id: felt252, calls: Span)++` [.item-kind]#internal# - -Cancel mechanism. Can be used to modify the way canceling is -performed (for example adding a vault/timelock). - -[#GovernorComponent-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[GovernorComponent-name]] -==== `[.contract-item-name]#++name++#++() → felt252++` [.item-kind]#external# - -Name of the governor instance (used in building the {SNIP-12} domain separator). - -[.contract-item] -[[GovernorComponent-version]] -==== `[.contract-item-name]#++version++#++() → felt252++` [.item-kind]#external# - -Version of the governor instance (used in building {SNIP-12} domain separator). - -[.contract-item] -[[GovernorComponent-COUNTING_MODE]] -==== `[.contract-item-name]#++COUNTING_MODE++#++() → ByteArray++` [.item-kind]#external# - -A description of the possible `support` values for `cast_vote` and the way these votes are counted, meant to be consumed by UIs -to show correct vote options and interpret the results. The string is a URL-encoded sequence of key-value pairs -that each describe one aspect, for example `support=bravo&quorum=for,abstain`. - -There are 2 standard keys: `support` and `quorum`. - -- `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in -`GovernorBravo`. -- `quorum=bravo` means that only For votes are counted towards quorum. -- `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum. - -If a counting module makes use of encoded `params`, it should include this under a `params` -key with a unique name that describes the behavior. For example: - -- `params=fractional` might refer to a scheme where votes are divided fractionally between -for/against/abstain. -- `params=erc721` might refer to a scheme where specific NFTs are delegated to vote. - -NOTE: The string can be decoded by the standard https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`] -JavaScript class. - -[.contract-item] -[[GovernorComponent-hash_proposal]] -==== `[.contract-item-name]#++hash_proposal++#++(calls: Span, description_hash: felt252) → felt252++` [.item-kind]#external# - -Hashing function used to (re)build the proposal id from the proposal details. - -[.contract-item] -[[GovernorComponent-state]] -==== `[.contract-item-name]#++state++#++(proposal_id: felt252) → ProposalState++` [.item-kind]#external# - -Returns the state of a proposal, given its id. - -[.contract-item] -[[GovernorComponent-proposal_threshold]] -==== `[.contract-item-name]#++proposal_threshold++#++() → u256++` [.item-kind]#external# - -The number of votes required in order for a voter to become a proposer. - -[.contract-item] -[[GovernorComponent-proposal_snapshot]] -==== `[.contract-item-name]#++proposal_snapshot++#++(proposal_id: felt252) → u64++` [.item-kind]#external# - -Timepoint used to retrieve user's votes and quorum. If using block number, the snapshot is performed at the -end of this block. Hence, voting for this proposal starts at the beginning of the following block. - -[.contract-item] -[[GovernorComponent-proposal_deadline]] -==== `[.contract-item-name]#++proposal_deadline++#++(proposal_id: felt252) → u64++` [.item-kind]#external# - -Timepoint at which votes close. If using block number, votes close at the end of this block, so -it is possible to cast a vote during this block. - -[.contract-item] -[[GovernorComponent-proposal_proposer]] -==== `[.contract-item-name]#++proposal_proposer++#++(proposal_id: felt252) → ContractAddress++` [.item-kind]#external# - -The account that created a proposal. - -[.contract-item] -[[GovernorComponent-proposal_eta]] -==== `[.contract-item-name]#++proposal_eta++#++(proposal_id: felt252) → u64++` [.item-kind]#external# - -The time when a queued proposal becomes executable ("ETA"). Unlike `proposal_snapshot` and -`proposal_deadline`, this doesn't use the governor clock, and instead relies on the -executor's clock which may be different. In most cases this will be a timestamp. - -[.contract-item] -[[GovernorComponent-proposal_needs_queuing]] -==== `[.contract-item-name]#++proposal_needs_queuing++#++(proposal_id: felt252) → bool++` [.item-kind]#external# - -Whether a proposal needs to be queued before execution. This indicates if the proposal needs to go through a timelock. - -[.contract-item] -[[GovernorComponent-voting_delay]] -==== `[.contract-item-name]#++voting_delay++#++() → u64++` [.item-kind]#external# - -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}) 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. - -[.contract-item] -[[GovernorComponent-voting_period]] -==== `[.contract-item-name]#++voting_period++#++() → u64++` [.item-kind]#external# - -Delay between the vote start and vote end. The unit this duration is expressed in depends on -the clock (see {ERC-6372}) this contract uses. - -NOTE: The `voting_delay` can delay the start of the vote. This must be considered when -setting the voting duration compared to the voting delay. - -NOTE: This value is stored when the proposal is submitted so that possible changes to the -value do not affect proposals that have already been submitted. - -[.contract-item] -[[GovernorComponent-quorum]] -==== `[.contract-item-name]#++quorum++#++(timepoint: u64) → u256++` [.item-kind]#external# - -Minimum number of votes required for a proposal to be successful. - -NOTE: The `timepoint` parameter corresponds to the snapshot used for counting vote. This -allows the quorum to scale depending on values such as the total supply of a token at this -timepoint. - -[.contract-item] -[[GovernorComponent-get_votes]] -==== `[.contract-item-name]#++get_votes++#++(account: ContractAddress, timepoint: u64) → u256++` [.item-kind]#external# - -Returns the voting power of an `account` at a specific `timepoint`. - -NOTE: This can be implemented in a number of ways, for example by reading the delegated -balance from one (or multiple) `ERC20Votes` tokens. - -[.contract-item] -[[GovernorComponent-get_votes_with_params]] -==== `[.contract-item-name]#++get_votes_with_params++#++(account: ContractAddress, timepoint: u64, params: Span) → u256++` [.item-kind]#external# - -Returns the voting power of an account at a specific timepoint, given additional encoded parameters. - -[.contract-item] -[[GovernorComponent-has_voted]] -==== `[.contract-item-name]#++has_voted++#++(proposal_id: felt252, account: ContractAddress) → bool++` [.item-kind]#external# - -Returns whether an account has cast a vote on a proposal. - -[.contract-item] -[[GovernorComponent-propose]] -==== `[.contract-item-name]#++propose++#++(calls: Span, description: ByteArray) → felt252++` [.item-kind]#external# - -Creates a new proposal. Voting starts after the delay specified by `voting_delay` and -lasts for a duration specified by `voting_period`. Returns the id of the proposal. - -This function has opt-in frontrunning protection, described in -`is_valid_description_for_proposer`. - -NOTE: The state of the Governor and targets may change between the proposal creation -and its execution. This may be the result of third party actions on the targeted -contracts, or other governor proposals. For example, the balance of this contract could -be updated or its access control permissions may be modified, possibly compromising the -proposal's ability to execute successfully (e.g. the governor doesn't have enough value -to cover a proposal with multiple transfers). - -Requirements: - -- The proposer must be authorized to submit the proposal. -- The proposer must have enough votes to submit the proposal if `proposal_threshold` is -greater than zero. -- The proposal must not already exist. - -Emits a {ProposalCreated} event. - -[.contract-item] -[[GovernorComponent-queue]] -==== `[.contract-item-name]#++queue++#++(calls: Span, description_hash: felt252) → felt252++` [.item-kind]#external# - -Queues a proposal. Some governors require this step to be performed before execution can -happen. If queuing is not necessary, this function may revert. -Queuing a proposal requires the quorum to be reached, the vote to be successful, and the -deadline to be reached. - -Returns the id of the proposal. - -Requirements: - -- The proposal must be in the `Succeeded` state. -- The queue operation must return a non-zero ETA. - -Emits a {ProposalQueued} event. - -[.contract-item] -[[GovernorComponent-execute]] -==== `[.contract-item-name]#++execute++#++(calls: span, description_hash: felt252) → felt252++` [.item-kind]#external# - -Executes a successful proposal. This requires the quorum to be reached, the vote to be -successful, and the deadline to be reached. Depending on the governor it might also be -required that the proposal was queued and that some delay passed. - -NOTE: Some modules can modify the requirements for execution, for example by adding an -additional timelock (See `timelock_controller`). - -Returns the id of the proposal. - -Requirements: - -- The proposal must be in the `Succeeded` or `Queued` state. - -Emits a {ProposalExecuted} event. - -[.contract-item] -[[GovernorComponent-cancel]] -==== `[.contract-item-name]#++cancel++#++(calls: Span, description_hash: felt252) → felt252++` [.item-kind]#external# - -Cancels a proposal. A proposal is cancellable by the proposer, but only while it is -Pending state, i.e. before the vote starts. - -Returns the id of the proposal. - -Requirements: - -- The proposal must be in the `Pending` state. -- The caller must be the proposer of the proposal. - -Emits a {ProposalCanceled} event. - -[.contract-item] -[[GovernorComponent-cast_vote]] -==== `[.contract-item-name]#++cast_vote++#++(proposal_id: felt252, support: u8) → u256++` [.item-kind]#external# - -Cast a vote. - -Requirements: - -- The proposal must be active. - -Emits a {VoteCast} event. - -[.contract-item] -[[GovernorComponent-cast_vote_with_reason]] -==== `[.contract-item-name]#++cast_vote_with_reason++#++(proposal_id: felt252, support: u8, reason: ByteArray) → u256++` [.item-kind]#external# - -Cast a vote with a `reason`. - -Requirements: - -- The proposal must be active. - -Emits a {VoteCast} event. - -[.contract-item] -[[GovernorComponent-cast_vote_with_reason_and_params]] -==== `[.contract-item-name]#++cast_vote_with_reason_and_params++#++(proposal_id: felt252, support: u8, reason: ByteArray, params: Span) → u256++` [.item-kind]#external# - -Cast a vote with a `reason` and additional serialized `params`. - -Requirements: - -- The proposal must be active. - -Emits either: - -- {VoteCast} event if no params are provided. -- {VoteCastWithParams} event otherwise. - -[.contract-item] -[[GovernorComponent-cast_vote_by_sig]] -==== `[.contract-item-name]#++cast_vote_by_sig++#++(proposal_id: felt252, support: u8, voter: ContractAddress, signature: Span) → u256++` [.item-kind]#external# - -Cast a vote using the ``voter``'s signature. - -Requirements: - -- The proposal must be active. -- 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. - -Emits a {VoteCast} event. - -[.contract-item] -[[GovernorComponent-cast_vote_with_reason_and_params_by_sig]] -==== `[.contract-item-name]#++cast_vote_with_reason_and_params_by_sig++#++(proposal_id: felt252, support: u8, voter: ContractAddress, reason: ByteArray, params: Span, signature: Span) → u256++` [.item-kind]#external# - -Cast a vote with a `reason` and additional serialized `params` using the ``voter``'s -signature. - -Requirements: - -- The proposal must be active. -- 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. - -Emits either: - -- {VoteCast} event if no params are provided. -- {VoteCastWithParams} event otherwise. - -[.contract-item] -[[GovernorComponent-nonces]] -==== `[.contract-item-name]#++nonces++#++(voter: ContractAddress) → felt252++` [.item-kind]#external# - -Returns the next unused nonce for an address. - -[.contract-item] -[[GovernorComponent-relay]] -==== `[.contract-item-name]#++relay++#++(call: Call)++` [.item-kind]#external# - -Relays a transaction or function call to an arbitrary target. - -In cases where the governance executor is some contract other than the governor itself, like -when using a timelock, this function can be invoked in a governance proposal to recover -tokens that were sent to the governor contract by mistake. - -NOTE: If the executor is simply the governor itself, use of `relay` is redundant. - -[#GovernorComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[GovernorComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState)++` [.item-kind]#internal# - -Initializes the contract by registering the supported interface id. - -[.contract-item] -[[GovernorComponent-get_proposal]] -==== `[.contract-item-name]#++get_proposal++#++(self: @ContractState, proposal_id: felt252) → ProposalCore++` [.item-kind]#internal# - -Returns the proposal object given its id. - -[.contract-item] -[[GovernorComponent-is_valid_description_for_proposer]] -==== `[.contract-item-name]#++is_valid_description_for_proposer++#++(self: @ContractState, proposer: ContractAddress, description: ByteArray) → bool++` [.item-kind]#internal# - -Checks if the proposer is authorized to submit a proposal with the given description. - -If the proposal description ends with `#proposer=0x???`, where `0x???` is an address -written as a hex string (case insensitive), then the submission of this proposal will -only be authorized to said address. - -This is used for frontrunning protection. By adding this pattern at the end of their -proposal, one can ensure that no other address can submit the same proposal. An attacker -would have to either remove or change that part, which would result in a different -proposal id. - -NOTE: In Starknet, the Sequencer ensures the order of transactions, but frontrunning -can still be achieved by nodes, and potentially other actors in the future with -sequencer decentralization. - -If the description does not match this pattern, it is unrestricted and anyone can submit -it. This includes: - -- If the `0x???` part is not a valid hex string. -- If the `0x???` part is a valid hex string, but does not contain exactly 64 hex digits. -- If it ends with the expected suffix followed by newlines or other whitespace. -- If it ends with some other similar suffix, e.g. `#other=abc`. -- If it does not end with any such suffix. - -[.contract-item] -[[GovernorComponent-_hash_proposal]] -==== `[.contract-item-name]#++_hash_proposal++#++(self: @ContractState, calls: Span, description_hash: felt252) → felt252++` [.item-kind]#internal# - -Returns the proposal id computed from the given parameters. - -The proposal id is computed as a Pedersen hash of: - -- The array of calls being proposed -- The description hash - -[.contract-item] -[[GovernorComponent-_proposal_snapshot]] -==== `[.contract-item-name]#++_proposal_snapshot++#++(self: @ContractState, proposal_id: felt252) → u64++` [.item-kind]#internal# - -Timepoint used to retrieve user's votes and quorum. If using block number, the snapshot -is performed at the end of this block. Hence, voting for this proposal starts at the -beginning of the following block. - -[.contract-item] -[[GovernorComponent-_proposal_deadline]] -==== `[.contract-item-name]#++_proposal_deadline++#++(self: @ContractState, proposal_id: felt252) → u64++` [.item-kind]#internal# - -Timepoint at which votes close. If using block number, votes close at the end of this -block, so it is possible to cast a vote during this block. - -[.contract-item] -[[GovernorComponent-_proposal_proposer]] -==== `[.contract-item-name]#++_proposal_proposer++#++(self: @ContractState, proposal_id: felt252) → ContractAddress++` [.item-kind]#internal# - -The account that created a proposal. - -[.contract-item] -[[GovernorComponent-_proposal_eta]] -==== `[.contract-item-name]#++_proposal_eta++#++(self: @ContractState, proposal_id: felt252) → u64++` [.item-kind]#internal# - -The time when a queued proposal becomes executable ("ETA"). Unlike `proposal_snapshot` -and `proposal_deadline`, this doesn't use the governor clock, and instead relies on the -executor's clock which may be different. In most cases this will be a timestamp. - -[.contract-item] -[[GovernorComponent-assert_only_governance]] -==== `[.contract-item-name]#++assert_only_governance++#++(self: @ContractState)++` [.item-kind]#internal# - -Asserts that the caller is the governance executor. - -WARNING: When the executor is not the governor itself (i.e. a timelock), it can call -functions that are restricted with this modifier, and also potentially execute -transactions on behalf of the governor. Because of this, this module is designed to work -with the TimelockController as the unique potential external executor. The timelock -MUST have the governor as the only proposer, canceller, and executor. - -[.contract-item] -[[GovernorComponent-validate_state]] -==== `[.contract-item-name]#++validate_state++#++(self: @ContractState, proposal_id: felt252, state: ProposalState)++` [.item-kind]#internal# - -Validates that a proposal is in the expected state. Otherwise it panics. - -[.contract-item] -[[GovernorComponent-use_nonce]] -==== `[.contract-item-name]#++use_nonce++#++(ref self: ContractState) → felt252++` [.item-kind]#internal# - -Consumes a nonce, returns the current value, and increments nonce. - -[.contract-item] -[[GovernorComponent-_get_votes]] -==== `[.contract-item-name]#++_get_votes++#++(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span) → u256++` [.item-kind]#internal# - -Internal wrapper for `GovernorVotesTrait::get_votes`. - -[.contract-item] -[[GovernorComponent-_proposal_threshold]] -==== `[.contract-item-name]#++_proposal_threshold++#++(self: @ContractState) → u256++` [.item-kind]#internal# - -Internal wrapper for `GovernorProposeTrait::proposal_threshold`. - -[.contract-item] -[[GovernorComponent-_state]] -==== `[.contract-item-name]#++_state++#++(self: @ContractState, proposal_id: felt252) → ProposalState++` [.item-kind]#internal# - -Returns the state of a proposal, given its id. - -Requirements: - -- The proposal must exist. - -[.contract-item] -[[GovernorComponent-_propose]] -==== `[.contract-item-name]#++_propose++#++(ref self: ContractState, calls: Span, description_hash: felt252) → felt252++` [.item-kind]#internal# - -Internal propose mechanism. Returns the proposal id. - -Requirements: - -- The proposal must not already exist. - -Emits a {ProposalCreated} event. - -[.contract-item] -[[GovernorComponent-_cancel]] -==== `[.contract-item-name]#++_cancel++#++(ref self: ContractState, proposal_id: felt252)++` [.item-kind]#internal# - -Internal cancel mechanism with minimal restrictions. - -A proposal can be cancelled in any state other than Canceled or Executed. - -NOTE: Once cancelled, a proposal can't be re-submitted. - -[.contract-item] -[[GovernorComponent-_count_vote]] -==== `[.contract-item-name]#++_count_vote++#++(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, weight: u256, params: Span)++` [.item-kind]#internal# - -Internal wrapper for `GovernorCountingTrait::count_vote`. - -[.contract-item] -[[GovernorComponent-_cast_vote]] -==== `[.contract-item-name]#++_cast_vote++#++(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, reason: ByteArray, params: Span) → u256++` [.item-kind]#internal# - -Internal vote-casting mechanism. - -Checks that the vote is pending and that it has not been cast yet. -This function retrieves the voting weight using `get_votes` and then calls -the `_count_vote` internal function. - -Emits either: - -- {VoteCast} event if no params are provided. -- {VoteCastWithParams} event otherwise. - -[#GovernorComponent-Events] -==== Events - -[.contract-item] -[[GovernorComponent-ProposalCreated]] -==== `[.contract-item-name]#++ProposalCreated++#++(proposal_id: felt252, proposer: ContractAddress, calls: Span, signatures: Span>, vote_start: u64, vote_end: u64, description: ByteArray)++` [.item-kind]#event# - -Emitted when a proposal is created. - -[.contract-item] -[[GovernorComponent-ProposalQueued]] -==== `[.contract-item-name]#++ProposalQueued++#++(proposal_id: felt252, eta_seconds: u64)++` [.item-kind]#event# - -Emitted when a proposal is queued. - -[.contract-item] -[[GovernorComponent-ProposalExecuted]] -==== `[.contract-item-name]#++ProposalExecuted++#++(proposal_id: felt252)++` [.item-kind]#event# - -Emitted when a proposal is executed. - -[.contract-item] -[[GovernorComponent-ProposalCanceled]] -==== `[.contract-item-name]#++ProposalCanceled++#++(proposal_id: felt252)++` [.item-kind]#event# - -Emitted when a proposal is canceled. - -[.contract-item] -[[GovernorComponent-VoteCast]] -==== `[.contract-item-name]#++VoteCast++#++(voter: ContractAddress, proposal_id: felt252, support: u8, weight: u256, reason: ByteArray)++` [.item-kind]#event# - -Emitted when a vote is cast. - -[.contract-item] -[[GovernorComponent-VoteCastWithParams]] -==== `[.contract-item-name]#++VoteCastWithParams++#++(voter: ContractAddress, proposal_id: felt252, support: u8, weight: u256, reason: ByteArray, params: Span)++` [.item-kind]#event# - -Emitted when a vote is cast with params. - -== Governor extensions - -:extension-traits: xref:#GovernorComponent-Extensions-Traits-Traits[extensions traits] - -The Governor component can (and must) be extended by implementing the {extension-traits} to add the desired functionality. -This can be achieved by directly implementing the traits on your contract, or by using a set of ready-to-use extensions -provided by the library, which are presented below. - -[.contract] -[[GovernorCoreExecutionComponent]] -=== `++GovernorCoreExecutionComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/governance/src/governor/extensions/governor_core_execution.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_governance::governor::extensions::GovernorCoreExecutionComponent; -``` - -Extension of {GovernorComponent} providing an execution mechanism directly through -the Governor itself. For a timelocked execution mechanism, see -xref:#GovernorTimelockExecutionComponent[GovernorTimelockExecutionComponent]. - -[.contract-index] -.Extension traits implementations --- -.GovernorExecution - -* xref:#GovernorCoreExecutionComponent-state[`++state(self, proposal_id)++`] -* xref:#GovernorCoreExecutionComponent-executor[`++executor(self)++`] -* xref:#GovernorCoreExecutionComponent-execute_operations[`++execute_operations(self, proposal_id, calls, description_hash)++`] -* xref:#GovernorCoreExecutionComponent-queue_operations[`++queue_operations(self, proposal_id, calls, description_hash)++`] -* xref:#GovernorCoreExecutionComponent-proposal_needs_queuing[`++proposal_needs_queuing(self, proposal_id)++`] -* xref:#GovernorCoreExecutionComponent-cancel_operations[`++cancel_operations(self, proposal_id, description_hash)++`] --- - -[#GovernorCoreExecutionComponent-Extension-Traits-Functions] -==== Extension traits functions - -[.contract-item] -[[GovernorCoreExecutionComponent-state]] -==== `[.contract-item-name]#++state++#++(self: @ContractState, proposal_id: felt252) → ProposalState++` [.item-kind]#internal# - -Returns the state of a proposal given its id. - -Requirements: - -- The proposal must exist. - -[.contract-item] -[[GovernorCoreExecutionComponent-executor]] -==== `[.contract-item-name]#++executor++#++(self: @ContractState) → ContractAddress++` [.item-kind]#internal# - -Returns the executor address. - -In this case, it returns the governor contract address since execution is performed directly through it. - -[.contract-item] -[[GovernorCoreExecutionComponent-execute_operations]] -==== `[.contract-item-name]#++execute_operations++#++(ref self: ContractState, proposal_id: felt252, calls: Span, description_hash: felt252)++` [.item-kind]#internal# - -Executes the proposal's operations directly through the governor contract. - -[.contract-item] -[[GovernorCoreExecutionComponent-queue_operations]] -==== `[.contract-item-name]#++queue_operations++#++(ref self: ContractState, proposal_id: felt252, calls: Span, description_hash: felt252) → u64++` [.item-kind]#internal# - -In this implementation, queuing is not required so it returns 0. - -[.contract-item] -[[GovernorCoreExecutionComponent-proposal_needs_queuing]] -==== `[.contract-item-name]#++proposal_needs_queuing++#++(self: @ContractState, proposal_id: felt252) → bool++` [.item-kind]#internal# - -In this implementation, it always returns false. - -[.contract-item] -[[GovernorCoreExecutionComponent-cancel_operations]] -==== `[.contract-item-name]#++cancel_operations++#++(ref self: ContractState, proposal_id: felt252, description_hash: felt252)++` [.item-kind]#internal# - -Cancels a proposal's operations. - -[.contract] -[[GovernorCountingSimpleComponent]] -=== `++GovernorCountingSimpleComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/governance/src/governor/extensions/governor_counting_simple.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_governance::governor::extensions::GovernorCountingSimpleComponent; -``` - -Extension of {GovernorComponent} for simple vote counting with three options. - -[.contract-index] -.Extension traits implementations --- -.GovernorCounting - -* xref:#GovernorCountingSimpleComponent-counting_mode[`counting_mode(self)`] -* xref:#GovernorCountingSimpleComponent-count_vote[`count_vote(self, proposal_id, account, support, total_weight, params)`] -* xref:#GovernorCountingSimpleComponent-has_voted[`has_voted(self, proposal_id, account)`] -* xref:#GovernorCountingSimpleComponent-quorum_reached[`quorum_reached(self, proposal_id)`] -* xref:#GovernorCountingSimpleComponent-vote_succeeded[`vote_succeeded(self, proposal_id)`] --- - -[#GovernorCountingSimpleComponent-Extension-Traits-Functions] -==== Extension traits functions - -[.contract-item] -[[GovernorCountingSimpleComponent-counting_mode]] -==== `[.contract-item-name]#++counting_mode++#++(self: @ContractState) → ByteArray++` [.item-kind]#internal# - -Returns `"support=bravo&quorum=for,abstain"`. - -- `support=bravo` indicates that the support follows the Governor Bravo format where voters can vote For, Against, or Abstain -- `quorum=for,abstain` indicates that both For and Abstain votes count toward quorum - -[.contract-item] -[[GovernorCountingSimpleComponent-count_vote]] -==== `[.contract-item-name]#++count_vote++#++(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, total_weight: u256, params: Span) → u256++` [.item-kind]#internal# - -Records a vote for a proposal. - -The support value follows the `VoteType` enum (0=Against, 1=For, 2=Abstain). - -Returns the weight that was counted. - -[.contract-item] -[[GovernorCountingSimpleComponent-has_voted]] -==== `[.contract-item-name]#++has_voted++#++(self: @ContractState, proposal_id: felt252, account: ContractAddress) → bool++` [.item-kind]#internal# - -Returns whether an account has cast a vote on a proposal. - -[.contract-item] -[[GovernorCountingSimpleComponent-quorum_reached]] -==== `[.contract-item-name]#++quorum_reached++#++(self: @ContractState, proposal_id: felt252) → bool++` [.item-kind]#internal# - -Returns whether a proposal has reached quorum. - -In this implementation, both For and Abstain votes count toward quorum. - -[.contract-item] -[[GovernorCountingSimpleComponent-vote_succeeded]] -==== `[.contract-item-name]#++vote_succeeded++#++(self: @ContractState, proposal_id: felt252) → bool++` [.item-kind]#internal# - -Returns whether a proposal has succeeded. - -In this implementation, the For votes must be strictly greater than Against votes. - -[.contract] -[[GovernorSettingsComponent]] -=== `++GovernorSettingsComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/governance/src/governor/extensions/governor_settings.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_governance::governor::extensions::GovernorSettingsComponent; -``` - -Extension of {GovernorComponent} for settings that are updatable through governance. - -[.contract-index] -.Extension traits implementations --- -.GovernorSettings - -* xref:#GovernorSettingsComponent-voting_delay[`++voting_delay(self)++`] -* xref:#GovernorSettingsComponent-voting_period[`++voting_period(self)++`] -* xref:#GovernorSettingsComponent-proposal_threshold[`++proposal_threshold(self)++`] --- - -[.contract-index] -.Embeddable implementations --- -.GovernorSettingsAdminImpl - -* xref:#GovernorSettingsComponent-set_voting_delay[`++set_voting_delay(self, new_voting_delay)++`] -* xref:#GovernorSettingsComponent-set_voting_period[`++set_voting_period(self, new_voting_period)++`] -* xref:#GovernorSettingsComponent-set_proposal_threshold[`++set_proposal_threshold(self, new_proposal_threshold)++`] --- - -[.contract-index] -.Internal implementations --- -.InternalImpl - -* xref:#GovernorSettingsComponent-initializer[`++initializer(self, new_voting_delay, new_voting_period, new_proposal_threshold)++`] -* xref:#GovernorSettingsComponent-assert_only_governance[`++assert_only_governance(self)++`] -* xref:#GovernorSettingsComponent-_set_voting_delay[`++_set_voting_delay(self, new_voting_delay)++`] -* xref:#GovernorSettingsComponent-_set_voting_period[`++_set_voting_period(self, new_voting_period)++`] -* xref:#GovernorSettingsComponent-_set_proposal_threshold[`++_set_proposal_threshold(self, new_proposal_threshold)++`] --- - -[.contract-index] -.Events --- -* xref:#GovernorSettingsComponent-VotingDelayUpdated[`++VotingDelayUpdated(old_voting_delay, new_voting_delay)++`] -* xref:#GovernorSettingsComponent-VotingPeriodUpdated[`++VotingPeriodUpdated(old_voting_period, new_voting_period)++`] -* xref:#GovernorSettingsComponent-ProposalThresholdUpdated[`++ProposalThresholdUpdated(old_proposal_threshold, new_proposal_threshold)++`] --- - -[#GovernorSettings-Extension-Traits-Functions] -==== Extension traits functions - -[.contract-item] -[[GovernorSettingsComponent-voting_delay]] -==== `[.contract-item-name]#++voting_delay++#++(self: @ContractState) → u64++` [.item-kind]#internal# - -Returns the delay, between when a proposal is created and when voting starts. - -[.contract-item] -[[GovernorSettingsComponent-voting_period]] -==== `[.contract-item-name]#++voting_period++#++(self: @ContractState) → u64++` [.item-kind]#internal# - -Returns the time period, during which votes can be cast. - -[.contract-item] -[[GovernorSettingsComponent-proposal_threshold]] -==== `[.contract-item-name]#++proposal_threshold++#++(self: @ContractState) → u256++` [.item-kind]#internal# - -Returns the minimum number of votes required for an account to create a proposal. - -[#GovernorSettings-Embeddable-Functions] -==== Embeddable functions - -:VotingDelayUpdated: xref:#GovernorSettingsComponent-VotingDelayUpdated[VotingDelayUpdated] -:VotingPeriodUpdated: xref:#GovernorSettingsComponent-VotingPeriodUpdated[VotingPeriodUpdated] -:ProposalThresholdUpdated: xref:#GovernorSettingsComponent-ProposalThresholdUpdated[ProposalThresholdUpdated] - -[.contract-item] -[[GovernorSettingsComponent-set_voting_delay]] -==== `[.contract-item-name]#++set_voting_delay++#++(ref self: ContractState, new_voting_delay: u64)++` [.item-kind]#external# - -Sets the voting delay. - -Requirements: - -- Caller must be the governance executor. - -NOTE: This function does not emit an event if the new voting delay is the same as the old one. - -May emit a {VotingDelayUpdated} event. - -[.contract-item] -[[GovernorSettingsComponent-set_voting_period]] -==== `[.contract-item-name]#++set_voting_period++#++(ref self: ContractState, new_voting_period: u64)++` [.item-kind]#external# - -Sets the voting period. - -NOTE: This function does not emit an event if the new voting period is the same as the -old one. - -Requirements: - -- Caller must be the governance executor. -- `new_voting_period` must be greater than 0. - -May emit a {VotingPeriodUpdated} event. - -[.contract-item] -[[GovernorSettingsComponent-set_proposal_threshold]] -==== `[.contract-item-name]#++set_proposal_threshold++#++(ref self: ContractState, new_proposal_threshold: u256)++` [.item-kind]#external# - -Sets the proposal threshold. - -NOTE: This function does not emit an event if the new proposal threshold is the same as -the old one. - -Requirements: - -- Caller must be the governance executor. - -May emit a {ProposalThresholdUpdated} event. - -[#GovernorSettingsComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[GovernorSettingsComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, initial_voting_delay: u64, initial_voting_period: u64, initial_proposal_threshold: u256)++` [.item-kind]#internal# - -Initializes the component by setting the default values. - -Requirements: - -- `new_voting_period` must be greater than 0. - -Emits a {VotingDelayUpdated}, {VotingPeriodUpdated}, and {ProposalThresholdUpdated} event. - -[.contract-item] -[[GovernorSettingsComponent-assert_only_governance]] -==== `[.contract-item-name]#++assert_only_governance++#++(ref self: ContractState)++` [.item-kind]#internal# - -Asserts that the caller is the governance executor. - -[.contract-item] -[[GovernorSettingsComponent-_set_voting_delay]] -==== `[.contract-item-name]#++_set_voting_delay++#++(ref self: ContractState, new_voting_delay: u64)++` [.item-kind]#internal# - -Internal function to update the voting delay. - -NOTE: This function does not emit an event if the new voting delay is the same as the -old one. - -May emit a {VotingDelayUpdated} event. - -[.contract-item] -[[GovernorSettingsComponent-_set_voting_period]] -==== `[.contract-item-name]#++_set_voting_period++#++(ref self: ContractState, new_voting_period: u64)++` [.item-kind]#internal# - -Internal function to update the voting period. - -Requirements: - -- `new_voting_period` must be greater than 0. - -NOTE: This function does not emit an event if the new voting period is the same as the old one. - -May emit a {VotingPeriodUpdated} event. - -[.contract-item] -[[GovernorSettingsComponent-_set_proposal_threshold]] -==== `[.contract-item-name]#++_set_proposal_threshold++#++(ref self: ContractState, new_proposal_threshold: u256)++` [.item-kind]#internal# - -Internal function to update the proposal threshold. - -NOTE: This function does not emit an event if the new proposal threshold is the same as the old one. - -May emit a {ProposalThresholdUpdated} event. - -[#GovernorSettings-Events] -==== Events - -[.contract-item] -[[GovernorSettingsComponent-VotingDelayUpdated]] -==== `[.contract-item-name]#++VotingDelayUpdated++#++(old_voting_delay: u64, new_voting_delay: u64)++` [.item-kind]#event# - -Emitted when the voting delay is updated. - -[.contract-item] -[[GovernorSettingsComponent-VotingPeriodUpdated]] -==== `[.contract-item-name]#++VotingPeriodUpdated++#++(old_voting_period: u64, new_voting_period: u64)++` [.item-kind]#event# - -Emitted when the voting period is updated. - -[.contract-item] -[[GovernorSettingsComponent-ProposalThresholdUpdated]] -==== `[.contract-item-name]#++ProposalThresholdUpdated++#++(old_proposal_threshold: u256, new_proposal_threshold: u256)++` [.item-kind]#event# - -Emitted when the proposal threshold is updated. - -[.contract] -[[GovernorVotesComponent]] -=== `++GovernorVotesComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/governance/src/governor/extensions/governor_votes.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_governance::governor::extensions::GovernorVotesComponent; -``` - -Extension of {GovernorComponent} for voting weight extraction from a token with the {IVotes} -extension. - -[.contract-index] -.Extension traits implementations --- -.GovernorVotes - -* xref:#GovernorVotesComponent-clock[`++clock(self)++`] -* xref:#GovernorVotesComponent-CLOCK_MODE[`++CLOCK_MODE(self)++`] -* xref:#GovernorVotesComponent-get_votes[`++get_votes(self, account, timepoint, params)++`] --- - -[.contract-index] -.Embeddable implementations --- -.VotesTokenImpl - -* xref:#GovernorVotesComponent-token[`++token(self)++`] --- - -[.contract-index] -.Internal implementations --- -.InternalImpl - -* xref:#GovernorVotesComponent-initializer[`++initializer(self, votes_token)++`] --- - -[#GovernorVotes-Extension-Traits-Functions] -==== Extension traits functions - -[.contract-item] -[[GovernorVotesComponent-clock]] -==== `[.contract-item-name]#++clock++#++(self: @ContractState) → u64++` [.item-kind]#internal# - -Returns the current timepoint determined by the governor's operational mode, intended for use in time-sensitive logic. -See {ERC-6372-clock}. - -Requirements: - -- This function MUST always be non-decreasing. - -[.contract-item] -[[GovernorVotesComponent-CLOCK_MODE]] -==== `[.contract-item-name]#++CLOCK_MODE++#++(self: @ContractState) → ByteArray++` [.item-kind]#internal# - -Returns a description of the clock the governor is operating in. -See {ERC-6372-clock-mode}. - -Requirements: - -- The output MUST be formatted like a URL query string, decodable in standard JavaScript. - -[.contract-item] -[[GovernorVotesComponent-get_votes]] -==== `[.contract-item-name]#++get_votes++#++(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span) → u256++` [.item-kind]#internal# - -Returns the voting power of `account` at a specific `timepoint` using the votes token. - -[[GovernorVotesComponent-Embeddable-Functions]] -==== Embeddable functions - -[.contract-item] -[[GovernorVotesComponent-token]] -==== `[.contract-item-name]#++token++#++(self: @ContractState) → ContractAddress++` [.item-kind]#external# - -Returns the votes token that voting power is sourced from. - -[#GovernorVotesComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[GovernorVotesComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, votes_token: ContractAddress)++` [.item-kind]#internal# - -Initializes the component by setting the votes token. - -Requirements: - -- `votes_token` must not be zero. - -:QuorumNumeratorUpdated: xref:#GovernorVotesQuorumFractionComponent-QuorumNumeratorUpdated[QuorumNumeratorUpdated] - -[.contract] -[[GovernorVotesQuorumFractionComponent]] -=== `++GovernorVotesQuorumFractionComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/governance/src/governor/extensions/governor_votes_quorum_fraction.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_governance::governor::extensions::GovernorVotesQuorumFractionComponent; -``` - -Extension of {GovernorComponent} for voting weight extraction from a token with the -{IVotes} extension and a quorum expressed as a fraction of the total supply. - -[.contract-index] -.Extension traits implementations --- -.GovernorQuorum - -* xref:#GovernorVotesQuorumFractionComponent-quorum[`++quorum(self, timepoint)++`] - -.GovernorVotes - -* xref:#GovernorVotesQuorumFractionComponent-clock[`++clock(self)++`] -* xref:#GovernorVotesQuorumFractionComponent-CLOCK_MODE[`++CLOCK_MODE(self)++`] -* xref:#GovernorVotesQuorumFractionComponent-get_votes[`++get_votes(self, account, timepoint, params)++`] --- - -[.contract-index] -.Embeddable implementations --- -.QuorumFractionImpl - -* xref:#GovernorVotesQuorumFractionComponent-token[`++token(self)++`] -* xref:#GovernorVotesQuorumFractionComponent-current_quorum_numerator[`++current_quorum_numerator(self)++`] -* xref:#GovernorVotesQuorumFractionComponent-quorum_numerator[`++quorum_numerator(self, timepoint)++`] -* xref:#GovernorVotesQuorumFractionComponent-quorum_denominator[`++quorum_denominator(self)++`] --- - -[.contract-index] -.Internal implementations --- -.InternalImpl - -* xref:#GovernorVotesQuorumFractionComponent-initializer[`++initializer(self, votes_token, quorum_numerator)++`] -* xref:#GovernorVotesQuorumFractionComponent-update_quorum_numerator[`++update_quorum_numerator(self, new_quorum_numerator)++`] --- - -[.contract-index] -.Events --- -* xref:#GovernorVotesQuorumFractionComponent-QuorumNumeratorUpdated[`++QuorumNumeratorUpdated(old_quorum_numerator, new_quorum_numerator)++`] --- - -[#GovernorVotesQuorumFractionComponent-Extension-Traits-Functions] -==== Extension traits functions - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-quorum]] -==== `[.contract-item-name]#++quorum++#++(self: @ContractState, timepoint: u64) → u256++` [.item-kind]#internal# - -It is computed as a percentage of the votes token total supply at a given `timepoint` in the past. - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-clock]] -==== `[.contract-item-name]#++clock++#++(self: @ContractState) → u64++` [.item-kind]#internal# - -Returns the current timepoint determined by the governor's operational mode, intended for use in time-sensitive logic. -See {ERC-6372-clock}. - -Requirements: - -- This function MUST always be non-decreasing. - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-CLOCK_MODE]] -==== `[.contract-item-name]#++CLOCK_MODE++#++(self: @ContractState) → ByteArray++` [.item-kind]#internal# - -Returns a description of the clock the governor is operating in. -See {ERC-6372-clock-mode}. - -Requirements: - -- The output MUST be formatted like a URL query string, decodable in standard JavaScript. - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-get_votes]] -==== `[.contract-item-name]#++get_votes++#++(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span) → u256++` [.item-kind]#internal# - -Returns the voting power of `account` at a specific `timepoint` using the votes token. - -[#GovernorVotesQuorumFractionComponent-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-token]] -==== `[.contract-item-name]#++token++#++(self: @ContractState) → ContractAddress++` [.item-kind]#external# - -Returns the address of the votes token used for voting power extraction. - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-current_quorum_numerator]] -==== `[.contract-item-name]#++current_quorum_numerator++#++(self: @ContractState) → u256++` [.item-kind]#external# - -Returns the current quorum numerator value. - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-quorum_numerator]] -==== `[.contract-item-name]#++quorum_numerator++#++(self: @ContractState, timepoint: u64) → u256++` [.item-kind]#external# - -Returns the quorum numerator value at a specific `timepoint` in the past. - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-quorum_denominator]] -==== `[.contract-item-name]#++quorum_denominator++#++(self: @ContractState) → u256++` [.item-kind]#external# - -Returns the quorum denominator value. - -[#GovernorVotesQuorumFractionComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(self: @ComponentState, votes_token: ContractAddress, quorum_numerator: u256)++` [.item-kind]#internal# - -Initializes the component by setting the votes token and the initial quorum numerator value. - -Requirements: - -* `votes_token` must not be zero. -* `quorum_numerator` must be less than `quorum_denominator`. - -Emits a {QuorumNumeratorUpdated} event. - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-update_quorum_numerator]] -==== `[.contract-item-name]#++update_quorum_numerator++#++(self: @ComponentState, new_quorum_numerator: u256)++` [.item-kind]#internal# - -Updates the quorum numerator. - -NOTE: This function does not emit an event if the new quorum numerator is the same as the old one. - -Requirements: - -* `new_quorum_numerator` must be less than `quorum_denominator`. - -May emit a {QuorumNumeratorUpdated} event. - -[#GovernorVotesQuorumFractionComponent-Events] -==== Events - -[.contract-item] -[[GovernorVotesQuorumFractionComponent-QuorumNumeratorUpdated]] -==== `[.contract-item-name]#++QuorumNumeratorUpdated++#++(old_quorum_numerator: u256, new_quorum_numerator: u256)++` [.item-kind]#event# - -Emitted when the quorum numerator is updated. - -:roles: xref:governance/timelock.adoc#roles - -[.contract] -[[GovernorTimelockExecutionComponent]] -=== `++GovernorTimelockExecutionComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/governance/src/governor/extensions/governor_timelock_execution.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_governance::governor::extensions::GovernorTimelockExecutionComponent; -``` - -Extension of {GovernorComponent} that binds the execution process to an instance of a contract -implementing {TimelockControllerComponent}. This adds a delay, enforced by the timelock -to all successful proposals (in addition to the voting duration). - -NOTE: The Governor needs the {roles}[PROPOSER, EXECUTOR, and CANCELLER roles] to work properly. - -Using this model means the proposal will be operated by the timelock and not by the -governor. Thus, the assets and permissions must be attached to the timelock. Any asset -sent to the governor will be inaccessible from a proposal, unless executed via -`Governor::relay`. - -WARNING: Setting up the timelock to have additional proposers or cancellers besides -the governor is very risky, as it grants them the ability to: 1) execute operations as the -timelock, and thus possibly performing operations or accessing funds that are expected to only -be accessible through a vote, and 2) block governance proposals that have been approved by the -voters, effectively executing a Denial of Service attack. - -[.contract-index] -.Extension traits implementations --- -.GovernorExecution - -* xref:#GovernorTimelockExecutionComponent-state[`++state(self, proposal_id)++`] -* xref:#GovernorTimelockExecutionComponent-executor[`++executor(self)++`] -* xref:#GovernorTimelockExecutionComponent-execute_operations[`++execute_operations(self, proposal_id, calls, description_hash)++`] -* xref:#GovernorTimelockExecutionComponent-queue_operations[`++queue_operations(self, proposal_id, calls, description_hash)++`] -* xref:#GovernorTimelockExecutionComponent-proposal_needs_queuing[`++proposal_needs_queuing(self, proposal_id)++`] -* xref:#GovernorTimelockExecutionComponent-cancel_operations[`++cancel_operations(self, proposal_id, description_hash)++`] --- - -[.contract-index] -.Embeddable implementations --- -.TimelockedImpl - -* xref:#GovernorTimelockExecutionComponent-timelock[`++timelock(self)++`] -* xref:#GovernorTimelockExecutionComponent-get_timelock_id[`++get_timelock_id(self, proposal_id)++`] -* xref:#GovernorTimelockExecutionComponent-update_timelock[`++update_timelock(self, new_timelock)++`] --- - -[.contract-index] -.Internal implementations --- -.InternalImpl - -* xref:#GovernorTimelockExecutionComponent-initializer[`++initializer(self, timelock_controller)++`] -* xref:#GovernorTimelockExecutionComponent-assert_only_governance[`++assert_only_governance(self)++`] -* xref:#GovernorTimelockExecutionComponent-timelock_salt[`++timelock_salt(self, description_hash)++`] -* xref:#GovernorTimelockExecutionComponent-get_timelock_dispatcher[`++get_timelock_dispatcher(self)++`] -* xref:#GovernorTimelockExecutionComponent-_update_timelock[`++_update_timelock(self, new_timelock)++`] - --- - -[.contract-index] -.Events --- -* xref:#GovernorTimelockExecutionComponent-TimelockUpdated[`++TimelockUpdated(old_timelock, new_timelock)++`] --- - -[#GovernorTimelockExecutionComponent-Extension-Traits-Functions] -==== Extension traits functions - -[.contract-item] -[[GovernorTimelockExecutionComponent-state]] -==== `[.contract-item-name]#++state++#++(self: @ContractState, proposal_id: felt252) → ProposalState++` [.item-kind]#internal# - -Returns the state of a proposal given its id. - -Requirements: - -- The proposal must exist. - -[.contract-item] -[[GovernorTimelockExecutionComponent-executor]] -==== `[.contract-item-name]#++executor++#++(self: @ContractState) → ContractAddress++` [.item-kind]#internal# - -Returns the executor address. - -In this module, the executor is the timelock controller. - -[.contract-item] -[[GovernorTimelockExecutionComponent-execute_operations]] -==== `[.contract-item-name]#++execute_operations++#++(ref self: ContractState, proposal_id: felt252, calls: Span, description_hash: felt252)++` [.item-kind]#internal# - -Runs the already queued proposal through the timelock. - -[.contract-item] -[[GovernorTimelockExecutionComponent-queue_operations]] -==== `[.contract-item-name]#++queue_operations++#++(ref self: ContractState, proposal_id: felt252, calls: Span, description_hash: felt252) → u64++` [.item-kind]#internal# - -Queue a proposal to the timelock. - -Returns the eta for the execution of the queued proposal. - -[.contract-item] -[[GovernorTimelockExecutionComponent-proposal_needs_queuing]] -==== `[.contract-item-name]#++proposal_needs_queuing++#++(self: @ContractState, proposal_id: felt252) → bool++` [.item-kind]#internal# - -In this implementation, it always returns true. - -[.contract-item] -[[GovernorTimelockExecutionComponent-cancel_operations]] -==== `[.contract-item-name]#++cancel_operations++#++(ref self: ContractState, proposal_id: felt252, description_hash: felt252)++` [.item-kind]#internal# - -Cancels the timelocked proposal if it has already been queued. - -[#GovernorTimelockExecutionComponent-Embeddable-Functions] -==== Embeddable functions - -:TimelockUpdated: xref:#GovernorTimelockExecutionComponent-TimelockUpdated[TimelockUpdated] - -[.contract-item] -[[GovernorTimelockExecutionComponent-timelock]] -==== `[.contract-item-name]#++timelock++#++(self: @ContractState) → ContractAddress++` [.item-kind]#external# - -Returns the timelock controller address. - -[.contract-item] -[[GovernorTimelockExecutionComponent-get_timelock_id]] -==== `[.contract-item-name]#++get_timelock_id++#++(self: @ContractState) → felt252++` [.item-kind]#external# - -Returns the timelock proposal id for a given proposal id. - -[.contract-item] -[[GovernorTimelockExecutionComponent-update_timelock]] -==== `[.contract-item-name]#++update_timelock++#++(ref self: ContractState, new_timelock: ContractAddress)++` [.item-kind]#external# - -Updates the associated timelock. - -Requirements: - -- The caller must be the governance. - -Emits a {TimelockUpdated} event. - -[#GovernorTimelockExecutionComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[GovernorTimelockExecutionComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, timelock: ContractAddress)++` [.item-kind]#internal# - -Initializes the timelock controller. - -Requirements: - -- The timelock must not be the zero address. - -[.contract-item] -[[GovernorTimelockExecutionComponent-assert_only_governance]] -==== `[.contract-item-name]#++assert_only_governance++#++(self: @ContractState)++` [.item-kind]#internal# - -Ensures the caller is the executor (the timelock controller in this case). - -[.contract-item] -[[GovernorTimelockExecutionComponent-timelock_salt]] -==== `[.contract-item-name]#++timelock_salt++#++(self: @ContractState, description_hash: felt252) → felt252++` [.item-kind]#internal# - -Computes the `TimelockController` operation salt as the XOR of -the governor address and `description_hash`. - -It is computed with the governor address itself to avoid collisions across -governor instances using the same timelock. - -[.contract-item] -[[GovernorTimelockExecutionComponent-get_timelock_dispatcher]] -==== `[.contract-item-name]#++get_timelock_dispatcher++#++(self: @ContractState) → ITimelockDispatcher++` [.item-kind]#internal# - -Returns a dispatcher for interacting with the timelock controller. - -[.contract-item] -[[GovernorTimelockExecutionComponent-_update_timelock]] -==== `[.contract-item-name]#++_update_timelock++#++(ref self: ContractState, new_timelock: ContractAddress)++` [.item-kind]#internal# - -Internal function to update the timelock controller address. - -Emits a {TimelockUpdated} event. - -[#GovernorTimelockExecutionComponent-Events] -==== Events - -[.contract-item] -[[GovernorTimelockExecutionComponent-TimelockUpdated]] -==== `[.contract-item-name]#++TimelockUpdated++#++(old_timelock: ContractAddress, new_timelock: ContractAddress)++` [.item-kind]#event# - -Emitted when the timelock controller is updated. - -== Multisig - -A Multisig module enhances security and decentralization by requiring multiple signers to -approve and execute transactions. Features include configurable quorum, signer management, -and self-administration, ensuring collective decision-making and transparency for critical -operations. - -[.contract] -[[MultisigComponent]] -=== `++MultisigComponent++` - -:MultisigComponent-CallSalt: xref:MultisigComponent-CallSalt[CallSalt] -:MultisigComponent-SignerAdded: xref:MultisigComponent-SignerAdded[SignerAdded] -:MultisigComponent-SignerRemoved: xref:MultisigComponent-SignerRemoved[SignerRemoved] -:MultisigComponent-QuorumUpdated: xref:MultisigComponent-QuorumUpdated[QuorumUpdated] -:MultisigComponent-TransactionSubmitted: xref:MultisigComponent-TransactionSubmitted[TransactionSubmitted] -:MultisigComponent-TransactionConfirmed: xref:MultisigComponent-TransactionConfirmed[TransactionConfirmed] -:MultisigComponent-ConfirmationRevoked: xref:MultisigComponent-ConfirmationRevoked[ConfirmationRevoked] -:MultisigComponent-TransactionExecuted: xref:MultisigComponent-TransactionExecuted[TransactionExecuted] - -[.hljs-theme-dark] -```cairo -use openzeppelin_governance::multisig::MultisigComponent; -``` - -Component that implements <> and provides functionality for multisignature wallets, -including transaction management, quorum handling, and signer operations. - -[.contract-index] -.Embeddable Implementations --- -.MultisigImpl - -* xref:#MultisigComponent-get_quorum[`++get_quorum(self)++`] -* xref:#MultisigComponent-is_signer[`++is_signer(self, signer)++`] -* xref:#MultisigComponent-get_signers[`++get_signers(self)++`] -* xref:#MultisigComponent-is_confirmed[`++is_confirmed(self, id)++`] -* xref:#MultisigComponent-is_confirmed_by[`++is_confirmed_by(self, id, signer)++`] -* xref:#MultisigComponent-is_executed[`++is_executed(self, id)++`] -* xref:#MultisigComponent-get_submitted_block[`++get_submitted_block(self, id)++`] -* xref:#MultisigComponent-get_transaction_state[`++get_transaction_state(self, id)++`] -* xref:#MultisigComponent-get_transaction_confirmations[`++get_transaction_confirmations(self, id)++`] -* xref:#MultisigComponent-hash_transaction[`++hash_transaction(self, to, selector, calldata, salt)++`] -* xref:#MultisigComponent-hash_transaction_batch[`++hash_transaction_batch(self, calls, salt)++`] -* xref:#MultisigComponent-add_signers[`++add_signers(ref self, new_quorum, signers_to_add)++`] -* xref:#MultisigComponent-remove_signers[`++remove_signers(ref self, new_quorum, signers_to_remove)++`] -* xref:#MultisigComponent-replace_signer[`++replace_signer(ref self, signer_to_remove, signer_to_add)++`] -* xref:#MultisigComponent-change_quorum[`++change_quorum(ref self, new_quorum)++`] -* xref:#MultisigComponent-submit_transaction[`++submit_transaction(ref self, to, selector, calldata, salt)++`] -* xref:#MultisigComponent-submit_transaction_batch[`++submit_transaction_batch(ref self, calls, salt)++`] -* xref:#MultisigComponent-confirm_transaction[`++confirm_transaction(ref self, id)++`] -* xref:#MultisigComponent-revoke_confirmation[`++revoke_confirmation(ref self, id)++`] -* xref:#MultisigComponent-execute_transaction[`++execute_transaction(ref self, to, selector, calldata, salt)++`] -* xref:#MultisigComponent-execute_transaction_batch[`++execute_transaction_batch(ref self, calls, salt)++`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#MultisigComponent-initializer[`++initializer(ref self, quorum, signers)++`] -* xref:#MultisigComponent-resolve_tx_state[`++resolve_tx_state(self, id)++`] -* xref:#MultisigComponent-assert_one_of_signers[`++assert_one_of_signers(self, caller)++`] -* xref:#MultisigComponent-assert_tx_exists[`++assert_tx_exists(self, id)++`] -* xref:#MultisigComponent-assert_only_self[`++assert_only_self(self)++`] -* xref:#MultisigComponent-_add_signers[`++_add_signers(ref self, new_quorum, signers_to_add)++`] -* xref:#MultisigComponent-_remove_signers[`++_remove_signers(ref self, new_quorum, signers_to_remove)++`] -* xref:#MultisigComponent-_replace_signer[`++_replace_signer(ref self, signer_to_remove, signer_to_add)++`] -* xref:#MultisigComponent-_change_quorum[`++_change_quorum(ref self, new_quorum)++`] --- - -[.contract-index] -.Events --- -* xref:#MultisigComponent-SignerAdded[`++SignerAdded(signer)++`] -* xref:#MultisigComponent-SignerRemoved[`++SignerRemoved(signer)++`] -* xref:#MultisigComponent-QuorumUpdated[`++QuorumUpdated(old_quorum, new_quorum)++`] -* xref:#MultisigComponent-TransactionSubmitted[`++TransactionSubmitted(id, signer)++`] -* xref:#MultisigComponent-TransactionConfirmed[`++TransactionConfirmed(id, signer)++`] -* xref:#MultisigComponent-ConfirmationRevoked[`++ConfirmationRevoked(id, signer)++`] -* xref:#MultisigComponent-TransactionExecuted[`++TransactionExecuted(id)++`] -* xref:#MultisigComponent-CallSalt[`++CallSalt(id, salt)++`] --- - -[#MultisigComponent-Functions] -==== Embeddable functions - -[.contract-item] -[[MultisigComponent-get_quorum]] -==== `[.contract-item-name]#++get_quorum++#++(self: @ContractState) → u32++` [.item-kind]#external# - -Returns the current quorum value. - -[.contract-item] -[[MultisigComponent-is_signer]] -==== `[.contract-item-name]#++is_signer++#++(self: @ContractState, signer: ContractAddress) → bool++` [.item-kind]#external# - -Checks if a given `signer` is registered. - -[.contract-item] -[[MultisigComponent-get_signers]] -==== `[.contract-item-name]#++get_signers++#++(self: @ContractState) → Span++` [.item-kind]#external# - -Returns a list of all current signers. - -[.contract-item] -[[MultisigComponent-is_confirmed]] -==== `[.contract-item-name]#++is_confirmed++#++(self: @ContractState, id: TransactionID) → bool++` [.item-kind]#external# - -Returns whether the transaction with the given `id` has been confirmed. A confirmed transaction has received the required number of confirmations (quorum). - -[.contract-item] -[[MultisigComponent-is_confirmed_by]] -==== `[.contract-item-name]#++is_confirmed_by++#++(self: @ContractState, id: TransactionID, signer: ContractAddress) → bool++` [.item-kind]#external# - -Returns whether the transaction with the given `id` has been confirmed by the specified `signer`. - -[.contract-item] -[[MultisigComponent-is_executed]] -==== `[.contract-item-name]#++is_executed++#++(self: @ContractState, id: TransactionID) → bool++` [.item-kind]#external# - -Returns whether the transaction with the given `id` has been executed. - -[.contract-item] -[[MultisigComponent-get_submitted_block]] -==== `[.contract-item-name]#++get_submitted_block++#++(self: @ContractState, id: TransactionID) → u64++` [.item-kind]#external# - -Returns the block number when the transaction with the given `id` was submitted. - -[.contract-item] -[[MultisigComponent-get_transaction_state]] -==== `[.contract-item-name]#++get_transaction_state++#++(self: @ContractState, id: TransactionID) → TransactionState++` [.item-kind]#external# - -Returns the current state of the transaction with the given `id`. - -The possible states are: - -- `NotFound`: the transaction does not exist. -- `Pending`: the transaction exists but hasn't reached the required confirmations. -- `Confirmed`: the transaction has reached the required confirmations but hasn't been executed. -- `Executed`: the transaction has been executed. - -[.contract-item] -[[MultisigComponent-get_transaction_confirmations]] -==== `[.contract-item-name]#++get_transaction_confirmations++#++(self: @ContractState, id: TransactionID) → u32++` [.item-kind]#external# - -Returns the number of confirmations from registered signers for the transaction with the specified `id`. - -[.contract-item] -[[MultisigComponent-hash_transaction]] -==== `[.contract-item-name]#++hash_transaction++#++(self: @ContractState, to: ContractAddress, selector: felt252, calldata: Span, salt: felt252)++` [.item-kind]#external# - -Returns the computed identifier of a transaction containing a single call. - -[.contract-item] -[[MultisigComponent-hash_transaction_batch]] -==== `[.contract-item-name]#++hash_transaction_batch++#++(self: @ContractState, calls: Span, salt: felt252)++` [.item-kind]#external# - -Returns the computed identifier of a transaction containing a batch of calls. - -[.contract-item] -[[MultisigComponent-add_signers]] -==== `[.contract-item-name]#++add_signers++#++(ref self: ContractState, new_quorum: u32, signers_to_add: Span)++` [.item-kind]#external# - -Adds new signers and updates the quorum. - -Requirements: - -- The caller must be the contract itself. -- `new_quorum` must be less than or equal to the total number of signers after addition. - -Emits a {MultisigComponent-SignerAdded} event for each signer added. - -Emits a {MultisigComponent-QuorumUpdated} event if the quorum changes. - -[.contract-item] -[[MultisigComponent-remove_signers]] -==== `[.contract-item-name]#++remove_signers++#++(ref self: ContractState, new_quorum: u32, signers_to_remove: Span)++` [.item-kind]#external# - -Removes signers and updates the quorum. - -Requirements: - -- The caller must be the contract itself. -- `new_quorum` must be less than or equal to the total number of signers after removal. - -Emits a {MultisigComponent-SignerRemoved} event for each signer removed. - -Emits a {MultisigComponent-QuorumUpdated} event if the quorum changes. - -[.contract-item] -[[MultisigComponent-replace_signer]] -==== `[.contract-item-name]#++replace_signer++#++(ref self: ContractState, signer_to_remove: ContractAddress, signer_to_add: ContractAddress)++` [.item-kind]#external# - -Replaces an existing signer with a new signer. - -Requirements: - -- The caller must be the contract itself. -- `signer_to_remove` must be an existing signer. -- `signer_to_add` must not be an existing signer. - -Emits a {MultisigComponent-SignerRemoved} event for the removed signer. - -Emits a {MultisigComponent-SignerAdded} event for the new signer. - -[.contract-item] -[[MultisigComponent-change_quorum]] -==== `[.contract-item-name]#++change_quorum++#++(ref self: ContractState, new_quorum: u32)++` [.item-kind]#external# - -Updates the quorum value to `new_quorum`. - -Requirements: - -- The caller must be the contract itself. -- `new_quorum` must be non-zero. -- `new_quorum` must be less than or equal to the total number of signers. - -Emits a {MultisigComponent-QuorumUpdated} event if the quorum changes. - -[.contract-item] -[[MultisigComponent-submit_transaction]] -==== `[.contract-item-name]#++submit_transaction++#++(ref self: ContractState, to: ContractAddress, selector: felt252, calldata: Span, salt: felt252)++` [.item-kind]#external# - -Submits a new transaction for confirmation. - -Requirements: - -- The caller must be a registered signer. -- The transaction must not have been submitted before. - -Emits a {MultisigComponent-TransactionSubmitted} event. - -Emits a {MultisigComponent-CallSalt} event if `salt` is not zero. - -[.contract-item] -[[MultisigComponent-submit_transaction_batch]] -==== `[.contract-item-name]#++submit_transaction_batch++#++(ref self: ContractState, calls: Span, salt: felt252)++` [.item-kind]#external# - -Submits a new batch transaction for confirmation. - -Requirements: - -- The caller must be a registered signer. -- The transaction must not have been submitted before. - -Emits a {MultisigComponent-TransactionSubmitted} event. - -Emits a {MultisigComponent-CallSalt} event if `salt` is not zero. - -[.contract-item] -[[MultisigComponent-confirm_transaction]] -==== `[.contract-item-name]#++confirm_transaction++#++(ref self: ContractState, id: TransactionID)++` [.item-kind]#external# - -Confirms a transaction with the given `id`. - -Requirements: - -- The caller must be a registered signer. -- The transaction must exist and not be executed. -- The caller must not have already confirmed the transaction. - -Emits a {MultisigComponent-TransactionConfirmed} event. - -[.contract-item] -[[MultisigComponent-revoke_confirmation]] -==== `[.contract-item-name]#++revoke_confirmation++#++(ref self: ContractState, id: TransactionID)++` [.item-kind]#external# - -Revokes a previous confirmation for a transaction with the given `id`. - -Requirements: - -- The transaction must exist and not be executed. -- The caller must have previously confirmed the transaction. - -Emits a {MultisigComponent-ConfirmationRevoked} event. - -[.contract-item] -[[MultisigComponent-execute_transaction]] -==== `[.contract-item-name]#++execute_transaction++#++(ref self: ContractState, to: ContractAddress, selector: felt252, calldata: Span, salt: felt252)++` [.item-kind]#external# - -Executes a confirmed transaction. - -Requirements: - -- The caller must be a registered signer. -- The transaction must be confirmed and not yet executed. - -Emits a {MultisigComponent-TransactionExecuted} event. - -[.contract-item] -[[MultisigComponent-execute_transaction_batch]] -==== `[.contract-item-name]#++execute_transaction_batch++#++(ref self: ContractState, calls: Span, salt: felt252)++` [.item-kind]#external# - -Executes a confirmed batch transaction. - -Requirements: - -- The caller must be a registered signer. -- The transaction must be confirmed and not yet executed. - -Emits a {MultisigComponent-TransactionExecuted} event. - -[#MultisigComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[MultisigComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, quorum: u32, signers: Span)++` [.item-kind]#internal# - -Initializes the Multisig component with the initial `quorum` and `signers`. -This function must be called during contract initialization to set up the initial state. - -Requirements: - -- `quorum` must be non-zero and less than or equal to the number of `signers`. - -Emits a {MultisigComponent-SignerAdded} event for each signer added. - -Emits a {MultisigComponent-QuorumUpdated} event. - -[.contract-item] -[[MultisigComponent-resolve_tx_state]] -==== `[.contract-item-name]#++resolve_tx_state++#++(self: @ContractState, id: TransactionID) → TransactionState++` [.item-kind]#internal# - -Resolves and returns the current state of the transaction with the given `id`. - -The possible states are: - -- `NotFound`: the transaction does not exist. -- `Pending`: the transaction exists but hasn't reached the required confirmations. -- `Confirmed`: the transaction has reached the required confirmations but hasn't been executed. -- `Executed`: the transaction has been executed. - -[.contract-item] -[[MultisigComponent-assert_one_of_signers]] -==== `[.contract-item-name]#++assert_one_of_signers++#++(self: @ContractState, caller: ContractAddress)++` [.item-kind]#internal# - -Asserts that the `caller` is one of the registered signers. - -Requirements: - -- The `caller` must be a registered signer. - -[.contract-item] -[[MultisigComponent-assert_tx_exists]] -==== `[.contract-item-name]#++assert_tx_exists++#++(self: @ContractState, id: TransactionID)++` [.item-kind]#internal# - -Asserts that a transaction with the given `id` exists. - -Requirements: - -- The transaction with the given `id` must have been submitted. - -[.contract-item] -[[MultisigComponent-assert_only_self]] -==== `[.contract-item-name]#++assert_only_self++#++(self: @ContractState)++` [.item-kind]#internal# - -Asserts that the caller is the contract itself. - -Requirements: - -- The caller must be the contract's own address. - -[.contract-item] -[[MultisigComponent-_add_signers]] -==== `[.contract-item-name]#++_add_signers++#++(ref self: ContractState, new_quorum: u32, signers_to_add: Span)++` [.item-kind]#internal# - -Adds new signers and updates the quorum. - -Requirements: - -- Each signer address must be non-zero. -- `new_quorum` must be non-zero and less than or equal to the total number of signers after addition. - -Emits a {MultisigComponent-SignerAdded} event for each new signer added. - -Emits a {MultisigComponent-QuorumUpdated} event if the quorum changes. - -[.contract-item] -[[MultisigComponent-_remove_signers]] -==== `[.contract-item-name]#++_remove_signers++#++(ref self: ContractState, new_quorum: u32, signers_to_remove: Span)++` [.item-kind]#internal# - -Removes existing signers and updates the quorum. - -Requirements: - -- `new_quorum` must be non-zero and less than or equal to the total number of signers -after removal. - -Emits a {MultisigComponent-SignerRemoved} event for each signer removed. - -Emits a {MultisigComponent-QuorumUpdated} event if the quorum changes. - -[.contract-item] -[[MultisigComponent-_replace_signer]] -==== `[.contract-item-name]#++_replace_signer++#++(ref self: ContractState, signer_to_remove: ContractAddress, signer_to_add: ContractAddress)++` [.item-kind]#internal# - -Replaces an existing signer with a new signer. - -Requirements: - -- `signer_to_remove` must be an existing signer. -- `signer_to_add` must not be an existing signer. -- `signer_to_add` must be a non-zero address. - -Emits a {MultisigComponent-SignerRemoved} event for the removed signer. - -Emits a {MultisigComponent-SignerAdded} event for the new signer. - -[.contract-item] -[[MultisigComponent-_change_quorum]] -==== `[.contract-item-name]#++_change_quorum++#++(ref self: ContractState, new_quorum: u32)++` [.item-kind]#internal# - -Updates the quorum value to `new_quorum` if it differs from the current quorum. - -Requirements: - -- `new_quorum` must be non-zero. -- `new_quorum` must be less than or equal to the total number of signers. - -Emits a {MultisigComponent-QuorumUpdated} event if the quorum changes. - -[#MultisigComponent-Events] -==== Events - -[.contract-item] -[[MultisigComponent-SignerAdded]] -==== `[.contract-item-name]#++SignerAdded++#++(signer: ContractAddress)++` [.item-kind]#event# - -Emitted when a new `signer` is added. - -[.contract-item] -[[MultisigComponent-SignerRemoved]] -==== `[.contract-item-name]#++SignerRemoved++#++(signer: ContractAddress)++` [.item-kind]#event# - -Emitted when a `signer` is removed. - -[.contract-item] -[[MultisigComponent-QuorumUpdated]] -==== `[.contract-item-name]#++QuorumUpdated++#++(old_quorum: u32, new_quorum: u32)++` [.item-kind]#event# - -Emitted when the `quorum` value is updated. - -[.contract-item] -[[MultisigComponent-TransactionSubmitted]] -==== `[.contract-item-name]#++TransactionSubmitted++#++(id: TransactionID, signer: ContractAddress)++` [.item-kind]#event# - -Emitted when a new transaction is submitted by a `signer`. - -[.contract-item] -[[MultisigComponent-TransactionConfirmed]] -==== `[.contract-item-name]#++TransactionConfirmed++#++(id: TransactionID, signer: ContractAddress)++` [.item-kind]#event# - -Emitted when a transaction is confirmed by a `signer`. - -[.contract-item] -[[MultisigComponent-ConfirmationRevoked]] -==== `[.contract-item-name]#++ConfirmationRevoked++#++(id: TransactionID, signer: ContractAddress)++` [.item-kind]#event# - -Emitted when a `signer` revokes his confirmation. - -[.contract-item] -[[MultisigComponent-TransactionExecuted]] -==== `[.contract-item-name]#++TransactionExecuted++#++(id: TransactionID)++` [.item-kind]#event# - -Emitted when a transaction is executed. - -[.contract-item] -[[MultisigComponent-CallSalt]] -==== `[.contract-item-name]#++CallSalt++#++(id: felt252, salt: felt252)++` [.item-kind]#event# - -Emitted when a new transaction is submitted with non-zero salt. - -== Timelock - -In a governance system, `TimelockControllerComponent` is in charge of introducing a delay between a proposal and its execution. - -[.contract] -[[TimelockControllerComponent]] -=== `++TimelockControllerComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/governance/src/timelock/timelock_controller.cairo[{github-icon},role=heading-link] - -:TimelockComponent-CallScheduled: xref:TimelockControllerComponent-CallScheduled[CallScheduled] -:TimelockComponent-CallExecuted: xref:TimelockControllerComponent-CallExecuted[CallExecuted] -:TimelockComponent-CallSalt: xref:TimelockControllerComponent-CallSalt[CallSalt] -:TimelockComponent-CallCancelled: xref:TimelockControllerComponent-CallCancelled[CallCancelled] -:TimelockComponent-MinDelayChanged: xref:TimelockControllerComponent-MinDelayChanged[MinDelayChanged] - -include::../utils/_common.adoc[] - -[.hljs-theme-dark] -```cairo -use openzeppelin_governance::timelock::TimelockControllerComponent; -``` - -Component that implements <> and enables the implementing contract to act as a timelock controller. - -[.contract-index#TimelockControllerComponent-Embeddable-Mixin-Impl] -.{mixin-impls} - --- -.TimelockMixinImpl - -* xref:#TimelockControllerComponent-Embeddable-Impls-TimelockImpl[`++TimelockImpl++`] -* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls[`++SRC5Impl++`] -* xref:api/access.adoc#AccessControlComponent-Embeddable-Impls[`++AccessControlImpl++`] -* xref:api/access.adoc#AccessControlComponent-Embeddable-Impls[`++AccessControlCamelImpl++`] --- - -[.contract-index#TimelockControllerComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#TimelockControllerComponent-Embeddable-Impls-TimelockImpl] -.TimelockImpl - -* xref:#TimelockControllerComponent-is_operation[`++is_operation(self, id)++`] -* xref:#TimelockControllerComponent-is_operation_pending[`++is_operation_pending(self, id)++`] -* xref:#TimelockControllerComponent-is_operation_ready[`++is_operation_ready(self, id)++`] -* xref:#TimelockControllerComponent-is_operation_done[`++is_operation_done(self, id)++`] -* xref:#TimelockControllerComponent-get_timestamp[`++get_timestamp(self, id)++`] -* xref:#TimelockControllerComponent-get_operation_state[`++get_operation_state(self, id)++`] -* xref:#TimelockControllerComponent-get_min_delay[`++get_min_delay(self)++`] -* xref:#TimelockControllerComponent-hash_operation[`++hash_operation(self, call, predecessor, salt)++`] -* xref:#TimelockControllerComponent-hash_operation_batch[`++hash_operation_batch(self, calls, predecessor, salt)++`] -* xref:#TimelockControllerComponent-schedule[`++schedule(self, call, predecessor, salt, delay)++`] -* xref:#TimelockControllerComponent-schedule_batch[`++schedule_batch(self, calls, predecessor, salt, delay)++`] -* xref:#TimelockControllerComponent-cancel[`++cancel(self, id)++`] -* xref:#TimelockControllerComponent-execute[`++execute(self, call, predecessor, salt)++`] -* xref:#TimelockControllerComponent-execute_batch[`++execute_batch(self, calls, predecessor, salt)++`] -* xref:#TimelockControllerComponent-update_delay[`++update_delay(self, new_delay)++`] - -.SRC5Impl -* xref:api/introspection.adoc#ISRC5-supports_interface[`supports_interface(self, interface_id: felt252)`] - -.AccessControlImpl -* xref:api/access.adoc#IAccessControl-has_role[`++has_role(self, role, account)++`] -* xref:api/access.adoc#IAccessControl-get_role_admin[`++get_role_admin(self, role)++`] -* xref:api/access.adoc#IAccessControl-grant_role[`++grant_role(self, role, account)++`] -* xref:api/access.adoc#IAccessControl-revoke_role[`++revoke_role(self, role, account)++`] -* xref:api/access.adoc#IAccessControl-renounce_role[`++renounce_role(self, role, account)++`] - -.AccessControlCamelImpl -* xref:api/access.adoc#IAccessControl-hasRole[`++hasRole(self, role, account)++`] -* xref:api/access.adoc#IAccessControl-getRoleAdmin[`++getRoleAdmin(self, role)++`] -* xref:api/access.adoc#IAccessControl-grantRole[`++grantRole(self, role, account)++`] -* xref:api/access.adoc#IAccessControl-revokeRole[`++revokeRole(self, role, account)++`] -* xref:api/access.adoc#IAccessControl-renounceRole[`++renounceRole(self, role, account)++`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#TimelockControllerComponent-initializer[`++initializer(self, min_delay, proposers, executors, admin)++`] -* xref:#TimelockControllerComponent-assert_only_role[`++assert_only_role(self, role)++`] -* xref:#TimelockControllerComponent-assert_only_role_or_open_role[`++assert_only_role_or_open_role(self, role)++`] -* xref:#TimelockControllerComponent-assert_only_self[`++assert_only_self(self)++`] -* xref:#TimelockControllerComponent-_before_call[`++_before_call(self, id, predecessor)++`] -* xref:#TimelockControllerComponent-_after_call[`++_after_call(self, id)++`] -* xref:#TimelockControllerComponent-_schedule[`++_schedule(self, id, delay)++`] -* xref:#TimelockControllerComponent-_execute[`++_execute(self, call)++`] --- - -[.contract-index] -.Events --- -* xref:#TimelockControllerComponent-CallScheduled[`++CallScheduled(id, index, call, predecessor, delay)++`] -* xref:#TimelockControllerComponent-CallExecuted[`++CallExecuted(id, index, call)++`] -* xref:#TimelockControllerComponent-CallSalt[`++CallSalt(id, salt)++`] -* xref:#TimelockControllerComponent-CallCancelled[`++CallCancelled(id)++`] -* xref:#TimelockControllerComponent-MinDelayChanged[`++MinDelayChanged(old_duration, new_duration)++`] --- - -[#TimelockControllerComponent-Functions] -==== Embeddable functions - -[.contract-item] -[[TimelockControllerComponent-is_operation]] -==== `[.contract-item-name]#++is_operation++#++(self: @ContractState, id: felt252) → bool++` [.item-kind]#external# - -Returns whether `id` corresponds to a registered operation. -This includes the OperationStates: `Waiting`, `Ready`, and `Done`. - -[.contract-item] -[[TimelockControllerComponent-is_operation_pending]] -==== `[.contract-item-name]#++is_operation_pending++#++(self: @ContractState, id: felt252) → bool++` [.item-kind]#external# - -Returns whether the `id` OperationState is pending or not. -Note that a pending operation may be either `Waiting` or `Ready`. - -[.contract-item] -[[TimelockControllerComponent-is_operation_ready]] -==== `[.contract-item-name]#++is_operation_ready++#++(self: @ContractState, id: felt252) → bool++` [.item-kind]#external# - -Returns whether the `id` OperationState is `Ready` or not. - -[.contract-item] -[[TimelockControllerComponent-is_operation_done]] -==== `[.contract-item-name]#++is_operation_done++#++(self: @ContractState, id: felt252) → bool++` [.item-kind]#external# - -Returns whether the `id` OperationState is `Done` or not. - -[.contract-item] -[[TimelockControllerComponent-get_timestamp]] -==== `[.contract-item-name]#++get_timestamp++#++(self: @ContractState, id: felt252) → u64++` [.item-kind]#external# - -Returns the timestamp at which `id` becomes `Ready`. - -NOTE: `0` means the OperationState is `Unset` and `1` means the OperationState -is `Done`. - -[.contract-item] -[[TimelockControllerComponent-get_operation_state]] -==== `[.contract-item-name]#++get_operation_state++#++(self: @ContractState, id: felt252) → OperationState++` [.item-kind]#external# - -Returns the current state of the operation with the given `id`. - -The possible states are: - -- `Unset`: the operation has not been scheduled or has been canceled. -- `Waiting`: the operation has been scheduled and is pending the scheduled delay. -- `Ready`: the timer has expired, and the operation is eligible for execution. -- `Done`: the operation has been executed. - -[.contract-item] -[[TimelockControllerComponent-get_min_delay]] -==== `[.contract-item-name]#++get_min_delay++#++(self: @ContractState) → u64++` [.item-kind]#external# - -Returns the minimum delay in seconds for an operation to become valid. -This value can be changed by executing an operation that calls `update_delay`. - -[.contract-item] -[[TimelockControllerComponent-hash_operation]] -==== `[.contract-item-name]#++hash_operation++#++(self: @ContractState, call: Call, predecessor: felt252, salt: felt252)++` [.item-kind]#external# - -Returns the identifier of an operation containing a single transaction. - -[.contract-item] -[[TimelockControllerComponent-hash_operation_batch]] -==== `[.contract-item-name]#++hash_operation_batch++#++(self: @ContractState, calls: Span, predecessor: felt252, salt: felt252)++` [.item-kind]#external# - -Returns the identifier of an operation containing a batch of transactions. - -[.contract-item] -[[TimelockControllerComponent-schedule]] -==== `[.contract-item-name]#++schedule++#++(ref self: ContractState, call: Call, predecessor: felt252, salt: felt252, delay: u64)++` [.item-kind]#external# - -Schedule an operation containing a single transaction. - -Requirements: - -- The caller must have the `PROPOSER_ROLE` role. -- The proposal must not already exist. -- `delay` must be greater than or equal to the min delay. - -Emits {TimelockComponent-CallScheduled} event. -Emits {TimelockComponent-CallSalt} event if `salt` is not zero. - -[.contract-item] -[[TimelockControllerComponent-schedule_batch]] -==== `[.contract-item-name]#++schedule_batch++#++(ref self: ContractState, calls: Span, predecessor: felt252, salt: felt252, delay: u64)++` [.item-kind]#external# - -Schedule an operation containing a batch of transactions. - -Requirements: - -- The caller must have the `PROPOSER_ROLE` role. -- The proposal must not already exist. -- `delay` must be greater than or equal to the min delay. - -Emits one {TimelockComponent-CallScheduled} event for each transaction in the batch. -Emits {TimelockComponent-CallSalt} event if `salt` is not zero. - -[.contract-item] -[[TimelockControllerComponent-cancel]] -==== `[.contract-item-name]#++cancel++#++(ref self: ContractState, id: felt252)++` [.item-kind]#external# - -Cancels an operation. A canceled operation returns to `Unset` OperationState. - -Requirements: - -- The caller must have the `CANCELLER_ROLE` role. -- `id` must be a pending operation. - -Emits a {TimelockComponent-CallCancelled} event. - -[.contract-item] -[[TimelockControllerComponent-execute]] -==== `[.contract-item-name]#++execute++#++(ref self: ContractState, call: Call, predecessor: felt252, salt: felt252)++` [.item-kind]#external# - -Execute a (Ready) operation containing a single Call. - -Requirements: - -- Caller must have `EXECUTOR_ROLE`. -- `id` must be in Ready OperationState. -- `predecessor` must either be `0` or in Done OperationState. - -Emits a {TimelockComponent-CallExecuted} event. - -NOTE: This function can reenter, but it doesn't pose a risk because <> -checks that the proposal is pending, thus any modifications to the operation during -reentrancy should be caught. - -[.contract-item] -[[TimelockControllerComponent-execute_batch]] -==== `[.contract-item-name]#++execute_batch++#++(ref self: ContractState, calls: Span, predecessor: felt252, salt: felt252)++` [.item-kind]#external# - -Execute a (Ready) operation containing a batch of Calls. - -Requirements: - -- Caller must have `EXECUTOR_ROLE`. -- `id` must be in Ready OperationState. -- `predecessor` must either be `0` or in Done OperationState. - -Emits a {TimelockComponent-CallExecuted} event for each Call. - -NOTE: This function can reenter, but it doesn't pose a risk because `_after_call` -checks that the proposal is pending, thus any modifications to the operation during -reentrancy should be caught. - -[.contract-item] -[[TimelockControllerComponent-update_delay]] -==== `[.contract-item-name]#++update_delay++#++(ref self: ContractState, new_delay: u64)++` [.item-kind]#external# - -Changes the minimum timelock duration for future operations. - -Requirements: - -- The caller must be the timelock itself. This can only be achieved by scheduling -and later executing an operation where the timelock is the target and the data -is the serialized call to this function. - -Emits a {TimelockComponent-MinDelayChanged} event. - -[#TimelockControllerComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[TimelockControllerComponent-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, min_delay: u64, proposers: Span, executors: Span, admin: ContractAddress)++` [.item-kind]#internal# - -Initializes the contract by registering support for SRC5 and AccessControl. - -This function also configures the contract with the following parameters: - -- `min_delay`: initial minimum delay in seconds for operations. -- `proposers`: accounts to be granted proposer and canceller roles. -- `executors`: accounts to be granted executor role. -- `admin`: optional account to be granted admin role; disable with zero address. - -WARNING: The optional admin can aid with initial configuration of roles after deployment -without being subject to delay, but this role should be subsequently renounced in favor of -administration through timelocked proposals. - -Emits two {IAccessControl-RoleGranted} events for each account in `proposers` with `PROPOSER_ROLE` and -`CANCELLER_ROLE` roles. - -Emits a {IAccessControl-RoleGranted} event for each account in `executors` with `EXECUTOR_ROLE` role. - -May emit a {IAccessControl-RoleGranted} event for `admin` with `DEFAULT_ADMIN_ROLE` role (if `admin` is -not zero). - -Emits {TimelockComponent-MinDelayChanged} event. - -[.contract-item] -[[TimelockControllerComponent-assert_only_role]] -==== `[.contract-item-name]#++assert_only_role++#++(self: @ContractState, role: felt252)++` [.item-kind]#internal# - -Validates that the caller has the given `role`. -Otherwise it panics. - -[.contract-item] -[[TimelockControllerComponent-assert_only_role_or_open_role]] -==== `[.contract-item-name]#++assert_only_role_or_open_role++#++(self: @ContractState, role: felt252)++` [.item-kind]#internal# - -Validates that the caller has the given `role`. -If `role` is granted to the zero address, then this is considered an open role which allows anyone to be the caller. - -[.contract-item] -[[TimelockControllerComponent-assert_only_self]] -==== `[.contract-item-name]#++assert_only_self++#++(self: @ContractState)++` [.item-kind]#internal# - -Validates that the caller is the timelock contract itself. -Otherwise it panics. - -[.contract-item] -[[TimelockControllerComponent-_before_call]] -==== `[.contract-item-name]#++_before_call++#++(self: @ContractState, id: felt252, predecessor: felt252)++` [.item-kind]#internal# - -Private function that checks before execution of an operation's calls. - -Requirements: - -- `id` must be in the `Ready` OperationState. -- `predecessor` must either be zero or be in the `Done` OperationState. - -[.contract-item] -[[TimelockControllerComponent-_after_call]] -==== `[.contract-item-name]#++_after_call++#++(self: @ContractState, id: felt252)++` [.item-kind]#internal# - -Private function that checks after execution of an operation's calls -and sets the OperationState of `id` to `Done`. - -Requirements: - -- `id` must be in the Ready OperationState. - -[.contract-item] -[[TimelockControllerComponent-_schedule]] -==== `[.contract-item-name]#++_schedule++#++(ref self: ContractState, id: felt252, delay: u64)++` [.item-kind]#internal# - -Private function that schedules an operation that is to become valid after a given `delay`. - -[.contract-item] -[[TimelockControllerComponent-_execute]] -==== `[.contract-item-name]#++_execute++#++(ref self: ContractState, call: Call)++` [.item-kind]#internal# - -Private function that executes an operation's calls. - -[#TimelockControllerComponent-Events] -==== Events - -[.contract-item] -[[TimelockControllerComponent-CallScheduled]] -==== `[.contract-item-name]#++CallScheduled++#++(id: felt252, index: felt252, call: Call, predecessor: felt252, delay: u64)++` [.item-kind]#event# - -Emitted when `call` is scheduled as part of operation `id`. - -[.contract-item] -[[TimelockControllerComponent-CallExecuted]] -==== `[.contract-item-name]#++CallExecuted++#++(id: felt252, index: felt252, call: Call)++` [.item-kind]#event# - -Emitted when `call` is performed as part of operation `id`. - -[.contract-item] -[[TimelockControllerComponent-CallSalt]] -==== `[.contract-item-name]#++CallSalt++#++(id: felt252, salt: felt252)++` [.item-kind]#event# - -Emitted when a new proposal is scheduled with non-zero salt. - -[.contract-item] -[[TimelockControllerComponent-CallCancelled]] -==== `[.contract-item-name]#++CallCancelled++#++(id: felt252)++` [.item-kind]#event# - -Emitted when operation `id` is cancelled. - -[.contract-item] -[[TimelockControllerComponent-MinDelayChanged]] -==== `[.contract-item-name]#++MinDelayChanged++#++(old_duration: u64, new_duration: u64)++` [.item-kind]#event# - -Emitted when the minimum delay for future operations is modified. - -== Votes - -The `VotesComponent` provides a flexible system for tracking and delegating voting power. This system allows users to delegate their voting power to other addresses, enabling more active participation in governance. - -[.contract] -[[VotesComponent]] -=== `++VotesComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/governance/src/votes/votes.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_governance::votes::VotesComponent; -``` -Component that implements the {IVotes} interface and provides a flexible system for tracking and delegating voting power. - -By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. - -NOTE: When using this module, your contract must implement the {VotingUnitsTrait}. For convenience, this is done automatically for `ERC20` and `ERC721` tokens. - -[.contract-index] -.Voting Units Trait Implementations --- -.ERC20VotesImpl -* xref:#VotesComponent-ERC20VotesImpl-get_voting_units[`++get_voting_units(self, account)++`] - -.ERC721VotesImpl -* xref:#VotesComponent-ERC721VotesImpl-get_voting_units[`++get_voting_units(self, account)++`] --- - -[.contract-index#VotesComponent-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#VotesComponent-Embeddable-Impls-VotesImpl] -.VotesImpl -* xref:#VotesComponent-get_votes[`++get_votes(self, account)++`] -* xref:#VotesComponent-get_past_votes[`++get_past_votes(self, account, timepoint)++`] -* xref:#VotesComponent-get_past_total_supply[`++get_past_total_supply(self, timepoint)++`] -* xref:#VotesComponent-delegates[`++delegates(self, account)++`] -* xref:#VotesComponent-delegate[`++delegate(self, delegatee)++`] -* xref:#VotesComponent-delegate_by_sig[`++delegate_by_sig(self, delegator, delegatee, nonce, expiry, signature)++`] -* xref:#VotesComponent-clock[`++clock(self)++`] -* xref:#VotesComponent-CLOCK_MODE[`++CLOCK_MODE(self)++`] --- - -[.contract-index] -.Internal implementations --- -.InternalImpl -* xref:#VotesComponent-get_total_supply[`++get_total_supply(self)++`] -* xref:#VotesComponent-move_delegate_votes[`++move_delegate_votes(self, from, to, amount)++`] -* xref:#VotesComponent-transfer_voting_units[`++transfer_voting_units(self, from, to, amount)++`] -* xref:#VotesComponent-num_checkpoints[`++num_checkpoints(self, account)++`] -* xref:#VotesComponent-checkpoints[`++checkpoints(self, account, pos)++`] -* xref:#VotesComponent-_delegate[`++_delegate(self, account, delegatee)++`] --- - -[.contract-index] -.Events --- -* xref:#VotesComponent-DelegateChanged[`++DelegateChanged(delegator, from_delegate, to_delegate)++`] -* xref:#VotesComponent-DelegateVotesChanged[`++DelegateVotesChanged(delegate, previous_votes, new_votes)++`] --- - -[#VotesComponent-ERC20VotesImpl] -==== ERC20VotesImpl - -[.contract-item] -[[VotesComponent-ERC20VotesImpl-get_voting_units]] -==== `[.contract-item-name]#++get_voting_units++#++(self: @ContractState, account: ContractAddress) → u256++` [.item-kind]#internal# - -Returns the number of voting units for a given account. - -This implementation is specific to ERC20 tokens, where the balance -of tokens directly represents the number of voting units. - -NOTE: This implementation will work out of the box if the ERC20 component -is implemented in the final contract. - -WARNING: This implementation assumes tokens map to voting units 1:1. -Any deviation from this formula when transferring voting units (e.g. by using hooks) -may compromise the internal vote accounting. - -[#VotesComponent-ERC721VotesImpl] -==== ERC721VotesImpl - -[.contract-item] -[[VotesComponent-ERC721VotesImpl-get_voting_units]] -==== `[.contract-item-name]#++get_voting_units++#++(self: @ContractState, account: ContractAddress) → u256++` [.item-kind]#internal# - -Returns the number of voting units for a given account. - -This implementation is specific to ERC721 tokens, where each token -represents one voting unit. The function returns the balance of -ERC721 tokens for the specified account. - -NOTE: This implementation will work out of the box if the ERC721 component -is implemented in the final contract. - -WARNING: This implementation assumes tokens map to voting units 1:1. -Any deviation from this formula when transferring voting units (e.g. by using hooks) -may compromise the internal vote accounting. - -[#VotesComponent-Functions] -==== Embeddable functions - -[.contract-item] -[[VotesComponent-get_votes]] -==== `[.contract-item-name]#++get_votes++#++(self: @ContractState, account: ContractAddress) → u256++` [.item-kind]#external# - -Returns the current amount of votes that `account` has. - -[.contract-item] -[[VotesComponent-get_past_votes]] -==== `[.contract-item-name]#++get_past_votes++#++(self: @ContractState, account: ContractAddress, timepoint: u64) → u256++` [.item-kind]#external# - -Returns the amount of votes that `account` had at a specific moment in the past. - -Requirements: - -- `timepoint` must be in the past. - -[.contract-item] -[[VotesComponent-get_past_total_supply]] -==== `[.contract-item-name]#++get_past_total_supply++#++(self: @ContractState, timepoint: u64) → u256++` [.item-kind]#external# - -Returns the total supply of votes available at a specific moment in the past. - -NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. -Votes that have not been delegated are still part of total supply, even though they would not participate in a -vote. - -Requirements: - -- `timepoint` must be in the past. - -[.contract-item] -[[VotesComponent-delegates]] -==== `[.contract-item-name]#++delegates++#++(self: @ContractState, account: ContractAddress) → ContractAddress++` [.item-kind]#external# - -Returns the delegate that `account` has chosen. - -[.contract-item] -[[VotesComponent-delegate]] -==== `[.contract-item-name]#++delegate++#++(ref self: ContractState, delegatee: ContractAddress)++` [.item-kind]#external# - -Delegates votes from the sender to `delegatee`. - -Emits a {VotesComponent-DelegateChanged} event. - -May emit one or two {VotesComponent-DelegateVotesChanged} events. - -[.contract-item] -[[VotesComponent-delegate_by_sig]] -==== `[.contract-item-name]#++delegate_by_sig++#++(ref self: ContractState, delegator: ContractAddress, delegatee: ContractAddress, nonce: felt252, expiry: u64, signature: Span)++` [.item-kind]#external# - -Delegates votes from `delegator` to `delegatee` through a {SNIP-12} message signature validation. - -Requirements: - -- `expiry` must not be in the past. -- `nonce` must match the account's current nonce. -- `delegator` must implement `SRC6::is_valid_signature`. -- `signature` should be valid for the message hash. - -Emits a {VotesComponent-DelegateChanged} event. - -May emit one or two {VotesComponent-DelegateVotesChanged} events. - -[.contract-item] -[[VotesComponent-clock]] -==== `[.contract-item-name]#++clock++#++(self: @ContractState) → u64++` [.item-kind]#external# - -Returns the current timepoint determined by the contract’s operational mode, intended for use in time-sensitive logic. -See {ERC-6372-clock}. - -Requirements: - -- This function MUST always be non-decreasing. - -[.contract-item] -[[VotesComponent-CLOCK_MODE]] -==== `[.contract-item-name]#++CLOCK_MODE++#++(self: @ContractState) → u64++` [.item-kind]#external# - -Returns a description of the clock the contract is operating in. -See {ERC-6372-clock-mode}. - -Requirements: - -- The output MUST be formatted like a URL query string, decodable in standard JavaScript. - -[#VotesComponent-Internal-functions] -==== Internal functions - -[.contract-item] -[[VotesComponent-get_total_supply]] -==== `[.contract-item-name]#++get_total_supply++#++(self: @ContractState) → u256++` [.item-kind]#internal# - -Returns the current total supply of votes. - -[.contract-item] -[[VotesComponent-move_delegate_votes]] -==== `[.contract-item-name]#++move_delegate_votes++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256)++` [.item-kind]#internal# - -Moves delegated votes from one delegate to another. - -May emit one or two {VotesComponent-DelegateVotesChanged} events. - -[.contract-item] -[[VotesComponent-transfer_voting_units]] -==== `[.contract-item-name]#++transfer_voting_units++#++(ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256)++` [.item-kind]#internal# - -Transfers, mints, or burns voting units. - -To register a mint, `from` should be zero. To register a burn, `to` -should be zero. Total supply of voting units will be adjusted with mints and burns. - -WARNING: If voting units are based on an underlying transferable asset (like a token), you must call this function every time the asset is transferred to keep the internal voting power accounting in sync. For ERC20 and ERC721 tokens, this is typically handled using hooks. - -May emit one or two {VotesComponent-DelegateVotesChanged} events. - -[.contract-item] -[[VotesComponent-num_checkpoints]] -==== `[.contract-item-name]#++num_checkpoints++#++(self: @ContractState, account: ContractAddress) → u64++` [.item-kind]#internal# - -Returns the number of checkpoints for `account`. - -[.contract-item] -[[VotesComponent-checkpoints]] -==== `[.contract-item-name]#++checkpoints++#++(self: @ContractState, account: ContractAddress, pos: u64) → Checkpoint++` [.item-kind]#internal# - -Returns the `pos`-th checkpoint for `account`. - -[.contract-item] -[[VotesComponent-_delegate]] -==== `[.contract-item-name]#++_delegate++#++(ref self: ContractState, account: ContractAddress, delegatee: ContractAddress)++` [.item-kind]#internal# - -Delegates all of ``account``'s voting units to `delegatee`. - -Emits a {VotesComponent-DelegateChanged} event. - -May emit one or two {VotesComponent-DelegateVotesChanged} events. - -[#VotesComponent-Events] -==== Events - -[.contract-item] -[[VotesComponent-DelegateChanged]] -==== `[.contract-item-name]#++DelegateChanged++#++(delegator: ContractAddress, from_delegate: ContractAddress, to_delegate: ContractAddress)++` [.item-kind]#event# - -Emitted when an account changes their delegate. - -[.contract-item] -[[VotesComponent-DelegateVotesChanged]] -==== `[.contract-item-name]#++DelegateVotesChanged++#++(delegate: ContractAddress, previous_votes: u256, new_votes: u256)++` [.item-kind]#event# - -Emitted when a token transfer or delegate change results in changes to a delegate's number of votes. - -[.contract] -[[VotingUnitsTrait]] -=== `++VotingUnitsTrait++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/governance/src/votes/votes.cairo[{github-icon},role=heading-link] - -```cairo -pub trait VotingUnitsTrait { - fn get_voting_units(self: @TState, account: ContractAddress) -> u256; -} -``` - -A trait that must be implemented when integrating {VotesComponent} into a contract. It offers a mechanism to retrieve the number of voting units for a given account at the current time. - -[.contract-index] -.Functions --- -* xref:#VotingUnitsTrait-get_voting_units[`++get_voting_units(self, account)++`] --- - -[#VotingUnitsTrait-Functions] -==== Functions - -[.contract-item] -[[VotingUnitsTrait-get_voting_units]] -==== `[.contract-item-name]#++get_voting_units++#++(self: @TState, account: ContractAddress) → u256++` [.item-kind]#external# - -Returns the number of voting units for a given account. For ERC20, this is typically the token balance. For ERC721, this is typically the number of tokens owned. - -WARNING: While any formula can be used as a measure of voting units, the internal vote accounting of the contract may be -compromised if voting units are transferred in any external flow by following a different formula. + -For example, when implementing the hook for ERC20, the number of voting units transferred should match the formula given by the -`get_voting_units` implementation. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/api/introspection.adoc b/docs/modules/ROOT/pages/api/introspection.adoc deleted file mode 100644 index 6b73653c7..000000000 --- a/docs/modules/ROOT/pages/api/introspection.adoc +++ /dev/null @@ -1,102 +0,0 @@ -:github-icon: pass:[] -:snip5: https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md[SNIP-5] -:inner-src5: xref:api/introspection.adoc#ISRC5[SRC5 ID] - -= Introspection - -This crate handles https://en.wikipedia.org/wiki/Type_introspection[type introspection] of contracts. In other words, it examines which functions can be called on a given contract. This is referred to as the contract's interface. - -== Interfaces - -include::../utils/_common.adoc[] - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_introspection` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[ISRC5]] -=== `++ISRC5++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/introspection.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_interfaces::introspection::ISRC5; -``` - -Interface of the SRC5 Introspection Standard as defined in {snip5}. - -[.contract-index] -.{inner-src5} --- -0x3f918d17e5ee77373b56385708f855659a07f75997f365cf87748628532a055 --- - -[.contract-index] -.Functions --- -* xref:#ISRC5-supports_interface[`++supports_interface(interface_id)++`] --- - -[#ISRC5-Functions] -==== Functions - -[.contract-item] -[[ISRC5-supports_interface]] -==== `[.contract-item-name]#++supports_interface++#++(interface_id: felt252) → bool++` [.item-kind]#external# - -Checks whether the contract implements the given interface. - -TIP: Check xref:introspection#computing_the_interface_id[Computing the Interface ID] for more information -on how to compute this ID. - -== Core - -[.contract] -[[SRC5Component]] -=== `++SRC5Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/introspection/src/src5.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_introspection::src5::SRC5Component; -``` - -SRC5 component extending xref:ISRC5[`ISRC5`]. - -[.contract-index#SRC5Component-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#SRC5Component-Embeddable-Impls-SRC5Impl] -.SRC5Impl - -* xref:#SRC5Component-supports_interface[`++supports_interface(self, interface_id)++`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#SRC5Component-register_interface[`++register_interface(self, interface_id)++`] -* xref:#SRC5Component-deregister_interface[`++deregister_interface(self, interface_id)++`] --- - -[#SRC5Component-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[SRC5Component-supports_interface]] -==== `[.contract-item-name]#++supports_interface++#++(self: @ContractState, interface_id: felt252) → bool++` [.item-kind]#external# - -See xref:ISRC5-supports_interface[`ISRC5::supports_interface`]. - -[#SRC5Component-Internal-Functions] -==== Internal functions - -[.contract-item] -[[SRC5Component-register_interface]] -==== `[.contract-item-name]#++register_interface++#++(ref self: ComponentState, interface_id: felt252)++` [.item-kind]#internal# - -Registers support for the given `interface_id`. - -[.contract-item] -[[SRC5Component-deregister_interface]] -==== `[.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/api/merkle-tree.adoc b/docs/modules/ROOT/pages/api/merkle-tree.adoc deleted file mode 100644 index 1a048161a..000000000 --- a/docs/modules/ROOT/pages/api/merkle-tree.adoc +++ /dev/null @@ -1,209 +0,0 @@ -:github-icon: pass:[] -:strk-merkle-tree: https://github.com/ericnordelo/strk-merkle-tree[JavaScript library] -:verify: xref:#merkle_proof-verify[verify] -:verify_pedersen: xref:#merkle_proof-verify_pedersen[verify_pedersen] -:verify_poseidon: xref:#merkle_proof-verify_poseidon[verify_poseidon] -:verify_multi_proof: xref:#merkle_proof-verify_multi_proof[verify_multi_proof] -:process_multi_proof: xref:#merkle_proof-process_multi_proof[process_multi_proof] - -= Merkle Tree - -This crate provides a set of utilities for verifying Merkle Tree proofs on-chain. The tree and the proofs can be -generated using this {strk-merkle-tree}. - -This module provides: - -- `{verify}` - can prove that some value is part of a Merkle tree. - -- `{verify_multi_proof}` - can prove multiple values are part of a Merkle tree. - -NOTE: `openzeppelin_merkle_tree` doesn't have dependencies outside of `corelib`, and can be used in projects that are not Starknet-related. - -[TIP] -==== -To use it as a standalone package, you can add it in your `Scarb.toml` as follows: - -`openzeppelin_merkle_tree = "4.0.0-alpha.1"` -==== - -== Modules - -[.contract] -[[merkle_proof]] -=== `++merkle_proof++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/merkle_tree/src/merkle_proof.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_merkle_tree::merkle_proof; -``` - -These functions deal with verification of Merkle Tree proofs. - -The tree and the proofs can be generated using this {strk-merkle-tree}. You will find a quickstart guide in the readme. - -WARNING: You should avoid using leaf values that are two felt252 values long prior to hashing, or use a hash function -other than the one used to hash internal nodes for hashing leaves. This is because the concatenation of a sorted pair -of internal nodes in the Merkle tree could be reinterpreted as a leaf value. The JavaScript library generates Merkle -trees that are safe against this attack out of the box. - -[.contract-index] -.Functions --- -* xref:#merkle_proof-verify[`++verify(proof, root, leaf)++`] -* xref:#merkle_proof-verify_pedersen[`++verify_pedersen(proof, root, leaf)++`] -* xref:#merkle_proof-verify_poseidon[`++verify_poseidon(proof, root, leaf)++`] -* xref:#merkle_proof-process_proof[`++process_proof(proof, leaf)++`] -* xref:#merkle_proof-verify_multi_proof[`++verify_multi_proof(proof, proof_flags, root, leaves)++`] -* xref:#merkle_proof-process_multi_proof[`++process_multi_proof(proof, proof_flags, leaf)++`] --- - -[#merkle_proof-Functions] -==== Functions - -[.contract-item] -[[merkle_proof-verify]] -==== `[.contract-item-name]#++verify<+CommutativeHasher>++#++(proof: Span, root: felt252, leaf: felt252) → bool++` [.item-kind]#public# - -Returns true if a `leaf` can be proved to be a part of a Merkle tree defined by `root`. - -For this, a `proof` must be provided, containing sibling hashes on the branch from the leaf to the root of the tree. - -Each pair of leaves and each pair of pre-images are assumed to be sorted. - -[NOTE] -==== -This function expects a `CommutativeHasher` implementation. See xref:#hashes-CommutativeHasher[hashes::CommutativeHasher] for more information. - -`{verify_pedersen}` and `{verify_poseidon}` already include the corresponding `Hasher` implementations. -==== - -[.contract-item] -[[merkle_proof-verify_pedersen]] -==== `[.contract-item-name]#++verify_pedersen++#++(proof: Span, root: felt252, leaf: felt252) → bool++` [.item-kind]#public# - -Version of `{verify}` using Pedersen as the hashing function. - -[.contract-item] -[[merkle_proof-verify_poseidon]] -==== `[.contract-item-name]#++verify_poseidon++#++(proof: Span, root: felt252, leaf: felt252) → bool++` [.item-kind]#public# - -Version of `{verify}` using Poseidon as the hashing function. - -[.contract-item] -[[merkle_proof-process_proof]] -==== `[.contract-item-name]#++process_proof<+CommutativeHasher>++#++(proof: Span, leaf: felt252) → felt252++` [.item-kind]#public# - -Returns the rebuilt hash obtained by traversing a Merkle tree up from `leaf` using `proof`. - -A `proof` is valid if and only if the rebuilt hash matches the root of the tree. - -When processing the proof, the pairs of leaves & pre-images are assumed to be sorted. - -NOTE: This function expects a `CommutativeHasher` implementation. See xref:#hashes-CommutativeHasher[hashes::CommutativeHasher] for more information. - -[.contract-item] -[[merkle_proof-verify_multi_proof]] -==== `[.contract-item-name]#++verify_multi_proof<+CommutativeHasher>++#++(proof: Span, proof_flags: Span, root: felt252, leaves: Span) → bool++` [.item-kind]#public# - -Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined -by `root`, according to `proof` and `proof_flags` as described in `{process_multi_proof}`. - -The `leaves` must be validated independently. - -CAUTION: Not all Merkle trees admit multiproofs. See `{process_multi_proof}` for details. - -NOTE: Consider the case where `root == proof.at(0) && leaves.len() == 0` as it will return `true`. - -NOTE: This function expects a `CommutativeHasher` implementation. See xref:#hashes-CommutativeHasher[hashes::CommutativeHasher] for more information. - -[.contract-item] -[[merkle_proof-process_multi_proof]] -==== `[.contract-item-name]#++process_multi_proof<+CommutativeHasher>++#++(proof: Span, proof_flags: Span, leaves: Span) → felt252++` [.item-kind]#public# - -Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. - -The reconstruction proceeds by incrementally reconstructing all inner nodes by combining a -leaf/inner node with either another leaf/inner node or a proof sibling node, depending on -whether each `proof_flags` item is true or false respectively. - -[CAUTION] -==== -Not all Merkle trees admit multiproofs. -To use multiproofs, it is sufficient to ensure that: - -1. The tree is complete (but not necessarily perfect). -2. The leaves to be proven are in the opposite order than they are in the tree. -(i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). -==== - -NOTE: The _empty set_ (i.e. the case where `proof.len() == 1 && leaves.len() == 0`) is -considered a no-op, and therefore a valid multiproof (i.e. it returns `proof.at(0)`). Consider -disallowing this case if you're not validating the leaves elsewhere. - -NOTE: This function expects a `CommutativeHasher` implementation. See xref:#hashes-CommutativeHasher[hashes::CommutativeHasher] for more information. - - -[.contract] -[[hashes]] -=== `++hashes++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/merkle_tree/src/hashes.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_merkle_tree::hashes; -``` - -:pedersen-hasher: xref:#hashes-PedersenCHasher[PedersenCHasher] -:poseidon-hasher: xref:#hashes-PoseidonCHasher[PoseidonCHasher] - -Module providing the trait and default implementations for the commutative hash functions used in -xref:#merkle_proof[`merkle_proof`]. - -NOTE: The `{pedersen-hasher}` implementation matches the default node hashing function used in the {strk-merkle-tree}. - -[.contract-index] -.Traits --- -* xref:#hashes-CommutativeHasher[`++CommutativeHasher++`] --- - -[.contract-index] -.Impls --- -* xref:#hashes-PedersenCHasher[`++PedersenCHasher++`] -* xref:#hashes-PoseidonCHasher[`++PoseidonCHasher++`] --- - -[#hashes-Traits] -==== Traits - -[.contract-item] -[[hashes-CommutativeHasher]] -==== `[.contract-item-name]#++CommutativeHasher++#` [.item-kind]#trait# - -Declares a commutative hash function with the following signature: - -`commutative_hash(a: felt252, b: felt252) -> felt252;` - -which computes a commutative hash of a sorted pair of felt252 values. - -This is usually implemented as an extension of a non-commutative hash function, like -Pedersen or Poseidon, returning the hash of the concatenation of the two values by first -sorting them. - -Frequently used when working with merkle proofs. - -NOTE: The `commutative_hash` function MUST follow the invariant that `commutative_hash(a, b) == commutative_hash(b, a)`. - -[#hashes-Impls] -==== Impls - -[.contract-item] -[[hashes-PedersenCHasher]] -==== `[.contract-item-name]#++PedersenCHasher++#` [.item-kind]#impl# - -Implementation of the `CommutativeHasher` trait which computes the Pedersen hash of chaining the two input values -with the len (2), sorting the pair first. - -[.contract-item] -[[hashes-PoseidonCHasher]] -==== `[.contract-item-name]#++PoseidonCHasher++#` [.item-kind]#impl# - -Implementation of the `CommutativeHasher` trait which computes the Poseidon hash of the concatenation of two values, sorting the pair first. diff --git a/docs/modules/ROOT/pages/api/security.adoc b/docs/modules/ROOT/pages/api/security.adoc deleted file mode 100644 index f01a34f74..000000000 --- a/docs/modules/ROOT/pages/api/security.adoc +++ /dev/null @@ -1,200 +0,0 @@ -:github-icon: pass:[] - -= Security - -This crate provides components to handle common security-related tasks. - -== Initializable - -[.contract] -[[InitializableComponent]] -=== `++InitializableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/security/src/initializable.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_security::InitializableComponent; -``` - -Component enabling one-time initialization for contracts. - -[.contract-index] -.Embeddable Implementations --- -.InitializableImpl - -* xref:#InitializableComponent-is_initialized[`++is_initialized(self)++`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#InitializableComponent-initialize[`++initialize(self)++`] --- - -[#InitializableComponent-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[InitializableComponent-is_initialized]] -==== `[.contract-item-name]#++is_initialized++#++(self: @ComponentState)++ → bool` [.item-kind]#external# - -Returns whether the contract has been initialized. - -[#InitializableComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[InitializableComponent-initialize]] -==== `[.contract-item-name]#++initialize++#++(ref self: ComponentState)++` [.item-kind]#internal# - -Initializes the contract. Can only be called once. - -Requirements: - -- the contract must not have been initialized before. - -== Pausable - -[.contract] -[[PausableComponent]] -=== `++PausableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/security/src/pausable.cairo[{github-icon},role=heading-link] - -:Paused: xref:PausableComponent-Paused[Paused] -:Unpaused: xref:PausableComponent-Unpaused[Unpaused] - -```cairo -use openzeppelin_security::PausableComponent; -``` - -Component to implement an emergency stop mechanism. - -[.contract-index] -.Embeddable Implementations --- -.PausableImpl - -* xref:#PausableComponent-is_paused[`++is_paused(self)++`] --- - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#PausableComponent-assert_not_paused[`++assert_not_paused(self)++`] -* xref:#PausableComponent-assert_paused[`++assert_paused(self)++`] -* xref:#PausableComponent-pause[`++pause(self)++`] -* xref:#PausableComponent-unpause[`++unpause(self)++`] --- - -[.contract-index] -.Events --- -* xref:#PausableComponent-Paused[`++Paused(account)++`] -* xref:#PausableComponent-Unpaused[`++Unpaused(account)++`] --- - -[#PausableComponent-Embeddable-Functions] -==== Embeddable functions - -[.contract-item] -[[PausableComponent-is_paused]] -==== `[.contract-item-name]#++is_paused++#++(self: @ComponentState)++ → bool` [.item-kind]#external# - -Returns whether the contract is currently paused. - -[#PausableComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[PausableComponent-assert_not_paused]] -==== `[.contract-item-name]#++assert_not_paused++#++(self: @ComponentState)++` [.item-kind]#internal# - -Panics if the contract is paused. - -[.contract-item] -[[PausableComponent-assert_paused]] -==== `[.contract-item-name]#++assert_paused++#++(self: @ComponentState)++` [.item-kind]#internal# - -Panics if the contract is not paused. - -[.contract-item] -[[PausableComponent-pause]] -==== `[.contract-item-name]#++pause++#++(ref self: ComponentState)++` [.item-kind]#internal# - -Pauses the contract. - -Requirements: - -- the contract must not be paused. - -Emits a {Paused} event. - -[.contract-item] -[[PausableComponent-unpause]] -==== `[.contract-item-name]#++unpause++#++(ref self: ComponentState)++` [.item-kind]#internal# - -Unpauses the contract. - -Requirements: - -- the contract must be paused. - -Emits an {Unpaused} event. - - -[#PausableComponent-Events] -==== Events - -[.contract-item] -[[PausableComponent-Paused]] -==== `[.contract-item-name]#++Paused++#++(account: ContractAddress)++` [.item-kind]#event# - -Emitted when the contract is paused by `account`. - -[.contract-item] -[[PausableComponent-Unpaused]] -==== `[.contract-item-name]#++Unpaused++#++(account: ContractAddress)++` [.item-kind]#event# - -Emitted when the contract is unpaused by `account`. - -== ReentrancyGuard - -[.contract] -[[ReentrancyGuardComponent]] -=== `++ReentrancyGuardComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/security/src/reentrancyguard.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_security::ReentrancyGuardComponent; -``` - -Component to help prevent reentrant calls. - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#ReentrancyGuardComponent-start[`++start(self)++`] -* xref:#ReentrancyGuardComponent-end[`++end(self)++`] --- - -[#ReentrancyGuardComponent-Internal-Functions] -==== Internal functions - -[.contract-item] -[[ReentrancyGuardComponent-start]] -==== `[.contract-item-name]#++start++#++(ref self: ComponentState)++` [.item-kind]#internal# - -Prevents a contract's function from calling itself or another protected function, directly or indirectly. - -Requirements: - -- the guard must not be currently enabled. - -[.contract-item] -[[ReentrancyGuardComponent-end]] -==== `[.contract-item-name]#++end++#++(ref self: ComponentState)++` [.item-kind]#internal# - -Removes the reentrant guard. diff --git a/docs/modules/ROOT/pages/api/token_common.adoc b/docs/modules/ROOT/pages/api/token_common.adoc deleted file mode 100644 index 0c10d2479..000000000 --- a/docs/modules/ROOT/pages/api/token_common.adoc +++ /dev/null @@ -1,509 +0,0 @@ -:github-icon: pass:[] -:eip2981: https://eips.ethereum.org/EIPS/eip-2981[EIP-2981] -:inner-src5: xref:api/introspection.adoc#ISRC5[SRC5 ID] - -= Common (Token) - -include::../utils/_common.adoc[] - -This module provides extensions and utilities that are common to multiple token standards. - -== Interfaces - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_token` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[IERC2981]] -=== `++IERC2981++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc2981.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc2981::IERC2981; -``` - -[.contract-index] -.{inner-src5} --- -0x2d3414e45a8700c29f119a54b9f11dca0e29e06ddcb214018fc37340e165ed6 --- - -Interface of the ERC2981 standard as defined in {eip2981}. - -[.contract-index] -.Functions --- -* xref:#IERC2981-royalty_info[`++royalty_info(token_id, sale_price)++`] --- - -[#IERC2981-Functions] -==== Functions - -[.contract-item] -[[IERC2981-royalty_info]] -==== `[.contract-item-name]#++royalty_info++#++(token_id: u256, sale_price: u256) → (ContractAddress, u256)++` [.item-kind]#external# - -Returns how much royalty is owed and to whom, based on a sale price that may be denominated -in any unit of exchange. The royalty amount is denominated and must be paid in that same -unit of exchange. - -[.contract] -[[IERC2981Info]] -=== `++IERC2981Info++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc2981.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc2981::IERC2981Info; -``` - -Interface providing external read functions for discovering the state of ERC2981 component. - -[.contract-index] -.Functions --- -* xref:#IERC2981Info-default_royalty[`++default_royalty()++`] -* xref:#IERC2981Info-token_royalty[`++token_royalty(token_id)++`] --- - -[#IERC2981Info-Functions] -==== Functions - -[.contract-item] -[[IERC2981Info-default_royalty]] -==== `[.contract-item-name]#++default_royalty++#++() → (ContractAddress, u128, u128)++` [.item-kind]#external# - -Returns the royalty information that all ids in this contract will default to. - -The returned tuple contains: - -- `t.0`: The receiver of the royalty payment. -- `t.1`: The numerator of the royalty fraction. -- `t.2`: The denominator of the royalty fraction. - -[.contract-item] -[[IERC2981Info-token_royalty]] -==== `[.contract-item-name]#++token_royalty++#++(token_id: u256) → (ContractAddress, u128, u128)++` [.item-kind]#external# - -Returns the royalty information specific to a token. - -The returned tuple contains: - -- `t.0`: The receiver of the royalty payment. -- `t.1`: The numerator of the royalty fraction. -- `t.2`: The denominator of the royalty fraction. - -[.contract] -[[IERC2981Admin]] -=== `++IERC2981Admin++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/token/erc2981.cairo[{github-icon},role=heading-link] - -[.hljs-theme-dark] -```cairo -use openzeppelin_interfaces::erc2981::IERC2981Admin; -``` - -Interface providing external admin functions for managing the settings of ERC2981 component. - -[.contract-index] -.Functions --- -* xref:#IERC2981Admin-set_default_royalty[`++set_default_royalty(receiver, fee_numerator)++`] -* xref:#IERC2981Admin-delete_default_royalty[`++delete_default_royalty()++`] -* xref:#IERC2981Admin-set_token_royalty[`++set_token_royalty(token_id, receiver, fee_numerator)++`] -* xref:#IERC2981Admin-reset_token_royalty[`++reset_token_royalty(token_id)++`] --- - -[#IERC2981Admin-Functions] -==== Functions - -[.contract-item] -[[IERC2981Admin-set_default_royalty]] -==== `[.contract-item-name]#++set_default_royalty++#++(receiver: ContractAddress, fee_numerator: u128)++` [.item-kind]#external# - -Sets the royalty information that all ids in this contract will default to. - -[.contract-item] -[[IERC2981Admin-delete_default_royalty]] -==== `[.contract-item-name]#++delete_default_royalty++#++()++` [.item-kind]#external# - -Sets the default royalty percentage and receiver to zero. - -[.contract-item] -[[IERC2981Admin-set_token_royalty]] -==== `[.contract-item-name]#++set_token_royalty++#++(token_id: u256, receiver: ContractAddress, fee_numerator: u128)++` [.item-kind]#external# - -Sets the royalty information for a specific token id that takes precedence over the global default. - -[.contract-item] -[[IERC2981Admin-reset_token_royalty]] -==== `[.contract-item-name]#++reset_token_royalty++#++(token_id: u256)++` [.item-kind]#external# - -Resets royalty information for the token id back to unset. - -== ERC2981 - -[.contract] -[[ERC2981Component]] -=== `++ERC2981Component++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/token/src/common/erc2981/erc2981.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_token::common::erc2981::ERC2981Component; -``` - -ERC2981 component extending <>. - -[.contract-index] -.{immutable-config} --- -.constants -* xref:#ERC2981Component-IC-FEE_DENOMINATOR[`++FEE_DENOMINATOR++`] - -.functions -* xref:#ERC2981Component-IC-validate[`++validate()++`] --- - -[.contract-index#ERC2981Component-Embeddable-Impls] -.Embeddable Implementations --- -[.sub-index#ERC2981Component-Embeddable-Impls-ERC20Impl] -.ERC2981Impl -* xref:#ERC2981Component-royalty_info[`++royalty_info(self, token_id, sale_price)++`] - -[.sub-index#ERC2981Component-Embeddable-Impls-ERC2981InfoImpl] -.ERC2981InfoImpl -* xref:#ERC2981InfoImpl-default_royalty[`++default_royalty(self)++`] -* xref:#ERC2981InfoImpl-token_royalty[`++token_royalty(self, token_id)++`] - -[.sub-index#ERC2981Component-Embeddable-Impls-ERC2981AdminOwnableImpl] -.ERC2981AdminOwnableImpl -* xref:#ERC2981AdminOwnableImpl-set_default_royalty[`++set_default_royalty(self, receiver, fee_numerator)++`] -* xref:#ERC2981AdminOwnableImpl-delete_default_royalty[`++delete_default_royalty(self)++`] -* xref:#ERC2981AdminOwnableImpl-set_token_royalty[`++set_token_royalty(self, token_id, receiver, fee_numerator)++`] -* xref:#ERC2981AdminOwnableImpl-reset_token_royalty[`++reset_token_royalty(self, token_id)++`] - -[.sub-index#ERC2981Component-Embeddable-Impls-ERC2981AdminAccessControlImpl] -.ERC2981AdminAccessControlImpl -* xref:#ERC2981AdminAccessControlImpl-set_default_royalty[`++set_default_royalty(self, receiver, fee_numerator)++`] -* xref:#ERC2981AdminAccessControlImpl-delete_default_royalty[`++delete_default_royalty(self)++`] -* xref:#ERC2981AdminAccessControlImpl-set_token_royalty[`++set_token_royalty(self, token_id, receiver, fee_numerator)++`] -* xref:#ERC2981AdminAccessControlImpl-reset_token_royalty[`++reset_token_royalty(self, token_id)++`] - -[.sub-index#ERC2981Component-Embeddable-Impls-ERC2981AdminAccessControlDefaultAdminRulesImpl] -.ERC2981AdminAccessControlDefaultAdminRulesImpl -* xref:#ERC2981AdminAccessControlDefaultAdminRulesImpl-set_default_royalty[`++set_default_royalty(self, receiver, fee_numerator)++`] -* xref:#ERC2981AdminAccessControlDefaultAdminRulesImpl-delete_default_royalty[`++delete_default_royalty(self)++`] -* xref:#ERC2981AdminAccessControlDefaultAdminRulesImpl-set_token_royalty[`++set_token_royalty(self, token_id, receiver, fee_numerator)++`] -* xref:#ERC2981AdminAccessControlDefaultAdminRulesImpl-reset_token_royalty[`++reset_token_royalty(self, token_id)++`] --- - -[.contract-index] -.Internal implementations --- -.InternalImpl -* xref:#ERC2981Component-initializer[`++initializer(self, default_receiver, default_royalty_fraction)++`] -* xref:#ERC2981Component-_default_royalty[`++_default_royalty(self)++`] -* xref:#ERC2981Component-_set_default_royalty[`++_set_default_royalty(self, receiver, fee_numerator)++`] -* xref:#ERC2981Component-_delete_default_royalty[`++_delete_default_royalty(self)++`] -* xref:#ERC2981Component-_token_royalty[`++_token_royalty(self, token_id)++`] -* xref:#ERC2981Component-_set_token_royalty[`++_set_token_royalty(self, token_id, receiver, fee_numerator)++`] -* xref:#ERC2981Component-_reset_token_royalty[`++_reset_token_royalty(self, token_id)++`] --- - -[#ERC2981Component-Immutable-Config] -==== Immutable Config constants - -[.contract-item] -[[ERC2981Component-IC-FEE_DENOMINATOR]] -==== `[.contract-item-name]#++FEE_DENOMINATOR:++#++ u128++` [.item-kind]#constant# - -The denominator with which to interpret the fee set in -`_set_token_royalty` and `_set_default_royalty` as a fraction of the sale price. - -[.contract-item] -[[ERC2981Component-IC-validate]] -==== `[.contract-item-name]#++validate++#++()++` [.item-kind]#internal# - -Validates the given implementation of the contract's configuration. - -Requirements: - -- `FEE_DENOMINATOR` must be greater than 0. - -NOTE: This function is called by the contract's initializer. - -[#ERC2981Component-Embeddable-functions] -==== Embeddable functions - -[.contract-item] -[[ERC2981Component-royalty_info]] -==== `[.contract-item-name]#++royalty_info++#++(@self: ContractState, token_id: u256, sale_price: u256) → (ContractAddress, u256)++` [.item-kind]#external# - -Returns how much royalty is owed and to whom, based on a sale price that may be -denominated in any unit of exchange. The royalty amount is denominated and should be -paid in that same unit of exchange. - -The returned tuple contains: - -- `t.0`: The receiver of the royalty payment. -- `t.1`: The amount of royalty payment. - -[.contract-item] -[[ERC2981InfoImpl-default_royalty]] -==== `[.contract-item-name]#++default_royalty++#++(@self: ContractState) → (ContractAddress, u128, u128)++` [.item-kind]#external# - -Returns the royalty information that all ids in this contract will default to. - -The returned tuple contains: - -- `t.0`: The receiver of the royalty payment. -- `t.1`: The numerator of the royalty fraction. -- `t.2`: The denominator of the royalty fraction. - -[.contract-item] -[[ERC2981InfoImpl-token_royalty]] -==== `[.contract-item-name]#++token_royalty++#++(self: @ContractState, token_id: u256) → (ContractAddress, u128, u128)++` [.item-kind]#external# - -Returns the royalty information specific to a token. -If no specific royalty information is set for the token, the default is returned. - -The returned tuple contains: - -- `t.0`: The receiver of the royalty payment. -- `t.1`: The numerator of the royalty fraction. -- `t.2`: The denominator of the royalty fraction. - -[#ERC2981Component-ERC2981AdminOwnableImpl] -==== ERC2981AdminOwnableImpl - -:ownable-component: xref:/api/access.adoc#OwnableComponent[OwnableComponent] - -Provides admin functions for managing royalty settings that are restricted to be called only by the contract's owner. -Requires the contract to implement {ownable-component}. - -[.contract-item] -[[ERC2981AdminOwnableImpl-set_default_royalty]] -==== `[.contract-item-name]#++set_default_royalty++#++(ref self: ContractState, receiver: ContractAddress, fee_numerator: u128)++` [.item-kind]#external# - -Sets the royalty information that all ids in this contract will default to. - -Requirements: - -- The caller is the contract owner. -- `receiver` cannot be the zero address. -- `fee_numerator` cannot be greater than the fee denominator. - -[.contract-item] -[[ERC2981AdminOwnableImpl-delete_default_royalty]] -==== `[.contract-item-name]#++delete_default_royalty++#++(ref self: ContractState)++` [.item-kind]#external# - -Sets the default royalty percentage and receiver to zero. - -Requirements: - -- The caller is the contract owner. - -[.contract-item] -[[ERC2981AdminOwnableImpl-set_token_royalty]] -==== `[.contract-item-name]#++set_token_royalty++#++(ref self: ContractState, token_id: u256, receiver: ContractAddress, fee_numerator: u128)++` [.item-kind]#external# - -Sets the royalty information for a specific token id that takes precedence over the global default. - -Requirements: - -- The caller is the contract owner. -- `receiver` cannot be the zero address. -- `fee_numerator` cannot be greater than the fee denominator. - -[.contract-item] -[[ERC2981AdminOwnableImpl-reset_token_royalty]] -==== `[.contract-item-name]#++reset_token_royalty++#++(ref self: ContractState, token_id: u256)++` [.item-kind]#external# - -Resets royalty information for the token id back to unset. - -Requirements: - -- The caller is the contract owner. - -[#ERC2981Component-ERC2981AdminAccessControlImpl] -==== ERC2981AdminAccessControlImpl - -:accesscontrol-component: xref:api/access.adoc#AccessControlComponent[AccessControlComponent] - -Provides admin functions for managing royalty settings that require `ROYALTY_ADMIN_ROLE` to be granted to the caller. -Requires the contract to implement {accesscontrol-component}. - -[.contract-item] -[[ERC2981AdminAccessControlImpl-ROYALTY_ADMIN_ROLE]] -==== `[.contract-item-name]#++ROYALTY_ADMIN_ROLE:++#++ felt252++` [.item-kind]#constant# - -Role for the admin responsible for managing royalty settings. - -[.contract-item] -[[ERC2981AdminAccessControlImpl-set_default_royalty]] -==== `[.contract-item-name]#++set_default_royalty++#++(ref self: ContractState, receiver: ContractAddress, fee_numerator: u128)++` [.item-kind]#external# - -Sets the royalty information that all ids in this contract will default to. - -Requirements: - -- The caller must have `ROYALTY_ADMIN_ROLE` role. -- `receiver` cannot be the zero address. -- `fee_numerator` cannot be greater than the fee denominator. - -[.contract-item] -[[ERC2981AdminAccessControlImpl-delete_default_royalty]] -==== `[.contract-item-name]#++delete_default_royalty++#++(ref self: ContractState)++` [.item-kind]#external# - -Sets the default royalty percentage and receiver to zero. - -Requirements: - -- The caller must have `ROYALTY_ADMIN_ROLE` role. - -[.contract-item] -[[ERC2981AdminAccessControlImpl-set_token_royalty]] -==== `[.contract-item-name]#++set_token_royalty++#++(ref self: ContractState, token_id: u256, receiver: ContractAddress, fee_numerator: u128)++` [.item-kind]#external# - -Sets the royalty information for a specific token id that takes precedence over the global default. - -Requirements: - -- The caller must have `ROYALTY_ADMIN_ROLE` role. -- `receiver` cannot be the zero address. -- `fee_numerator` cannot be greater than the fee denominator. - -[.contract-item] -[[ERC2981AdminAccessControlImpl-reset_token_royalty]] -==== `[.contract-item-name]#++reset_token_royalty++#++(ref self: ContractState, token_id: u256)++` [.item-kind]#external# - -Resets royalty information for the token id back to unset. - -Requirements: - -- The caller must have `ROYALTY_ADMIN_ROLE` role. - -[#ERC2981Component-ERC2981AdminAccessControlDefaultAdminRulesImpl] -==== ERC2981AdminAccessControlDefaultAdminRulesImpl - -:accesscontrol-default-admin-rules-component: xref:api/access.adoc#AccessControlDefaultAdminRulesComponent[AccessControlDefaultAdminRulesComponent] - -An alternative implementation of xref:#IERC2981Admin[IERC2981Admin]. Provides admin functions for managing royalty settings -that require `ROYALTY_ADMIN_ROLE` to be granted to the caller. Requires the contract to implement {accesscontrol-default-admin-rules-component}. - -[.contract-item] -[[ERC2981AdminAccessControlDefaultAdminRulesImpl-set_default_royalty]] -==== `[.contract-item-name]#++set_default_royalty++#++(ref self: ContractState, receiver: ContractAddress, fee_numerator: u128)++` [.item-kind]#external# - -Sets the royalty information that all ids in this contract will default to. - -Requirements: - -- The caller must have `ROYALTY_ADMIN_ROLE` role. -- `receiver` cannot be the zero address. -- `fee_numerator` cannot be greater than the fee denominator. - -[.contract-item] -[[ERC2981AdminAccessControlDefaultAdminRulesImpl-delete_default_royalty]] -==== `[.contract-item-name]#++delete_default_royalty++#++(ref self: ContractState)++` [.item-kind]#external# - -Sets the default royalty percentage and receiver to zero. - -Requirements: - -- The caller must have `ROYALTY_ADMIN_ROLE` role. - -[.contract-item] -[[ERC2981AdminAccessControlDefaultAdminRulesImpl-set_token_royalty]] -==== `[.contract-item-name]#++set_token_royalty++#++(ref self: ContractState, token_id: u256, receiver: ContractAddress, fee_numerator: u128)++` [.item-kind]#external# - -Sets the royalty information for a specific token id that takes precedence over the global default. - -Requirements: - -- The caller must have `ROYALTY_ADMIN_ROLE` role. -- `receiver` cannot be the zero address. -- `fee_numerator` cannot be greater than the fee denominator. - -[.contract-item] -[[ERC2981AdminAccessControlDefaultAdminRulesImpl-reset_token_royalty]] -==== `[.contract-item-name]#++reset_token_royalty++#++(ref self: ContractState, token_id: u256)++` [.item-kind]#external# - -Resets royalty information for the token id back to unset. - -Requirements: - -- The caller must have `ROYALTY_ADMIN_ROLE` role. - -[#ERC2981Component-Internal-functions] -==== Internal functions - -[.contract-item] -[[ERC2981Component-initializer]] -==== `[.contract-item-name]#++initializer++#++(ref self: ContractState, default_receiver: ContractAddress, default_royalty_fraction: u128)++` [.item-kind]#internal# - -Initializes the contract by setting the default royalty and registering the supported interface. - -Requirements: - -- `default_receiver` cannot be the zero address. -- `default_royalty_fraction` cannot be greater than the fee denominator. -- The fee denominator must be greater than 0. - -NOTE: The fee denominator is set by the contract using the {immutable-config}. - -[.contract-item] -[[ERC2981Component-_default_royalty]] -==== `[.contract-item-name]#++_default_royalty++#++(self: @ContractState) → (ContractAddress, u128, u128)++` [.item-kind]#internal# - -Returns the royalty information that all ids in this contract will default to. - -The returned tuple contains: - -- `t.0`: The receiver of the royalty payment. -- `t.1`: The numerator of the royalty fraction. -- `t.2`: The denominator of the royalty fraction. - -[.contract-item] -[[ERC2981Component-_set_default_royalty]] -==== `[.contract-item-name]#++_set_default_royalty++#++(ref self: ContractState, receiver: ContractAddress, fee_numerator: u128)++` [.item-kind]#internal# - -Sets the royalty information that all ids in this contract will default to. - -Requirements: - -- `receiver` cannot be the zero address. -- `fee_numerator` cannot be greater than the fee denominator. - -[.contract-item] -[[ERC2981Component-_delete_default_royalty]] -==== `[.contract-item-name]#++_delete_default_royalty++#++(ref self: ContractState)++` [.item-kind]#internal# - -Sets the default royalty percentage and receiver to zero. - -[.contract-item] -[[ERC2981Component-_token_royalty]] -==== `[.contract-item-name]#++_token_royalty++#++(self: @ContractState, token_id: u256) → (ContractAddress, u256, u256)++` [.item-kind]#internal# - -Returns the royalty information that all ids in this contract will default to. - -The returned tuple contains: - -- `t.0`: The receiver of the royalty payment. -- `t.1`: The numerator of the royalty fraction. -- `t.2`: The denominator of the royalty fraction. - -[.contract-item] -[[ERC2981Component-_set_token_royalty]] -==== `[.contract-item-name]#++_set_token_royalty++#++(ref self: ContractState, token_id: u256, receiver: ContractAddress, fee_numerator: u128)++` [.item-kind]#internal# - -Sets the royalty information for a specific token id that takes precedence over the global default. - -Requirements: - -- `receiver` cannot be the zero address. -- `fee_numerator` cannot be greater than the fee denominator. - -[.contract-item] -[[ERC2981Component-_reset_token_royalty]] -==== `[.contract-item-name]#++_reset_token_royalty++#++(ref self: ContractState, token_id: u256)++` [.item-kind]#internal# - -Resets royalty information for the token id back to unset. diff --git a/docs/modules/ROOT/pages/api/udc.adoc b/docs/modules/ROOT/pages/api/udc.adoc deleted file mode 100644 index 5ea523e7e..000000000 --- a/docs/modules/ROOT/pages/api/udc.adoc +++ /dev/null @@ -1,92 +0,0 @@ -:github-icon: pass:[] - -= Universal Deployer - -Reference of the Universal Deployer Contract (UDC) interface and preset. - -== Interfaces - -include::../utils/_common.adoc[] - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_utils` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[IUniversalDeployer]] -=== `++IUniversalDeployer++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/utils/deployments.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_interfaces::deployments::IUniversalDeployer; -``` - -[.contract-index] -.Functions --- -* xref:#IUniversalDeployer-deploy_contract[`++deploy_contract(class_hash, salt, not_from_zero, calldata)++`] --- - -[.contract-index] -.Events --- -* xref:#IUniversalDeployer-ContractDeployed[`++ContractDeployed(address, deployer, not_from_zero, class_hash, calldata, salt)++`] --- - -[#IUniversalDeployer-Functions] -==== Functions - -[.contract-item] -[[IUniversalDeployer-deploy_contract]] -==== `[.contract-item-name]#++deploy_contract++#++(class_hash: ClassHash, salt: felt252, not_from_zero: bool, calldata: Span) → ContractAddress++` [.item-kind]#external# - -Deploys a contract through the Universal Deployer Contract. - -[#IUniversalDeployer-Events] -==== Events - -[.contract-item] -[[IUniversalDeployer-ContractDeployed]] -==== `[.contract-item-name]#++ContractDeployed++#++(address: ContractAddress, deployer: ContractAddress, not_from_zero: bool, class_hash: ClassHash, calldata: Span, salt: felt252)++` [.item-kind]#event# - -Emitted when `deployer` deploys a contract through the Universal Deployer Contract. - -== Presets - -:origin-dependent: xref:/udc.adoc#origin_dependent[origin-dependent] -:origin-independent: xref:/udc.adoc#origin_independent[origin-independent] - -[.contract] -[[UniversalDeployer]] -=== `++UniversalDeployer++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/presets/src/universal_deployer.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_presets::UniversalDeployer; -``` - -The standard Universal Deployer Contract. - -include::../utils/_class_hashes.adoc[] - -[.contract-index] -.{presets-page} --- -{UniversalDeployer-class-hash} --- - -[.contract-index] -.Embedded Implementations --- -.UniversalDeployerImpl -* xref:#UniversalDeployer-deploy_contract[`++deploy_contract(self, address, deployer, not_from_zero, class_hash, calldata, salt)++`] --- - -[.contract-item] -[[UniversalDeployer-deploy_contract]] -==== `[.contract-item-name]#++deploy_contract++#++(ref self: ContractState, address: ContractAddress, deployer: ContractAddress, not_from_zero: bool, class_hash: ClassHash, calldata: Span, salt: felt252) -> ContractAddress++` [.item-kind]#external# - -Deploys a contract through the Universal Deployer Contract. - -When `not_from_zero` is `true`, `salt` is hashed with the caller address and the modified salt is passed to the inner `deploy_syscall`. This type of deployment is {origin-dependent}. - -When `not_from_zero` is `false`, the deployment type is {origin-independent}. - -Emits an <> event. diff --git a/docs/modules/ROOT/pages/api/upgrades.adoc b/docs/modules/ROOT/pages/api/upgrades.adoc deleted file mode 100644 index 458afe677..000000000 --- a/docs/modules/ROOT/pages/api/upgrades.adoc +++ /dev/null @@ -1,144 +0,0 @@ -:github-icon: pass:[] -:class_hash: https://docs.starknet.io/architecture-and-concepts/smart-contracts/class-hash/[class hash] - -= Upgrades - -This crate provides interfaces and utilities related to upgradeability. - -== Interfaces - -include::../utils/_common.adoc[] - -NOTE: Starting from version `3.x.x`, the interfaces are no longer part of the `openzeppelin_upgrades` package. The references -documented here are contained in the `openzeppelin_interfaces` package version `v{current_openzeppelin_interfaces_version}`. - -[.contract] -[[IUpgradeable]] -=== `++IUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/upgrades.cairo[{github-icon},role=heading-link] - -:Upgraded: xref:UpgradeableComponent-Upgraded[Upgraded] - -```cairo -use openzeppelin_interfaces::upgrades::IUpgradeable; -``` - -Interface of an upgradeable contract. - -[.contract-index] -.Functions --- -* xref:#IUpgradeable-upgrade[`++upgrade(new_class_hash)++`] --- - -[#IUpgradeable-Functions] -==== Functions - -[.contract-item] -[[IUpgradeable-upgrade]] -==== `[.contract-item-name]#++upgrade++#++(new_class_hash: ClassHash)++` [.item-kind]#external# - -Upgrades the contract code by updating its {class_hash}. - -NOTE: This function is usually protected by an xref:access.adoc[Access Control] mechanism. - -[.contract] -[[IUpgradeAndCall]] -=== `++IUpgradeAndCall++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/interfaces/src/upgrades.cairo[{github-icon},role=heading-link] - -:Upgraded: xref:UpgradeableComponent-Upgraded[Upgraded] - -```cairo -use openzeppelin_interfaces::upgrades::IUpgradeAndCall; -``` - -Interface for an upgradeable contract that couples an upgrade with a function call in the upgraded context. - -[.contract-index] -.Functions --- -* xref:#IUpgradeAndCall-upgrade_and_call[`++upgrade_and_call(new_class_hash, selector, calldata)++`] --- - -[#IUpgradeAndCall-Functions] -==== Functions - -[.contract-item] -[[IUpgradeAndCall-upgrade_and_call]] -==== `[.contract-item-name]#++upgrade_and_call++#++(new_class_hash: ClassHash, selector: felt252, calldata: Span) → Span++` [.item-kind]#external# - -Upgrades the contract code by updating its {class_hash} and calls `selector` with the upgraded context. - -NOTE: This function is usually protected by an xref:access.adoc[Access Control] mechanism. - -== Core - -[.contract] -[[UpgradeableComponent]] -=== `++UpgradeableComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/upgrades/src/upgradeable.cairo[{github-icon},role=heading-link] - -```cairo -use openzeppelin_upgrades::upgradeable::UpgradeableComponent; -``` - -Upgradeable component. - -[.contract-index] -.Internal Implementations --- -.InternalImpl - -* xref:#UpgradeableComponent-upgrade[`++upgrade(self, new_class_hash)++`] -* xref:#UpgradeableComponent-upgrade_and_call[`++upgrade_and_call(self, new_class_hash, selector, calldata)++`] --- - -[.contract-index] -.Events --- -* xref:#UpgradeableComponent-Upgraded[`++Upgraded(class_hash)++`] --- - -[#UpgradeableComponent-Internal-Functions] -==== Internal Functions - -:snip6: https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-6.md[SNIP-6] - -[.contract-item] -[[UpgradeableComponent-upgrade]] -==== `[.contract-item-name]#++upgrade++#++(ref self: ContractState, new_class_hash: ClassHash)++` [.item-kind]#internal# - -Upgrades the contract by updating the contract {class_hash}. - -Requirements: - -- `new_class_hash` must be different from zero. - -Emits an {Upgraded} event. - -[.contract-item] -[[UpgradeableComponent-upgrade_and_call]] -==== `[.contract-item-name]#++upgrade_and_call++#++(ref self: ContractState, new_class_hash: ClassHash, selector: felt252, calldata: Span) → Span++` [.item-kind]#internal# - -Replaces the contract's class hash with `new_class_hash` and then calls `selector` -from the upgraded context. -This function returns the unwrapped `call_contract_syscall` return value(s), if available, of the `selector` call. - -Requirements: - -- `new_class_hash` must be different from zero. - -NOTE: The function call comes from the upgraded contract itself and not the account. - -NOTE: A similar behavior to `upgrade_and_call` can also be achieved with a list of calls from an account since the {snip6} account standard supports multicall. -An account can execute a list of calls with xref:IUpgradeable-upgrade[upgrade] being the first element in the list and the extra function call as the second. -With this approach, the calls will execute from the account's context and can't be front-ran. - -Emits an {Upgraded} event. - -[#UpgradeableComponent-Events] -==== Events - -[.contract-item] -[[UpgradeableComponent-Upgraded]] -==== `[.contract-item-name]#++Upgraded++#++(class_hash: ClassHash)++` [.item-kind]#event# - -Emitted when the {class_hash} is upgraded. diff --git a/docs/modules/ROOT/pages/backwards-compatibility.adoc b/docs/modules/ROOT/pages/backwards-compatibility.adoc deleted file mode 100644 index dc3d8fb43..000000000 --- a/docs/modules/ROOT/pages/backwards-compatibility.adoc +++ /dev/null @@ -1,33 +0,0 @@ -= Backwards Compatibility - -OpenZeppelin Contracts uses semantic versioning to communicate backwards compatibility of its API and storage layout. Patch and minor updates will generally be backwards compatible, with rare exceptions as detailed below. Major updates should be assumed incompatible with previous releases. On this page, we provide details about these guarantees. - -Bear in mind that while releasing versions, we treat minors as majors and patches as minors, in accordance with semantic versioning. This means that `v2.1.0` could be adding features to `v4.0.0-alpha.1`, while `v4.0.0-alpha.1` would be considered a breaking release. - -== API - -In backwards compatible releases, all changes should be either additions or modifications to internal implementation details. Most code should continue to compile and behave as expected. The exceptions to this rule are listed below. - -=== Security - -Infrequently, a patch or minor update will remove or change an API in a breaking way but only if the previous API is considered insecure. These breaking changes will be noted in the changelog and release notes, and published along with a security advisory. - -=== Errors - -The specific error format and data that is included with reverts should not be assumed stable unless otherwise specified. - -=== Major releases - -Major releases should be assumed incompatible. Nevertheless, the external interfaces of contracts will remain compatible if they are standardized, or if the maintainers judge that changing them would cause significant strain on the ecosystem. - -An important aspect that major releases may break is "upgrade compatibility", in particular storage layout compatibility. It will never be safe for a live contract to upgrade from one major release to another. - -In the case of breaking "upgrade compatibility", an entry to the changelog will be added listing those breaking changes. - -== Storage layout - -Patch updates will always preserve storage layout compatibility, and after `v4.0.0-alpha.1` minors will too. This means that a live contract can be upgraded from one minor to another without corrupting the storage layout. In some cases it may be necessary to initialize new state variables when upgrading, although we expect this to be infrequent. - -== Cairo version - -The minimum Cairo version required to compile the contracts will remain unchanged for patch updates, but it may change for minors. diff --git a/docs/modules/ROOT/pages/erc4626.adoc b/docs/modules/ROOT/pages/erc4626.adoc deleted file mode 100644 index 761a99e4f..000000000 --- a/docs/modules/ROOT/pages/erc4626.adoc +++ /dev/null @@ -1,467 +0,0 @@ -= ERC4626 -:stem: latexmath - -https://eips.ethereum.org/EIPS/eip-4626[ERC4626] is an extension of xref:erc20.adoc[ERC20] that proposes a standard interface for token vaults. This standard interface can be used by widely different contracts (including lending markets, aggregators, and intrinsically interest bearing tokens), which brings a number of subtleties. Navigating these potential issues is essential to implementing a compliant and composable token vault. - -We provide a base component of ERC4626 which is designed to allow developers to easily re-configure the vault's behavior, using traits and hooks, while staying compliant. In this guide, we will discuss some security considerations that affect ERC4626. We will also discuss common customizations of the vault. - -[[inflation-attack]] -== Security concern: Inflation attack - -=== Visualizing the vault - -In exchange for the assets deposited into an ERC4626 vault, a user receives shares. These shares can later be burned to redeem the corresponding underlying assets. The number of shares a user gets depends on the amount of assets they put in and on the exchange rate of the vault. This exchange rate is defined by the current liquidity held by the vault. - -- If a vault has 100 tokens to back 200 shares, then each share is worth 0.5 assets. -- If a vault has 200 tokens to back 100 shares, then each share is worth 2.0 assets. - -In other words, the exchange rate can be defined as the slope of the line that passes through the origin and the current number of assets and shares in the vault. Deposits and withdrawals move the vault in this line. - -image::erc4626-rate-linear.png[Exchange rates in linear scale] - -When plotted in log-log scale, the rate is defined similarly, but appears differently (because the point (0,0) is infinitely far away). Rates are represented by "diagonal" lines with different offsets. - -image::erc4626-rate-loglog.png[Exchange rates in logarithmic scale] - -In such a representation, widely different rates can be clearly visible in the same graph. This wouldn't be the case in linear scale. - -image::erc4626-rate-loglogext.png[More exchange rates in logarithmic scale] - -=== The attack - -When depositing tokens, the number of shares a user gets is rounded towards zero. This rounding takes away value from the user in favor of the vault (i.e. in favor of all the current shareholders). This rounding is often negligible because of the amount at stake. If you deposit 1e9 shares worth of tokens, the rounding will have you lose at most 0.0000001% of your deposit. However if you deposit 10 shares worth of tokens, you could lose 10% of your deposit. Even worse, if you deposit less than 1 share worth of tokens, you will receive 0 shares, effectively making a donation. - -For a given amount of assets, the more shares you receive the safer you are. If you want to limit your losses to at most 1%, you need to receive at least 100 shares. - -image::erc4626-deposit.png[Depositing assets] - -In the figure we can see that for a given deposit of 500 assets, the number of shares we get and the corresponding rounding losses depend on the exchange rate. If the exchange rate is that of the orange curve, we are getting less than a share, so we lose 100% of our deposit. However, if the exchange rate is that of the green curve, we get 5000 shares, which limits our rounding losses to at most 0.02%. - -image::erc4626-mint.png[Minting shares] - -Symmetrically, if we focus on limiting our losses to a maximum of 0.5%, we need to get at least 200 shares. With the green exchange rate that requires just 20 tokens, but with the orange rate that requires 200000 tokens. - -We can clearly see that the blue and green curves correspond to vaults that are safer than the yellow and orange curves. - -The idea of an inflation attack is that an attacker can donate assets to the vault to move the rate curve to the right, and make the vault unsafe. - -image::erc4626-attack.png[Inflation attack without protection] - -Figure 6 shows how an attacker can manipulate the rate of an empty vault. First the attacker must deposit a small amount of tokens (1 token) and follow up with a donation of 1e5 tokens directly to the vault to move the exchange rate "right". This puts the vault in a state where any deposit smaller than 1e5 would be completely lost to the vault. Given that the attacker is the only shareholder (from their donation), the attacker would steal all the tokens deposited. - -An attacker would typically wait for a user to do the first deposit into the vault, and would frontrun that operation with the attack described above. The risk is low, and the size of the "donation" required to manipulate the vault is equivalent to the size of the deposit that is being attacked. - -In math that gives: - -- stem:[a_0] the attacker deposit -- stem:[a_1] the attacker donation -- stem:[u] the user deposit - -[%header,cols=4*] -|=== -| -| Assets -| Shares -| Rate - -| initial -| stem:[0] -| stem:[0] -| - - -| after attacker's deposit -| stem:[a_0] -| stem:[a_0] -| stem:[1] - -| after attacker's donation -| stem:[a_0+a_1] -| stem:[a_0] -| stem:[\frac{a_0}{a_0+a_1}] -|=== - -This means a deposit of stem:[u] will give stem:[\frac{u \times a_0}{a_0 + a_1}] shares. - -For the attacker to dilute that deposit to 0 shares, causing the user to lose all its deposit, it must ensure that - -[stem] -++++ -\frac{u \times a_0}{a_0+a_1} < 1 \iff u < 1 + \frac{a_1}{a_0} -++++ - -Using stem:[a_0 = 1] and stem:[a_1 = u] is enough. So the attacker only needs stem:[u+1] assets to perform a successful attack. - -It is easy to generalize the above results to scenarios where the attacker is going after a smaller fraction of the user's deposit. In order to target stem:[\frac{u}{n}], the user needs to suffer rounding of a similar fraction, which means the user must receive at most stem:[n] shares. This results in: - -[stem] -++++ -\frac{u \times a_0}{a_0+a_1} < n \iff \frac{u}{n} < 1 + \frac{a_1}{a_0} -++++ - -In this scenario, the attack is stem:[n] times less powerful (in how much it is stealing) and costs stem:[n] times less to execute. In both cases, the amount of funds the attacker needs to commit is equivalent to its potential earnings. - -=== Defending with a virtual offset - -The defense we propose is based on the approach used in link:https://github.com/boringcrypto/YieldBox[YieldBox]. It consists of two parts: - -- Use an offset between the "precision" of the representation of shares and assets. Said otherwise, we use more decimal places to represent the shares than the underlying token does to represent the assets. -- Include virtual shares and virtual assets in the exchange rate computation. These virtual assets enforce the conversion rate when the vault is empty. - -These two parts work together in enforcing the security of the vault. First, the increased precision corresponds to a high rate, which we saw is safer as it reduces the rounding error when computing the amount of shares. Second, the virtual assets and shares (in addition to simplifying a lot of the computations) capture part of the donation, making it unprofitable to perform an attack. - -Following the previous math definitions, we have: - -- stem:[\delta] the vault offset -- stem:[a_0] the attacker deposit -- stem:[a_1] the attacker donation -- stem:[u] the user deposit - -[%header,cols=4*] -|=== -| -| Assets -| Shares -| Rate - -| initial -| stem:[1] -| stem:[10^\delta] -| stem:[10^\delta] - -| after attacker's deposit -| stem:[1+a_0] -| stem:[10^\delta \times (1+a_0)] -| stem:[10^\delta] - -| after attacker's donation -| stem:[1+a_0+a_1] -| stem:[10^\delta \times (1+a_0)] -| stem:[10^\delta \times \frac{1+a_0}{1+a_0+a_1}] -|=== - -One important thing to note is that the attacker only owns a fraction stem:[\frac{a_0}{1 + a_0}] of the shares, so when doing the donation, he will only be able to recover that fraction stem:[\frac{a_1 \times a_0}{1 + a_0}] of the donation. The remaining stem:[\frac{a_1}{1+a_0}] are captured by the vault. - -[stem] -++++ -\mathit{loss} = \frac{a_1}{1+a_0} -++++ - -When the user deposits stem:[u], he receives - -[stem] -++++ -10^\delta \times u \times \frac{1+a_0}{1+a_0+a_1} -++++ - -For the attacker to dilute that deposit to 0 shares, causing the user to lose all its deposit, it must ensure that - -[stem] -++++ -10^\delta \times u \times \frac{1+a_0}{1+a_0+a_1} < 1 -++++ - -[stem] -++++ -\iff 10^\delta \times u < \frac{1+a_0+a_1}{1+a_0} -++++ - -[stem] -++++ -\iff 10^\delta \times u < 1 + \frac{a_1}{1+a_0} -++++ - -[stem] -++++ -\iff 10^\delta \times u \le \mathit{loss} -++++ - -- If the offset is 0, the attacker loss is at least equal to the user's deposit. -- If the offset is greater than 0, the attacker will have to suffer losses that are orders of magnitude bigger than the amount of value that can hypothetically be stolen from the user. - -This shows that even with an offset of 0, the virtual shares and assets make this attack non profitable for the attacker. Bigger offsets increase the security even further by making any attack on the user extremely wasteful. - -The following figure shows how the offset impacts the initial rate and limits the ability of an attacker with limited funds to inflate it effectively. - -image::erc4626-attack-3a.png[Inflation attack without offset=3] -stem:[\delta = 3], stem:[a_0 = 1], stem:[a_1 = 10^5] - -image::erc4626-attack-3b.png[Inflation attack without offset=3 and an attacker deposit that limits its losses] -stem:[\delta = 3], stem:[a_0 = 100], stem:[a_1 = 10^5] - -image::erc4626-attack-6.png[Inflation attack without offset=6] -stem:[\delta = 6], stem:[a_0 = 1], stem:[a_1 = 10^5] - -== Usage - -[[fees]] -=== Custom behavior: Adding fees to the vault - -:fee_config_trait: xref:/api/erc20.adoc#ERC4626Component-FeeConfigTrait[FeeConfigTrait] -:no_fees_impl: https://github.com/OpenZeppelin/cairo-contracts/tree/main/packages/token/src/erc20/extensions/erc4626/erc4626.cairo#L874[ERC4626DefaultNoFees] -:erc4626_mocks: https://github.com/OpenZeppelin/cairo-contracts/tree/main/packages/test_common/src/mocks/erc4626.cairo[ERC4626 mocks] - -In ERC4626 vaults, fees can be captured during deposit/mint and/or withdraw/redeem operations. It is essential to remain -compliant with the ERC4626 requirements regarding the preview functions. Fees are calculated through the {fee_config_trait} -implementation. By default, the ERC4626 component charges no fees. If this is the desired behavior, you can use the default -{no_fees_impl} implementation. - -NOTE: Starting from v4.0.0-alpha.1, fees can be charged in either assets or shares. Prior versions only supported fees taken in assets. -See the updated {fee_config_trait} and implementation examples in {erc4626_mocks}. - -For example, if calling `deposit(100, receiver)`, the caller should deposit exactly 100 underlying tokens, including fees, and the receiver should receive a number of shares that matches the value returned by `preview_deposit(100)`. -Similarly, `preview_mint` should account for the fees that the user will have to pay on top of share's cost. - -As for the `Deposit` event, while this is less clear in the EIP spec itself, -there seems to be consensus that it should include the number of assets paid for by the user, including the fees. - -On the other hand, when withdrawing assets, the number given by the user should correspond to what the user receives. -Any fees should be added to the quote (in shares) performed by `preview_withdraw`. - -The `Withdraw` event should include the number of shares the user burns (including fees) and the number of assets the user actually receives (after fees are deducted). - -The consequence of this design is that both the `Deposit` and `Withdraw` events will describe two exchange rates. -The spread between the "Buy-in" and the "Exit" prices correspond to the fees taken by the vault. - -The following example describes how fees taken in assets on deposits/withdrawals and in shares on mints/redemptions -proportional to the deposited/withdrawn amount can be implemented: - -```cairo -/// The mock contract charges fees in assets on deposits and withdrawals and in shares on mints and -/// redemptions. -/// This is an opinionated design decision for the purpose of testing. -/// DO NOT USE IN PRODUCTION -#[starknet::contract] -#[with_components(ERC20, ERC4626)] -pub mod ERC4626Fees { - use openzeppelin_interfaces::erc20::{IERC20Dispatcher, IERC20DispatcherTrait}; - use openzeppelin_token::erc20::extensions::erc4626::ERC4626Component::{Fee, FeeConfigTrait}; - use openzeppelin_token::erc20::extensions::erc4626::{ - DefaultConfig, ERC4626DefaultNoLimits, ERC4626SelfAssetsManagement, - }; - use openzeppelin_token::erc20::{DefaultConfig as ERC20DefaultConfig, ERC20HooksEmptyImpl}; - use openzeppelin_utils::math; - use openzeppelin_utils::math::Rounding; - use starknet::ContractAddress; - use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; - - const _BASIS_POINT_SCALE: u256 = 10_000; - - // ERC4626 - #[abi(embed_v0)] - impl ERC4626ComponentImpl = ERC4626Component::ERC4626Impl; - // ERC4626MetadataImpl is a custom impl of IERC20Metadata - #[abi(embed_v0)] - impl ERC4626MetadataImpl = ERC4626Component::ERC4626MetadataImpl; - - // ERC20 - #[abi(embed_v0)] - impl ERC20Impl = ERC20Component::ERC20Impl; - #[abi(embed_v0)] - impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl; - - #[storage] - pub struct Storage { - pub entry_fee_basis_point_value: u256, - pub entry_fee_recipient: ContractAddress, - pub exit_fee_basis_point_value: u256, - pub exit_fee_recipient: ContractAddress, - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - underlying_asset: ContractAddress, - initial_supply: u256, - recipient: ContractAddress, - entry_fee: u256, - entry_treasury: ContractAddress, - exit_fee: u256, - exit_treasury: ContractAddress, - ) { - self.erc20.initializer(name, symbol); - self.erc20.mint(recipient, initial_supply); - self.erc4626.initializer(underlying_asset); - - self.entry_fee_basis_point_value.write(entry_fee); - self.entry_fee_recipient.write(entry_treasury); - self.exit_fee_basis_point_value.write(exit_fee); - self.exit_fee_recipient.write(exit_treasury); - } - - /// Hooks - impl ERC4626HooksImpl of ERC4626Component::ERC4626HooksTrait { - fn after_deposit( - ref self: ERC4626Component::ComponentState, - caller: ContractAddress, - receiver: ContractAddress, - assets: u256, - shares: u256, - fee: Option, - ) { - if let Option::Some(fee) = fee { - let mut contract_state = self.get_contract_mut(); - let fee_recipient = contract_state.entry_fee_recipient.read(); - match fee { - Fee::Assets(fee) => { - let asset_address = contract_state.asset(); - let asset_dispatcher = IERC20Dispatcher { contract_address: asset_address }; - assert( - asset_dispatcher.transfer(fee_recipient, fee), 'Fee transfer failed', - ); - }, - Fee::Shares(fee) => contract_state.erc20.mint(fee_recipient, fee), - }; - } - } - - fn before_withdraw( - ref self: ERC4626Component::ComponentState, - caller: ContractAddress, - receiver: ContractAddress, - owner: ContractAddress, - assets: u256, - shares: u256, - fee: Option, - ) { - if let Option::Some(fee) = fee { - let mut contract_state = self.get_contract_mut(); - let fee_recipient = contract_state.exit_fee_recipient.read(); - match fee { - Fee::Assets(fee) => { - let asset_address = contract_state.asset(); - let asset_dispatcher = IERC20Dispatcher { contract_address: asset_address }; - assert( - asset_dispatcher.transfer(fee_recipient, fee), 'Fee transfer failed', - ); - }, - Fee::Shares(fee) => { - if caller != owner { - contract_state.erc20._spend_allowance(owner, caller, fee); - } - contract_state.erc20._transfer(owner, fee_recipient, fee); - }, - }; - } - } - } - - /// Calculate fees - impl FeeConfigImpl of FeeConfigTrait { - fn calculate_deposit_fee( - self: @ERC4626Component::ComponentState, assets: u256, shares: u256, - ) -> Option { - let contract_state = self.get_contract(); - let fee = fee_on_total(assets, contract_state.entry_fee_basis_point_value.read()); - Option::Some(Fee::Assets(fee)) - } - - fn calculate_mint_fee( - self: @ERC4626Component::ComponentState, assets: u256, shares: u256, - ) -> Option { - let contract_state = self.get_contract(); - let fee = fee_on_raw(shares, contract_state.entry_fee_basis_point_value.read()); - Option::Some(Fee::Shares(fee)) - } - - fn calculate_withdraw_fee( - self: @ERC4626Component::ComponentState, assets: u256, shares: u256, - ) -> Option { - let contract_state = self.get_contract(); - let fee = fee_on_raw(assets, contract_state.exit_fee_basis_point_value.read()); - Option::Some(Fee::Assets(fee)) - } - - fn calculate_redeem_fee( - self: @ERC4626Component::ComponentState, assets: u256, shares: u256, - ) -> Option { - let contract_state = self.get_contract(); - let fee = fee_on_total(shares, contract_state.exit_fee_basis_point_value.read()); - Option::Some(Fee::Shares(fee)) - } - } - - /// Calculates the fees that should be added to an amount `assets` that does not already - /// include fees. - /// Used in IERC4626::mint and IERC4626::withdraw operations. - fn fee_on_raw( - assets: u256, - fee_basis_points: u256, - ) -> u256 { - math::u256_mul_div(assets, fee_basis_points, _BASIS_POINT_SCALE, Rounding::Ceil) - } - - /// Calculates the fee part of an amount `assets` that already includes fees. - /// Used in IERC4626::deposit and IERC4626::redeem operations. - fn fee_on_total( - assets: u256, - fee_basis_points: u256, - ) -> u256 { - math::u256_mul_div( - assets, fee_basis_points, fee_basis_points + _BASIS_POINT_SCALE, Rounding::Ceil, - ) - } -} -``` - -== Interface - -:erc4626-component: xref:/api/erc20.adoc#ERC4626Component[ERC4626Component] -:ierc4626: xref:/api/erc20.adoc#IERC4626[IERC4626] -:ierc20: xref:/api/erc20.adoc#IERC20[IERC20] -:ierc20-metadata: xref:/api/erc20.adoc#IERC20Metadata[IERC20Metadata] - -The following interface represents the full ABI of the Contracts for Cairo {erc4626-component}. -The full interface includes the {ierc4626}, {ierc20}, and {ierc20-metadata} interfaces. -Note that implementing the IERC20Metadata interface is a requirement of IERC4626. - -[,cairo] ----- -#[starknet::interface] -pub trait ERC4626ABI { - // IERC4626 - fn asset() -> ContractAddress; - fn total_assets() -> u256; - fn convert_to_shares(assets: u256) -> u256; - fn convert_to_assets(shares: u256) -> u256; - fn max_deposit(receiver: ContractAddress) -> u256; - fn preview_deposit(assets: u256) -> u256; - fn deposit(assets: u256, receiver: ContractAddress) -> u256; - fn max_mint(receiver: ContractAddress) -> u256; - fn preview_mint(shares: u256) -> u256; - fn mint(shares: u256, receiver: ContractAddress) -> u256; - fn max_withdraw(owner: ContractAddress) -> u256; - fn preview_withdraw(assets: u256) -> u256; - fn withdraw( - assets: u256, receiver: ContractAddress, owner: ContractAddress, - ) -> u256; - fn max_redeem(owner: ContractAddress) -> u256; - fn preview_redeem(shares: u256) -> u256; - fn redeem( - shares: u256, receiver: ContractAddress, owner: ContractAddress, - ) -> u256; - - // IERC20 - fn total_supply() -> u256; - fn balance_of(account: ContractAddress) -> u256; - fn allowance(owner: ContractAddress, spender: ContractAddress) -> u256; - fn transfer(recipient: ContractAddress, amount: u256) -> bool; - fn transfer_from( - sender: ContractAddress, recipient: ContractAddress, amount: u256, - ) -> bool; - fn approve(spender: ContractAddress, amount: u256) -> bool; - - // IERC20Metadata - fn name() -> ByteArray; - fn symbol() -> ByteArray; - fn decimals() -> u8; - - // IERC20CamelOnly - fn totalSupply() -> u256; - fn balanceOf(account: ContractAddress) -> u256; - fn transferFrom( - sender: ContractAddress, recipient: ContractAddress, amount: u256, - ) -> bool; -} ----- diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc deleted file mode 100644 index 1fa37df7e..000000000 --- a/docs/modules/ROOT/pages/index.adoc +++ /dev/null @@ -1,166 +0,0 @@ -:starknet: https://starkware.co/product/starknet/[Starknet] -:scarb: https://docs.swmansion.com/scarb[Scarb] -:installation: https://docs.swmansion.com/scarb/download.html[this guide] - -= Contracts for Cairo - -include::./utils/_common.adoc[] - -*A library for secure smart contract development* written in Cairo for {starknet}. This library consists of a set of xref:components.adoc[reusable components] to build custom smart contracts, as well as -ready-to-deploy xref:presets.adoc[presets]. You can also find other xref:/api/utilities.adoc[utilities] including xref:interfaces.adoc[interfaces and dispatchers] and xref:/api/testing.adoc[test utilities] -that facilitate testing with Starknet Foundry. - -WARNING: This repo contains highly experimental code. Expect rapid iteration. *Use at your own risk.* - -NOTE: You can track our roadmap and future milestones in our https://github.com/orgs/OpenZeppelin/projects/29/[Github Project]. - -== Installation - -The library is available as a {scarb} package. Follow {installation} for installing Cairo and Scarb on your machine -before proceeding, and run the following command to check that the installation was successful: - -[,bash] ----- -$ scarb --version - -scarb 2.13.1 (dc0dbfd50 2025-09-15) -cairo: 2.13.1 (https://crates.io/crates/cairo-lang-compiler/2.13.1) -sierra: 1.7.0 ----- - -=== Set up your project - -Create an empty directory, and `cd` into it: - -[,bash] ----- -mkdir my_project/ && cd my_project/ ----- - -Initialize a new Scarb project: - -[,bash] ----- -scarb init ----- - -The contents of `my_project/` should now look like this: - -[,bash] ----- -$ ls - -Scarb.toml src ----- - -=== Install the library - -:versioning: xref:index.adoc#versioning_of_the_sub_packages[Versioning of the sub-packages] - -[IMPORTANT] -==== -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. -==== - -Install the library by declaring it as a dependency in the project's `Scarb.toml` file: - -[,javascript] ----- -[dependencies] -openzeppelin = "4.0.0-alpha.1" ----- - -The previous example would import the entire library. We can also add each package as a separate dependency to -improve the building time by not including modules that won't be used: - -[,javascript,subs=+attributes] ----- -[dependencies] -openzeppelin_access = "4.0.0-alpha.1" -openzeppelin_token = "4.0.0-alpha.1" -openzeppelin_interfaces = "{current_openzeppelin_interfaces_version}" ----- - -== Versioning of the sub-packages - -Here you can find a reference of the versioning of the sub-packages for this umbrella version: - -[,javascript,subs=+attributes] ----- -[dependencies] -openzeppelin_access = "4.0.0-alpha.1" -openzeppelin_token = "4.0.0-alpha.1" -openzeppelin_access = "4.0.0-alpha.1" -openzeppelin_account = "4.0.0-alpha.1" -openzeppelin_finance = "4.0.0-alpha.1" -openzeppelin_interfaces = "{current_openzeppelin_interfaces_version}" -openzeppelin_governance = "4.0.0-alpha.1" -openzeppelin_introspection = "4.0.0-alpha.1" -openzeppelin_merkle_tree = "4.0.0-alpha.1" -openzeppelin_presets = "4.0.0-alpha.1" -openzeppelin_security = "4.0.0-alpha.1" -openzeppelin_token = "4.0.0-alpha.1" -openzeppelin_upgrades = "4.0.0-alpha.1" - -openzeppelin_interfaces = "{current_openzeppelin_interfaces_version}" -openzeppelin_utils = "{current_openzeppelin_utils_version}" ----- - -== Basic usage - -This is how it looks to build an ERC20 contract using the xref:erc20.adoc[ERC20 component]. -Copy the code into `src/lib.cairo`. - -[,cairo] ----- -#[starknet::contract] -mod MyERC20Token { - // NOTE: If you added the entire library as a dependency, - // use `openzeppelin::token` instead. - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl, DefaultConfig}; - use starknet::ContractAddress; - - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - - // ERC20 Mixin - #[abi(embed_v0)] - impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl; - impl ERC20InternalImpl = ERC20Component::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - erc20: ERC20Component::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - ERC20Event: ERC20Component::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - fixed_supply: u256, - recipient: ContractAddress - ) { - self.erc20.initializer(name, symbol); - self.erc20.mint(recipient, fixed_supply); - } -} ----- - -You can now compile it: - -[,bash] ----- -scarb build ----- diff --git a/docs/modules/ROOT/pages/interfaces.adoc b/docs/modules/ROOT/pages/interfaces.adoc deleted file mode 100644 index ef31556ae..000000000 --- a/docs/modules/ROOT/pages/interfaces.adoc +++ /dev/null @@ -1,64 +0,0 @@ -= Interfaces - -include::utils/_common.adoc[] - -Starting from version `3.x.x`, OpenZeppelin Contracts for Cairo interfaces have been separated from their implementation modules into a dedicated package called `openzeppelin_interfaces`. This architectural change brings several important benefits: - -== Decoupled Dependencies - -The main motivation behind this separation is to decouple dependencies among packages when only interfaces are needed. For example, if a project only needs to interact with an ERC20 contract but doesn't need to implement one, it can depend solely on the interfaces package without pulling in the full implementation. - -[subs="attributes",javascript] ----- -[dependencies] -openzeppelin_interfaces = "{current_openzeppelin_interfaces_version}" ----- - -IMPORTANT: The version of the interfaces package is independent from the version of the implementation packages. -The current umbrella version is `v4.0.0-alpha.1`, and it depends on the `openzeppelin_interfaces` package `v{current_openzeppelin_interfaces_version}`. - -== Stable Versioning - -The interfaces package follows its own versioning scheme, independent from the implementation packages. Since interfaces are meant to be stable and rarely change, the major version of the interfaces package won't be updated as frequently as the implementation packages. - -This stability means that: - -* Dependencies can remain compatible for longer periods -* Breaking changes in implementations won't force interface updates -* Projects depending only on interfaces are less likely to face version conflicts - -== Usage - -The interfaces package provides three main types of traits that can be imported directly from their respective modules: - -=== Interface Traits - -Standard interface traits that define the contract's functions: - -[source,cairo] ----- -use openzeppelin_interfaces::erc20::IERC20; -use openzeppelin_interfaces::erc721::IERC721; ----- - -=== Dispatchers - -Contract dispatchers for interacting with deployed contracts: - -[source,cairo] ----- -use openzeppelin_interfaces::erc20::IERC20Dispatcher; -use openzeppelin_interfaces::erc721::IERC721Dispatcher; ----- - -=== ABI Traits - -Complete external ABI definition of a given component/contract: - -[source,cairo] ----- -use openzeppelin_interfaces::erc20::ERC20ABI; -use openzeppelin_interfaces::erc721::ERC721ABI; ----- - -This modular approach provides a cleaner and more maintainable way to work with OpenZeppelin contracts, especially in larger projects with multiple dependencies. diff --git a/docs/modules/ROOT/pages/macros.adoc b/docs/modules/ROOT/pages/macros.adoc deleted file mode 100644 index 450f17fca..000000000 --- a/docs/modules/ROOT/pages/macros.adoc +++ /dev/null @@ -1,16 +0,0 @@ -:github-icon: pass:[] - -= Macros - -This crate provides a collection of macros that streamline and simplify development with the library. -To use them, you need to add the `openzeppelin_macros` crate as a dependency in your `Scarb.toml` file: - -```toml -[dependencies] -openzeppelin_macros = "4.0.0-alpha.1" -``` - -== Attribute macros - -- xref:macros/with_components.adoc[with_components] -- xref:macros/type_hash.adoc[type_hash] diff --git a/docs/modules/ROOT/pages/presets.adoc b/docs/modules/ROOT/pages/presets.adoc deleted file mode 100644 index 6437590f5..000000000 --- a/docs/modules/ROOT/pages/presets.adoc +++ /dev/null @@ -1,168 +0,0 @@ -:account-upgradeable: xref:/api/account.adoc#AccountUpgradeable[AccountUpgradeable] -:erc20-upgradeable: xref:/api/erc20.adoc#ERC20Upgradeable[ERC20Upgradeable] -:erc721-upgradeable: xref:/api/erc721.adoc#ERC721Upgradeable[ERC721Upgradeable] -:erc1155-upgradeable: xref:/api/erc1155.adoc#ERC1155Upgradeable[ERC1155Upgradeable] -:eth-account-upgradeable: xref:/api/account.adoc#EthAccountUpgradeable[EthAccountUpgradeable] -:udc: xref:/api/udc.adoc#UniversalDeployer[UniversalDeployer] -:vesting-wallet: xref:/api/finance.adoc#VestingWallet[VestingWallet] -:sierra-class-hashes: https://docs.starknet.io/architecture-and-concepts/smart-contracts/class-hash/[Sierra class hashes] -:starkli: https://book.starkli.rs/introduction[starkli] -:wizard: https://wizard.openzeppelin.com[Wizard for Cairo] - - -= Presets - -include::utils/_class_hashes.adoc[] - -Presets are ready-to-deploy contracts provided by the library. Since presets are intended to be very simple -and as generic as possible, there's no support for custom or complex contracts such as `ERC20Pausable` or `ERC721Mintable`. - -TIP: For contract customization and combination of modules you can use {wizard}, our code-generation tool. - - -== Available presets - -List of available presets and their corresponding {sierra-class-hashes}. Like Contracts for Cairo, -use of preset contracts are subject to the terms of the -https://github.com/OpenZeppelin/cairo-contracts?tab=MIT-1-ov-file#readme[MIT License]. - -NOTE: Class hashes were computed using {class-hash-cairo-version} and the `scarb --release` profile. - -CAUTION: Before version 4.0.0-alpha.1, class hashes were computed using the `scarb --dev` profile. - -|=== -| Name | Sierra Class Hash - -| `{account-upgradeable}` -| `{AccountUpgradeable-class-hash}` - -| `{erc20-upgradeable}` -| `{ERC20Upgradeable-class-hash}` - -| `{erc721-upgradeable}` -| `{ERC721Upgradeable-class-hash}` - -| `{erc1155-upgradeable}` -| `{ERC1155Upgradeable-class-hash}` - -| `{eth-account-upgradeable}` -| `{EthAccountUpgradeable-class-hash}` - -| `{udc}` -| `{UniversalDeployer-class-hash}` - -| `{vesting-wallet}` -| `{VestingWallet-class-hash}` -|=== - -TIP: {starkli} class-hash command can be used to compute the class hash from a Sierra artifact. - -== Usage - -:setup_project: xref:index.adoc#set_up_your_project[setting up a project] -:install_lib: xref:index.adoc#install_the_library[installing the Contracts for Cairo library] -:presets_dir: link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/presets/src[presets directory] - -These preset contracts are ready-to-deploy which means they should already be declared on the Sepolia network. -Simply deploy the preset class hash and add the appropriate constructor arguments. -Deploying the ERC20Upgradeable preset with {starkli}, for example, will look like this: - -[,bash, subs="verbatim,attributes"] ----- -starkli deploy {ERC20Upgradeable-class-hash} \ - \ - --network="sepolia" ----- - -If a class hash has yet to be declared, copy/paste the preset contract code and declare it locally. -Start by {setup_project} and {install_lib}. -Copy the target preset contract from the {presets_dir} and paste it in the new project's `src/lib.cairo` like this: - -[,cairo] ----- -// src/lib.cairo - -#[starknet::contract] -mod ERC20Upgradeable { - use openzeppelin_access::ownable::OwnableComponent; - use openzeppelin_token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; - use openzeppelin_upgrades::UpgradeableComponent; - use openzeppelin_interfaces::upgrades::IUpgradeable; - use starknet::{ContractAddress, ClassHash}; - - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); - component!(path: ERC20Component, storage: erc20, event: ERC20Event); - component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); - - // Ownable Mixin - #[abi(embed_v0)] - impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl; - impl OwnableInternalImpl = OwnableComponent::InternalImpl; - - // ERC20 Mixin - #[abi(embed_v0)] - impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl; - impl ERC20InternalImpl = ERC20Component::InternalImpl; - - // Upgradeable - impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - ownable: OwnableComponent::Storage, - #[substorage(v0)] - erc20: ERC20Component::Storage, - #[substorage(v0)] - upgradeable: UpgradeableComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - OwnableEvent: OwnableComponent::Event, - #[flat] - ERC20Event: ERC20Component::Event, - #[flat] - UpgradeableEvent: UpgradeableComponent::Event - } - - #[constructor] - fn constructor( - ref self: ContractState, - name: ByteArray, - symbol: ByteArray, - fixed_supply: u256, - recipient: ContractAddress, - owner: ContractAddress - ) { - self.ownable.initializer(owner); - self.erc20.initializer(name, symbol); - self.erc20.mint(recipient, fixed_supply); - } - - #[abi(embed_v0)] - impl UpgradeableImpl of IUpgradeable { - fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { - self.ownable.assert_only_owner(); - self.upgradeable.upgrade(new_class_hash); - } - } -} ----- - -Next, compile the contract. - -[,bash] ----- -scarb build ----- - -Finally, declare the preset. - -[,bash] ----- -starkli declare target/dev/my_project_ERC20Upgradeable.contract_class.json \ - --network="sepolia" ----- diff --git a/docs/modules/ROOT/pages/upgrades.adoc b/docs/modules/ROOT/pages/upgrades.adoc deleted file mode 100644 index 5e56c575e..000000000 --- a/docs/modules/ROOT/pages/upgrades.adoc +++ /dev/null @@ -1,125 +0,0 @@ -:contract_classes: https://docs.starknet.io/architecture-and-concepts/smart-contracts/contract-classes/[Contract Classes] -:class_hash: https://docs.starknet.io/architecture-and-concepts/smart-contracts/class-hash/[class hash] -:replace_class_syscall: https://docs.starknet.io/architecture-and-concepts/smart-contracts/system-calls-cairo1/#replace_class[replace_class] -:upgradeable: https://github.com/OpenZeppelin/cairo-contracts/blob/release-v4.0.0-alpha.1/packages/upgrades/src/upgradeable.cairo[Upgradeable] -:ownable: xref:access.adoc#ownership_and_ownable[Ownable] -:i_upgradeable: xref:api/upgrades.adoc#IUpgradeable[IUpgradeable] -:library_calls: https://docs.starknet.io/architecture-and-concepts/smart-contracts/system-calls-cairo1/#library_call[library calls] - -= Upgrades - -In different blockchains, multiple patterns have been developed for making a contract upgradeable including the widely adopted proxy patterns. - -Starknet has native upgradeability through a syscall that updates the contract source code, removing xref:#proxies_in_starknet[the need for proxies]. - -WARNING: Make sure you follow xref:#security[our security recommendations] before upgrading. - -== Replacing contract classes - -To better comprehend how upgradeability works in Starknet, it's important to understand the difference between a contract and its contract class. - -{contract_classes} represent the source code of a program. All contracts are associated to a class, and many contracts can be instances of the same one. Classes are usually represented by a {class_hash}, and before a contract of a class can be deployed, the class hash needs to be declared. - -=== `replace_class_syscall` - -The `{replace_class_syscall}` syscall allows a contract to update its source code by replacing its class hash once deployed. - - -[,cairo] ----- -/// Upgrades the contract source code to the new contract class. -fn upgrade(new_class_hash: ClassHash) { - assert(!new_class_hash.is_zero(), 'Class hash cannot be zero'); - starknet::replace_class_syscall(new_class_hash).unwrap_syscall(); -} ----- - -NOTE: If a contract is deployed without this mechanism, its class hash can still be replaced through {library_calls}. - -== `Upgradeable` component - -OpenZeppelin Contracts for Cairo provides {upgradeable} to add upgradeability support to your contracts. - -=== Usage - -Upgrades are often very sensitive operations, and some form of access control is usually required to -avoid unauthorized upgrades. The {ownable} module is used in this example. - -NOTE: We will be using the following module to implement the {i_upgradeable} interface described in the API Reference section. - -[,cairo] ----- -#[starknet::contract] -mod UpgradeableContract { - use openzeppelin_access::ownable::OwnableComponent; - use openzeppelin_upgrades::UpgradeableComponent; - use openzeppelin_interfaces::upgrades::IUpgradeable; - use starknet::ClassHash; - use starknet::ContractAddress; - - component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); - component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); - - // Ownable Mixin - #[abi(embed_v0)] - impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl; - impl OwnableInternalImpl = OwnableComponent::InternalImpl; - - // Upgradeable - impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl; - - #[storage] - struct Storage { - #[substorage(v0)] - ownable: OwnableComponent::Storage, - #[substorage(v0)] - upgradeable: UpgradeableComponent::Storage - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - #[flat] - OwnableEvent: OwnableComponent::Event, - #[flat] - UpgradeableEvent: UpgradeableComponent::Event - } - - #[constructor] - fn constructor(ref self: ContractState, owner: ContractAddress) { - self.ownable.initializer(owner); - } - - #[abi(embed_v0)] - impl UpgradeableImpl of IUpgradeable { - fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { - // This function can only be called by the owner - self.ownable.assert_only_owner(); - - // Replace the class hash upgrading the contract - self.upgradeable.upgrade(new_class_hash); - } - } -} ----- - -== Security - -Upgrades can be very sensitive operations, and security should always be top of mind while performing one. Please make sure you thoroughly review the changes and their consequences before upgrading. Some aspects to consider are: - -- API changes that might affect integration. For example, changing an external function's arguments might break existing contracts or offchain systems calling your contract. -- Storage changes that might result in lost data (e.g. changing a storage slot name, making existing storage inaccessible). -- Collisions (e.g. mistakenly reusing the same storage slot from another component) are also possible, although less likely if best practices are followed, for example prepending storage variables with the component's name (e.g. `ERC20_balances`). -- Always check for xref:backwards-compatibility.adoc[backwards compatibility] before upgrading between versions of OpenZeppelin Contracts. - -== Proxies in Starknet - -Proxies enable different patterns such as upgrades and clones. But since Starknet achieves the same in different ways is that there's no support to implement them. - -In the case of contract upgrades, it is achieved by simply changing the contract's class hash. As of clones, contracts already are like clones of the class they implement. - -Implementing a proxy pattern in Starknet has an important limitation: there is no fallback mechanism to be used -for redirecting every potential function call to the implementation. This means that a generic proxy contract -can't be implemented. Instead, a limited proxy contract can implement specific functions that forward -their execution to another contract class. -This can still be useful for example to upgrade the logic of some functions. diff --git a/docs/modules/ROOT/pages/utils/_class_hashes.adoc b/docs/modules/ROOT/pages/utils/_class_hashes.adoc deleted file mode 100644 index 2396a7ea8..000000000 --- a/docs/modules/ROOT/pages/utils/_class_hashes.adoc +++ /dev/null @@ -1,16 +0,0 @@ -// Version -:class-hash-cairo-version: https://crates.io/crates/cairo-lang-compiler/2.17.0[cairo 2.17.0] - -// Class Hashes -:ERC20Upgradeable-class-hash: 0x02306d411d9061591d2a661f177ea92e53918a474803c33a901bace86dfaea6c -:ERC721Upgradeable-class-hash: 0x0735400adfb617a215a0eadd009e84ecebf10b258b7ce7583d4131f7fa793bf1 -:ERC1155Upgradeable-class-hash: 0x02f81498862c308981a544e7da3e65c715c375c97a881da2d157b2f3a3dcdd93 -:AccountUpgradeable-class-hash: 0x0342f3c683f708fd920e625e425b77726aa4c834da47ec92b4da5c207f025207 -:EthAccountUpgradeable-class-hash: 0x0216f6773aef13b25e5f8ecc989c4a4668d45ba118b41bbdca10d08fc6fda878 -:UniversalDeployer-class-hash: 0x00ce766f9026176e6796a13720059301c4caa1b24cc55d964afb62bed07b0158 -:MetaTransactionV0-class-hash: 0x051d6576154ab74933e521cd0d8e3367d14ff1713fd2b2ce982af1f555564134 -:VestingWallet-class-hash: 0x051be0e6c0a6904b496c77f991f423e766ff465752cb18e93b6eb5ca525cf219 - -// Presets page -:presets-page: xref:presets.adoc[Sierra class hash] - diff --git a/docs/modules/ROOT/pages/wizard.adoc b/docs/modules/ROOT/pages/wizard.adoc deleted file mode 100644 index a02788f8c..000000000 --- a/docs/modules/ROOT/pages/wizard.adoc +++ /dev/null @@ -1,14 +0,0 @@ -= Wizard for Cairo -:page-notoc: - -Not sure where to start? Use the interactive generator below to bootstrap your -contract and learn about the components offered in OpenZeppelin Contracts for Cairo. - - -NOTE: We strongly recommend checking the xref:components.adoc[Components] section to understand how to extend from our library. - -++++ - - - -++++ diff --git a/scripts/generate_class_hashes.py b/scripts/generate_class_hashes.py new file mode 100644 index 000000000..075eb106b --- /dev/null +++ b/scripts/generate_class_hashes.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python3 +"""Generate preset class-hash constants for the external documentation repository.""" + +import argparse +import json +import re +import subprocess +import sys +from pathlib import Path +from typing import Any, Dict, List + +REPO_ROOT = Path(__file__).resolve().parents[1] +TARGET_DIR = REPO_ROOT / "target" +ARTIFACT_MANIFEST = TARGET_DIR / "release/openzeppelin_presets.starknet_artifacts.json" +PRESET_ORDER = [ + "AccountUpgradeable", + "ERC20Upgradeable", + "ERC721Upgradeable", + "ERC1155Upgradeable", + "EthAccountUpgradeable", + "MetaTransactionV0", + "UniversalDeployer", + "VestingWallet", +] +HASH_PATTERN = re.compile(r"^0x[0-9a-fA-F]+$") +SCARB_VERSION_PATTERN = re.compile(r'^scarb-version\s*=\s*"([^"]+)"\s*$', re.MULTILINE) +STARK_FIELD_PRIME = 2 ** 251 + 17 * 2 ** 192 + 1 + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Generate JavaScript constants for the preset class hashes in OpenZeppelin docs." + ) + parser.add_argument( + "--no-build", + action="store_true", + help="Reuse existing release artifacts instead of building openzeppelin_presets.", + ) + parser.add_argument( + "--scarb-version", + help="Override the scarb version read from the workspace Scarb.toml.", + ) + return parser.parse_args() + + +def read_scarb_version() -> str: + manifest = (REPO_ROOT / "Scarb.toml").read_text(encoding="utf-8") + match = SCARB_VERSION_PATTERN.search(manifest) + if match is None: + raise ValueError("could not find workspace scarb-version in Scarb.toml") + return match.group(1) + + +def build_presets() -> None: + subprocess.run( + [ + "scarb", + "--manifest-path", + str(REPO_ROOT / "Scarb.toml"), + "--target-dir", + str(TARGET_DIR), + "--release", + "build", + "-p", + "openzeppelin_presets", + ], + cwd=REPO_ROOT, + check=True, + stdout=sys.stderr, + ) + + +def read_artifact_manifest() -> Any: + with ARTIFACT_MANIFEST.open(encoding="utf-8") as manifest_file: + return json.load(manifest_file) + + +def normalize_hash(value: Any) -> str: + if not isinstance(value, str) or HASH_PATTERN.fullmatch(value) is None: + raise ValueError(f"invalid Sierra class hash: {value!r}") + + digits = value[2:].lower() + if len(digits) > 64: + raise ValueError(f"Sierra class hash exceeds 32 bytes: {value}") + if int(digits, 16) >= STARK_FIELD_PRIME: + raise ValueError(f"Sierra class hash is outside the Stark field: {value}") + return f"0x{digits.zfill(64)}" + + +def extract_preset_artifacts(payload: Any) -> Dict[str, Path]: + if not isinstance(payload, dict): + raise ValueError("Scarb artifact manifest must be an object") + + contracts = payload.get("contracts") + if not isinstance(contracts, list): + raise ValueError("Scarb artifact manifest must contain a contracts list") + + artifacts: Dict[str, Path] = {} + for contract in contracts: + if not isinstance(contract, dict): + raise ValueError("each contract entry must be an object") + + name = contract.get("contract_name") + if not isinstance(name, str) or not name: + raise ValueError("each contract entry must have a contract_name") + if name in artifacts: + raise ValueError(f"duplicate preset contract: {name}") + + contract_artifacts = contract.get("artifacts") + if not isinstance(contract_artifacts, dict): + raise ValueError(f"preset contract has no artifacts object: {name}") + sierra_file = contract_artifacts.get("sierra") + if not isinstance(sierra_file, str) or not sierra_file: + raise ValueError(f"preset contract has no Sierra artifact: {name}") + + artifacts[name] = ARTIFACT_MANIFEST.parent / sierra_file + + if not artifacts: + raise ValueError("Scarb artifact manifest contains no preset contracts") + + missing = [name for name in PRESET_ORDER if name not in artifacts] + unexpected = sorted(name for name in artifacts if name not in PRESET_ORDER) + if missing or unexpected: + differences = [] + if missing: + differences.append(f"missing: {', '.join(missing)}") + if unexpected: + differences.append(f"unexpected: {', '.join(unexpected)}") + raise ValueError( + f"preset artifacts do not match the documentation constants ({'; '.join(differences)})" + ) + return artifacts + + +def compute_class_hash(artifact: Path) -> str: + if not artifact.is_file(): + raise ValueError(f"Sierra artifact not found: {artifact}") + + result = subprocess.run( + ["starkli", "class-hash", str(artifact)], + cwd=REPO_ROOT, + check=True, + stdout=subprocess.PIPE, + text=True, + ) + return normalize_hash(result.stdout.strip()) + + +def compute_preset_hashes(artifacts: Dict[str, Path]) -> Dict[str, str]: + return {name: compute_class_hash(artifact) for name, artifact in artifacts.items()} + + +def ordered_names(hashes: Dict[str, str]) -> List[str]: + preferred_positions = {name: index for index, name in enumerate(PRESET_ORDER)} + return sorted( + hashes, + key=lambda name: (preferred_positions.get(name, len(PRESET_ORDER)), name), + ) + + +def format_constants(scarb_version: str, hashes: Dict[str, str]) -> str: + lines = [ + f'export const CLASS_HASH_SCARB_VERSION = "{scarb_version}";', + "", + "export const CLASS_HASHES = {", + ] + for name in ordered_names(hashes): + lines.extend( + [ + f"\t{name}ClassHash:", + f'\t\t"{hashes[name]}",', + ] + ) + lines.extend(["};", ""]) + return "\n".join(lines) + + +def main() -> int: + args = parse_args() + try: + if not args.no_build: + build_presets() + artifacts = extract_preset_artifacts(read_artifact_manifest()) + scarb_version = args.scarb_version or read_scarb_version() + hashes = compute_preset_hashes(artifacts) + print(format_constants(scarb_version, hashes), end="") + except FileNotFoundError as error: + print(f"error: required file or command not found: {error.filename}", file=sys.stderr) + return 1 + except subprocess.CalledProcessError as error: + print(f"error: command failed with exit code {error.returncode}", file=sys.stderr) + return error.returncode or 1 + except (json.JSONDecodeError, OSError, ValueError) as error: + print(f"error: {error}", file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/get_hashes_page.py b/scripts/get_hashes_page.py deleted file mode 100644 index 593e79704..000000000 --- a/scripts/get_hashes_page.py +++ /dev/null @@ -1,75 +0,0 @@ -import sys -import json - -KNOWN_ORDER = [ - "ERC20Upgradeable", - "ERC721Upgradeable", - "ERC1155Upgradeable", - "AccountUpgradeable", - "EthAccountUpgradeable", - "UniversalDeployer" -] - -def main(): - # Required compiler version argument - cmp_version = sys.argv[1] - - # Read class hashes from stdin - contracts = json.load(sys.stdin) - - print(generate_doc_file(cmp_version, contracts)) - - -def generate_doc_file(cmp_version, contracts): - header = f"""// Version -:class-hash-cairo-version: \ -https://crates.io/crates/cairo-lang-compiler/{cmp_version}[cairo {cmp_version}] -""" - hashes = "// Class Hashes\n" - contracts['contracts'] = remove_prefix_from_names(contracts['contracts']) - contracts['contracts'].sort(key=lambda x: x['name']) - - hashes += get_known_order_hashes(contracts['contracts']) - for contract in contracts['contracts']: - # Avoid the already added contracts in the known order - if contract['name'] in KNOWN_ORDER: - continue - # Avoid adding mocks - # TODO: remove this after mocks are removed from the artifacts built outside tests - if "Mock" in contract['name']: - continue - hashes += f":{contract['name']}-class-hash: {normalize_len(contract['sierra'])}\n" - - footer = """// Presets page -:presets-page: xref:presets.adoc[Sierra class hash]""" - - return f"{header}\n{hashes}\n{footer}\n" - - -def remove_prefix_from_names(contracts): - for contract in contracts: - contract.update([("name", remove_prefix(contract['name'], 'openzeppelin_presets_'))]) - return contracts - - -def remove_prefix(text, prefix): - if text.startswith(prefix): - return text[len(prefix):] - return text - - -def get_known_order_hashes(contracts): - known_order_hashes = [""] * len(KNOWN_ORDER) - for contract in contracts: - if contract['name'] in KNOWN_ORDER: - index = KNOWN_ORDER.index(contract['name']) - known_order_hashes[index] = f":{contract['name']}-class-hash: {normalize_len(contract['sierra'])}\n" - return ''.join(known_order_hashes) - - -def normalize_len(sierra_hash): - return "0x" + "0" * (66 - len(sierra_hash)) + sierra_hash[2:] - - -if __name__ == '__main__': - main()