diff --git a/.githooks/pre-push b/.githooks/pre-push deleted file mode 100755 index f028ce58e..000000000 --- a/.githooks/pre-push +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -if [ "${CI:-"false"}" != "true" ]; then - npm run test:generation - npm run lint -fi diff --git a/.github/actions/gas-compare/action.yml b/.github/actions/gas-compare/action.yml index 23a756f3d..78c286c94 100644 --- a/.github/actions/gas-compare/action.yml +++ b/.github/actions/gas-compare/action.yml @@ -2,18 +2,18 @@ name: Compare gas costs description: Compare gas costs between branches inputs: token: - description: github token + description: GitHub token, required to access GitHub API required: true report: - description: report to read from + description: Path to the report to compare required: false default: gasReporterOutput.json out_report: - description: report to read + description: Path to save the output report required: false default: ${{ github.ref_name }}.gasreport.json ref_report: - description: report to read from + description: Path to the reference report for comparison required: false default: ${{ github.base_ref }}.gasreport.json @@ -44,7 +44,8 @@ runs: shell: bash - name: Save report if: github.event_name != 'pull_request' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: gasreport + overwrite: true path: ${{ inputs.out_report }} diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index b68fec649..3c5fc602e 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -19,4 +19,4 @@ runs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable diff --git a/.github/actions/storage-layout/action.yml b/.github/actions/storage-layout/action.yml index 573564b67..fb68d5f6b 100644 --- a/.github/actions/storage-layout/action.yml +++ b/.github/actions/storage-layout/action.yml @@ -50,7 +50,8 @@ runs: shell: bash - name: Save artifacts if: github.event_name != 'pull_request' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: layout + overwrite: true path: ${{ inputs.out_layout }} diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 18a38b3c5..6700832b6 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -43,7 +43,7 @@ jobs: run: npm run test:inheritance - name: Check pragma consistency between files run: npm run test:pragma - - name: Check proceduraly generated contracts are up-to-date + - name: Check procedurally generated contracts are up-to-date run: npm run test:generation - name: Compare gas costs uses: ./.github/actions/gas-compare @@ -97,7 +97,7 @@ jobs: uses: ./.github/actions/setup - name: Run coverage run: npm run coverage - - uses: codecov/codecov-action@v4 + - uses: codecov/codecov-action@v5 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} @@ -118,11 +118,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up environment uses: ./.github/actions/setup - - run: rm foundry.toml - uses: crytic/slither-action@v0.4.0 - with: - node-version: 18.15 - slither-version: 0.10.1 codespell: runs-on: ubuntu-latest diff --git a/.github/workflows/formal-verification.yml b/.github/workflows/formal-verification.yml index e0475b195..86acca7f3 100644 --- a/.github/workflows/formal-verification.yml +++ b/.github/workflows/formal-verification.yml @@ -52,7 +52,7 @@ jobs: - name: Install python packages run: pip install -r fv-requirements.txt - name: Install java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: ${{ env.JAVA_VERSION }} diff --git a/.gitignore b/.gitignore index b2b1eab1e..50f1bf5b7 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ npm-debug.log # docs artifacts docs/modules/api +build/site # only used to package @openzeppelin/contracts contracts/build/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 000000000..4738b0555 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +npm run test:generation +npx lint-staged diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b5eb8448..0d6e04e24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,64 @@ # Changelog +## 5.3.0 (2025-04-09) + +### Breaking Changes + +- Replace `GovernorCountingOverridable.VoteReceipt` struct parameter member names `hasOverriden` and `overridenWeight` for `hasOverridden` and `overriddenWeight` respectively. + +#### Custom error changes + +- Replace `AccessControlNonRevokable` with `AccessControlNonRevocable`. +- Replace `GovernorAlreadyOverridenVote` with `GovernorAlreadyOverriddenVote`. +- Replace `GovernorOnlyProposer` with `GovernorUnableToCancel`. + +### Changes by category + +#### Account + +- `ERC4337Utils`: Update the `hash` function to call `getUserOpHash` on the specified entrypoint and add an `ENTRYPOINT_V08` constant. ([#5614](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5614)) +- `ERC7579Utils`: Add ABI decoding checks on calldata bounds within `decodeBatch`. ([#5371](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5371)) +- `ERC7579Utils`: Replace `address(0)` with `address(this)` during execution for calldata compression efficiency. ([#5614](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5614)) + +#### Governance + +- `IGovernor`: Add the `getProposalId` function to the governor interface. ([#5290](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5290)) +- `GovernorProposalGuardian`: Add a governance extension that defines a proposal guardian who can cancel proposals at any stage in their lifecycle. ([#5303](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5303)) +- `GovernorSequentialProposalId`: Adds a `Governor` extension that sequentially numbers proposal ids instead of using the hash. ([#5290](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5290)) +- `GovernorSuperQuorum`: Add a governance extension to support a super quorum. Proposals that meet the super quorum (and have a majority of for votes) advance to the `Succeeded` state before the proposal deadline. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526)) +- `GovernorVotesSuperQuorumFraction`: Add a variant of the `GovernorSuperQuorum` extensions where the super quorum is expressed as a fraction of the total supply. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526)) +- `TimelockController`: Receive function is now virtual. ([#5509](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5509)) + +#### Structures + +- `EnumerableSet`: Add `clear` function to EnumerableSets which deletes all values in the set. ([#5486](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5486)) +- `EnumerableMap`: Add `clear` function to EnumerableMaps which deletes all entries in the map. ([#5486](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5486)) +- `MerkleTree`: Add an update function that replaces a previously inserted leaf with a new value, updating the tree root along the way. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526)) + +#### Tokens + +- `ERC4626`: Use the `asset` getter in `totalAssets`, `_deposit` and `_withdraw`. ([#5322](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5322)) +- `IERC6909`: Add the interface for ERC-6909. ([#5343](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5343)) +- `ERC6909`: Add a standard implementation of ERC6909. ([#5394](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5394)) +- `ERC6909TokenSupply`: Add an extension of ERC6909 which tracks total supply for each token id. ([#5394](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5394)) +- `ERC6909Metadata`: Add an extension of ERC6909 which adds metadata functionality. ([#5394](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5394)) +- `ERC6909ContentURI`: Add an extension of ERC6909 which adds content URI functionality. ([#5394](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5394)) +- `SafeERC20`: Add `trySafeTransfer` and `trySafeTransferFrom` that do not revert and return false if the transfer is not successful. ([#5483](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5483)) + +#### Other + +- `Address`: bubble up revert data on `sendValue` failed call. ([#5379](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5379)) +- `Calldata`: Library with `emptyBytes` and `emptyString` functions to generate empty `bytes` and `string` calldata types. ([#5422](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5422)) +- `ERC2771Forwarder`: Expose the `_isTrustedByTarget` internal function to check whether a target trusts the forwarder. ([#5416](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5416)) +- `Hashes`: Expose `efficientKeccak256` for hashing non-commutative pairs of bytes32 without allocating extra memory. ([#5442](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5442)) +- `Initializable`: Add `_initializableStorageSlot` function that returns a pointer to the storage struct. The function allows customizing with a custom storage slot with an `override`. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526)) +- `Math`: Add `add512`, `mul512` and `mulShr`. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526)) +- `Math`: Add saturating arithmetic operations `saturatingAdd`, `saturatingSub` and `saturatingMul`. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526)) +- `MessageHashUtils`: Add `toDataWithIntendedValidatorHash(address, bytes32)`. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526)) +- `P256`: Adjust precompile detection in `verifyNative` to consider empty `returndata` on invalid verification. Previously, invalid signatures would've reverted with a `MissingPrecompile` error in chains with RIP-7212 support. ([#5620](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5620)) +- `Pausable`: Stop explicitly setting `paused` to `false` during construction. ([#5448](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5448)) +- `Strings`: Add `espaceJSON` that escapes special characters in JSON strings. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526)) + ## 5.2.0 (2025-01-08) ### Breaking Changes @@ -37,7 +96,7 @@ This version comes with changes to the custom error identifiers. Contracts previ ### Utils - `Address`: bubble up revert data on `sendValue` failed call ([#5418](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5418)) -- `Bytes`: Add a library of common operation that operate on `bytes` objects. ([#5252](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5252)) +- `Bytes`: Add a library of common operations that operate on `bytes` objects. ([#5252](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5252)) - `CAIP2` and `CAIP10`: Add libraries for formatting and parsing CAIP-2 and CAIP-10 identifiers. ([#5252](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5252)) - `NoncesKeyed`: Add a variant of `Nonces` that implements the ERC-4337 entrypoint nonce system. ([#5272](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5272)) - `Packing`: Add variants for packing `bytes10` and `bytes22` ([#5274](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5274)) @@ -48,7 +107,7 @@ This version comes with changes to the custom error identifiers. Contracts previ ### Breaking changes - `ERC1967Utils`: Removed duplicate declaration of the `Upgraded`, `AdminChanged` and `BeaconUpgraded` events. These events are still available through the `IERC1967` interface located under the `contracts/interfaces/` directory. Minimum pragma version is now 0.8.21. -- `Governor`, `GovernorCountingSimple`: The `_countVote` virtual function now returns an `uint256` with the total votes casted. This change allows for more flexibility for partial and fractional voting. Upgrading users may get a compilation error that can be fixed by adding a return statement to the `_countVote` function. +- `Governor`, `GovernorCountingSimple`: The `_countVote` virtual function now returns an `uint256` with the total votes cast. This change allows for more flexibility for partial and fractional voting. Upgrading users may get a compilation error that can be fixed by adding a return statement to the `_countVote` function. #### Custom error changes @@ -419,7 +478,7 @@ Instead, contracts now revert with custom errors. Systems that interact with sma ##### Relying on storage locations for retrieving data -After 5.0, the storage location of some variables were changed. This is the case for `Initializable` and all the upgradeable contracts since they now use namespaced storaged locations. Any system relying on storage locations for retrieving data or detecting capabilities should be updated to support these new locations. +After 5.0, the storage location of some variables was changed. This is the case for `Initializable` and all the upgradeable contracts since they now use namespaced storage locations. Any system relying on storage locations for retrieving data or detecting capabilities should be updated to support these new locations. ## 4.9.6 (2024-02-29) diff --git a/FUNDING.json b/FUNDING.json index c67286216..0a362ba35 100644 --- a/FUNDING.json +++ b/FUNDING.json @@ -3,5 +3,8 @@ "ethereum": { "ownedBy": "0xAeb37910f93486C85A1F8F994b67E8187554d664" } + }, + "opRetro": { + "projectId": "0x939241afa4c4b9e1dda6b8250baa8f04fa8b0debce738cfd324c0b18f9926d25" } } diff --git a/GUIDELINES.md b/GUIDELINES.md index 2c21e956b..deafed005 100644 --- a/GUIDELINES.md +++ b/GUIDELINES.md @@ -6,7 +6,7 @@ Code must be thoroughly tested with quality unit tests. We defer to the [Moloch Testing Guide](https://github.com/MolochVentures/moloch/tree/master/test#readme) for specific recommendations, though not all of it is relevant here. Note the introduction: -> Tests should be written, not only to verify correctness of the target code, but to be comprehensively reviewed by other programmers. Therefore, for mission critical Solidity code, the quality of the tests are just as important (if not more so) than the code itself, and should be written with the highest standards of clarity and elegance. +> Tests should be written, not only to verify correctness of the target code, but to be comprehensively reviewed by other programmers. Therefore, for mission critical Solidity code, the quality of the tests is just as important (if not more so) than the code itself, and should be written to the highest standards of clarity and elegance. Every addition or change to the code must come with relevant and comprehensive tests. diff --git a/LICENSE b/LICENSE index b2fee8f21..367f411ba 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2024 Zeppelin Group Ltd +Copyright (c) 2016-2025 Zeppelin Group Ltd Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index fa7b4e31e..60d0a430a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Coverage Status](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts/graph/badge.svg)](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts) [![GitPOAPs](https://public-api.gitpoap.io/v1/repo/OpenZeppelin/openzeppelin-contracts/badge)](https://www.gitpoap.io/gh/OpenZeppelin/openzeppelin-contracts) [![Docs](https://img.shields.io/badge/docs-%F0%9F%93%84-yellow)](https://docs.openzeppelin.com/contracts) -[![Forum](https://img.shields.io/badge/forum-%F0%9F%92%AC-yellow)](https://docs.openzeppelin.com/contracts) +[![Forum](https://img.shields.io/badge/forum-%F0%9F%92%AC-yellow)](https://forum.openzeppelin.com/) **A library for secure smart contract development.** Build on a solid foundation of community-vetted code. @@ -70,7 +70,7 @@ The guides in the [documentation site](https://docs.openzeppelin.com/contracts) * [Tokens](https://docs.openzeppelin.com/contracts/tokens): create tradeable assets or collectives, and distribute them via [Crowdsales](https://docs.openzeppelin.com/contracts/crowdsales). * [Utilities](https://docs.openzeppelin.com/contracts/utilities): generic useful tools including non-overflowing math, signature verification, and trustless paying systems. -The [full API](https://docs.openzeppelin.com/contracts/api/token/ERC20) is also thoroughly documented, and serves as a great reference when developing your smart contract application. You can also ask for help or follow Contracts's development in the [community forum](https://forum.openzeppelin.com). +The [full API](https://docs.openzeppelin.com/contracts/api/token/ERC20) is also thoroughly documented, and serves as a great reference when developing your smart contract application. You can also ask for help or follow Contracts' development in the [community forum](https://forum.openzeppelin.com). Finally, you may want to take a look at the [guides on our blog](https://blog.openzeppelin.com/), which cover several common use cases and good practices. The following articles provide great background reading, though please note that some of the referenced tools have changed, as the tooling in the ecosystem continues to rapidly evolve. diff --git a/RELEASING.md b/RELEASING.md index 06dd218e8..6820d403d 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,10 +1,10 @@ # Releasing -OpenZeppelin Contracts uses a fully automated release process that takes care of compiling, packaging, and publishing the library, all of which is carried out in a clean CI environment (GitHub Actions), implemented in the ([`release-cycle`](.github/workflows/release-cycle.yml)) workflow. This helps to reduce the potential for human error and inconsistencies, and ensures that the release process is ongoing and reliable. +OpenZeppelin Contracts uses a fully automated release process that takes care of compiling, packaging, and publishing the library, all of which is carried out in a clean CI environment (GitHub Actions), implemented in the [`release-cycle`](.github/workflows/release-cycle.yml) workflow. This helps to reduce the potential for human error and inconsistencies, and ensures that the release process is consistent and reliable. ## Changesets -[Changesets](https://github.com/changesets/changesets/) is used as part of our release process for `CHANGELOG.md` management. Each change that is relevant for the codebase is expected to include a changeset. +[Changesets](https://github.com/changesets/changesets/) are used as part of our release process for `CHANGELOG.md` management. Each change that is relevant for the codebase is expected to include a changeset. ## Branching model diff --git a/SECURITY.md b/SECURITY.md index 9922c45e7..bea59e1f2 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -40,4 +40,4 @@ Note as well that the Solidity language itself only guarantees security updates ## Legal -Smart contracts are a nascent technology and carry a high level of technical risk and uncertainty. OpenZeppelin Contracts is made available under the MIT License, which disclaims all warranties in relation to the project and which limits the liability of those that contribute and maintain the project, including OpenZeppelin. Your use of the project is also governed by the terms found at www.openzeppelin.com/tos (the "Terms"). As set out in the Terms, you are solely responsible for any use of OpenZeppelin Contracts and you assume all risks associated with any such use. This Security Policy in no way evidences or represents an on-going duty by any contributor, including OpenZeppelin, to correct any flaws or alert you to all or any of the potential risks of utilizing the project. +Smart contracts are a nascent technology and carry a high level of technical risk and uncertainty. OpenZeppelin Contracts is made available under the MIT License, which disclaims all warranties in relation to the project and which limits the liability of those that contribute and maintain the project, including OpenZeppelin. Your use of the project is also governed by the terms found at www.openzeppelin.com/tos (the "Terms"). As set out in the Terms, you are solely responsible for any use of OpenZeppelin Contracts and you assume all risks associated with any such use. This Security Policy in no way evidences or represents an ongoing duty by any contributor, including OpenZeppelin, to correct any flaws or alert you to all or any of the potential risks of utilizing the project. diff --git a/audits/2017-03.md b/audits/2017-03.md index 4cd6dbfd3..d54174ecb 100644 --- a/audits/2017-03.md +++ b/audits/2017-03.md @@ -20,7 +20,7 @@ The git commit hash we evaluated is: # Disclaimer -The audit makes no statements or warrantees about utility of the code, safety of the code, suitability of the business model, regulatory regime for the business model, or any other statements about fitness of the contracts to purpose, or their bugfree status. The audit documentation is for discussion purposes only. +The audit makes no statements or warranties about utility of the code, safety of the code, suitability of the business model, regulatory regime for the business model, or any other statements about fitness of the contracts to purpose, or their bug free status. The audit documentation is for discussion purposes only. # Executive Summary @@ -90,7 +90,7 @@ We are still working through the confirmation protocol in `Shareable.sol`, but w This bug has a number of causes that need to be addressed: 1. `resetSpentToday` and `confirm` together do not limit the days on which the function can be called or (it appears) the number of times it can be called. -1. Once a call has been confirmed and `execute`d it appears that it can be re-executed. This is not good. +1. Once a call has been confirmed and executed it appears that it can be re-executed. This is not good. 3. `confirmandCheck` doesn't seem to have logic about whether or not the function in question has been called. 4. Even if it did, `revoke` would need updates and logic to deal with revocation requests after a function call had been completed. @@ -109,7 +109,7 @@ It would be nice to see how many payments are pending. This would imply a bit of ## Shareable Contract -We do not believe the `Shareable.sol` contract is ready for primetime. It is missing functions, and as written may be vulnerable to a reordering attack -- an attack in which a miner or other party "racing" with a smart contract participant inserts their own information into a list or mapping. +We do not believe the `Shareable.sol` contract is ready for prime time. It is missing functions, and as written may be vulnerable to a reordering attack -- an attack in which a miner or other party "racing" with a smart contract participant inserts their own information into a list or mapping. The confirmation and revocation code needs to be looked over with a very careful eye imagining extraordinarily bad behavior by shared owners before this contract can be called safe. @@ -159,7 +159,7 @@ Allows owner to set a public string of contract information. No issues. This needs some work. Doesn't check if `_required <= len(_owners)` for instance, that would be a bummer. What if _required were like `MAX - 1`? -I have a general concern about the difference between `owners`, `_owners`, and `owner` in `Ownable.sol`. I recommend "Owners" be renamed. In general we do not recomment single character differences in variable names, although a preceding underscore is not uncommon in Solidity code. +I have a general concern about the difference between `owners`, `_owners`, and `owner` in `Ownable.sol`. I recommend "Owners" be renamed. In general we do not recommend single character differences in variable names, although a preceding underscore is not uncommon in Solidity code. Line 34: "this contract only has six types of events"...actually only two. @@ -224,7 +224,7 @@ Transfer() and transferFrom() use SafeMath functions, which will cause them to t ### SimpleToken -Sample instantiation of StandardToken. Note that in this sample, decimals is 18 and supply only 10,000, so the supply is a small fraction of a single nominal token. +Sample instantiation of StandardToken. Note that in this sample, decimals is 18 and supply is only 10,000, so the supply is a small fraction of a single nominal token. ### CrowdsaleToken diff --git a/audits/2024-12-v5.2.pdf b/audits/2024-12-v5.2.pdf new file mode 100644 index 000000000..ef138f7ec Binary files /dev/null and b/audits/2024-12-v5.2.pdf differ diff --git a/audits/README.md b/audits/README.md index 34bda2af3..4e8c94653 100644 --- a/audits/README.md +++ b/audits/README.md @@ -1,13 +1,14 @@ # Audits -| Date | Version | Commit | Auditor | Scope | Links | -| ------------ | ------- | --------- | ------------ | -------------------- | ----------------------------------------------------------- | -| October 2024 | v5.1.0 | TBD | OpenZeppelin | v5.1 Changes | [🔗](./2024-10-v5.1.pdf) | -| October 2023 | v5.0.0 | `b5a3e69` | OpenZeppelin | v5.0 Changes | [🔗](./2023-10-v5.0.pdf) | -| May 2023 | v4.9.0 | `91df66c` | OpenZeppelin | v4.9 Changes | [🔗](./2023-05-v4.9.pdf) | -| October 2022 | v4.8.0 | `14f98db` | OpenZeppelin | ERC4626, Checkpoints | [🔗](./2022-10-ERC4626.pdf) [🔗](./2022-10-Checkpoints.pdf) | -| October 2018 | v2.0.0 | `dac5bcc` | LevelK | Everything | [🔗](./2018-10.pdf) | -| March 2017 | v1.0.4 | `9c5975a` | New Alchemy | Everything | [🔗](./2017-03.md) | +| Date | Version | Commit | Auditor | Scope | Links | +| ------------- | ------- | -------------------------------------------------------------------------------- | ------------ | -------------------- | ----------------------------------------------------------- | +| December 2024 | v5.2.0 | [`98d28f9`](https://github.com/openzeppelin/openzeppelin-contracts/tree/98d28f9) | OpenZeppelin | v5.2 Changes | [🔗](./2024-12-v5.2.pdf) | +| October 2024 | v5.1.0 | [`aba9ff6`](https://github.com/openzeppelin/openzeppelin-contracts/tree/aba9ff6) | OpenZeppelin | v5.1 Changes | [🔗](./2024-10-v5.1.pdf) | +| October 2023 | v5.0.0 | [`b5a3e69`](https://github.com/openzeppelin/openzeppelin-contracts/tree/b5a3e69) | OpenZeppelin | v5.0 Changes | [🔗](./2023-10-v5.0.pdf) | +| May 2023 | v4.9.0 | [`91df66c`](https://github.com/openzeppelin/openzeppelin-contracts/tree/91df66c) | OpenZeppelin | v4.9 Changes | [🔗](./2023-05-v4.9.pdf) | +| October 2022 | v4.8.0 | [`14f98db`](https://github.com/openzeppelin/openzeppelin-contracts/tree/14f98db) | OpenZeppelin | ERC4626, Checkpoints | [🔗](./2022-10-ERC4626.pdf) [🔗](./2022-10-Checkpoints.pdf) | +| October 2018 | v2.0.0 | [`dac5bcc`](https://github.com/openzeppelin/openzeppelin-contracts/tree/dac5bcc) | LevelK | Everything | [🔗](./2018-10.pdf) | +| March 2017 | v1.0.4 | [`9c5975a`](https://github.com/openzeppelin/openzeppelin-contracts/tree/9c5975a) | New Alchemy | Everything | [🔗](./2017-03.md) | # Formal Verification diff --git a/certora/README.md b/certora/README.md index cd85ba3d4..ff2ccdf7d 100644 --- a/certora/README.md +++ b/certora/README.md @@ -2,14 +2,14 @@ These instructions detail the process for running Certora Verification Tool on OpenZeppelin Contracts. -Documentation for CVT and the specification language are available [here](https://certora.atlassian.net/wiki/spaces/CPD/overview). +Documentation for CVT and the specification language is available [here](https://certora.atlassian.net/wiki/spaces/CPD/overview). ## Prerequisites Follow the [Certora installation guide](https://docs.certora.com/en/latest/docs/user-guide/getting-started/install.html) in order to get the Certora Prover Package and the `solc` executable folder in your path. > **Note** -> An API Key is required for local testing. Although the prover will run on a Github Actions' CI environment on selected Pull Requests. +> An API Key is required for local testing. Although the prover will run on a GitHub Actions' CI environment on selected Pull Requests. ## Running the verification diff --git a/certora/run.js b/certora/run.js index 7b65534ea..91f4a6aec 100755 --- a/certora/run.js +++ b/certora/run.js @@ -7,11 +7,16 @@ // node certora/run.js AccessControl // node certora/run.js AccessControlHarness:AccessControl -const proc = require('child_process'); -const { PassThrough } = require('stream'); -const events = require('events'); +import { spawn } from 'child_process'; +import { PassThrough } from 'stream'; +import { once } from 'events'; +import path from 'path'; +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; +import pLimit from 'p-limit'; +import fs from 'fs/promises'; -const argv = require('yargs') +const argv = yargs(hideBin(process.argv)) .env('') .options({ all: { @@ -21,7 +26,7 @@ const argv = require('yargs') spec: { alias: 's', type: 'string', - default: __dirname + '/specs.json', + default: path.resolve(import.meta.dirname, 'specs.json'), }, parallel: { alias: 'p', @@ -38,18 +43,20 @@ const argv = require('yargs') type: 'array', default: [], }, - }).argv; + }) + .parse(); function match(entry, request) { const [reqSpec, reqContract] = request.split(':').reverse(); return entry.spec == reqSpec && (!reqContract || entry.contract == reqContract); } -const specs = require(argv.spec).filter(s => argv.all || argv._.some(r => match(s, r))); -const limit = require('p-limit')(argv.parallel); +const specs = JSON.parse(fs.readFileSync(argv.spec, 'utf8')).filter(s => argv.all || argv._.some(r => match(s, r))); + +const limit = pLimit(argv.parallel); if (argv._.length == 0 && !argv.all) { - console.error(`Warning: No specs requested. Did you forgot to toggle '--all'?`); + console.error(`Warning: No specs requested. Did you forget to toggle '--all'?`); } for (const r of argv._) { @@ -64,12 +71,13 @@ if (process.exitCode) { } for (const { spec, contract, files, options = [] } of specs) { - limit( - runCertora, - spec, - contract, - files, - [...options, ...argv.options].flatMap(opt => opt.split(' ')), + limit(() => + runCertora( + spec, + contract, + files, + [...options, ...argv.options].flatMap(opt => opt.split(' ')), + ), ); } @@ -79,7 +87,7 @@ async function runCertora(spec, contract, files, options = []) { if (argv.verbose) { console.log('Running:', args.join(' ')); } - const child = proc.spawn('certoraRun', args); + const child = spawn('certoraRun', args); const stream = new PassThrough(); const output = collect(stream); @@ -103,7 +111,7 @@ async function runCertora(spec, contract, files, options = []) { }); // wait for process end - const [code, signal] = await events.once(child, 'exit'); + const [code, signal] = await once(child, 'exit'); // error if (code || signal) { @@ -152,7 +160,7 @@ function writeEntry(spec, contract, success, url) { formatRow( spec, contract, - success ? ':x:' : ':heavy_check_mark:', + success ? ':heavy_check_mark:' : ':x:', url ? `[link](${url?.replace('/output/', '/jobStatus/')})` : 'error', url ? `[link](${url})` : 'error', ), diff --git a/certora/specs/AccessControlDefaultAdminRules.spec b/certora/specs/AccessControlDefaultAdminRules.spec index 2f5bb9d45..5860fd564 100644 --- a/certora/specs/AccessControlDefaultAdminRules.spec +++ b/certora/specs/AccessControlDefaultAdminRules.spec @@ -176,7 +176,7 @@ rule renounceRoleEffect(env e, bytes32 role) { /* ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ Rule: defaultAdmin is only affected by accepting an admin transfer or renoucing │ +│ Rule: defaultAdmin is only affected by accepting an admin transfer or renouncing │ └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ */ rule noDefaultAdminChange(env e, method f, calldataarg args) { @@ -188,7 +188,7 @@ rule noDefaultAdminChange(env e, method f, calldataarg args) { f.selector == sig:acceptDefaultAdminTransfer().selector || f.selector == sig:renounceRole(bytes32,address).selector ), - "default admin is only affected by accepting an admin transfer or renoucing"; + "default admin is only affected by accepting an admin transfer or renouncing"; } /* diff --git a/certora/specs/ERC20FlashMint.spec b/certora/specs/ERC20FlashMint.spec index 4071052ea..6942495b0 100644 --- a/certora/specs/ERC20FlashMint.spec +++ b/certora/specs/ERC20FlashMint.spec @@ -18,7 +18,7 @@ methods { */ ghost mapping(address => mathint) trackedMintAmount; ghost mapping(address => mathint) trackedBurnAmount; -ghost mapping(address => mapping(address => mathint)) trackedTransferedAmount; +ghost mapping(address => mapping(address => mathint)) trackedTransferredAmount; function specUpdate(address from, address to, uint256 amount) { if (from == 0 && to == 0) { assert(false); } // defensive @@ -28,7 +28,7 @@ function specUpdate(address from, address to, uint256 amount) { } else if (to == 0) { trackedBurnAmount[from] = amount; } else { - trackedTransferedAmount[from][to] = amount; + trackedTransferredAmount[from][to] = amount; } } @@ -51,5 +51,5 @@ rule checkMintAndBurn(env e) { assert trackedMintAmount[receiver] == to_mathint(amount); assert trackedBurnAmount[receiver] == amount + to_mathint(recipient == 0 ? fees : 0); - assert (fees > 0 && recipient != 0) => trackedTransferedAmount[receiver][recipient] == to_mathint(fees); + assert (fees > 0 && recipient != 0) => trackedTransferredAmount[receiver][recipient] == to_mathint(fees); } diff --git a/contracts/access/AccessControl.sol b/contracts/access/AccessControl.sol index 3e3341e9c..aa6645532 100644 --- a/contracts/access/AccessControl.sol +++ b/contracts/access/AccessControl.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol) pragma solidity ^0.8.20; @@ -191,7 +191,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 { } /** - * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. + * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * diff --git a/contracts/access/IAccessControl.sol b/contracts/access/IAccessControl.sol index 4c16a6ef7..f6dc00d61 100644 --- a/contracts/access/IAccessControl.sol +++ b/contracts/access/IAccessControl.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; @@ -23,7 +23,7 @@ interface IAccessControl { * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. + * {RoleAdminChanged} not being emitted to signal this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); diff --git a/contracts/access/manager/AuthorityUtils.sol b/contracts/access/manager/AuthorityUtils.sol index fb3018ca8..8b0470968 100644 --- a/contracts/access/manager/AuthorityUtils.sol +++ b/contracts/access/manager/AuthorityUtils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/AuthorityUtils.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (access/manager/AuthorityUtils.sol) pragma solidity ^0.8.20; @@ -17,16 +17,20 @@ library AuthorityUtils { address target, bytes4 selector ) internal view returns (bool immediate, uint32 delay) { - (bool success, bytes memory data) = authority.staticcall( - abi.encodeCall(IAuthority.canCall, (caller, target, selector)) - ); - if (success) { - if (data.length >= 0x40) { - (immediate, delay) = abi.decode(data, (bool, uint32)); - } else if (data.length >= 0x20) { - immediate = abi.decode(data, (bool)); + bytes memory data = abi.encodeCall(IAuthority.canCall, (caller, target, selector)); + + assembly ("memory-safe") { + mstore(0x00, 0x00) + mstore(0x20, 0x00) + + if staticcall(gas(), authority, add(data, 0x20), mload(data), 0x00, 0x40) { + immediate := mload(0x00) + delay := mload(0x20) + + // If delay does not fit in a uint32, return 0 (no delay) + // equivalent to: if gt(delay, 0xFFFFFFFF) { delay := 0 } + delay := mul(delay, iszero(shr(32, delay))) } } - return (immediate, delay); } } diff --git a/contracts/account/utils/draft-ERC4337Utils.sol b/contracts/account/utils/draft-ERC4337Utils.sol index d13d51939..6d2c8ccca 100644 --- a/contracts/account/utils/draft-ERC4337Utils.sol +++ b/contracts/account/utils/draft-ERC4337Utils.sol @@ -1,12 +1,18 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (account/utils/draft-ERC4337Utils.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (account/utils/draft-ERC4337Utils.sol) pragma solidity ^0.8.20; -import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol"; +import {IEntryPoint, PackedUserOperation} from "../../interfaces/draft-IERC4337.sol"; import {Math} from "../../utils/math/Math.sol"; +import {Calldata} from "../../utils/Calldata.sol"; import {Packing} from "../../utils/Packing.sol"; +/// @dev This is available on all entrypoint since v0.4.0, but is not formally part of the ERC. +interface IEntryPointExtra { + function getUserOpHash(PackedUserOperation calldata userOp) external view returns (bytes32); +} + /** * @dev Library with common ERC-4337 utility functions. * @@ -15,6 +21,12 @@ import {Packing} from "../../utils/Packing.sol"; library ERC4337Utils { using Packing for *; + /// @dev Address of the entrypoint v0.7.0 + IEntryPoint internal constant ENTRYPOINT_V07 = IEntryPoint(0x0000000071727De22E5E9d8BAf0edAc6f37da032); + + /// @dev Address of the entrypoint v0.8.0 + IEntryPoint internal constant ENTRYPOINT_V08 = IEntryPoint(0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108); + /// @dev For simulation purposes, validateUserOp (and validatePaymasterUserOp) return this value on success. uint256 internal constant SIG_VALIDATION_SUCCESS = 0; @@ -73,31 +85,16 @@ library ERC4337Utils { return (aggregator_, block.timestamp < validAfter || validUntil < block.timestamp); } - /// @dev Computes the hash of a user operation for a given entrypoint and chainid. - function hash( - PackedUserOperation calldata self, - address entrypoint, - uint256 chainid - ) internal pure returns (bytes32) { - bytes32 result = keccak256( - abi.encode( - keccak256( - abi.encode( - self.sender, - self.nonce, - keccak256(self.initCode), - keccak256(self.callData), - self.accountGasLimits, - self.preVerificationGas, - self.gasFees, - keccak256(self.paymasterAndData) - ) - ), - entrypoint, - chainid - ) - ); - return result; + /// @dev Get the hash of a user operation for a given entrypoint + function hash(PackedUserOperation calldata self, address entrypoint) internal view returns (bytes32) { + // NOTE: getUserOpHash is available since v0.4.0 + // + // Prior to v0.8.0, this was easy to replicate for any entrypoint and chainId. Since v0.8.0 of the + // entrypoint, this depends on the Entrypoint's domain separator, which cannot be hardcoded and is complex + // to recompute. Domain separator could be fetch using the `getDomainSeparatorV4` getter, or recomputed from + // the ERC-5267 getter, but both operation would require doing a view call to the entrypoint. Overall it feels + // simpler and less error prone to get that functionality from the entrypoint directly. + return IEntryPointExtra(entrypoint).getUserOpHash(self); } /// @dev Returns `factory` from the {PackedUserOperation}, or address(0) if the initCode is empty or not properly formatted. @@ -107,7 +104,7 @@ library ERC4337Utils { /// @dev Returns `factoryData` from the {PackedUserOperation}, or empty bytes if the initCode is empty or not properly formatted. function factoryData(PackedUserOperation calldata self) internal pure returns (bytes calldata) { - return self.initCode.length < 20 ? _emptyCalldataBytes() : self.initCode[20:]; + return self.initCode.length < 20 ? Calldata.emptyBytes() : self.initCode[20:]; } /// @dev Returns `verificationGasLimit` from the {PackedUserOperation}. @@ -157,14 +154,6 @@ library ERC4337Utils { /// @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}. function paymasterData(PackedUserOperation calldata self) internal pure returns (bytes calldata) { - return self.paymasterAndData.length < 52 ? _emptyCalldataBytes() : self.paymasterAndData[52:]; - } - - // slither-disable-next-line write-after-write - function _emptyCalldataBytes() private pure returns (bytes calldata result) { - assembly ("memory-safe") { - result.offset := 0 - result.length := 0 - } + return self.paymasterAndData.length < 52 ? Calldata.emptyBytes() : self.paymasterAndData[52:]; } } diff --git a/contracts/account/utils/draft-ERC7579Utils.sol b/contracts/account/utils/draft-ERC7579Utils.sol index 28aa64d5c..027d00df4 100644 --- a/contracts/account/utils/draft-ERC7579Utils.sol +++ b/contracts/account/utils/draft-ERC7579Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (account/utils/draft-ERC7579Utils.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (account/utils/draft-ERC7579Utils.sol) pragma solidity ^0.8.20; @@ -218,7 +218,9 @@ library ERC7579Utils { uint256 value, bytes calldata data ) private returns (bytes memory) { - (bool success, bytes memory returndata) = target.call{value: value}(data); + (bool success, bytes memory returndata) = (target == address(0) ? address(this) : target).call{value: value}( + data + ); return _validateExecutionMode(index, execType, success, returndata); } @@ -229,7 +231,7 @@ library ERC7579Utils { address target, bytes calldata data ) private returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); + (bool success, bytes memory returndata) = (target == address(0) ? address(this) : target).delegatecall(data); return _validateExecutionMode(index, execType, success, returndata); } diff --git a/contracts/finance/VestingWallet.sol b/contracts/finance/VestingWallet.sol index d29194563..03024fae7 100644 --- a/contracts/finance/VestingWallet.sol +++ b/contracts/finance/VestingWallet.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (finance/VestingWallet.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (finance/VestingWallet.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol"; @@ -16,7 +16,7 @@ import {Ownable} from "../access/Ownable.sol"; * Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly) * be immediately releasable. * - * By setting the duration to 0, one can configure this contract to behave like an asset timelock that hold tokens for + * By setting the duration to 0, one can configure this contract to behave like an asset timelock that holds tokens for * a beneficiary until a specified time. * * NOTE: Since the wallet is {Ownable}, and ownership can be transferred, it is possible to sell unvested tokens. diff --git a/contracts/governance/Governor.sol b/contracts/governance/Governor.sol index 41258afff..c0f7a8b48 100644 --- a/contracts/governance/Governor.sol +++ b/contracts/governance/Governor.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (governance/Governor.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (governance/Governor.sol) pragma solidity ^0.8.20; @@ -21,9 +21,9 @@ import {IGovernor, IERC6372} from "./IGovernor.sol"; * * This contract is abstract and requires several functions to be implemented in various modules: * - * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote} + * - A counting module must implement {_quorumReached}, {_voteSucceeded} and {_countVote} * - A voting module must implement {_getVotes} - * - Additionally, {votingPeriod} must also be implemented + * - Additionally, {votingPeriod}, {votingDelay}, and {quorum} must also be implemented */ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC721Receiver, IERC1155Receiver { using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque; @@ -92,6 +92,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { return interfaceId == type(IGovernor).interfaceId || + interfaceId == type(IGovernor).interfaceId ^ IGovernor.getProposalId.selector || interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } @@ -132,6 +133,18 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash))); } + /** + * @dev See {IGovernor-getProposalId}. + */ + function getProposalId( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) public view virtual returns (uint256) { + return hashProposal(targets, values, calldatas, descriptionHash); + } + /** * @dev See {IGovernor-state}. */ @@ -317,7 +330,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 string memory description, address proposer ) internal virtual returns (uint256 proposalId) { - proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description))); + proposalId = getProposalId(targets, values, calldatas, keccak256(bytes(description))); if (targets.length != values.length || targets.length != calldatas.length || targets.length == 0) { revert GovernorInvalidProposalLength(targets.length, calldatas.length, values.length); @@ -358,7 +371,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 bytes[] memory calldatas, bytes32 descriptionHash ) public virtual returns (uint256) { - uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); + uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Succeeded)); @@ -406,7 +419,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 bytes[] memory calldatas, bytes32 descriptionHash ) public payable virtual returns (uint256) { - uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); + uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); _validateStateBitmap( proposalId, @@ -442,7 +455,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 * performed (for example adding a vault/timelock). * * NOTE: Calling this function directly will NOT check the current state of the proposal, set the executed flag to - * true or emit the `ProposalExecuted` event. Executing a proposal should be done using {execute} or {_execute}. + * true or emit the `ProposalExecuted` event. Executing a proposal should be done using {execute}. */ function _executeOperations( uint256 /* proposalId */, @@ -468,14 +481,11 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 ) public virtual returns (uint256) { // The proposalId will be recomputed in the `_cancel` call further down. However we need the value before we // do the internal call, because we need to check the proposal state BEFORE the internal `_cancel` call - // changes it. The `hashProposal` duplication has a cost that is limited, and that we accept. - uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); + // changes it. The `getProposalId` duplication has a cost that is limited, and that we accept. + uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); - // public cancel restrictions (on top of existing _cancel restrictions). - _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Pending)); - if (_msgSender() != proposalProposer(proposalId)) { - revert GovernorOnlyProposer(_msgSender()); - } + address caller = _msgSender(); + if (!_validateCancel(proposalId, caller)) revert GovernorUnableToCancel(proposalId, caller); return _cancel(targets, values, calldatas, descriptionHash); } @@ -492,7 +502,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 bytes[] memory calldatas, bytes32 descriptionHash ) internal virtual returns (uint256) { - uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); + uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash); _validateStateBitmap( proposalId, @@ -792,6 +802,15 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 } } + /** + * @dev Check if the `caller` can cancel the proposal with the given `proposalId`. + * + * The default implementation allows the proposal proposer to cancel the proposal during the pending state. + */ + function _validateCancel(uint256 proposalId, address caller) internal view virtual returns (bool) { + return (state(proposalId) == ProposalState.Pending) && caller == proposalProposer(proposalId); + } + /** * @inheritdoc IERC6372 */ diff --git a/contracts/governance/IGovernor.sol b/contracts/governance/IGovernor.sol index 28f8aaac0..d51e7deb2 100644 --- a/contracts/governance/IGovernor.sol +++ b/contracts/governance/IGovernor.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (governance/IGovernor.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (governance/IGovernor.sol) pragma solidity ^0.8.20; @@ -39,11 +39,6 @@ interface IGovernor is IERC165, IERC6372 { */ error GovernorDisabledDeposit(); - /** - * @dev The `account` is not a proposer. - */ - error GovernorOnlyProposer(address account); - /** * @dev The `account` is not the governance executor. */ @@ -112,6 +107,11 @@ interface IGovernor is IERC165, IERC6372 { */ error GovernorInvalidSignature(address voter); + /** + * @dev The given `account` is unable to cancel the proposal with given `proposalId`. + */ + error GovernorUnableToCancel(uint256 proposalId, address account); + /** * @dev Emitted when a proposal is created. */ @@ -203,7 +203,9 @@ interface IGovernor is IERC165, IERC6372 { /** * @notice module:core - * @dev Hashing function used to (re)build the proposal id from the proposal details.. + * @dev Hashing function used to (re)build the proposal id from the proposal details. + * + * NOTE: For all off-chain and external calls, use {getProposalId}. */ function hashProposal( address[] memory targets, @@ -212,6 +214,17 @@ interface IGovernor is IERC165, IERC6372 { bytes32 descriptionHash ) external pure returns (uint256); + /** + * @notice module:core + * @dev Function used to get the proposal id from the proposal details. + */ + function getProposalId( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) external view returns (uint256); + /** * @notice module:core * @dev Current state of a proposal, following Compound's convention diff --git a/contracts/governance/README.adoc b/contracts/governance/README.adoc index d390d1be8..0a9c2c4e3 100644 --- a/contracts/governance/README.adoc +++ b/contracts/governance/README.adoc @@ -20,17 +20,19 @@ For a written walkthrough, check out our guide on xref:ROOT:governance.adoc[How Votes modules determine the source of voting power, and sometimes quorum number. -* {GovernorVotes}: Extracts voting weight from an {ERC20Votes}, or since v4.5 an {ERC721Votes} token. +* {GovernorVotes}: Extracts voting weight from an {IVotes} contract. * {GovernorVotesQuorumFraction}: Combines with `GovernorVotes` to set the quorum as a fraction of the total token supply. +* {GovernorVotesSuperQuorumFraction}: Combines `GovernorSuperQuorum` with `GovernorVotesQuorumFraction` to set the super quorum as a fraction of the total token supply. + Counting modules determine valid voting options. * {GovernorCountingSimple}: Simple voting mechanism with 3 voting options: Against, For and Abstain. * {GovernorCountingFractional}: A more modular voting system that allows a user to vote with only part of its voting power, and to split that weight arbitrarily between the 3 different options (Against, For and Abstain). -* {GovernorCountingOverridable}: An extended version of `GovernorCountingSimple` which allows delegatees to override their delegates while the vote is live. +* {GovernorCountingOverridable}: An extended version of `GovernorCountingSimple` which allows delegatees to override their delegates while the vote is live. Must be used in conjunction with {VotesExtended}. Timelock extensions add a delay for governance decisions to be executed. The workflow is extended to require a `queue` step before execution. With these modules, proposals are executed by the external timelock contract, thus it is the timelock that has to hold the assets that are being governed. @@ -48,6 +50,10 @@ Other extensions can customize the behavior or interface in multiple ways. * {GovernorPreventLateQuorum}: Ensures there is a minimum voting period after quorum is reached as a security protection against large voters. +* {GovernorProposalGuardian}: Adds a proposal guardian that can cancel proposals at any stage in their lifecycle--this permission is passed on to the proposers if the guardian is not set. + +* {GovernorSuperQuorum}: Extension of {Governor} with a super quorum. Proposals that meet the super quorum (and have a majority of for votes) advance to the `Succeeded` state before the proposal deadline. + In addition to modules and extensions, the core contract requires a few virtual functions to be implemented to your particular specifications: * <>: Delay (in ERC-6372 clock) since the proposal is submitted until voting power is fixed and voting starts. This can be used to enforce a delay after a proposal is published for users to buy tokens, or delegate their votes. @@ -68,12 +74,14 @@ NOTE: Functions of the `Governor` contract do not include access control. If you {{GovernorCountingFractional}} -{{GovernorCountingOverride}} +{{GovernorCountingOverridable}} {{GovernorVotes}} {{GovernorVotesQuorumFraction}} +{{GovernorVotesSuperQuorumFraction}} + === Extensions {{GovernorTimelockAccess}} @@ -88,6 +96,10 @@ NOTE: Functions of the `Governor` contract do not include access control. If you {{GovernorStorage}} +{{GovernorProposalGuardian}} + +{{GovernorSuperQuorum}} + == Utils {{Votes}} @@ -103,7 +115,7 @@ In a governance system, the {TimelockController} contract is in charge of introd [[timelock-terminology]] ==== Terminology -* *Operation:* A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution (see xref:access-control.adoc#operation_lifecycle[operation lifecycle]). If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content. +* *Operation:* A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution. If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content. * *Operation status:* ** *Unset:* An operation that is not part of the timelock mechanism. ** *Waiting:* An operation that has been scheduled, before the timer expires. diff --git a/contracts/governance/TimelockController.sol b/contracts/governance/TimelockController.sol index 349d940fd..b8e4bfae6 100644 --- a/contracts/governance/TimelockController.sol +++ b/contracts/governance/TimelockController.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (governance/TimelockController.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (governance/TimelockController.sol) pragma solidity ^0.8.20; @@ -152,7 +152,7 @@ contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder { /** * @dev Contract might receive/hold ETH as part of the maintenance process. */ - receive() external payable {} + receive() external payable virtual {} /** * @dev See {IERC165-supportsInterface}. diff --git a/contracts/governance/extensions/GovernorCountingFractional.sol b/contracts/governance/extensions/GovernorCountingFractional.sol index d2231bb95..2462227a0 100644 --- a/contracts/governance/extensions/GovernorCountingFractional.sol +++ b/contracts/governance/extensions/GovernorCountingFractional.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorCountingFractional.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorCountingFractional.sol) pragma solidity ^0.8.20; @@ -27,7 +27,7 @@ import {Math} from "../../utils/math/Math.sol"; * * Voting from an L2 with tokens held by a bridge * * Voting privately from a shielded pool using zero knowledge proofs. * - * Based on ScopeLift's GovernorCountingFractional[https://github.com/ScopeLift/flexible-voting/blob/e5de2efd1368387b840931f19f3c184c85842761/src/GovernorCountingFractional.sol] + * Based on ScopeLift's https://github.com/ScopeLift/flexible-voting/blob/e5de2efd1368387b840931f19f3c184c85842761/src/GovernorCountingFractional.sol[`GovernorCountingFractional`] * * _Available since v5.1._ */ @@ -125,9 +125,9 @@ abstract contract GovernorCountingFractional is Governor { * * `abi.encodePacked(uint128(againstVotes), uint128(forVotes), uint128(abstainVotes))` * - * NOTE: Consider that fractional voting restricts the number of casted vote (in each category) to 128 bits. + * NOTE: Consider that fractional voting restricts the number of casted votes (in each category) to 128 bits. * Depending on how many decimals the underlying token has, a single voter may require to split their vote into - * multiple vote operations. For precision higher than ~30 decimals, large token holders may require an + * multiple vote operations. For precision higher than ~30 decimals, large token holders may require a * potentially large number of calls to cast all their votes. The voter has the possibility to cast all the * remaining votes in a single operation using the traditional "bravo" vote. */ diff --git a/contracts/governance/extensions/GovernorCountingOverridable.sol b/contracts/governance/extensions/GovernorCountingOverridable.sol index 2ed6c1cc5..bc06de96d 100644 --- a/contracts/governance/extensions/GovernorCountingOverridable.sol +++ b/contracts/governance/extensions/GovernorCountingOverridable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (governance/extensions/GovernorCountingOverridable.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorCountingOverridable.sol) pragma solidity ^0.8.20; @@ -27,8 +27,8 @@ abstract contract GovernorCountingOverridable is GovernorVotes { struct VoteReceipt { uint8 casted; // 0 if vote was not casted. Otherwise: support + 1 - bool hasOverriden; - uint208 overridenWeight; + bool hasOverridden; + uint208 overriddenWeight; } struct ProposalVote { @@ -42,7 +42,7 @@ abstract contract GovernorCountingOverridable is GovernorVotes { /// @dev A delegated vote on `proposalId` was overridden by `weight` event OverrideVoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason); - error GovernorAlreadyOverridenVote(address account); + error GovernorAlreadyOverriddenVote(address account); mapping(uint256 proposalId => ProposalVote) private _proposalVotes; @@ -70,7 +70,7 @@ abstract contract GovernorCountingOverridable is GovernorVotes { * @dev Check if an `account` has overridden their delegate for a proposal. */ function hasVotedOverride(uint256 proposalId, address account) public view virtual returns (bool) { - return _proposalVotes[proposalId].voteReceipt[account].hasOverriden; + return _proposalVotes[proposalId].voteReceipt[account].hasOverridden; } /** @@ -122,7 +122,7 @@ abstract contract GovernorCountingOverridable is GovernorVotes { revert GovernorAlreadyCastVote(account); } - totalWeight -= proposalVote.voteReceipt[account].overridenWeight; + totalWeight -= proposalVote.voteReceipt[account].overriddenWeight; proposalVote.votes[support] += totalWeight; proposalVote.voteReceipt[account].casted = support + 1; @@ -141,26 +141,26 @@ abstract contract GovernorCountingOverridable is GovernorVotes { revert GovernorInvalidVoteType(); } - if (proposalVote.voteReceipt[account].hasOverriden) { - revert GovernorAlreadyOverridenVote(account); + if (proposalVote.voteReceipt[account].hasOverridden) { + revert GovernorAlreadyOverriddenVote(account); } uint256 snapshot = proposalSnapshot(proposalId); - uint256 overridenWeight = VotesExtended(address(token())).getPastBalanceOf(account, snapshot); + uint256 overriddenWeight = VotesExtended(address(token())).getPastBalanceOf(account, snapshot); address delegate = VotesExtended(address(token())).getPastDelegate(account, snapshot); uint8 delegateCasted = proposalVote.voteReceipt[delegate].casted; - proposalVote.voteReceipt[account].hasOverriden = true; - proposalVote.votes[support] += overridenWeight; + proposalVote.voteReceipt[account].hasOverridden = true; + proposalVote.votes[support] += overriddenWeight; if (delegateCasted == 0) { - proposalVote.voteReceipt[delegate].overridenWeight += SafeCast.toUint208(overridenWeight); + proposalVote.voteReceipt[delegate].overriddenWeight += SafeCast.toUint208(overriddenWeight); } else { uint8 delegateSupport = delegateCasted - 1; - proposalVote.votes[delegateSupport] -= overridenWeight; - emit VoteReduced(delegate, proposalId, delegateSupport, overridenWeight); + proposalVote.votes[delegateSupport] -= overriddenWeight; + emit VoteReduced(delegate, proposalId, delegateSupport, overriddenWeight); } - return overridenWeight; + return overriddenWeight; } /// @dev Variant of {Governor-_castVote} that deals with vote overrides. Returns the overridden weight. @@ -172,13 +172,13 @@ abstract contract GovernorCountingOverridable is GovernorVotes { ) internal virtual returns (uint256) { _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Active)); - uint256 overridenWeight = _countOverride(proposalId, account, support); + uint256 overriddenWeight = _countOverride(proposalId, account, support); - emit OverrideVoteCast(account, proposalId, support, overridenWeight, reason); + emit OverrideVoteCast(account, proposalId, support, overriddenWeight, reason); _tallyUpdated(proposalId); - return overridenWeight; + return overriddenWeight; } /// @dev Public function for casting an override vote. Returns the overridden weight. diff --git a/contracts/governance/extensions/GovernorProposalGuardian.sol b/contracts/governance/extensions/GovernorProposalGuardian.sol new file mode 100644 index 000000000..10821ff41 --- /dev/null +++ b/contracts/governance/extensions/GovernorProposalGuardian.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorProposalGuardian.sol) +pragma solidity ^0.8.20; + +import {Governor} from "../Governor.sol"; + +/** + * @dev Extension of {Governor} which adds a proposal guardian that can cancel proposals at any stage in the proposal's lifecycle. + * + * NOTE: if the proposal guardian is not configured, then proposers take this role for their proposals. + */ +abstract contract GovernorProposalGuardian is Governor { + address private _proposalGuardian; + + event ProposalGuardianSet(address oldProposalGuardian, address newProposalGuardian); + + /** + * @dev Getter that returns the address of the proposal guardian. + */ + function proposalGuardian() public view virtual returns (address) { + return _proposalGuardian; + } + + /** + * @dev Update the proposal guardian's address. This operation can only be performed through a governance proposal. + * + * Emits a {ProposalGuardianSet} event. + */ + function setProposalGuardian(address newProposalGuardian) public virtual onlyGovernance { + _setProposalGuardian(newProposalGuardian); + } + + /** + * @dev Internal setter for the proposal guardian. + * + * Emits a {ProposalGuardianSet} event. + */ + function _setProposalGuardian(address newProposalGuardian) internal virtual { + emit ProposalGuardianSet(_proposalGuardian, newProposalGuardian); + _proposalGuardian = newProposalGuardian; + } + + /** + * @dev Override {Governor-_validateCancel} to implement the extended cancellation logic. + * + * * The {proposalGuardian} can cancel any proposal at any point. + * * If no proposal guardian is set, the {IGovernor-proposalProposer} can cancel their proposals at any point. + * * In any case, permissions defined in {Governor-_validateCancel} (or another override) remains valid. + */ + function _validateCancel(uint256 proposalId, address caller) internal view virtual override returns (bool) { + address guardian = proposalGuardian(); + + return + guardian == caller || + (guardian == address(0) && caller == proposalProposer(proposalId)) || + super._validateCancel(proposalId, caller); + } +} diff --git a/contracts/governance/extensions/GovernorSequentialProposalId.sol b/contracts/governance/extensions/GovernorSequentialProposalId.sol new file mode 100644 index 000000000..8cfa5aa46 --- /dev/null +++ b/contracts/governance/extensions/GovernorSequentialProposalId.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorSequentialProposalId.sol) + +pragma solidity ^0.8.20; + +import {Governor} from "../Governor.sol"; + +/** + * @dev Extension of {Governor} that changes the numbering of proposal ids from the default hash-based approach to + * sequential ids. + */ +abstract contract GovernorSequentialProposalId is Governor { + uint256 private _latestProposalId; + mapping(uint256 proposalHash => uint256 proposalId) private _proposalIds; + + /** + * @dev The {latestProposalId} may only be initialized if it hasn't been set yet + * (through initialization or the creation of a proposal). + */ + error GovernorAlreadyInitializedLatestProposalId(); + + /** + * @dev See {IGovernor-getProposalId}. + */ + function getProposalId( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) public view virtual override returns (uint256) { + uint256 proposalHash = hashProposal(targets, values, calldatas, descriptionHash); + uint256 storedProposalId = _proposalIds[proposalHash]; + if (storedProposalId == 0) { + revert GovernorNonexistentProposal(0); + } + return storedProposalId; + } + + /** + * @dev Returns the latest proposal id. A return value of 0 means no proposals have been created yet. + */ + function latestProposalId() public view virtual returns (uint256) { + return _latestProposalId; + } + + /** + * @dev See {IGovernor-_propose}. + * Hook into the proposing mechanism to increment proposal count. + */ + function _propose( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + string memory description, + address proposer + ) internal virtual override returns (uint256) { + uint256 proposalHash = hashProposal(targets, values, calldatas, keccak256(bytes(description))); + uint256 storedProposalId = _proposalIds[proposalHash]; + if (storedProposalId == 0) { + _proposalIds[proposalHash] = ++_latestProposalId; + } + return super._propose(targets, values, calldatas, description, proposer); + } + + /** + * @dev Internal function to set the {latestProposalId}. This function is helpful when transitioning + * from another governance system. The next proposal id will be `newLatestProposalId` + 1. + * + * May only call this function if the current value of {latestProposalId} is 0. + */ + function _initializeLatestProposalId(uint256 newLatestProposalId) internal virtual { + if (_latestProposalId != 0) { + revert GovernorAlreadyInitializedLatestProposalId(); + } + _latestProposalId = newLatestProposalId; + } +} diff --git a/contracts/governance/extensions/GovernorStorage.sol b/contracts/governance/extensions/GovernorStorage.sol index 22db09992..914b77d9d 100644 --- a/contracts/governance/extensions/GovernorStorage.sol +++ b/contracts/governance/extensions/GovernorStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorStorage.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorStorage.sol) pragma solidity ^0.8.20; @@ -50,7 +50,7 @@ abstract contract GovernorStorage is Governor { } /** - * @dev Version of {IGovernorTimelock-queue} with only `proposalId` as an argument. + * @dev Version of {IGovernor-queue} with only `proposalId` as an argument. */ function queue(uint256 proposalId) public virtual { // here, using storage is more efficient than memory diff --git a/contracts/governance/extensions/GovernorSuperQuorum.sol b/contracts/governance/extensions/GovernorSuperQuorum.sol new file mode 100644 index 000000000..f10e8e13f --- /dev/null +++ b/contracts/governance/extensions/GovernorSuperQuorum.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorSuperQuorum.sol) +pragma solidity ^0.8.20; + +import {Governor} from "../Governor.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; +import {Checkpoints} from "../../utils/structs/Checkpoints.sol"; + +/** + * @dev Extension of {Governor} with a super quorum. Proposals that meet the super quorum (and have a majority of for + * votes) advance to the `Succeeded` state before the proposal deadline. Counting modules that want to use this + * extension must implement {proposalVotes}. + */ +abstract contract GovernorSuperQuorum is Governor { + /** + * @dev Minimum number of cast votes required for a proposal to reach super quorum. Only FOR votes are counted + * towards the super quorum. Once the super quorum is reached, an active proposal can proceed to the next state + * without waiting for the proposal deadline. + * + * NOTE: The `timepoint` parameter corresponds to the snapshot used for counting the vote. This enables scaling of the + * quorum depending on values such as the `totalSupply` of a token at this timepoint (see {ERC20Votes}). + * + * NOTE: Make sure the value specified for the super quorum is greater than {quorum}, otherwise, it may be + * possible to pass a proposal with less votes than the default quorum. + */ + function superQuorum(uint256 timepoint) public view virtual returns (uint256); + + /** + * @dev Accessor to the internal vote counts. This must be implemented by the counting module. Counting modules + * that don't implement this function are incompatible with this module + */ + function proposalVotes( + uint256 proposalId + ) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes); + + /** + * @dev Overridden version of the {Governor-state} function that checks if the proposal has reached the super + * quorum. + * + * NOTE: If the proposal reaches super quorum but {_voteSucceeded} returns false, eg, assuming the super quorum + * has been set low enough that both FOR and AGAINST votes have exceeded it and AGAINST votes exceed FOR votes, + * the proposal continues to be active until {_voteSucceeded} returns true or the proposal deadline is reached. + * This means that with a low super quorum it is also possible that a vote can succeed prematurely before enough + * AGAINST voters have a chance to vote. Hence, it is recommended to set a high enough super quorum to avoid these + * types of scenarios. + */ + function state(uint256 proposalId) public view virtual override returns (ProposalState) { + ProposalState currentState = super.state(proposalId); + if (currentState != ProposalState.Active) return currentState; + + (, uint256 forVotes, ) = proposalVotes(proposalId); + if (forVotes < superQuorum(proposalSnapshot(proposalId)) || !_voteSucceeded(proposalId)) { + return ProposalState.Active; + } else if (proposalEta(proposalId) == 0) { + return ProposalState.Succeeded; + } else { + return ProposalState.Queued; + } + } +} diff --git a/contracts/governance/extensions/GovernorTimelockAccess.sol b/contracts/governance/extensions/GovernorTimelockAccess.sol index 5b8429b83..c208c5a36 100644 --- a/contracts/governance/extensions/GovernorTimelockAccess.sol +++ b/contracts/governance/extensions/GovernorTimelockAccess.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorTimelockAccess.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorTimelockAccess.sol) pragma solidity ^0.8.20; @@ -277,7 +277,7 @@ abstract contract GovernorTimelockAccess is Governor { } /** - * @dev See {IGovernor-_cancel} + * @dev See {Governor-_cancel} */ function _cancel( address[] memory targets, diff --git a/contracts/governance/extensions/GovernorTimelockCompound.sol b/contracts/governance/extensions/GovernorTimelockCompound.sol index 309f9a4fa..e0f4f5571 100644 --- a/contracts/governance/extensions/GovernorTimelockCompound.sol +++ b/contracts/governance/extensions/GovernorTimelockCompound.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorTimelockCompound.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorTimelockCompound.sol) pragma solidity ^0.8.20; @@ -10,7 +10,7 @@ import {SafeCast} from "../../utils/math/SafeCast.sol"; /** * @dev Extension of {Governor} that binds the execution process to a Compound Timelock. This adds a delay, enforced by - * the external timelock to all successful proposal (in addition to the voting duration). The {Governor} needs to be + * the external timelock to all successful proposals (in addition to the voting duration). The {Governor} needs to be * the admin of the timelock for any operation to be performed. A public, unrestricted, * {GovernorTimelockCompound-__acceptAdmin} is available to accept ownership of the timelock. * diff --git a/contracts/governance/extensions/GovernorTimelockControl.sol b/contracts/governance/extensions/GovernorTimelockControl.sol index ba0953d16..02262cef7 100644 --- a/contracts/governance/extensions/GovernorTimelockControl.sol +++ b/contracts/governance/extensions/GovernorTimelockControl.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorTimelockControl.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorTimelockControl.sol) pragma solidity ^0.8.20; @@ -17,7 +17,7 @@ import {SafeCast} from "../../utils/math/SafeCast.sol"; * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be * inaccessible from a proposal, unless executed via {Governor-relay}. * - * WARNING: Setting up the TimelockController to have additional proposers or cancellers besides the governor is very + * WARNING: Setting up the TimelockController to have additional proposers or cancelers 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. diff --git a/contracts/governance/extensions/GovernorVotesQuorumFraction.sol b/contracts/governance/extensions/GovernorVotesQuorumFraction.sol index 85a1f9826..a72d9de2a 100644 --- a/contracts/governance/extensions/GovernorVotesQuorumFraction.sol +++ b/contracts/governance/extensions/GovernorVotesQuorumFraction.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (governance/extensions/GovernorVotesQuorumFraction.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorVotesQuorumFraction.sol) pragma solidity ^0.8.20; import {GovernorVotes} from "./GovernorVotes.sol"; +import {Math} from "../../utils/math/Math.sol"; import {SafeCast} from "../../utils/math/SafeCast.sol"; import {Checkpoints} from "../../utils/structs/Checkpoints.sol"; @@ -45,18 +46,7 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes { * @dev Returns the quorum numerator at a specific timepoint. See {quorumDenominator}. */ function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) { - uint256 length = _quorumNumeratorHistory._checkpoints.length; - - // Optimistic search, check the latest checkpoint - Checkpoints.Checkpoint208 storage latest = _quorumNumeratorHistory._checkpoints[length - 1]; - uint48 latestKey = latest._key; - uint208 latestValue = latest._value; - if (latestKey <= timepoint) { - return latestValue; - } - - // Otherwise, do the binary search - return _quorumNumeratorHistory.upperLookupRecent(SafeCast.toUint48(timepoint)); + return _optimisticUpperLookupRecent(_quorumNumeratorHistory, timepoint); } /** @@ -70,7 +60,7 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes { * @dev Returns the quorum for a timepoint, in terms of number of votes: `supply * numerator / denominator`. */ function quorum(uint256 timepoint) public view virtual override returns (uint256) { - return (token().getPastTotalSupply(timepoint) * quorumNumerator(timepoint)) / quorumDenominator(); + return Math.mulDiv(token().getPastTotalSupply(timepoint), quorumNumerator(timepoint), quorumDenominator()); } /** @@ -107,4 +97,17 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes { emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator); } + + /** + * @dev Returns the numerator at a specific timepoint. + */ + function _optimisticUpperLookupRecent( + Checkpoints.Trace208 storage ckpts, + uint256 timepoint + ) internal view returns (uint256) { + // If trace is empty, key and value are both equal to 0. + // In that case `key <= timepoint` is true, and it is ok to return 0. + (, uint48 key, uint208 value) = ckpts.latestCheckpoint(); + return key <= timepoint ? value : ckpts.upperLookupRecent(SafeCast.toUint48(timepoint)); + } } diff --git a/contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol b/contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol new file mode 100644 index 000000000..6686210e5 --- /dev/null +++ b/contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorVotesSuperQuorumFraction.sol) +pragma solidity ^0.8.20; + +import {Governor} from "../Governor.sol"; +import {GovernorSuperQuorum} from "./GovernorSuperQuorum.sol"; +import {GovernorVotesQuorumFraction} from "./GovernorVotesQuorumFraction.sol"; +import {Math} from "../../utils/math/Math.sol"; +import {SafeCast} from "../../utils/math/SafeCast.sol"; +import {Checkpoints} from "../../utils/structs/Checkpoints.sol"; + +/** + * @dev Extension of {GovernorVotesQuorumFraction} with a super quorum expressed as a + * fraction of the total supply. Proposals that meet the super quorum (and have a majority of for votes) advance to + * the `Succeeded` state before the proposal deadline. + */ +abstract contract GovernorVotesSuperQuorumFraction is GovernorVotesQuorumFraction, GovernorSuperQuorum { + using Checkpoints for Checkpoints.Trace208; + + Checkpoints.Trace208 private _superQuorumNumeratorHistory; + + event SuperQuorumNumeratorUpdated(uint256 oldSuperQuorumNumerator, uint256 newSuperQuorumNumerator); + + /** + * @dev The super quorum set is not valid as it exceeds the quorum denominator. + */ + error GovernorInvalidSuperQuorumFraction(uint256 superQuorumNumerator, uint256 denominator); + + /** + * @dev The super quorum set is not valid as it is smaller or equal to the quorum. + */ + error GovernorInvalidSuperQuorumTooSmall(uint256 superQuorumNumerator, uint256 quorumNumerator); + + /** + * @dev The quorum set is not valid as it exceeds the super quorum. + */ + error GovernorInvalidQuorumTooLarge(uint256 quorumNumerator, uint256 superQuorumNumerator); + + /** + * @dev Initialize super quorum as a fraction of the token's total supply. + * + * The super quorum is specified as a fraction of the token's total supply and has to + * be greater than the quorum. + */ + constructor(uint256 superQuorumNumeratorValue) { + _updateSuperQuorumNumerator(superQuorumNumeratorValue); + } + + /** + * @dev Returns the current super quorum numerator. + */ + function superQuorumNumerator() public view virtual returns (uint256) { + return _superQuorumNumeratorHistory.latest(); + } + + /** + * @dev Returns the super quorum numerator at a specific `timepoint`. + */ + function superQuorumNumerator(uint256 timepoint) public view virtual returns (uint256) { + return _optimisticUpperLookupRecent(_superQuorumNumeratorHistory, timepoint); + } + + /** + * @dev Returns the super quorum for a `timepoint`, in terms of number of votes: `supply * numerator / denominator`. + * See {GovernorSuperQuorum-superQuorum} for more details. + */ + function superQuorum(uint256 timepoint) public view virtual override returns (uint256) { + return Math.mulDiv(token().getPastTotalSupply(timepoint), superQuorumNumerator(timepoint), quorumDenominator()); + } + + /** + * @dev Changes the super quorum numerator. + * + * Emits a {SuperQuorumNumeratorUpdated} event. + * + * Requirements: + * + * - Must be called through a governance proposal. + * - New super quorum numerator must be smaller or equal to the denominator. + * - New super quorum numerator must be greater than or equal to the quorum numerator. + */ + function updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) public virtual onlyGovernance { + _updateSuperQuorumNumerator(newSuperQuorumNumerator); + } + + /** + * @dev Changes the super quorum numerator. + * + * Emits a {SuperQuorumNumeratorUpdated} event. + * + * Requirements: + * + * - New super quorum numerator must be smaller or equal to the denominator. + * - New super quorum numerator must be greater than or equal to the quorum numerator. + */ + function _updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) internal virtual { + uint256 denominator = quorumDenominator(); + if (newSuperQuorumNumerator > denominator) { + revert GovernorInvalidSuperQuorumFraction(newSuperQuorumNumerator, denominator); + } + + uint256 quorumNumerator = quorumNumerator(); + if (newSuperQuorumNumerator < quorumNumerator) { + revert GovernorInvalidSuperQuorumTooSmall(newSuperQuorumNumerator, quorumNumerator); + } + + uint256 oldSuperQuorumNumerator = _superQuorumNumeratorHistory.latest(); + _superQuorumNumeratorHistory.push(clock(), SafeCast.toUint208(newSuperQuorumNumerator)); + + emit SuperQuorumNumeratorUpdated(oldSuperQuorumNumerator, newSuperQuorumNumerator); + } + + /** + * @dev Overrides {GovernorVotesQuorumFraction-_updateQuorumNumerator} to ensure the super + * quorum numerator is greater than or equal to the quorum numerator. + */ + function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual override { + // Ignoring check when the superQuorum was never set (construction sets quorum before superQuorum) + if (_superQuorumNumeratorHistory.length() > 0) { + uint256 superQuorumNumerator_ = superQuorumNumerator(); + if (newQuorumNumerator > superQuorumNumerator_) { + revert GovernorInvalidQuorumTooLarge(newQuorumNumerator, superQuorumNumerator_); + } + } + super._updateQuorumNumerator(newQuorumNumerator); + } + + /// @inheritdoc GovernorSuperQuorum + function state( + uint256 proposalId + ) public view virtual override(Governor, GovernorSuperQuorum) returns (ProposalState) { + return super.state(proposalId); + } +} diff --git a/contracts/interfaces/IERC1271.sol b/contracts/interfaces/IERC1271.sol index 8c239942a..71e0b72b6 100644 --- a/contracts/interfaces/IERC1271.sol +++ b/contracts/interfaces/IERC1271.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1271.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC1271.sol) pragma solidity ^0.8.20; @@ -11,7 +11,7 @@ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed - * @param signature Signature byte array associated with _data + * @param signature Signature byte array associated with `hash` */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); } diff --git a/contracts/interfaces/IERC4626.sol b/contracts/interfaces/IERC4626.sol index 8ebadd72f..ce55f72e1 100644 --- a/contracts/interfaces/IERC4626.sol +++ b/contracts/interfaces/IERC4626.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4626.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol) pragma solidity ^0.8.20; @@ -198,7 +198,7 @@ interface IERC4626 is IERC20, IERC20Metadata { function maxRedeem(address owner) external view returns (uint256 maxShares); /** - * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, + * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block, * given current on-chain conditions. * * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call diff --git a/contracts/interfaces/README.adoc b/contracts/interfaces/README.adoc index 61aae05d1..703cd15b5 100644 --- a/contracts/interfaces/README.adoc +++ b/contracts/interfaces/README.adoc @@ -40,6 +40,10 @@ are useful to interact with third party contracts that implement them. - {IERC5313} - {IERC5805} - {IERC6372} +- {IERC6909} +- {IERC6909ContentURI} +- {IERC6909Metadata} +- {IERC6909TokenSupply} - {IERC7674} == Detailed ABI @@ -74,12 +78,22 @@ are useful to interact with third party contracts that implement them. {{IERC4626}} -{{IERC5313}} +{{IERC4906}} {{IERC5267}} +{{IERC5313}} + {{IERC5805}} {{IERC6372}} +{{IERC6909}} + +{{IERC6909ContentURI}} + +{{IERC6909Metadata}} + +{{IERC6909TokenSupply}} + {{IERC7674}} diff --git a/contracts/interfaces/draft-IERC4337.sol b/contracts/interfaces/draft-IERC4337.sol index 2aa526db6..62fbe4b64 100644 --- a/contracts/interfaces/draft-IERC4337.sol +++ b/contracts/interfaces/draft-IERC4337.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (interfaces/draft-IERC4337.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/draft-IERC4337.sol) pragma solidity ^0.8.20; @@ -21,7 +21,7 @@ pragma solidity ^0.8.20; * - `paymasterData` (`bytes`): Data for paymaster (only if paymaster exists) * - `signature` (`bytes`): Data passed into the account to verify authorization * - * When passed to on-chain contacts, the following packed version is used. + * When passed to on-chain contracts, the following packed version is used. * - `sender` (`address`) * - `nonce` (`uint256`) * - `initCode` (`bytes`): concatenation of factory address and factoryData (or empty) @@ -164,13 +164,13 @@ interface IEntryPoint is IEntryPointNonces, IEntryPointStake { /** * @dev Executes a batch of user operations. - * @param beneficiary Address to which gas is refunded up completing the execution. + * @param beneficiary Address to which gas is refunded upon completing the execution. */ function handleOps(PackedUserOperation[] calldata ops, address payable beneficiary) external; /** * @dev Executes a batch of aggregated user operations per aggregator. - * @param beneficiary Address to which gas is refunded up completing the execution. + * @param beneficiary Address to which gas is refunded upon completing the execution. */ function handleAggregatedOps( UserOpsPerAggregator[] calldata opsPerAggregator, diff --git a/contracts/interfaces/draft-IERC6909.sol b/contracts/interfaces/draft-IERC6909.sol new file mode 100644 index 000000000..c6d550d65 --- /dev/null +++ b/contracts/interfaces/draft-IERC6909.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/draft-IERC6909.sol) + +pragma solidity ^0.8.20; + +import {IERC165} from "../utils/introspection/IERC165.sol"; + +/** + * @dev Required interface of an ERC-6909 compliant contract, as defined in the + * https://eips.ethereum.org/EIPS/eip-6909[ERC]. + */ +interface IERC6909 is IERC165 { + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set for a token of type `id`. + * The new allowance is `amount`. + */ + event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount); + + /** + * @dev Emitted when `owner` grants or revokes operator status for a `spender`. + */ + event OperatorSet(address indexed owner, address indexed spender, bool approved); + + /** + * @dev Emitted when `amount` tokens of type `id` are moved from `sender` to `receiver` initiated by `caller`. + */ + event Transfer( + address caller, + address indexed sender, + address indexed receiver, + uint256 indexed id, + uint256 amount + ); + + /** + * @dev Returns the amount of tokens of type `id` owned by `owner`. + */ + function balanceOf(address owner, uint256 id) external view returns (uint256); + + /** + * @dev Returns the amount of tokens of type `id` that `spender` is allowed to spend on behalf of `owner`. + * + * NOTE: Does not include operator allowances. + */ + function allowance(address owner, address spender, uint256 id) external view returns (uint256); + + /** + * @dev Returns true if `spender` is set as an operator for `owner`. + */ + function isOperator(address owner, address spender) external view returns (bool); + + /** + * @dev Sets an approval to `spender` for `amount` of tokens of type `id` from the caller's tokens. An `amount` of + * `type(uint256).max` signifies an unlimited approval. + * + * Must return true. + */ + function approve(address spender, uint256 id, uint256 amount) external returns (bool); + + /** + * @dev Grants or revokes unlimited transfer permission of any token id to `spender` for the caller's tokens. + * + * Must return true. + */ + function setOperator(address spender, bool approved) external returns (bool); + + /** + * @dev Transfers `amount` of token type `id` from the caller's account to `receiver`. + * + * Must return true. + */ + function transfer(address receiver, uint256 id, uint256 amount) external returns (bool); + + /** + * @dev Transfers `amount` of token type `id` from `sender` to `receiver`. + * + * Must return true. + */ + function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool); +} + +/** + * @dev Optional extension of {IERC6909} that adds metadata functions. + */ +interface IERC6909Metadata is IERC6909 { + /** + * @dev Returns the name of the token of type `id`. + */ + function name(uint256 id) external view returns (string memory); + + /** + * @dev Returns the ticker symbol of the token of type `id`. + */ + function symbol(uint256 id) external view returns (string memory); + + /** + * @dev Returns the number of decimals for the token of type `id`. + */ + function decimals(uint256 id) external view returns (uint8); +} + +/** + * @dev Optional extension of {IERC6909} that adds content URI functions. + */ +interface IERC6909ContentURI is IERC6909 { + /** + * @dev Returns URI for the contract. + */ + function contractURI() external view returns (string memory); + + /** + * @dev Returns the URI for the token of type `id`. + */ + function tokenURI(uint256 id) external view returns (string memory); +} + +/** + * @dev Optional extension of {IERC6909} that adds a token supply function. + */ +interface IERC6909TokenSupply is IERC6909 { + /** + * @dev Returns the total supply of the token of type `id`. + */ + function totalSupply(uint256 id) external view returns (uint256); +} diff --git a/contracts/interfaces/draft-IERC7579.sol b/contracts/interfaces/draft-IERC7579.sol index 077d9783f..dbe991542 100644 --- a/contracts/interfaces/draft-IERC7579.sol +++ b/contracts/interfaces/draft-IERC7579.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (interfaces/draft-IERC7579.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/draft-IERC7579.sol) pragma solidity ^0.8.20; import {PackedUserOperation} from "./draft-IERC4337.sol"; @@ -15,7 +15,7 @@ uint256 constant MODULE_TYPE_HOOK = 4; interface IERC7579Module { /** * @dev This function is called by the smart account during installation of the module - * @param data arbitrary data that may be required on the module during `onInstall` initialization + * @param data arbitrary data that may be passed to the module during `onInstall` initialization * * MUST revert on error (e.g. if module is already enabled) */ @@ -23,7 +23,7 @@ interface IERC7579Module { /** * @dev This function is called by the smart account during uninstallation of the module - * @param data arbitrary data that may be required on the module during `onUninstall` de-initialization + * @param data arbitrary data that may be passed to the module during `onUninstall` de-initialization * * MUST revert on error */ @@ -186,7 +186,7 @@ interface IERC7579ModuleConfig { * @dev Installs a Module of a certain type on the smart account * @param moduleTypeId the module type ID according to the ERC-7579 spec * @param module the module address - * @param initData arbitrary data that may be required on the module during `onInstall` + * @param initData arbitrary data that may be passed to the module during `onInstall` * initialization. * * MUST implement authorization control @@ -200,8 +200,8 @@ interface IERC7579ModuleConfig { * @dev Uninstalls a Module of a certain type on the smart account * @param moduleTypeId the module type ID according the ERC-7579 spec * @param module the module address - * @param deInitData arbitrary data that may be required on the module during `onInstall` - * initialization. + * @param deInitData arbitrary data that may be passed to the module during `onUninstall` + * deinitialization. * * MUST implement authorization control * MUST call `onUninstall` on the module with the `deInitData` parameter if provided @@ -214,7 +214,7 @@ interface IERC7579ModuleConfig { * @dev Returns whether a module is installed on the smart account * @param moduleTypeId the module type ID according the ERC-7579 spec * @param module the module address - * @param additionalContext arbitrary data that may be required to determine if the module is installed + * @param additionalContext arbitrary data that may be passed to determine if the module is installed * * MUST return true if the module is installed and false otherwise */ diff --git a/contracts/metatx/ERC2771Forwarder.sol b/contracts/metatx/ERC2771Forwarder.sol index 4a069874e..a463e70e0 100644 --- a/contracts/metatx/ERC2771Forwarder.sol +++ b/contracts/metatx/ERC2771Forwarder.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (metatx/ERC2771Forwarder.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (metatx/ERC2771Forwarder.sol) pragma solidity ^0.8.20; @@ -302,8 +302,11 @@ contract ERC2771Forwarder is EIP712, Nonces { * * This function performs a static call to the target contract calling the * {ERC2771Context-isTrustedForwarder} function. + * + * NOTE: Consider the execution of this forwarder is permissionless. Without this check, anyone may transfer assets + * that are owned by, or are approved to this forwarder. */ - function _isTrustedByTarget(address target) private view returns (bool) { + function _isTrustedByTarget(address target) internal view virtual returns (bool) { bytes memory encodedParams = abi.encodeCall(ERC2771Context.isTrustedForwarder, (address(this))); bool success; diff --git a/contracts/mocks/AuthorityMock.sol b/contracts/mocks/AuthorityMock.sol index 4f3e1de3a..cd2356ec1 100644 --- a/contracts/mocks/AuthorityMock.sol +++ b/contracts/mocks/AuthorityMock.sol @@ -12,7 +12,7 @@ contract NotAuthorityMock is IAuthority { } contract AuthorityNoDelayMock is IAuthority { - bool _immediate; + bool private _immediate; function canCall( address /* caller */, @@ -28,14 +28,14 @@ contract AuthorityNoDelayMock is IAuthority { } contract AuthorityDelayMock { - bool _immediate; - uint32 _delay; + bool private _immediate; + uint256 private _delay; function canCall( address /* caller */, address /* target */, bytes4 /* selector */ - ) external view returns (bool immediate, uint32 delay) { + ) external view returns (bool immediate, uint256 delay) { return (_immediate, _delay); } @@ -43,7 +43,7 @@ contract AuthorityDelayMock { _immediate = immediate; } - function _setDelay(uint32 delay) external { + function _setDelay(uint256 delay) external { _delay = delay; } } diff --git a/contracts/mocks/MerkleTreeMock.sol b/contracts/mocks/MerkleTreeMock.sol index dcde6b658..48ee1a6e4 100644 --- a/contracts/mocks/MerkleTreeMock.sol +++ b/contracts/mocks/MerkleTreeMock.sol @@ -14,6 +14,7 @@ contract MerkleTreeMock { bytes32 public root; event LeafInserted(bytes32 leaf, uint256 index, bytes32 root); + event LeafUpdated(bytes32 oldLeaf, bytes32 newLeaf, uint256 index, bytes32 root); function setup(uint8 _depth, bytes32 _zero) public { root = _tree.setup(_depth, _zero); @@ -25,6 +26,13 @@ contract MerkleTreeMock { root = currentRoot; } + function update(uint256 index, bytes32 oldValue, bytes32 newValue, bytes32[] memory proof) public { + (bytes32 oldRoot, bytes32 newRoot) = _tree.update(index, oldValue, newValue, proof); + if (oldRoot != root) revert MerkleTree.MerkleTreeUpdateInvalidProof(); + emit LeafUpdated(oldValue, newValue, index, newRoot); + root = newRoot; + } + function depth() public view returns (uint256) { return _tree.depth(); } diff --git a/contracts/mocks/docs/access-control/AccessControlModified.sol b/contracts/mocks/docs/access-control/AccessControlModified.sol index 9994afc92..479fa2079 100644 --- a/contracts/mocks/docs/access-control/AccessControlModified.sol +++ b/contracts/mocks/docs/access-control/AccessControlModified.sol @@ -5,10 +5,10 @@ pragma solidity ^0.8.20; import {AccessControl} from "../../../access/AccessControl.sol"; contract AccessControlModified is AccessControl { - error AccessControlNonRevokable(); + error AccessControlNonRevocable(); // Override the revokeRole function function revokeRole(bytes32, address) public pure override { - revert AccessControlNonRevokable(); + revert AccessControlNonRevocable(); } } diff --git a/contracts/mocks/docs/token/ERC6909/ERC6909GameItems.sol b/contracts/mocks/docs/token/ERC6909/ERC6909GameItems.sol new file mode 100644 index 000000000..611e1dd66 --- /dev/null +++ b/contracts/mocks/docs/token/ERC6909/ERC6909GameItems.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {ERC6909Metadata} from "../../../../token/ERC6909/extensions/draft-ERC6909Metadata.sol"; + +contract ERC6909GameItems is ERC6909Metadata { + uint256 public constant GOLD = 0; + uint256 public constant SILVER = 1; + uint256 public constant THORS_HAMMER = 2; + uint256 public constant SWORD = 3; + uint256 public constant SHIELD = 4; + + constructor() { + _setDecimals(GOLD, 18); + _setDecimals(SILVER, 18); + // Default decimals is 0 + _setDecimals(SWORD, 9); + _setDecimals(SHIELD, 9); + + _mint(msg.sender, GOLD, 10 ** 18); + _mint(msg.sender, SILVER, 10_000 ** 18); + _mint(msg.sender, THORS_HAMMER, 1); + _mint(msg.sender, SWORD, 10 ** 9); + _mint(msg.sender, SHIELD, 10 ** 9); + } +} diff --git a/contracts/mocks/governance/GovernorProposalGuardianMock.sol b/contracts/mocks/governance/GovernorProposalGuardianMock.sol new file mode 100644 index 000000000..5ed45d6c9 --- /dev/null +++ b/contracts/mocks/governance/GovernorProposalGuardianMock.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {Governor} from "../../governance/Governor.sol"; +import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol"; +import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol"; +import {GovernorVotesQuorumFraction} from "../../governance/extensions/GovernorVotesQuorumFraction.sol"; +import {GovernorProposalGuardian} from "../../governance/extensions/GovernorProposalGuardian.sol"; + +abstract contract GovernorProposalGuardianMock is + GovernorSettings, + GovernorVotesQuorumFraction, + GovernorCountingSimple, + GovernorProposalGuardian +{ + function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) { + return super.proposalThreshold(); + } + + function _validateCancel( + uint256 proposalId, + address caller + ) internal view override(Governor, GovernorProposalGuardian) returns (bool) { + return super._validateCancel(proposalId, caller); + } +} diff --git a/contracts/mocks/governance/GovernorSequentialProposalIdMock.sol b/contracts/mocks/governance/GovernorSequentialProposalIdMock.sol new file mode 100644 index 000000000..882ee0b24 --- /dev/null +++ b/contracts/mocks/governance/GovernorSequentialProposalIdMock.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {Governor} from "../../governance/Governor.sol"; +import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol"; +import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol"; +import {GovernorVotesQuorumFraction} from "../../governance/extensions/GovernorVotesQuorumFraction.sol"; +import {GovernorSequentialProposalId} from "../../governance/extensions/GovernorSequentialProposalId.sol"; + +abstract contract GovernorSequentialProposalIdMock is + GovernorSettings, + GovernorVotesQuorumFraction, + GovernorCountingSimple, + GovernorSequentialProposalId +{ + function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) { + return super.proposalThreshold(); + } + + function getProposalId( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) public view virtual override(Governor, GovernorSequentialProposalId) returns (uint256) { + return super.getProposalId(targets, values, calldatas, descriptionHash); + } + + function _propose( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + string memory description, + address proposer + ) internal virtual override(Governor, GovernorSequentialProposalId) returns (uint256 proposalId) { + return super._propose(targets, values, calldatas, description, proposer); + } +} diff --git a/contracts/mocks/governance/GovernorSuperQuorumMock.sol b/contracts/mocks/governance/GovernorSuperQuorumMock.sol new file mode 100644 index 000000000..2a48dbb7c --- /dev/null +++ b/contracts/mocks/governance/GovernorSuperQuorumMock.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {Governor} from "../../governance/Governor.sol"; +import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol"; +import {GovernorVotes} from "../../governance/extensions/GovernorVotes.sol"; +import {GovernorSuperQuorum} from "../../governance/extensions/GovernorSuperQuorum.sol"; +import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol"; +import {GovernorTimelockControl} from "../../governance/extensions/GovernorTimelockControl.sol"; + +abstract contract GovernorSuperQuorumMock is + GovernorSettings, + GovernorVotes, + GovernorTimelockControl, + GovernorSuperQuorum, + GovernorCountingSimple +{ + uint256 private _quorum; + uint256 private _superQuorum; + + constructor(uint256 quorum_, uint256 superQuorum_) { + _quorum = quorum_; + _superQuorum = superQuorum_; + } + + function quorum(uint256) public view override returns (uint256) { + return _quorum; + } + + function superQuorum(uint256) public view override returns (uint256) { + return _superQuorum; + } + + function state( + uint256 proposalId + ) public view override(Governor, GovernorSuperQuorum, GovernorTimelockControl) returns (ProposalState) { + return super.state(proposalId); + } + + function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) { + return super.proposalThreshold(); + } + + function proposalVotes( + uint256 proposalId + ) + public + view + virtual + override(GovernorCountingSimple, GovernorSuperQuorum) + returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) + { + return super.proposalVotes(proposalId); + } + + function _cancel( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) internal override(Governor, GovernorTimelockControl) returns (uint256) { + return super._cancel(targets, values, calldatas, descriptionHash); + } + + function _executeOperations( + uint256 proposalId, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) internal override(Governor, GovernorTimelockControl) { + super._executeOperations(proposalId, targets, values, calldatas, descriptionHash); + } + + function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) { + return super._executor(); + } + + function _queueOperations( + uint256 proposalId, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + bytes32 descriptionHash + ) internal override(Governor, GovernorTimelockControl) returns (uint48) { + return super._queueOperations(proposalId, targets, values, calldatas, descriptionHash); + } + + function proposalNeedsQueuing( + uint256 proposalId + ) public view override(Governor, GovernorTimelockControl) returns (bool) { + return super.proposalNeedsQueuing(proposalId); + } +} diff --git a/contracts/mocks/governance/GovernorVotesSuperQuorumFractionMock.sol b/contracts/mocks/governance/GovernorVotesSuperQuorumFractionMock.sol new file mode 100644 index 000000000..4967b033b --- /dev/null +++ b/contracts/mocks/governance/GovernorVotesSuperQuorumFractionMock.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {Governor} from "../../governance/Governor.sol"; +import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol"; +import {GovernorSuperQuorum} from "../../governance/extensions/GovernorSuperQuorum.sol"; +import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol"; +import {GovernorVotesSuperQuorumFraction} from "../../governance/extensions/GovernorVotesSuperQuorumFraction.sol"; + +abstract contract GovernorVotesSuperQuorumFractionMock is + GovernorSettings, + GovernorVotesSuperQuorumFraction, + GovernorCountingSimple +{ + function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) { + return super.proposalThreshold(); + } + + function proposalVotes( + uint256 proposalId + ) + public + view + virtual + override(GovernorCountingSimple, GovernorSuperQuorum) + returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes) + { + return super.proposalVotes(proposalId); + } + + function state( + uint256 proposalId + ) public view override(Governor, GovernorVotesSuperQuorumFraction) returns (ProposalState) { + return super.state(proposalId); + } +} diff --git a/contracts/mocks/token/ERC20ForceApproveMock.sol b/contracts/mocks/token/ERC20ForceApproveMock.sol index 36c0f574d..aecfb9e0f 100644 --- a/contracts/mocks/token/ERC20ForceApproveMock.sol +++ b/contracts/mocks/token/ERC20ForceApproveMock.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import {ERC20} from "../../token/ERC20/ERC20.sol"; -// contract that replicate USDT (0xdac17f958d2ee523a2206206994597c13d831ec7) approval behavior +// contract that replicates USDT (0xdac17f958d2ee523a2206206994597c13d831ec7) approval behavior abstract contract ERC20ForceApproveMock is ERC20 { function approve(address spender, uint256 amount) public virtual override returns (bool) { require(amount == 0 || allowance(msg.sender, spender) == 0, "USDT approval failure"); diff --git a/contracts/package.json b/contracts/package.json index 3682eadeb..70ae73bc2 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,7 +1,7 @@ { "name": "@openzeppelin/contracts", "description": "Secure Smart Contract library for Solidity", - "version": "5.2.0", + "version": "5.3.0", "files": [ "**/*.sol", "/build/contracts/*.json", diff --git a/contracts/proxy/Clones.sol b/contracts/proxy/Clones.sol index 6b8d9cc6f..9bddf5116 100644 --- a/contracts/proxy/Clones.sol +++ b/contracts/proxy/Clones.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (proxy/Clones.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (proxy/Clones.sol) pragma solidity ^0.8.20; @@ -21,7 +21,7 @@ library Clones { error CloneArgumentsTooLong(); /** - * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. + * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`. * * This function uses the create opcode, which should never revert. */ @@ -54,7 +54,7 @@ library Clones { } /** - * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. + * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`. * * This function uses the create2 opcode and a `salt` to deterministically deploy * the clone. Using the same `implementation` and `salt` multiple times will revert, since @@ -158,7 +158,7 @@ library Clones { } /** - * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation` with custom + * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom * immutable arguments. These are provided through `args` and cannot be changed after deployment. To * access the arguments within the implementation, use {fetchCloneArgs}. * diff --git a/contracts/proxy/utils/Initializable.sol b/contracts/proxy/utils/Initializable.sol index b3d82b586..0d05fdb0e 100644 --- a/contracts/proxy/utils/Initializable.sol +++ b/contracts/proxy/utils/Initializable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; @@ -112,7 +112,7 @@ abstract contract Initializable { // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized - // - construction: the contract is initialized at version 1 (no reininitialization) and the + // - construction: the contract is initialized at version 1 (no reinitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; @@ -216,13 +216,23 @@ abstract contract Initializable { return _getInitializableStorage()._initializing; } + /** + * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location. + * + * NOTE: Consider following the ERC-7201 formula to derive storage locations. + */ + function _initializableStorageSlot() internal pure virtual returns (bytes32) { + return INITIALIZABLE_STORAGE; + } + /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { + bytes32 slot = _initializableStorageSlot(); assembly { - $.slot := INITIALIZABLE_STORAGE + $.slot := slot } } } diff --git a/contracts/proxy/utils/UUPSUpgradeable.sol b/contracts/proxy/utils/UUPSUpgradeable.sol index 4719c023b..d0f58427f 100644 --- a/contracts/proxy/utils/UUPSUpgradeable.sol +++ b/contracts/proxy/utils/UUPSUpgradeable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.22; @@ -91,7 +91,6 @@ abstract contract UUPSUpgradeable is IERC1822Proxiable { /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC-1967 compliant implementation pointing to self. - * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( diff --git a/contracts/token/ERC1155/IERC1155.sol b/contracts/token/ERC1155/IERC1155.sol index 0da320fbe..ea1c0daba 100644 --- a/contracts/token/ERC1155/IERC1155.sol +++ b/contracts/token/ERC1155/IERC1155.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.20; @@ -81,7 +81,7 @@ interface IERC1155 is IERC165 { * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens - * to an untrusted contract, when invoking {onERC1155Received} on the receiver. + * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * @@ -101,7 +101,7 @@ interface IERC1155 is IERC165 { * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens - * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver. + * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * diff --git a/contracts/token/ERC1155/utils/ERC1155Utils.sol b/contracts/token/ERC1155/utils/ERC1155Utils.sol index 371cd86ba..346579393 100644 --- a/contracts/token/ERC1155/utils/ERC1155Utils.sol +++ b/contracts/token/ERC1155/utils/ERC1155Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Utils.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/utils/ERC1155Utils.sol) pragma solidity ^0.8.20; @@ -15,7 +15,7 @@ import {IERC1155Errors} from "../../../interfaces/draft-IERC6093.sol"; */ library ERC1155Utils { /** - * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155-onERC1155Received} + * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received} * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). * * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). @@ -50,7 +50,7 @@ library ERC1155Utils { } /** - * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155-onERC1155BatchReceived} + * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived} * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). * * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). diff --git a/contracts/token/ERC20/ERC20.sol b/contracts/token/ERC20/ERC20.sol index 471908d6c..13137bcf6 100644 --- a/contracts/token/ERC20/ERC20.sol +++ b/contracts/token/ERC20/ERC20.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/ERC20.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; @@ -39,8 +39,7 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { /** * @dev Sets the values for {name} and {symbol}. * - * All two of these values are immutable: they can only be set once during - * construction. + * Both values are immutable: they can only be set once during construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; @@ -241,7 +240,7 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { } /** - * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. + * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. @@ -291,7 +290,7 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { } /** - * @dev Updates `owner` s allowance for `spender` based on spent `value`. + * @dev Updates `owner`'s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. diff --git a/contracts/token/ERC20/README.adoc b/contracts/token/ERC20/README.adoc index bfbe6790b..1b4d31d2e 100644 --- a/contracts/token/ERC20/README.adoc +++ b/contracts/token/ERC20/README.adoc @@ -7,11 +7,11 @@ This set of interfaces, contracts, and utilities are all related to the https:// TIP: For an overview of ERC-20 tokens and a walk through on how to create a token contract read our xref:ROOT:erc20.adoc[ERC-20 guide]. -There are a few core contracts that implement the behavior specified in the ERC: +There are a few core contracts that implement the behavior specified in the ERC-20 standard: * {IERC20}: the interface all ERC-20 implementations should conform to. -* {IERC20Metadata}: the extended ERC-20 interface including the <>, <> and <> functions. -* {ERC20}: the implementation of the ERC-20 interface, including the <>, <> and <> optional standard extension to the base interface. +* {IERC20Metadata}: the extended ERC-20 interface including the <>, <> and <> functions. +* {ERC20}: the implementation of the ERC-20 interface, including the <>, <> and <> optional extensions to the standard interface. Additionally there are multiple custom extensions, including: @@ -30,9 +30,9 @@ Finally, there are some utilities to interact with ERC-20 contracts in various w * {SafeERC20}: a wrapper around the interface that eliminates the need to handle boolean return values. -Other utilities that support ERC-20 assets can be found in codebase: +Other utilities that support ERC-20 assets can be found in the codebase: -* ERC-20 tokens can be timelocked (held tokens for a beneficiary until a specified time) or vested (released following a given schedule) using a {VestingWallet}. +* ERC-20 tokens can be timelocked (held for a beneficiary until a specified time) or vested (released following a given schedule) using a {VestingWallet}. NOTE: This core set of contracts is designed to be unopinionated, allowing developers to access the internal functions in ERC-20 (such as <>) and expose them as external functions in the way they prefer. diff --git a/contracts/token/ERC20/extensions/ERC4626.sol b/contracts/token/ERC20/extensions/ERC4626.sol index ec9a25507..2dc89e988 100644 --- a/contracts/token/ERC20/extensions/ERC4626.sol +++ b/contracts/token/ERC20/extensions/ERC4626.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC4626.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/extensions/ERC4626.sol) pragma solidity ^0.8.20; @@ -34,7 +34,7 @@ import {Math} from "../../../utils/math/Math.sol"; * offset (0) makes it non-profitable even if an attacker is able to capture value from multiple user deposits, as a result * of the value being captured by the virtual shares (out of the attacker's donation) matching the attacker's expected gains. * With a larger offset, the attack becomes orders of magnitude more expensive than it is profitable. More details about the - * underlying math can be found xref:erc4626.adoc#inflation-attack[here]. + * underlying math can be found xref:ROOT:erc4626.adoc#inflation-attack[here]. * * The drawback of this approach is that the virtual shares do capture (a very small) part of the value being accrued * to the vault. Also, if the vault experiences losses, the users try to exit the vault, the virtual shares and assets @@ -114,7 +114,7 @@ abstract contract ERC4626 is ERC20, IERC4626 { /** @dev See {IERC4626-totalAssets}. */ function totalAssets() public view virtual returns (uint256) { - return _asset.balanceOf(address(this)); + return IERC20(asset()).balanceOf(address(this)); } /** @dev See {IERC4626-convertToShares}. */ @@ -237,14 +237,14 @@ abstract contract ERC4626 is ERC20, IERC4626 { * @dev Deposit/mint common workflow. */ function _deposit(address caller, address receiver, uint256 assets, uint256 shares) internal virtual { - // If _asset is ERC-777, `transferFrom` can trigger a reentrancy BEFORE the transfer happens through the + // If asset() is ERC-777, `transferFrom` can trigger a reentrancy BEFORE the transfer happens through the // `tokensToSend` hook. On the other hand, the `tokenReceived` hook, that is triggered after the transfer, // calls the vault, which is assumed not malicious. // // Conclusion: we need to do the transfer before we mint so that any reentrancy would happen before the // assets are transferred and before the shares are minted, which is a valid state. // slither-disable-next-line reentrancy-no-eth - SafeERC20.safeTransferFrom(_asset, caller, address(this), assets); + SafeERC20.safeTransferFrom(IERC20(asset()), caller, address(this), assets); _mint(receiver, shares); emit Deposit(caller, receiver, assets, shares); @@ -264,14 +264,14 @@ abstract contract ERC4626 is ERC20, IERC4626 { _spendAllowance(owner, caller, shares); } - // If _asset is ERC-777, `transfer` can trigger a reentrancy AFTER the transfer happens through the + // If asset() is ERC-777, `transfer` can trigger a reentrancy AFTER the transfer happens through the // `tokensReceived` hook. On the other hand, the `tokensToSend` hook, that is triggered before the transfer, // calls the vault, which is assumed not malicious. // // Conclusion: we need to do the transfer after the burn so that any reentrancy would happen after the // shares are burned and after the assets are transferred, which is a valid state. _burn(owner, shares); - SafeERC20.safeTransfer(_asset, receiver, assets); + SafeERC20.safeTransfer(IERC20(asset()), receiver, assets); emit Withdraw(caller, receiver, owner, assets, shares); } diff --git a/contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol b/contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol index d30521b49..357daa937 100644 --- a/contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol +++ b/contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/draft-ERC20TemporaryApproval.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/extensions/draft-ERC20TemporaryApproval.sol) pragma solidity ^0.8.24; @@ -61,7 +61,7 @@ abstract contract ERC20TemporaryApproval is ERC20, IERC7674 { } /** - * @dev Sets `value` as the temporary allowance of `spender` over the `owner` s tokens. + * @dev Sets `value` as the temporary allowance of `spender` over the `owner`'s tokens. * * This internal function is equivalent to `temporaryApprove`, and can be used to e.g. set automatic allowances * for certain subsystems, etc. diff --git a/contracts/token/ERC20/utils/SafeERC20.sol b/contracts/token/ERC20/utils/SafeERC20.sol index edac165bc..883e8d30c 100644 --- a/contracts/token/ERC20/utils/SafeERC20.sol +++ b/contracts/token/ERC20/utils/SafeERC20.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; @@ -42,6 +42,20 @@ library SafeERC20 { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } + /** + * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful. + */ + function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) { + return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value))); + } + + /** + * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful. + */ + function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) { + return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value))); + } + /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. diff --git a/contracts/token/ERC6909/README.adoc b/contracts/token/ERC6909/README.adoc new file mode 100644 index 000000000..17d116cc4 --- /dev/null +++ b/contracts/token/ERC6909/README.adoc @@ -0,0 +1,27 @@ += ERC-6909 + +[.readme-notice] +NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/token/erc6909 + +This set of interfaces and contracts are all related to the https://eips.ethereum.org/EIPS/eip-6909[ERC-6909 Minimal Multi-Token Interface]. + +The ERC consists of four interfaces which fulfill different roles--the interfaces are as follows: + +. {IERC6909}: Base interface for a vanilla ERC6909 token. +. {IERC6909ContentURI}: Extends the base interface and adds content URI (contract and token level) functionality. +. {IERC6909Metadata}: Extends the base interface and adds metadata functionality, which exposes a name, symbol, and decimals for each token id. +. {IERC6909TokenSupply}: Extends the base interface and adds total supply functionality for each token id. + +Implementations are provided for each of the 4 interfaces defined in the ERC. + +== Core + +{{ERC6909}} + +== Extensions + +{{ERC6909ContentURI}} + +{{ERC6909Metadata}} + +{{ERC6909TokenSupply}} diff --git a/contracts/token/ERC6909/draft-ERC6909.sol b/contracts/token/ERC6909/draft-ERC6909.sol new file mode 100644 index 000000000..6f5cdd6a8 --- /dev/null +++ b/contracts/token/ERC6909/draft-ERC6909.sol @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/draft-ERC6909.sol) + +pragma solidity ^0.8.20; + +import {IERC6909} from "../../interfaces/draft-IERC6909.sol"; +import {Context} from "../../utils/Context.sol"; +import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; + +/** + * @dev Implementation of ERC-6909. + * See https://eips.ethereum.org/EIPS/eip-6909 + */ +contract ERC6909 is Context, ERC165, IERC6909 { + mapping(address owner => mapping(uint256 id => uint256)) private _balances; + + mapping(address owner => mapping(address operator => bool)) private _operatorApprovals; + + mapping(address owner => mapping(address spender => mapping(uint256 id => uint256))) private _allowances; + + error ERC6909InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 id); + error ERC6909InsufficientAllowance(address spender, uint256 allowance, uint256 needed, uint256 id); + error ERC6909InvalidApprover(address approver); + error ERC6909InvalidReceiver(address receiver); + error ERC6909InvalidSender(address sender); + error ERC6909InvalidSpender(address spender); + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId == type(IERC6909).interfaceId || super.supportsInterface(interfaceId); + } + + /// @inheritdoc IERC6909 + function balanceOf(address owner, uint256 id) public view virtual override returns (uint256) { + return _balances[owner][id]; + } + + /// @inheritdoc IERC6909 + function allowance(address owner, address spender, uint256 id) public view virtual override returns (uint256) { + return _allowances[owner][spender][id]; + } + + /// @inheritdoc IERC6909 + function isOperator(address owner, address spender) public view virtual override returns (bool) { + return _operatorApprovals[owner][spender]; + } + + /// @inheritdoc IERC6909 + function approve(address spender, uint256 id, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, id, amount); + return true; + } + + /// @inheritdoc IERC6909 + function setOperator(address spender, bool approved) public virtual override returns (bool) { + _setOperator(_msgSender(), spender, approved); + return true; + } + + /// @inheritdoc IERC6909 + function transfer(address receiver, uint256 id, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), receiver, id, amount); + return true; + } + + /// @inheritdoc IERC6909 + function transferFrom( + address sender, + address receiver, + uint256 id, + uint256 amount + ) public virtual override returns (bool) { + address caller = _msgSender(); + if (sender != caller && !isOperator(sender, caller)) { + _spendAllowance(sender, caller, id, amount); + } + _transfer(sender, receiver, id, amount); + return true; + } + + /** + * @dev Creates `amount` of token `id` and assigns them to `account`, by transferring it from address(0). + * Relies on the `_update` mechanism. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * NOTE: This function is not virtual, {_update} should be overridden instead. + */ + function _mint(address to, uint256 id, uint256 amount) internal { + if (to == address(0)) { + revert ERC6909InvalidReceiver(address(0)); + } + _update(address(0), to, id, amount); + } + + /** + * @dev Moves `amount` of token `id` from `from` to `to` without checking for approvals. This function verifies + * that neither the sender nor the receiver are address(0), which means it cannot mint or burn tokens. + * Relies on the `_update` mechanism. + * + * Emits a {Transfer} event. + * + * NOTE: This function is not virtual, {_update} should be overridden instead. + */ + function _transfer(address from, address to, uint256 id, uint256 amount) internal { + if (from == address(0)) { + revert ERC6909InvalidSender(address(0)); + } + if (to == address(0)) { + revert ERC6909InvalidReceiver(address(0)); + } + _update(from, to, id, amount); + } + + /** + * @dev Destroys a `amount` of token `id` from `account`. + * Relies on the `_update` mechanism. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * NOTE: This function is not virtual, {_update} should be overridden instead + */ + function _burn(address from, uint256 id, uint256 amount) internal { + if (from == address(0)) { + revert ERC6909InvalidSender(address(0)); + } + _update(from, address(0), id, amount); + } + + /** + * @dev Transfers `amount` of token `id` from `from` to `to`, or alternatively mints (or burns) if `from` + * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding + * this function. + * + * Emits a {Transfer} event. + */ + function _update(address from, address to, uint256 id, uint256 amount) internal virtual { + address caller = _msgSender(); + + if (from != address(0)) { + uint256 fromBalance = _balances[from][id]; + if (fromBalance < amount) { + revert ERC6909InsufficientBalance(from, fromBalance, amount, id); + } + unchecked { + // Overflow not possible: amount <= fromBalance. + _balances[from][id] = fromBalance - amount; + } + } + if (to != address(0)) { + _balances[to][id] += amount; + } + + emit Transfer(caller, from, to, id, amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner`'s `id` tokens. + * + * This internal function is equivalent to `approve`, and can be used to e.g. set automatic allowances for certain + * subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve(address owner, address spender, uint256 id, uint256 amount) internal virtual { + if (owner == address(0)) { + revert ERC6909InvalidApprover(address(0)); + } + if (spender == address(0)) { + revert ERC6909InvalidSpender(address(0)); + } + _allowances[owner][spender][id] = amount; + emit Approval(owner, spender, id, amount); + } + + /** + * @dev Approve `spender` to operate on all of `owner`'s tokens + * + * This internal function is equivalent to `setOperator`, and can be used to e.g. set automatic allowances for + * certain subsystems, etc. + * + * Emits an {OperatorSet} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _setOperator(address owner, address spender, bool approved) internal virtual { + if (owner == address(0)) { + revert ERC6909InvalidApprover(address(0)); + } + if (spender == address(0)) { + revert ERC6909InvalidSpender(address(0)); + } + _operatorApprovals[owner][spender] = approved; + emit OperatorSet(owner, spender, approved); + } + + /** + * @dev Updates `owner`'s allowance for `spender` based on spent `amount`. + * + * Does not update the allowance value in case of infinite allowance. + * Revert if not enough allowance is available. + * + * Does not emit an {Approval} event. + */ + function _spendAllowance(address owner, address spender, uint256 id, uint256 amount) internal virtual { + uint256 currentAllowance = allowance(owner, spender, id); + if (currentAllowance < type(uint256).max) { + if (currentAllowance < amount) { + revert ERC6909InsufficientAllowance(spender, currentAllowance, amount, id); + } + unchecked { + _allowances[owner][spender][id] = currentAllowance - amount; + } + } + } +} diff --git a/contracts/token/ERC6909/extensions/draft-ERC6909ContentURI.sol b/contracts/token/ERC6909/extensions/draft-ERC6909ContentURI.sol new file mode 100644 index 000000000..9d082c066 --- /dev/null +++ b/contracts/token/ERC6909/extensions/draft-ERC6909ContentURI.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/extensions/draft-ERC6909ContentURI.sol) + +pragma solidity ^0.8.20; + +import {ERC6909} from "../draft-ERC6909.sol"; +import {IERC6909ContentURI} from "../../../interfaces/draft-IERC6909.sol"; + +/** + * @dev Implementation of the Content URI extension defined in ERC6909. + */ +contract ERC6909ContentURI is ERC6909, IERC6909ContentURI { + string private _contractURI; + mapping(uint256 id => string) private _tokenURIs; + + /// @dev Event emitted when the contract URI is changed. See https://eips.ethereum.org/EIPS/eip-7572[ERC-7572] for details. + event ContractURIUpdated(); + + /// @dev See {IERC1155-URI} + event URI(string value, uint256 indexed id); + + /// @inheritdoc IERC6909ContentURI + function contractURI() public view virtual override returns (string memory) { + return _contractURI; + } + + /// @inheritdoc IERC6909ContentURI + function tokenURI(uint256 id) public view virtual override returns (string memory) { + return _tokenURIs[id]; + } + + /** + * @dev Sets the {contractURI} for the contract. + * + * Emits a {ContractURIUpdated} event. + */ + function _setContractURI(string memory newContractURI) internal virtual { + _contractURI = newContractURI; + + emit ContractURIUpdated(); + } + + /** + * @dev Sets the {tokenURI} for a given token of type `id`. + * + * Emits a {URI} event. + */ + function _setTokenURI(uint256 id, string memory newTokenURI) internal virtual { + _tokenURIs[id] = newTokenURI; + + emit URI(newTokenURI, id); + } +} diff --git a/contracts/token/ERC6909/extensions/draft-ERC6909Metadata.sol b/contracts/token/ERC6909/extensions/draft-ERC6909Metadata.sol new file mode 100644 index 000000000..31efebe88 --- /dev/null +++ b/contracts/token/ERC6909/extensions/draft-ERC6909Metadata.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/extensions/draft-ERC6909Metadata.sol) + +pragma solidity ^0.8.20; + +import {ERC6909} from "../draft-ERC6909.sol"; +import {IERC6909Metadata} from "../../../interfaces/draft-IERC6909.sol"; + +/** + * @dev Implementation of the Metadata extension defined in ERC6909. Exposes the name, symbol, and decimals of each token id. + */ +contract ERC6909Metadata is ERC6909, IERC6909Metadata { + struct TokenMetadata { + string name; + string symbol; + uint8 decimals; + } + + mapping(uint256 id => TokenMetadata) private _tokenMetadata; + + /// @dev The name of the token of type `id` was updated to `newName`. + event ERC6909NameUpdated(uint256 indexed id, string newName); + + /// @dev The symbol for the token of type `id` was updated to `newSymbol`. + event ERC6909SymbolUpdated(uint256 indexed id, string newSymbol); + + /// @dev The decimals value for token of type `id` was updated to `newDecimals`. + event ERC6909DecimalsUpdated(uint256 indexed id, uint8 newDecimals); + + /// @inheritdoc IERC6909Metadata + function name(uint256 id) public view virtual override returns (string memory) { + return _tokenMetadata[id].name; + } + + /// @inheritdoc IERC6909Metadata + function symbol(uint256 id) public view virtual override returns (string memory) { + return _tokenMetadata[id].symbol; + } + + /// @inheritdoc IERC6909Metadata + function decimals(uint256 id) public view virtual override returns (uint8) { + return _tokenMetadata[id].decimals; + } + + /** + * @dev Sets the `name` for a given token of type `id`. + * + * Emits an {ERC6909NameUpdated} event. + */ + function _setName(uint256 id, string memory newName) internal virtual { + _tokenMetadata[id].name = newName; + + emit ERC6909NameUpdated(id, newName); + } + + /** + * @dev Sets the `symbol` for a given token of type `id`. + * + * Emits an {ERC6909SymbolUpdated} event. + */ + function _setSymbol(uint256 id, string memory newSymbol) internal virtual { + _tokenMetadata[id].symbol = newSymbol; + + emit ERC6909SymbolUpdated(id, newSymbol); + } + + /** + * @dev Sets the `decimals` for a given token of type `id`. + * + * Emits an {ERC6909DecimalsUpdated} event. + */ + function _setDecimals(uint256 id, uint8 newDecimals) internal virtual { + _tokenMetadata[id].decimals = newDecimals; + + emit ERC6909DecimalsUpdated(id, newDecimals); + } +} diff --git a/contracts/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol b/contracts/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol new file mode 100644 index 000000000..0fd4c224a --- /dev/null +++ b/contracts/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/extensions/draft-ERC6909TokenSupply.sol) + +pragma solidity ^0.8.20; + +import {ERC6909} from "../draft-ERC6909.sol"; +import {IERC6909TokenSupply} from "../../../interfaces/draft-IERC6909.sol"; + +/** + * @dev Implementation of the Token Supply extension defined in ERC6909. + * Tracks the total supply of each token id individually. + */ +contract ERC6909TokenSupply is ERC6909, IERC6909TokenSupply { + mapping(uint256 id => uint256) private _totalSupplies; + + /// @inheritdoc IERC6909TokenSupply + function totalSupply(uint256 id) public view virtual override returns (uint256) { + return _totalSupplies[id]; + } + + /// @dev Override the `_update` function to update the total supply of each token id as necessary. + function _update(address from, address to, uint256 id, uint256 amount) internal virtual override { + super._update(from, to, id, amount); + + if (from == address(0)) { + _totalSupplies[id] += amount; + } + if (to == address(0)) { + unchecked { + // amount <= _balances[from][id] <= _totalSupplies[id] + _totalSupplies[id] -= amount; + } + } + } +} diff --git a/contracts/token/ERC721/README.adoc b/contracts/token/ERC721/README.adoc index 5554720d6..22a306235 100644 --- a/contracts/token/ERC721/README.adoc +++ b/contracts/token/ERC721/README.adoc @@ -3,7 +3,7 @@ [.readme-notice] NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/token/erc721 -This set of interfaces, contracts, and utilities are all related to the https://eips.ethereum.org/EIPS/eip-721[ERC-721 Non-Fungible Token Standard]. +This set of interfaces, contracts, and utilities is all related to the https://eips.ethereum.org/EIPS/eip-721[ERC-721 Non-Fungible Token Standard]. TIP: For a walk through on how to create an ERC-721 token read our xref:ROOT:erc721.adoc[ERC-721 guide]. @@ -22,7 +22,7 @@ OpenZeppelin Contracts provides implementations of all four interfaces: Additionally there are a few of other extensions: -* {ERC721Consecutive}: An implementation of https://eips.ethereum.org/EIPS/eip-2309[ERC-2309] for minting batchs of tokens during construction, in accordance with ERC-721. +* {ERC721Consecutive}: An implementation of https://eips.ethereum.org/EIPS/eip-2309[ERC-2309] for minting batches of tokens during construction, in accordance with ERC-721. * {ERC721URIStorage}: A more flexible but more expensive way of storing metadata. * {ERC721Votes}: Support for voting and vote delegation. * {ERC721Royalty}: A way to signal royalty information following ERC-2981. diff --git a/contracts/token/ERC721/extensions/ERC721Consecutive.sol b/contracts/token/ERC721/extensions/ERC721Consecutive.sol index 6b849d774..0f3267364 100644 --- a/contracts/token/ERC721/extensions/ERC721Consecutive.sol +++ b/contracts/token/ERC721/extensions/ERC721Consecutive.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Consecutive.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC721/extensions/ERC721Consecutive.sol) pragma solidity ^0.8.20; @@ -159,7 +159,7 @@ abstract contract ERC721Consecutive is IERC2309, ERC721 { } /** - * @dev Used to offset the first token id in {_nextConsecutiveId} + * @dev Used to offset the first token id in `_nextConsecutiveId` */ function _firstConsecutiveId() internal view virtual returns (uint96) { return 0; diff --git a/contracts/token/ERC721/extensions/ERC721URIStorage.sol b/contracts/token/ERC721/extensions/ERC721URIStorage.sol index d8b4d8d1f..bbb0d4c53 100644 --- a/contracts/token/ERC721/extensions/ERC721URIStorage.sol +++ b/contracts/token/ERC721/extensions/ERC721URIStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721URIStorage.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC721/extensions/ERC721URIStorage.sol) pragma solidity ^0.8.20; @@ -52,7 +52,7 @@ abstract contract ERC721URIStorage is IERC4906, ERC721 { /** * @dev Sets `_tokenURI` as the tokenURI of `tokenId`. * - * Emits {MetadataUpdate}. + * Emits {IERC4906-MetadataUpdate}. */ function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual { _tokenURIs[tokenId] = _tokenURI; diff --git a/contracts/token/ERC721/utils/ERC721Utils.sol b/contracts/token/ERC721/utils/ERC721Utils.sol index 2fd091afd..1ae7a600b 100644 --- a/contracts/token/ERC721/utils/ERC721Utils.sol +++ b/contracts/token/ERC721/utils/ERC721Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/utils/ERC721Utils.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC721/utils/ERC721Utils.sol) pragma solidity ^0.8.20; @@ -15,7 +15,7 @@ import {IERC721Errors} from "../../../interfaces/draft-IERC6093.sol"; */ library ERC721Utils { /** - * @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received} + * @dev Performs an acceptance check for the provided `operator` by calling {IERC721Receiver-onERC721Received} * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). * * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). diff --git a/contracts/token/common/ERC2981.sol b/contracts/token/common/ERC2981.sol index 8335e56ef..9c25e9b37 100644 --- a/contracts/token/common/ERC2981.sol +++ b/contracts/token/common/ERC2981.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (token/common/ERC2981.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (token/common/ERC2981.sol) pragma solidity ^0.8.20; @@ -39,7 +39,7 @@ abstract contract ERC2981 is IERC2981, ERC165 { error ERC2981InvalidDefaultRoyaltyReceiver(address receiver); /** - * @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1). + * @dev The royalty set for a specific `tokenId` is invalid (eg. (numerator / denominator) >= 1). */ error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator); diff --git a/contracts/utils/Arrays.sol b/contracts/utils/Arrays.sol index bd3401703..0c1f14e26 100644 --- a/contracts/utils/Arrays.sol +++ b/contracts/utils/Arrays.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/Arrays.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol) // This file was procedurally generated from scripts/generate/templates/Arrays.js. pragma solidity ^0.8.20; @@ -448,7 +448,7 @@ library Arrays { } /** - * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. + * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. * * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. */ @@ -459,7 +459,7 @@ library Arrays { } /** - * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. + * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. * * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. */ @@ -470,7 +470,7 @@ library Arrays { } /** - * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. + * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. * * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. */ diff --git a/contracts/utils/Calldata.sol b/contracts/utils/Calldata.sol new file mode 100644 index 000000000..41860b29f --- /dev/null +++ b/contracts/utils/Calldata.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.3.0) (utils/Calldata.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Helper library for manipulating objects in calldata. + */ +library Calldata { + // slither-disable-next-line write-after-write + function emptyBytes() internal pure returns (bytes calldata result) { + assembly ("memory-safe") { + result.offset := 0 + result.length := 0 + } + } + + // slither-disable-next-line write-after-write + function emptyString() internal pure returns (string calldata result) { + assembly ("memory-safe") { + result.offset := 0 + result.length := 0 + } + } +} diff --git a/contracts/utils/Multicall.sol b/contracts/utils/Multicall.sol index 0dd5b4adc..94222feb0 100644 --- a/contracts/utils/Multicall.sol +++ b/contracts/utils/Multicall.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.1) (utils/Multicall.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/Multicall.sol) pragma solidity ^0.8.20; @@ -13,10 +13,10 @@ import {Context} from "./Context.sol"; * careful about sending transactions invoking {multicall}. For example, a relay address that filters function * selectors won't filter calls nested within a {multicall} operation. * - * NOTE: Since 5.0.1 and 4.9.4, this contract identifies non-canonical contexts (i.e. `msg.sender` is not {_msgSender}). + * NOTE: Since 5.0.1 and 4.9.4, this contract identifies non-canonical contexts (i.e. `msg.sender` is not {Context-_msgSender}). * If a non-canonical context is identified, the following self `delegatecall` appends the last bytes of `msg.data` * to the subcall. This makes it safe to use with {ERC2771Context}. Contexts that don't affect the resolution of - * {_msgSender} are not propagated to subcalls. + * {Context-_msgSender} are not propagated to subcalls. */ abstract contract Multicall is Context { /** diff --git a/contracts/utils/Pausable.sol b/contracts/utils/Pausable.sol index 312f1cb90..68e7d2681 100644 --- a/contracts/utils/Pausable.sol +++ b/contracts/utils/Pausable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol) pragma solidity ^0.8.20; @@ -37,13 +37,6 @@ abstract contract Pausable is Context { */ error ExpectedPause(); - /** - * @dev Initializes the contract in unpaused state. - */ - constructor() { - _paused = false; - } - /** * @dev Modifier to make a function callable only when the contract is not paused. * diff --git a/contracts/utils/README.adoc b/contracts/utils/README.adoc index 432b806e3..5151b4616 100644 --- a/contracts/utils/README.adoc +++ b/contracts/utils/README.adoc @@ -18,12 +18,12 @@ Miscellaneous contracts and libraries containing utility functions you can use t * {ReentrancyGuardTransient}: Variant of {ReentrancyGuard} that uses transient storage (https://eips.ethereum.org/EIPS/eip-1153[EIP-1153]). * {Pausable}: A common emergency response mechanism that can pause functionality while a remediation is pending. * {Nonces}: Utility for tracking and verifying address nonces that only increment. - * {NoncesKeyed}: Alternative to {Nonces}, that support key-ed nonces following https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337 speciciations]. + * {NoncesKeyed}: Alternative to {Nonces}, that support keyed nonces following https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337 specifications]. * {ERC165}, {ERC165Checker}: Utilities for inspecting interfaces supported by contracts. * {BitMaps}: A simple library to manage boolean value mapped to a numerical index in an efficient way. * {EnumerableMap}: A type like Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`], but with key-value _enumeration_: this will let you know how many entries a mapping has, and iterate over them (which is not possible with `mapping`). * {EnumerableSet}: Like {EnumerableMap}, but for https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets]. Can be used to store privileged accounts, issued IDs, etc. - * {DoubleEndedQueue}: An implementation of a https://en.wikipedia.org/wiki/Double-ended_queue[double ended queue] whose values can be removed added or remove from both sides. Useful for FIFO and LIFO structures. + * {DoubleEndedQueue}: An implementation of a https://en.wikipedia.org/wiki/Double-ended_queue[double ended queue] whose values can be added or removed from both sides. Useful for FIFO and LIFO structures. * {CircularBuffer}: A data structure to store the last N values pushed to it. * {Checkpoints}: A data structure to store values mapped to a strictly increasing key. Can be used for storing and accessing values over time. * {Heap}: A library that implements a https://en.wikipedia.org/wiki/Binary_heap[binary heap] in storage. @@ -33,8 +33,9 @@ Miscellaneous contracts and libraries containing utility functions you can use t * {Arrays}: Collection of functions that operate on https://docs.soliditylang.org/en/latest/types.html#arrays[`arrays`]. * {Base64}: On-chain base64 and base64URL encoding according to https://datatracker.ietf.org/doc/html/rfc4648[RFC-4648]. * {Bytes}: Common operations on bytes objects. + * {Calldata}: Helpers for manipulating calldata. * {Strings}: Common operations for strings formatting. - * {ShortString}: Library to encode (and decode) short strings into (or from) a single bytes32 slot for optimizing costs. Short strings are limited to 31 characters. + * {ShortStrings}: Library to encode (and decode) short strings into (or from) a single bytes32 slot for optimizing costs. Short strings are limited to 31 characters. * {SlotDerivation}: Methods for deriving storage slot from ERC-7201 namespaces as well as from constructions such as mapping and arrays. * {StorageSlot}: Methods for accessing specific storage slots formatted as common primitive types. * {TransientSlot}: Primitives for reading from and writing to transient storage (only value types are currently supported). @@ -42,7 +43,7 @@ Miscellaneous contracts and libraries containing utility functions you can use t * {Context}: A utility for abstracting the sender and calldata in the current execution context. * {Packing}: A library for packing and unpacking multiple values into bytes32 * {Panic}: A library to revert with https://docs.soliditylang.org/en/v0.8.20/control-structures.html#panic-via-assert-and-error-via-require[Solidity panic codes]. - * {Comparators}: A library that contains comparator functions to use with with the {Heap} library. + * {Comparators}: A library that contains comparator functions to use with the {Heap} library. * {CAIP2}, {CAIP10}: Libraries for formatting and parsing CAIP-2 and CAIP-10 identifiers. [NOTE] @@ -128,6 +129,10 @@ Ethereum contracts have no native concept of an interface, so applications must {{Base64}} +{{Bytes}} + +{{Calldata}} + {{Strings}} {{ShortStrings}} @@ -147,3 +152,7 @@ Ethereum contracts have no native concept of an interface, so applications must {{Panic}} {{Comparators}} + +{{CAIP2}} + +{{CAIP10}} diff --git a/contracts/utils/ReentrancyGuardTransient.sol b/contracts/utils/ReentrancyGuardTransient.sol index 1a62e29da..a1318c86f 100644 --- a/contracts/utils/ReentrancyGuardTransient.sol +++ b/contracts/utils/ReentrancyGuardTransient.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuardTransient.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/ReentrancyGuardTransient.sol) pragma solidity ^0.8.24; @@ -38,7 +38,7 @@ abstract contract ReentrancyGuardTransient { } function _nonReentrantBefore() private { - // On the first call to nonReentrant, _status will be NOT_ENTERED + // On the first call to nonReentrant, REENTRANCY_GUARD_STORAGE.asBoolean().tload() will be false if (_reentrancyGuardEntered()) { revert ReentrancyGuardReentrantCall(); } diff --git a/contracts/utils/ShortStrings.sol b/contracts/utils/ShortStrings.sol index fb8bde516..81d713d4b 100644 --- a/contracts/utils/ShortStrings.sol +++ b/contracts/utils/ShortStrings.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/ShortStrings.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/ShortStrings.sol) pragma solidity ^0.8.20; @@ -95,7 +95,7 @@ library ShortStrings { } /** - * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. + * @dev Decode a string that was encoded to `ShortString` or written to storage using {toShortStringWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { @@ -107,7 +107,7 @@ library ShortStrings { /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using - * {setWithFallback}. + * {toShortStringWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. diff --git a/contracts/utils/SlotDerivation.sol b/contracts/utils/SlotDerivation.sol index 62d1545c6..df23efa28 100644 --- a/contracts/utils/SlotDerivation.sol +++ b/contracts/utils/SlotDerivation.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/SlotDerivation.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol) // This file was procedurally generated from scripts/generate/templates/SlotDerivation.js. pragma solidity ^0.8.20; @@ -19,7 +19,7 @@ pragma solidity ^0.8.20; * using SlotDerivation for bytes32; * * // Declare a namespace - * string private constant _NAMESPACE = "" // eg. OpenZeppelin.Slot + * string private constant _NAMESPACE = ""; // eg. OpenZeppelin.Slot * * function setValueInNamespace(uint256 key, address newValue) internal { * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue; diff --git a/contracts/utils/Strings.sol b/contracts/utils/Strings.sol index 0360b4cab..e5aa2c550 100644 --- a/contracts/utils/Strings.sol +++ b/contracts/utils/Strings.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.2.0) (utils/Strings.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol) pragma solidity ^0.8.20; @@ -15,6 +15,14 @@ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; + uint256 private constant SPECIAL_CHARS_LOOKUP = + (1 << 0x08) | // backspace + (1 << 0x09) | // tab + (1 << 0x0a) | // newline + (1 << 0x0c) | // form feed + (1 << 0x0d) | // carriage return + (1 << 0x22) | // double quote + (1 << 0x5c); // backslash /** * @dev The `value` string doesn't fit in the specified `length`. @@ -139,7 +147,7 @@ library Strings { } /** - * @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and + * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: @@ -177,7 +185,7 @@ library Strings { } /** - * @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that + * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseUintUncheckedBounds( @@ -250,7 +258,7 @@ library Strings { } /** - * @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that + * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseIntUncheckedBounds( @@ -287,7 +295,7 @@ library Strings { } /** - * @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and + * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: @@ -325,7 +333,7 @@ library Strings { } /** - * @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that + * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseHexUintUncheckedBounds( @@ -346,7 +354,7 @@ library Strings { result *= 16; unchecked { // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check). - // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked. + // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked. result += chr; } } @@ -364,7 +372,7 @@ library Strings { } /** - * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and + * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: @@ -378,7 +386,7 @@ library Strings { /** * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly - * formatted address. See {parseAddress} requirements. + * formatted address. See {parseAddress-string} requirements. */ function tryParseAddress(string memory input) internal pure returns (bool success, address value) { return tryParseAddress(input, 0, bytes(input).length); @@ -386,7 +394,7 @@ library Strings { /** * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly - * formatted address. See {parseAddress} requirements. + * formatted address. See {parseAddress-string-uint256-uint256} requirements. */ function tryParseAddress( string memory input, @@ -426,6 +434,47 @@ library Strings { return value; } + /** + * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata. + * + * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped. + * + * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of + * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode + * characters that are not in this range, but other tooling may provide different results. + */ + function escapeJSON(string memory input) internal pure returns (string memory) { + bytes memory buffer = bytes(input); + bytes memory output = new bytes(2 * buffer.length); // worst case scenario + uint256 outputLength = 0; + + for (uint256 i; i < buffer.length; ++i) { + bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i)); + if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) { + output[outputLength++] = "\\"; + if (char == 0x08) output[outputLength++] = "b"; + else if (char == 0x09) output[outputLength++] = "t"; + else if (char == 0x0a) output[outputLength++] = "n"; + else if (char == 0x0c) output[outputLength++] = "f"; + else if (char == 0x0d) output[outputLength++] = "r"; + else if (char == 0x5c) output[outputLength++] = "\\"; + else if (char == 0x22) { + // solhint-disable-next-line quotes + output[outputLength++] = '"'; + } + } else { + output[outputLength++] = char; + } + } + // write the actual length and deallocate unused memory + assembly ("memory-safe") { + mstore(output, outputLength) + mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63))))) + } + + return string(output); + } + /** * @dev Reads a bytes32 from a bytes array without bounds checking. * diff --git a/contracts/utils/TransientSlot.sol b/contracts/utils/TransientSlot.sol index 25c57dd3f..f0caea13d 100644 --- a/contracts/utils/TransientSlot.sol +++ b/contracts/utils/TransientSlot.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/TransientSlot.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/TransientSlot.sol) // This file was procedurally generated from scripts/generate/templates/TransientSlot.js. pragma solidity ^0.8.24; @@ -32,7 +32,7 @@ pragma solidity ^0.8.24; */ library TransientSlot { /** - * @dev UDVT that represent a slot holding a address. + * @dev UDVT that represents a slot holding an address. */ type AddressSlot is bytes32; @@ -44,7 +44,7 @@ library TransientSlot { } /** - * @dev UDVT that represent a slot holding a bool. + * @dev UDVT that represents a slot holding a bool. */ type BooleanSlot is bytes32; @@ -56,7 +56,7 @@ library TransientSlot { } /** - * @dev UDVT that represent a slot holding a bytes32. + * @dev UDVT that represents a slot holding a bytes32. */ type Bytes32Slot is bytes32; @@ -68,7 +68,7 @@ library TransientSlot { } /** - * @dev UDVT that represent a slot holding a uint256. + * @dev UDVT that represents a slot holding a uint256. */ type Uint256Slot is bytes32; @@ -80,7 +80,7 @@ library TransientSlot { } /** - * @dev UDVT that represent a slot holding a int256. + * @dev UDVT that represents a slot holding a int256. */ type Int256Slot is bytes32; diff --git a/contracts/utils/cryptography/EIP712.sol b/contracts/utils/cryptography/EIP712.sol index f15a67bd9..8ac545a8f 100644 --- a/contracts/utils/cryptography/EIP712.sol +++ b/contracts/utils/cryptography/EIP712.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/EIP712.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.20; @@ -48,7 +48,9 @@ abstract contract EIP712 is IERC5267 { ShortString private immutable _name; ShortString private immutable _version; + // slither-disable-next-line constable-states string private _nameFallback; + // slither-disable-next-line constable-states string private _versionFallback; /** @@ -109,7 +111,7 @@ abstract contract EIP712 is IERC5267 { } /** - * @dev See {IERC-5267}. + * @inheritdoc IERC5267 */ function eip712Domain() public diff --git a/contracts/utils/cryptography/Hashes.sol b/contracts/utils/cryptography/Hashes.sol index 893883164..48c9bbe2d 100644 --- a/contracts/utils/cryptography/Hashes.sol +++ b/contracts/utils/cryptography/Hashes.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/Hashes.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/Hashes.sol) pragma solidity ^0.8.20; @@ -15,13 +15,13 @@ library Hashes { * NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. */ function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) { - return a < b ? _efficientKeccak256(a, b) : _efficientKeccak256(b, a); + return a < b ? efficientKeccak256(a, b) : efficientKeccak256(b, a); } /** * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory. */ - function _efficientKeccak256(bytes32 a, bytes32 b) private pure returns (bytes32 value) { + function efficientKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32 value) { assembly ("memory-safe") { mstore(0x00, a) mstore(0x20, b) diff --git a/contracts/utils/cryptography/MessageHashUtils.sol b/contracts/utils/cryptography/MessageHashUtils.sol index e1cbccb65..37e92395f 100644 --- a/contracts/utils/cryptography/MessageHashUtils.sol +++ b/contracts/utils/cryptography/MessageHashUtils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MessageHashUtils.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; @@ -19,7 +19,7 @@ library MessageHashUtils { * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the - * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. + * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will @@ -41,7 +41,7 @@ library MessageHashUtils { * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the - * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. + * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ @@ -63,6 +63,21 @@ library MessageHashUtils { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } + /** + * @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32. + */ + function toDataWithIntendedValidatorHash( + address validator, + bytes32 messageHash + ) internal pure returns (bytes32 digest) { + assembly ("memory-safe") { + mstore(0x00, hex"19_00") + mstore(0x02, shl(96, validator)) + mstore(0x16, messageHash) + digest := keccak256(0x00, 0x36) + } + } + /** * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`). * diff --git a/contracts/utils/cryptography/P256.sol b/contracts/utils/cryptography/P256.sol index 510eb55e7..81d79adc4 100644 --- a/contracts/utils/cryptography/P256.sol +++ b/contracts/utils/cryptography/P256.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/P256.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/P256.sol) pragma solidity ^0.8.20; import {Math} from "../math/Math.sol"; @@ -90,10 +90,48 @@ library P256 { ) private view returns (bool valid, bool supported) { if (!_isProperSignature(r, s) || !isValidPublicKey(qx, qy)) { return (false, true); // signature is invalid, and its not because the precompile is missing + } else if (_rip7212(h, r, s, qx, qy)) { + return (true, true); // precompile is present, signature is valid + } else if ( + // Given precompiles have no bytecode (i.e. `address(0x100).code.length == 0`), we use + // a valid signature with small `r` and `s` values to check if the precompile is present. Taken from + // https://github.com/C2SP/wycheproof/blob/4672ff74d68766e7785c2cac4c597effccef2c5c/testvectors/ecdsa_secp256r1_sha256_p1363_test.json#L1173-L1204 + _rip7212( + 0xbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023, // sha256("123400") + 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000001, + 0xa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac957, + 0x5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b + ) + ) { + return (false, true); // precompile is present, signature is invalid + } else { + return (false, false); // precompile is absent } + } - (bool success, bytes memory returndata) = address(0x100).staticcall(abi.encode(h, r, s, qx, qy)); - return (success && returndata.length == 0x20) ? (abi.decode(returndata, (bool)), true) : (false, false); + /** + * @dev Low level helper for {_tryVerifyNative}. Calls the precompile and checks if there is a return value. + */ + function _rip7212(bytes32 h, bytes32 r, bytes32 s, bytes32 qx, bytes32 qy) private view returns (bool isValid) { + assembly ("memory-safe") { + // Use the free memory pointer without updating it at the end of the function + let ptr := mload(0x40) + mstore(ptr, h) + mstore(add(ptr, 0x20), r) + mstore(add(ptr, 0x40), s) + mstore(add(ptr, 0x60), qx) + mstore(add(ptr, 0x80), qy) + // RIP-7212 precompiles return empty bytes when an invalid signature is passed, making it impossible + // to distinguish the presence of the precompile. Custom precompile implementations may decide to + // return `bytes32(0)` (i.e. false) without developers noticing, so we decide to evaluate the return value + // without expanding memory using scratch space. + mstore(0x00, 0) // zero out scratch space in case the precompile doesn't return anything + if iszero(staticcall(gas(), 0x100, ptr, 0xa0, 0x00, 0x20)) { + invalid() + } + isValid := mload(0x00) + } } /** diff --git a/contracts/utils/math/Math.sol b/contracts/utils/math/Math.sol index 85a420b1a..f0d608a2d 100644 --- a/contracts/utils/math/Math.sol +++ b/contracts/utils/math/Math.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol) pragma solidity ^0.8.20; @@ -18,38 +18,68 @@ library Math { } /** - * @dev Returns the addition of two unsigned integers, with an success flag (no overflow). + * @dev Return the 512-bit addition of two uint256. + * + * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low. + */ + function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) { + assembly ("memory-safe") { + low := add(a, b) + high := lt(low, a) + } + } + + /** + * @dev Return the 512-bit multiplication of two uint256. + * + * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low. + */ + function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) { + // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use + // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 + // variables such that product = high * 2²⁵⁶ + low. + assembly ("memory-safe") { + let mm := mulmod(a, b, not(0)) + low := mul(a, b) + high := sub(sub(mm, low), lt(mm, low)) + } + } + + /** + * @dev Returns the addition of two unsigned integers, with a success flag (no overflow). */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { uint256 c = a + b; - if (c < a) return (false, 0); - return (true, c); + success = c >= a; + result = c * SafeCast.toUint(success); } } /** - * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow). + * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow). */ function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { - if (b > a) return (false, 0); - return (true, a - b); + uint256 c = a - b; + success = c <= a; + result = c * SafeCast.toUint(success); } } /** - * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow). + * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow). */ function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (true, 0); uint256 c = a * b; - if (c / a != b) return (false, 0); - return (true, c); + assembly ("memory-safe") { + // Only true when the multiplication doesn't overflow + // (c / a == b) || (a == 0) + success := or(eq(div(c, a), b), iszero(a)) + } + // equivalent to: success ? c : 0 + result = c * SafeCast.toUint(success); } } @@ -58,8 +88,11 @@ library Math { */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { - if (b == 0) return (false, 0); - return (true, a / b); + success = b > 0; + assembly ("memory-safe") { + // The `DIV` opcode returns zero when the denominator is 0. + result := div(a, b) + } } } @@ -68,11 +101,38 @@ library Math { */ function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { - if (b == 0) return (false, 0); - return (true, a % b); + success = b > 0; + assembly ("memory-safe") { + // The `MOD` opcode returns zero when the denominator is 0. + result := mod(a, b) + } } } + /** + * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing. + */ + function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) { + (bool success, uint256 result) = tryAdd(a, b); + return ternary(success, result, type(uint256).max); + } + + /** + * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing. + */ + function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) { + (, uint256 result) = trySub(a, b); + return result; + } + + /** + * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing. + */ + function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) { + (bool success, uint256 result) = tryMul(a, b); + return ternary(success, result, type(uint256).max); + } + /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * @@ -143,26 +203,18 @@ library Math { */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { - // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use - // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 - // variables such that product = prod1 * 2²⁵⁶ + prod0. - uint256 prod0 = x * y; // Least significant 256 bits of the product - uint256 prod1; // Most significant 256 bits of the product - assembly { - let mm := mulmod(x, y, not(0)) - prod1 := sub(sub(mm, prod0), lt(mm, prod0)) - } + (uint256 high, uint256 low) = mul512(x, y); // Handle non-overflow cases, 256 by 256 division. - if (prod1 == 0) { + if (high == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. - return prod0 / denominator; + return low / denominator; } // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0. - if (denominator <= prod1) { + if (denominator <= high) { Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW)); } @@ -170,34 +222,34 @@ library Math { // 512 by 256 division. /////////////////////////////////////////////// - // Make division exact by subtracting the remainder from [prod1 prod0]. + // Make division exact by subtracting the remainder from [high low]. uint256 remainder; - assembly { + assembly ("memory-safe") { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. - prod1 := sub(prod1, gt(remainder, prod0)) - prod0 := sub(prod0, remainder) + high := sub(high, gt(remainder, low)) + low := sub(low, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); - assembly { + assembly ("memory-safe") { // Divide denominator by twos. denominator := div(denominator, twos) - // Divide [prod1 prod0] by twos. - prod0 := div(prod0, twos) + // Divide [high low] by twos. + low := div(low, twos) // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } - // Shift in bits from prod1 into prod0. - prod0 |= prod1 * twos; + // Shift in bits from high into low. + low |= high * twos; // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for @@ -215,9 +267,9 @@ library Math { // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is - // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1 + // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high // is no longer required. - result = prod0 * inverse; + result = low * inverse; return result; } } @@ -229,6 +281,26 @@ library Math { return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } + /** + * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256. + */ + function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) { + unchecked { + (uint256 high, uint256 low) = mul512(x, y); + if (high >= 1 << n) { + Panic.panic(Panic.UNDER_OVERFLOW); + } + return (high << (256 - n)) | (low >> n); + } + } + + /** + * @dev Calculates x * y >> n with full precision, following the selected rounding direction. + */ + function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) { + return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0); + } + /** * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. * @@ -537,41 +609,45 @@ library Math { * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ - function log2(uint256 value) internal pure returns (uint256) { - uint256 result = 0; - uint256 exp; - unchecked { - exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); - value >>= exp; - result += exp; + function log2(uint256 x) internal pure returns (uint256 r) { + // If value has upper 128 bits set, log2 result is at least 128 + r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7; + // If upper 64 bits of 128-bit half set, add 64 to result + r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6; + // If upper 32 bits of 64-bit half set, add 32 to result + r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5; + // If upper 16 bits of 32-bit half set, add 16 to result + r |= SafeCast.toUint((x >> r) > 0xffff) << 4; + // If upper 8 bits of 16-bit half set, add 8 to result + r |= SafeCast.toUint((x >> r) > 0xff) << 3; + // If upper 4 bits of 8-bit half set, add 4 to result + r |= SafeCast.toUint((x >> r) > 0xf) << 2; - exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); - value >>= exp; - result += exp; - - exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); - value >>= exp; - result += exp; - - exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); - value >>= exp; - result += exp; - - exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); - value >>= exp; - result += exp; - - exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); - value >>= exp; - result += exp; - - exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); - value >>= exp; - result += exp; - - result += SafeCast.toUint(value > 1); + // Shifts value right by the current result and use it as an index into this lookup table: + // + // | x (4 bits) | index | table[index] = MSB position | + // |------------|---------|-----------------------------| + // | 0000 | 0 | table[0] = 0 | + // | 0001 | 1 | table[1] = 0 | + // | 0010 | 2 | table[2] = 1 | + // | 0011 | 3 | table[3] = 1 | + // | 0100 | 4 | table[4] = 2 | + // | 0101 | 5 | table[5] = 2 | + // | 0110 | 6 | table[6] = 2 | + // | 0111 | 7 | table[7] = 2 | + // | 1000 | 8 | table[8] = 3 | + // | 1001 | 9 | table[9] = 3 | + // | 1010 | 10 | table[10] = 3 | + // | 1011 | 11 | table[11] = 3 | + // | 1100 | 12 | table[12] = 3 | + // | 1101 | 13 | table[13] = 3 | + // | 1110 | 14 | table[14] = 3 | + // | 1111 | 15 | table[15] = 3 | + // + // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes. + assembly ("memory-safe") { + r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000)) } - return result; } /** @@ -640,29 +716,17 @@ library Math { * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ - function log256(uint256 value) internal pure returns (uint256) { - uint256 result = 0; - uint256 isGt; - unchecked { - isGt = SafeCast.toUint(value > (1 << 128) - 1); - value >>= isGt * 128; - result += isGt * 16; - - isGt = SafeCast.toUint(value > (1 << 64) - 1); - value >>= isGt * 64; - result += isGt * 8; - - isGt = SafeCast.toUint(value > (1 << 32) - 1); - value >>= isGt * 32; - result += isGt * 4; - - isGt = SafeCast.toUint(value > (1 << 16) - 1); - value >>= isGt * 16; - result += isGt * 2; - - result += SafeCast.toUint(value > (1 << 8) - 1); - } - return result; + function log256(uint256 x) internal pure returns (uint256 r) { + // If value has upper 128 bits set, log2 result is at least 128 + r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7; + // If upper 64 bits of 128-bit half set, add 64 to result + r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6; + // If upper 32 bits of 64-bit half set, add 32 to result + r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5; + // If upper 16 bits of 32-bit half set, add 16 to result + r |= SafeCast.toUint((x >> r) > 0xffff) << 4; + // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8 + return (r >> 3) | SafeCast.toUint((x >> r) > 0xff); } /** diff --git a/contracts/utils/structs/Checkpoints.sol b/contracts/utils/structs/Checkpoints.sol index 8d8f13031..8ad3c5ab5 100644 --- a/contracts/utils/structs/Checkpoints.sol +++ b/contracts/utils/structs/Checkpoints.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/Checkpoints.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/Checkpoints.sol) // This file was procedurally generated from scripts/generate/templates/Checkpoints.js. pragma solidity ^0.8.20; @@ -114,7 +114,7 @@ library Checkpoints { } /** - * @dev Returns the number of checkpoint. + * @dev Returns the number of checkpoints. */ function length(Trace224 storage self) internal view returns (uint256) { return self._checkpoints.length; @@ -317,7 +317,7 @@ library Checkpoints { } /** - * @dev Returns the number of checkpoint. + * @dev Returns the number of checkpoints. */ function length(Trace208 storage self) internal view returns (uint256) { return self._checkpoints.length; @@ -520,7 +520,7 @@ library Checkpoints { } /** - * @dev Returns the number of checkpoint. + * @dev Returns the number of checkpoints. */ function length(Trace160 storage self) internal view returns (uint256) { return self._checkpoints.length; diff --git a/contracts/utils/structs/CircularBuffer.sol b/contracts/utils/structs/CircularBuffer.sol index ae0a4a88f..43ce89be7 100644 --- a/contracts/utils/structs/CircularBuffer.sol +++ b/contracts/utils/structs/CircularBuffer.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/CircularBuffer.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/CircularBuffer.sol) pragma solidity ^0.8.20; import {Math} from "../math/Math.sol"; @@ -62,7 +62,7 @@ library CircularBuffer { } /** - * @dev Initialize a new CircularBuffer of given size. + * @dev Initialize a new CircularBuffer of a given size. * * If the CircularBuffer was already setup and used, calling that function again will reset it to a blank state. * diff --git a/contracts/utils/structs/EnumerableMap.sol b/contracts/utils/structs/EnumerableMap.sol index 4e12acec1..09fa498fc 100644 --- a/contracts/utils/structs/EnumerableMap.sol +++ b/contracts/utils/structs/EnumerableMap.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableMap.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/EnumerableMap.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. pragma solidity ^0.8.20; @@ -16,6 +16,7 @@ import {EnumerableSet} from "./EnumerableSet.sol"; * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. + * - Map can be cleared (all entries removed) in O(n). * * ```solidity * contract Example { @@ -90,6 +91,20 @@ library EnumerableMap { return map._keys.remove(key); } + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(Bytes32ToBytes32Map storage map) internal { + uint256 len = length(map); + for (uint256 i = 0; i < len; ++i) { + delete map._values[map._keys.at(i)]; + } + map._keys.clear(); + } + /** * @dev Returns true if the key is in the map. O(1). */ @@ -185,6 +200,16 @@ library EnumerableMap { return remove(map._inner, bytes32(key)); } + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(UintToUintMap storage map) internal { + clear(map._inner); + } + /** * @dev Returns true if the key is in the map. O(1). */ @@ -278,6 +303,16 @@ library EnumerableMap { return remove(map._inner, bytes32(key)); } + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(UintToAddressMap storage map) internal { + clear(map._inner); + } + /** * @dev Returns true if the key is in the map. O(1). */ @@ -371,6 +406,16 @@ library EnumerableMap { return remove(map._inner, bytes32(key)); } + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(UintToBytes32Map storage map) internal { + clear(map._inner); + } + /** * @dev Returns true if the key is in the map. O(1). */ @@ -464,6 +509,16 @@ library EnumerableMap { return remove(map._inner, bytes32(uint256(uint160(key)))); } + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(AddressToUintMap storage map) internal { + clear(map._inner); + } + /** * @dev Returns true if the key is in the map. O(1). */ @@ -557,6 +612,16 @@ library EnumerableMap { return remove(map._inner, bytes32(uint256(uint160(key)))); } + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(AddressToAddressMap storage map) internal { + clear(map._inner); + } + /** * @dev Returns true if the key is in the map. O(1). */ @@ -650,6 +715,16 @@ library EnumerableMap { return remove(map._inner, bytes32(uint256(uint160(key)))); } + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(AddressToBytes32Map storage map) internal { + clear(map._inner); + } + /** * @dev Returns true if the key is in the map. O(1). */ @@ -743,6 +818,16 @@ library EnumerableMap { return remove(map._inner, key); } + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(Bytes32ToUintMap storage map) internal { + clear(map._inner); + } + /** * @dev Returns true if the key is in the map. O(1). */ @@ -836,6 +921,16 @@ library EnumerableMap { return remove(map._inner, key); } + /** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(Bytes32ToAddressMap storage map) internal { + clear(map._inner); + } + /** * @dev Returns true if the key is in the map. O(1). */ diff --git a/contracts/utils/structs/EnumerableSet.sol b/contracts/utils/structs/EnumerableSet.sol index 065202e82..ec8bb3779 100644 --- a/contracts/utils/structs/EnumerableSet.sol +++ b/contracts/utils/structs/EnumerableSet.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; +import {Arrays} from "../Arrays.sol"; + /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive @@ -14,6 +16,7 @@ pragma solidity ^0.8.20; * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * - Set can be cleared (all elements removed) in O(n). * * ```solidity * contract Example { @@ -114,6 +117,20 @@ library EnumerableSet { } } + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ + function _clear(Set storage set) private { + uint256 len = _length(set); + for (uint256 i = 0; i < len; ++i) { + delete set._positions[set._values[i]]; + } + Arrays.unsafeSetLength(set._values, 0); + } + /** * @dev Returns true if the value is in the set. O(1). */ @@ -180,6 +197,16 @@ library EnumerableSet { return _remove(set._inner, value); } + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(Bytes32Set storage set) internal { + _clear(set._inner); + } + /** * @dev Returns true if the value is in the set. O(1). */ @@ -253,6 +280,16 @@ library EnumerableSet { return _remove(set._inner, bytes32(uint256(uint160(value)))); } + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(AddressSet storage set) internal { + _clear(set._inner); + } + /** * @dev Returns true if the value is in the set. O(1). */ @@ -326,6 +363,16 @@ library EnumerableSet { return _remove(set._inner, bytes32(value)); } + /** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ + function clear(UintSet storage set) internal { + _clear(set._inner); + } + /** * @dev Returns true if the value is in the set. O(1). */ diff --git a/contracts/utils/structs/MerkleTree.sol b/contracts/utils/structs/MerkleTree.sol index 56f5bc672..010ccfe8b 100644 --- a/contracts/utils/structs/MerkleTree.sol +++ b/contracts/utils/structs/MerkleTree.sol @@ -1,11 +1,12 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/MerkleTree.sol) +// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/MerkleTree.sol) pragma solidity ^0.8.20; import {Hashes} from "../cryptography/Hashes.sol"; import {Arrays} from "../Arrays.sol"; import {Panic} from "../Panic.sol"; +import {StorageSlot} from "../StorageSlot.sol"; /** * @dev Library for managing https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] data structures. @@ -27,6 +28,12 @@ import {Panic} from "../Panic.sol"; * _Available since v5.1._ */ library MerkleTree { + /// @dev Error emitted when trying to update a leaf that was not previously pushed. + error MerkleTreeUpdateInvalidIndex(uint256 index, uint256 length); + + /// @dev Error emitted when the proof used during an update is invalid (could not reproduce the side). + error MerkleTreeUpdateInvalidProof(); + /** * @dev A complete `bytes32` Merkle tree. * @@ -88,7 +95,7 @@ library MerkleTree { // Build each root of zero-filled subtrees bytes32 currentZero = zero; - for (uint32 i = 0; i < treeDepth; ++i) { + for (uint256 i = 0; i < treeDepth; ++i) { Arrays.unsafeAccess(self._zeros, i).value = currentZero; currentZero = fnHash(currentZero, currentZero); } @@ -143,7 +150,7 @@ library MerkleTree { // Rebuild branch from leaf to root uint256 currentIndex = index; bytes32 currentLevelHash = leaf; - for (uint32 i = 0; i < treeDepth; i++) { + for (uint256 i = 0; i < treeDepth; i++) { // Reaching the parent node, is currentLevelHash the left child? bool isLeft = currentIndex % 2 == 0; @@ -166,6 +173,91 @@ library MerkleTree { return (index, currentLevelHash); } + /** + * @dev Change the value of the leaf at position `index` from `oldValue` to `newValue`. Returns the recomputed "old" + * root (before the update) and "new" root (after the update). The caller must verify that the reconstructed old + * root is the last known one. + * + * The `proof` must be an up-to-date inclusion proof for the leaf being updated. This means that this function is + * vulnerable to front-running. Any {push} or {update} operation (that changes the root of the tree) would render + * all "in flight" updates invalid. + * + * This variant uses {Hashes-commutativeKeccak256} to hash internal nodes. It should only be used on merkle trees + * that were setup using the same (default) hashing function (i.e. by calling + * {xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-}[the default setup] function). + */ + function update( + Bytes32PushTree storage self, + uint256 index, + bytes32 oldValue, + bytes32 newValue, + bytes32[] memory proof + ) internal returns (bytes32 oldRoot, bytes32 newRoot) { + return update(self, index, oldValue, newValue, proof, Hashes.commutativeKeccak256); + } + + /** + * @dev Change the value of the leaf at position `index` from `oldValue` to `newValue`. Returns the recomputed "old" + * root (before the update) and "new" root (after the update). The caller must verify that the reconstructed old + * root is the last known one. + * + * The `proof` must be an up-to-date inclusion proof for the leaf being update. This means that this function is + * vulnerable to front-running. Any {push} or {update} operation (that changes the root of the tree) would render + * all "in flight" updates invalid. + * + * This variant uses a custom hashing function to hash internal nodes. It should only be called with the same + * function as the one used during the initial setup of the merkle tree. + */ + function update( + Bytes32PushTree storage self, + uint256 index, + bytes32 oldValue, + bytes32 newValue, + bytes32[] memory proof, + function(bytes32, bytes32) view returns (bytes32) fnHash + ) internal returns (bytes32 oldRoot, bytes32 newRoot) { + unchecked { + // Check index range + uint256 length = self._nextLeafIndex; + if (index >= length) revert MerkleTreeUpdateInvalidIndex(index, length); + + // Cache read + uint256 treeDepth = depth(self); + + // Workaround stack too deep + bytes32[] storage sides = self._sides; + + // This cannot overflow because: 0 <= index < length + uint256 lastIndex = length - 1; + uint256 currentIndex = index; + bytes32 currentLevelHashOld = oldValue; + bytes32 currentLevelHashNew = newValue; + for (uint32 i = 0; i < treeDepth; i++) { + bool isLeft = currentIndex % 2 == 0; + + lastIndex >>= 1; + currentIndex >>= 1; + + if (isLeft && currentIndex == lastIndex) { + StorageSlot.Bytes32Slot storage side = Arrays.unsafeAccess(sides, i); + if (side.value != currentLevelHashOld) revert MerkleTreeUpdateInvalidProof(); + side.value = currentLevelHashNew; + } + + bytes32 sibling = proof[i]; + currentLevelHashOld = fnHash( + isLeft ? currentLevelHashOld : sibling, + isLeft ? sibling : currentLevelHashOld + ); + currentLevelHashNew = fnHash( + isLeft ? currentLevelHashNew : sibling, + isLeft ? sibling : currentLevelHashNew + ); + } + return (currentLevelHashOld, currentLevelHashNew); + } + } + /** * @dev Tree's depth (set at initialization) */ diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 15af8b40e..52f7e37b0 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -13,6 +13,7 @@ ** xref:erc721.adoc[ERC-721] ** xref:erc1155.adoc[ERC-1155] ** xref:erc4626.adoc[ERC-4626] +** xref:erc6909.adoc[ERC-6909] * xref:governance.adoc[Governance] diff --git a/docs/modules/ROOT/pages/access-control.adoc b/docs/modules/ROOT/pages/access-control.adoc index bef18ca11..57d26bc08 100644 --- a/docs/modules/ROOT/pages/access-control.adoc +++ b/docs/modules/ROOT/pages/access-control.adoc @@ -24,7 +24,7 @@ WARNING: Removing the owner altogether will mean that administrative tasks that Ownable is a simple and effective way to implement access control, but you should be mindful of the dangers associated with transferring the ownership to an incorrect account that can't interact with this contract anymore. An alternative to this problem is using xref:api:access.adoc#Ownable2Step[`Ownable2Step`]; a variant of Ownable that requires the new owner to explicitly accept the ownership transfer by calling xref:api:access.adoc#Ownable2Step-acceptOwnership--[`acceptOwnership`]. -Note that *a contract can also be the owner of another one*! This opens the door to using, for example, a https://gnosis-safe.io[Gnosis Safe], an https://aragon.org[Aragon DAO], or a totally custom contract that _you_ create. +Note that *a contract can also be the owner of another one*! This opens the door to using, for example, a https://safe.global[Gnosis Safe], an https://aragon.org[Aragon DAO], or a totally custom contract that _you_ create. In this way, you can use _composability_ to add additional layers of access control complexity to your contracts. Instead of having a single regular Ethereum account (Externally Owned Account, or EOA) as the owner, you could use a 2-of-3 multisig run by your project leads, for example. Prominent projects in the space, such as https://makerdao.com[MakerDAO], use systems similar to this one. diff --git a/docs/modules/ROOT/pages/crowdsales.adoc b/docs/modules/ROOT/pages/crowdsales.adoc deleted file mode 100644 index 37579211d..000000000 --- a/docs/modules/ROOT/pages/crowdsales.adoc +++ /dev/null @@ -1,11 +0,0 @@ -= Crowdsales - -All crowdsale-related contracts were removed from the OpenZeppelin Contracts library on the https://forum.openzeppelin.com/t/openzeppelin-contracts-v3-0-beta-release/2256[v3.0.0 release] due to both a decline in their usage and the complexity associated with migrating them to Solidity v0.6. - -They are however still available on the v2.5 release of OpenZeppelin Contracts, which you can install by running: - -```console -$ npm install @openzeppelin/contracts@v2.5 -``` - -Refer to the https://docs.openzeppelin.com/contracts/2.x/crowdsales[v2.x documentation] when working with them. diff --git a/docs/modules/ROOT/pages/drafts.adoc b/docs/modules/ROOT/pages/drafts.adoc deleted file mode 100644 index b2c1ae628..000000000 --- a/docs/modules/ROOT/pages/drafts.adoc +++ /dev/null @@ -1,19 +0,0 @@ -= Drafts - -All draft contracts were either moved into a different directory or removed from the OpenZeppelin Contracts library on the https://forum.openzeppelin.com/t/openzeppelin-contracts-v3-0-beta-release/2256[v3.0.0 release]. - -* `ERC20Migrator`: removed. -* xref:api:token/ERC20.adoc#ERC20Snapshot[`ERC20Snapshot`]: moved to `token/ERC20`. -* `ERC20Detailed` and `ERC1046`: removed. -* `TokenVesting`: removed. Pending a replacement that is being discussed in https://github.com/OpenZeppelin/openzeppelin-contracts/issues/1214[`#1214`]. -* xref:api:utils.adoc#Counters[`Counters`]: moved to xref:api:utils.adoc[`utils`]. -* xref:api:utils.adoc#Strings[`Strings`]: moved to xref:api:utils.adoc[`utils`]. -* xref:api:utils.adoc#SignedSafeMath[`SignedSafeMath`]: moved to xref:api:utils.adoc[`utils`]. - -Removed contracts are still available on the v2.5 release of OpenZeppelin Contracts, which you can install by running: - -```console -$ npm install @openzeppelin/contracts@v2.5 -``` - -Refer to the xref:2.x@contracts:api:drafts.adoc[v2.x documentation] when working with them. diff --git a/docs/modules/ROOT/pages/erc1155.adoc b/docs/modules/ROOT/pages/erc1155.adoc index 7f00f3ea4..2c31db8b8 100644 --- a/docs/modules/ROOT/pages/erc1155.adoc +++ b/docs/modules/ROOT/pages/erc1155.adoc @@ -106,7 +106,7 @@ A key difference when using xref:api:token/ERC1155.adoc#IERC1155-safeTransferFro ERC1155InvalidReceiver("
") ---- -This is a good thing! It means that the recipient contract has not registered itself as aware of the ERC-1155 protocol, so transfers to it are disabled to *prevent tokens from being locked forever*. As an example, https://etherscan.io/token/0xa74476443119A942dE498590Fe1f2454d7D4aC0d?a=0xa74476443119A942dE498590Fe1f2454d7D4aC0d[the Golem contract currently holds over 350k `GNT` tokens], worth multiple tens of thousands of dollars, and lacks methods to get them out of there. This has happened to virtually every ERC20-backed project, usually due to user error. +This is a good thing! It means that the recipient contract has not registered itself as aware of the ERC-1155 protocol, so transfers to it are disabled to *prevent tokens from being locked forever*. As an example, https://etherscan.io/token/0xa74476443119A942dE498590Fe1f2454d7D4aC0d?a=0xa74476443119A942dE498590Fe1f2454d7D4aC0d[the Golem contract currently holds over 350k `GNT` tokens], and lacks methods to get them out of there. This has happened to virtually every ERC20-backed project, usually due to user error. In order for our contract to receive ERC-1155 tokens we can inherit from the convenience contract xref:api:token/ERC1155.adoc#ERC1155Holder[`ERC1155Holder`] which handles the registering for us. However, we need to remember to implement functionality to allow tokens to be transferred out of our contract: diff --git a/docs/modules/ROOT/pages/erc20-supply.adoc b/docs/modules/ROOT/pages/erc20-supply.adoc index ae21e4a8a..273cb3252 100644 --- a/docs/modules/ROOT/pages/erc20-supply.adoc +++ b/docs/modules/ROOT/pages/erc20-supply.adoc @@ -68,4 +68,4 @@ include::api:example$ERC20WithAutoMinerReward.sol[] [[wrapping-up]] == Wrapping Up -We've seen how to implement a ERC-20 supply mechanism: internally through `_mint`. Hopefully this has helped you understand how to use OpenZeppelin Contracts and some of the design principles behind it, and you can apply them to your own smart contracts. +We've seen how to implement an ERC-20 supply mechanism: internally through `_mint`. Hopefully this has helped you understand how to use OpenZeppelin Contracts and some of the design principles behind it, and you can apply them to your own smart contracts. diff --git a/docs/modules/ROOT/pages/erc6909.adoc b/docs/modules/ROOT/pages/erc6909.adoc new file mode 100644 index 000000000..164ded8ed --- /dev/null +++ b/docs/modules/ROOT/pages/erc6909.adoc @@ -0,0 +1,47 @@ += ERC-6909 + +ERC-6909 is a draft EIP that draws on ERC-1155 learnings since it was published in 2018. The main goals of ERC-6909 is to decrease gas costs and complexity--this is mainly accomplished by removing batching and callbacks. + +TIP: To understand the inspiration for a multi token standard, see the xref:erc1155.adoc#multi-token-standard[multi token standard] section within the EIP-1155 docs. + +== Changes from ERC-1155 + +There are three main changes from ERC-1155 which are as follows: + +. The removal of batch operations. +. The removal of transfer callbacks. +. Granularization in approvals--approvals can be set globally (as operators) or as amounts per token (inspired by ERC20). + +== Constructing an ERC-6909 Token Contract + +We'll use ERC-6909 to track multiple items in a game, each having their own unique attributes. All item types will by minted to the deployer of the contract, which we can later transfer to players. We'll also use the xref:api:token/ERC6909.adoc#ERC6909Metadata[`ERC6909Metadata`] extension to add decimals to our fungible items (the vanilla ERC-6909 implementation does not have decimals). + +For simplicity, we will mint all items in the constructor--however, minting functionality could be added to the contract to mint on demand to players. + +TIP: For an overview of minting mechanisms, check out xref:erc20-supply.adoc[Creating ERC-20 Supply]. + +Here's what a contract for tokenized items might look like: + +[source,solidity] +---- +include::api:example$token/ERC6909/ERC6909GameItems.sol[] +---- + +Note that there is no content URI functionality in the base implementation, but the xref:api:token/ERC6909.adoc#ERC6909ContentURI[`ERC6909ContentURI`] extension adds it. Additionally, the base implementation does not track total supplies, but the xref:api:token/ERC6909.adoc#ERC6909TokenSupply[`ERC6909TokenSupply`] extension tracks the total supply of each token id. + +Once the contract is deployed, we will be able to query the deployer’s balance: +[source,javascript] +---- +> gameItems.balanceOf(deployerAddress, 3) +1000000000 +---- + +We can transfer items to player accounts: +[source,javascript] +---- +> gameItems.transfer(playerAddress, 2, 1) +> gameItems.balanceOf(playerAddress, 2) +1 +> gameItems.balanceOf(deployerAddress, 2) +0 +---- diff --git a/docs/modules/ROOT/pages/governance.adoc b/docs/modules/ROOT/pages/governance.adoc index 5f8e77555..c2b8218ff 100644 --- a/docs/modules/ROOT/pages/governance.adoc +++ b/docs/modules/ROOT/pages/governance.adoc @@ -20,7 +20,7 @@ The ERC-20 extension to keep track of votes and vote delegation is one such case === Governor & GovernorStorage -An OpenZeppelin Governor contract is not interface-compatible with Compound's GovernorAlpha or Bravo. Even though events are fully compatible, proposal lifecycle functions (creation, execution, etc.) have different signatures that are meant to optimize storage use. Other functions from GovernorAlpha and Bravo are likewise not available. It’s possible to opt in some Bravo-like behavior by inheriting from the GovernorStorage module. This module provides proposal enumerability and alternate versions of the `queue`, `execute` and `cancel` function that only take the proposal id. This module reduces the calldata needed by some operations in exchange for an increased the storage footprint. This might be a good trade-off for some L2 chains. It also provides primitives for indexer-free frontends. +An OpenZeppelin Governor contract is not interface-compatible with Compound's GovernorAlpha or Bravo. Even though events are fully compatible, proposal lifecycle functions (creation, execution, etc.) have different signatures that are meant to optimize storage use. Other functions from GovernorAlpha and Bravo are likewise not available. It’s possible to opt in some Bravo-like behavior by inheriting from the GovernorStorage module. This module provides proposal enumerability and alternate versions of the `queue`, `execute` and `cancel` function that only take the proposal id. This module reduces the calldata needed by some operations in exchange for an increased storage footprint. This might be a good trade-off for some L2 chains. It also provides primitives for indexer-free frontends. Note that even with the use of this module, one important difference with Compound's GovernorBravo is the way that `proposalId`s are calculated. Governor uses the hash of the proposal parameters with the purpose of keeping its data off-chain by event indexing, while the original Bravo implementation uses sequential `proposalId`s. @@ -52,7 +52,7 @@ If your project already has a live token that does not include ERC20Votes and is include::api:example$governance/MyTokenWrapped.sol[] ``` -NOTE: The only other source of voting power available in OpenZeppelin Contracts currently is xref:api:token/ERC721.adoc#ERC721Votes[`ERC721Votes`]. ERC-721 tokens that don't provide this functionality can be wrapped into a voting tokens using a combination of xref:api:token/ERC721.adoc#ERC721Votes[`ERC721Votes`] and xref:api:token/ERC721Wrapper.adoc#ERC721Wrapper[`ERC721Wrapper`]. +NOTE: The only other source of voting power available in OpenZeppelin Contracts currently is xref:api:token/ERC721.adoc#ERC721Votes[`ERC721Votes`]. ERC-721 tokens that don't provide this functionality can be wrapped into a voting tokens using a combination of xref:api:token/ERC721.adoc#ERC721Votes[`ERC721Votes`] and xref:api:token/ERC721.adoc#ERC721Wrapper[`ERC721Wrapper`]. NOTE: The internal clock used by the token to store voting balances will dictate the operating mode of the Governor contract attached to it. By default, block numbers are used. Since v4.9, developers can override the xref:api:interfaces.adoc#IERC6372[IERC6372] clock to use timestamps instead of block numbers. diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 1ba449559..3c8e57ed3 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -63,7 +63,7 @@ The guides in the sidebar will teach about different concepts, and how to use th The xref:api:token/ERC20.adoc[full API] is also thoroughly documented, and serves as a great reference when developing your smart contract application. You can also ask for help or follow Contracts' development in the https://forum.openzeppelin.com[community forum]. -Finally, you may want to take a look at the https://blog.openzeppelin.com/guides/[guides on our blog], which cover several common use cases and good practices. The following articles provide great background reading, though please note, some of the referenced tools have changed as the tooling in the ecosystem continues to rapidly evolve. +The following articles provide great background reading, though please note, some of the referenced tools have changed as the tooling in the ecosystem continues to rapidly evolve. * https://blog.openzeppelin.com/the-hitchhikers-guide-to-smart-contracts-in-ethereum-848f08001f05[The Hitchhiker’s Guide to Smart Contracts in Ethereum] will help you get an overview of the various tools available for smart contract development, and help you set up your environment. * https://blog.openzeppelin.com/a-gentle-introduction-to-ethereum-programming-part-1-783cc7796094[A Gentle Introduction to Ethereum Programming, Part 1] provides very useful information on an introductory level, including many basic concepts from the Ethereum platform. diff --git a/docs/modules/ROOT/pages/utilities.adoc b/docs/modules/ROOT/pages/utilities.adoc index bb519907d..f6b22b025 100644 --- a/docs/modules/ROOT/pages/utilities.adoc +++ b/docs/modules/ROOT/pages/utilities.adoc @@ -12,7 +12,7 @@ At a high level, signatures are a set of cryptographic algorithms that allow for ==== Ethereum Signatures (secp256k1) -xref:api:utils.adoc#ECDSA[`ECDSA`] provides functions for recovering and managing Ethereum account ECDSA signatures. These are often generated via https://web3js.readthedocs.io/en/v1.7.3/web3-eth.html#sign[`web3.eth.sign`], and are a 65 byte array (of type `bytes` in Solidity) arranged the following way: `[[v (1)], [r (32)], [s (32)]]`. +xref:api:utils.adoc#ECDSA[`ECDSA`] provides functions for recovering and managing Ethereum account ECDSA signatures. These are often generated via https://web3js.readthedocs.io/en/v1.7.3/web3-eth.html#sign[`web3.eth.sign`], and form a 65-byte array (of type `bytes` in Solidity) arranged the following way: `[[v (1)], [r (32)], [s (32)]]`. The data signer can be recovered with xref:api:utils.adoc#ECDSA-recover-bytes32-bytes-[`ECDSA.recover`], and its address compared to verify the signature. Most wallets will hash the data to sign and add the prefix `\x19Ethereum Signed Message:\n`, so when attempting to recover the signer of an Ethereum signed message hash, you'll want to use xref:api:utils.adoc#MessageHashUtils-toEthSignedMessageHash-bytes32-[`toEthSignedMessageHash`]. @@ -197,7 +197,7 @@ The `Enumerable*` structures are similar to mappings in that they store and remo Building an on-chain Merkle Tree allows developers to keep track of the history of roots in a decentralized manner. For these cases, the xref:api:utils.adoc#MerkleTree[`MerkleTree`] includes a predefined structure with functions to manipulate the tree (e.g. pushing values or resetting the tree). -The Merkle Tree does not keep track of the roots purposely, so that developers can choose their tracking mechanism. Setting up and using a Merkle Tree in Solidity is as simple as follows: +The Merkle Tree does not keep track of the roots intentionally, so that developers can choose their tracking mechanism. Setting up and using a Merkle Tree in Solidity is as simple as follows: NOTE: Functions are exposed without access control for demonstration purposes @@ -243,7 +243,7 @@ function _hashFn(bytes32 a, bytes32 b) internal view returns(bytes32) { === Using a Heap -A https://en.wikipedia.org/wiki/Binary_heap[binary heap] is a data structure that always store the most important element at its peak and it can be used as a priority queue. +A https://en.wikipedia.org/wiki/Binary_heap[binary heap] is a data structure that always stores the most important element at its peak and it can be used as a priority queue. To define what is most important in a heap, these frequently take comparator functions that tell the binary heap whether a value has more relevance than another. @@ -358,7 +358,7 @@ This is especially useful for building URL-safe tokenURIs for both xref:api:toke Here is an example to send JSON Metadata through a Base64 Data URI using an ERC-721: -[source, solidity] +[source,solidity] ---- include::api:example$utilities/Base64NFT.sol[] ---- diff --git a/docs/modules/api/examples/access-control/AccessControlModified.sol b/docs/modules/api/examples/access-control/AccessControlModified.sol index bc944cabf..a08546a1e 100644 --- a/docs/modules/api/examples/access-control/AccessControlModified.sol +++ b/docs/modules/api/examples/access-control/AccessControlModified.sol @@ -5,10 +5,10 @@ pragma solidity ^0.8.20; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; contract AccessControlModified is AccessControl { - error AccessControlNonRevokable(); + error AccessControlNonRevocable(); // Override the revokeRole function function revokeRole(bytes32, address) public pure override { - revert AccessControlNonRevokable(); + revert AccessControlNonRevocable(); } } diff --git a/docs/modules/api/examples/token/ERC6909/ERC6909GameItems.sol b/docs/modules/api/examples/token/ERC6909/ERC6909GameItems.sol new file mode 100644 index 000000000..8cdaca49c --- /dev/null +++ b/docs/modules/api/examples/token/ERC6909/ERC6909GameItems.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {ERC6909Metadata} from "@openzeppelin/contracts/token/ERC6909/extensions/draft-ERC6909Metadata.sol"; + +contract ERC6909GameItems is ERC6909Metadata { + uint256 public constant GOLD = 0; + uint256 public constant SILVER = 1; + uint256 public constant THORS_HAMMER = 2; + uint256 public constant SWORD = 3; + uint256 public constant SHIELD = 4; + + constructor() { + _setDecimals(GOLD, 18); + _setDecimals(SILVER, 18); + // Default decimals is 0 + _setDecimals(SWORD, 9); + _setDecimals(SHIELD, 9); + + _mint(msg.sender, GOLD, 10 ** 18); + _mint(msg.sender, SILVER, 10_000 ** 18); + _mint(msg.sender, THORS_HAMMER, 1); + _mint(msg.sender, SWORD, 10 ** 9); + _mint(msg.sender, SHIELD, 10 ** 9); + } +} diff --git a/docs/modules/api/nav.adoc b/docs/modules/api/nav.adoc index d9f67fd74..fcb227614 100644 --- a/docs/modules/api/nav.adoc +++ b/docs/modules/api/nav.adoc @@ -5,6 +5,7 @@ * xref:token/ERC20.adoc[ERC 20] * xref:token/ERC721.adoc[ERC 721] * xref:token/ERC1155.adoc[ERC 1155] +* xref:token/ERC6909.adoc[ERC 6909] * xref:finance.adoc[Finance] * xref:governance.adoc[Governance] * xref:interfaces.adoc[Interfaces] diff --git a/docs/modules/api/pages/access.adoc b/docs/modules/api/pages/access.adoc index 234edc012..5df51825f 100644 --- a/docs/modules/api/pages/access.adoc +++ b/docs/modules/api/pages/access.adoc @@ -356,9 +356,16 @@ This directory provides ways to restrict who can access the functions of a contr :transferOwnership: pass:normal[xref:#Ownable-transferOwnership-address-[`++transferOwnership++`]] :_transferOwnership: pass:normal[xref:#Ownable-_transferOwnership-address-[`++_transferOwnership++`]] +:constructor-address: pass:normal[xref:#Ownable-constructor-address-[`++constructor++`]] +:owner-: pass:normal[xref:#Ownable-owner--[`++owner++`]] +:_checkOwner-: pass:normal[xref:#Ownable-_checkOwner--[`++_checkOwner++`]] +:renounceOwnership-: pass:normal[xref:#Ownable-renounceOwnership--[`++renounceOwnership++`]] +:transferOwnership-address: pass:normal[xref:#Ownable-transferOwnership-address-[`++transferOwnership++`]] +:_transferOwnership-address: pass:normal[xref:#Ownable-_transferOwnership-address-[`++_transferOwnership++`]] + [.contract] [[Ownable]] -=== `++Ownable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/Ownable.sol[{github-icon},role=heading-link] +=== `++Ownable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/Ownable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -479,9 +486,14 @@ The owner is not a valid owner account. (eg. `address(0)`) :_transferOwnership: pass:normal[xref:#Ownable2Step-_transferOwnership-address-[`++_transferOwnership++`]] :acceptOwnership: pass:normal[xref:#Ownable2Step-acceptOwnership--[`++acceptOwnership++`]] +:pendingOwner-: pass:normal[xref:#Ownable2Step-pendingOwner--[`++pendingOwner++`]] +:transferOwnership-address: pass:normal[xref:#Ownable2Step-transferOwnership-address-[`++transferOwnership++`]] +:_transferOwnership-address: pass:normal[xref:#Ownable2Step-_transferOwnership-address-[`++_transferOwnership++`]] +:acceptOwnership-: pass:normal[xref:#Ownable2Step-acceptOwnership--[`++acceptOwnership++`]] + [.contract] [[Ownable2Step]] -=== `++Ownable2Step++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/Ownable2Step.sol[{github-icon},role=heading-link] +=== `++Ownable2Step++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/Ownable2Step.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -585,9 +597,15 @@ The new owner accepts the ownership transfer. :revokeRole: pass:normal[xref:#IAccessControl-revokeRole-bytes32-address-[`++revokeRole++`]] :renounceRole: pass:normal[xref:#IAccessControl-renounceRole-bytes32-address-[`++renounceRole++`]] +:hasRole-bytes32-address: pass:normal[xref:#IAccessControl-hasRole-bytes32-address-[`++hasRole++`]] +:getRoleAdmin-bytes32: pass:normal[xref:#IAccessControl-getRoleAdmin-bytes32-[`++getRoleAdmin++`]] +:grantRole-bytes32-address: pass:normal[xref:#IAccessControl-grantRole-bytes32-address-[`++grantRole++`]] +:revokeRole-bytes32-address: pass:normal[xref:#IAccessControl-revokeRole-bytes32-address-[`++revokeRole++`]] +:renounceRole-bytes32-address: pass:normal[xref:#IAccessControl-renounceRole-bytes32-address-[`++renounceRole++`]] + [.contract] [[IAccessControl]] -=== `++IAccessControl++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/IAccessControl.sol[{github-icon},role=heading-link] +=== `++IAccessControl++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/IAccessControl.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -688,7 +706,7 @@ Requirements: Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite -{RoleAdminChanged} not being emitted signaling this. +{RoleAdminChanged} not being emitted to signal this. [.contract-item] [[IAccessControl-RoleGranted-bytes32-address-address-]] @@ -738,9 +756,22 @@ NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. :_grantRole: pass:normal[xref:#AccessControl-_grantRole-bytes32-address-[`++_grantRole++`]] :_revokeRole: pass:normal[xref:#AccessControl-_revokeRole-bytes32-address-[`++_revokeRole++`]] +:supportsInterface-bytes4: pass:normal[xref:#AccessControl-supportsInterface-bytes4-[`++supportsInterface++`]] +:hasRole-bytes32-address: pass:normal[xref:#AccessControl-hasRole-bytes32-address-[`++hasRole++`]] +:_checkRole-bytes32: pass:normal[xref:#AccessControl-_checkRole-bytes32-[`++_checkRole++`]] +:_checkRole-bytes32-address: pass:normal[xref:#AccessControl-_checkRole-bytes32-address-[`++_checkRole++`]] +:getRoleAdmin-bytes32: pass:normal[xref:#AccessControl-getRoleAdmin-bytes32-[`++getRoleAdmin++`]] +:grantRole-bytes32-address: pass:normal[xref:#AccessControl-grantRole-bytes32-address-[`++grantRole++`]] +:revokeRole-bytes32-address: pass:normal[xref:#AccessControl-revokeRole-bytes32-address-[`++revokeRole++`]] +:renounceRole-bytes32-address: pass:normal[xref:#AccessControl-renounceRole-bytes32-address-[`++renounceRole++`]] +:_setRoleAdmin-bytes32-bytes32: pass:normal[xref:#AccessControl-_setRoleAdmin-bytes32-bytes32-[`++_setRoleAdmin++`]] +:_grantRole-bytes32-address: pass:normal[xref:#AccessControl-_grantRole-bytes32-address-[`++_grantRole++`]] +:_revokeRole-bytes32-address: pass:normal[xref:#AccessControl-_revokeRole-bytes32-address-[`++_revokeRole++`]] +:DEFAULT_ADMIN_ROLE-bytes32: pass:normal[xref:#AccessControl-DEFAULT_ADMIN_ROLE-bytes32[`++DEFAULT_ADMIN_ROLE++`]] + [.contract] [[AccessControl]] -=== `++AccessControl++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/AccessControl.sol[{github-icon},role=heading-link] +=== `++AccessControl++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/AccessControl.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -965,7 +996,7 @@ May emit a {RoleGranted} event. [[AccessControl-_revokeRole-bytes32-address-]] ==== `[.contract-item-name]#++_revokeRole++#++(bytes32 role, address account) → bool++` [.item-kind]#internal# -Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. +Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked. Internal function without access restriction. @@ -980,9 +1011,12 @@ May emit a {RoleRevoked} event. :getRoleMember: pass:normal[xref:#IAccessControlEnumerable-getRoleMember-bytes32-uint256-[`++getRoleMember++`]] :getRoleMemberCount: pass:normal[xref:#IAccessControlEnumerable-getRoleMemberCount-bytes32-[`++getRoleMemberCount++`]] +:getRoleMember-bytes32-uint256: pass:normal[xref:#IAccessControlEnumerable-getRoleMember-bytes32-uint256-[`++getRoleMember++`]] +:getRoleMemberCount-bytes32: pass:normal[xref:#IAccessControlEnumerable-getRoleMemberCount-bytes32-[`++getRoleMemberCount++`]] + [.contract] [[IAccessControlEnumerable]] -=== `++IAccessControlEnumerable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/extensions/IAccessControlEnumerable.sol[{github-icon},role=heading-link] +=== `++IAccessControlEnumerable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/extensions/IAccessControlEnumerable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1059,9 +1093,16 @@ together with {getRoleMember} to enumerate all bearers of a role. :_grantRole: pass:normal[xref:#AccessControlEnumerable-_grantRole-bytes32-address-[`++_grantRole++`]] :_revokeRole: pass:normal[xref:#AccessControlEnumerable-_revokeRole-bytes32-address-[`++_revokeRole++`]] +:supportsInterface-bytes4: pass:normal[xref:#AccessControlEnumerable-supportsInterface-bytes4-[`++supportsInterface++`]] +:getRoleMember-bytes32-uint256: pass:normal[xref:#AccessControlEnumerable-getRoleMember-bytes32-uint256-[`++getRoleMember++`]] +:getRoleMemberCount-bytes32: pass:normal[xref:#AccessControlEnumerable-getRoleMemberCount-bytes32-[`++getRoleMemberCount++`]] +:getRoleMembers-bytes32: pass:normal[xref:#AccessControlEnumerable-getRoleMembers-bytes32-[`++getRoleMembers++`]] +:_grantRole-bytes32-address: pass:normal[xref:#AccessControlEnumerable-_grantRole-bytes32-address-[`++_grantRole++`]] +:_revokeRole-bytes32-address: pass:normal[xref:#AccessControlEnumerable-_revokeRole-bytes32-address-[`++_revokeRole++`]] + [.contract] [[AccessControlEnumerable]] -=== `++AccessControlEnumerable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/extensions/AccessControlEnumerable.sol[{github-icon},role=heading-link] +=== `++AccessControlEnumerable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/extensions/AccessControlEnumerable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1222,9 +1263,20 @@ Overload {AccessControl-_revokeRole} to track enumerable memberships :rollbackDefaultAdminDelay: pass:normal[xref:#IAccessControlDefaultAdminRules-rollbackDefaultAdminDelay--[`++rollbackDefaultAdminDelay++`]] :defaultAdminDelayIncreaseWait: pass:normal[xref:#IAccessControlDefaultAdminRules-defaultAdminDelayIncreaseWait--[`++defaultAdminDelayIncreaseWait++`]] +:defaultAdmin-: pass:normal[xref:#IAccessControlDefaultAdminRules-defaultAdmin--[`++defaultAdmin++`]] +:pendingDefaultAdmin-: pass:normal[xref:#IAccessControlDefaultAdminRules-pendingDefaultAdmin--[`++pendingDefaultAdmin++`]] +:defaultAdminDelay-: pass:normal[xref:#IAccessControlDefaultAdminRules-defaultAdminDelay--[`++defaultAdminDelay++`]] +:pendingDefaultAdminDelay-: pass:normal[xref:#IAccessControlDefaultAdminRules-pendingDefaultAdminDelay--[`++pendingDefaultAdminDelay++`]] +:beginDefaultAdminTransfer-address: pass:normal[xref:#IAccessControlDefaultAdminRules-beginDefaultAdminTransfer-address-[`++beginDefaultAdminTransfer++`]] +:cancelDefaultAdminTransfer-: pass:normal[xref:#IAccessControlDefaultAdminRules-cancelDefaultAdminTransfer--[`++cancelDefaultAdminTransfer++`]] +:acceptDefaultAdminTransfer-: pass:normal[xref:#IAccessControlDefaultAdminRules-acceptDefaultAdminTransfer--[`++acceptDefaultAdminTransfer++`]] +:changeDefaultAdminDelay-uint48: pass:normal[xref:#IAccessControlDefaultAdminRules-changeDefaultAdminDelay-uint48-[`++changeDefaultAdminDelay++`]] +:rollbackDefaultAdminDelay-: pass:normal[xref:#IAccessControlDefaultAdminRules-rollbackDefaultAdminDelay--[`++rollbackDefaultAdminDelay++`]] +:defaultAdminDelayIncreaseWait-: pass:normal[xref:#IAccessControlDefaultAdminRules-defaultAdminDelayIncreaseWait--[`++defaultAdminDelayIncreaseWait++`]] + [.contract] [[IAccessControlDefaultAdminRules]] -=== `++IAccessControlDefaultAdminRules++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/extensions/IAccessControlDefaultAdminRules.sol[{github-icon},role=heading-link] +=== `++IAccessControlDefaultAdminRules++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/extensions/IAccessControlDefaultAdminRules.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1511,9 +1563,35 @@ NOTE: `schedule` can be 0 indicating there's no transfer scheduled. :_rollbackDefaultAdminDelay: pass:normal[xref:#AccessControlDefaultAdminRules-_rollbackDefaultAdminDelay--[`++_rollbackDefaultAdminDelay++`]] :_delayChangeWait: pass:normal[xref:#AccessControlDefaultAdminRules-_delayChangeWait-uint48-[`++_delayChangeWait++`]] +:constructor-uint48-address: pass:normal[xref:#AccessControlDefaultAdminRules-constructor-uint48-address-[`++constructor++`]] +:supportsInterface-bytes4: pass:normal[xref:#AccessControlDefaultAdminRules-supportsInterface-bytes4-[`++supportsInterface++`]] +:owner-: pass:normal[xref:#AccessControlDefaultAdminRules-owner--[`++owner++`]] +:grantRole-bytes32-address: pass:normal[xref:#AccessControlDefaultAdminRules-grantRole-bytes32-address-[`++grantRole++`]] +:revokeRole-bytes32-address: pass:normal[xref:#AccessControlDefaultAdminRules-revokeRole-bytes32-address-[`++revokeRole++`]] +:renounceRole-bytes32-address: pass:normal[xref:#AccessControlDefaultAdminRules-renounceRole-bytes32-address-[`++renounceRole++`]] +:_grantRole-bytes32-address: pass:normal[xref:#AccessControlDefaultAdminRules-_grantRole-bytes32-address-[`++_grantRole++`]] +:_revokeRole-bytes32-address: pass:normal[xref:#AccessControlDefaultAdminRules-_revokeRole-bytes32-address-[`++_revokeRole++`]] +:_setRoleAdmin-bytes32-bytes32: pass:normal[xref:#AccessControlDefaultAdminRules-_setRoleAdmin-bytes32-bytes32-[`++_setRoleAdmin++`]] +:defaultAdmin-: pass:normal[xref:#AccessControlDefaultAdminRules-defaultAdmin--[`++defaultAdmin++`]] +:pendingDefaultAdmin-: pass:normal[xref:#AccessControlDefaultAdminRules-pendingDefaultAdmin--[`++pendingDefaultAdmin++`]] +:defaultAdminDelay-: pass:normal[xref:#AccessControlDefaultAdminRules-defaultAdminDelay--[`++defaultAdminDelay++`]] +:pendingDefaultAdminDelay-: pass:normal[xref:#AccessControlDefaultAdminRules-pendingDefaultAdminDelay--[`++pendingDefaultAdminDelay++`]] +:defaultAdminDelayIncreaseWait-: pass:normal[xref:#AccessControlDefaultAdminRules-defaultAdminDelayIncreaseWait--[`++defaultAdminDelayIncreaseWait++`]] +:beginDefaultAdminTransfer-address: pass:normal[xref:#AccessControlDefaultAdminRules-beginDefaultAdminTransfer-address-[`++beginDefaultAdminTransfer++`]] +:_beginDefaultAdminTransfer-address: pass:normal[xref:#AccessControlDefaultAdminRules-_beginDefaultAdminTransfer-address-[`++_beginDefaultAdminTransfer++`]] +:cancelDefaultAdminTransfer-: pass:normal[xref:#AccessControlDefaultAdminRules-cancelDefaultAdminTransfer--[`++cancelDefaultAdminTransfer++`]] +:_cancelDefaultAdminTransfer-: pass:normal[xref:#AccessControlDefaultAdminRules-_cancelDefaultAdminTransfer--[`++_cancelDefaultAdminTransfer++`]] +:acceptDefaultAdminTransfer-: pass:normal[xref:#AccessControlDefaultAdminRules-acceptDefaultAdminTransfer--[`++acceptDefaultAdminTransfer++`]] +:_acceptDefaultAdminTransfer-: pass:normal[xref:#AccessControlDefaultAdminRules-_acceptDefaultAdminTransfer--[`++_acceptDefaultAdminTransfer++`]] +:changeDefaultAdminDelay-uint48: pass:normal[xref:#AccessControlDefaultAdminRules-changeDefaultAdminDelay-uint48-[`++changeDefaultAdminDelay++`]] +:_changeDefaultAdminDelay-uint48: pass:normal[xref:#AccessControlDefaultAdminRules-_changeDefaultAdminDelay-uint48-[`++_changeDefaultAdminDelay++`]] +:rollbackDefaultAdminDelay-: pass:normal[xref:#AccessControlDefaultAdminRules-rollbackDefaultAdminDelay--[`++rollbackDefaultAdminDelay++`]] +:_rollbackDefaultAdminDelay-: pass:normal[xref:#AccessControlDefaultAdminRules-_rollbackDefaultAdminDelay--[`++_rollbackDefaultAdminDelay++`]] +:_delayChangeWait-uint48: pass:normal[xref:#AccessControlDefaultAdminRules-_delayChangeWait-uint48-[`++_delayChangeWait++`]] + [.contract] [[AccessControlDefaultAdminRules]] -=== `++AccessControlDefaultAdminRules++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/extensions/AccessControlDefaultAdminRules.sol[{github-icon},role=heading-link] +=== `++AccessControlDefaultAdminRules++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/extensions/AccessControlDefaultAdminRules.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1932,9 +2010,11 @@ See {defaultAdminDelayIncreaseWait}. :canCall: pass:normal[xref:#IAuthority-canCall-address-address-bytes4-[`++canCall++`]] +:canCall-address-address-bytes4: pass:normal[xref:#IAuthority-canCall-address-address-bytes4-[`++canCall++`]] + [.contract] [[IAuthority]] -=== `++IAuthority++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/manager/IAuthority.sol[{github-icon},role=heading-link] +=== `++IAuthority++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/manager/IAuthority.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2009,9 +2089,39 @@ Returns true if the caller can invoke on a target the function identified by a f :hashOperation: pass:normal[xref:#IAccessManager-hashOperation-address-address-bytes-[`++hashOperation++`]] :updateAuthority: pass:normal[xref:#IAccessManager-updateAuthority-address-address-[`++updateAuthority++`]] +:canCall-address-address-bytes4: pass:normal[xref:#IAccessManager-canCall-address-address-bytes4-[`++canCall++`]] +:expiration-: pass:normal[xref:#IAccessManager-expiration--[`++expiration++`]] +:minSetback-: pass:normal[xref:#IAccessManager-minSetback--[`++minSetback++`]] +:isTargetClosed-address: pass:normal[xref:#IAccessManager-isTargetClosed-address-[`++isTargetClosed++`]] +:getTargetFunctionRole-address-bytes4: pass:normal[xref:#IAccessManager-getTargetFunctionRole-address-bytes4-[`++getTargetFunctionRole++`]] +:getTargetAdminDelay-address: pass:normal[xref:#IAccessManager-getTargetAdminDelay-address-[`++getTargetAdminDelay++`]] +:getRoleAdmin-uint64: pass:normal[xref:#IAccessManager-getRoleAdmin-uint64-[`++getRoleAdmin++`]] +:getRoleGuardian-uint64: pass:normal[xref:#IAccessManager-getRoleGuardian-uint64-[`++getRoleGuardian++`]] +:getRoleGrantDelay-uint64: pass:normal[xref:#IAccessManager-getRoleGrantDelay-uint64-[`++getRoleGrantDelay++`]] +:getAccess-uint64-address: pass:normal[xref:#IAccessManager-getAccess-uint64-address-[`++getAccess++`]] +:hasRole-uint64-address: pass:normal[xref:#IAccessManager-hasRole-uint64-address-[`++hasRole++`]] +:labelRole-uint64-string: pass:normal[xref:#IAccessManager-labelRole-uint64-string-[`++labelRole++`]] +:grantRole-uint64-address-uint32: pass:normal[xref:#IAccessManager-grantRole-uint64-address-uint32-[`++grantRole++`]] +:revokeRole-uint64-address: pass:normal[xref:#IAccessManager-revokeRole-uint64-address-[`++revokeRole++`]] +:renounceRole-uint64-address: pass:normal[xref:#IAccessManager-renounceRole-uint64-address-[`++renounceRole++`]] +:setRoleAdmin-uint64-uint64: pass:normal[xref:#IAccessManager-setRoleAdmin-uint64-uint64-[`++setRoleAdmin++`]] +:setRoleGuardian-uint64-uint64: pass:normal[xref:#IAccessManager-setRoleGuardian-uint64-uint64-[`++setRoleGuardian++`]] +:setGrantDelay-uint64-uint32: pass:normal[xref:#IAccessManager-setGrantDelay-uint64-uint32-[`++setGrantDelay++`]] +:setTargetFunctionRole-address-bytes4---uint64: pass:normal[xref:#IAccessManager-setTargetFunctionRole-address-bytes4---uint64-[`++setTargetFunctionRole++`]] +:setTargetAdminDelay-address-uint32: pass:normal[xref:#IAccessManager-setTargetAdminDelay-address-uint32-[`++setTargetAdminDelay++`]] +:setTargetClosed-address-bool: pass:normal[xref:#IAccessManager-setTargetClosed-address-bool-[`++setTargetClosed++`]] +:getSchedule-bytes32: pass:normal[xref:#IAccessManager-getSchedule-bytes32-[`++getSchedule++`]] +:getNonce-bytes32: pass:normal[xref:#IAccessManager-getNonce-bytes32-[`++getNonce++`]] +:schedule-address-bytes-uint48: pass:normal[xref:#IAccessManager-schedule-address-bytes-uint48-[`++schedule++`]] +:execute-address-bytes: pass:normal[xref:#IAccessManager-execute-address-bytes-[`++execute++`]] +:cancel-address-address-bytes: pass:normal[xref:#IAccessManager-cancel-address-address-bytes-[`++cancel++`]] +:consumeScheduledOp-address-bytes: pass:normal[xref:#IAccessManager-consumeScheduledOp-address-bytes-[`++consumeScheduledOp++`]] +:hashOperation-address-address-bytes: pass:normal[xref:#IAccessManager-hashOperation-address-address-bytes-[`++hashOperation++`]] +:updateAuthority-address-address: pass:normal[xref:#IAccessManager-updateAuthority-address-address-[`++updateAuthority++`]] + [.contract] [[IAccessManager]] -=== `++IAccessManager++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/manager/IAccessManager.sol[{github-icon},role=heading-link] +=== `++IAccessManager++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/manager/IAccessManager.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2583,9 +2693,51 @@ Admin delay for a given `target` will be updated to `delay` when `since` is reac :hashOperation: pass:normal[xref:#AccessManager-hashOperation-address-address-bytes-[`++hashOperation++`]] :updateAuthority: pass:normal[xref:#AccessManager-updateAuthority-address-address-[`++updateAuthority++`]] +:constructor-address: pass:normal[xref:#AccessManager-constructor-address-[`++constructor++`]] +:canCall-address-address-bytes4: pass:normal[xref:#AccessManager-canCall-address-address-bytes4-[`++canCall++`]] +:expiration-: pass:normal[xref:#AccessManager-expiration--[`++expiration++`]] +:minSetback-: pass:normal[xref:#AccessManager-minSetback--[`++minSetback++`]] +:isTargetClosed-address: pass:normal[xref:#AccessManager-isTargetClosed-address-[`++isTargetClosed++`]] +:getTargetFunctionRole-address-bytes4: pass:normal[xref:#AccessManager-getTargetFunctionRole-address-bytes4-[`++getTargetFunctionRole++`]] +:getTargetAdminDelay-address: pass:normal[xref:#AccessManager-getTargetAdminDelay-address-[`++getTargetAdminDelay++`]] +:getRoleAdmin-uint64: pass:normal[xref:#AccessManager-getRoleAdmin-uint64-[`++getRoleAdmin++`]] +:getRoleGuardian-uint64: pass:normal[xref:#AccessManager-getRoleGuardian-uint64-[`++getRoleGuardian++`]] +:getRoleGrantDelay-uint64: pass:normal[xref:#AccessManager-getRoleGrantDelay-uint64-[`++getRoleGrantDelay++`]] +:getAccess-uint64-address: pass:normal[xref:#AccessManager-getAccess-uint64-address-[`++getAccess++`]] +:hasRole-uint64-address: pass:normal[xref:#AccessManager-hasRole-uint64-address-[`++hasRole++`]] +:labelRole-uint64-string: pass:normal[xref:#AccessManager-labelRole-uint64-string-[`++labelRole++`]] +:grantRole-uint64-address-uint32: pass:normal[xref:#AccessManager-grantRole-uint64-address-uint32-[`++grantRole++`]] +:revokeRole-uint64-address: pass:normal[xref:#AccessManager-revokeRole-uint64-address-[`++revokeRole++`]] +:renounceRole-uint64-address: pass:normal[xref:#AccessManager-renounceRole-uint64-address-[`++renounceRole++`]] +:setRoleAdmin-uint64-uint64: pass:normal[xref:#AccessManager-setRoleAdmin-uint64-uint64-[`++setRoleAdmin++`]] +:setRoleGuardian-uint64-uint64: pass:normal[xref:#AccessManager-setRoleGuardian-uint64-uint64-[`++setRoleGuardian++`]] +:setGrantDelay-uint64-uint32: pass:normal[xref:#AccessManager-setGrantDelay-uint64-uint32-[`++setGrantDelay++`]] +:_grantRole-uint64-address-uint32-uint32: pass:normal[xref:#AccessManager-_grantRole-uint64-address-uint32-uint32-[`++_grantRole++`]] +:_revokeRole-uint64-address: pass:normal[xref:#AccessManager-_revokeRole-uint64-address-[`++_revokeRole++`]] +:_setRoleAdmin-uint64-uint64: pass:normal[xref:#AccessManager-_setRoleAdmin-uint64-uint64-[`++_setRoleAdmin++`]] +:_setRoleGuardian-uint64-uint64: pass:normal[xref:#AccessManager-_setRoleGuardian-uint64-uint64-[`++_setRoleGuardian++`]] +:_setGrantDelay-uint64-uint32: pass:normal[xref:#AccessManager-_setGrantDelay-uint64-uint32-[`++_setGrantDelay++`]] +:setTargetFunctionRole-address-bytes4---uint64: pass:normal[xref:#AccessManager-setTargetFunctionRole-address-bytes4---uint64-[`++setTargetFunctionRole++`]] +:_setTargetFunctionRole-address-bytes4-uint64: pass:normal[xref:#AccessManager-_setTargetFunctionRole-address-bytes4-uint64-[`++_setTargetFunctionRole++`]] +:setTargetAdminDelay-address-uint32: pass:normal[xref:#AccessManager-setTargetAdminDelay-address-uint32-[`++setTargetAdminDelay++`]] +:_setTargetAdminDelay-address-uint32: pass:normal[xref:#AccessManager-_setTargetAdminDelay-address-uint32-[`++_setTargetAdminDelay++`]] +:setTargetClosed-address-bool: pass:normal[xref:#AccessManager-setTargetClosed-address-bool-[`++setTargetClosed++`]] +:_setTargetClosed-address-bool: pass:normal[xref:#AccessManager-_setTargetClosed-address-bool-[`++_setTargetClosed++`]] +:getSchedule-bytes32: pass:normal[xref:#AccessManager-getSchedule-bytes32-[`++getSchedule++`]] +:getNonce-bytes32: pass:normal[xref:#AccessManager-getNonce-bytes32-[`++getNonce++`]] +:schedule-address-bytes-uint48: pass:normal[xref:#AccessManager-schedule-address-bytes-uint48-[`++schedule++`]] +:execute-address-bytes: pass:normal[xref:#AccessManager-execute-address-bytes-[`++execute++`]] +:cancel-address-address-bytes: pass:normal[xref:#AccessManager-cancel-address-address-bytes-[`++cancel++`]] +:consumeScheduledOp-address-bytes: pass:normal[xref:#AccessManager-consumeScheduledOp-address-bytes-[`++consumeScheduledOp++`]] +:_consumeScheduledOp-bytes32: pass:normal[xref:#AccessManager-_consumeScheduledOp-bytes32-[`++_consumeScheduledOp++`]] +:hashOperation-address-address-bytes: pass:normal[xref:#AccessManager-hashOperation-address-address-bytes-[`++hashOperation++`]] +:updateAuthority-address-address: pass:normal[xref:#AccessManager-updateAuthority-address-address-[`++updateAuthority++`]] +:ADMIN_ROLE-uint64: pass:normal[xref:#AccessManager-ADMIN_ROLE-uint64[`++ADMIN_ROLE++`]] +:PUBLIC_ROLE-uint64: pass:normal[xref:#AccessManager-PUBLIC_ROLE-uint64[`++PUBLIC_ROLE++`]] + [.contract] [[AccessManager]] -=== `++AccessManager++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/manager/AccessManager.sol[{github-icon},role=heading-link] +=== `++AccessManager++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/manager/AccessManager.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3184,9 +3336,13 @@ The identifier of the public role. Automatically granted to all addresses with n :setAuthority: pass:normal[xref:#IAccessManaged-setAuthority-address-[`++setAuthority++`]] :isConsumingScheduledOp: pass:normal[xref:#IAccessManaged-isConsumingScheduledOp--[`++isConsumingScheduledOp++`]] +:authority-: pass:normal[xref:#IAccessManaged-authority--[`++authority++`]] +:setAuthority-address: pass:normal[xref:#IAccessManaged-setAuthority-address-[`++setAuthority++`]] +:isConsumingScheduledOp-: pass:normal[xref:#IAccessManaged-isConsumingScheduledOp--[`++isConsumingScheduledOp++`]] + [.contract] [[IAccessManaged]] -=== `++IAccessManaged++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/manager/IAccessManaged.sol[{github-icon},role=heading-link] +=== `++IAccessManaged++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/manager/IAccessManaged.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3264,9 +3420,16 @@ Authority that manages this contract was updated. :_setAuthority: pass:normal[xref:#AccessManaged-_setAuthority-address-[`++_setAuthority++`]] :_checkCanCall: pass:normal[xref:#AccessManaged-_checkCanCall-address-bytes-[`++_checkCanCall++`]] +:constructor-address: pass:normal[xref:#AccessManaged-constructor-address-[`++constructor++`]] +:authority-: pass:normal[xref:#AccessManaged-authority--[`++authority++`]] +:setAuthority-address: pass:normal[xref:#AccessManaged-setAuthority-address-[`++setAuthority++`]] +:isConsumingScheduledOp-: pass:normal[xref:#AccessManaged-isConsumingScheduledOp--[`++isConsumingScheduledOp++`]] +:_setAuthority-address: pass:normal[xref:#AccessManaged-_setAuthority-address-[`++_setAuthority++`]] +:_checkCanCall-address-bytes: pass:normal[xref:#AccessManaged-_checkCanCall-address-bytes-[`++_checkCanCall++`]] + [.contract] [[AccessManaged]] -=== `++AccessManaged++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/manager/AccessManaged.sol[{github-icon},role=heading-link] +=== `++AccessManaged++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/manager/AccessManaged.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3392,9 +3555,11 @@ is less than 4 bytes long. :canCallWithDelay: pass:normal[xref:#AuthorityUtils-canCallWithDelay-address-address-address-bytes4-[`++canCallWithDelay++`]] +:canCallWithDelay-address-address-address-bytes4: pass:normal[xref:#AuthorityUtils-canCallWithDelay-address-address-address-bytes4-[`++canCallWithDelay++`]] + [.contract] [[AuthorityUtils]] -=== `++AuthorityUtils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/manager/AuthorityUtils.sol[{github-icon},role=heading-link] +=== `++AuthorityUtils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/access/manager/AuthorityUtils.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity diff --git a/docs/modules/api/pages/account.adoc b/docs/modules/api/pages/account.adoc index c5c7dcf65..5a96f4271 100644 --- a/docs/modules/api/pages/account.adoc +++ b/docs/modules/api/pages/account.adoc @@ -4,7 +4,7 @@ :xref-ERC4337Utils-packValidationData-bool-uint48-uint48-: xref:account.adoc#ERC4337Utils-packValidationData-bool-uint48-uint48- :xref-ERC4337Utils-combineValidationData-uint256-uint256-: xref:account.adoc#ERC4337Utils-combineValidationData-uint256-uint256- :xref-ERC4337Utils-getValidationData-uint256-: xref:account.adoc#ERC4337Utils-getValidationData-uint256- -:xref-ERC4337Utils-hash-struct-PackedUserOperation-address-uint256-: xref:account.adoc#ERC4337Utils-hash-struct-PackedUserOperation-address-uint256- +:xref-ERC4337Utils-hash-struct-PackedUserOperation-address-: xref:account.adoc#ERC4337Utils-hash-struct-PackedUserOperation-address- :xref-ERC4337Utils-factory-struct-PackedUserOperation-: xref:account.adoc#ERC4337Utils-factory-struct-PackedUserOperation- :xref-ERC4337Utils-factoryData-struct-PackedUserOperation-: xref:account.adoc#ERC4337Utils-factoryData-struct-PackedUserOperation- :xref-ERC4337Utils-verificationGasLimit-struct-PackedUserOperation-: xref:account.adoc#ERC4337Utils-verificationGasLimit-struct-PackedUserOperation- @@ -16,6 +16,8 @@ :xref-ERC4337Utils-paymasterVerificationGasLimit-struct-PackedUserOperation-: xref:account.adoc#ERC4337Utils-paymasterVerificationGasLimit-struct-PackedUserOperation- :xref-ERC4337Utils-paymasterPostOpGasLimit-struct-PackedUserOperation-: xref:account.adoc#ERC4337Utils-paymasterPostOpGasLimit-struct-PackedUserOperation- :xref-ERC4337Utils-paymasterData-struct-PackedUserOperation-: xref:account.adoc#ERC4337Utils-paymasterData-struct-PackedUserOperation- +:xref-ERC4337Utils-ENTRYPOINT_V07-contract-IEntryPoint: xref:account.adoc#ERC4337Utils-ENTRYPOINT_V07-contract-IEntryPoint +:xref-ERC4337Utils-ENTRYPOINT_V08-contract-IEntryPoint: xref:account.adoc#ERC4337Utils-ENTRYPOINT_V08-contract-IEntryPoint :xref-ERC4337Utils-SIG_VALIDATION_SUCCESS-uint256: xref:account.adoc#ERC4337Utils-SIG_VALIDATION_SUCCESS-uint256 :xref-ERC4337Utils-SIG_VALIDATION_FAILED-uint256: xref:account.adoc#ERC4337Utils-SIG_VALIDATION_FAILED-uint256 :PackedUserOperation: pass:normal[xref:interfaces.adoc#PackedUserOperation[`PackedUserOperation`]] @@ -64,6 +66,8 @@ This directory includes contracts to build accounts for ERC-4337. == Utilities +:ENTRYPOINT_V07: pass:normal[xref:#ERC4337Utils-ENTRYPOINT_V07-contract-IEntryPoint[`++ENTRYPOINT_V07++`]] +:ENTRYPOINT_V08: pass:normal[xref:#ERC4337Utils-ENTRYPOINT_V08-contract-IEntryPoint[`++ENTRYPOINT_V08++`]] :SIG_VALIDATION_SUCCESS: pass:normal[xref:#ERC4337Utils-SIG_VALIDATION_SUCCESS-uint256[`++SIG_VALIDATION_SUCCESS++`]] :SIG_VALIDATION_FAILED: pass:normal[xref:#ERC4337Utils-SIG_VALIDATION_FAILED-uint256[`++SIG_VALIDATION_FAILED++`]] :parseValidationData: pass:normal[xref:#ERC4337Utils-parseValidationData-uint256-[`++parseValidationData++`]] @@ -71,7 +75,7 @@ This directory includes contracts to build accounts for ERC-4337. :packValidationData: pass:normal[xref:#ERC4337Utils-packValidationData-bool-uint48-uint48-[`++packValidationData++`]] :combineValidationData: pass:normal[xref:#ERC4337Utils-combineValidationData-uint256-uint256-[`++combineValidationData++`]] :getValidationData: pass:normal[xref:#ERC4337Utils-getValidationData-uint256-[`++getValidationData++`]] -:hash: pass:normal[xref:#ERC4337Utils-hash-struct-PackedUserOperation-address-uint256-[`++hash++`]] +:hash: pass:normal[xref:#ERC4337Utils-hash-struct-PackedUserOperation-address-[`++hash++`]] :factory: pass:normal[xref:#ERC4337Utils-factory-struct-PackedUserOperation-[`++factory++`]] :factoryData: pass:normal[xref:#ERC4337Utils-factoryData-struct-PackedUserOperation-[`++factoryData++`]] :verificationGasLimit: pass:normal[xref:#ERC4337Utils-verificationGasLimit-struct-PackedUserOperation-[`++verificationGasLimit++`]] @@ -84,9 +88,27 @@ This directory includes contracts to build accounts for ERC-4337. :paymasterPostOpGasLimit: pass:normal[xref:#ERC4337Utils-paymasterPostOpGasLimit-struct-PackedUserOperation-[`++paymasterPostOpGasLimit++`]] :paymasterData: pass:normal[xref:#ERC4337Utils-paymasterData-struct-PackedUserOperation-[`++paymasterData++`]] +:parseValidationData-uint256: pass:normal[xref:#ERC4337Utils-parseValidationData-uint256-[`++parseValidationData++`]] +:packValidationData-address-uint48-uint48: pass:normal[xref:#ERC4337Utils-packValidationData-address-uint48-uint48-[`++packValidationData++`]] +:packValidationData-bool-uint48-uint48: pass:normal[xref:#ERC4337Utils-packValidationData-bool-uint48-uint48-[`++packValidationData++`]] +:combineValidationData-uint256-uint256: pass:normal[xref:#ERC4337Utils-combineValidationData-uint256-uint256-[`++combineValidationData++`]] +:getValidationData-uint256: pass:normal[xref:#ERC4337Utils-getValidationData-uint256-[`++getValidationData++`]] +:hash-struct-PackedUserOperation-address: pass:normal[xref:#ERC4337Utils-hash-struct-PackedUserOperation-address-[`++hash++`]] +:factory-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-factory-struct-PackedUserOperation-[`++factory++`]] +:factoryData-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-factoryData-struct-PackedUserOperation-[`++factoryData++`]] +:verificationGasLimit-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-verificationGasLimit-struct-PackedUserOperation-[`++verificationGasLimit++`]] +:callGasLimit-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-callGasLimit-struct-PackedUserOperation-[`++callGasLimit++`]] +:maxPriorityFeePerGas-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-maxPriorityFeePerGas-struct-PackedUserOperation-[`++maxPriorityFeePerGas++`]] +:maxFeePerGas-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-maxFeePerGas-struct-PackedUserOperation-[`++maxFeePerGas++`]] +:gasPrice-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-gasPrice-struct-PackedUserOperation-[`++gasPrice++`]] +:paymaster-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-paymaster-struct-PackedUserOperation-[`++paymaster++`]] +:paymasterVerificationGasLimit-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-paymasterVerificationGasLimit-struct-PackedUserOperation-[`++paymasterVerificationGasLimit++`]] +:paymasterPostOpGasLimit-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-paymasterPostOpGasLimit-struct-PackedUserOperation-[`++paymasterPostOpGasLimit++`]] +:paymasterData-struct-PackedUserOperation: pass:normal[xref:#ERC4337Utils-paymasterData-struct-PackedUserOperation-[`++paymasterData++`]] + [.contract] [[ERC4337Utils]] -=== `++ERC4337Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/account/utils/draft-ERC4337Utils.sol[{github-icon},role=heading-link] +=== `++ERC4337Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/account/utils/draft-ERC4337Utils.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -105,7 +127,7 @@ See https://eips.ethereum.org/EIPS/eip-4337[ERC-4337]. * {xref-ERC4337Utils-packValidationData-bool-uint48-uint48-}[`++packValidationData(sigSuccess, validAfter, validUntil)++`] * {xref-ERC4337Utils-combineValidationData-uint256-uint256-}[`++combineValidationData(validationData1, validationData2)++`] * {xref-ERC4337Utils-getValidationData-uint256-}[`++getValidationData(validationData)++`] -* {xref-ERC4337Utils-hash-struct-PackedUserOperation-address-uint256-}[`++hash(self, entrypoint, chainid)++`] +* {xref-ERC4337Utils-hash-struct-PackedUserOperation-address-}[`++hash(self, entrypoint)++`] * {xref-ERC4337Utils-factory-struct-PackedUserOperation-}[`++factory(self)++`] * {xref-ERC4337Utils-factoryData-struct-PackedUserOperation-}[`++factoryData(self)++`] * {xref-ERC4337Utils-verificationGasLimit-struct-PackedUserOperation-}[`++verificationGasLimit(self)++`] @@ -123,6 +145,8 @@ See https://eips.ethereum.org/EIPS/eip-4337[ERC-4337]. [.contract-index] .Internal Variables -- +* {xref-ERC4337Utils-ENTRYPOINT_V07-contract-IEntryPoint}[`++contract IEntryPoint constant ENTRYPOINT_V07++`] +* {xref-ERC4337Utils-ENTRYPOINT_V08-contract-IEntryPoint}[`++contract IEntryPoint constant ENTRYPOINT_V08++`] * {xref-ERC4337Utils-SIG_VALIDATION_SUCCESS-uint256}[`++uint256 constant SIG_VALIDATION_SUCCESS++`] * {xref-ERC4337Utils-SIG_VALIDATION_FAILED-uint256}[`++uint256 constant SIG_VALIDATION_FAILED++`] @@ -162,10 +186,10 @@ the `validAfter` is the maximum and the `validUntil` is the minimum of both. Returns the aggregator of the `validationData` and whether it is out of time range. [.contract-item] -[[ERC4337Utils-hash-struct-PackedUserOperation-address-uint256-]] -==== `[.contract-item-name]#++hash++#++(struct PackedUserOperation self, address entrypoint, uint256 chainid) → bytes32++` [.item-kind]#internal# +[[ERC4337Utils-hash-struct-PackedUserOperation-address-]] +==== `[.contract-item-name]#++hash++#++(struct PackedUserOperation self, address entrypoint) → bytes32++` [.item-kind]#internal# -Computes the hash of a user operation for a given entrypoint and chainid. +Get the hash of a user operation for a given entrypoint [.contract-item] [[ERC4337Utils-factory-struct-PackedUserOperation-]] @@ -233,6 +257,18 @@ Returns the third section of `paymasterAndData` from the {PackedUserOperation}. Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}. +[.contract-item] +[[ERC4337Utils-ENTRYPOINT_V07-contract-IEntryPoint]] +==== `contract IEntryPoint [.contract-item-name]#++ENTRYPOINT_V07++#` [.item-kind]#internal constant# + +Address of the entrypoint v0.7.0 + +[.contract-item] +[[ERC4337Utils-ENTRYPOINT_V08-contract-IEntryPoint]] +==== `contract IEntryPoint [.contract-item-name]#++ENTRYPOINT_V08++#` [.item-kind]#internal constant# + +Address of the entrypoint v0.8.0 + [.contract-item] [[ERC4337Utils-SIG_VALIDATION_SUCCESS-uint256]] ==== `uint256 [.contract-item-name]#++SIG_VALIDATION_SUCCESS++#` [.item-kind]#internal constant# @@ -270,9 +306,21 @@ For simulation purposes, validateUserOp (and validatePaymasterUserOp) must retur :encodeBatch: pass:normal[xref:#ERC7579Utils-encodeBatch-struct-Execution---[`++encodeBatch++`]] :decodeBatch: pass:normal[xref:#ERC7579Utils-decodeBatch-bytes-[`++decodeBatch++`]] +:execSingle-bytes-ExecType: pass:normal[xref:#ERC7579Utils-execSingle-bytes-ExecType-[`++execSingle++`]] +:execBatch-bytes-ExecType: pass:normal[xref:#ERC7579Utils-execBatch-bytes-ExecType-[`++execBatch++`]] +:execDelegateCall-bytes-ExecType: pass:normal[xref:#ERC7579Utils-execDelegateCall-bytes-ExecType-[`++execDelegateCall++`]] +:encodeMode-CallType-ExecType-ModeSelector-ModePayload: pass:normal[xref:#ERC7579Utils-encodeMode-CallType-ExecType-ModeSelector-ModePayload-[`++encodeMode++`]] +:decodeMode-Mode: pass:normal[xref:#ERC7579Utils-decodeMode-Mode-[`++decodeMode++`]] +:encodeSingle-address-uint256-bytes: pass:normal[xref:#ERC7579Utils-encodeSingle-address-uint256-bytes-[`++encodeSingle++`]] +:decodeSingle-bytes: pass:normal[xref:#ERC7579Utils-decodeSingle-bytes-[`++decodeSingle++`]] +:encodeDelegate-address-bytes: pass:normal[xref:#ERC7579Utils-encodeDelegate-address-bytes-[`++encodeDelegate++`]] +:decodeDelegate-bytes: pass:normal[xref:#ERC7579Utils-decodeDelegate-bytes-[`++decodeDelegate++`]] +:encodeBatch-struct-Execution--: pass:normal[xref:#ERC7579Utils-encodeBatch-struct-Execution---[`++encodeBatch++`]] +:decodeBatch-bytes: pass:normal[xref:#ERC7579Utils-decodeBatch-bytes-[`++decodeBatch++`]] + [.contract] [[ERC7579Utils]] -=== `++ERC7579Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/account/utils/draft-ERC7579Utils.sol[{github-icon},role=heading-link] +=== `++ERC7579Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/account/utils/draft-ERC7579Utils.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity diff --git a/docs/modules/api/pages/finance.adoc b/docs/modules/api/pages/finance.adoc index 0e3861eb8..40d44d873 100644 --- a/docs/modules/api/pages/finance.adoc +++ b/docs/modules/api/pages/finance.adoc @@ -56,9 +56,24 @@ This directory includes primitives for financial systems: :vestedAmount: pass:normal[xref:#VestingWallet-vestedAmount-address-uint64-[`++vestedAmount++`]] :_vestingSchedule: pass:normal[xref:#VestingWallet-_vestingSchedule-uint256-uint64-[`++_vestingSchedule++`]] +:constructor-address-uint64-uint64: pass:normal[xref:#VestingWallet-constructor-address-uint64-uint64-[`++constructor++`]] +:receive-: pass:normal[xref:#VestingWallet-receive--[`++receive++`]] +:start-: pass:normal[xref:#VestingWallet-start--[`++start++`]] +:duration-: pass:normal[xref:#VestingWallet-duration--[`++duration++`]] +:end-: pass:normal[xref:#VestingWallet-end--[`++end++`]] +:released-: pass:normal[xref:#VestingWallet-released--[`++released++`]] +:released-address: pass:normal[xref:#VestingWallet-released-address-[`++released++`]] +:releasable-: pass:normal[xref:#VestingWallet-releasable--[`++releasable++`]] +:releasable-address: pass:normal[xref:#VestingWallet-releasable-address-[`++releasable++`]] +:release-: pass:normal[xref:#VestingWallet-release--[`++release++`]] +:release-address: pass:normal[xref:#VestingWallet-release-address-[`++release++`]] +:vestedAmount-uint64: pass:normal[xref:#VestingWallet-vestedAmount-uint64-[`++vestedAmount++`]] +:vestedAmount-address-uint64: pass:normal[xref:#VestingWallet-vestedAmount-address-uint64-[`++vestedAmount++`]] +:_vestingSchedule-uint256-uint64: pass:normal[xref:#VestingWallet-_vestingSchedule-uint256-uint64-[`++_vestingSchedule++`]] + [.contract] [[VestingWallet]] -=== `++VestingWallet++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/finance/VestingWallet.sol[{github-icon},role=heading-link] +=== `++VestingWallet++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/finance/VestingWallet.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -72,7 +87,7 @@ Any assets transferred to this contract will follow the vesting schedule as if t Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly) be immediately releasable. -By setting the duration to 0, one can configure this contract to behave like an asset timelock that hold tokens for +By setting the duration to 0, one can configure this contract to behave like an asset timelock that holds tokens for a beneficiary until a specified time. NOTE: Since the wallet is {Ownable}, and ownership can be transferred, it is possible to sell unvested tokens. diff --git a/docs/modules/api/pages/governance.adoc b/docs/modules/api/pages/governance.adoc index 9cddbf4de..a5f4a0fa9 100644 --- a/docs/modules/api/pages/governance.adoc +++ b/docs/modules/api/pages/governance.adoc @@ -1,12 +1,13 @@ :github-icon: pass:[] :Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] :GovernorVotes: pass:normal[xref:governance.adoc#GovernorVotes[`GovernorVotes`]] -:ERC20Votes: pass:normal[xref:token/ERC20.adoc#ERC20Votes[`ERC20Votes`]] -:ERC721Votes: pass:normal[xref:token/ERC721.adoc#ERC721Votes[`ERC721Votes`]] +:IVotes: pass:normal[xref:governance.adoc#IVotes[`IVotes`]] :GovernorVotesQuorumFraction: pass:normal[xref:governance.adoc#GovernorVotesQuorumFraction[`GovernorVotesQuorumFraction`]] +:GovernorVotesSuperQuorumFraction: pass:normal[xref:governance.adoc#GovernorVotesSuperQuorumFraction[`GovernorVotesSuperQuorumFraction`]] :GovernorCountingSimple: pass:normal[xref:governance.adoc#GovernorCountingSimple[`GovernorCountingSimple`]] :GovernorCountingFractional: pass:normal[xref:governance.adoc#GovernorCountingFractional[`GovernorCountingFractional`]] :GovernorCountingOverridable: pass:normal[xref:governance.adoc#GovernorCountingOverridable[`GovernorCountingOverridable`]] +:VotesExtended: pass:normal[xref:governance.adoc#VotesExtended[`VotesExtended`]] :GovernorTimelockAccess: pass:normal[xref:governance.adoc#GovernorTimelockAccess[`GovernorTimelockAccess`]] :AccessManager: pass:normal[xref:access.adoc#AccessManager[`AccessManager`]] :GovernorTimelockControl: pass:normal[xref:governance.adoc#GovernorTimelockControl[`GovernorTimelockControl`]] @@ -15,12 +16,16 @@ :GovernorStorage: pass:normal[xref:governance.adoc#GovernorStorage[`GovernorStorage`]] :GovernorSettings: pass:normal[xref:governance.adoc#GovernorSettings[`GovernorSettings`]] :GovernorPreventLateQuorum: pass:normal[xref:governance.adoc#GovernorPreventLateQuorum[`GovernorPreventLateQuorum`]] +:GovernorProposalGuardian: pass:normal[xref:governance.adoc#GovernorProposalGuardian[`GovernorProposalGuardian`]] +:GovernorSuperQuorum: pass:normal[xref:governance.adoc#GovernorSuperQuorum[`GovernorSuperQuorum`]] +:Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] :Governor-_cancel: pass:normal[xref:governance.adoc#Governor-_cancel-address---uint256---bytes---bytes32-[`Governor._cancel`]] :Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] :xref-IGovernor-name--: xref:governance.adoc#IGovernor-name-- :xref-IGovernor-version--: xref:governance.adoc#IGovernor-version-- :xref-IGovernor-COUNTING_MODE--: xref:governance.adoc#IGovernor-COUNTING_MODE-- :xref-IGovernor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#IGovernor-hashProposal-address---uint256---bytes---bytes32- +:xref-IGovernor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#IGovernor-getProposalId-address---uint256---bytes---bytes32- :xref-IGovernor-state-uint256-: xref:governance.adoc#IGovernor-state-uint256- :xref-IGovernor-proposalThreshold--: xref:governance.adoc#IGovernor-proposalThreshold-- :xref-IGovernor-proposalSnapshot-uint256-: xref:governance.adoc#IGovernor-proposalSnapshot-uint256- @@ -55,7 +60,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -68,6 +72,7 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :IERC6372-clock: pass:normal[xref:interfaces.adoc#IERC6372-clock--[`IERC6372.clock`]] :ERC20Votes: pass:normal[xref:token/ERC20.adoc#ERC20Votes[`ERC20Votes`]] :ERC20Votes: pass:normal[xref:token/ERC20.adoc#ERC20Votes[`ERC20Votes`]] @@ -82,6 +87,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- :xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- @@ -121,6 +127,7 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- :xref-Governor-clock--: xref:governance.adoc#Governor-clock-- :xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- :xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- @@ -148,7 +155,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -161,12 +167,14 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- :GovernorSettings: pass:normal[xref:governance.adoc#GovernorSettings[`GovernorSettings`]] :IERC165-supportsInterface: pass:normal[xref:utils.adoc#IERC165-supportsInterface-bytes4-[`IERC165.supportsInterface`]] :IGovernor-name: pass:normal[xref:governance.adoc#IGovernor-name--[`IGovernor.name`]] :IGovernor-version: pass:normal[xref:governance.adoc#IGovernor-version--[`IGovernor.version`]] :IGovernor-hashProposal: pass:normal[xref:governance.adoc#IGovernor-hashProposal-address---uint256---bytes---bytes32-[`IGovernor.hashProposal`]] +:IGovernor-getProposalId: pass:normal[xref:governance.adoc#IGovernor-getProposalId-address---uint256---bytes---bytes32-[`IGovernor.getProposalId`]] :IGovernor-state: pass:normal[xref:governance.adoc#IGovernor-state-uint256-[`IGovernor.state`]] :IGovernor-proposalThreshold: pass:normal[xref:governance.adoc#IGovernor-proposalThreshold--[`IGovernor.proposalThreshold`]] :IGovernor-proposalSnapshot: pass:normal[xref:governance.adoc#IGovernor-proposalSnapshot-uint256-[`IGovernor.proposalSnapshot`]] @@ -208,6 +216,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- :xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- @@ -244,6 +253,7 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- :xref-Governor-clock--: xref:governance.adoc#Governor-clock-- :xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- :xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- @@ -269,7 +279,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -282,6 +291,7 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- :IGovernor-COUNTING_MODE: pass:normal[xref:governance.adoc#IGovernor-COUNTING_MODE--[`IGovernor.COUNTING_MODE`]] :IGovernor-hasVoted: pass:normal[xref:governance.adoc#IGovernor-hasVoted-uint256-address-[`IGovernor.hasVoted`]] @@ -303,6 +313,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- :xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- @@ -339,6 +350,7 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- :xref-Governor-clock--: xref:governance.adoc#Governor-clock-- :xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- :xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- @@ -365,7 +377,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -378,6 +389,7 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- :xref-GovernorCountingFractional-VOTE_TYPE_FRACTIONAL-uint8: xref:governance.adoc#GovernorCountingFractional-VOTE_TYPE_FRACTIONAL-uint8 :IGovernor-COUNTING_MODE: pass:normal[xref:governance.adoc#IGovernor-COUNTING_MODE--[`IGovernor.COUNTING_MODE`]] @@ -387,6 +399,116 @@ :Governor-_countVote: pass:normal[xref:governance.adoc#Governor-_countVote-uint256-address-uint8-uint256-bytes-[`Governor._countVote`]] :GovernorCountingSimple: pass:normal[xref:governance.adoc#GovernorCountingSimple[`GovernorCountingSimple`]] :Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] +:VotesExtended: pass:normal[xref:governance.adoc#VotesExtended[`VotesExtended`]] +:xref-GovernorCountingOverridable-COUNTING_MODE--: xref:governance.adoc#GovernorCountingOverridable-COUNTING_MODE-- +:xref-GovernorCountingOverridable-hasVoted-uint256-address-: xref:governance.adoc#GovernorCountingOverridable-hasVoted-uint256-address- +:xref-GovernorCountingOverridable-hasVotedOverride-uint256-address-: xref:governance.adoc#GovernorCountingOverridable-hasVotedOverride-uint256-address- +:xref-GovernorCountingOverridable-proposalVotes-uint256-: xref:governance.adoc#GovernorCountingOverridable-proposalVotes-uint256- +:xref-GovernorCountingOverridable-_quorumReached-uint256-: xref:governance.adoc#GovernorCountingOverridable-_quorumReached-uint256- +:xref-GovernorCountingOverridable-_voteSucceeded-uint256-: xref:governance.adoc#GovernorCountingOverridable-_voteSucceeded-uint256- +:xref-GovernorCountingOverridable-_countVote-uint256-address-uint8-uint256-bytes-: xref:governance.adoc#GovernorCountingOverridable-_countVote-uint256-address-uint8-uint256-bytes- +:xref-GovernorCountingOverridable-_countOverride-uint256-address-uint8-: xref:governance.adoc#GovernorCountingOverridable-_countOverride-uint256-address-uint8- +:xref-GovernorCountingOverridable-_castOverride-uint256-address-uint8-string-: xref:governance.adoc#GovernorCountingOverridable-_castOverride-uint256-address-uint8-string- +:xref-GovernorCountingOverridable-castOverrideVote-uint256-uint8-string-: xref:governance.adoc#GovernorCountingOverridable-castOverrideVote-uint256-uint8-string- +:xref-GovernorCountingOverridable-castOverrideVoteBySig-uint256-uint8-address-string-bytes-: xref:governance.adoc#GovernorCountingOverridable-castOverrideVoteBySig-uint256-uint8-address-string-bytes- +:xref-GovernorCountingOverridable-OVERRIDE_BALLOT_TYPEHASH-bytes32: xref:governance.adoc#GovernorCountingOverridable-OVERRIDE_BALLOT_TYPEHASH-bytes32 +:xref-GovernorVotes-token--: xref:governance.adoc#GovernorVotes-token-- +:xref-GovernorVotes-clock--: xref:governance.adoc#GovernorVotes-clock-- +:xref-GovernorVotes-CLOCK_MODE--: xref:governance.adoc#GovernorVotes-CLOCK_MODE-- +:xref-GovernorVotes-_getVotes-address-uint256-bytes-: xref:governance.adoc#GovernorVotes-_getVotes-address-uint256-bytes- +:xref-Governor-receive--: xref:governance.adoc#Governor-receive-- +:xref-Governor-supportsInterface-bytes4-: xref:governance.adoc#Governor-supportsInterface-bytes4- +:xref-Governor-name--: xref:governance.adoc#Governor-name-- +:xref-Governor-version--: xref:governance.adoc#Governor-version-- +:xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- +:xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- +:xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- +:xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- +:xref-Governor-proposalDeadline-uint256-: xref:governance.adoc#Governor-proposalDeadline-uint256- +:xref-Governor-proposalProposer-uint256-: xref:governance.adoc#Governor-proposalProposer-uint256- +:xref-Governor-proposalEta-uint256-: xref:governance.adoc#Governor-proposalEta-uint256- +:xref-Governor-proposalNeedsQueuing-uint256-: xref:governance.adoc#Governor-proposalNeedsQueuing-uint256- +:xref-Governor-_checkGovernance--: xref:governance.adoc#Governor-_checkGovernance-- +:xref-Governor-_tallyUpdated-uint256-: xref:governance.adoc#Governor-_tallyUpdated-uint256- +:xref-Governor-_defaultParams--: xref:governance.adoc#Governor-_defaultParams-- +:xref-Governor-propose-address---uint256---bytes---string-: xref:governance.adoc#Governor-propose-address---uint256---bytes---string- +:xref-Governor-_propose-address---uint256---bytes---string-address-: xref:governance.adoc#Governor-_propose-address---uint256---bytes---string-address- +:xref-Governor-queue-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-queue-address---uint256---bytes---bytes32- +:xref-Governor-_queueOperations-uint256-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_queueOperations-uint256-address---uint256---bytes---bytes32- +:xref-Governor-execute-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-execute-address---uint256---bytes---bytes32- +:xref-Governor-_executeOperations-uint256-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_executeOperations-uint256-address---uint256---bytes---bytes32- +:xref-Governor-cancel-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-cancel-address---uint256---bytes---bytes32- +:xref-Governor-_cancel-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_cancel-address---uint256---bytes---bytes32- +:xref-Governor-getVotes-address-uint256-: xref:governance.adoc#Governor-getVotes-address-uint256- +:xref-Governor-getVotesWithParams-address-uint256-bytes-: xref:governance.adoc#Governor-getVotesWithParams-address-uint256-bytes- +:xref-Governor-castVote-uint256-uint8-: xref:governance.adoc#Governor-castVote-uint256-uint8- +:xref-Governor-castVoteWithReason-uint256-uint8-string-: xref:governance.adoc#Governor-castVoteWithReason-uint256-uint8-string- +:xref-Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes-: xref:governance.adoc#Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes- +:xref-Governor-castVoteBySig-uint256-uint8-address-bytes-: xref:governance.adoc#Governor-castVoteBySig-uint256-uint8-address-bytes- +:xref-Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-: xref:governance.adoc#Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes- +:xref-Governor-_castVote-uint256-address-uint8-string-: xref:governance.adoc#Governor-_castVote-uint256-address-uint8-string- +:xref-Governor-_castVote-uint256-address-uint8-string-bytes-: xref:governance.adoc#Governor-_castVote-uint256-address-uint8-string-bytes- +:xref-Governor-relay-address-uint256-bytes-: xref:governance.adoc#Governor-relay-address-uint256-bytes- +:xref-Governor-_executor--: xref:governance.adoc#Governor-_executor-- +:xref-Governor-onERC721Received-address-address-uint256-bytes-: xref:governance.adoc#Governor-onERC721Received-address-address-uint256-bytes- +:xref-Governor-onERC1155Received-address-address-uint256-uint256-bytes-: xref:governance.adoc#Governor-onERC1155Received-address-address-uint256-uint256-bytes- +:xref-Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes-: xref:governance.adoc#Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes- +:xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- +:xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- +:xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- +:xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- +:xref-Governor-votingPeriod--: xref:governance.adoc#Governor-votingPeriod-- +:xref-Governor-quorum-uint256-: xref:governance.adoc#Governor-quorum-uint256- +:xref-Governor-BALLOT_TYPEHASH-bytes32: xref:governance.adoc#Governor-BALLOT_TYPEHASH-bytes32 +:xref-Governor-EXTENDED_BALLOT_TYPEHASH-bytes32: xref:governance.adoc#Governor-EXTENDED_BALLOT_TYPEHASH-bytes32 +:xref-Nonces-nonces-address-: xref:utils.adoc#Nonces-nonces-address- +:xref-Nonces-_useNonce-address-: xref:utils.adoc#Nonces-_useNonce-address- +:xref-Nonces-_useCheckedNonce-address-uint256-: xref:utils.adoc#Nonces-_useCheckedNonce-address-uint256- +:xref-EIP712-_domainSeparatorV4--: xref:utils.adoc#EIP712-_domainSeparatorV4-- +:xref-EIP712-_hashTypedDataV4-bytes32-: xref:utils.adoc#EIP712-_hashTypedDataV4-bytes32- +:xref-EIP712-eip712Domain--: xref:utils.adoc#EIP712-eip712Domain-- +:xref-EIP712-_EIP712Name--: xref:utils.adoc#EIP712-_EIP712Name-- +:xref-EIP712-_EIP712Version--: xref:utils.adoc#EIP712-_EIP712Version-- +:xref-GovernorCountingOverridable-VoteReduced-address-uint256-uint8-uint256-: xref:governance.adoc#GovernorCountingOverridable-VoteReduced-address-uint256-uint8-uint256- +:xref-GovernorCountingOverridable-OverrideVoteCast-address-uint256-uint8-uint256-string-: xref:governance.adoc#GovernorCountingOverridable-OverrideVoteCast-address-uint256-uint8-uint256-string- +:xref-IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string-: xref:governance.adoc#IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string- +:xref-IGovernor-ProposalQueued-uint256-uint256-: xref:governance.adoc#IGovernor-ProposalQueued-uint256-uint256- +:xref-IGovernor-ProposalExecuted-uint256-: xref:governance.adoc#IGovernor-ProposalExecuted-uint256- +:xref-IGovernor-ProposalCanceled-uint256-: xref:governance.adoc#IGovernor-ProposalCanceled-uint256- +:xref-IGovernor-VoteCast-address-uint256-uint8-uint256-string-: xref:governance.adoc#IGovernor-VoteCast-address-uint256-uint8-uint256-string- +:xref-IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes-: xref:governance.adoc#IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes- +:xref-IERC5267-EIP712DomainChanged--: xref:interfaces.adoc#IERC5267-EIP712DomainChanged-- +:xref-GovernorCountingOverridable-GovernorAlreadyOverriddenVote-address-: xref:governance.adoc#GovernorCountingOverridable-GovernorAlreadyOverriddenVote-address- +:xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- +:xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- +:xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- +:xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- +:xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- +:xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- +:xref-IGovernor-GovernorInvalidVotingPeriod-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidVotingPeriod-uint256- +:xref-IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256- +:xref-IGovernor-GovernorRestrictedProposer-address-: xref:governance.adoc#IGovernor-GovernorRestrictedProposer-address- +:xref-IGovernor-GovernorInvalidVoteType--: xref:governance.adoc#IGovernor-GovernorInvalidVoteType-- +:xref-IGovernor-GovernorInvalidVoteParams--: xref:governance.adoc#IGovernor-GovernorInvalidVoteParams-- +:xref-IGovernor-GovernorQueueNotImplemented--: xref:governance.adoc#IGovernor-GovernorQueueNotImplemented-- +:xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- +:xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- +:xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- +:xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- +:IGovernor-COUNTING_MODE: pass:normal[xref:governance.adoc#IGovernor-COUNTING_MODE--[`IGovernor.COUNTING_MODE`]] +:IGovernor-hasVoted: pass:normal[xref:governance.adoc#IGovernor-hasVoted-uint256-address-[`IGovernor.hasVoted`]] +:Governor-_quorumReached: pass:normal[xref:governance.adoc#Governor-_quorumReached-uint256-[`Governor._quorumReached`]] +:Governor-_voteSucceeded: pass:normal[xref:governance.adoc#Governor-_voteSucceeded-uint256-[`Governor._voteSucceeded`]] +:Governor-_countVote: pass:normal[xref:governance.adoc#Governor-_countVote-uint256-address-uint8-uint256-bytes-[`Governor._countVote`]] +:Governor-_castVote: pass:normal[xref:governance.adoc#Governor-_castVote-uint256-address-uint8-string-bytes-[`Governor._castVote`]] +:IGovernor-VoteCast: pass:normal[xref:governance.adoc#IGovernor-VoteCast-address-uint256-uint8-uint256-string-[`IGovernor.VoteCast`]] +:IGovernor-VoteCastWithParams: pass:normal[xref:governance.adoc#IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes-[`IGovernor.VoteCastWithParams`]] +:Governor-_countVote: pass:normal[xref:governance.adoc#Governor-_countVote-uint256-address-uint8-uint256-bytes-[`Governor._countVote`]] +:Governor-_castVote: pass:normal[xref:governance.adoc#Governor-_castVote-uint256-address-uint8-string-bytes-[`Governor._castVote`]] +:Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] :ERC20Votes: pass:normal[xref:token/ERC20.adoc#ERC20Votes[`ERC20Votes`]] :ERC721Votes: pass:normal[xref:token/ERC721.adoc#ERC721Votes[`ERC721Votes`]] :xref-GovernorVotes-constructor-contract-IVotes-: xref:governance.adoc#GovernorVotes-constructor-contract-IVotes- @@ -399,6 +521,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- :xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- @@ -437,6 +560,7 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- :xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- :xref-Governor-votingPeriod--: xref:governance.adoc#Governor-votingPeriod-- :xref-Governor-quorum-uint256-: xref:governance.adoc#Governor-quorum-uint256- @@ -462,7 +586,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -475,6 +598,7 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- :Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] :ERC20Votes: pass:normal[xref:token/ERC20.adoc#ERC20Votes[`ERC20Votes`]] @@ -485,6 +609,7 @@ :xref-GovernorVotesQuorumFraction-quorum-uint256-: xref:governance.adoc#GovernorVotesQuorumFraction-quorum-uint256- :xref-GovernorVotesQuorumFraction-updateQuorumNumerator-uint256-: xref:governance.adoc#GovernorVotesQuorumFraction-updateQuorumNumerator-uint256- :xref-GovernorVotesQuorumFraction-_updateQuorumNumerator-uint256-: xref:governance.adoc#GovernorVotesQuorumFraction-_updateQuorumNumerator-uint256- +:xref-GovernorVotesQuorumFraction-_optimisticUpperLookupRecent-struct-Checkpoints-Trace208-uint256-: xref:governance.adoc#GovernorVotesQuorumFraction-_optimisticUpperLookupRecent-struct-Checkpoints-Trace208-uint256- :xref-GovernorVotes-token--: xref:governance.adoc#GovernorVotes-token-- :xref-GovernorVotes-clock--: xref:governance.adoc#GovernorVotes-clock-- :xref-GovernorVotes-CLOCK_MODE--: xref:governance.adoc#GovernorVotes-CLOCK_MODE-- @@ -494,6 +619,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- :xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- @@ -532,6 +658,7 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- :xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- :xref-Governor-votingPeriod--: xref:governance.adoc#Governor-votingPeriod-- :xref-Governor-BALLOT_TYPEHASH-bytes32: xref:governance.adoc#Governor-BALLOT_TYPEHASH-bytes32 @@ -558,7 +685,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -571,7 +697,119 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- +:GovernorVotesQuorumFraction: pass:normal[xref:governance.adoc#GovernorVotesQuorumFraction[`GovernorVotesQuorumFraction`]] +:xref-GovernorVotesSuperQuorumFraction-constructor-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-constructor-uint256- +:xref-GovernorVotesSuperQuorumFraction-superQuorumNumerator--: xref:governance.adoc#GovernorVotesSuperQuorumFraction-superQuorumNumerator-- +:xref-GovernorVotesSuperQuorumFraction-superQuorumNumerator-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-superQuorumNumerator-uint256- +:xref-GovernorVotesSuperQuorumFraction-superQuorum-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-superQuorum-uint256- +:xref-GovernorVotesSuperQuorumFraction-updateSuperQuorumNumerator-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-updateSuperQuorumNumerator-uint256- +:xref-GovernorVotesSuperQuorumFraction-_updateSuperQuorumNumerator-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-_updateSuperQuorumNumerator-uint256- +:xref-GovernorVotesSuperQuorumFraction-_updateQuorumNumerator-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-_updateQuorumNumerator-uint256- +:xref-GovernorVotesSuperQuorumFraction-state-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-state-uint256- +:xref-GovernorSuperQuorum-proposalVotes-uint256-: xref:governance.adoc#GovernorSuperQuorum-proposalVotes-uint256- +:xref-GovernorVotesQuorumFraction-quorumNumerator--: xref:governance.adoc#GovernorVotesQuorumFraction-quorumNumerator-- +:xref-GovernorVotesQuorumFraction-quorumNumerator-uint256-: xref:governance.adoc#GovernorVotesQuorumFraction-quorumNumerator-uint256- +:xref-GovernorVotesQuorumFraction-quorumDenominator--: xref:governance.adoc#GovernorVotesQuorumFraction-quorumDenominator-- +:xref-GovernorVotesQuorumFraction-quorum-uint256-: xref:governance.adoc#GovernorVotesQuorumFraction-quorum-uint256- +:xref-GovernorVotesQuorumFraction-updateQuorumNumerator-uint256-: xref:governance.adoc#GovernorVotesQuorumFraction-updateQuorumNumerator-uint256- +:xref-GovernorVotesQuorumFraction-_optimisticUpperLookupRecent-struct-Checkpoints-Trace208-uint256-: xref:governance.adoc#GovernorVotesQuorumFraction-_optimisticUpperLookupRecent-struct-Checkpoints-Trace208-uint256- +:xref-GovernorVotes-token--: xref:governance.adoc#GovernorVotes-token-- +:xref-GovernorVotes-clock--: xref:governance.adoc#GovernorVotes-clock-- +:xref-GovernorVotes-CLOCK_MODE--: xref:governance.adoc#GovernorVotes-CLOCK_MODE-- +:xref-GovernorVotes-_getVotes-address-uint256-bytes-: xref:governance.adoc#GovernorVotes-_getVotes-address-uint256-bytes- +:xref-Governor-receive--: xref:governance.adoc#Governor-receive-- +:xref-Governor-supportsInterface-bytes4-: xref:governance.adoc#Governor-supportsInterface-bytes4- +:xref-Governor-name--: xref:governance.adoc#Governor-name-- +:xref-Governor-version--: xref:governance.adoc#Governor-version-- +:xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- +:xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- +:xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- +:xref-Governor-proposalDeadline-uint256-: xref:governance.adoc#Governor-proposalDeadline-uint256- +:xref-Governor-proposalProposer-uint256-: xref:governance.adoc#Governor-proposalProposer-uint256- +:xref-Governor-proposalEta-uint256-: xref:governance.adoc#Governor-proposalEta-uint256- +:xref-Governor-proposalNeedsQueuing-uint256-: xref:governance.adoc#Governor-proposalNeedsQueuing-uint256- +:xref-Governor-_checkGovernance--: xref:governance.adoc#Governor-_checkGovernance-- +:xref-Governor-_quorumReached-uint256-: xref:governance.adoc#Governor-_quorumReached-uint256- +:xref-Governor-_voteSucceeded-uint256-: xref:governance.adoc#Governor-_voteSucceeded-uint256- +:xref-Governor-_countVote-uint256-address-uint8-uint256-bytes-: xref:governance.adoc#Governor-_countVote-uint256-address-uint8-uint256-bytes- +:xref-Governor-_tallyUpdated-uint256-: xref:governance.adoc#Governor-_tallyUpdated-uint256- +:xref-Governor-_defaultParams--: xref:governance.adoc#Governor-_defaultParams-- +:xref-Governor-propose-address---uint256---bytes---string-: xref:governance.adoc#Governor-propose-address---uint256---bytes---string- +:xref-Governor-_propose-address---uint256---bytes---string-address-: xref:governance.adoc#Governor-_propose-address---uint256---bytes---string-address- +:xref-Governor-queue-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-queue-address---uint256---bytes---bytes32- +:xref-Governor-_queueOperations-uint256-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_queueOperations-uint256-address---uint256---bytes---bytes32- +:xref-Governor-execute-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-execute-address---uint256---bytes---bytes32- +:xref-Governor-_executeOperations-uint256-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_executeOperations-uint256-address---uint256---bytes---bytes32- +:xref-Governor-cancel-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-cancel-address---uint256---bytes---bytes32- +:xref-Governor-_cancel-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_cancel-address---uint256---bytes---bytes32- +:xref-Governor-getVotes-address-uint256-: xref:governance.adoc#Governor-getVotes-address-uint256- +:xref-Governor-getVotesWithParams-address-uint256-bytes-: xref:governance.adoc#Governor-getVotesWithParams-address-uint256-bytes- +:xref-Governor-castVote-uint256-uint8-: xref:governance.adoc#Governor-castVote-uint256-uint8- +:xref-Governor-castVoteWithReason-uint256-uint8-string-: xref:governance.adoc#Governor-castVoteWithReason-uint256-uint8-string- +:xref-Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes-: xref:governance.adoc#Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes- +:xref-Governor-castVoteBySig-uint256-uint8-address-bytes-: xref:governance.adoc#Governor-castVoteBySig-uint256-uint8-address-bytes- +:xref-Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-: xref:governance.adoc#Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes- +:xref-Governor-_castVote-uint256-address-uint8-string-: xref:governance.adoc#Governor-_castVote-uint256-address-uint8-string- +:xref-Governor-_castVote-uint256-address-uint8-string-bytes-: xref:governance.adoc#Governor-_castVote-uint256-address-uint8-string-bytes- +:xref-Governor-relay-address-uint256-bytes-: xref:governance.adoc#Governor-relay-address-uint256-bytes- +:xref-Governor-_executor--: xref:governance.adoc#Governor-_executor-- +:xref-Governor-onERC721Received-address-address-uint256-bytes-: xref:governance.adoc#Governor-onERC721Received-address-address-uint256-bytes- +:xref-Governor-onERC1155Received-address-address-uint256-uint256-bytes-: xref:governance.adoc#Governor-onERC1155Received-address-address-uint256-uint256-bytes- +:xref-Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes-: xref:governance.adoc#Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes- +:xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- +:xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- +:xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- +:xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- +:xref-Governor-votingPeriod--: xref:governance.adoc#Governor-votingPeriod-- +:xref-Governor-BALLOT_TYPEHASH-bytes32: xref:governance.adoc#Governor-BALLOT_TYPEHASH-bytes32 +:xref-Governor-EXTENDED_BALLOT_TYPEHASH-bytes32: xref:governance.adoc#Governor-EXTENDED_BALLOT_TYPEHASH-bytes32 +:xref-IGovernor-COUNTING_MODE--: xref:governance.adoc#IGovernor-COUNTING_MODE-- +:xref-IGovernor-hasVoted-uint256-address-: xref:governance.adoc#IGovernor-hasVoted-uint256-address- +:xref-Nonces-nonces-address-: xref:utils.adoc#Nonces-nonces-address- +:xref-Nonces-_useNonce-address-: xref:utils.adoc#Nonces-_useNonce-address- +:xref-Nonces-_useCheckedNonce-address-uint256-: xref:utils.adoc#Nonces-_useCheckedNonce-address-uint256- +:xref-EIP712-_domainSeparatorV4--: xref:utils.adoc#EIP712-_domainSeparatorV4-- +:xref-EIP712-_hashTypedDataV4-bytes32-: xref:utils.adoc#EIP712-_hashTypedDataV4-bytes32- +:xref-EIP712-eip712Domain--: xref:utils.adoc#EIP712-eip712Domain-- +:xref-EIP712-_EIP712Name--: xref:utils.adoc#EIP712-_EIP712Name-- +:xref-EIP712-_EIP712Version--: xref:utils.adoc#EIP712-_EIP712Version-- +:xref-GovernorVotesSuperQuorumFraction-SuperQuorumNumeratorUpdated-uint256-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-SuperQuorumNumeratorUpdated-uint256-uint256- +:xref-GovernorVotesQuorumFraction-QuorumNumeratorUpdated-uint256-uint256-: xref:governance.adoc#GovernorVotesQuorumFraction-QuorumNumeratorUpdated-uint256-uint256- +:xref-IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string-: xref:governance.adoc#IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string- +:xref-IGovernor-ProposalQueued-uint256-uint256-: xref:governance.adoc#IGovernor-ProposalQueued-uint256-uint256- +:xref-IGovernor-ProposalExecuted-uint256-: xref:governance.adoc#IGovernor-ProposalExecuted-uint256- +:xref-IGovernor-ProposalCanceled-uint256-: xref:governance.adoc#IGovernor-ProposalCanceled-uint256- +:xref-IGovernor-VoteCast-address-uint256-uint8-uint256-string-: xref:governance.adoc#IGovernor-VoteCast-address-uint256-uint8-uint256-string- +:xref-IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes-: xref:governance.adoc#IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes- +:xref-IERC5267-EIP712DomainChanged--: xref:interfaces.adoc#IERC5267-EIP712DomainChanged-- +:xref-GovernorVotesSuperQuorumFraction-GovernorInvalidSuperQuorumFraction-uint256-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-GovernorInvalidSuperQuorumFraction-uint256-uint256- +:xref-GovernorVotesSuperQuorumFraction-GovernorInvalidSuperQuorumTooSmall-uint256-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-GovernorInvalidSuperQuorumTooSmall-uint256-uint256- +:xref-GovernorVotesSuperQuorumFraction-GovernorInvalidQuorumTooLarge-uint256-uint256-: xref:governance.adoc#GovernorVotesSuperQuorumFraction-GovernorInvalidQuorumTooLarge-uint256-uint256- +:xref-GovernorVotesQuorumFraction-GovernorInvalidQuorumFraction-uint256-uint256-: xref:governance.adoc#GovernorVotesQuorumFraction-GovernorInvalidQuorumFraction-uint256-uint256- +:xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- +:xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- +:xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- +:xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- +:xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- +:xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- +:xref-IGovernor-GovernorInvalidVotingPeriod-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidVotingPeriod-uint256- +:xref-IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256- +:xref-IGovernor-GovernorRestrictedProposer-address-: xref:governance.adoc#IGovernor-GovernorRestrictedProposer-address- +:xref-IGovernor-GovernorInvalidVoteType--: xref:governance.adoc#IGovernor-GovernorInvalidVoteType-- +:xref-IGovernor-GovernorInvalidVoteParams--: xref:governance.adoc#IGovernor-GovernorInvalidVoteParams-- +:xref-IGovernor-GovernorQueueNotImplemented--: xref:governance.adoc#IGovernor-GovernorQueueNotImplemented-- +:xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- +:xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- +:xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- +:xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- +:GovernorSuperQuorum-superQuorum: pass:normal[xref:governance.adoc#GovernorSuperQuorum-superQuorum-uint256-[`GovernorSuperQuorum.superQuorum`]] +:GovernorVotesQuorumFraction-_updateQuorumNumerator: pass:normal[xref:governance.adoc#GovernorVotesQuorumFraction-_updateQuorumNumerator-uint256-[`GovernorVotesQuorumFraction._updateQuorumNumerator`]] +:Governor-state: pass:normal[xref:governance.adoc#Governor-state-uint256-[`Governor.state`]] :Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] :AccessManager: pass:normal[xref:access.adoc#AccessManager[`AccessManager`]] :GovernorTimelockControl: pass:normal[xref:governance.adoc#GovernorTimelockControl[`GovernorTimelockControl`]] @@ -597,6 +835,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- :xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- @@ -631,6 +870,7 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- :xref-Governor-clock--: xref:governance.adoc#Governor-clock-- :xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- :xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- @@ -663,7 +903,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -676,6 +915,7 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- :AccessManager: pass:normal[xref:access.adoc#AccessManager[`AccessManager`]] :AccessManager: pass:normal[xref:access.adoc#AccessManager[`AccessManager`]] @@ -685,6 +925,7 @@ :IGovernor-proposalNeedsQueuing: pass:normal[xref:governance.adoc#IGovernor-proposalNeedsQueuing-uint256-[`IGovernor.proposalNeedsQueuing`]] :IGovernor-propose: pass:normal[xref:governance.adoc#IGovernor-propose-address---uint256---bytes---string-[`IGovernor.propose`]] :AccessManager-execute: pass:normal[xref:access.adoc#AccessManager-execute-address-bytes-[`AccessManager.execute`]] +:Governor-_cancel: pass:normal[xref:governance.adoc#Governor-_cancel-address---uint256---bytes---bytes32-[`Governor._cancel`]] :Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] :TimelockController: pass:normal[xref:governance.adoc#TimelockController[`TimelockController`]] :TimelockController: pass:normal[xref:governance.adoc#TimelockController[`TimelockController`]] @@ -709,6 +950,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- :xref-Governor-proposalDeadline-uint256-: xref:governance.adoc#Governor-proposalDeadline-uint256- @@ -742,6 +984,7 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- :xref-Governor-clock--: xref:governance.adoc#Governor-clock-- :xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- :xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- @@ -770,7 +1013,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -783,6 +1025,7 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- :Governor-state: pass:normal[xref:governance.adoc#Governor-state-uint256-[`Governor.state`]] :IGovernor-proposalNeedsQueuing: pass:normal[xref:governance.adoc#IGovernor-proposalNeedsQueuing-uint256-[`IGovernor.proposalNeedsQueuing`]] @@ -811,6 +1054,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- :xref-Governor-proposalDeadline-uint256-: xref:governance.adoc#Governor-proposalDeadline-uint256- @@ -844,6 +1088,7 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- :xref-Governor-clock--: xref:governance.adoc#Governor-clock-- :xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- :xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- @@ -872,7 +1117,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -885,6 +1129,7 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- :Governor-state: pass:normal[xref:governance.adoc#Governor-state-uint256-[`Governor.state`]] :IGovernor-proposalNeedsQueuing: pass:normal[xref:governance.adoc#IGovernor-proposalNeedsQueuing-uint256-[`IGovernor.proposalNeedsQueuing`]] @@ -906,6 +1151,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- :xref-Governor-proposalDeadline-uint256-: xref:governance.adoc#Governor-proposalDeadline-uint256- @@ -944,6 +1190,7 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- :xref-Governor-clock--: xref:governance.adoc#Governor-clock-- :xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- :xref-Governor-quorum-uint256-: xref:governance.adoc#Governor-quorum-uint256- @@ -972,7 +1219,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -985,6 +1231,7 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- :IGovernor-votingDelay: pass:normal[xref:governance.adoc#IGovernor-votingDelay--[`IGovernor.votingDelay`]] :IGovernor-votingPeriod: pass:normal[xref:governance.adoc#IGovernor-votingPeriod--[`IGovernor.votingPeriod`]] @@ -1000,6 +1247,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- :xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- @@ -1037,6 +1285,7 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- :xref-Governor-clock--: xref:governance.adoc#Governor-clock-- :xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- :xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- @@ -1066,7 +1315,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -1079,6 +1327,7 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- :Governor-proposalDeadline: pass:normal[xref:governance.adoc#Governor-proposalDeadline-uint256-[`Governor.proposalDeadline`]] :Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] @@ -1096,6 +1345,7 @@ :xref-Governor-name--: xref:governance.adoc#Governor-name-- :xref-Governor-version--: xref:governance.adoc#Governor-version-- :xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- :xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- :xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- :xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- @@ -1134,6 +1384,101 @@ :xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- :xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- :xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- +:xref-Governor-clock--: xref:governance.adoc#Governor-clock-- +:xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- +:xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- +:xref-Governor-votingPeriod--: xref:governance.adoc#Governor-votingPeriod-- +:xref-Governor-quorum-uint256-: xref:governance.adoc#Governor-quorum-uint256- +:xref-Governor-BALLOT_TYPEHASH-bytes32: xref:governance.adoc#Governor-BALLOT_TYPEHASH-bytes32 +:xref-Governor-EXTENDED_BALLOT_TYPEHASH-bytes32: xref:governance.adoc#Governor-EXTENDED_BALLOT_TYPEHASH-bytes32 +:xref-IGovernor-COUNTING_MODE--: xref:governance.adoc#IGovernor-COUNTING_MODE-- +:xref-IGovernor-hasVoted-uint256-address-: xref:governance.adoc#IGovernor-hasVoted-uint256-address- +:xref-Nonces-nonces-address-: xref:utils.adoc#Nonces-nonces-address- +:xref-Nonces-_useNonce-address-: xref:utils.adoc#Nonces-_useNonce-address- +:xref-Nonces-_useCheckedNonce-address-uint256-: xref:utils.adoc#Nonces-_useCheckedNonce-address-uint256- +:xref-EIP712-_domainSeparatorV4--: xref:utils.adoc#EIP712-_domainSeparatorV4-- +:xref-EIP712-_hashTypedDataV4-bytes32-: xref:utils.adoc#EIP712-_hashTypedDataV4-bytes32- +:xref-EIP712-eip712Domain--: xref:utils.adoc#EIP712-eip712Domain-- +:xref-EIP712-_EIP712Name--: xref:utils.adoc#EIP712-_EIP712Name-- +:xref-EIP712-_EIP712Version--: xref:utils.adoc#EIP712-_EIP712Version-- +:xref-IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string-: xref:governance.adoc#IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string- +:xref-IGovernor-ProposalQueued-uint256-uint256-: xref:governance.adoc#IGovernor-ProposalQueued-uint256-uint256- +:xref-IGovernor-ProposalExecuted-uint256-: xref:governance.adoc#IGovernor-ProposalExecuted-uint256- +:xref-IGovernor-ProposalCanceled-uint256-: xref:governance.adoc#IGovernor-ProposalCanceled-uint256- +:xref-IGovernor-VoteCast-address-uint256-uint8-uint256-string-: xref:governance.adoc#IGovernor-VoteCast-address-uint256-uint8-uint256-string- +:xref-IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes-: xref:governance.adoc#IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes- +:xref-IERC5267-EIP712DomainChanged--: xref:interfaces.adoc#IERC5267-EIP712DomainChanged-- +:xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- +:xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- +:xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- +:xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- +:xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- +:xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- +:xref-IGovernor-GovernorInvalidVotingPeriod-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidVotingPeriod-uint256- +:xref-IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256- +:xref-IGovernor-GovernorRestrictedProposer-address-: xref:governance.adoc#IGovernor-GovernorRestrictedProposer-address- +:xref-IGovernor-GovernorInvalidVoteType--: xref:governance.adoc#IGovernor-GovernorInvalidVoteType-- +:xref-IGovernor-GovernorInvalidVoteParams--: xref:governance.adoc#IGovernor-GovernorInvalidVoteParams-- +:xref-IGovernor-GovernorQueueNotImplemented--: xref:governance.adoc#IGovernor-GovernorQueueNotImplemented-- +:xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- +:xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- +:xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- +:xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- +:IGovernor-queue: pass:normal[xref:governance.adoc#IGovernor-queue-address---uint256---bytes---bytes32-[`IGovernor.queue`]] +:IGovernor-execute: pass:normal[xref:governance.adoc#IGovernor-execute-address---uint256---bytes---bytes32-[`IGovernor.execute`]] +:IGovernor-cancel: pass:normal[xref:governance.adoc#IGovernor-cancel-address---uint256---bytes---bytes32-[`IGovernor.cancel`]] +:Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] +:xref-GovernorProposalGuardian-proposalGuardian--: xref:governance.adoc#GovernorProposalGuardian-proposalGuardian-- +:xref-GovernorProposalGuardian-setProposalGuardian-address-: xref:governance.adoc#GovernorProposalGuardian-setProposalGuardian-address- +:xref-GovernorProposalGuardian-_setProposalGuardian-address-: xref:governance.adoc#GovernorProposalGuardian-_setProposalGuardian-address- +:xref-GovernorProposalGuardian-_validateCancel-uint256-address-: xref:governance.adoc#GovernorProposalGuardian-_validateCancel-uint256-address- +:xref-Governor-receive--: xref:governance.adoc#Governor-receive-- +:xref-Governor-supportsInterface-bytes4-: xref:governance.adoc#Governor-supportsInterface-bytes4- +:xref-Governor-name--: xref:governance.adoc#Governor-name-- +:xref-Governor-version--: xref:governance.adoc#Governor-version-- +:xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- +:xref-Governor-state-uint256-: xref:governance.adoc#Governor-state-uint256- +:xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- +:xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- +:xref-Governor-proposalDeadline-uint256-: xref:governance.adoc#Governor-proposalDeadline-uint256- +:xref-Governor-proposalProposer-uint256-: xref:governance.adoc#Governor-proposalProposer-uint256- +:xref-Governor-proposalEta-uint256-: xref:governance.adoc#Governor-proposalEta-uint256- +:xref-Governor-proposalNeedsQueuing-uint256-: xref:governance.adoc#Governor-proposalNeedsQueuing-uint256- +:xref-Governor-_checkGovernance--: xref:governance.adoc#Governor-_checkGovernance-- +:xref-Governor-_quorumReached-uint256-: xref:governance.adoc#Governor-_quorumReached-uint256- +:xref-Governor-_voteSucceeded-uint256-: xref:governance.adoc#Governor-_voteSucceeded-uint256- +:xref-Governor-_getVotes-address-uint256-bytes-: xref:governance.adoc#Governor-_getVotes-address-uint256-bytes- +:xref-Governor-_countVote-uint256-address-uint8-uint256-bytes-: xref:governance.adoc#Governor-_countVote-uint256-address-uint8-uint256-bytes- +:xref-Governor-_tallyUpdated-uint256-: xref:governance.adoc#Governor-_tallyUpdated-uint256- +:xref-Governor-_defaultParams--: xref:governance.adoc#Governor-_defaultParams-- +:xref-Governor-propose-address---uint256---bytes---string-: xref:governance.adoc#Governor-propose-address---uint256---bytes---string- +:xref-Governor-_propose-address---uint256---bytes---string-address-: xref:governance.adoc#Governor-_propose-address---uint256---bytes---string-address- +:xref-Governor-queue-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-queue-address---uint256---bytes---bytes32- +:xref-Governor-_queueOperations-uint256-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_queueOperations-uint256-address---uint256---bytes---bytes32- +:xref-Governor-execute-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-execute-address---uint256---bytes---bytes32- +:xref-Governor-_executeOperations-uint256-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_executeOperations-uint256-address---uint256---bytes---bytes32- +:xref-Governor-cancel-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-cancel-address---uint256---bytes---bytes32- +:xref-Governor-_cancel-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_cancel-address---uint256---bytes---bytes32- +:xref-Governor-getVotes-address-uint256-: xref:governance.adoc#Governor-getVotes-address-uint256- +:xref-Governor-getVotesWithParams-address-uint256-bytes-: xref:governance.adoc#Governor-getVotesWithParams-address-uint256-bytes- +:xref-Governor-castVote-uint256-uint8-: xref:governance.adoc#Governor-castVote-uint256-uint8- +:xref-Governor-castVoteWithReason-uint256-uint8-string-: xref:governance.adoc#Governor-castVoteWithReason-uint256-uint8-string- +:xref-Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes-: xref:governance.adoc#Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes- +:xref-Governor-castVoteBySig-uint256-uint8-address-bytes-: xref:governance.adoc#Governor-castVoteBySig-uint256-uint8-address-bytes- +:xref-Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-: xref:governance.adoc#Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes- +:xref-Governor-_castVote-uint256-address-uint8-string-: xref:governance.adoc#Governor-_castVote-uint256-address-uint8-string- +:xref-Governor-_castVote-uint256-address-uint8-string-bytes-: xref:governance.adoc#Governor-_castVote-uint256-address-uint8-string-bytes- +:xref-Governor-relay-address-uint256-bytes-: xref:governance.adoc#Governor-relay-address-uint256-bytes- +:xref-Governor-_executor--: xref:governance.adoc#Governor-_executor-- +:xref-Governor-onERC721Received-address-address-uint256-bytes-: xref:governance.adoc#Governor-onERC721Received-address-address-uint256-bytes- +:xref-Governor-onERC1155Received-address-address-uint256-uint256-bytes-: xref:governance.adoc#Governor-onERC1155Received-address-address-uint256-uint256-bytes- +:xref-Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes-: xref:governance.adoc#Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes- +:xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- +:xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- +:xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- :xref-Governor-clock--: xref:governance.adoc#Governor-clock-- :xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- :xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- @@ -1151,6 +1496,7 @@ :xref-EIP712-eip712Domain--: xref:utils.adoc#EIP712-eip712Domain-- :xref-EIP712-_EIP712Name--: xref:utils.adoc#EIP712-_EIP712Name-- :xref-EIP712-_EIP712Version--: xref:utils.adoc#EIP712-_EIP712Version-- +:xref-GovernorProposalGuardian-ProposalGuardianSet-address-address-: xref:governance.adoc#GovernorProposalGuardian-ProposalGuardianSet-address-address- :xref-IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string-: xref:governance.adoc#IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string- :xref-IGovernor-ProposalQueued-uint256-uint256-: xref:governance.adoc#IGovernor-ProposalQueued-uint256-uint256- :xref-IGovernor-ProposalExecuted-uint256-: xref:governance.adoc#IGovernor-ProposalExecuted-uint256- @@ -1161,7 +1507,6 @@ :xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- :xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- :xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- -:xref-IGovernor-GovernorOnlyProposer-address-: xref:governance.adoc#IGovernor-GovernorOnlyProposer-address- :xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- :xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- :xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- @@ -1174,9 +1519,103 @@ :xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- :xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- :xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- -:IGovernor-execute: pass:normal[xref:governance.adoc#IGovernor-execute-address---uint256---bytes---bytes32-[`IGovernor.execute`]] -:IGovernor-cancel: pass:normal[xref:governance.adoc#IGovernor-cancel-address---uint256---bytes---bytes32-[`IGovernor.cancel`]] +:Governor-_validateCancel: pass:normal[xref:governance.adoc#Governor-_validateCancel-uint256-address-[`Governor._validateCancel`]] +:IGovernor-proposalProposer: pass:normal[xref:governance.adoc#IGovernor-proposalProposer-uint256-[`IGovernor.proposalProposer`]] +:Governor-_validateCancel: pass:normal[xref:governance.adoc#Governor-_validateCancel-uint256-address-[`Governor._validateCancel`]] +:Governor: pass:normal[xref:governance.adoc#Governor[`Governor`]] +:xref-GovernorSuperQuorum-superQuorum-uint256-: xref:governance.adoc#GovernorSuperQuorum-superQuorum-uint256- +:xref-GovernorSuperQuorum-proposalVotes-uint256-: xref:governance.adoc#GovernorSuperQuorum-proposalVotes-uint256- +:xref-GovernorSuperQuorum-state-uint256-: xref:governance.adoc#GovernorSuperQuorum-state-uint256- +:xref-Governor-receive--: xref:governance.adoc#Governor-receive-- +:xref-Governor-supportsInterface-bytes4-: xref:governance.adoc#Governor-supportsInterface-bytes4- +:xref-Governor-name--: xref:governance.adoc#Governor-name-- +:xref-Governor-version--: xref:governance.adoc#Governor-version-- +:xref-Governor-hashProposal-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-hashProposal-address---uint256---bytes---bytes32- +:xref-Governor-getProposalId-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-getProposalId-address---uint256---bytes---bytes32- +:xref-Governor-proposalThreshold--: xref:governance.adoc#Governor-proposalThreshold-- +:xref-Governor-proposalSnapshot-uint256-: xref:governance.adoc#Governor-proposalSnapshot-uint256- +:xref-Governor-proposalDeadline-uint256-: xref:governance.adoc#Governor-proposalDeadline-uint256- +:xref-Governor-proposalProposer-uint256-: xref:governance.adoc#Governor-proposalProposer-uint256- +:xref-Governor-proposalEta-uint256-: xref:governance.adoc#Governor-proposalEta-uint256- +:xref-Governor-proposalNeedsQueuing-uint256-: xref:governance.adoc#Governor-proposalNeedsQueuing-uint256- +:xref-Governor-_checkGovernance--: xref:governance.adoc#Governor-_checkGovernance-- +:xref-Governor-_quorumReached-uint256-: xref:governance.adoc#Governor-_quorumReached-uint256- +:xref-Governor-_voteSucceeded-uint256-: xref:governance.adoc#Governor-_voteSucceeded-uint256- +:xref-Governor-_getVotes-address-uint256-bytes-: xref:governance.adoc#Governor-_getVotes-address-uint256-bytes- +:xref-Governor-_countVote-uint256-address-uint8-uint256-bytes-: xref:governance.adoc#Governor-_countVote-uint256-address-uint8-uint256-bytes- +:xref-Governor-_tallyUpdated-uint256-: xref:governance.adoc#Governor-_tallyUpdated-uint256- +:xref-Governor-_defaultParams--: xref:governance.adoc#Governor-_defaultParams-- +:xref-Governor-propose-address---uint256---bytes---string-: xref:governance.adoc#Governor-propose-address---uint256---bytes---string- +:xref-Governor-_propose-address---uint256---bytes---string-address-: xref:governance.adoc#Governor-_propose-address---uint256---bytes---string-address- +:xref-Governor-queue-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-queue-address---uint256---bytes---bytes32- +:xref-Governor-_queueOperations-uint256-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_queueOperations-uint256-address---uint256---bytes---bytes32- +:xref-Governor-execute-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-execute-address---uint256---bytes---bytes32- +:xref-Governor-_executeOperations-uint256-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_executeOperations-uint256-address---uint256---bytes---bytes32- +:xref-Governor-cancel-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-cancel-address---uint256---bytes---bytes32- +:xref-Governor-_cancel-address---uint256---bytes---bytes32-: xref:governance.adoc#Governor-_cancel-address---uint256---bytes---bytes32- +:xref-Governor-getVotes-address-uint256-: xref:governance.adoc#Governor-getVotes-address-uint256- +:xref-Governor-getVotesWithParams-address-uint256-bytes-: xref:governance.adoc#Governor-getVotesWithParams-address-uint256-bytes- +:xref-Governor-castVote-uint256-uint8-: xref:governance.adoc#Governor-castVote-uint256-uint8- +:xref-Governor-castVoteWithReason-uint256-uint8-string-: xref:governance.adoc#Governor-castVoteWithReason-uint256-uint8-string- +:xref-Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes-: xref:governance.adoc#Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes- +:xref-Governor-castVoteBySig-uint256-uint8-address-bytes-: xref:governance.adoc#Governor-castVoteBySig-uint256-uint8-address-bytes- +:xref-Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-: xref:governance.adoc#Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes- +:xref-Governor-_castVote-uint256-address-uint8-string-: xref:governance.adoc#Governor-_castVote-uint256-address-uint8-string- +:xref-Governor-_castVote-uint256-address-uint8-string-bytes-: xref:governance.adoc#Governor-_castVote-uint256-address-uint8-string-bytes- +:xref-Governor-relay-address-uint256-bytes-: xref:governance.adoc#Governor-relay-address-uint256-bytes- +:xref-Governor-_executor--: xref:governance.adoc#Governor-_executor-- +:xref-Governor-onERC721Received-address-address-uint256-bytes-: xref:governance.adoc#Governor-onERC721Received-address-address-uint256-bytes- +:xref-Governor-onERC1155Received-address-address-uint256-uint256-bytes-: xref:governance.adoc#Governor-onERC1155Received-address-address-uint256-uint256-bytes- +:xref-Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes-: xref:governance.adoc#Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes- +:xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-: xref:governance.adoc#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState- +:xref-Governor-_validateStateBitmap-uint256-bytes32-: xref:governance.adoc#Governor-_validateStateBitmap-uint256-bytes32- +:xref-Governor-_isValidDescriptionForProposer-address-string-: xref:governance.adoc#Governor-_isValidDescriptionForProposer-address-string- +:xref-Governor-_validateCancel-uint256-address-: xref:governance.adoc#Governor-_validateCancel-uint256-address- +:xref-Governor-clock--: xref:governance.adoc#Governor-clock-- +:xref-Governor-CLOCK_MODE--: xref:governance.adoc#Governor-CLOCK_MODE-- +:xref-Governor-votingDelay--: xref:governance.adoc#Governor-votingDelay-- +:xref-Governor-votingPeriod--: xref:governance.adoc#Governor-votingPeriod-- +:xref-Governor-quorum-uint256-: xref:governance.adoc#Governor-quorum-uint256- +:xref-Governor-BALLOT_TYPEHASH-bytes32: xref:governance.adoc#Governor-BALLOT_TYPEHASH-bytes32 +:xref-Governor-EXTENDED_BALLOT_TYPEHASH-bytes32: xref:governance.adoc#Governor-EXTENDED_BALLOT_TYPEHASH-bytes32 +:xref-IGovernor-COUNTING_MODE--: xref:governance.adoc#IGovernor-COUNTING_MODE-- +:xref-IGovernor-hasVoted-uint256-address-: xref:governance.adoc#IGovernor-hasVoted-uint256-address- +:xref-Nonces-nonces-address-: xref:utils.adoc#Nonces-nonces-address- +:xref-Nonces-_useNonce-address-: xref:utils.adoc#Nonces-_useNonce-address- +:xref-Nonces-_useCheckedNonce-address-uint256-: xref:utils.adoc#Nonces-_useCheckedNonce-address-uint256- +:xref-EIP712-_domainSeparatorV4--: xref:utils.adoc#EIP712-_domainSeparatorV4-- +:xref-EIP712-_hashTypedDataV4-bytes32-: xref:utils.adoc#EIP712-_hashTypedDataV4-bytes32- +:xref-EIP712-eip712Domain--: xref:utils.adoc#EIP712-eip712Domain-- +:xref-EIP712-_EIP712Name--: xref:utils.adoc#EIP712-_EIP712Name-- +:xref-EIP712-_EIP712Version--: xref:utils.adoc#EIP712-_EIP712Version-- +:xref-IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string-: xref:governance.adoc#IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string- +:xref-IGovernor-ProposalQueued-uint256-uint256-: xref:governance.adoc#IGovernor-ProposalQueued-uint256-uint256- +:xref-IGovernor-ProposalExecuted-uint256-: xref:governance.adoc#IGovernor-ProposalExecuted-uint256- +:xref-IGovernor-ProposalCanceled-uint256-: xref:governance.adoc#IGovernor-ProposalCanceled-uint256- +:xref-IGovernor-VoteCast-address-uint256-uint8-uint256-string-: xref:governance.adoc#IGovernor-VoteCast-address-uint256-uint8-uint256-string- +:xref-IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes-: xref:governance.adoc#IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes- +:xref-IERC5267-EIP712DomainChanged--: xref:interfaces.adoc#IERC5267-EIP712DomainChanged-- +:xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256- +:xref-IGovernor-GovernorAlreadyCastVote-address-: xref:governance.adoc#IGovernor-GovernorAlreadyCastVote-address- +:xref-IGovernor-GovernorDisabledDeposit--: xref:governance.adoc#IGovernor-GovernorDisabledDeposit-- +:xref-IGovernor-GovernorOnlyExecutor-address-: xref:governance.adoc#IGovernor-GovernorOnlyExecutor-address- +:xref-IGovernor-GovernorNonexistentProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNonexistentProposal-uint256- +:xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-: xref:governance.adoc#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32- +:xref-IGovernor-GovernorInvalidVotingPeriod-uint256-: xref:governance.adoc#IGovernor-GovernorInvalidVotingPeriod-uint256- +:xref-IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256-: xref:governance.adoc#IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256- +:xref-IGovernor-GovernorRestrictedProposer-address-: xref:governance.adoc#IGovernor-GovernorRestrictedProposer-address- +:xref-IGovernor-GovernorInvalidVoteType--: xref:governance.adoc#IGovernor-GovernorInvalidVoteType-- +:xref-IGovernor-GovernorInvalidVoteParams--: xref:governance.adoc#IGovernor-GovernorInvalidVoteParams-- +:xref-IGovernor-GovernorQueueNotImplemented--: xref:governance.adoc#IGovernor-GovernorQueueNotImplemented-- +:xref-IGovernor-GovernorNotQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorNotQueuedProposal-uint256- +:xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-: xref:governance.adoc#IGovernor-GovernorAlreadyQueuedProposal-uint256- +:xref-IGovernor-GovernorInvalidSignature-address-: xref:governance.adoc#IGovernor-GovernorInvalidSignature-address- +:xref-IGovernor-GovernorUnableToCancel-uint256-address-: xref:governance.adoc#IGovernor-GovernorUnableToCancel-uint256-address- +:xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256- +:ERC20Votes: pass:normal[xref:token/ERC20.adoc#ERC20Votes[`ERC20Votes`]] +:Governor-state: pass:normal[xref:governance.adoc#Governor-state-uint256-[`Governor.state`]] :ERC721Votes: pass:normal[xref:token/ERC721.adoc#ERC721Votes[`ERC721Votes`]] :ERC721-balanceOf: pass:normal[xref:token/ERC721.adoc#ERC721-balanceOf-address-[`ERC721.balanceOf`]] :ERC721-_update: pass:normal[xref:token/ERC721.adoc#ERC721-_update-address-uint256-address-[`ERC721._update`]] @@ -1337,17 +1776,19 @@ For a written walkthrough, check out our guide on xref:ROOT:governance.adoc[How Votes modules determine the source of voting power, and sometimes quorum number. -* {GovernorVotes}: Extracts voting weight from an {ERC20Votes}, or since v4.5 an {ERC721Votes} token. +* {GovernorVotes}: Extracts voting weight from an {IVotes} contract. * {GovernorVotesQuorumFraction}: Combines with `GovernorVotes` to set the quorum as a fraction of the total token supply. +* {GovernorVotesSuperQuorumFraction}: Combines `GovernorSuperQuorum` with `GovernorVotesQuorumFraction` to set the super quorum as a fraction of the total token supply. + Counting modules determine valid voting options. * {GovernorCountingSimple}: Simple voting mechanism with 3 voting options: Against, For and Abstain. * {GovernorCountingFractional}: A more modular voting system that allows a user to vote with only part of its voting power, and to split that weight arbitrarily between the 3 different options (Against, For and Abstain). -* {GovernorCountingOverridable}: An extended version of `GovernorCountingSimple` which allows delegatees to override their delegates while the vote is live. +* {GovernorCountingOverridable}: An extended version of `GovernorCountingSimple` which allows delegatees to override their delegates while the vote is live. Must be used in conjunction with {VotesExtended}. Timelock extensions add a delay for governance decisions to be executed. The workflow is extended to require a `queue` step before execution. With these modules, proposals are executed by the external timelock contract, thus it is the timelock that has to hold the assets that are being governed. @@ -1365,6 +1806,10 @@ Other extensions can customize the behavior or interface in multiple ways. * {GovernorPreventLateQuorum}: Ensures there is a minimum voting period after quorum is reached as a security protection against large voters. +* {GovernorProposalGuardian}: Adds a proposal guardian that can cancel proposals at any stage in their lifecycle--this permission is passed on to the proposers if the guardian is not set. + +* {GovernorSuperQuorum}: Extension of {Governor} with a super quorum. Proposals that meet the super quorum (and have a majority of for votes) advance to the `Succeeded` state before the proposal deadline. + In addition to modules and extensions, the core contract requires a few virtual functions to be implemented to your particular specifications: * <>: Delay (in ERC-6372 clock) since the proposal is submitted until voting power is fixed and voting starts. This can be used to enforce a delay after a proposal is published for users to buy tokens, or delegate their votes. @@ -1379,7 +1824,6 @@ NOTE: Functions of the `Governor` contract do not include access control. If you :GovernorInvalidProposalLength: pass:normal[xref:#IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-[`++GovernorInvalidProposalLength++`]] :GovernorAlreadyCastVote: pass:normal[xref:#IGovernor-GovernorAlreadyCastVote-address-[`++GovernorAlreadyCastVote++`]] :GovernorDisabledDeposit: pass:normal[xref:#IGovernor-GovernorDisabledDeposit--[`++GovernorDisabledDeposit++`]] -:GovernorOnlyProposer: pass:normal[xref:#IGovernor-GovernorOnlyProposer-address-[`++GovernorOnlyProposer++`]] :GovernorOnlyExecutor: pass:normal[xref:#IGovernor-GovernorOnlyExecutor-address-[`++GovernorOnlyExecutor++`]] :GovernorNonexistentProposal: pass:normal[xref:#IGovernor-GovernorNonexistentProposal-uint256-[`++GovernorNonexistentProposal++`]] :GovernorUnexpectedProposalState: pass:normal[xref:#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-[`++GovernorUnexpectedProposalState++`]] @@ -1392,6 +1836,7 @@ NOTE: Functions of the `Governor` contract do not include access control. If you :GovernorNotQueuedProposal: pass:normal[xref:#IGovernor-GovernorNotQueuedProposal-uint256-[`++GovernorNotQueuedProposal++`]] :GovernorAlreadyQueuedProposal: pass:normal[xref:#IGovernor-GovernorAlreadyQueuedProposal-uint256-[`++GovernorAlreadyQueuedProposal++`]] :GovernorInvalidSignature: pass:normal[xref:#IGovernor-GovernorInvalidSignature-address-[`++GovernorInvalidSignature++`]] +:GovernorUnableToCancel: pass:normal[xref:#IGovernor-GovernorUnableToCancel-uint256-address-[`++GovernorUnableToCancel++`]] :ProposalCreated: pass:normal[xref:#IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string-[`++ProposalCreated++`]] :ProposalQueued: pass:normal[xref:#IGovernor-ProposalQueued-uint256-uint256-[`++ProposalQueued++`]] :ProposalExecuted: pass:normal[xref:#IGovernor-ProposalExecuted-uint256-[`++ProposalExecuted++`]] @@ -1402,6 +1847,7 @@ NOTE: Functions of the `Governor` contract do not include access control. If you :version: pass:normal[xref:#IGovernor-version--[`++version++`]] :COUNTING_MODE: pass:normal[xref:#IGovernor-COUNTING_MODE--[`++COUNTING_MODE++`]] :hashProposal: pass:normal[xref:#IGovernor-hashProposal-address---uint256---bytes---bytes32-[`++hashProposal++`]] +:getProposalId: pass:normal[xref:#IGovernor-getProposalId-address---uint256---bytes---bytes32-[`++getProposalId++`]] :state: pass:normal[xref:#IGovernor-state-uint256-[`++state++`]] :proposalThreshold: pass:normal[xref:#IGovernor-proposalThreshold--[`++proposalThreshold++`]] :proposalSnapshot: pass:normal[xref:#IGovernor-proposalSnapshot-uint256-[`++proposalSnapshot++`]] @@ -1425,9 +1871,37 @@ NOTE: Functions of the `Governor` contract do not include access control. If you :castVoteBySig: pass:normal[xref:#IGovernor-castVoteBySig-uint256-uint8-address-bytes-[`++castVoteBySig++`]] :castVoteWithReasonAndParamsBySig: pass:normal[xref:#IGovernor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-[`++castVoteWithReasonAndParamsBySig++`]] +:name-: pass:normal[xref:#IGovernor-name--[`++name++`]] +:version-: pass:normal[xref:#IGovernor-version--[`++version++`]] +:COUNTING_MODE-: pass:normal[xref:#IGovernor-COUNTING_MODE--[`++COUNTING_MODE++`]] +:hashProposal-address---uint256---bytes---bytes32: pass:normal[xref:#IGovernor-hashProposal-address---uint256---bytes---bytes32-[`++hashProposal++`]] +:getProposalId-address---uint256---bytes---bytes32: pass:normal[xref:#IGovernor-getProposalId-address---uint256---bytes---bytes32-[`++getProposalId++`]] +:state-uint256: pass:normal[xref:#IGovernor-state-uint256-[`++state++`]] +:proposalThreshold-: pass:normal[xref:#IGovernor-proposalThreshold--[`++proposalThreshold++`]] +:proposalSnapshot-uint256: pass:normal[xref:#IGovernor-proposalSnapshot-uint256-[`++proposalSnapshot++`]] +:proposalDeadline-uint256: pass:normal[xref:#IGovernor-proposalDeadline-uint256-[`++proposalDeadline++`]] +:proposalProposer-uint256: pass:normal[xref:#IGovernor-proposalProposer-uint256-[`++proposalProposer++`]] +:proposalEta-uint256: pass:normal[xref:#IGovernor-proposalEta-uint256-[`++proposalEta++`]] +:proposalNeedsQueuing-uint256: pass:normal[xref:#IGovernor-proposalNeedsQueuing-uint256-[`++proposalNeedsQueuing++`]] +:votingDelay-: pass:normal[xref:#IGovernor-votingDelay--[`++votingDelay++`]] +:votingPeriod-: pass:normal[xref:#IGovernor-votingPeriod--[`++votingPeriod++`]] +:quorum-uint256: pass:normal[xref:#IGovernor-quorum-uint256-[`++quorum++`]] +:getVotes-address-uint256: pass:normal[xref:#IGovernor-getVotes-address-uint256-[`++getVotes++`]] +:getVotesWithParams-address-uint256-bytes: pass:normal[xref:#IGovernor-getVotesWithParams-address-uint256-bytes-[`++getVotesWithParams++`]] +:hasVoted-uint256-address: pass:normal[xref:#IGovernor-hasVoted-uint256-address-[`++hasVoted++`]] +:propose-address---uint256---bytes---string: pass:normal[xref:#IGovernor-propose-address---uint256---bytes---string-[`++propose++`]] +:queue-address---uint256---bytes---bytes32: pass:normal[xref:#IGovernor-queue-address---uint256---bytes---bytes32-[`++queue++`]] +:execute-address---uint256---bytes---bytes32: pass:normal[xref:#IGovernor-execute-address---uint256---bytes---bytes32-[`++execute++`]] +:cancel-address---uint256---bytes---bytes32: pass:normal[xref:#IGovernor-cancel-address---uint256---bytes---bytes32-[`++cancel++`]] +:castVote-uint256-uint8: pass:normal[xref:#IGovernor-castVote-uint256-uint8-[`++castVote++`]] +:castVoteWithReason-uint256-uint8-string: pass:normal[xref:#IGovernor-castVoteWithReason-uint256-uint8-string-[`++castVoteWithReason++`]] +:castVoteWithReasonAndParams-uint256-uint8-string-bytes: pass:normal[xref:#IGovernor-castVoteWithReasonAndParams-uint256-uint8-string-bytes-[`++castVoteWithReasonAndParams++`]] +:castVoteBySig-uint256-uint8-address-bytes: pass:normal[xref:#IGovernor-castVoteBySig-uint256-uint8-address-bytes-[`++castVoteBySig++`]] +:castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes: pass:normal[xref:#IGovernor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-[`++castVoteWithReasonAndParamsBySig++`]] + [.contract] [[IGovernor]] -=== `++IGovernor++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/IGovernor.sol[{github-icon},role=heading-link] +=== `++IGovernor++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/IGovernor.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1446,6 +1920,7 @@ Making event parameters `indexed` affects how events are decoded, potentially br * {xref-IGovernor-version--}[`++version()++`] * {xref-IGovernor-COUNTING_MODE--}[`++COUNTING_MODE()++`] * {xref-IGovernor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-IGovernor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-IGovernor-state-uint256-}[`++state(proposalId)++`] * {xref-IGovernor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-IGovernor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] @@ -1504,7 +1979,6 @@ Making event parameters `indexed` affects how events are decoded, potentially br * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -1517,6 +1991,7 @@ Making event parameters `indexed` affects how events are decoded, potentially br * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -1566,7 +2041,15 @@ JavaScript class. [[IGovernor-hashProposal-address---uint256---bytes---bytes32-]] ==== `[.contract-item-name]#++hashProposal++#++(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256++` [.item-kind]#external# -Hashing function used to (re)build the proposal id from the proposal details.. +Hashing function used to (re)build the proposal id from the proposal details. + +NOTE: For all off-chain and external calls, use {getProposalId}. + +[.contract-item] +[[IGovernor-getProposalId-address---uint256---bytes---bytes32-]] +==== `[.contract-item-name]#++getProposalId++#++(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256++` [.item-kind]#external# + +Function used to get the proposal id from the proposal details. [.contract-item] [[IGovernor-state-uint256-]] @@ -1818,12 +2301,6 @@ The vote was already cast. Token deposits are disabled in this contract. -[.contract-item] -[[IGovernor-GovernorOnlyProposer-address-]] -==== `[.contract-item-name]#++GovernorOnlyProposer++#++(address account)++` [.item-kind]#error# - -The `account` is not a proposer. - [.contract-item] [[IGovernor-GovernorOnlyExecutor-address-]] ==== `[.contract-item-name]#++GovernorOnlyExecutor++#++(address account)++` [.item-kind]#error# @@ -1904,6 +2381,12 @@ The proposal has already been queued. The provided signature is not valid for the expected `voter`. If the `voter` is a contract, the signature is not valid using {IERC1271-isValidSignature}. +[.contract-item] +[[IGovernor-GovernorUnableToCancel-uint256-address-]] +==== `[.contract-item-name]#++GovernorUnableToCancel++#++(uint256 proposalId, address account)++` [.item-kind]#error# + +The given `account` is unable to cancel the proposal with given `proposalId`. + :BALLOT_TYPEHASH: pass:normal[xref:#Governor-BALLOT_TYPEHASH-bytes32[`++BALLOT_TYPEHASH++`]] :EXTENDED_BALLOT_TYPEHASH: pass:normal[xref:#Governor-EXTENDED_BALLOT_TYPEHASH-bytes32[`++EXTENDED_BALLOT_TYPEHASH++`]] :ProposalCore: pass:normal[xref:#Governor-ProposalCore[`++ProposalCore++`]] @@ -1914,6 +2397,7 @@ If the `voter` is a contract, the signature is not valid using {IERC1271-isValid :name: pass:normal[xref:#Governor-name--[`++name++`]] :version: pass:normal[xref:#Governor-version--[`++version++`]] :hashProposal: pass:normal[xref:#Governor-hashProposal-address---uint256---bytes---bytes32-[`++hashProposal++`]] +:getProposalId: pass:normal[xref:#Governor-getProposalId-address---uint256---bytes---bytes32-[`++getProposalId++`]] :state: pass:normal[xref:#Governor-state-uint256-[`++state++`]] :proposalThreshold: pass:normal[xref:#Governor-proposalThreshold--[`++proposalThreshold++`]] :proposalSnapshot: pass:normal[xref:#Governor-proposalSnapshot-uint256-[`++proposalSnapshot++`]] @@ -1953,15 +2437,71 @@ If the `voter` is a contract, the signature is not valid using {IERC1271-isValid :_encodeStateBitmap: pass:normal[xref:#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-[`++_encodeStateBitmap++`]] :_validateStateBitmap: pass:normal[xref:#Governor-_validateStateBitmap-uint256-bytes32-[`++_validateStateBitmap++`]] :_isValidDescriptionForProposer: pass:normal[xref:#Governor-_isValidDescriptionForProposer-address-string-[`++_isValidDescriptionForProposer++`]] +:_validateCancel: pass:normal[xref:#Governor-_validateCancel-uint256-address-[`++_validateCancel++`]] :clock: pass:normal[xref:#Governor-clock--[`++clock++`]] :CLOCK_MODE: pass:normal[xref:#Governor-CLOCK_MODE--[`++CLOCK_MODE++`]] :votingDelay: pass:normal[xref:#Governor-votingDelay--[`++votingDelay++`]] :votingPeriod: pass:normal[xref:#Governor-votingPeriod--[`++votingPeriod++`]] :quorum: pass:normal[xref:#Governor-quorum-uint256-[`++quorum++`]] +:constructor-string: pass:normal[xref:#Governor-constructor-string-[`++constructor++`]] +:receive-: pass:normal[xref:#Governor-receive--[`++receive++`]] +:supportsInterface-bytes4: pass:normal[xref:#Governor-supportsInterface-bytes4-[`++supportsInterface++`]] +:name-: pass:normal[xref:#Governor-name--[`++name++`]] +:version-: pass:normal[xref:#Governor-version--[`++version++`]] +:hashProposal-address---uint256---bytes---bytes32: pass:normal[xref:#Governor-hashProposal-address---uint256---bytes---bytes32-[`++hashProposal++`]] +:getProposalId-address---uint256---bytes---bytes32: pass:normal[xref:#Governor-getProposalId-address---uint256---bytes---bytes32-[`++getProposalId++`]] +:state-uint256: pass:normal[xref:#Governor-state-uint256-[`++state++`]] +:proposalThreshold-: pass:normal[xref:#Governor-proposalThreshold--[`++proposalThreshold++`]] +:proposalSnapshot-uint256: pass:normal[xref:#Governor-proposalSnapshot-uint256-[`++proposalSnapshot++`]] +:proposalDeadline-uint256: pass:normal[xref:#Governor-proposalDeadline-uint256-[`++proposalDeadline++`]] +:proposalProposer-uint256: pass:normal[xref:#Governor-proposalProposer-uint256-[`++proposalProposer++`]] +:proposalEta-uint256: pass:normal[xref:#Governor-proposalEta-uint256-[`++proposalEta++`]] +:proposalNeedsQueuing-uint256: pass:normal[xref:#Governor-proposalNeedsQueuing-uint256-[`++proposalNeedsQueuing++`]] +:_checkGovernance-: pass:normal[xref:#Governor-_checkGovernance--[`++_checkGovernance++`]] +:_quorumReached-uint256: pass:normal[xref:#Governor-_quorumReached-uint256-[`++_quorumReached++`]] +:_voteSucceeded-uint256: pass:normal[xref:#Governor-_voteSucceeded-uint256-[`++_voteSucceeded++`]] +:_getVotes-address-uint256-bytes: pass:normal[xref:#Governor-_getVotes-address-uint256-bytes-[`++_getVotes++`]] +:_countVote-uint256-address-uint8-uint256-bytes: pass:normal[xref:#Governor-_countVote-uint256-address-uint8-uint256-bytes-[`++_countVote++`]] +:_tallyUpdated-uint256: pass:normal[xref:#Governor-_tallyUpdated-uint256-[`++_tallyUpdated++`]] +:_defaultParams-: pass:normal[xref:#Governor-_defaultParams--[`++_defaultParams++`]] +:propose-address---uint256---bytes---string: pass:normal[xref:#Governor-propose-address---uint256---bytes---string-[`++propose++`]] +:_propose-address---uint256---bytes---string-address: pass:normal[xref:#Governor-_propose-address---uint256---bytes---string-address-[`++_propose++`]] +:queue-address---uint256---bytes---bytes32: pass:normal[xref:#Governor-queue-address---uint256---bytes---bytes32-[`++queue++`]] +:_queueOperations-uint256-address---uint256---bytes---bytes32: pass:normal[xref:#Governor-_queueOperations-uint256-address---uint256---bytes---bytes32-[`++_queueOperations++`]] +:execute-address---uint256---bytes---bytes32: pass:normal[xref:#Governor-execute-address---uint256---bytes---bytes32-[`++execute++`]] +:_executeOperations-uint256-address---uint256---bytes---bytes32: pass:normal[xref:#Governor-_executeOperations-uint256-address---uint256---bytes---bytes32-[`++_executeOperations++`]] +:cancel-address---uint256---bytes---bytes32: pass:normal[xref:#Governor-cancel-address---uint256---bytes---bytes32-[`++cancel++`]] +:_cancel-address---uint256---bytes---bytes32: pass:normal[xref:#Governor-_cancel-address---uint256---bytes---bytes32-[`++_cancel++`]] +:getVotes-address-uint256: pass:normal[xref:#Governor-getVotes-address-uint256-[`++getVotes++`]] +:getVotesWithParams-address-uint256-bytes: pass:normal[xref:#Governor-getVotesWithParams-address-uint256-bytes-[`++getVotesWithParams++`]] +:castVote-uint256-uint8: pass:normal[xref:#Governor-castVote-uint256-uint8-[`++castVote++`]] +:castVoteWithReason-uint256-uint8-string: pass:normal[xref:#Governor-castVoteWithReason-uint256-uint8-string-[`++castVoteWithReason++`]] +:castVoteWithReasonAndParams-uint256-uint8-string-bytes: pass:normal[xref:#Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes-[`++castVoteWithReasonAndParams++`]] +:castVoteBySig-uint256-uint8-address-bytes: pass:normal[xref:#Governor-castVoteBySig-uint256-uint8-address-bytes-[`++castVoteBySig++`]] +:castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes: pass:normal[xref:#Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-[`++castVoteWithReasonAndParamsBySig++`]] +:_castVote-uint256-address-uint8-string: pass:normal[xref:#Governor-_castVote-uint256-address-uint8-string-[`++_castVote++`]] +:_castVote-uint256-address-uint8-string-bytes: pass:normal[xref:#Governor-_castVote-uint256-address-uint8-string-bytes-[`++_castVote++`]] +:relay-address-uint256-bytes: pass:normal[xref:#Governor-relay-address-uint256-bytes-[`++relay++`]] +:_executor-: pass:normal[xref:#Governor-_executor--[`++_executor++`]] +:onERC721Received-address-address-uint256-bytes: pass:normal[xref:#Governor-onERC721Received-address-address-uint256-bytes-[`++onERC721Received++`]] +:onERC1155Received-address-address-uint256-uint256-bytes: pass:normal[xref:#Governor-onERC1155Received-address-address-uint256-uint256-bytes-[`++onERC1155Received++`]] +:onERC1155BatchReceived-address-address-uint256---uint256---bytes: pass:normal[xref:#Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes-[`++onERC1155BatchReceived++`]] +:_encodeStateBitmap-enum-IGovernor-ProposalState: pass:normal[xref:#Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-[`++_encodeStateBitmap++`]] +:_validateStateBitmap-uint256-bytes32: pass:normal[xref:#Governor-_validateStateBitmap-uint256-bytes32-[`++_validateStateBitmap++`]] +:_isValidDescriptionForProposer-address-string: pass:normal[xref:#Governor-_isValidDescriptionForProposer-address-string-[`++_isValidDescriptionForProposer++`]] +:_validateCancel-uint256-address: pass:normal[xref:#Governor-_validateCancel-uint256-address-[`++_validateCancel++`]] +:clock-: pass:normal[xref:#Governor-clock--[`++clock++`]] +:CLOCK_MODE-: pass:normal[xref:#Governor-CLOCK_MODE--[`++CLOCK_MODE++`]] +:votingDelay-: pass:normal[xref:#Governor-votingDelay--[`++votingDelay++`]] +:votingPeriod-: pass:normal[xref:#Governor-votingPeriod--[`++votingPeriod++`]] +:quorum-uint256: pass:normal[xref:#Governor-quorum-uint256-[`++quorum++`]] +:BALLOT_TYPEHASH-bytes32: pass:normal[xref:#Governor-BALLOT_TYPEHASH-bytes32[`++BALLOT_TYPEHASH++`]] +:EXTENDED_BALLOT_TYPEHASH-bytes32: pass:normal[xref:#Governor-EXTENDED_BALLOT_TYPEHASH-bytes32[`++EXTENDED_BALLOT_TYPEHASH++`]] + [.contract] [[Governor]] -=== `++Governor++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/Governor.sol[{github-icon},role=heading-link] +=== `++Governor++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/Governor.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1972,9 +2512,9 @@ Core of the governance system, designed to be extended through various modules. This contract is abstract and requires several functions to be implemented in various modules: -- A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote} +- A counting module must implement {_quorumReached}, {_voteSucceeded} and {_countVote} - A voting module must implement {_getVotes} -- Additionally, {votingPeriod} must also be implemented +- Additionally, {votingPeriod}, {votingDelay}, and {quorum} must also be implemented [.contract-index] .Modifiers @@ -1991,6 +2531,7 @@ This contract is abstract and requires several functions to be implemented in va * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-state-uint256-}[`++state(proposalId)++`] * {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] @@ -2030,6 +2571,7 @@ This contract is abstract and requires several functions to be implemented in va * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-clock--}[`++clock()++`] * {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] * {xref-Governor-votingDelay--}[`++votingDelay()++`] @@ -2132,7 +2674,6 @@ This contract is abstract and requires several functions to be implemented in va * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -2145,6 +2686,7 @@ This contract is abstract and requires several functions to be implemented in va * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -2226,6 +2768,12 @@ same proposal (with same operation and same description) will have the same id i across multiple networks. This also means that in order to execute the same operation twice (on the same governor) the proposer will have to change the description in order to avoid proposal id conflicts. +[.contract-item] +[[Governor-getProposalId-address---uint256---bytes---bytes32-]] +==== `[.contract-item-name]#++getProposalId++#++(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256++` [.item-kind]#public# + +See {IGovernor-getProposalId}. + [.contract-item] [[Governor-state-uint256-]] ==== `[.contract-item-name]#++state++#++(uint256 proposalId) → enum IGovernor.ProposalState++` [.item-kind]#public# @@ -2369,7 +2917,7 @@ Internal execution mechanism. Can be overridden (without a super call) to modify performed (for example adding a vault/timelock). NOTE: Calling this function directly will NOT check the current state of the proposal, set the executed flag to -true or emit the `ProposalExecuted` event. Executing a proposal should be done using {execute} or {_execute}. +true or emit the `ProposalExecuted` event. Executing a proposal should be done using {execute}. [.contract-item] [[Governor-cancel-address---uint256---bytes---bytes32-]] @@ -2511,6 +3059,14 @@ If requirements are not met, reverts with a {GovernorUnexpectedProposalState} er [[Governor-_isValidDescriptionForProposer-address-string-]] ==== `[.contract-item-name]#++_isValidDescriptionForProposer++#++(address proposer, string description) → bool++` [.item-kind]#internal# +[.contract-item] +[[Governor-_validateCancel-uint256-address-]] +==== `[.contract-item-name]#++_validateCancel++#++(uint256 proposalId, address caller) → bool++` [.item-kind]#internal# + +Check if the `caller` can cancel the proposal with the given `proposalId`. + +The default implementation allows the proposal proposer to cancel the proposal during the pending state. + [.contract-item] [[Governor-clock--]] ==== `[.contract-item-name]#++clock++#++() → uint48++` [.item-kind]#public# @@ -2578,9 +3134,16 @@ quorum depending on values such as the totalSupply of a token at this timepoint :_voteSucceeded: pass:normal[xref:#GovernorCountingSimple-_voteSucceeded-uint256-[`++_voteSucceeded++`]] :_countVote: pass:normal[xref:#GovernorCountingSimple-_countVote-uint256-address-uint8-uint256-bytes-[`++_countVote++`]] +:COUNTING_MODE-: pass:normal[xref:#GovernorCountingSimple-COUNTING_MODE--[`++COUNTING_MODE++`]] +:hasVoted-uint256-address: pass:normal[xref:#GovernorCountingSimple-hasVoted-uint256-address-[`++hasVoted++`]] +:proposalVotes-uint256: pass:normal[xref:#GovernorCountingSimple-proposalVotes-uint256-[`++proposalVotes++`]] +:_quorumReached-uint256: pass:normal[xref:#GovernorCountingSimple-_quorumReached-uint256-[`++_quorumReached++`]] +:_voteSucceeded-uint256: pass:normal[xref:#GovernorCountingSimple-_voteSucceeded-uint256-[`++_voteSucceeded++`]] +:_countVote-uint256-address-uint8-uint256-bytes: pass:normal[xref:#GovernorCountingSimple-_countVote-uint256-address-uint8-uint256-bytes-[`++_countVote++`]] + [.contract] [[GovernorCountingSimple]] -=== `++GovernorCountingSimple++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/extensions/GovernorCountingSimple.sol[{github-icon},role=heading-link] +=== `++GovernorCountingSimple++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorCountingSimple.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2606,6 +3169,7 @@ Extension of {Governor} for simple, 3 options, vote counting. * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-state-uint256-}[`++state(proposalId)++`] * {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] @@ -2642,6 +3206,7 @@ Extension of {Governor} for simple, 3 options, vote counting. * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-clock--}[`++clock()++`] * {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] * {xref-Governor-votingDelay--}[`++votingDelay()++`] @@ -2748,7 +3313,6 @@ Extension of {Governor} for simple, 3 options, vote counting. * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -2761,6 +3325,7 @@ Extension of {Governor} for simple, 3 options, vote counting. * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -2830,9 +3395,17 @@ See {Governor-_countVote}. In this module, the support follows the `VoteType` en :_voteSucceeded: pass:normal[xref:#GovernorCountingFractional-_voteSucceeded-uint256-[`++_voteSucceeded++`]] :_countVote: pass:normal[xref:#GovernorCountingFractional-_countVote-uint256-address-uint8-uint256-bytes-[`++_countVote++`]] +:COUNTING_MODE-: pass:normal[xref:#GovernorCountingFractional-COUNTING_MODE--[`++COUNTING_MODE++`]] +:hasVoted-uint256-address: pass:normal[xref:#GovernorCountingFractional-hasVoted-uint256-address-[`++hasVoted++`]] +:usedVotes-uint256-address: pass:normal[xref:#GovernorCountingFractional-usedVotes-uint256-address-[`++usedVotes++`]] +:proposalVotes-uint256: pass:normal[xref:#GovernorCountingFractional-proposalVotes-uint256-[`++proposalVotes++`]] +:_quorumReached-uint256: pass:normal[xref:#GovernorCountingFractional-_quorumReached-uint256-[`++_quorumReached++`]] +:_voteSucceeded-uint256: pass:normal[xref:#GovernorCountingFractional-_voteSucceeded-uint256-[`++_voteSucceeded++`]] +:_countVote-uint256-address-uint8-uint256-bytes: pass:normal[xref:#GovernorCountingFractional-_countVote-uint256-address-uint8-uint256-bytes-[`++_countVote++`]] + [.contract] [[GovernorCountingFractional]] -=== `++GovernorCountingFractional++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/extensions/GovernorCountingFractional.sol[{github-icon},role=heading-link] +=== `++GovernorCountingFractional++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorCountingFractional.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2858,7 +3431,7 @@ Some example use cases include: * Voting from an L2 with tokens held by a bridge * Voting privately from a shielded pool using zero knowledge proofs. -Based on ScopeLift's GovernorCountingFractional[https://github.com/ScopeLift/flexible-voting/blob/e5de2efd1368387b840931f19f3c184c85842761/src/GovernorCountingFractional.sol] +Based on ScopeLift's https://github.com/ScopeLift/flexible-voting/blob/e5de2efd1368387b840931f19f3c184c85842761/src/GovernorCountingFractional.sol[`GovernorCountingFractional`] _Available since v5.1._ @@ -2880,6 +3453,7 @@ _Available since v5.1._ * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-state-uint256-}[`++state(proposalId)++`] * {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] @@ -2916,6 +3490,7 @@ _Available since v5.1._ * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-clock--}[`++clock()++`] * {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] * {xref-Governor-votingDelay--}[`++votingDelay()++`] @@ -3023,7 +3598,6 @@ _Available since v5.1._ * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -3036,6 +3610,7 @@ _Available since v5.1._ * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -3158,9 +3733,9 @@ their checkpointed total weight minus votes already cast on the proposal). This `abi.encodePacked(uint128(againstVotes), uint128(forVotes), uint128(abstainVotes))` -NOTE: Consider that fractional voting restricts the number of casted vote (in each category) to 128 bits. +NOTE: Consider that fractional voting restricts the number of casted votes (in each category) to 128 bits. Depending on how many decimals the underlying token has, a single voter may require to split their vote into -multiple vote operations. For precision higher than ~30 decimals, large token holders may require an +multiple vote operations. For precision higher than ~30 decimals, large token holders may require a potentially large number of calls to cast all their votes. The voter has the possibility to cast all the remaining votes in a single operation using the traditional "bravo" vote. @@ -3174,15 +3749,376 @@ A fractional vote params uses more votes than are available for that user. [[GovernorCountingFractional-VOTE_TYPE_FRACTIONAL-uint8]] ==== `uint8 [.contract-item-name]#++VOTE_TYPE_FRACTIONAL++#` [.item-kind]#internal constant# +:OVERRIDE_BALLOT_TYPEHASH: pass:normal[xref:#GovernorCountingOverridable-OVERRIDE_BALLOT_TYPEHASH-bytes32[`++OVERRIDE_BALLOT_TYPEHASH++`]] +:VoteType: pass:normal[xref:#GovernorCountingOverridable-VoteType[`++VoteType++`]] +:VoteReceipt: pass:normal[xref:#GovernorCountingOverridable-VoteReceipt[`++VoteReceipt++`]] +:ProposalVote: pass:normal[xref:#GovernorCountingOverridable-ProposalVote[`++ProposalVote++`]] +:VoteReduced: pass:normal[xref:#GovernorCountingOverridable-VoteReduced-address-uint256-uint8-uint256-[`++VoteReduced++`]] +:OverrideVoteCast: pass:normal[xref:#GovernorCountingOverridable-OverrideVoteCast-address-uint256-uint8-uint256-string-[`++OverrideVoteCast++`]] +:GovernorAlreadyOverriddenVote: pass:normal[xref:#GovernorCountingOverridable-GovernorAlreadyOverriddenVote-address-[`++GovernorAlreadyOverriddenVote++`]] +:COUNTING_MODE: pass:normal[xref:#GovernorCountingOverridable-COUNTING_MODE--[`++COUNTING_MODE++`]] +:hasVoted: pass:normal[xref:#GovernorCountingOverridable-hasVoted-uint256-address-[`++hasVoted++`]] +:hasVotedOverride: pass:normal[xref:#GovernorCountingOverridable-hasVotedOverride-uint256-address-[`++hasVotedOverride++`]] +:proposalVotes: pass:normal[xref:#GovernorCountingOverridable-proposalVotes-uint256-[`++proposalVotes++`]] +:_quorumReached: pass:normal[xref:#GovernorCountingOverridable-_quorumReached-uint256-[`++_quorumReached++`]] +:_voteSucceeded: pass:normal[xref:#GovernorCountingOverridable-_voteSucceeded-uint256-[`++_voteSucceeded++`]] +:_countVote: pass:normal[xref:#GovernorCountingOverridable-_countVote-uint256-address-uint8-uint256-bytes-[`++_countVote++`]] +:_countOverride: pass:normal[xref:#GovernorCountingOverridable-_countOverride-uint256-address-uint8-[`++_countOverride++`]] +:_castOverride: pass:normal[xref:#GovernorCountingOverridable-_castOverride-uint256-address-uint8-string-[`++_castOverride++`]] +:castOverrideVote: pass:normal[xref:#GovernorCountingOverridable-castOverrideVote-uint256-uint8-string-[`++castOverrideVote++`]] +:castOverrideVoteBySig: pass:normal[xref:#GovernorCountingOverridable-castOverrideVoteBySig-uint256-uint8-address-string-bytes-[`++castOverrideVoteBySig++`]] + +:COUNTING_MODE-: pass:normal[xref:#GovernorCountingOverridable-COUNTING_MODE--[`++COUNTING_MODE++`]] +:hasVoted-uint256-address: pass:normal[xref:#GovernorCountingOverridable-hasVoted-uint256-address-[`++hasVoted++`]] +:hasVotedOverride-uint256-address: pass:normal[xref:#GovernorCountingOverridable-hasVotedOverride-uint256-address-[`++hasVotedOverride++`]] +:proposalVotes-uint256: pass:normal[xref:#GovernorCountingOverridable-proposalVotes-uint256-[`++proposalVotes++`]] +:_quorumReached-uint256: pass:normal[xref:#GovernorCountingOverridable-_quorumReached-uint256-[`++_quorumReached++`]] +:_voteSucceeded-uint256: pass:normal[xref:#GovernorCountingOverridable-_voteSucceeded-uint256-[`++_voteSucceeded++`]] +:_countVote-uint256-address-uint8-uint256-bytes: pass:normal[xref:#GovernorCountingOverridable-_countVote-uint256-address-uint8-uint256-bytes-[`++_countVote++`]] +:_countOverride-uint256-address-uint8: pass:normal[xref:#GovernorCountingOverridable-_countOverride-uint256-address-uint8-[`++_countOverride++`]] +:_castOverride-uint256-address-uint8-string: pass:normal[xref:#GovernorCountingOverridable-_castOverride-uint256-address-uint8-string-[`++_castOverride++`]] +:castOverrideVote-uint256-uint8-string: pass:normal[xref:#GovernorCountingOverridable-castOverrideVote-uint256-uint8-string-[`++castOverrideVote++`]] +:castOverrideVoteBySig-uint256-uint8-address-string-bytes: pass:normal[xref:#GovernorCountingOverridable-castOverrideVoteBySig-uint256-uint8-address-string-bytes-[`++castOverrideVoteBySig++`]] +:OVERRIDE_BALLOT_TYPEHASH-bytes32: pass:normal[xref:#GovernorCountingOverridable-OVERRIDE_BALLOT_TYPEHASH-bytes32[`++OVERRIDE_BALLOT_TYPEHASH++`]] + +[.contract] +[[GovernorCountingOverridable]] +=== `++GovernorCountingOverridable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorCountingOverridable.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/governance/extensions/GovernorCountingOverridable.sol"; +``` + +Extension of {Governor} which enables delegators to override the vote of their delegates. This module requires a +token that inherits {VotesExtended}. + +[.contract-index] +.Functions +-- +* {xref-GovernorCountingOverridable-COUNTING_MODE--}[`++COUNTING_MODE()++`] +* {xref-GovernorCountingOverridable-hasVoted-uint256-address-}[`++hasVoted(proposalId, account)++`] +* {xref-GovernorCountingOverridable-hasVotedOverride-uint256-address-}[`++hasVotedOverride(proposalId, account)++`] +* {xref-GovernorCountingOverridable-proposalVotes-uint256-}[`++proposalVotes(proposalId)++`] +* {xref-GovernorCountingOverridable-_quorumReached-uint256-}[`++_quorumReached(proposalId)++`] +* {xref-GovernorCountingOverridable-_voteSucceeded-uint256-}[`++_voteSucceeded(proposalId)++`] +* {xref-GovernorCountingOverridable-_countVote-uint256-address-uint8-uint256-bytes-}[`++_countVote(proposalId, account, support, totalWeight, )++`] +* {xref-GovernorCountingOverridable-_countOverride-uint256-address-uint8-}[`++_countOverride(proposalId, account, support)++`] +* {xref-GovernorCountingOverridable-_castOverride-uint256-address-uint8-string-}[`++_castOverride(proposalId, account, support, reason)++`] +* {xref-GovernorCountingOverridable-castOverrideVote-uint256-uint8-string-}[`++castOverrideVote(proposalId, support, reason)++`] +* {xref-GovernorCountingOverridable-castOverrideVoteBySig-uint256-uint8-address-string-bytes-}[`++castOverrideVoteBySig(proposalId, support, voter, reason, signature)++`] +* {xref-GovernorCountingOverridable-OVERRIDE_BALLOT_TYPEHASH-bytes32}[`++OVERRIDE_BALLOT_TYPEHASH()++`] + +[.contract-subindex-inherited] +.GovernorVotes +* {xref-GovernorVotes-token--}[`++token()++`] +* {xref-GovernorVotes-clock--}[`++clock()++`] +* {xref-GovernorVotes-CLOCK_MODE--}[`++CLOCK_MODE()++`] +* {xref-GovernorVotes-_getVotes-address-uint256-bytes-}[`++_getVotes(account, timepoint, )++`] + +[.contract-subindex-inherited] +.Governor +* {xref-Governor-receive--}[`++receive()++`] +* {xref-Governor-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] +* {xref-Governor-name--}[`++name()++`] +* {xref-Governor-version--}[`++version()++`] +* {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-state-uint256-}[`++state(proposalId)++`] +* {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] +* {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] +* {xref-Governor-proposalDeadline-uint256-}[`++proposalDeadline(proposalId)++`] +* {xref-Governor-proposalProposer-uint256-}[`++proposalProposer(proposalId)++`] +* {xref-Governor-proposalEta-uint256-}[`++proposalEta(proposalId)++`] +* {xref-Governor-proposalNeedsQueuing-uint256-}[`++proposalNeedsQueuing()++`] +* {xref-Governor-_checkGovernance--}[`++_checkGovernance()++`] +* {xref-Governor-_tallyUpdated-uint256-}[`++_tallyUpdated(proposalId)++`] +* {xref-Governor-_defaultParams--}[`++_defaultParams()++`] +* {xref-Governor-propose-address---uint256---bytes---string-}[`++propose(targets, values, calldatas, description)++`] +* {xref-Governor-_propose-address---uint256---bytes---string-address-}[`++_propose(targets, values, calldatas, description, proposer)++`] +* {xref-Governor-queue-address---uint256---bytes---bytes32-}[`++queue(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_queueOperations-uint256-address---uint256---bytes---bytes32-}[`++_queueOperations(, , , , )++`] +* {xref-Governor-execute-address---uint256---bytes---bytes32-}[`++execute(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_executeOperations-uint256-address---uint256---bytes---bytes32-}[`++_executeOperations(, targets, values, calldatas, )++`] +* {xref-Governor-cancel-address---uint256---bytes---bytes32-}[`++cancel(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_cancel-address---uint256---bytes---bytes32-}[`++_cancel(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getVotes-address-uint256-}[`++getVotes(account, timepoint)++`] +* {xref-Governor-getVotesWithParams-address-uint256-bytes-}[`++getVotesWithParams(account, timepoint, params)++`] +* {xref-Governor-castVote-uint256-uint8-}[`++castVote(proposalId, support)++`] +* {xref-Governor-castVoteWithReason-uint256-uint8-string-}[`++castVoteWithReason(proposalId, support, reason)++`] +* {xref-Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes-}[`++castVoteWithReasonAndParams(proposalId, support, reason, params)++`] +* {xref-Governor-castVoteBySig-uint256-uint8-address-bytes-}[`++castVoteBySig(proposalId, support, voter, signature)++`] +* {xref-Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-}[`++castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)++`] +* {xref-Governor-_castVote-uint256-address-uint8-string-}[`++_castVote(proposalId, account, support, reason)++`] +* {xref-Governor-_castVote-uint256-address-uint8-string-bytes-}[`++_castVote(proposalId, account, support, reason, params)++`] +* {xref-Governor-relay-address-uint256-bytes-}[`++relay(target, value, data)++`] +* {xref-Governor-_executor--}[`++_executor()++`] +* {xref-Governor-onERC721Received-address-address-uint256-bytes-}[`++onERC721Received(, , , )++`] +* {xref-Governor-onERC1155Received-address-address-uint256-uint256-bytes-}[`++onERC1155Received(, , , , )++`] +* {xref-Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes-}[`++onERC1155BatchReceived(, , , , )++`] +* {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] +* {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] +* {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] +* {xref-Governor-votingDelay--}[`++votingDelay()++`] +* {xref-Governor-votingPeriod--}[`++votingPeriod()++`] +* {xref-Governor-quorum-uint256-}[`++quorum(timepoint)++`] +* {xref-Governor-BALLOT_TYPEHASH-bytes32}[`++BALLOT_TYPEHASH()++`] +* {xref-Governor-EXTENDED_BALLOT_TYPEHASH-bytes32}[`++EXTENDED_BALLOT_TYPEHASH()++`] + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces +* {xref-Nonces-nonces-address-}[`++nonces(owner)++`] +* {xref-Nonces-_useNonce-address-}[`++_useNonce(owner)++`] +* {xref-Nonces-_useCheckedNonce-address-uint256-}[`++_useCheckedNonce(owner, nonce)++`] + +[.contract-subindex-inherited] +.EIP712 +* {xref-EIP712-_domainSeparatorV4--}[`++_domainSeparatorV4()++`] +* {xref-EIP712-_hashTypedDataV4-bytes32-}[`++_hashTypedDataV4(structHash)++`] +* {xref-EIP712-eip712Domain--}[`++eip712Domain()++`] +* {xref-EIP712-_EIP712Name--}[`++_EIP712Name()++`] +* {xref-EIP712-_EIP712Version--}[`++_EIP712Version()++`] + +[.contract-subindex-inherited] +.IERC5267 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Events +-- +* {xref-GovernorCountingOverridable-VoteReduced-address-uint256-uint8-uint256-}[`++VoteReduced(delegate, proposalId, support, weight)++`] +* {xref-GovernorCountingOverridable-OverrideVoteCast-address-uint256-uint8-uint256-string-}[`++OverrideVoteCast(voter, proposalId, support, weight, reason)++`] + +[.contract-subindex-inherited] +.GovernorVotes + +[.contract-subindex-inherited] +.Governor + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string-}[`++ProposalCreated(proposalId, proposer, targets, values, signatures, calldatas, voteStart, voteEnd, description)++`] +* {xref-IGovernor-ProposalQueued-uint256-uint256-}[`++ProposalQueued(proposalId, etaSeconds)++`] +* {xref-IGovernor-ProposalExecuted-uint256-}[`++ProposalExecuted(proposalId)++`] +* {xref-IGovernor-ProposalCanceled-uint256-}[`++ProposalCanceled(proposalId)++`] +* {xref-IGovernor-VoteCast-address-uint256-uint8-uint256-string-}[`++VoteCast(voter, proposalId, support, weight, reason)++`] +* {xref-IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes-}[`++VoteCastWithParams(voter, proposalId, support, weight, reason, params)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces + +[.contract-subindex-inherited] +.EIP712 + +[.contract-subindex-inherited] +.IERC5267 +* {xref-IERC5267-EIP712DomainChanged--}[`++EIP712DomainChanged()++`] + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Errors +-- +* {xref-GovernorCountingOverridable-GovernorAlreadyOverriddenVote-address-}[`++GovernorAlreadyOverriddenVote(account)++`] + +[.contract-subindex-inherited] +.GovernorVotes + +[.contract-subindex-inherited] +.Governor + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] +* {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] +* {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] +* {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] +* {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] +* {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] +* {xref-IGovernor-GovernorInvalidVotingPeriod-uint256-}[`++GovernorInvalidVotingPeriod(votingPeriod)++`] +* {xref-IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256-}[`++GovernorInsufficientProposerVotes(proposer, votes, threshold)++`] +* {xref-IGovernor-GovernorRestrictedProposer-address-}[`++GovernorRestrictedProposer(proposer)++`] +* {xref-IGovernor-GovernorInvalidVoteType--}[`++GovernorInvalidVoteType()++`] +* {xref-IGovernor-GovernorInvalidVoteParams--}[`++GovernorInvalidVoteParams()++`] +* {xref-IGovernor-GovernorQueueNotImplemented--}[`++GovernorQueueNotImplemented()++`] +* {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] +* {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] +* {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces +* {xref-Nonces-InvalidAccountNonce-address-uint256-}[`++InvalidAccountNonce(account, currentNonce)++`] + +[.contract-subindex-inherited] +.EIP712 + +[.contract-subindex-inherited] +.IERC5267 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[GovernorCountingOverridable-COUNTING_MODE--]] +==== `[.contract-item-name]#++COUNTING_MODE++#++() → string++` [.item-kind]#public# + +See {IGovernor-COUNTING_MODE}. + +[.contract-item] +[[GovernorCountingOverridable-hasVoted-uint256-address-]] +==== `[.contract-item-name]#++hasVoted++#++(uint256 proposalId, address account) → bool++` [.item-kind]#public# + +See {IGovernor-hasVoted}. + +NOTE: Calling {castVote} (or similar) casts a vote using the voting power that is delegated to the voter. +Conversely, calling {castOverrideVote} (or similar) uses the voting power of the account itself, from its asset +balances. Casting an "override vote" does not count as voting and won't be reflected by this getter. Consider +using {hasVotedOverride} to check if an account has casted an "override vote" for a given proposal id. + +[.contract-item] +[[GovernorCountingOverridable-hasVotedOverride-uint256-address-]] +==== `[.contract-item-name]#++hasVotedOverride++#++(uint256 proposalId, address account) → bool++` [.item-kind]#public# + +Check if an `account` has overridden their delegate for a proposal. + +[.contract-item] +[[GovernorCountingOverridable-proposalVotes-uint256-]] +==== `[.contract-item-name]#++proposalVotes++#++(uint256 proposalId) → uint256 againstVotes, uint256 forVotes, uint256 abstainVotes++` [.item-kind]#public# + +Accessor to the internal vote counts. + +[.contract-item] +[[GovernorCountingOverridable-_quorumReached-uint256-]] +==== `[.contract-item-name]#++_quorumReached++#++(uint256 proposalId) → bool++` [.item-kind]#internal# + +See {Governor-_quorumReached}. + +[.contract-item] +[[GovernorCountingOverridable-_voteSucceeded-uint256-]] +==== `[.contract-item-name]#++_voteSucceeded++#++(uint256 proposalId) → bool++` [.item-kind]#internal# + +See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes. + +[.contract-item] +[[GovernorCountingOverridable-_countVote-uint256-address-uint8-uint256-bytes-]] +==== `[.contract-item-name]#++_countVote++#++(uint256 proposalId, address account, uint8 support, uint256 totalWeight, bytes) → uint256++` [.item-kind]#internal# + +See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo). + +NOTE: called by {Governor-_castVote} which emits the {IGovernor-VoteCast} (or {IGovernor-VoteCastWithParams}) +event. + +[.contract-item] +[[GovernorCountingOverridable-_countOverride-uint256-address-uint8-]] +==== `[.contract-item-name]#++_countOverride++#++(uint256 proposalId, address account, uint8 support) → uint256++` [.item-kind]#internal# + +Variant of {Governor-_countVote} that deals with vote overrides. + +NOTE: See {hasVoted} for more details about the difference between {castVote} and {castOverrideVote}. + +[.contract-item] +[[GovernorCountingOverridable-_castOverride-uint256-address-uint8-string-]] +==== `[.contract-item-name]#++_castOverride++#++(uint256 proposalId, address account, uint8 support, string reason) → uint256++` [.item-kind]#internal# + +Variant of {Governor-_castVote} that deals with vote overrides. Returns the overridden weight. + +[.contract-item] +[[GovernorCountingOverridable-castOverrideVote-uint256-uint8-string-]] +==== `[.contract-item-name]#++castOverrideVote++#++(uint256 proposalId, uint8 support, string reason) → uint256++` [.item-kind]#public# + +Public function for casting an override vote. Returns the overridden weight. + +[.contract-item] +[[GovernorCountingOverridable-castOverrideVoteBySig-uint256-uint8-address-string-bytes-]] +==== `[.contract-item-name]#++castOverrideVoteBySig++#++(uint256 proposalId, uint8 support, address voter, string reason, bytes signature) → uint256++` [.item-kind]#public# + +Public function for casting an override vote using a voter's signature. Returns the overridden weight. + +[.contract-item] +[[GovernorCountingOverridable-OVERRIDE_BALLOT_TYPEHASH-bytes32]] +==== `[.contract-item-name]#++OVERRIDE_BALLOT_TYPEHASH++#++() → bytes32++` [.item-kind]#public# + +[.contract-item] +[[GovernorCountingOverridable-VoteReduced-address-uint256-uint8-uint256-]] +==== `[.contract-item-name]#++VoteReduced++#++(address indexed delegate, uint256 proposalId, uint8 support, uint256 weight)++` [.item-kind]#event# + +The votes casted by `delegate` were reduced by `weight` after an override vote was casted by the original token holder + +[.contract-item] +[[GovernorCountingOverridable-OverrideVoteCast-address-uint256-uint8-uint256-string-]] +==== `[.contract-item-name]#++OverrideVoteCast++#++(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason)++` [.item-kind]#event# + +A delegated vote on `proposalId` was overridden by `weight` + +[.contract-item] +[[GovernorCountingOverridable-GovernorAlreadyOverriddenVote-address-]] +==== `[.contract-item-name]#++GovernorAlreadyOverriddenVote++#++(address account)++` [.item-kind]#error# + :constructor: pass:normal[xref:#GovernorVotes-constructor-contract-IVotes-[`++constructor++`]] :token: pass:normal[xref:#GovernorVotes-token--[`++token++`]] :clock: pass:normal[xref:#GovernorVotes-clock--[`++clock++`]] :CLOCK_MODE: pass:normal[xref:#GovernorVotes-CLOCK_MODE--[`++CLOCK_MODE++`]] :_getVotes: pass:normal[xref:#GovernorVotes-_getVotes-address-uint256-bytes-[`++_getVotes++`]] +:constructor-contract-IVotes: pass:normal[xref:#GovernorVotes-constructor-contract-IVotes-[`++constructor++`]] +:token-: pass:normal[xref:#GovernorVotes-token--[`++token++`]] +:clock-: pass:normal[xref:#GovernorVotes-clock--[`++clock++`]] +:CLOCK_MODE-: pass:normal[xref:#GovernorVotes-CLOCK_MODE--[`++CLOCK_MODE++`]] +:_getVotes-address-uint256-bytes: pass:normal[xref:#GovernorVotes-_getVotes-address-uint256-bytes-[`++_getVotes++`]] + [.contract] [[GovernorVotes]] -=== `++GovernorVotes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/extensions/GovernorVotes.sol[{github-icon},role=heading-link] +=== `++GovernorVotes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorVotes.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3208,6 +4144,7 @@ token. * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-state-uint256-}[`++state(proposalId)++`] * {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] @@ -3246,6 +4183,7 @@ token. * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-votingDelay--}[`++votingDelay()++`] * {xref-Governor-votingPeriod--}[`++votingPeriod()++`] * {xref-Governor-quorum-uint256-}[`++quorum(timepoint)++`] @@ -3352,7 +4290,6 @@ token. * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -3365,6 +4302,7 @@ token. * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -3423,10 +4361,20 @@ Machine-readable description of the clock as specified in ERC-6372. :quorum: pass:normal[xref:#GovernorVotesQuorumFraction-quorum-uint256-[`++quorum++`]] :updateQuorumNumerator: pass:normal[xref:#GovernorVotesQuorumFraction-updateQuorumNumerator-uint256-[`++updateQuorumNumerator++`]] :_updateQuorumNumerator: pass:normal[xref:#GovernorVotesQuorumFraction-_updateQuorumNumerator-uint256-[`++_updateQuorumNumerator++`]] +:_optimisticUpperLookupRecent: pass:normal[xref:#GovernorVotesQuorumFraction-_optimisticUpperLookupRecent-struct-Checkpoints-Trace208-uint256-[`++_optimisticUpperLookupRecent++`]] + +:constructor-uint256: pass:normal[xref:#GovernorVotesQuorumFraction-constructor-uint256-[`++constructor++`]] +:quorumNumerator-: pass:normal[xref:#GovernorVotesQuorumFraction-quorumNumerator--[`++quorumNumerator++`]] +:quorumNumerator-uint256: pass:normal[xref:#GovernorVotesQuorumFraction-quorumNumerator-uint256-[`++quorumNumerator++`]] +:quorumDenominator-: pass:normal[xref:#GovernorVotesQuorumFraction-quorumDenominator--[`++quorumDenominator++`]] +:quorum-uint256: pass:normal[xref:#GovernorVotesQuorumFraction-quorum-uint256-[`++quorum++`]] +:updateQuorumNumerator-uint256: pass:normal[xref:#GovernorVotesQuorumFraction-updateQuorumNumerator-uint256-[`++updateQuorumNumerator++`]] +:_updateQuorumNumerator-uint256: pass:normal[xref:#GovernorVotesQuorumFraction-_updateQuorumNumerator-uint256-[`++_updateQuorumNumerator++`]] +:_optimisticUpperLookupRecent-struct-Checkpoints-Trace208-uint256: pass:normal[xref:#GovernorVotesQuorumFraction-_optimisticUpperLookupRecent-struct-Checkpoints-Trace208-uint256-[`++_optimisticUpperLookupRecent++`]] [.contract] [[GovernorVotesQuorumFraction]] -=== `++GovernorVotesQuorumFraction++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/extensions/GovernorVotesQuorumFraction.sol[{github-icon},role=heading-link] +=== `++GovernorVotesQuorumFraction++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorVotesQuorumFraction.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3446,6 +4394,7 @@ fraction of the total supply. * {xref-GovernorVotesQuorumFraction-quorum-uint256-}[`++quorum(timepoint)++`] * {xref-GovernorVotesQuorumFraction-updateQuorumNumerator-uint256-}[`++updateQuorumNumerator(newQuorumNumerator)++`] * {xref-GovernorVotesQuorumFraction-_updateQuorumNumerator-uint256-}[`++_updateQuorumNumerator(newQuorumNumerator)++`] +* {xref-GovernorVotesQuorumFraction-_optimisticUpperLookupRecent-struct-Checkpoints-Trace208-uint256-}[`++_optimisticUpperLookupRecent(ckpts, timepoint)++`] [.contract-subindex-inherited] .GovernorVotes @@ -3461,6 +4410,7 @@ fraction of the total supply. * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-state-uint256-}[`++state(proposalId)++`] * {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] @@ -3499,6 +4449,7 @@ fraction of the total supply. * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-votingDelay--}[`++votingDelay()++`] * {xref-Governor-votingPeriod--}[`++votingPeriod()++`] * {xref-Governor-BALLOT_TYPEHASH-bytes32}[`++BALLOT_TYPEHASH()++`] @@ -3612,7 +4563,6 @@ fraction of the total supply. * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -3625,6 +4575,7 @@ fraction of the total supply. * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -3706,6 +4657,12 @@ Requirements: - New numerator must be smaller or equal to the denominator. +[.contract-item] +[[GovernorVotesQuorumFraction-_optimisticUpperLookupRecent-struct-Checkpoints-Trace208-uint256-]] +==== `[.contract-item-name]#++_optimisticUpperLookupRecent++#++(struct Checkpoints.Trace208 ckpts, uint256 timepoint) → uint256++` [.item-kind]#internal# + +Returns the numerator at a specific timepoint. + [.contract-item] [[GovernorVotesQuorumFraction-QuorumNumeratorUpdated-uint256-uint256-]] ==== `[.contract-item-name]#++QuorumNumeratorUpdated++#++(uint256 oldQuorumNumerator, uint256 newQuorumNumerator)++` [.item-kind]#event# @@ -3716,6 +4673,381 @@ Requirements: The quorum set is not a valid fraction. +:SuperQuorumNumeratorUpdated: pass:normal[xref:#GovernorVotesSuperQuorumFraction-SuperQuorumNumeratorUpdated-uint256-uint256-[`++SuperQuorumNumeratorUpdated++`]] +:GovernorInvalidSuperQuorumFraction: pass:normal[xref:#GovernorVotesSuperQuorumFraction-GovernorInvalidSuperQuorumFraction-uint256-uint256-[`++GovernorInvalidSuperQuorumFraction++`]] +:GovernorInvalidSuperQuorumTooSmall: pass:normal[xref:#GovernorVotesSuperQuorumFraction-GovernorInvalidSuperQuorumTooSmall-uint256-uint256-[`++GovernorInvalidSuperQuorumTooSmall++`]] +:GovernorInvalidQuorumTooLarge: pass:normal[xref:#GovernorVotesSuperQuorumFraction-GovernorInvalidQuorumTooLarge-uint256-uint256-[`++GovernorInvalidQuorumTooLarge++`]] +:constructor: pass:normal[xref:#GovernorVotesSuperQuorumFraction-constructor-uint256-[`++constructor++`]] +:superQuorumNumerator: pass:normal[xref:#GovernorVotesSuperQuorumFraction-superQuorumNumerator--[`++superQuorumNumerator++`]] +:superQuorumNumerator: pass:normal[xref:#GovernorVotesSuperQuorumFraction-superQuorumNumerator-uint256-[`++superQuorumNumerator++`]] +:superQuorum: pass:normal[xref:#GovernorVotesSuperQuorumFraction-superQuorum-uint256-[`++superQuorum++`]] +:updateSuperQuorumNumerator: pass:normal[xref:#GovernorVotesSuperQuorumFraction-updateSuperQuorumNumerator-uint256-[`++updateSuperQuorumNumerator++`]] +:_updateSuperQuorumNumerator: pass:normal[xref:#GovernorVotesSuperQuorumFraction-_updateSuperQuorumNumerator-uint256-[`++_updateSuperQuorumNumerator++`]] +:_updateQuorumNumerator: pass:normal[xref:#GovernorVotesSuperQuorumFraction-_updateQuorumNumerator-uint256-[`++_updateQuorumNumerator++`]] +:state: pass:normal[xref:#GovernorVotesSuperQuorumFraction-state-uint256-[`++state++`]] + +:constructor-uint256: pass:normal[xref:#GovernorVotesSuperQuorumFraction-constructor-uint256-[`++constructor++`]] +:superQuorumNumerator-: pass:normal[xref:#GovernorVotesSuperQuorumFraction-superQuorumNumerator--[`++superQuorumNumerator++`]] +:superQuorumNumerator-uint256: pass:normal[xref:#GovernorVotesSuperQuorumFraction-superQuorumNumerator-uint256-[`++superQuorumNumerator++`]] +:superQuorum-uint256: pass:normal[xref:#GovernorVotesSuperQuorumFraction-superQuorum-uint256-[`++superQuorum++`]] +:updateSuperQuorumNumerator-uint256: pass:normal[xref:#GovernorVotesSuperQuorumFraction-updateSuperQuorumNumerator-uint256-[`++updateSuperQuorumNumerator++`]] +:_updateSuperQuorumNumerator-uint256: pass:normal[xref:#GovernorVotesSuperQuorumFraction-_updateSuperQuorumNumerator-uint256-[`++_updateSuperQuorumNumerator++`]] +:_updateQuorumNumerator-uint256: pass:normal[xref:#GovernorVotesSuperQuorumFraction-_updateQuorumNumerator-uint256-[`++_updateQuorumNumerator++`]] +:state-uint256: pass:normal[xref:#GovernorVotesSuperQuorumFraction-state-uint256-[`++state++`]] + +[.contract] +[[GovernorVotesSuperQuorumFraction]] +=== `++GovernorVotesSuperQuorumFraction++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol"; +``` + +Extension of {GovernorVotesQuorumFraction} with a super quorum expressed as a +fraction of the total supply. Proposals that meet the super quorum (and have a majority of for votes) advance to +the `Succeeded` state before the proposal deadline. + +[.contract-index] +.Functions +-- +* {xref-GovernorVotesSuperQuorumFraction-constructor-uint256-}[`++constructor(superQuorumNumeratorValue)++`] +* {xref-GovernorVotesSuperQuorumFraction-superQuorumNumerator--}[`++superQuorumNumerator()++`] +* {xref-GovernorVotesSuperQuorumFraction-superQuorumNumerator-uint256-}[`++superQuorumNumerator(timepoint)++`] +* {xref-GovernorVotesSuperQuorumFraction-superQuorum-uint256-}[`++superQuorum(timepoint)++`] +* {xref-GovernorVotesSuperQuorumFraction-updateSuperQuorumNumerator-uint256-}[`++updateSuperQuorumNumerator(newSuperQuorumNumerator)++`] +* {xref-GovernorVotesSuperQuorumFraction-_updateSuperQuorumNumerator-uint256-}[`++_updateSuperQuorumNumerator(newSuperQuorumNumerator)++`] +* {xref-GovernorVotesSuperQuorumFraction-_updateQuorumNumerator-uint256-}[`++_updateQuorumNumerator(newQuorumNumerator)++`] +* {xref-GovernorVotesSuperQuorumFraction-state-uint256-}[`++state(proposalId)++`] + +[.contract-subindex-inherited] +.GovernorSuperQuorum +* {xref-GovernorSuperQuorum-proposalVotes-uint256-}[`++proposalVotes(proposalId)++`] + +[.contract-subindex-inherited] +.GovernorVotesQuorumFraction +* {xref-GovernorVotesQuorumFraction-quorumNumerator--}[`++quorumNumerator()++`] +* {xref-GovernorVotesQuorumFraction-quorumNumerator-uint256-}[`++quorumNumerator(timepoint)++`] +* {xref-GovernorVotesQuorumFraction-quorumDenominator--}[`++quorumDenominator()++`] +* {xref-GovernorVotesQuorumFraction-quorum-uint256-}[`++quorum(timepoint)++`] +* {xref-GovernorVotesQuorumFraction-updateQuorumNumerator-uint256-}[`++updateQuorumNumerator(newQuorumNumerator)++`] +* {xref-GovernorVotesQuorumFraction-_optimisticUpperLookupRecent-struct-Checkpoints-Trace208-uint256-}[`++_optimisticUpperLookupRecent(ckpts, timepoint)++`] + +[.contract-subindex-inherited] +.GovernorVotes +* {xref-GovernorVotes-token--}[`++token()++`] +* {xref-GovernorVotes-clock--}[`++clock()++`] +* {xref-GovernorVotes-CLOCK_MODE--}[`++CLOCK_MODE()++`] +* {xref-GovernorVotes-_getVotes-address-uint256-bytes-}[`++_getVotes(account, timepoint, )++`] + +[.contract-subindex-inherited] +.Governor +* {xref-Governor-receive--}[`++receive()++`] +* {xref-Governor-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] +* {xref-Governor-name--}[`++name()++`] +* {xref-Governor-version--}[`++version()++`] +* {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] +* {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] +* {xref-Governor-proposalDeadline-uint256-}[`++proposalDeadline(proposalId)++`] +* {xref-Governor-proposalProposer-uint256-}[`++proposalProposer(proposalId)++`] +* {xref-Governor-proposalEta-uint256-}[`++proposalEta(proposalId)++`] +* {xref-Governor-proposalNeedsQueuing-uint256-}[`++proposalNeedsQueuing()++`] +* {xref-Governor-_checkGovernance--}[`++_checkGovernance()++`] +* {xref-Governor-_quorumReached-uint256-}[`++_quorumReached(proposalId)++`] +* {xref-Governor-_voteSucceeded-uint256-}[`++_voteSucceeded(proposalId)++`] +* {xref-Governor-_countVote-uint256-address-uint8-uint256-bytes-}[`++_countVote(proposalId, account, support, totalWeight, params)++`] +* {xref-Governor-_tallyUpdated-uint256-}[`++_tallyUpdated(proposalId)++`] +* {xref-Governor-_defaultParams--}[`++_defaultParams()++`] +* {xref-Governor-propose-address---uint256---bytes---string-}[`++propose(targets, values, calldatas, description)++`] +* {xref-Governor-_propose-address---uint256---bytes---string-address-}[`++_propose(targets, values, calldatas, description, proposer)++`] +* {xref-Governor-queue-address---uint256---bytes---bytes32-}[`++queue(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_queueOperations-uint256-address---uint256---bytes---bytes32-}[`++_queueOperations(, , , , )++`] +* {xref-Governor-execute-address---uint256---bytes---bytes32-}[`++execute(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_executeOperations-uint256-address---uint256---bytes---bytes32-}[`++_executeOperations(, targets, values, calldatas, )++`] +* {xref-Governor-cancel-address---uint256---bytes---bytes32-}[`++cancel(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_cancel-address---uint256---bytes---bytes32-}[`++_cancel(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getVotes-address-uint256-}[`++getVotes(account, timepoint)++`] +* {xref-Governor-getVotesWithParams-address-uint256-bytes-}[`++getVotesWithParams(account, timepoint, params)++`] +* {xref-Governor-castVote-uint256-uint8-}[`++castVote(proposalId, support)++`] +* {xref-Governor-castVoteWithReason-uint256-uint8-string-}[`++castVoteWithReason(proposalId, support, reason)++`] +* {xref-Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes-}[`++castVoteWithReasonAndParams(proposalId, support, reason, params)++`] +* {xref-Governor-castVoteBySig-uint256-uint8-address-bytes-}[`++castVoteBySig(proposalId, support, voter, signature)++`] +* {xref-Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-}[`++castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)++`] +* {xref-Governor-_castVote-uint256-address-uint8-string-}[`++_castVote(proposalId, account, support, reason)++`] +* {xref-Governor-_castVote-uint256-address-uint8-string-bytes-}[`++_castVote(proposalId, account, support, reason, params)++`] +* {xref-Governor-relay-address-uint256-bytes-}[`++relay(target, value, data)++`] +* {xref-Governor-_executor--}[`++_executor()++`] +* {xref-Governor-onERC721Received-address-address-uint256-bytes-}[`++onERC721Received(, , , )++`] +* {xref-Governor-onERC1155Received-address-address-uint256-uint256-bytes-}[`++onERC1155Received(, , , , )++`] +* {xref-Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes-}[`++onERC1155BatchReceived(, , , , )++`] +* {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] +* {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] +* {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] +* {xref-Governor-votingDelay--}[`++votingDelay()++`] +* {xref-Governor-votingPeriod--}[`++votingPeriod()++`] +* {xref-Governor-BALLOT_TYPEHASH-bytes32}[`++BALLOT_TYPEHASH()++`] +* {xref-Governor-EXTENDED_BALLOT_TYPEHASH-bytes32}[`++EXTENDED_BALLOT_TYPEHASH()++`] + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-COUNTING_MODE--}[`++COUNTING_MODE()++`] +* {xref-IGovernor-hasVoted-uint256-address-}[`++hasVoted(proposalId, account)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces +* {xref-Nonces-nonces-address-}[`++nonces(owner)++`] +* {xref-Nonces-_useNonce-address-}[`++_useNonce(owner)++`] +* {xref-Nonces-_useCheckedNonce-address-uint256-}[`++_useCheckedNonce(owner, nonce)++`] + +[.contract-subindex-inherited] +.EIP712 +* {xref-EIP712-_domainSeparatorV4--}[`++_domainSeparatorV4()++`] +* {xref-EIP712-_hashTypedDataV4-bytes32-}[`++_hashTypedDataV4(structHash)++`] +* {xref-EIP712-eip712Domain--}[`++eip712Domain()++`] +* {xref-EIP712-_EIP712Name--}[`++_EIP712Name()++`] +* {xref-EIP712-_EIP712Version--}[`++_EIP712Version()++`] + +[.contract-subindex-inherited] +.IERC5267 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Events +-- +* {xref-GovernorVotesSuperQuorumFraction-SuperQuorumNumeratorUpdated-uint256-uint256-}[`++SuperQuorumNumeratorUpdated(oldSuperQuorumNumerator, newSuperQuorumNumerator)++`] + +[.contract-subindex-inherited] +.GovernorSuperQuorum + +[.contract-subindex-inherited] +.GovernorVotesQuorumFraction +* {xref-GovernorVotesQuorumFraction-QuorumNumeratorUpdated-uint256-uint256-}[`++QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator)++`] + +[.contract-subindex-inherited] +.GovernorVotes + +[.contract-subindex-inherited] +.Governor + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string-}[`++ProposalCreated(proposalId, proposer, targets, values, signatures, calldatas, voteStart, voteEnd, description)++`] +* {xref-IGovernor-ProposalQueued-uint256-uint256-}[`++ProposalQueued(proposalId, etaSeconds)++`] +* {xref-IGovernor-ProposalExecuted-uint256-}[`++ProposalExecuted(proposalId)++`] +* {xref-IGovernor-ProposalCanceled-uint256-}[`++ProposalCanceled(proposalId)++`] +* {xref-IGovernor-VoteCast-address-uint256-uint8-uint256-string-}[`++VoteCast(voter, proposalId, support, weight, reason)++`] +* {xref-IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes-}[`++VoteCastWithParams(voter, proposalId, support, weight, reason, params)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces + +[.contract-subindex-inherited] +.EIP712 + +[.contract-subindex-inherited] +.IERC5267 +* {xref-IERC5267-EIP712DomainChanged--}[`++EIP712DomainChanged()++`] + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Errors +-- +* {xref-GovernorVotesSuperQuorumFraction-GovernorInvalidSuperQuorumFraction-uint256-uint256-}[`++GovernorInvalidSuperQuorumFraction(superQuorumNumerator, denominator)++`] +* {xref-GovernorVotesSuperQuorumFraction-GovernorInvalidSuperQuorumTooSmall-uint256-uint256-}[`++GovernorInvalidSuperQuorumTooSmall(superQuorumNumerator, quorumNumerator)++`] +* {xref-GovernorVotesSuperQuorumFraction-GovernorInvalidQuorumTooLarge-uint256-uint256-}[`++GovernorInvalidQuorumTooLarge(quorumNumerator, superQuorumNumerator)++`] + +[.contract-subindex-inherited] +.GovernorSuperQuorum + +[.contract-subindex-inherited] +.GovernorVotesQuorumFraction +* {xref-GovernorVotesQuorumFraction-GovernorInvalidQuorumFraction-uint256-uint256-}[`++GovernorInvalidQuorumFraction(quorumNumerator, quorumDenominator)++`] + +[.contract-subindex-inherited] +.GovernorVotes + +[.contract-subindex-inherited] +.Governor + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] +* {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] +* {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] +* {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] +* {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] +* {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] +* {xref-IGovernor-GovernorInvalidVotingPeriod-uint256-}[`++GovernorInvalidVotingPeriod(votingPeriod)++`] +* {xref-IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256-}[`++GovernorInsufficientProposerVotes(proposer, votes, threshold)++`] +* {xref-IGovernor-GovernorRestrictedProposer-address-}[`++GovernorRestrictedProposer(proposer)++`] +* {xref-IGovernor-GovernorInvalidVoteType--}[`++GovernorInvalidVoteType()++`] +* {xref-IGovernor-GovernorInvalidVoteParams--}[`++GovernorInvalidVoteParams()++`] +* {xref-IGovernor-GovernorQueueNotImplemented--}[`++GovernorQueueNotImplemented()++`] +* {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] +* {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] +* {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces +* {xref-Nonces-InvalidAccountNonce-address-uint256-}[`++InvalidAccountNonce(account, currentNonce)++`] + +[.contract-subindex-inherited] +.EIP712 + +[.contract-subindex-inherited] +.IERC5267 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-constructor-uint256-]] +==== `[.contract-item-name]#++constructor++#++(uint256 superQuorumNumeratorValue)++` [.item-kind]#internal# + +Initialize super quorum as a fraction of the token's total supply. + +The super quorum is specified as a fraction of the token's total supply and has to +be greater than the quorum. + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-superQuorumNumerator--]] +==== `[.contract-item-name]#++superQuorumNumerator++#++() → uint256++` [.item-kind]#public# + +Returns the current super quorum numerator. + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-superQuorumNumerator-uint256-]] +==== `[.contract-item-name]#++superQuorumNumerator++#++(uint256 timepoint) → uint256++` [.item-kind]#public# + +Returns the super quorum numerator at a specific `timepoint`. + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-superQuorum-uint256-]] +==== `[.contract-item-name]#++superQuorum++#++(uint256 timepoint) → uint256++` [.item-kind]#public# + +Returns the super quorum for a `timepoint`, in terms of number of votes: `supply * numerator / denominator`. +See {GovernorSuperQuorum-superQuorum} for more details. + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-updateSuperQuorumNumerator-uint256-]] +==== `[.contract-item-name]#++updateSuperQuorumNumerator++#++(uint256 newSuperQuorumNumerator)++` [.item-kind]#public# + +Changes the super quorum numerator. + +Emits a {SuperQuorumNumeratorUpdated} event. + +Requirements: + +- Must be called through a governance proposal. +- New super quorum numerator must be smaller or equal to the denominator. +- New super quorum numerator must be greater than or equal to the quorum numerator. + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-_updateSuperQuorumNumerator-uint256-]] +==== `[.contract-item-name]#++_updateSuperQuorumNumerator++#++(uint256 newSuperQuorumNumerator)++` [.item-kind]#internal# + +Changes the super quorum numerator. + +Emits a {SuperQuorumNumeratorUpdated} event. + +Requirements: + +- New super quorum numerator must be smaller or equal to the denominator. +- New super quorum numerator must be greater than or equal to the quorum numerator. + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-_updateQuorumNumerator-uint256-]] +==== `[.contract-item-name]#++_updateQuorumNumerator++#++(uint256 newQuorumNumerator)++` [.item-kind]#internal# + +Overrides {GovernorVotesQuorumFraction-_updateQuorumNumerator} to ensure the super +quorum numerator is greater than or equal to the quorum numerator. + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-state-uint256-]] +==== `[.contract-item-name]#++state++#++(uint256 proposalId) → enum IGovernor.ProposalState++` [.item-kind]#public# + +Overridden version of the {Governor-state} function that checks if the proposal has reached the super +quorum. + +NOTE: If the proposal reaches super quorum but {_voteSucceeded} returns false, eg, assuming the super quorum +has been set low enough that both FOR and AGAINST votes have exceeded it and AGAINST votes exceed FOR votes, +the proposal continues to be active until {_voteSucceeded} returns true or the proposal deadline is reached. +This means that with a low super quorum it is also possible that a vote can succeed prematurely before enough +AGAINST voters have a chance to vote. Hence, it is recommended to set a high enough super quorum to avoid these +types of scenarios. + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-SuperQuorumNumeratorUpdated-uint256-uint256-]] +==== `[.contract-item-name]#++SuperQuorumNumeratorUpdated++#++(uint256 oldSuperQuorumNumerator, uint256 newSuperQuorumNumerator)++` [.item-kind]#event# + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-GovernorInvalidSuperQuorumFraction-uint256-uint256-]] +==== `[.contract-item-name]#++GovernorInvalidSuperQuorumFraction++#++(uint256 superQuorumNumerator, uint256 denominator)++` [.item-kind]#error# + +The super quorum set is not valid as it exceeds the quorum denominator. + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-GovernorInvalidSuperQuorumTooSmall-uint256-uint256-]] +==== `[.contract-item-name]#++GovernorInvalidSuperQuorumTooSmall++#++(uint256 superQuorumNumerator, uint256 quorumNumerator)++` [.item-kind]#error# + +The super quorum set is not valid as it is smaller or equal to the quorum. + +[.contract-item] +[[GovernorVotesSuperQuorumFraction-GovernorInvalidQuorumTooLarge-uint256-uint256-]] +==== `[.contract-item-name]#++GovernorInvalidQuorumTooLarge++#++(uint256 quorumNumerator, uint256 superQuorumNumerator)++` [.item-kind]#error# + +The quorum set is not valid as it exceeds the super quorum. + === Extensions :ExecutionPlan: pass:normal[xref:#GovernorTimelockAccess-ExecutionPlan[`++ExecutionPlan++`]] @@ -3739,9 +5071,24 @@ The quorum set is not a valid fraction. :_executeOperations: pass:normal[xref:#GovernorTimelockAccess-_executeOperations-uint256-address---uint256---bytes---bytes32-[`++_executeOperations++`]] :_cancel: pass:normal[xref:#GovernorTimelockAccess-_cancel-address---uint256---bytes---bytes32-[`++_cancel++`]] +:constructor-address-uint32: pass:normal[xref:#GovernorTimelockAccess-constructor-address-uint32-[`++constructor++`]] +:accessManager-: pass:normal[xref:#GovernorTimelockAccess-accessManager--[`++accessManager++`]] +:baseDelaySeconds-: pass:normal[xref:#GovernorTimelockAccess-baseDelaySeconds--[`++baseDelaySeconds++`]] +:setBaseDelaySeconds-uint32: pass:normal[xref:#GovernorTimelockAccess-setBaseDelaySeconds-uint32-[`++setBaseDelaySeconds++`]] +:_setBaseDelaySeconds-uint32: pass:normal[xref:#GovernorTimelockAccess-_setBaseDelaySeconds-uint32-[`++_setBaseDelaySeconds++`]] +:isAccessManagerIgnored-address-bytes4: pass:normal[xref:#GovernorTimelockAccess-isAccessManagerIgnored-address-bytes4-[`++isAccessManagerIgnored++`]] +:setAccessManagerIgnored-address-bytes4---bool: pass:normal[xref:#GovernorTimelockAccess-setAccessManagerIgnored-address-bytes4---bool-[`++setAccessManagerIgnored++`]] +:_setAccessManagerIgnored-address-bytes4-bool: pass:normal[xref:#GovernorTimelockAccess-_setAccessManagerIgnored-address-bytes4-bool-[`++_setAccessManagerIgnored++`]] +:proposalExecutionPlan-uint256: pass:normal[xref:#GovernorTimelockAccess-proposalExecutionPlan-uint256-[`++proposalExecutionPlan++`]] +:proposalNeedsQueuing-uint256: pass:normal[xref:#GovernorTimelockAccess-proposalNeedsQueuing-uint256-[`++proposalNeedsQueuing++`]] +:propose-address---uint256---bytes---string: pass:normal[xref:#GovernorTimelockAccess-propose-address---uint256---bytes---string-[`++propose++`]] +:_queueOperations-uint256-address---uint256---bytes---bytes32: pass:normal[xref:#GovernorTimelockAccess-_queueOperations-uint256-address---uint256---bytes---bytes32-[`++_queueOperations++`]] +:_executeOperations-uint256-address---uint256---bytes---bytes32: pass:normal[xref:#GovernorTimelockAccess-_executeOperations-uint256-address---uint256---bytes---bytes32-[`++_executeOperations++`]] +:_cancel-address---uint256---bytes---bytes32: pass:normal[xref:#GovernorTimelockAccess-_cancel-address---uint256---bytes---bytes32-[`++_cancel++`]] + [.contract] [[GovernorTimelockAccess]] -=== `++GovernorTimelockAccess++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/extensions/GovernorTimelockAccess.sol[{github-icon},role=heading-link] +=== `++GovernorTimelockAccess++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorTimelockAccess.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3800,6 +5147,7 @@ the same time. See {AccessManager-schedule} for a workaround. * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-state-uint256-}[`++state(proposalId)++`] * {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] @@ -3834,6 +5182,7 @@ the same time. See {AccessManager-schedule} for a workaround. * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-clock--}[`++clock()++`] * {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] * {xref-Governor-votingDelay--}[`++votingDelay()++`] @@ -3947,7 +5296,6 @@ the same time. See {AccessManager-schedule} for a workaround. * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -3960,6 +5308,7 @@ the same time. See {AccessManager-schedule} for a workaround. * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -4078,7 +5427,7 @@ Mechanism to execute a proposal, potentially going through {AccessManager-execut [[GovernorTimelockAccess-_cancel-address---uint256---bytes---bytes32-]] ==== `[.contract-item-name]#++_cancel++#++(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256++` [.item-kind]#internal# -See {IGovernor-_cancel} +See {Governor-_cancel} [.contract-item] [[GovernorTimelockAccess-BaseDelaySet-uint32-uint32-]] @@ -4111,9 +5460,19 @@ See {IGovernor-_cancel} :_executor: pass:normal[xref:#GovernorTimelockControl-_executor--[`++_executor++`]] :updateTimelock: pass:normal[xref:#GovernorTimelockControl-updateTimelock-contract-TimelockController-[`++updateTimelock++`]] +:constructor-contract-TimelockController: pass:normal[xref:#GovernorTimelockControl-constructor-contract-TimelockController-[`++constructor++`]] +:state-uint256: pass:normal[xref:#GovernorTimelockControl-state-uint256-[`++state++`]] +:timelock-: pass:normal[xref:#GovernorTimelockControl-timelock--[`++timelock++`]] +:proposalNeedsQueuing-uint256: pass:normal[xref:#GovernorTimelockControl-proposalNeedsQueuing-uint256-[`++proposalNeedsQueuing++`]] +:_queueOperations-uint256-address---uint256---bytes---bytes32: pass:normal[xref:#GovernorTimelockControl-_queueOperations-uint256-address---uint256---bytes---bytes32-[`++_queueOperations++`]] +:_executeOperations-uint256-address---uint256---bytes---bytes32: pass:normal[xref:#GovernorTimelockControl-_executeOperations-uint256-address---uint256---bytes---bytes32-[`++_executeOperations++`]] +:_cancel-address---uint256---bytes---bytes32: pass:normal[xref:#GovernorTimelockControl-_cancel-address---uint256---bytes---bytes32-[`++_cancel++`]] +:_executor-: pass:normal[xref:#GovernorTimelockControl-_executor--[`++_executor++`]] +:updateTimelock-contract-TimelockController: pass:normal[xref:#GovernorTimelockControl-updateTimelock-contract-TimelockController-[`++updateTimelock++`]] + [.contract] [[GovernorTimelockControl]] -=== `++GovernorTimelockControl++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/extensions/GovernorTimelockControl.sol[{github-icon},role=heading-link] +=== `++GovernorTimelockControl++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorTimelockControl.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -4128,7 +5487,7 @@ Using this model means the proposal will be operated by the {TimelockController} the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be inaccessible from a proposal, unless executed via {Governor-relay}. -WARNING: Setting up the TimelockController to have additional proposers or cancellers besides the governor is very +WARNING: Setting up the TimelockController to have additional proposers or cancelers 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. @@ -4153,6 +5512,7 @@ proposals that have been approved by the voters, effectively executing a Denial * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] * {xref-Governor-proposalDeadline-uint256-}[`++proposalDeadline(proposalId)++`] @@ -4186,6 +5546,7 @@ proposals that have been approved by the voters, effectively executing a Denial * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-clock--}[`++clock()++`] * {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] * {xref-Governor-votingDelay--}[`++votingDelay()++`] @@ -4295,7 +5656,6 @@ proposals that have been approved by the voters, effectively executing a Denial * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -4308,6 +5668,7 @@ proposals that have been approved by the voters, effectively executing a Denial * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -4407,9 +5768,20 @@ Emitted when the timelock controller used for proposal execution is modified. :__acceptAdmin: pass:normal[xref:#GovernorTimelockCompound-__acceptAdmin--[`++__acceptAdmin++`]] :updateTimelock: pass:normal[xref:#GovernorTimelockCompound-updateTimelock-contract-ICompoundTimelock-[`++updateTimelock++`]] +:constructor-contract-ICompoundTimelock: pass:normal[xref:#GovernorTimelockCompound-constructor-contract-ICompoundTimelock-[`++constructor++`]] +:state-uint256: pass:normal[xref:#GovernorTimelockCompound-state-uint256-[`++state++`]] +:timelock-: pass:normal[xref:#GovernorTimelockCompound-timelock--[`++timelock++`]] +:proposalNeedsQueuing-uint256: pass:normal[xref:#GovernorTimelockCompound-proposalNeedsQueuing-uint256-[`++proposalNeedsQueuing++`]] +:_queueOperations-uint256-address---uint256---bytes---bytes32: pass:normal[xref:#GovernorTimelockCompound-_queueOperations-uint256-address---uint256---bytes---bytes32-[`++_queueOperations++`]] +:_executeOperations-uint256-address---uint256---bytes---bytes32: pass:normal[xref:#GovernorTimelockCompound-_executeOperations-uint256-address---uint256---bytes---bytes32-[`++_executeOperations++`]] +:_cancel-address---uint256---bytes---bytes32: pass:normal[xref:#GovernorTimelockCompound-_cancel-address---uint256---bytes---bytes32-[`++_cancel++`]] +:_executor-: pass:normal[xref:#GovernorTimelockCompound-_executor--[`++_executor++`]] +:__acceptAdmin-: pass:normal[xref:#GovernorTimelockCompound-__acceptAdmin--[`++__acceptAdmin++`]] +:updateTimelock-contract-ICompoundTimelock: pass:normal[xref:#GovernorTimelockCompound-updateTimelock-contract-ICompoundTimelock-[`++updateTimelock++`]] + [.contract] [[GovernorTimelockCompound]] -=== `++GovernorTimelockCompound++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/extensions/GovernorTimelockCompound.sol[{github-icon},role=heading-link] +=== `++GovernorTimelockCompound++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorTimelockCompound.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -4417,7 +5789,7 @@ import "@openzeppelin/contracts/governance/extensions/GovernorTimelockCompound.s ``` Extension of {Governor} that binds the execution process to a Compound Timelock. This adds a delay, enforced by -the external timelock to all successful proposal (in addition to the voting duration). The {Governor} needs to be +the external timelock to all successful proposals (in addition to the voting duration). The {Governor} needs to be the admin of the timelock for any operation to be performed. A public, unrestricted, {GovernorTimelockCompound-__acceptAdmin} is available to accept ownership of the timelock. @@ -4446,6 +5818,7 @@ inaccessible from a proposal, unless executed via {Governor-relay}. * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] * {xref-Governor-proposalDeadline-uint256-}[`++proposalDeadline(proposalId)++`] @@ -4479,6 +5852,7 @@ inaccessible from a proposal, unless executed via {Governor-relay}. * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-clock--}[`++clock()++`] * {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] * {xref-Governor-votingDelay--}[`++votingDelay()++`] @@ -4588,7 +5962,6 @@ inaccessible from a proposal, unless executed via {Governor-relay}. * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -4601,6 +5974,7 @@ inaccessible from a proposal, unless executed via {Governor-relay}. * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -4715,9 +6089,20 @@ Emitted when the timelock controller used for proposal execution is modified. :_setVotingPeriod: pass:normal[xref:#GovernorSettings-_setVotingPeriod-uint32-[`++_setVotingPeriod++`]] :_setProposalThreshold: pass:normal[xref:#GovernorSettings-_setProposalThreshold-uint256-[`++_setProposalThreshold++`]] +:constructor-uint48-uint32-uint256: pass:normal[xref:#GovernorSettings-constructor-uint48-uint32-uint256-[`++constructor++`]] +:votingDelay-: pass:normal[xref:#GovernorSettings-votingDelay--[`++votingDelay++`]] +:votingPeriod-: pass:normal[xref:#GovernorSettings-votingPeriod--[`++votingPeriod++`]] +:proposalThreshold-: pass:normal[xref:#GovernorSettings-proposalThreshold--[`++proposalThreshold++`]] +:setVotingDelay-uint48: pass:normal[xref:#GovernorSettings-setVotingDelay-uint48-[`++setVotingDelay++`]] +:setVotingPeriod-uint32: pass:normal[xref:#GovernorSettings-setVotingPeriod-uint32-[`++setVotingPeriod++`]] +:setProposalThreshold-uint256: pass:normal[xref:#GovernorSettings-setProposalThreshold-uint256-[`++setProposalThreshold++`]] +:_setVotingDelay-uint48: pass:normal[xref:#GovernorSettings-_setVotingDelay-uint48-[`++_setVotingDelay++`]] +:_setVotingPeriod-uint32: pass:normal[xref:#GovernorSettings-_setVotingPeriod-uint32-[`++_setVotingPeriod++`]] +:_setProposalThreshold-uint256: pass:normal[xref:#GovernorSettings-_setProposalThreshold-uint256-[`++_setProposalThreshold++`]] + [.contract] [[GovernorSettings]] -=== `++GovernorSettings++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/extensions/GovernorSettings.sol[{github-icon},role=heading-link] +=== `++GovernorSettings++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorSettings.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -4747,6 +6132,7 @@ Extension of {Governor} for settings updatable through governance. * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-state-uint256-}[`++state(proposalId)++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] * {xref-Governor-proposalDeadline-uint256-}[`++proposalDeadline(proposalId)++`] @@ -4785,6 +6171,7 @@ Extension of {Governor} for settings updatable through governance. * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-clock--}[`++clock()++`] * {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] * {xref-Governor-quorum-uint256-}[`++quorum(timepoint)++`] @@ -4894,7 +6281,6 @@ Extension of {Governor} for settings updatable through governance. * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -4907,6 +6293,7 @@ Extension of {Governor} for settings updatable through governance. * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -5022,9 +6409,16 @@ Emits a {ProposalThresholdSet} event. :setLateQuorumVoteExtension: pass:normal[xref:#GovernorPreventLateQuorum-setLateQuorumVoteExtension-uint48-[`++setLateQuorumVoteExtension++`]] :_setLateQuorumVoteExtension: pass:normal[xref:#GovernorPreventLateQuorum-_setLateQuorumVoteExtension-uint48-[`++_setLateQuorumVoteExtension++`]] +:constructor-uint48: pass:normal[xref:#GovernorPreventLateQuorum-constructor-uint48-[`++constructor++`]] +:proposalDeadline-uint256: pass:normal[xref:#GovernorPreventLateQuorum-proposalDeadline-uint256-[`++proposalDeadline++`]] +:_tallyUpdated-uint256: pass:normal[xref:#GovernorPreventLateQuorum-_tallyUpdated-uint256-[`++_tallyUpdated++`]] +:lateQuorumVoteExtension-: pass:normal[xref:#GovernorPreventLateQuorum-lateQuorumVoteExtension--[`++lateQuorumVoteExtension++`]] +:setLateQuorumVoteExtension-uint48: pass:normal[xref:#GovernorPreventLateQuorum-setLateQuorumVoteExtension-uint48-[`++setLateQuorumVoteExtension++`]] +:_setLateQuorumVoteExtension-uint48: pass:normal[xref:#GovernorPreventLateQuorum-_setLateQuorumVoteExtension-uint48-[`++_setLateQuorumVoteExtension++`]] + [.contract] [[GovernorPreventLateQuorum]] -=== `++GovernorPreventLateQuorum++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/extensions/GovernorPreventLateQuorum.sol[{github-icon},role=heading-link] +=== `++GovernorPreventLateQuorum++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorPreventLateQuorum.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -5056,6 +6450,7 @@ proposal. * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-state-uint256-}[`++state(proposalId)++`] * {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] @@ -5093,6 +6488,7 @@ proposal. * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-clock--}[`++clock()++`] * {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] * {xref-Governor-votingDelay--}[`++votingDelay()++`] @@ -5203,7 +6599,6 @@ proposal. * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -5216,6 +6611,7 @@ proposal. * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -5307,9 +6703,17 @@ Emitted when the {lateQuorumVoteExtension} parameter is changed. :proposalDetails: pass:normal[xref:#GovernorStorage-proposalDetails-uint256-[`++proposalDetails++`]] :proposalDetailsAt: pass:normal[xref:#GovernorStorage-proposalDetailsAt-uint256-[`++proposalDetailsAt++`]] +:_propose-address---uint256---bytes---string-address: pass:normal[xref:#GovernorStorage-_propose-address---uint256---bytes---string-address-[`++_propose++`]] +:queue-uint256: pass:normal[xref:#GovernorStorage-queue-uint256-[`++queue++`]] +:execute-uint256: pass:normal[xref:#GovernorStorage-execute-uint256-[`++execute++`]] +:cancel-uint256: pass:normal[xref:#GovernorStorage-cancel-uint256-[`++cancel++`]] +:proposalCount-: pass:normal[xref:#GovernorStorage-proposalCount--[`++proposalCount++`]] +:proposalDetails-uint256: pass:normal[xref:#GovernorStorage-proposalDetails-uint256-[`++proposalDetails++`]] +:proposalDetailsAt-uint256: pass:normal[xref:#GovernorStorage-proposalDetailsAt-uint256-[`++proposalDetailsAt++`]] + [.contract] [[GovernorStorage]] -=== `++GovernorStorage++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/extensions/GovernorStorage.sol[{github-icon},role=heading-link] +=== `++GovernorStorage++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorStorage.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -5342,6 +6746,7 @@ Use cases for this module include: * {xref-Governor-name--}[`++name()++`] * {xref-Governor-version--}[`++version()++`] * {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] * {xref-Governor-state-uint256-}[`++state(proposalId)++`] * {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] * {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] @@ -5380,6 +6785,7 @@ Use cases for this module include: * {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] * {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] * {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] * {xref-Governor-clock--}[`++clock()++`] * {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] * {xref-Governor-votingDelay--}[`++votingDelay()++`] @@ -5488,7 +6894,6 @@ Use cases for this module include: * {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] * {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] * {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] -* {xref-IGovernor-GovernorOnlyProposer-address-}[`++GovernorOnlyProposer(account)++`] * {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] * {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] * {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] @@ -5501,6 +6906,7 @@ Use cases for this module include: * {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] * {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] [.contract-subindex-inherited] .IERC6372 @@ -5533,7 +6939,7 @@ Hook into the proposing mechanism [[GovernorStorage-queue-uint256-]] ==== `[.contract-item-name]#++queue++#++(uint256 proposalId)++` [.item-kind]#public# -Version of {IGovernorTimelock-queue} with only `proposalId` as an argument. +Version of {IGovernor-queue} with only `proposalId` as an argument. [.contract-item] [[GovernorStorage-execute-uint256-]] @@ -5565,6 +6971,518 @@ Returns the details of a proposalId. Reverts if `proposalId` is not a known prop Returns the details (including the proposalId) of a proposal given its sequential index. +:ProposalGuardianSet: pass:normal[xref:#GovernorProposalGuardian-ProposalGuardianSet-address-address-[`++ProposalGuardianSet++`]] +:proposalGuardian: pass:normal[xref:#GovernorProposalGuardian-proposalGuardian--[`++proposalGuardian++`]] +:setProposalGuardian: pass:normal[xref:#GovernorProposalGuardian-setProposalGuardian-address-[`++setProposalGuardian++`]] +:_setProposalGuardian: pass:normal[xref:#GovernorProposalGuardian-_setProposalGuardian-address-[`++_setProposalGuardian++`]] +:_validateCancel: pass:normal[xref:#GovernorProposalGuardian-_validateCancel-uint256-address-[`++_validateCancel++`]] + +:proposalGuardian-: pass:normal[xref:#GovernorProposalGuardian-proposalGuardian--[`++proposalGuardian++`]] +:setProposalGuardian-address: pass:normal[xref:#GovernorProposalGuardian-setProposalGuardian-address-[`++setProposalGuardian++`]] +:_setProposalGuardian-address: pass:normal[xref:#GovernorProposalGuardian-_setProposalGuardian-address-[`++_setProposalGuardian++`]] +:_validateCancel-uint256-address: pass:normal[xref:#GovernorProposalGuardian-_validateCancel-uint256-address-[`++_validateCancel++`]] + +[.contract] +[[GovernorProposalGuardian]] +=== `++GovernorProposalGuardian++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorProposalGuardian.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/governance/extensions/GovernorProposalGuardian.sol"; +``` + +Extension of {Governor} which adds a proposal guardian that can cancel proposals at any stage in the proposal's lifecycle. + +NOTE: if the proposal guardian is not configured, then proposers take this role for their proposals. + +[.contract-index] +.Functions +-- +* {xref-GovernorProposalGuardian-proposalGuardian--}[`++proposalGuardian()++`] +* {xref-GovernorProposalGuardian-setProposalGuardian-address-}[`++setProposalGuardian(newProposalGuardian)++`] +* {xref-GovernorProposalGuardian-_setProposalGuardian-address-}[`++_setProposalGuardian(newProposalGuardian)++`] +* {xref-GovernorProposalGuardian-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] + +[.contract-subindex-inherited] +.Governor +* {xref-Governor-receive--}[`++receive()++`] +* {xref-Governor-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] +* {xref-Governor-name--}[`++name()++`] +* {xref-Governor-version--}[`++version()++`] +* {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-state-uint256-}[`++state(proposalId)++`] +* {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] +* {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] +* {xref-Governor-proposalDeadline-uint256-}[`++proposalDeadline(proposalId)++`] +* {xref-Governor-proposalProposer-uint256-}[`++proposalProposer(proposalId)++`] +* {xref-Governor-proposalEta-uint256-}[`++proposalEta(proposalId)++`] +* {xref-Governor-proposalNeedsQueuing-uint256-}[`++proposalNeedsQueuing()++`] +* {xref-Governor-_checkGovernance--}[`++_checkGovernance()++`] +* {xref-Governor-_quorumReached-uint256-}[`++_quorumReached(proposalId)++`] +* {xref-Governor-_voteSucceeded-uint256-}[`++_voteSucceeded(proposalId)++`] +* {xref-Governor-_getVotes-address-uint256-bytes-}[`++_getVotes(account, timepoint, params)++`] +* {xref-Governor-_countVote-uint256-address-uint8-uint256-bytes-}[`++_countVote(proposalId, account, support, totalWeight, params)++`] +* {xref-Governor-_tallyUpdated-uint256-}[`++_tallyUpdated(proposalId)++`] +* {xref-Governor-_defaultParams--}[`++_defaultParams()++`] +* {xref-Governor-propose-address---uint256---bytes---string-}[`++propose(targets, values, calldatas, description)++`] +* {xref-Governor-_propose-address---uint256---bytes---string-address-}[`++_propose(targets, values, calldatas, description, proposer)++`] +* {xref-Governor-queue-address---uint256---bytes---bytes32-}[`++queue(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_queueOperations-uint256-address---uint256---bytes---bytes32-}[`++_queueOperations(, , , , )++`] +* {xref-Governor-execute-address---uint256---bytes---bytes32-}[`++execute(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_executeOperations-uint256-address---uint256---bytes---bytes32-}[`++_executeOperations(, targets, values, calldatas, )++`] +* {xref-Governor-cancel-address---uint256---bytes---bytes32-}[`++cancel(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_cancel-address---uint256---bytes---bytes32-}[`++_cancel(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getVotes-address-uint256-}[`++getVotes(account, timepoint)++`] +* {xref-Governor-getVotesWithParams-address-uint256-bytes-}[`++getVotesWithParams(account, timepoint, params)++`] +* {xref-Governor-castVote-uint256-uint8-}[`++castVote(proposalId, support)++`] +* {xref-Governor-castVoteWithReason-uint256-uint8-string-}[`++castVoteWithReason(proposalId, support, reason)++`] +* {xref-Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes-}[`++castVoteWithReasonAndParams(proposalId, support, reason, params)++`] +* {xref-Governor-castVoteBySig-uint256-uint8-address-bytes-}[`++castVoteBySig(proposalId, support, voter, signature)++`] +* {xref-Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-}[`++castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)++`] +* {xref-Governor-_castVote-uint256-address-uint8-string-}[`++_castVote(proposalId, account, support, reason)++`] +* {xref-Governor-_castVote-uint256-address-uint8-string-bytes-}[`++_castVote(proposalId, account, support, reason, params)++`] +* {xref-Governor-relay-address-uint256-bytes-}[`++relay(target, value, data)++`] +* {xref-Governor-_executor--}[`++_executor()++`] +* {xref-Governor-onERC721Received-address-address-uint256-bytes-}[`++onERC721Received(, , , )++`] +* {xref-Governor-onERC1155Received-address-address-uint256-uint256-bytes-}[`++onERC1155Received(, , , , )++`] +* {xref-Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes-}[`++onERC1155BatchReceived(, , , , )++`] +* {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] +* {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] +* {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-clock--}[`++clock()++`] +* {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] +* {xref-Governor-votingDelay--}[`++votingDelay()++`] +* {xref-Governor-votingPeriod--}[`++votingPeriod()++`] +* {xref-Governor-quorum-uint256-}[`++quorum(timepoint)++`] +* {xref-Governor-BALLOT_TYPEHASH-bytes32}[`++BALLOT_TYPEHASH()++`] +* {xref-Governor-EXTENDED_BALLOT_TYPEHASH-bytes32}[`++EXTENDED_BALLOT_TYPEHASH()++`] + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-COUNTING_MODE--}[`++COUNTING_MODE()++`] +* {xref-IGovernor-hasVoted-uint256-address-}[`++hasVoted(proposalId, account)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces +* {xref-Nonces-nonces-address-}[`++nonces(owner)++`] +* {xref-Nonces-_useNonce-address-}[`++_useNonce(owner)++`] +* {xref-Nonces-_useCheckedNonce-address-uint256-}[`++_useCheckedNonce(owner, nonce)++`] + +[.contract-subindex-inherited] +.EIP712 +* {xref-EIP712-_domainSeparatorV4--}[`++_domainSeparatorV4()++`] +* {xref-EIP712-_hashTypedDataV4-bytes32-}[`++_hashTypedDataV4(structHash)++`] +* {xref-EIP712-eip712Domain--}[`++eip712Domain()++`] +* {xref-EIP712-_EIP712Name--}[`++_EIP712Name()++`] +* {xref-EIP712-_EIP712Version--}[`++_EIP712Version()++`] + +[.contract-subindex-inherited] +.IERC5267 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Events +-- +* {xref-GovernorProposalGuardian-ProposalGuardianSet-address-address-}[`++ProposalGuardianSet(oldProposalGuardian, newProposalGuardian)++`] + +[.contract-subindex-inherited] +.Governor + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string-}[`++ProposalCreated(proposalId, proposer, targets, values, signatures, calldatas, voteStart, voteEnd, description)++`] +* {xref-IGovernor-ProposalQueued-uint256-uint256-}[`++ProposalQueued(proposalId, etaSeconds)++`] +* {xref-IGovernor-ProposalExecuted-uint256-}[`++ProposalExecuted(proposalId)++`] +* {xref-IGovernor-ProposalCanceled-uint256-}[`++ProposalCanceled(proposalId)++`] +* {xref-IGovernor-VoteCast-address-uint256-uint8-uint256-string-}[`++VoteCast(voter, proposalId, support, weight, reason)++`] +* {xref-IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes-}[`++VoteCastWithParams(voter, proposalId, support, weight, reason, params)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces + +[.contract-subindex-inherited] +.EIP712 + +[.contract-subindex-inherited] +.IERC5267 +* {xref-IERC5267-EIP712DomainChanged--}[`++EIP712DomainChanged()++`] + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Errors +-- + +[.contract-subindex-inherited] +.Governor + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] +* {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] +* {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] +* {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] +* {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] +* {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] +* {xref-IGovernor-GovernorInvalidVotingPeriod-uint256-}[`++GovernorInvalidVotingPeriod(votingPeriod)++`] +* {xref-IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256-}[`++GovernorInsufficientProposerVotes(proposer, votes, threshold)++`] +* {xref-IGovernor-GovernorRestrictedProposer-address-}[`++GovernorRestrictedProposer(proposer)++`] +* {xref-IGovernor-GovernorInvalidVoteType--}[`++GovernorInvalidVoteType()++`] +* {xref-IGovernor-GovernorInvalidVoteParams--}[`++GovernorInvalidVoteParams()++`] +* {xref-IGovernor-GovernorQueueNotImplemented--}[`++GovernorQueueNotImplemented()++`] +* {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] +* {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] +* {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces +* {xref-Nonces-InvalidAccountNonce-address-uint256-}[`++InvalidAccountNonce(account, currentNonce)++`] + +[.contract-subindex-inherited] +.EIP712 + +[.contract-subindex-inherited] +.IERC5267 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[GovernorProposalGuardian-proposalGuardian--]] +==== `[.contract-item-name]#++proposalGuardian++#++() → address++` [.item-kind]#public# + +Getter that returns the address of the proposal guardian. + +[.contract-item] +[[GovernorProposalGuardian-setProposalGuardian-address-]] +==== `[.contract-item-name]#++setProposalGuardian++#++(address newProposalGuardian)++` [.item-kind]#public# + +Update the proposal guardian's address. This operation can only be performed through a governance proposal. + +Emits a {ProposalGuardianSet} event. + +[.contract-item] +[[GovernorProposalGuardian-_setProposalGuardian-address-]] +==== `[.contract-item-name]#++_setProposalGuardian++#++(address newProposalGuardian)++` [.item-kind]#internal# + +Internal setter for the proposal guardian. + +Emits a {ProposalGuardianSet} event. + +[.contract-item] +[[GovernorProposalGuardian-_validateCancel-uint256-address-]] +==== `[.contract-item-name]#++_validateCancel++#++(uint256 proposalId, address caller) → bool++` [.item-kind]#internal# + +Override {Governor-_validateCancel} to implement the extended cancellation logic. + +* The {proposalGuardian} can cancel any proposal at any point. +* If no proposal guardian is set, the {IGovernor-proposalProposer} can cancel their proposals at any point. +* In any case, permissions defined in {Governor-_validateCancel} (or another override) remains valid. + +[.contract-item] +[[GovernorProposalGuardian-ProposalGuardianSet-address-address-]] +==== `[.contract-item-name]#++ProposalGuardianSet++#++(address oldProposalGuardian, address newProposalGuardian)++` [.item-kind]#event# + +:superQuorum: pass:normal[xref:#GovernorSuperQuorum-superQuorum-uint256-[`++superQuorum++`]] +:proposalVotes: pass:normal[xref:#GovernorSuperQuorum-proposalVotes-uint256-[`++proposalVotes++`]] +:state: pass:normal[xref:#GovernorSuperQuorum-state-uint256-[`++state++`]] + +:superQuorum-uint256: pass:normal[xref:#GovernorSuperQuorum-superQuorum-uint256-[`++superQuorum++`]] +:proposalVotes-uint256: pass:normal[xref:#GovernorSuperQuorum-proposalVotes-uint256-[`++proposalVotes++`]] +:state-uint256: pass:normal[xref:#GovernorSuperQuorum-state-uint256-[`++state++`]] + +[.contract] +[[GovernorSuperQuorum]] +=== `++GovernorSuperQuorum++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/extensions/GovernorSuperQuorum.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/governance/extensions/GovernorSuperQuorum.sol"; +``` + +Extension of {Governor} with a super quorum. Proposals that meet the super quorum (and have a majority of for +votes) advance to the `Succeeded` state before the proposal deadline. Counting modules that want to use this +extension must implement {proposalVotes}. + +[.contract-index] +.Functions +-- +* {xref-GovernorSuperQuorum-superQuorum-uint256-}[`++superQuorum(timepoint)++`] +* {xref-GovernorSuperQuorum-proposalVotes-uint256-}[`++proposalVotes(proposalId)++`] +* {xref-GovernorSuperQuorum-state-uint256-}[`++state(proposalId)++`] + +[.contract-subindex-inherited] +.Governor +* {xref-Governor-receive--}[`++receive()++`] +* {xref-Governor-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] +* {xref-Governor-name--}[`++name()++`] +* {xref-Governor-version--}[`++version()++`] +* {xref-Governor-hashProposal-address---uint256---bytes---bytes32-}[`++hashProposal(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getProposalId-address---uint256---bytes---bytes32-}[`++getProposalId(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-proposalThreshold--}[`++proposalThreshold()++`] +* {xref-Governor-proposalSnapshot-uint256-}[`++proposalSnapshot(proposalId)++`] +* {xref-Governor-proposalDeadline-uint256-}[`++proposalDeadline(proposalId)++`] +* {xref-Governor-proposalProposer-uint256-}[`++proposalProposer(proposalId)++`] +* {xref-Governor-proposalEta-uint256-}[`++proposalEta(proposalId)++`] +* {xref-Governor-proposalNeedsQueuing-uint256-}[`++proposalNeedsQueuing()++`] +* {xref-Governor-_checkGovernance--}[`++_checkGovernance()++`] +* {xref-Governor-_quorumReached-uint256-}[`++_quorumReached(proposalId)++`] +* {xref-Governor-_voteSucceeded-uint256-}[`++_voteSucceeded(proposalId)++`] +* {xref-Governor-_getVotes-address-uint256-bytes-}[`++_getVotes(account, timepoint, params)++`] +* {xref-Governor-_countVote-uint256-address-uint8-uint256-bytes-}[`++_countVote(proposalId, account, support, totalWeight, params)++`] +* {xref-Governor-_tallyUpdated-uint256-}[`++_tallyUpdated(proposalId)++`] +* {xref-Governor-_defaultParams--}[`++_defaultParams()++`] +* {xref-Governor-propose-address---uint256---bytes---string-}[`++propose(targets, values, calldatas, description)++`] +* {xref-Governor-_propose-address---uint256---bytes---string-address-}[`++_propose(targets, values, calldatas, description, proposer)++`] +* {xref-Governor-queue-address---uint256---bytes---bytes32-}[`++queue(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_queueOperations-uint256-address---uint256---bytes---bytes32-}[`++_queueOperations(, , , , )++`] +* {xref-Governor-execute-address---uint256---bytes---bytes32-}[`++execute(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_executeOperations-uint256-address---uint256---bytes---bytes32-}[`++_executeOperations(, targets, values, calldatas, )++`] +* {xref-Governor-cancel-address---uint256---bytes---bytes32-}[`++cancel(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-_cancel-address---uint256---bytes---bytes32-}[`++_cancel(targets, values, calldatas, descriptionHash)++`] +* {xref-Governor-getVotes-address-uint256-}[`++getVotes(account, timepoint)++`] +* {xref-Governor-getVotesWithParams-address-uint256-bytes-}[`++getVotesWithParams(account, timepoint, params)++`] +* {xref-Governor-castVote-uint256-uint8-}[`++castVote(proposalId, support)++`] +* {xref-Governor-castVoteWithReason-uint256-uint8-string-}[`++castVoteWithReason(proposalId, support, reason)++`] +* {xref-Governor-castVoteWithReasonAndParams-uint256-uint8-string-bytes-}[`++castVoteWithReasonAndParams(proposalId, support, reason, params)++`] +* {xref-Governor-castVoteBySig-uint256-uint8-address-bytes-}[`++castVoteBySig(proposalId, support, voter, signature)++`] +* {xref-Governor-castVoteWithReasonAndParamsBySig-uint256-uint8-address-string-bytes-bytes-}[`++castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)++`] +* {xref-Governor-_castVote-uint256-address-uint8-string-}[`++_castVote(proposalId, account, support, reason)++`] +* {xref-Governor-_castVote-uint256-address-uint8-string-bytes-}[`++_castVote(proposalId, account, support, reason, params)++`] +* {xref-Governor-relay-address-uint256-bytes-}[`++relay(target, value, data)++`] +* {xref-Governor-_executor--}[`++_executor()++`] +* {xref-Governor-onERC721Received-address-address-uint256-bytes-}[`++onERC721Received(, , , )++`] +* {xref-Governor-onERC1155Received-address-address-uint256-uint256-bytes-}[`++onERC1155Received(, , , , )++`] +* {xref-Governor-onERC1155BatchReceived-address-address-uint256---uint256---bytes-}[`++onERC1155BatchReceived(, , , , )++`] +* {xref-Governor-_encodeStateBitmap-enum-IGovernor-ProposalState-}[`++_encodeStateBitmap(proposalState)++`] +* {xref-Governor-_validateStateBitmap-uint256-bytes32-}[`++_validateStateBitmap(proposalId, allowedStates)++`] +* {xref-Governor-_isValidDescriptionForProposer-address-string-}[`++_isValidDescriptionForProposer(proposer, description)++`] +* {xref-Governor-_validateCancel-uint256-address-}[`++_validateCancel(proposalId, caller)++`] +* {xref-Governor-clock--}[`++clock()++`] +* {xref-Governor-CLOCK_MODE--}[`++CLOCK_MODE()++`] +* {xref-Governor-votingDelay--}[`++votingDelay()++`] +* {xref-Governor-votingPeriod--}[`++votingPeriod()++`] +* {xref-Governor-quorum-uint256-}[`++quorum(timepoint)++`] +* {xref-Governor-BALLOT_TYPEHASH-bytes32}[`++BALLOT_TYPEHASH()++`] +* {xref-Governor-EXTENDED_BALLOT_TYPEHASH-bytes32}[`++EXTENDED_BALLOT_TYPEHASH()++`] + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-COUNTING_MODE--}[`++COUNTING_MODE()++`] +* {xref-IGovernor-hasVoted-uint256-address-}[`++hasVoted(proposalId, account)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces +* {xref-Nonces-nonces-address-}[`++nonces(owner)++`] +* {xref-Nonces-_useNonce-address-}[`++_useNonce(owner)++`] +* {xref-Nonces-_useCheckedNonce-address-uint256-}[`++_useCheckedNonce(owner, nonce)++`] + +[.contract-subindex-inherited] +.EIP712 +* {xref-EIP712-_domainSeparatorV4--}[`++_domainSeparatorV4()++`] +* {xref-EIP712-_hashTypedDataV4-bytes32-}[`++_hashTypedDataV4(structHash)++`] +* {xref-EIP712-eip712Domain--}[`++eip712Domain()++`] +* {xref-EIP712-_EIP712Name--}[`++_EIP712Name()++`] +* {xref-EIP712-_EIP712Version--}[`++_EIP712Version()++`] + +[.contract-subindex-inherited] +.IERC5267 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Events +-- + +[.contract-subindex-inherited] +.Governor + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-ProposalCreated-uint256-address-address---uint256---string---bytes---uint256-uint256-string-}[`++ProposalCreated(proposalId, proposer, targets, values, signatures, calldatas, voteStart, voteEnd, description)++`] +* {xref-IGovernor-ProposalQueued-uint256-uint256-}[`++ProposalQueued(proposalId, etaSeconds)++`] +* {xref-IGovernor-ProposalExecuted-uint256-}[`++ProposalExecuted(proposalId)++`] +* {xref-IGovernor-ProposalCanceled-uint256-}[`++ProposalCanceled(proposalId)++`] +* {xref-IGovernor-VoteCast-address-uint256-uint8-uint256-string-}[`++VoteCast(voter, proposalId, support, weight, reason)++`] +* {xref-IGovernor-VoteCastWithParams-address-uint256-uint8-uint256-string-bytes-}[`++VoteCastWithParams(voter, proposalId, support, weight, reason, params)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces + +[.contract-subindex-inherited] +.EIP712 + +[.contract-subindex-inherited] +.IERC5267 +* {xref-IERC5267-EIP712DomainChanged--}[`++EIP712DomainChanged()++`] + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Errors +-- + +[.contract-subindex-inherited] +.Governor + +[.contract-subindex-inherited] +.IERC1155Receiver + +[.contract-subindex-inherited] +.IERC721Receiver + +[.contract-subindex-inherited] +.IGovernor +* {xref-IGovernor-GovernorInvalidProposalLength-uint256-uint256-uint256-}[`++GovernorInvalidProposalLength(targets, calldatas, values)++`] +* {xref-IGovernor-GovernorAlreadyCastVote-address-}[`++GovernorAlreadyCastVote(voter)++`] +* {xref-IGovernor-GovernorDisabledDeposit--}[`++GovernorDisabledDeposit()++`] +* {xref-IGovernor-GovernorOnlyExecutor-address-}[`++GovernorOnlyExecutor(account)++`] +* {xref-IGovernor-GovernorNonexistentProposal-uint256-}[`++GovernorNonexistentProposal(proposalId)++`] +* {xref-IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-ProposalState-bytes32-}[`++GovernorUnexpectedProposalState(proposalId, current, expectedStates)++`] +* {xref-IGovernor-GovernorInvalidVotingPeriod-uint256-}[`++GovernorInvalidVotingPeriod(votingPeriod)++`] +* {xref-IGovernor-GovernorInsufficientProposerVotes-address-uint256-uint256-}[`++GovernorInsufficientProposerVotes(proposer, votes, threshold)++`] +* {xref-IGovernor-GovernorRestrictedProposer-address-}[`++GovernorRestrictedProposer(proposer)++`] +* {xref-IGovernor-GovernorInvalidVoteType--}[`++GovernorInvalidVoteType()++`] +* {xref-IGovernor-GovernorInvalidVoteParams--}[`++GovernorInvalidVoteParams()++`] +* {xref-IGovernor-GovernorQueueNotImplemented--}[`++GovernorQueueNotImplemented()++`] +* {xref-IGovernor-GovernorNotQueuedProposal-uint256-}[`++GovernorNotQueuedProposal(proposalId)++`] +* {xref-IGovernor-GovernorAlreadyQueuedProposal-uint256-}[`++GovernorAlreadyQueuedProposal(proposalId)++`] +* {xref-IGovernor-GovernorInvalidSignature-address-}[`++GovernorInvalidSignature(voter)++`] +* {xref-IGovernor-GovernorUnableToCancel-uint256-address-}[`++GovernorUnableToCancel(proposalId, account)++`] + +[.contract-subindex-inherited] +.IERC6372 + +[.contract-subindex-inherited] +.Nonces +* {xref-Nonces-InvalidAccountNonce-address-uint256-}[`++InvalidAccountNonce(account, currentNonce)++`] + +[.contract-subindex-inherited] +.EIP712 + +[.contract-subindex-inherited] +.IERC5267 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[GovernorSuperQuorum-superQuorum-uint256-]] +==== `[.contract-item-name]#++superQuorum++#++(uint256 timepoint) → uint256++` [.item-kind]#public# + +Minimum number of cast votes required for a proposal to reach super quorum. Only FOR votes are counted +towards the super quorum. Once the super quorum is reached, an active proposal can proceed to the next state +without waiting for the proposal deadline. + +NOTE: The `timepoint` parameter corresponds to the snapshot used for counting the vote. This enables scaling of the +quorum depending on values such as the `totalSupply` of a token at this timepoint (see {ERC20Votes}). + +NOTE: Make sure the value specified for the super quorum is greater than {quorum}, otherwise, it may be +possible to pass a proposal with less votes than the default quorum. + +[.contract-item] +[[GovernorSuperQuorum-proposalVotes-uint256-]] +==== `[.contract-item-name]#++proposalVotes++#++(uint256 proposalId) → uint256 againstVotes, uint256 forVotes, uint256 abstainVotes++` [.item-kind]#public# + +Accessor to the internal vote counts. This must be implemented by the counting module. Counting modules +that don't implement this function are incompatible with this module + +[.contract-item] +[[GovernorSuperQuorum-state-uint256-]] +==== `[.contract-item-name]#++state++#++(uint256 proposalId) → enum IGovernor.ProposalState++` [.item-kind]#public# + +Overridden version of the {Governor-state} function that checks if the proposal has reached the super +quorum. + +NOTE: If the proposal reaches super quorum but {_voteSucceeded} returns false, eg, assuming the super quorum +has been set low enough that both FOR and AGAINST votes have exceeded it and AGAINST votes exceed FOR votes, +the proposal continues to be active until {_voteSucceeded} returns true or the proposal deadline is reached. +This means that with a low super quorum it is also possible that a vote can succeed prematurely before enough +AGAINST voters have a chance to vote. Hence, it is recommended to set a high enough super quorum to avoid these +types of scenarios. + == Utils :ERC6372InconsistentClock: pass:normal[xref:#Votes-ERC6372InconsistentClock--[`++ERC6372InconsistentClock++`]] @@ -5586,9 +7504,26 @@ Returns the details (including the proposalId) of a proposal given its sequentia :_checkpoints: pass:normal[xref:#Votes-_checkpoints-address-uint32-[`++_checkpoints++`]] :_getVotingUnits: pass:normal[xref:#Votes-_getVotingUnits-address-[`++_getVotingUnits++`]] +:clock-: pass:normal[xref:#Votes-clock--[`++clock++`]] +:CLOCK_MODE-: pass:normal[xref:#Votes-CLOCK_MODE--[`++CLOCK_MODE++`]] +:_validateTimepoint-uint256: pass:normal[xref:#Votes-_validateTimepoint-uint256-[`++_validateTimepoint++`]] +:getVotes-address: pass:normal[xref:#Votes-getVotes-address-[`++getVotes++`]] +:getPastVotes-address-uint256: pass:normal[xref:#Votes-getPastVotes-address-uint256-[`++getPastVotes++`]] +:getPastTotalSupply-uint256: pass:normal[xref:#Votes-getPastTotalSupply-uint256-[`++getPastTotalSupply++`]] +:_getTotalSupply-: pass:normal[xref:#Votes-_getTotalSupply--[`++_getTotalSupply++`]] +:delegates-address: pass:normal[xref:#Votes-delegates-address-[`++delegates++`]] +:delegate-address: pass:normal[xref:#Votes-delegate-address-[`++delegate++`]] +:delegateBySig-address-uint256-uint256-uint8-bytes32-bytes32: pass:normal[xref:#Votes-delegateBySig-address-uint256-uint256-uint8-bytes32-bytes32-[`++delegateBySig++`]] +:_delegate-address-address: pass:normal[xref:#Votes-_delegate-address-address-[`++_delegate++`]] +:_transferVotingUnits-address-address-uint256: pass:normal[xref:#Votes-_transferVotingUnits-address-address-uint256-[`++_transferVotingUnits++`]] +:_moveDelegateVotes-address-address-uint256: pass:normal[xref:#Votes-_moveDelegateVotes-address-address-uint256-[`++_moveDelegateVotes++`]] +:_numCheckpoints-address: pass:normal[xref:#Votes-_numCheckpoints-address-[`++_numCheckpoints++`]] +:_checkpoints-address-uint32: pass:normal[xref:#Votes-_checkpoints-address-uint32-[`++_checkpoints++`]] +:_getVotingUnits-address: pass:normal[xref:#Votes-_getVotingUnits-address-[`++_getVotingUnits++`]] + [.contract] [[Votes]] -=== `++Votes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/utils/Votes.sol[{github-icon},role=heading-link] +=== `++Votes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/utils/Votes.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -5846,9 +7781,14 @@ Lookup to future votes is not available. :_delegate: pass:normal[xref:#VotesExtended-_delegate-address-address-[`++_delegate++`]] :_transferVotingUnits: pass:normal[xref:#VotesExtended-_transferVotingUnits-address-address-uint256-[`++_transferVotingUnits++`]] +:getPastDelegate-address-uint256: pass:normal[xref:#VotesExtended-getPastDelegate-address-uint256-[`++getPastDelegate++`]] +:getPastBalanceOf-address-uint256: pass:normal[xref:#VotesExtended-getPastBalanceOf-address-uint256-[`++getPastBalanceOf++`]] +:_delegate-address-address: pass:normal[xref:#VotesExtended-_delegate-address-address-[`++_delegate++`]] +:_transferVotingUnits-address-address-uint256: pass:normal[xref:#VotesExtended-_transferVotingUnits-address-address-uint256-[`++_transferVotingUnits++`]] + [.contract] [[VotesExtended]] -=== `++VotesExtended++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/utils/VotesExtended.sol[{github-icon},role=heading-link] +=== `++VotesExtended++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/utils/VotesExtended.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -6071,9 +8011,33 @@ In a governance system, the {TimelockController} contract is in charge of introd :updateDelay: pass:normal[xref:#TimelockController-updateDelay-uint256-[`++updateDelay++`]] :_encodeStateBitmap: pass:normal[xref:#TimelockController-_encodeStateBitmap-enum-TimelockController-OperationState-[`++_encodeStateBitmap++`]] +:constructor-uint256-address---address---address: pass:normal[xref:#TimelockController-constructor-uint256-address---address---address-[`++constructor++`]] +:receive-: pass:normal[xref:#TimelockController-receive--[`++receive++`]] +:supportsInterface-bytes4: pass:normal[xref:#TimelockController-supportsInterface-bytes4-[`++supportsInterface++`]] +:isOperation-bytes32: pass:normal[xref:#TimelockController-isOperation-bytes32-[`++isOperation++`]] +:isOperationPending-bytes32: pass:normal[xref:#TimelockController-isOperationPending-bytes32-[`++isOperationPending++`]] +:isOperationReady-bytes32: pass:normal[xref:#TimelockController-isOperationReady-bytes32-[`++isOperationReady++`]] +:isOperationDone-bytes32: pass:normal[xref:#TimelockController-isOperationDone-bytes32-[`++isOperationDone++`]] +:getTimestamp-bytes32: pass:normal[xref:#TimelockController-getTimestamp-bytes32-[`++getTimestamp++`]] +:getOperationState-bytes32: pass:normal[xref:#TimelockController-getOperationState-bytes32-[`++getOperationState++`]] +:getMinDelay-: pass:normal[xref:#TimelockController-getMinDelay--[`++getMinDelay++`]] +:hashOperation-address-uint256-bytes-bytes32-bytes32: pass:normal[xref:#TimelockController-hashOperation-address-uint256-bytes-bytes32-bytes32-[`++hashOperation++`]] +:hashOperationBatch-address---uint256---bytes---bytes32-bytes32: pass:normal[xref:#TimelockController-hashOperationBatch-address---uint256---bytes---bytes32-bytes32-[`++hashOperationBatch++`]] +:schedule-address-uint256-bytes-bytes32-bytes32-uint256: pass:normal[xref:#TimelockController-schedule-address-uint256-bytes-bytes32-bytes32-uint256-[`++schedule++`]] +:scheduleBatch-address---uint256---bytes---bytes32-bytes32-uint256: pass:normal[xref:#TimelockController-scheduleBatch-address---uint256---bytes---bytes32-bytes32-uint256-[`++scheduleBatch++`]] +:cancel-bytes32: pass:normal[xref:#TimelockController-cancel-bytes32-[`++cancel++`]] +:execute-address-uint256-bytes-bytes32-bytes32: pass:normal[xref:#TimelockController-execute-address-uint256-bytes-bytes32-bytes32-[`++execute++`]] +:executeBatch-address---uint256---bytes---bytes32-bytes32: pass:normal[xref:#TimelockController-executeBatch-address---uint256---bytes---bytes32-bytes32-[`++executeBatch++`]] +:_execute-address-uint256-bytes: pass:normal[xref:#TimelockController-_execute-address-uint256-bytes-[`++_execute++`]] +:updateDelay-uint256: pass:normal[xref:#TimelockController-updateDelay-uint256-[`++updateDelay++`]] +:_encodeStateBitmap-enum-TimelockController-OperationState: pass:normal[xref:#TimelockController-_encodeStateBitmap-enum-TimelockController-OperationState-[`++_encodeStateBitmap++`]] +:PROPOSER_ROLE-bytes32: pass:normal[xref:#TimelockController-PROPOSER_ROLE-bytes32[`++PROPOSER_ROLE++`]] +:EXECUTOR_ROLE-bytes32: pass:normal[xref:#TimelockController-EXECUTOR_ROLE-bytes32[`++EXECUTOR_ROLE++`]] +:CANCELLER_ROLE-bytes32: pass:normal[xref:#TimelockController-CANCELLER_ROLE-bytes32[`++CANCELLER_ROLE++`]] + [.contract] [[TimelockController]] -=== `++TimelockController++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/governance/TimelockController.sol[{github-icon},role=heading-link] +=== `++TimelockController++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/governance/TimelockController.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -6542,7 +8506,7 @@ The caller account is not authorized. [[timelock-terminology]] ==== Terminology -* *Operation:* A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution (see xref:access-control.adoc#operation_lifecycle[operation lifecycle]). If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content. +* *Operation:* A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution. If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content. * *Operation status:* ** *Unset:* An operation that is not part of the timelock mechanism. ** *Waiting:* An operation that has been scheduled, before the timer expires. diff --git a/docs/modules/api/pages/interfaces.adoc b/docs/modules/api/pages/interfaces.adoc index 4760ff5bb..187be49da 100644 --- a/docs/modules/api/pages/interfaces.adoc +++ b/docs/modules/api/pages/interfaces.adoc @@ -32,6 +32,10 @@ :IERC5313: pass:normal[xref:interfaces.adoc#IERC5313[`IERC5313`]] :IERC5805: pass:normal[xref:interfaces.adoc#IERC5805[`IERC5805`]] :IERC6372: pass:normal[xref:interfaces.adoc#IERC6372[`IERC6372`]] +:IERC6909: pass:normal[xref:interfaces.adoc#IERC6909[`IERC6909`]] +:IERC6909ContentURI: pass:normal[xref:interfaces.adoc#IERC6909ContentURI[`IERC6909ContentURI`]] +:IERC6909Metadata: pass:normal[xref:interfaces.adoc#IERC6909Metadata[`IERC6909Metadata`]] +:IERC6909TokenSupply: pass:normal[xref:interfaces.adoc#IERC6909TokenSupply[`IERC6909TokenSupply`]] :IERC7674: pass:normal[xref:interfaces.adoc#IERC7674[`IERC7674`]] :xref-IERC20Errors-ERC20InsufficientBalance-address-uint256-uint256-: xref:interfaces.adoc#IERC20Errors-ERC20InsufficientBalance-address-uint256-uint256- :xref-IERC20Errors-ERC20InvalidSender-address-: xref:interfaces.adoc#IERC20Errors-ERC20InvalidSender-address- @@ -135,9 +139,24 @@ :xref-IERC4626-Withdraw-address-address-address-uint256-uint256-: xref:interfaces.adoc#IERC4626-Withdraw-address-address-address-uint256-uint256- :xref-IERC20-Transfer-address-address-uint256-: xref:token/ERC20.adoc#IERC20-Transfer-address-address-uint256- :xref-IERC20-Approval-address-address-uint256-: xref:token/ERC20.adoc#IERC20-Approval-address-address-uint256- -:xref-IERC5313-owner--: xref:interfaces.adoc#IERC5313-owner-- +:xref-IERC721-balanceOf-address-: xref:token/ERC721.adoc#IERC721-balanceOf-address- +:xref-IERC721-ownerOf-uint256-: xref:token/ERC721.adoc#IERC721-ownerOf-uint256- +:xref-IERC721-safeTransferFrom-address-address-uint256-bytes-: xref:token/ERC721.adoc#IERC721-safeTransferFrom-address-address-uint256-bytes- +:xref-IERC721-safeTransferFrom-address-address-uint256-: xref:token/ERC721.adoc#IERC721-safeTransferFrom-address-address-uint256- +:xref-IERC721-transferFrom-address-address-uint256-: xref:token/ERC721.adoc#IERC721-transferFrom-address-address-uint256- +:xref-IERC721-approve-address-uint256-: xref:token/ERC721.adoc#IERC721-approve-address-uint256- +:xref-IERC721-setApprovalForAll-address-bool-: xref:token/ERC721.adoc#IERC721-setApprovalForAll-address-bool- +:xref-IERC721-getApproved-uint256-: xref:token/ERC721.adoc#IERC721-getApproved-uint256- +:xref-IERC721-isApprovedForAll-address-address-: xref:token/ERC721.adoc#IERC721-isApprovedForAll-address-address- +:xref-IERC165-supportsInterface-bytes4-: xref:utils.adoc#IERC165-supportsInterface-bytes4- +:xref-IERC4906-MetadataUpdate-uint256-: xref:interfaces.adoc#IERC4906-MetadataUpdate-uint256- +:xref-IERC4906-BatchMetadataUpdate-uint256-uint256-: xref:interfaces.adoc#IERC4906-BatchMetadataUpdate-uint256-uint256- +:xref-IERC721-Transfer-address-address-uint256-: xref:token/ERC721.adoc#IERC721-Transfer-address-address-uint256- +:xref-IERC721-Approval-address-address-uint256-: xref:token/ERC721.adoc#IERC721-Approval-address-address-uint256- +:xref-IERC721-ApprovalForAll-address-address-bool-: xref:token/ERC721.adoc#IERC721-ApprovalForAll-address-address-bool- :xref-IERC5267-eip712Domain--: xref:interfaces.adoc#IERC5267-eip712Domain-- :xref-IERC5267-EIP712DomainChanged--: xref:interfaces.adoc#IERC5267-EIP712DomainChanged-- +:xref-IERC5313-owner--: xref:interfaces.adoc#IERC5313-owner-- :xref-IVotes-getVotes-address-: xref:governance.adoc#IVotes-getVotes-address- :xref-IVotes-getPastVotes-address-uint256-: xref:governance.adoc#IVotes-getPastVotes-address-uint256- :xref-IVotes-getPastTotalSupply-uint256-: xref:governance.adoc#IVotes-getPastTotalSupply-uint256- @@ -151,6 +170,59 @@ :xref-IVotes-VotesExpiredSignature-uint256-: xref:governance.adoc#IVotes-VotesExpiredSignature-uint256- :xref-IERC6372-clock--: xref:interfaces.adoc#IERC6372-clock-- :xref-IERC6372-CLOCK_MODE--: xref:interfaces.adoc#IERC6372-CLOCK_MODE-- +:xref-IERC6909-balanceOf-address-uint256-: xref:interfaces.adoc#IERC6909-balanceOf-address-uint256- +:xref-IERC6909-allowance-address-address-uint256-: xref:interfaces.adoc#IERC6909-allowance-address-address-uint256- +:xref-IERC6909-isOperator-address-address-: xref:interfaces.adoc#IERC6909-isOperator-address-address- +:xref-IERC6909-approve-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-approve-address-uint256-uint256- +:xref-IERC6909-setOperator-address-bool-: xref:interfaces.adoc#IERC6909-setOperator-address-bool- +:xref-IERC6909-transfer-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-transfer-address-uint256-uint256- +:xref-IERC6909-transferFrom-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-transferFrom-address-address-uint256-uint256- +:xref-IERC165-supportsInterface-bytes4-: xref:utils.adoc#IERC165-supportsInterface-bytes4- +:xref-IERC6909-Approval-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Approval-address-address-uint256-uint256- +:xref-IERC6909-OperatorSet-address-address-bool-: xref:interfaces.adoc#IERC6909-OperatorSet-address-address-bool- +:xref-IERC6909-Transfer-address-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Transfer-address-address-address-uint256-uint256- +:IERC6909: pass:normal[xref:interfaces.adoc#IERC6909[`IERC6909`]] +:xref-IERC6909ContentURI-contractURI--: xref:interfaces.adoc#IERC6909ContentURI-contractURI-- +:xref-IERC6909ContentURI-tokenURI-uint256-: xref:interfaces.adoc#IERC6909ContentURI-tokenURI-uint256- +:xref-IERC6909-balanceOf-address-uint256-: xref:interfaces.adoc#IERC6909-balanceOf-address-uint256- +:xref-IERC6909-allowance-address-address-uint256-: xref:interfaces.adoc#IERC6909-allowance-address-address-uint256- +:xref-IERC6909-isOperator-address-address-: xref:interfaces.adoc#IERC6909-isOperator-address-address- +:xref-IERC6909-approve-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-approve-address-uint256-uint256- +:xref-IERC6909-setOperator-address-bool-: xref:interfaces.adoc#IERC6909-setOperator-address-bool- +:xref-IERC6909-transfer-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-transfer-address-uint256-uint256- +:xref-IERC6909-transferFrom-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-transferFrom-address-address-uint256-uint256- +:xref-IERC165-supportsInterface-bytes4-: xref:utils.adoc#IERC165-supportsInterface-bytes4- +:xref-IERC6909-Approval-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Approval-address-address-uint256-uint256- +:xref-IERC6909-OperatorSet-address-address-bool-: xref:interfaces.adoc#IERC6909-OperatorSet-address-address-bool- +:xref-IERC6909-Transfer-address-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Transfer-address-address-address-uint256-uint256- +:IERC6909: pass:normal[xref:interfaces.adoc#IERC6909[`IERC6909`]] +:xref-IERC6909Metadata-name-uint256-: xref:interfaces.adoc#IERC6909Metadata-name-uint256- +:xref-IERC6909Metadata-symbol-uint256-: xref:interfaces.adoc#IERC6909Metadata-symbol-uint256- +:xref-IERC6909Metadata-decimals-uint256-: xref:interfaces.adoc#IERC6909Metadata-decimals-uint256- +:xref-IERC6909-balanceOf-address-uint256-: xref:interfaces.adoc#IERC6909-balanceOf-address-uint256- +:xref-IERC6909-allowance-address-address-uint256-: xref:interfaces.adoc#IERC6909-allowance-address-address-uint256- +:xref-IERC6909-isOperator-address-address-: xref:interfaces.adoc#IERC6909-isOperator-address-address- +:xref-IERC6909-approve-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-approve-address-uint256-uint256- +:xref-IERC6909-setOperator-address-bool-: xref:interfaces.adoc#IERC6909-setOperator-address-bool- +:xref-IERC6909-transfer-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-transfer-address-uint256-uint256- +:xref-IERC6909-transferFrom-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-transferFrom-address-address-uint256-uint256- +:xref-IERC165-supportsInterface-bytes4-: xref:utils.adoc#IERC165-supportsInterface-bytes4- +:xref-IERC6909-Approval-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Approval-address-address-uint256-uint256- +:xref-IERC6909-OperatorSet-address-address-bool-: xref:interfaces.adoc#IERC6909-OperatorSet-address-address-bool- +:xref-IERC6909-Transfer-address-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Transfer-address-address-address-uint256-uint256- +:IERC6909: pass:normal[xref:interfaces.adoc#IERC6909[`IERC6909`]] +:xref-IERC6909TokenSupply-totalSupply-uint256-: xref:interfaces.adoc#IERC6909TokenSupply-totalSupply-uint256- +:xref-IERC6909-balanceOf-address-uint256-: xref:interfaces.adoc#IERC6909-balanceOf-address-uint256- +:xref-IERC6909-allowance-address-address-uint256-: xref:interfaces.adoc#IERC6909-allowance-address-address-uint256- +:xref-IERC6909-isOperator-address-address-: xref:interfaces.adoc#IERC6909-isOperator-address-address- +:xref-IERC6909-approve-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-approve-address-uint256-uint256- +:xref-IERC6909-setOperator-address-bool-: xref:interfaces.adoc#IERC6909-setOperator-address-bool- +:xref-IERC6909-transfer-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-transfer-address-uint256-uint256- +:xref-IERC6909-transferFrom-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-transferFrom-address-address-uint256-uint256- +:xref-IERC165-supportsInterface-bytes4-: xref:utils.adoc#IERC165-supportsInterface-bytes4- +:xref-IERC6909-Approval-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Approval-address-address-uint256-uint256- +:xref-IERC6909-OperatorSet-address-address-bool-: xref:interfaces.adoc#IERC6909-OperatorSet-address-address-bool- +:xref-IERC6909-Transfer-address-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Transfer-address-address-address-uint256-uint256- :xref-IERC7674-temporaryApprove-address-uint256-: xref:interfaces.adoc#IERC7674-temporaryApprove-address-uint256- :xref-IERC20-totalSupply--: xref:token/ERC20.adoc#IERC20-totalSupply-- :xref-IERC20-balanceOf-address-: xref:token/ERC20.adoc#IERC20-balanceOf-address- @@ -202,6 +274,10 @@ are useful to interact with third party contracts that implement them. - {IERC5313} - {IERC5805} - {IERC6372} +- {IERC6909} +- {IERC6909ContentURI} +- {IERC6909Metadata} +- {IERC6909TokenSupply} - {IERC7674} == Detailed ABI @@ -215,7 +291,7 @@ are useful to interact with third party contracts that implement them. [.contract] [[IERC20Errors]] -=== `++IERC20Errors++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/draft-IERC6093.sol[{github-icon},role=heading-link] +=== `++IERC20Errors++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/draft-IERC6093.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -284,7 +360,7 @@ Indicates a failure with the `spender` to be approved. Used in approvals. [.contract] [[IERC721Errors]] -=== `++IERC721Errors++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/draft-IERC6093.sol[{github-icon},role=heading-link] +=== `++IERC721Errors++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/draft-IERC6093.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -367,7 +443,7 @@ Indicates a failure with the `operator` to be approved. Used in approvals. [.contract] [[IERC1155Errors]] -=== `++IERC1155Errors++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/draft-IERC6093.sol[{github-icon},role=heading-link] +=== `++IERC1155Errors++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/draft-IERC6093.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -435,9 +511,11 @@ Used in batch transfers. :isValidSignature: pass:normal[xref:#IERC1271-isValidSignature-bytes32-bytes-[`++isValidSignature++`]] +:isValidSignature-bytes32-bytes: pass:normal[xref:#IERC1271-isValidSignature-bytes32-bytes-[`++isValidSignature++`]] + [.contract] [[IERC1271]] -=== `++IERC1271++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC1271.sol[{github-icon},role=heading-link] +=== `++IERC1271++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC1271.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -467,9 +545,16 @@ Should return whether the signature provided is valid for the provided data :approveAndCall: pass:normal[xref:#IERC1363-approveAndCall-address-uint256-[`++approveAndCall++`]] :approveAndCall: pass:normal[xref:#IERC1363-approveAndCall-address-uint256-bytes-[`++approveAndCall++`]] +:transferAndCall-address-uint256: pass:normal[xref:#IERC1363-transferAndCall-address-uint256-[`++transferAndCall++`]] +:transferAndCall-address-uint256-bytes: pass:normal[xref:#IERC1363-transferAndCall-address-uint256-bytes-[`++transferAndCall++`]] +:transferFromAndCall-address-address-uint256: pass:normal[xref:#IERC1363-transferFromAndCall-address-address-uint256-[`++transferFromAndCall++`]] +:transferFromAndCall-address-address-uint256-bytes: pass:normal[xref:#IERC1363-transferFromAndCall-address-address-uint256-bytes-[`++transferFromAndCall++`]] +:approveAndCall-address-uint256: pass:normal[xref:#IERC1363-approveAndCall-address-uint256-[`++approveAndCall++`]] +:approveAndCall-address-uint256-bytes: pass:normal[xref:#IERC1363-approveAndCall-address-uint256-bytes-[`++approveAndCall++`]] + [.contract] [[IERC1363]] -=== `++IERC1363++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC1363.sol[{github-icon},role=heading-link] +=== `++IERC1363++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC1363.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -564,9 +649,11 @@ caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender` :onTransferReceived: pass:normal[xref:#IERC1363Receiver-onTransferReceived-address-address-uint256-bytes-[`++onTransferReceived++`]] +:onTransferReceived-address-address-uint256-bytes: pass:normal[xref:#IERC1363Receiver-onTransferReceived-address-address-uint256-bytes-[`++onTransferReceived++`]] + [.contract] [[IERC1363Receiver]] -=== `++IERC1363Receiver++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC1363Receiver.sol[{github-icon},role=heading-link] +=== `++IERC1363Receiver++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC1363Receiver.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -596,9 +683,11 @@ NOTE: To accept the transfer, this must return :onApprovalReceived: pass:normal[xref:#IERC1363Spender-onApprovalReceived-address-uint256-bytes-[`++onApprovalReceived++`]] +:onApprovalReceived-address-uint256-bytes: pass:normal[xref:#IERC1363Spender-onApprovalReceived-address-uint256-bytes-[`++onApprovalReceived++`]] + [.contract] [[IERC1363Spender]] -=== `++IERC1363Spender++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC1363Spender.sol[{github-icon},role=heading-link] +=== `++IERC1363Spender++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC1363Spender.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -628,9 +717,11 @@ NOTE: To accept the approval, this must return :canImplementInterfaceForAddress: pass:normal[xref:#IERC1820Implementer-canImplementInterfaceForAddress-bytes32-address-[`++canImplementInterfaceForAddress++`]] +:canImplementInterfaceForAddress-bytes32-address: pass:normal[xref:#IERC1820Implementer-canImplementInterfaceForAddress-bytes32-address-[`++canImplementInterfaceForAddress++`]] + [.contract] [[IERC1820Implementer]] -=== `++IERC1820Implementer++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC1820Implementer.sol[{github-icon},role=heading-link] +=== `++IERC1820Implementer++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC1820Implementer.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -669,9 +760,18 @@ See {IERC1820Registry-setInterfaceImplementer}. :implementsERC165Interface: pass:normal[xref:#IERC1820Registry-implementsERC165Interface-address-bytes4-[`++implementsERC165Interface++`]] :implementsERC165InterfaceNoCache: pass:normal[xref:#IERC1820Registry-implementsERC165InterfaceNoCache-address-bytes4-[`++implementsERC165InterfaceNoCache++`]] +:setManager-address-address: pass:normal[xref:#IERC1820Registry-setManager-address-address-[`++setManager++`]] +:getManager-address: pass:normal[xref:#IERC1820Registry-getManager-address-[`++getManager++`]] +:setInterfaceImplementer-address-bytes32-address: pass:normal[xref:#IERC1820Registry-setInterfaceImplementer-address-bytes32-address-[`++setInterfaceImplementer++`]] +:getInterfaceImplementer-address-bytes32: pass:normal[xref:#IERC1820Registry-getInterfaceImplementer-address-bytes32-[`++getInterfaceImplementer++`]] +:interfaceHash-string: pass:normal[xref:#IERC1820Registry-interfaceHash-string-[`++interfaceHash++`]] +:updateERC165Cache-address-bytes4: pass:normal[xref:#IERC1820Registry-updateERC165Cache-address-bytes4-[`++updateERC165Cache++`]] +:implementsERC165Interface-address-bytes4: pass:normal[xref:#IERC1820Registry-implementsERC165Interface-address-bytes4-[`++implementsERC165Interface++`]] +:implementsERC165InterfaceNoCache-address-bytes4: pass:normal[xref:#IERC1820Registry-implementsERC165InterfaceNoCache-address-bytes4-[`++implementsERC165InterfaceNoCache++`]] + [.contract] [[IERC1820Registry]] -=== `++IERC1820Registry++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC1820Registry.sol[{github-icon},role=heading-link] +=== `++IERC1820Registry++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC1820Registry.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -802,9 +902,11 @@ https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the ERC]. :proxiableUUID: pass:normal[xref:#IERC1822Proxiable-proxiableUUID--[`++proxiableUUID++`]] +:proxiableUUID-: pass:normal[xref:#IERC1822Proxiable-proxiableUUID--[`++proxiableUUID++`]] + [.contract] [[IERC1822Proxiable]] -=== `++IERC1822Proxiable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/draft-IERC1822.sol[{github-icon},role=heading-link] +=== `++IERC1822Proxiable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/draft-IERC1822.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -834,7 +936,7 @@ function revert if invoked through a proxy. [.contract] [[IERC2612]] -=== `++IERC2612++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC2612.sol[{github-icon},role=heading-link] +=== `++IERC2612++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC2612.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -855,9 +957,11 @@ import "@openzeppelin/contracts/interfaces/IERC2612.sol"; :royaltyInfo: pass:normal[xref:#IERC2981-royaltyInfo-uint256-uint256-[`++royaltyInfo++`]] +:royaltyInfo-uint256-uint256: pass:normal[xref:#IERC2981-royaltyInfo-uint256-uint256-[`++royaltyInfo++`]] + [.contract] [[IERC2981]] -=== `++IERC2981++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC2981.sol[{github-icon},role=heading-link] +=== `++IERC2981++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC2981.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -894,9 +998,13 @@ royalty receiver and 0 tokens to the seller. Contracts dealing with royalty shou :flashFee: pass:normal[xref:#IERC3156FlashLender-flashFee-address-uint256-[`++flashFee++`]] :flashLoan: pass:normal[xref:#IERC3156FlashLender-flashLoan-contract-IERC3156FlashBorrower-address-uint256-bytes-[`++flashLoan++`]] +:maxFlashLoan-address: pass:normal[xref:#IERC3156FlashLender-maxFlashLoan-address-[`++maxFlashLoan++`]] +:flashFee-address-uint256: pass:normal[xref:#IERC3156FlashLender-flashFee-address-uint256-[`++flashFee++`]] +:flashLoan-contract-IERC3156FlashBorrower-address-uint256-bytes: pass:normal[xref:#IERC3156FlashLender-flashLoan-contract-IERC3156FlashBorrower-address-uint256-bytes-[`++flashLoan++`]] + [.contract] [[IERC3156FlashLender]] -=== `++IERC3156FlashLender++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC3156FlashLender.sol[{github-icon},role=heading-link] +=== `++IERC3156FlashLender++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC3156FlashLender.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -935,9 +1043,11 @@ Initiate a flash loan. :onFlashLoan: pass:normal[xref:#IERC3156FlashBorrower-onFlashLoan-address-address-uint256-uint256-bytes-[`++onFlashLoan++`]] +:onFlashLoan-address-address-uint256-uint256-bytes: pass:normal[xref:#IERC3156FlashBorrower-onFlashLoan-address-address-uint256-uint256-bytes-[`++onFlashLoan++`]] + [.contract] [[IERC3156FlashBorrower]] -=== `++IERC3156FlashBorrower++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC3156FlashBorrower.sol[{github-icon},role=heading-link] +=== `++IERC3156FlashBorrower++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC3156FlashBorrower.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -979,9 +1089,26 @@ Receive a flash loan. :previewRedeem: pass:normal[xref:#IERC4626-previewRedeem-uint256-[`++previewRedeem++`]] :redeem: pass:normal[xref:#IERC4626-redeem-uint256-address-address-[`++redeem++`]] +:asset-: pass:normal[xref:#IERC4626-asset--[`++asset++`]] +:totalAssets-: pass:normal[xref:#IERC4626-totalAssets--[`++totalAssets++`]] +:convertToShares-uint256: pass:normal[xref:#IERC4626-convertToShares-uint256-[`++convertToShares++`]] +:convertToAssets-uint256: pass:normal[xref:#IERC4626-convertToAssets-uint256-[`++convertToAssets++`]] +:maxDeposit-address: pass:normal[xref:#IERC4626-maxDeposit-address-[`++maxDeposit++`]] +:previewDeposit-uint256: pass:normal[xref:#IERC4626-previewDeposit-uint256-[`++previewDeposit++`]] +:deposit-uint256-address: pass:normal[xref:#IERC4626-deposit-uint256-address-[`++deposit++`]] +:maxMint-address: pass:normal[xref:#IERC4626-maxMint-address-[`++maxMint++`]] +:previewMint-uint256: pass:normal[xref:#IERC4626-previewMint-uint256-[`++previewMint++`]] +:mint-uint256-address: pass:normal[xref:#IERC4626-mint-uint256-address-[`++mint++`]] +:maxWithdraw-address: pass:normal[xref:#IERC4626-maxWithdraw-address-[`++maxWithdraw++`]] +:previewWithdraw-uint256: pass:normal[xref:#IERC4626-previewWithdraw-uint256-[`++previewWithdraw++`]] +:withdraw-uint256-address-address: pass:normal[xref:#IERC4626-withdraw-uint256-address-address-[`++withdraw++`]] +:maxRedeem-address: pass:normal[xref:#IERC4626-maxRedeem-address-[`++maxRedeem++`]] +:previewRedeem-uint256: pass:normal[xref:#IERC4626-previewRedeem-uint256-[`++previewRedeem++`]] +:redeem-uint256-address-address: pass:normal[xref:#IERC4626-redeem-uint256-address-address-[`++redeem++`]] + [.contract] [[IERC4626]] -=== `++IERC4626++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC4626.sol[{github-icon},role=heading-link] +=== `++IERC4626++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC4626.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1238,7 +1365,7 @@ through a redeem call. [[IERC4626-previewRedeem-uint256-]] ==== `[.contract-item-name]#++previewRedeem++#++(uint256 shares) → uint256 assets++` [.item-kind]#external# -Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, +Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block, given current on-chain conditions. - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call @@ -1275,40 +1402,81 @@ Those methods should be performed separately. [[IERC4626-Withdraw-address-address-address-uint256-uint256-]] ==== `[.contract-item-name]#++Withdraw++#++(address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares)++` [.item-kind]#event# -:owner: pass:normal[xref:#IERC5313-owner--[`++owner++`]] +:MetadataUpdate: pass:normal[xref:#IERC4906-MetadataUpdate-uint256-[`++MetadataUpdate++`]] +:BatchMetadataUpdate: pass:normal[xref:#IERC4906-BatchMetadataUpdate-uint256-uint256-[`++BatchMetadataUpdate++`]] [.contract] -[[IERC5313]] -=== `++IERC5313++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC5313.sol[{github-icon},role=heading-link] +[[IERC4906]] +=== `++IERC4906++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC4906.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity -import "@openzeppelin/contracts/interfaces/IERC5313.sol"; +import "@openzeppelin/contracts/interfaces/IERC4906.sol"; ``` -Interface for the Light Contract Ownership Standard. - -A standardized minimal interface required to identify an account that controls a contract - [.contract-index] .Functions -- -* {xref-IERC5313-owner--}[`++owner()++`] + +[.contract-subindex-inherited] +.IERC721 +* {xref-IERC721-balanceOf-address-}[`++balanceOf(owner)++`] +* {xref-IERC721-ownerOf-uint256-}[`++ownerOf(tokenId)++`] +* {xref-IERC721-safeTransferFrom-address-address-uint256-bytes-}[`++safeTransferFrom(from, to, tokenId, data)++`] +* {xref-IERC721-safeTransferFrom-address-address-uint256-}[`++safeTransferFrom(from, to, tokenId)++`] +* {xref-IERC721-transferFrom-address-address-uint256-}[`++transferFrom(from, to, tokenId)++`] +* {xref-IERC721-approve-address-uint256-}[`++approve(to, tokenId)++`] +* {xref-IERC721-setApprovalForAll-address-bool-}[`++setApprovalForAll(operator, approved)++`] +* {xref-IERC721-getApproved-uint256-}[`++getApproved(tokenId)++`] +* {xref-IERC721-isApprovedForAll-address-address-}[`++isApprovedForAll(owner, operator)++`] + +[.contract-subindex-inherited] +.IERC165 +* {xref-IERC165-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] + +-- + +[.contract-index] +.Events +-- +* {xref-IERC4906-MetadataUpdate-uint256-}[`++MetadataUpdate(_tokenId)++`] +* {xref-IERC4906-BatchMetadataUpdate-uint256-uint256-}[`++BatchMetadataUpdate(_fromTokenId, _toTokenId)++`] + +[.contract-subindex-inherited] +.IERC721 +* {xref-IERC721-Transfer-address-address-uint256-}[`++Transfer(from, to, tokenId)++`] +* {xref-IERC721-Approval-address-address-uint256-}[`++Approval(owner, approved, tokenId)++`] +* {xref-IERC721-ApprovalForAll-address-address-bool-}[`++ApprovalForAll(owner, operator, approved)++`] + +[.contract-subindex-inherited] +.IERC165 -- [.contract-item] -[[IERC5313-owner--]] -==== `[.contract-item-name]#++owner++#++() → address++` [.item-kind]#external# +[[IERC4906-MetadataUpdate-uint256-]] +==== `[.contract-item-name]#++MetadataUpdate++#++(uint256 _tokenId)++` [.item-kind]#event# -Gets the address of the owner. +This event emits when the metadata of a token is changed. +So that the third-party platforms such as NFT market could +timely update the images and related attributes of the NFT. + +[.contract-item] +[[IERC4906-BatchMetadataUpdate-uint256-uint256-]] +==== `[.contract-item-name]#++BatchMetadataUpdate++#++(uint256 _fromTokenId, uint256 _toTokenId)++` [.item-kind]#event# + +This event emits when the metadata of a range of tokens is changed. +So that the third-party platforms such as NFT market could +timely update the images and related attributes of the NFTs. :EIP712DomainChanged: pass:normal[xref:#IERC5267-EIP712DomainChanged--[`++EIP712DomainChanged++`]] :eip712Domain: pass:normal[xref:#IERC5267-eip712Domain--[`++eip712Domain++`]] +:eip712Domain-: pass:normal[xref:#IERC5267-eip712Domain--[`++eip712Domain++`]] + [.contract] [[IERC5267]] -=== `++IERC5267++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC5267.sol[{github-icon},role=heading-link] +=== `++IERC5267++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC5267.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1342,9 +1510,39 @@ signature. MAY be emitted to signal that the domain could have changed. +:owner: pass:normal[xref:#IERC5313-owner--[`++owner++`]] + +:owner-: pass:normal[xref:#IERC5313-owner--[`++owner++`]] + +[.contract] +[[IERC5313]] +=== `++IERC5313++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC5313.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/interfaces/IERC5313.sol"; +``` + +Interface for the Light Contract Ownership Standard. + +A standardized minimal interface required to identify an account that controls a contract + +[.contract-index] +.Functions +-- +* {xref-IERC5313-owner--}[`++owner()++`] + +-- + +[.contract-item] +[[IERC5313-owner--]] +==== `[.contract-item-name]#++owner++#++() → address++` [.item-kind]#external# + +Gets the address of the owner. + [.contract] [[IERC5805]] -=== `++IERC5805++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC5805.sol[{github-icon},role=heading-link] +=== `++IERC5805++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC5805.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1401,9 +1599,12 @@ import "@openzeppelin/contracts/interfaces/IERC5805.sol"; :clock: pass:normal[xref:#IERC6372-clock--[`++clock++`]] :CLOCK_MODE: pass:normal[xref:#IERC6372-CLOCK_MODE--[`++CLOCK_MODE++`]] +:clock-: pass:normal[xref:#IERC6372-clock--[`++clock++`]] +:CLOCK_MODE-: pass:normal[xref:#IERC6372-CLOCK_MODE--[`++CLOCK_MODE++`]] + [.contract] [[IERC6372]] -=== `++IERC6372++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/IERC6372.sol[{github-icon},role=heading-link] +=== `++IERC6372++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/IERC6372.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1430,11 +1631,343 @@ Clock used for flagging checkpoints. Can be overridden to implement timestamp ba Description of the clock +:Approval: pass:normal[xref:#IERC6909-Approval-address-address-uint256-uint256-[`++Approval++`]] +:OperatorSet: pass:normal[xref:#IERC6909-OperatorSet-address-address-bool-[`++OperatorSet++`]] +:Transfer: pass:normal[xref:#IERC6909-Transfer-address-address-address-uint256-uint256-[`++Transfer++`]] +:balanceOf: pass:normal[xref:#IERC6909-balanceOf-address-uint256-[`++balanceOf++`]] +:allowance: pass:normal[xref:#IERC6909-allowance-address-address-uint256-[`++allowance++`]] +:isOperator: pass:normal[xref:#IERC6909-isOperator-address-address-[`++isOperator++`]] +:approve: pass:normal[xref:#IERC6909-approve-address-uint256-uint256-[`++approve++`]] +:setOperator: pass:normal[xref:#IERC6909-setOperator-address-bool-[`++setOperator++`]] +:transfer: pass:normal[xref:#IERC6909-transfer-address-uint256-uint256-[`++transfer++`]] +:transferFrom: pass:normal[xref:#IERC6909-transferFrom-address-address-uint256-uint256-[`++transferFrom++`]] + +:balanceOf-address-uint256: pass:normal[xref:#IERC6909-balanceOf-address-uint256-[`++balanceOf++`]] +:allowance-address-address-uint256: pass:normal[xref:#IERC6909-allowance-address-address-uint256-[`++allowance++`]] +:isOperator-address-address: pass:normal[xref:#IERC6909-isOperator-address-address-[`++isOperator++`]] +:approve-address-uint256-uint256: pass:normal[xref:#IERC6909-approve-address-uint256-uint256-[`++approve++`]] +:setOperator-address-bool: pass:normal[xref:#IERC6909-setOperator-address-bool-[`++setOperator++`]] +:transfer-address-uint256-uint256: pass:normal[xref:#IERC6909-transfer-address-uint256-uint256-[`++transfer++`]] +:transferFrom-address-address-uint256-uint256: pass:normal[xref:#IERC6909-transferFrom-address-address-uint256-uint256-[`++transferFrom++`]] + +[.contract] +[[IERC6909]] +=== `++IERC6909++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/draft-IERC6909.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/interfaces/draft-IERC6909.sol"; +``` + +Required interface of an ERC-6909 compliant contract, as defined in the +https://eips.ethereum.org/EIPS/eip-6909[ERC]. + +[.contract-index] +.Functions +-- +* {xref-IERC6909-balanceOf-address-uint256-}[`++balanceOf(owner, id)++`] +* {xref-IERC6909-allowance-address-address-uint256-}[`++allowance(owner, spender, id)++`] +* {xref-IERC6909-isOperator-address-address-}[`++isOperator(owner, spender)++`] +* {xref-IERC6909-approve-address-uint256-uint256-}[`++approve(spender, id, amount)++`] +* {xref-IERC6909-setOperator-address-bool-}[`++setOperator(spender, approved)++`] +* {xref-IERC6909-transfer-address-uint256-uint256-}[`++transfer(receiver, id, amount)++`] +* {xref-IERC6909-transferFrom-address-address-uint256-uint256-}[`++transferFrom(sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.IERC165 +* {xref-IERC165-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] + +-- + +[.contract-index] +.Events +-- +* {xref-IERC6909-Approval-address-address-uint256-uint256-}[`++Approval(owner, spender, id, amount)++`] +* {xref-IERC6909-OperatorSet-address-address-bool-}[`++OperatorSet(owner, spender, approved)++`] +* {xref-IERC6909-Transfer-address-address-address-uint256-uint256-}[`++Transfer(caller, sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[IERC6909-balanceOf-address-uint256-]] +==== `[.contract-item-name]#++balanceOf++#++(address owner, uint256 id) → uint256++` [.item-kind]#external# + +Returns the amount of tokens of type `id` owned by `owner`. + +[.contract-item] +[[IERC6909-allowance-address-address-uint256-]] +==== `[.contract-item-name]#++allowance++#++(address owner, address spender, uint256 id) → uint256++` [.item-kind]#external# + +Returns the amount of tokens of type `id` that `spender` is allowed to spend on behalf of `owner`. + +NOTE: Does not include operator allowances. + +[.contract-item] +[[IERC6909-isOperator-address-address-]] +==== `[.contract-item-name]#++isOperator++#++(address owner, address spender) → bool++` [.item-kind]#external# + +Returns true if `spender` is set as an operator for `owner`. + +[.contract-item] +[[IERC6909-approve-address-uint256-uint256-]] +==== `[.contract-item-name]#++approve++#++(address spender, uint256 id, uint256 amount) → bool++` [.item-kind]#external# + +Sets an approval to `spender` for `amount` of tokens of type `id` from the caller's tokens. An `amount` of +`type(uint256).max` signifies an unlimited approval. + +Must return true. + +[.contract-item] +[[IERC6909-setOperator-address-bool-]] +==== `[.contract-item-name]#++setOperator++#++(address spender, bool approved) → bool++` [.item-kind]#external# + +Grants or revokes unlimited transfer permission of any token id to `spender` for the caller's tokens. + +Must return true. + +[.contract-item] +[[IERC6909-transfer-address-uint256-uint256-]] +==== `[.contract-item-name]#++transfer++#++(address receiver, uint256 id, uint256 amount) → bool++` [.item-kind]#external# + +Transfers `amount` of token type `id` from the caller's account to `receiver`. + +Must return true. + +[.contract-item] +[[IERC6909-transferFrom-address-address-uint256-uint256-]] +==== `[.contract-item-name]#++transferFrom++#++(address sender, address receiver, uint256 id, uint256 amount) → bool++` [.item-kind]#external# + +Transfers `amount` of token type `id` from `sender` to `receiver`. + +Must return true. + +[.contract-item] +[[IERC6909-Approval-address-address-uint256-uint256-]] +==== `[.contract-item-name]#++Approval++#++(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount)++` [.item-kind]#event# + +Emitted when the allowance of a `spender` for an `owner` is set for a token of type `id`. +The new allowance is `amount`. + +[.contract-item] +[[IERC6909-OperatorSet-address-address-bool-]] +==== `[.contract-item-name]#++OperatorSet++#++(address indexed owner, address indexed spender, bool approved)++` [.item-kind]#event# + +Emitted when `owner` grants or revokes operator status for a `spender`. + +[.contract-item] +[[IERC6909-Transfer-address-address-address-uint256-uint256-]] +==== `[.contract-item-name]#++Transfer++#++(address caller, address indexed sender, address indexed receiver, uint256 indexed id, uint256 amount)++` [.item-kind]#event# + +Emitted when `amount` tokens of type `id` are moved from `sender` to `receiver` initiated by `caller`. + +:contractURI: pass:normal[xref:#IERC6909ContentURI-contractURI--[`++contractURI++`]] +:tokenURI: pass:normal[xref:#IERC6909ContentURI-tokenURI-uint256-[`++tokenURI++`]] + +:contractURI-: pass:normal[xref:#IERC6909ContentURI-contractURI--[`++contractURI++`]] +:tokenURI-uint256: pass:normal[xref:#IERC6909ContentURI-tokenURI-uint256-[`++tokenURI++`]] + +[.contract] +[[IERC6909ContentURI]] +=== `++IERC6909ContentURI++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/draft-IERC6909.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/interfaces/draft-IERC6909.sol"; +``` + +Optional extension of {IERC6909} that adds content URI functions. + +[.contract-index] +.Functions +-- +* {xref-IERC6909ContentURI-contractURI--}[`++contractURI()++`] +* {xref-IERC6909ContentURI-tokenURI-uint256-}[`++tokenURI(id)++`] + +[.contract-subindex-inherited] +.IERC6909 +* {xref-IERC6909-balanceOf-address-uint256-}[`++balanceOf(owner, id)++`] +* {xref-IERC6909-allowance-address-address-uint256-}[`++allowance(owner, spender, id)++`] +* {xref-IERC6909-isOperator-address-address-}[`++isOperator(owner, spender)++`] +* {xref-IERC6909-approve-address-uint256-uint256-}[`++approve(spender, id, amount)++`] +* {xref-IERC6909-setOperator-address-bool-}[`++setOperator(spender, approved)++`] +* {xref-IERC6909-transfer-address-uint256-uint256-}[`++transfer(receiver, id, amount)++`] +* {xref-IERC6909-transferFrom-address-address-uint256-uint256-}[`++transferFrom(sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.IERC165 +* {xref-IERC165-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] + +-- + +[.contract-index] +.Events +-- + +[.contract-subindex-inherited] +.IERC6909 +* {xref-IERC6909-Approval-address-address-uint256-uint256-}[`++Approval(owner, spender, id, amount)++`] +* {xref-IERC6909-OperatorSet-address-address-bool-}[`++OperatorSet(owner, spender, approved)++`] +* {xref-IERC6909-Transfer-address-address-address-uint256-uint256-}[`++Transfer(caller, sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[IERC6909ContentURI-contractURI--]] +==== `[.contract-item-name]#++contractURI++#++() → string++` [.item-kind]#external# + +Returns URI for the contract. + +[.contract-item] +[[IERC6909ContentURI-tokenURI-uint256-]] +==== `[.contract-item-name]#++tokenURI++#++(uint256 id) → string++` [.item-kind]#external# + +Returns the URI for the token of type `id`. + +:name: pass:normal[xref:#IERC6909Metadata-name-uint256-[`++name++`]] +:symbol: pass:normal[xref:#IERC6909Metadata-symbol-uint256-[`++symbol++`]] +:decimals: pass:normal[xref:#IERC6909Metadata-decimals-uint256-[`++decimals++`]] + +:name-uint256: pass:normal[xref:#IERC6909Metadata-name-uint256-[`++name++`]] +:symbol-uint256: pass:normal[xref:#IERC6909Metadata-symbol-uint256-[`++symbol++`]] +:decimals-uint256: pass:normal[xref:#IERC6909Metadata-decimals-uint256-[`++decimals++`]] + +[.contract] +[[IERC6909Metadata]] +=== `++IERC6909Metadata++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/draft-IERC6909.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/interfaces/draft-IERC6909.sol"; +``` + +Optional extension of {IERC6909} that adds metadata functions. + +[.contract-index] +.Functions +-- +* {xref-IERC6909Metadata-name-uint256-}[`++name(id)++`] +* {xref-IERC6909Metadata-symbol-uint256-}[`++symbol(id)++`] +* {xref-IERC6909Metadata-decimals-uint256-}[`++decimals(id)++`] + +[.contract-subindex-inherited] +.IERC6909 +* {xref-IERC6909-balanceOf-address-uint256-}[`++balanceOf(owner, id)++`] +* {xref-IERC6909-allowance-address-address-uint256-}[`++allowance(owner, spender, id)++`] +* {xref-IERC6909-isOperator-address-address-}[`++isOperator(owner, spender)++`] +* {xref-IERC6909-approve-address-uint256-uint256-}[`++approve(spender, id, amount)++`] +* {xref-IERC6909-setOperator-address-bool-}[`++setOperator(spender, approved)++`] +* {xref-IERC6909-transfer-address-uint256-uint256-}[`++transfer(receiver, id, amount)++`] +* {xref-IERC6909-transferFrom-address-address-uint256-uint256-}[`++transferFrom(sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.IERC165 +* {xref-IERC165-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] + +-- + +[.contract-index] +.Events +-- + +[.contract-subindex-inherited] +.IERC6909 +* {xref-IERC6909-Approval-address-address-uint256-uint256-}[`++Approval(owner, spender, id, amount)++`] +* {xref-IERC6909-OperatorSet-address-address-bool-}[`++OperatorSet(owner, spender, approved)++`] +* {xref-IERC6909-Transfer-address-address-address-uint256-uint256-}[`++Transfer(caller, sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[IERC6909Metadata-name-uint256-]] +==== `[.contract-item-name]#++name++#++(uint256 id) → string++` [.item-kind]#external# + +Returns the name of the token of type `id`. + +[.contract-item] +[[IERC6909Metadata-symbol-uint256-]] +==== `[.contract-item-name]#++symbol++#++(uint256 id) → string++` [.item-kind]#external# + +Returns the ticker symbol of the token of type `id`. + +[.contract-item] +[[IERC6909Metadata-decimals-uint256-]] +==== `[.contract-item-name]#++decimals++#++(uint256 id) → uint8++` [.item-kind]#external# + +Returns the number of decimals for the token of type `id`. + +:totalSupply: pass:normal[xref:#IERC6909TokenSupply-totalSupply-uint256-[`++totalSupply++`]] + +:totalSupply-uint256: pass:normal[xref:#IERC6909TokenSupply-totalSupply-uint256-[`++totalSupply++`]] + +[.contract] +[[IERC6909TokenSupply]] +=== `++IERC6909TokenSupply++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/draft-IERC6909.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/interfaces/draft-IERC6909.sol"; +``` + +Optional extension of {IERC6909} that adds a token supply function. + +[.contract-index] +.Functions +-- +* {xref-IERC6909TokenSupply-totalSupply-uint256-}[`++totalSupply(id)++`] + +[.contract-subindex-inherited] +.IERC6909 +* {xref-IERC6909-balanceOf-address-uint256-}[`++balanceOf(owner, id)++`] +* {xref-IERC6909-allowance-address-address-uint256-}[`++allowance(owner, spender, id)++`] +* {xref-IERC6909-isOperator-address-address-}[`++isOperator(owner, spender)++`] +* {xref-IERC6909-approve-address-uint256-uint256-}[`++approve(spender, id, amount)++`] +* {xref-IERC6909-setOperator-address-bool-}[`++setOperator(spender, approved)++`] +* {xref-IERC6909-transfer-address-uint256-uint256-}[`++transfer(receiver, id, amount)++`] +* {xref-IERC6909-transferFrom-address-address-uint256-uint256-}[`++transferFrom(sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.IERC165 +* {xref-IERC165-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] + +-- + +[.contract-index] +.Events +-- + +[.contract-subindex-inherited] +.IERC6909 +* {xref-IERC6909-Approval-address-address-uint256-uint256-}[`++Approval(owner, spender, id, amount)++`] +* {xref-IERC6909-OperatorSet-address-address-bool-}[`++OperatorSet(owner, spender, approved)++`] +* {xref-IERC6909-Transfer-address-address-address-uint256-uint256-}[`++Transfer(caller, sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[IERC6909TokenSupply-totalSupply-uint256-]] +==== `[.contract-item-name]#++totalSupply++#++(uint256 id) → uint256++` [.item-kind]#external# + +Returns the total supply of the token of type `id`. + :temporaryApprove: pass:normal[xref:#IERC7674-temporaryApprove-address-uint256-[`++temporaryApprove++`]] +:temporaryApprove-address-uint256: pass:normal[xref:#IERC7674-temporaryApprove-address-uint256-[`++temporaryApprove++`]] + [.contract] [[IERC7674]] -=== `++IERC7674++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/interfaces/draft-IERC7674.sol[{github-icon},role=heading-link] +=== `++IERC7674++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/interfaces/draft-IERC7674.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity diff --git a/docs/modules/api/pages/metatx.adoc b/docs/modules/api/pages/metatx.adoc index fa8310d65..a2ac30d3f 100644 --- a/docs/modules/api/pages/metatx.adoc +++ b/docs/modules/api/pages/metatx.adoc @@ -15,6 +15,7 @@ :xref-ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData-: xref:metatx.adoc#ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData- :xref-ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData-: xref:metatx.adoc#ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData- :xref-ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool-: xref:metatx.adoc#ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool- +:xref-ERC2771Forwarder-_isTrustedByTarget-address-: xref:metatx.adoc#ERC2771Forwarder-_isTrustedByTarget-address- :xref-Nonces-nonces-address-: xref:utils.adoc#Nonces-nonces-address- :xref-Nonces-_useNonce-address-: xref:utils.adoc#Nonces-_useNonce-address- :xref-Nonces-_useCheckedNonce-address-uint256-: xref:utils.adoc#Nonces-_useCheckedNonce-address-uint256- @@ -33,6 +34,7 @@ :xref-ERC2771Forwarder-_FORWARD_REQUEST_TYPEHASH-bytes32: xref:metatx.adoc#ERC2771Forwarder-_FORWARD_REQUEST_TYPEHASH-bytes32 :EIP712-constructor: pass:normal[xref:utils.adoc#EIP712-constructor-string-string-[`EIP712.constructor`]] :ECDSA-tryRecover: pass:normal[xref:utils.adoc#ECDSA-tryRecover-bytes32-uint8-bytes32-bytes32-[`ECDSA.tryRecover`]] +:ERC2771Context-isTrustedForwarder: pass:normal[xref:metatx.adoc#ERC2771Context-isTrustedForwarder-address-[`ERC2771Context.isTrustedForwarder`]] = Meta Transactions [.readme-notice] @@ -52,9 +54,16 @@ This directory includes contracts for adding meta-transaction capabilities (i.e. :_msgData: pass:normal[xref:#ERC2771Context-_msgData--[`++_msgData++`]] :_contextSuffixLength: pass:normal[xref:#ERC2771Context-_contextSuffixLength--[`++_contextSuffixLength++`]] +:constructor-address: pass:normal[xref:#ERC2771Context-constructor-address-[`++constructor++`]] +:trustedForwarder-: pass:normal[xref:#ERC2771Context-trustedForwarder--[`++trustedForwarder++`]] +:isTrustedForwarder-address: pass:normal[xref:#ERC2771Context-isTrustedForwarder-address-[`++isTrustedForwarder++`]] +:_msgSender-: pass:normal[xref:#ERC2771Context-_msgSender--[`++_msgSender++`]] +:_msgData-: pass:normal[xref:#ERC2771Context-_msgData--[`++_msgData++`]] +:_contextSuffixLength-: pass:normal[xref:#ERC2771Context-_contextSuffixLength--[`++_contextSuffixLength++`]] + [.contract] [[ERC2771Context]] -=== `++ERC2771Context++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/metatx/ERC2771Context.sol[{github-icon},role=heading-link] +=== `++ERC2771Context++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/metatx/ERC2771Context.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -139,10 +148,20 @@ ERC-2771 specifies the context as being a single address (20 bytes). :_validate: pass:normal[xref:#ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData-[`++_validate++`]] :_recoverForwardRequestSigner: pass:normal[xref:#ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData-[`++_recoverForwardRequestSigner++`]] :_execute: pass:normal[xref:#ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool-[`++_execute++`]] +:_isTrustedByTarget: pass:normal[xref:#ERC2771Forwarder-_isTrustedByTarget-address-[`++_isTrustedByTarget++`]] + +:constructor-string: pass:normal[xref:#ERC2771Forwarder-constructor-string-[`++constructor++`]] +:verify-struct-ERC2771Forwarder-ForwardRequestData: pass:normal[xref:#ERC2771Forwarder-verify-struct-ERC2771Forwarder-ForwardRequestData-[`++verify++`]] +:execute-struct-ERC2771Forwarder-ForwardRequestData: pass:normal[xref:#ERC2771Forwarder-execute-struct-ERC2771Forwarder-ForwardRequestData-[`++execute++`]] +:executeBatch-struct-ERC2771Forwarder-ForwardRequestData---address-payable: pass:normal[xref:#ERC2771Forwarder-executeBatch-struct-ERC2771Forwarder-ForwardRequestData---address-payable-[`++executeBatch++`]] +:_validate-struct-ERC2771Forwarder-ForwardRequestData: pass:normal[xref:#ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData-[`++_validate++`]] +:_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData: pass:normal[xref:#ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData-[`++_recoverForwardRequestSigner++`]] +:_execute-struct-ERC2771Forwarder-ForwardRequestData-bool: pass:normal[xref:#ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool-[`++_execute++`]] +:_isTrustedByTarget-address: pass:normal[xref:#ERC2771Forwarder-_isTrustedByTarget-address-[`++_isTrustedByTarget++`]] [.contract] [[ERC2771Forwarder]] -=== `++ERC2771Forwarder++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/metatx/ERC2771Forwarder.sol[{github-icon},role=heading-link] +=== `++ERC2771Forwarder++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/metatx/ERC2771Forwarder.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -196,6 +215,7 @@ used to execute arbitrary code. * {xref-ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData-}[`++_validate(request)++`] * {xref-ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData-}[`++_recoverForwardRequestSigner(request)++`] * {xref-ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool-}[`++_execute(request, requireValidRequest)++`] +* {xref-ERC2771Forwarder-_isTrustedByTarget-address-}[`++_isTrustedByTarget(target)++`] [.contract-subindex-inherited] .Nonces @@ -360,6 +380,18 @@ Emits an {ExecutedForwardRequest} event. IMPORTANT: Using this function doesn't check that all the `msg.value` was sent, potentially leaving value stuck in the contract. +[.contract-item] +[[ERC2771Forwarder-_isTrustedByTarget-address-]] +==== `[.contract-item-name]#++_isTrustedByTarget++#++(address target) → bool++` [.item-kind]#internal# + +Returns whether the target trusts this forwarder. + +This function performs a static call to the target contract calling the +{ERC2771Context-isTrustedForwarder} function. + +NOTE: Consider the execution of this forwarder is permissionless. Without this check, anyone may transfer assets +that are owned by, or are approved to this forwarder. + [.contract-item] [[ERC2771Forwarder-ExecutedForwardRequest-address-uint256-bool-]] ==== `[.contract-item-name]#++ExecutedForwardRequest++#++(address indexed signer, uint256 nonce, bool success)++` [.item-kind]#event# diff --git a/docs/modules/api/pages/proxy.adoc b/docs/modules/api/pages/proxy.adoc index 57cf4bd7a..5413b4916 100644 --- a/docs/modules/api/pages/proxy.adoc +++ b/docs/modules/api/pages/proxy.adoc @@ -124,6 +124,7 @@ :xref-Initializable-_disableInitializers--: xref:proxy.adoc#Initializable-_disableInitializers-- :xref-Initializable-_getInitializedVersion--: xref:proxy.adoc#Initializable-_getInitializedVersion-- :xref-Initializable-_isInitializing--: xref:proxy.adoc#Initializable-_isInitializing-- +:xref-Initializable-_initializableStorageSlot--: xref:proxy.adoc#Initializable-_initializableStorageSlot-- :xref-Initializable-Initialized-uint64-: xref:proxy.adoc#Initializable-Initialized-uint64- :xref-Initializable-InvalidInitialization--: xref:proxy.adoc#Initializable-InvalidInitialization-- :xref-Initializable-NotInitializing--: xref:proxy.adoc#Initializable-NotInitializing-- @@ -198,9 +199,14 @@ The current implementation of this security mechanism uses https://eips.ethereum :_fallback: pass:normal[xref:#Proxy-_fallback--[`++_fallback++`]] :fallback: pass:normal[xref:#Proxy-fallback--[`++fallback++`]] +:_delegate-address: pass:normal[xref:#Proxy-_delegate-address-[`++_delegate++`]] +:_implementation-: pass:normal[xref:#Proxy-_implementation--[`++_implementation++`]] +:_fallback-: pass:normal[xref:#Proxy-_fallback--[`++_fallback++`]] +:fallback-: pass:normal[xref:#Proxy-fallback--[`++fallback++`]] + [.contract] [[Proxy]] -=== `++Proxy++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/Proxy.sol[{github-icon},role=heading-link] +=== `++Proxy++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/Proxy.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -261,9 +267,12 @@ function in the contract matches the call data. :constructor: pass:normal[xref:#ERC1967Proxy-constructor-address-bytes-[`++constructor++`]] :_implementation: pass:normal[xref:#ERC1967Proxy-_implementation--[`++_implementation++`]] +:constructor-address-bytes: pass:normal[xref:#ERC1967Proxy-constructor-address-bytes-[`++constructor++`]] +:_implementation-: pass:normal[xref:#ERC1967Proxy-_implementation--[`++_implementation++`]] + [.contract] [[ERC1967Proxy]] -=== `++ERC1967Proxy++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/ERC1967/ERC1967Proxy.sol[{github-icon},role=heading-link] +=== `++ERC1967Proxy++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/ERC1967/ERC1967Proxy.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -326,9 +335,16 @@ the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. :getBeacon: pass:normal[xref:#ERC1967Utils-getBeacon--[`++getBeacon++`]] :upgradeBeaconToAndCall: pass:normal[xref:#ERC1967Utils-upgradeBeaconToAndCall-address-bytes-[`++upgradeBeaconToAndCall++`]] +:getImplementation-: pass:normal[xref:#ERC1967Utils-getImplementation--[`++getImplementation++`]] +:upgradeToAndCall-address-bytes: pass:normal[xref:#ERC1967Utils-upgradeToAndCall-address-bytes-[`++upgradeToAndCall++`]] +:getAdmin-: pass:normal[xref:#ERC1967Utils-getAdmin--[`++getAdmin++`]] +:changeAdmin-address: pass:normal[xref:#ERC1967Utils-changeAdmin-address-[`++changeAdmin++`]] +:getBeacon-: pass:normal[xref:#ERC1967Utils-getBeacon--[`++getBeacon++`]] +:upgradeBeaconToAndCall-address-bytes: pass:normal[xref:#ERC1967Utils-upgradeBeaconToAndCall-address-bytes-[`++upgradeBeaconToAndCall++`]] + [.contract] [[ERC1967Utils]] -=== `++ERC1967Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/ERC1967/ERC1967Utils.sol[{github-icon},role=heading-link] +=== `++ERC1967Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/ERC1967/ERC1967Utils.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -475,9 +491,13 @@ This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. :_proxyAdmin: pass:normal[xref:#TransparentUpgradeableProxy-_proxyAdmin--[`++_proxyAdmin++`]] :_fallback: pass:normal[xref:#TransparentUpgradeableProxy-_fallback--[`++_fallback++`]] +:constructor-address-address-bytes: pass:normal[xref:#TransparentUpgradeableProxy-constructor-address-address-bytes-[`++constructor++`]] +:_proxyAdmin-: pass:normal[xref:#TransparentUpgradeableProxy-_proxyAdmin--[`++_proxyAdmin++`]] +:_fallback-: pass:normal[xref:#TransparentUpgradeableProxy-_fallback--[`++_fallback++`]] + [.contract] [[TransparentUpgradeableProxy]] -=== `++TransparentUpgradeableProxy++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/transparent/TransparentUpgradeableProxy.sol[{github-icon},role=heading-link] +=== `++TransparentUpgradeableProxy++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/transparent/TransparentUpgradeableProxy.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -584,9 +604,13 @@ The proxy caller is the current admin, and can't fallback to the proxy target. :constructor: pass:normal[xref:#ProxyAdmin-constructor-address-[`++constructor++`]] :upgradeAndCall: pass:normal[xref:#ProxyAdmin-upgradeAndCall-contract-ITransparentUpgradeableProxy-address-bytes-[`++upgradeAndCall++`]] +:constructor-address: pass:normal[xref:#ProxyAdmin-constructor-address-[`++constructor++`]] +:upgradeAndCall-contract-ITransparentUpgradeableProxy-address-bytes: pass:normal[xref:#ProxyAdmin-upgradeAndCall-contract-ITransparentUpgradeableProxy-address-bytes-[`++upgradeAndCall++`]] +:UPGRADE_INTERFACE_VERSION-string: pass:normal[xref:#ProxyAdmin-UPGRADE_INTERFACE_VERSION-string[`++UPGRADE_INTERFACE_VERSION++`]] + [.contract] [[ProxyAdmin]] -=== `++ProxyAdmin++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/transparent/ProxyAdmin.sol[{github-icon},role=heading-link] +=== `++ProxyAdmin++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/transparent/ProxyAdmin.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -669,9 +693,13 @@ during an upgrade. :_implementation: pass:normal[xref:#BeaconProxy-_implementation--[`++_implementation++`]] :_getBeacon: pass:normal[xref:#BeaconProxy-_getBeacon--[`++_getBeacon++`]] +:constructor-address-bytes: pass:normal[xref:#BeaconProxy-constructor-address-bytes-[`++constructor++`]] +:_implementation-: pass:normal[xref:#BeaconProxy-_implementation--[`++_implementation++`]] +:_getBeacon-: pass:normal[xref:#BeaconProxy-_getBeacon--[`++_getBeacon++`]] + [.contract] [[BeaconProxy]] -=== `++BeaconProxy++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/beacon/BeaconProxy.sol[{github-icon},role=heading-link] +=== `++BeaconProxy++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/beacon/BeaconProxy.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -734,9 +762,11 @@ Returns the beacon. :implementation: pass:normal[xref:#IBeacon-implementation--[`++implementation++`]] +:implementation-: pass:normal[xref:#IBeacon-implementation--[`++implementation++`]] + [.contract] [[IBeacon]] -=== `++IBeacon++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/beacon/IBeacon.sol[{github-icon},role=heading-link] +=== `++IBeacon++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/beacon/IBeacon.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -766,9 +796,13 @@ Must return an address that can be used as a delegate call target. :implementation: pass:normal[xref:#UpgradeableBeacon-implementation--[`++implementation++`]] :upgradeTo: pass:normal[xref:#UpgradeableBeacon-upgradeTo-address-[`++upgradeTo++`]] +:constructor-address-address: pass:normal[xref:#UpgradeableBeacon-constructor-address-address-[`++constructor++`]] +:implementation-: pass:normal[xref:#UpgradeableBeacon-implementation--[`++implementation++`]] +:upgradeTo-address: pass:normal[xref:#UpgradeableBeacon-upgradeTo-address-[`++upgradeTo++`]] + [.contract] [[UpgradeableBeacon]] -=== `++UpgradeableBeacon++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/beacon/UpgradeableBeacon.sol[{github-icon},role=heading-link] +=== `++UpgradeableBeacon++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/beacon/UpgradeableBeacon.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -883,9 +917,23 @@ The `implementation` of the beacon is invalid. :predictDeterministicAddressWithImmutableArgs: pass:normal[xref:#Clones-predictDeterministicAddressWithImmutableArgs-address-bytes-bytes32-[`++predictDeterministicAddressWithImmutableArgs++`]] :fetchCloneArgs: pass:normal[xref:#Clones-fetchCloneArgs-address-[`++fetchCloneArgs++`]] +:clone-address: pass:normal[xref:#Clones-clone-address-[`++clone++`]] +:clone-address-uint256: pass:normal[xref:#Clones-clone-address-uint256-[`++clone++`]] +:cloneDeterministic-address-bytes32: pass:normal[xref:#Clones-cloneDeterministic-address-bytes32-[`++cloneDeterministic++`]] +:cloneDeterministic-address-bytes32-uint256: pass:normal[xref:#Clones-cloneDeterministic-address-bytes32-uint256-[`++cloneDeterministic++`]] +:predictDeterministicAddress-address-bytes32-address: pass:normal[xref:#Clones-predictDeterministicAddress-address-bytes32-address-[`++predictDeterministicAddress++`]] +:predictDeterministicAddress-address-bytes32: pass:normal[xref:#Clones-predictDeterministicAddress-address-bytes32-[`++predictDeterministicAddress++`]] +:cloneWithImmutableArgs-address-bytes: pass:normal[xref:#Clones-cloneWithImmutableArgs-address-bytes-[`++cloneWithImmutableArgs++`]] +:cloneWithImmutableArgs-address-bytes-uint256: pass:normal[xref:#Clones-cloneWithImmutableArgs-address-bytes-uint256-[`++cloneWithImmutableArgs++`]] +:cloneDeterministicWithImmutableArgs-address-bytes-bytes32: pass:normal[xref:#Clones-cloneDeterministicWithImmutableArgs-address-bytes-bytes32-[`++cloneDeterministicWithImmutableArgs++`]] +:cloneDeterministicWithImmutableArgs-address-bytes-bytes32-uint256: pass:normal[xref:#Clones-cloneDeterministicWithImmutableArgs-address-bytes-bytes32-uint256-[`++cloneDeterministicWithImmutableArgs++`]] +:predictDeterministicAddressWithImmutableArgs-address-bytes-bytes32-address: pass:normal[xref:#Clones-predictDeterministicAddressWithImmutableArgs-address-bytes-bytes32-address-[`++predictDeterministicAddressWithImmutableArgs++`]] +:predictDeterministicAddressWithImmutableArgs-address-bytes-bytes32: pass:normal[xref:#Clones-predictDeterministicAddressWithImmutableArgs-address-bytes-bytes32-[`++predictDeterministicAddressWithImmutableArgs++`]] +:fetchCloneArgs-address: pass:normal[xref:#Clones-fetchCloneArgs-address-[`++fetchCloneArgs++`]] + [.contract] [[Clones]] -=== `++Clones++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/Clones.sol[{github-icon},role=heading-link] +=== `++Clones++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/Clones.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -932,7 +980,7 @@ deterministic method. [[Clones-clone-address-]] ==== `[.contract-item-name]#++clone++#++(address implementation) → address instance++` [.item-kind]#internal# -Deploys and returns the address of a clone that mimics the behaviour of `implementation`. +Deploys and returns the address of a clone that mimics the behavior of `implementation`. This function uses the create opcode, which should never revert. @@ -950,7 +998,7 @@ to always have enough balance for new deployments. Consider exposing this functi [[Clones-cloneDeterministic-address-bytes32-]] ==== `[.contract-item-name]#++cloneDeterministic++#++(address implementation, bytes32 salt) → address instance++` [.item-kind]#internal# -Deploys and returns the address of a clone that mimics the behaviour of `implementation`. +Deploys and returns the address of a clone that mimics the behavior of `implementation`. This function uses the create2 opcode and a `salt` to deterministically deploy the clone. Using the same `implementation` and `salt` multiple times will revert, since @@ -1002,7 +1050,7 @@ to always have enough balance for new deployments. Consider exposing this functi [[Clones-cloneDeterministicWithImmutableArgs-address-bytes-bytes32-]] ==== `[.contract-item-name]#++cloneDeterministicWithImmutableArgs++#++(address implementation, bytes args, bytes32 salt) → address instance++` [.item-kind]#internal# -Deploys and returns the address of a clone that mimics the behaviour of `implementation` with custom +Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom immutable arguments. These are provided through `args` and cannot be changed after deployment. To access the arguments within the implementation, use {fetchCloneArgs}. @@ -1063,10 +1111,17 @@ Get the immutable args attached to a clone. :_disableInitializers: pass:normal[xref:#Initializable-_disableInitializers--[`++_disableInitializers++`]] :_getInitializedVersion: pass:normal[xref:#Initializable-_getInitializedVersion--[`++_getInitializedVersion++`]] :_isInitializing: pass:normal[xref:#Initializable-_isInitializing--[`++_isInitializing++`]] +:_initializableStorageSlot: pass:normal[xref:#Initializable-_initializableStorageSlot--[`++_initializableStorageSlot++`]] + +:_checkInitializing-: pass:normal[xref:#Initializable-_checkInitializing--[`++_checkInitializing++`]] +:_disableInitializers-: pass:normal[xref:#Initializable-_disableInitializers--[`++_disableInitializers++`]] +:_getInitializedVersion-: pass:normal[xref:#Initializable-_getInitializedVersion--[`++_getInitializedVersion++`]] +:_isInitializing-: pass:normal[xref:#Initializable-_isInitializing--[`++_isInitializing++`]] +:_initializableStorageSlot-: pass:normal[xref:#Initializable-_initializableStorageSlot--[`++_initializableStorageSlot++`]] [.contract] [[Initializable]] -=== `++Initializable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/utils/Initializable.sol[{github-icon},role=heading-link] +=== `++Initializable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/utils/Initializable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1137,6 +1192,7 @@ constructor() { * {xref-Initializable-_disableInitializers--}[`++_disableInitializers()++`] * {xref-Initializable-_getInitializedVersion--}[`++_getInitializedVersion()++`] * {xref-Initializable-_isInitializing--}[`++_isInitializing()++`] +* {xref-Initializable-_initializableStorageSlot--}[`++_initializableStorageSlot()++`] -- @@ -1225,6 +1281,14 @@ Returns the highest version that has been initialized. See {reinitializer}. Returns `true` if the contract is currently initializing. See {onlyInitializing}. +[.contract-item] +[[Initializable-_initializableStorageSlot--]] +==== `[.contract-item-name]#++_initializableStorageSlot++#++() → bytes32++` [.item-kind]#internal# + +Pointer to storage slot. Allows integrators to override it with a custom storage location. + +NOTE: Consider following the ERC-7201 formula to derive storage locations. + [.contract-item] [[Initializable-Initialized-uint64-]] ==== `[.contract-item-name]#++Initialized++#++(uint64 version)++` [.item-kind]#event# @@ -1254,9 +1318,16 @@ The contract is not initializing. :_checkNotDelegated: pass:normal[xref:#UUPSUpgradeable-_checkNotDelegated--[`++_checkNotDelegated++`]] :_authorizeUpgrade: pass:normal[xref:#UUPSUpgradeable-_authorizeUpgrade-address-[`++_authorizeUpgrade++`]] +:proxiableUUID-: pass:normal[xref:#UUPSUpgradeable-proxiableUUID--[`++proxiableUUID++`]] +:upgradeToAndCall-address-bytes: pass:normal[xref:#UUPSUpgradeable-upgradeToAndCall-address-bytes-[`++upgradeToAndCall++`]] +:_checkProxy-: pass:normal[xref:#UUPSUpgradeable-_checkProxy--[`++_checkProxy++`]] +:_checkNotDelegated-: pass:normal[xref:#UUPSUpgradeable-_checkNotDelegated--[`++_checkNotDelegated++`]] +:_authorizeUpgrade-address: pass:normal[xref:#UUPSUpgradeable-_authorizeUpgrade-address-[`++_authorizeUpgrade++`]] +:UPGRADE_INTERFACE_VERSION-string: pass:normal[xref:#UUPSUpgradeable-UPGRADE_INTERFACE_VERSION-string[`++UPGRADE_INTERFACE_VERSION++`]] + [.contract] [[UUPSUpgradeable]] -=== `++UUPSUpgradeable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/proxy/utils/UUPSUpgradeable.sol[{github-icon},role=heading-link] +=== `++UUPSUpgradeable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/proxy/utils/UUPSUpgradeable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1350,7 +1421,6 @@ Emits an {Upgraded} event. Reverts if the execution is not performed via delegatecall or the execution context is not of a proxy with an ERC-1967 compliant implementation pointing to self. -See {_onlyProxy}. [.contract-item] [[UUPSUpgradeable-_checkNotDelegated--]] diff --git a/docs/modules/api/pages/token/ERC1155.adoc b/docs/modules/api/pages/token/ERC1155.adoc index 8840497d0..f58b031c5 100644 --- a/docs/modules/api/pages/token/ERC1155.adoc +++ b/docs/modules/api/pages/token/ERC1155.adoc @@ -19,6 +19,8 @@ :xref-IERC1155-ApprovalForAll-address-address-bool-: xref:token/ERC1155.adoc#IERC1155-ApprovalForAll-address-address-bool- :xref-IERC1155-URI-string-uint256-: xref:token/ERC1155.adoc#IERC1155-URI-string-uint256- :IERC1155Receiver-onERC1155Received: pass:normal[xref:token/ERC1155.adoc#IERC1155Receiver-onERC1155Received-address-address-uint256-uint256-bytes-[`IERC1155Receiver.onERC1155Received`]] +:IERC1155Receiver-onERC1155Received: pass:normal[xref:token/ERC1155.adoc#IERC1155Receiver-onERC1155Received-address-address-uint256-uint256-bytes-[`IERC1155Receiver.onERC1155Received`]] +:IERC1155Receiver-onERC1155BatchReceived: pass:normal[xref:token/ERC1155.adoc#IERC1155Receiver-onERC1155BatchReceived-address-address-uint256---uint256---bytes-[`IERC1155Receiver.onERC1155BatchReceived`]] :IERC1155Receiver-onERC1155BatchReceived: pass:normal[xref:token/ERC1155.adoc#IERC1155Receiver-onERC1155BatchReceived-address-address-uint256---uint256---bytes-[`IERC1155Receiver.onERC1155BatchReceived`]] :IERC1155MetadataURI-uri: pass:normal[xref:token/ERC1155.adoc#IERC1155MetadataURI-uri-uint256-[`IERC1155MetadataURI.uri`]] :xref-IERC1155MetadataURI-uri-uint256-: xref:token/ERC1155.adoc#IERC1155MetadataURI-uri-uint256- @@ -231,6 +233,8 @@ :xref-ERC1155Utils-checkOnERC1155BatchReceived-address-address-address-uint256---uint256---bytes-: xref:token/ERC1155.adoc#ERC1155Utils-checkOnERC1155BatchReceived-address-address-address-uint256---uint256---bytes- :IERC1155Receiver-onERC1155Received: pass:normal[xref:token/ERC1155.adoc#IERC1155Receiver-onERC1155Received-address-address-uint256-uint256-bytes-[`IERC1155Receiver.onERC1155Received`]] :IERC1155Receiver-onERC1155Received: pass:normal[xref:token/ERC1155.adoc#IERC1155Receiver-onERC1155Received-address-address-uint256-uint256-bytes-[`IERC1155Receiver.onERC1155Received`]] +:IERC1155Receiver-onERC1155BatchReceived: pass:normal[xref:token/ERC1155.adoc#IERC1155Receiver-onERC1155BatchReceived-address-address-uint256---uint256---bytes-[`IERC1155Receiver.onERC1155BatchReceived`]] +:IERC1155Receiver-onERC1155Received: pass:normal[xref:token/ERC1155.adoc#IERC1155Receiver-onERC1155Received-address-address-uint256-uint256-bytes-[`IERC1155Receiver.onERC1155Received`]] = ERC-1155 [.readme-notice] @@ -262,9 +266,16 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel :safeTransferFrom: pass:normal[xref:#IERC1155-safeTransferFrom-address-address-uint256-uint256-bytes-[`++safeTransferFrom++`]] :safeBatchTransferFrom: pass:normal[xref:#IERC1155-safeBatchTransferFrom-address-address-uint256---uint256---bytes-[`++safeBatchTransferFrom++`]] +:balanceOf-address-uint256: pass:normal[xref:#IERC1155-balanceOf-address-uint256-[`++balanceOf++`]] +:balanceOfBatch-address---uint256--: pass:normal[xref:#IERC1155-balanceOfBatch-address---uint256---[`++balanceOfBatch++`]] +:setApprovalForAll-address-bool: pass:normal[xref:#IERC1155-setApprovalForAll-address-bool-[`++setApprovalForAll++`]] +:isApprovedForAll-address-address: pass:normal[xref:#IERC1155-isApprovedForAll-address-address-[`++isApprovedForAll++`]] +:safeTransferFrom-address-address-uint256-uint256-bytes: pass:normal[xref:#IERC1155-safeTransferFrom-address-address-uint256-uint256-bytes-[`++safeTransferFrom++`]] +:safeBatchTransferFrom-address-address-uint256---uint256---bytes: pass:normal[xref:#IERC1155-safeBatchTransferFrom-address-address-uint256---uint256---bytes-[`++safeBatchTransferFrom++`]] + [.contract] [[IERC1155]] -=== `++IERC1155++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC1155/IERC1155.sol[{github-icon},role=heading-link] +=== `++IERC1155++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC1155/IERC1155.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -346,7 +357,7 @@ See {setApprovalForAll}. Transfers a `value` amount of tokens of type `id` from `from` to `to`. WARNING: This function can potentially allow a reentrancy attack when transferring tokens -to an untrusted contract, when invoking {onERC1155Received} on the receiver. +to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver. Ensure to follow the checks-effects-interactions pattern and consider employing reentrancy guards when interacting with untrusted contracts. @@ -367,7 +378,7 @@ acceptance magic value. xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. WARNING: This function can potentially allow a reentrancy attack when transferring tokens -to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver. +to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver. Ensure to follow the checks-effects-interactions pattern and consider employing reentrancy guards when interacting with untrusted contracts. @@ -411,9 +422,11 @@ returned by {IERC1155MetadataURI-uri}. :uri: pass:normal[xref:#IERC1155MetadataURI-uri-uint256-[`++uri++`]] +:uri-uint256: pass:normal[xref:#IERC1155MetadataURI-uri-uint256-[`++uri++`]] + [.contract] [[IERC1155MetadataURI]] -=== `++IERC1155MetadataURI++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol[{github-icon},role=heading-link] +=== `++IERC1155MetadataURI++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -488,9 +501,29 @@ clients with the actual token type ID. :_burnBatch: pass:normal[xref:#ERC1155-_burnBatch-address-uint256---uint256---[`++_burnBatch++`]] :_setApprovalForAll: pass:normal[xref:#ERC1155-_setApprovalForAll-address-address-bool-[`++_setApprovalForAll++`]] +:constructor-string: pass:normal[xref:#ERC1155-constructor-string-[`++constructor++`]] +:supportsInterface-bytes4: pass:normal[xref:#ERC1155-supportsInterface-bytes4-[`++supportsInterface++`]] +:uri-uint256: pass:normal[xref:#ERC1155-uri-uint256-[`++uri++`]] +:balanceOf-address-uint256: pass:normal[xref:#ERC1155-balanceOf-address-uint256-[`++balanceOf++`]] +:balanceOfBatch-address---uint256--: pass:normal[xref:#ERC1155-balanceOfBatch-address---uint256---[`++balanceOfBatch++`]] +:setApprovalForAll-address-bool: pass:normal[xref:#ERC1155-setApprovalForAll-address-bool-[`++setApprovalForAll++`]] +:isApprovedForAll-address-address: pass:normal[xref:#ERC1155-isApprovedForAll-address-address-[`++isApprovedForAll++`]] +:safeTransferFrom-address-address-uint256-uint256-bytes: pass:normal[xref:#ERC1155-safeTransferFrom-address-address-uint256-uint256-bytes-[`++safeTransferFrom++`]] +:safeBatchTransferFrom-address-address-uint256---uint256---bytes: pass:normal[xref:#ERC1155-safeBatchTransferFrom-address-address-uint256---uint256---bytes-[`++safeBatchTransferFrom++`]] +:_update-address-address-uint256---uint256--: pass:normal[xref:#ERC1155-_update-address-address-uint256---uint256---[`++_update++`]] +:_updateWithAcceptanceCheck-address-address-uint256---uint256---bytes: pass:normal[xref:#ERC1155-_updateWithAcceptanceCheck-address-address-uint256---uint256---bytes-[`++_updateWithAcceptanceCheck++`]] +:_safeTransferFrom-address-address-uint256-uint256-bytes: pass:normal[xref:#ERC1155-_safeTransferFrom-address-address-uint256-uint256-bytes-[`++_safeTransferFrom++`]] +:_safeBatchTransferFrom-address-address-uint256---uint256---bytes: pass:normal[xref:#ERC1155-_safeBatchTransferFrom-address-address-uint256---uint256---bytes-[`++_safeBatchTransferFrom++`]] +:_setURI-string: pass:normal[xref:#ERC1155-_setURI-string-[`++_setURI++`]] +:_mint-address-uint256-uint256-bytes: pass:normal[xref:#ERC1155-_mint-address-uint256-uint256-bytes-[`++_mint++`]] +:_mintBatch-address-uint256---uint256---bytes: pass:normal[xref:#ERC1155-_mintBatch-address-uint256---uint256---bytes-[`++_mintBatch++`]] +:_burn-address-uint256-uint256: pass:normal[xref:#ERC1155-_burn-address-uint256-uint256-[`++_burn++`]] +:_burnBatch-address-uint256---uint256--: pass:normal[xref:#ERC1155-_burnBatch-address-uint256---uint256---[`++_burnBatch++`]] +:_setApprovalForAll-address-address-bool: pass:normal[xref:#ERC1155-_setApprovalForAll-address-address-bool-[`++_setApprovalForAll++`]] + [.contract] [[ERC1155]] -=== `++ERC1155++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC1155/ERC1155.sol[{github-icon},role=heading-link] +=== `++ERC1155++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC1155/ERC1155.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -810,9 +843,12 @@ Requirements: :onERC1155Received: pass:normal[xref:#IERC1155Receiver-onERC1155Received-address-address-uint256-uint256-bytes-[`++onERC1155Received++`]] :onERC1155BatchReceived: pass:normal[xref:#IERC1155Receiver-onERC1155BatchReceived-address-address-uint256---uint256---bytes-[`++onERC1155BatchReceived++`]] +:onERC1155Received-address-address-uint256-uint256-bytes: pass:normal[xref:#IERC1155Receiver-onERC1155Received-address-address-uint256-uint256-bytes-[`++onERC1155Received++`]] +:onERC1155BatchReceived-address-address-uint256---uint256---bytes: pass:normal[xref:#IERC1155Receiver-onERC1155BatchReceived-address-address-uint256---uint256---bytes-[`++onERC1155BatchReceived++`]] + [.contract] [[IERC1155Receiver]] -=== `++IERC1155Receiver++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC1155/IERC1155Receiver.sol[{github-icon},role=heading-link] +=== `++IERC1155Receiver++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC1155/IERC1155Receiver.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -861,9 +897,11 @@ NOTE: To accept the transfer(s), this must return :_update: pass:normal[xref:#ERC1155Pausable-_update-address-address-uint256---uint256---[`++_update++`]] +:_update-address-address-uint256---uint256--: pass:normal[xref:#ERC1155Pausable-_update-address-address-uint256---uint256---[`++_update++`]] + [.contract] [[ERC1155Pausable]] -=== `++ERC1155Pausable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC1155/extensions/ERC1155Pausable.sol[{github-icon},role=heading-link] +=== `++ERC1155Pausable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC1155/extensions/ERC1155Pausable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1014,9 +1052,12 @@ Requirements: :burn: pass:normal[xref:#ERC1155Burnable-burn-address-uint256-uint256-[`++burn++`]] :burnBatch: pass:normal[xref:#ERC1155Burnable-burnBatch-address-uint256---uint256---[`++burnBatch++`]] +:burn-address-uint256-uint256: pass:normal[xref:#ERC1155Burnable-burn-address-uint256-uint256-[`++burn++`]] +:burnBatch-address-uint256---uint256--: pass:normal[xref:#ERC1155Burnable-burnBatch-address-uint256---uint256---[`++burnBatch++`]] + [.contract] [[ERC1155Burnable]] -=== `++ERC1155Burnable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC1155/extensions/ERC1155Burnable.sol[{github-icon},role=heading-link] +=== `++ERC1155Burnable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC1155/extensions/ERC1155Burnable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1142,9 +1183,14 @@ own tokens and those that they have been approved to use. :exists: pass:normal[xref:#ERC1155Supply-exists-uint256-[`++exists++`]] :_update: pass:normal[xref:#ERC1155Supply-_update-address-address-uint256---uint256---[`++_update++`]] +:totalSupply-uint256: pass:normal[xref:#ERC1155Supply-totalSupply-uint256-[`++totalSupply++`]] +:totalSupply-: pass:normal[xref:#ERC1155Supply-totalSupply--[`++totalSupply++`]] +:exists-uint256: pass:normal[xref:#ERC1155Supply-exists-uint256-[`++exists++`]] +:_update-address-address-uint256---uint256--: pass:normal[xref:#ERC1155Supply-_update-address-address-uint256---uint256---[`++_update++`]] + [.contract] [[ERC1155Supply]] -=== `++ERC1155Supply++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC1155/extensions/ERC1155Supply.sol[{github-icon},role=heading-link] +=== `++ERC1155Supply++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC1155/extensions/ERC1155Supply.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1295,9 +1341,13 @@ See {ERC1155-_update}. :_setURI: pass:normal[xref:#ERC1155URIStorage-_setURI-uint256-string-[`++_setURI++`]] :_setBaseURI: pass:normal[xref:#ERC1155URIStorage-_setBaseURI-string-[`++_setBaseURI++`]] +:uri-uint256: pass:normal[xref:#ERC1155URIStorage-uri-uint256-[`++uri++`]] +:_setURI-uint256-string: pass:normal[xref:#ERC1155URIStorage-_setURI-uint256-string-[`++_setURI++`]] +:_setBaseURI-string: pass:normal[xref:#ERC1155URIStorage-_setBaseURI-string-[`++_setBaseURI++`]] + [.contract] [[ERC1155URIStorage]] -=== `++ERC1155URIStorage++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC1155/extensions/ERC1155URIStorage.sol[{github-icon},role=heading-link] +=== `++ERC1155URIStorage++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC1155/extensions/ERC1155URIStorage.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1449,9 +1499,13 @@ Sets `baseURI` as the `_baseURI` for all tokens :onERC1155Received: pass:normal[xref:#ERC1155Holder-onERC1155Received-address-address-uint256-uint256-bytes-[`++onERC1155Received++`]] :onERC1155BatchReceived: pass:normal[xref:#ERC1155Holder-onERC1155BatchReceived-address-address-uint256---uint256---bytes-[`++onERC1155BatchReceived++`]] +:supportsInterface-bytes4: pass:normal[xref:#ERC1155Holder-supportsInterface-bytes4-[`++supportsInterface++`]] +:onERC1155Received-address-address-uint256-uint256-bytes: pass:normal[xref:#ERC1155Holder-onERC1155Received-address-address-uint256-uint256-bytes-[`++onERC1155Received++`]] +:onERC1155BatchReceived-address-address-uint256---uint256---bytes: pass:normal[xref:#ERC1155Holder-onERC1155BatchReceived-address-address-uint256---uint256---bytes-[`++onERC1155BatchReceived++`]] + [.contract] [[ERC1155Holder]] -=== `++ERC1155Holder++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC1155/utils/ERC1155Holder.sol[{github-icon},role=heading-link] +=== `++ERC1155Holder++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC1155/utils/ERC1155Holder.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1498,9 +1552,12 @@ See {IERC165-supportsInterface}. :checkOnERC1155Received: pass:normal[xref:#ERC1155Utils-checkOnERC1155Received-address-address-address-uint256-uint256-bytes-[`++checkOnERC1155Received++`]] :checkOnERC1155BatchReceived: pass:normal[xref:#ERC1155Utils-checkOnERC1155BatchReceived-address-address-address-uint256---uint256---bytes-[`++checkOnERC1155BatchReceived++`]] +:checkOnERC1155Received-address-address-address-uint256-uint256-bytes: pass:normal[xref:#ERC1155Utils-checkOnERC1155Received-address-address-address-uint256-uint256-bytes-[`++checkOnERC1155Received++`]] +:checkOnERC1155BatchReceived-address-address-address-uint256---uint256---bytes: pass:normal[xref:#ERC1155Utils-checkOnERC1155BatchReceived-address-address-address-uint256---uint256---bytes-[`++checkOnERC1155BatchReceived++`]] + [.contract] [[ERC1155Utils]] -=== `++ERC1155Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC1155/utils/ERC1155Utils.sol[{github-icon},role=heading-link] +=== `++ERC1155Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC1155/utils/ERC1155Utils.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1525,7 +1582,7 @@ _Available since v5.1._ [[ERC1155Utils-checkOnERC1155Received-address-address-address-uint256-uint256-bytes-]] ==== `[.contract-item-name]#++checkOnERC1155Received++#++(address operator, address from, address to, uint256 id, uint256 value, bytes data)++` [.item-kind]#internal# -Performs an acceptance check for the provided `operator` by calling {IERC1155-onERC1155Received} +Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received} on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). @@ -1536,7 +1593,7 @@ the transfer. [[ERC1155Utils-checkOnERC1155BatchReceived-address-address-address-uint256---uint256---bytes-]] ==== `[.contract-item-name]#++checkOnERC1155BatchReceived++#++(address operator, address from, address to, uint256[] ids, uint256[] values, bytes data)++` [.item-kind]#internal# -Performs a batch acceptance check for the provided `operator` by calling {IERC1155-onERC1155BatchReceived} +Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived} on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). diff --git a/docs/modules/api/pages/token/ERC20.adoc b/docs/modules/api/pages/token/ERC20.adoc index 932633bf3..f0a50b8e4 100644 --- a/docs/modules/api/pages/token/ERC20.adoc +++ b/docs/modules/api/pages/token/ERC20.adoc @@ -499,6 +499,8 @@ :IERC4626-redeem: pass:normal[xref:interfaces.adoc#IERC4626-redeem-uint256-address-address-[`IERC4626.redeem`]] :xref-SafeERC20-safeTransfer-contract-IERC20-address-uint256-: xref:token/ERC20.adoc#SafeERC20-safeTransfer-contract-IERC20-address-uint256- :xref-SafeERC20-safeTransferFrom-contract-IERC20-address-address-uint256-: xref:token/ERC20.adoc#SafeERC20-safeTransferFrom-contract-IERC20-address-address-uint256- +:xref-SafeERC20-trySafeTransfer-contract-IERC20-address-uint256-: xref:token/ERC20.adoc#SafeERC20-trySafeTransfer-contract-IERC20-address-uint256- +:xref-SafeERC20-trySafeTransferFrom-contract-IERC20-address-address-uint256-: xref:token/ERC20.adoc#SafeERC20-trySafeTransferFrom-contract-IERC20-address-address-uint256- :xref-SafeERC20-safeIncreaseAllowance-contract-IERC20-address-uint256-: xref:token/ERC20.adoc#SafeERC20-safeIncreaseAllowance-contract-IERC20-address-uint256- :xref-SafeERC20-safeDecreaseAllowance-contract-IERC20-address-uint256-: xref:token/ERC20.adoc#SafeERC20-safeDecreaseAllowance-contract-IERC20-address-uint256- :xref-SafeERC20-forceApprove-contract-IERC20-address-uint256-: xref:token/ERC20.adoc#SafeERC20-forceApprove-contract-IERC20-address-uint256- @@ -539,11 +541,11 @@ This set of interfaces, contracts, and utilities are all related to the https:// TIP: For an overview of ERC-20 tokens and a walk through on how to create a token contract read our xref:ROOT:erc20.adoc[ERC-20 guide]. -There are a few core contracts that implement the behavior specified in the ERC: +There are a few core contracts that implement the behavior specified in the ERC-20 standard: * {IERC20}: the interface all ERC-20 implementations should conform to. -* {IERC20Metadata}: the extended ERC-20 interface including the <>, <> and <> functions. -* {ERC20}: the implementation of the ERC-20 interface, including the <>, <> and <> optional standard extension to the base interface. +* {IERC20Metadata}: the extended ERC-20 interface including the <>, <> and <> functions. +* {ERC20}: the implementation of the ERC-20 interface, including the <>, <> and <> optional extensions to the standard interface. Additionally there are multiple custom extensions, including: @@ -562,9 +564,9 @@ Finally, there are some utilities to interact with ERC-20 contracts in various w * {SafeERC20}: a wrapper around the interface that eliminates the need to handle boolean return values. -Other utilities that support ERC-20 assets can be found in codebase: +Other utilities that support ERC-20 assets can be found in the codebase: -* ERC-20 tokens can be timelocked (held tokens for a beneficiary until a specified time) or vested (released following a given schedule) using a {VestingWallet}. +* ERC-20 tokens can be timelocked (held for a beneficiary until a specified time) or vested (released following a given schedule) using a {VestingWallet}. NOTE: This core set of contracts is designed to be unopinionated, allowing developers to access the internal functions in ERC-20 (such as <>) and expose them as external functions in the way they prefer. @@ -579,9 +581,16 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel :approve: pass:normal[xref:#IERC20-approve-address-uint256-[`++approve++`]] :transferFrom: pass:normal[xref:#IERC20-transferFrom-address-address-uint256-[`++transferFrom++`]] +:totalSupply-: pass:normal[xref:#IERC20-totalSupply--[`++totalSupply++`]] +:balanceOf-address: pass:normal[xref:#IERC20-balanceOf-address-[`++balanceOf++`]] +:transfer-address-uint256: pass:normal[xref:#IERC20-transfer-address-uint256-[`++transfer++`]] +:allowance-address-address: pass:normal[xref:#IERC20-allowance-address-address-[`++allowance++`]] +:approve-address-uint256: pass:normal[xref:#IERC20-approve-address-uint256-[`++approve++`]] +:transferFrom-address-address-uint256: pass:normal[xref:#IERC20-transferFrom-address-address-uint256-[`++transferFrom++`]] + [.contract] [[IERC20]] -=== `++IERC20++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/IERC20.sol[{github-icon},role=heading-link] +=== `++IERC20++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/IERC20.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -692,9 +701,13 @@ a call to {approve}. `value` is the new allowance. :symbol: pass:normal[xref:#IERC20Metadata-symbol--[`++symbol++`]] :decimals: pass:normal[xref:#IERC20Metadata-decimals--[`++decimals++`]] +:name-: pass:normal[xref:#IERC20Metadata-name--[`++name++`]] +:symbol-: pass:normal[xref:#IERC20Metadata-symbol--[`++symbol++`]] +:decimals-: pass:normal[xref:#IERC20Metadata-decimals--[`++decimals++`]] + [.contract] [[IERC20Metadata]] -=== `++IERC20Metadata++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/IERC20Metadata.sol[{github-icon},role=heading-link] +=== `++IERC20Metadata++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/IERC20Metadata.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -768,9 +781,27 @@ Returns the decimals places of the token. :_approve: pass:normal[xref:#ERC20-_approve-address-address-uint256-bool-[`++_approve++`]] :_spendAllowance: pass:normal[xref:#ERC20-_spendAllowance-address-address-uint256-[`++_spendAllowance++`]] +:constructor-string-string: pass:normal[xref:#ERC20-constructor-string-string-[`++constructor++`]] +:name-: pass:normal[xref:#ERC20-name--[`++name++`]] +:symbol-: pass:normal[xref:#ERC20-symbol--[`++symbol++`]] +:decimals-: pass:normal[xref:#ERC20-decimals--[`++decimals++`]] +:totalSupply-: pass:normal[xref:#ERC20-totalSupply--[`++totalSupply++`]] +:balanceOf-address: pass:normal[xref:#ERC20-balanceOf-address-[`++balanceOf++`]] +:transfer-address-uint256: pass:normal[xref:#ERC20-transfer-address-uint256-[`++transfer++`]] +:allowance-address-address: pass:normal[xref:#ERC20-allowance-address-address-[`++allowance++`]] +:approve-address-uint256: pass:normal[xref:#ERC20-approve-address-uint256-[`++approve++`]] +:transferFrom-address-address-uint256: pass:normal[xref:#ERC20-transferFrom-address-address-uint256-[`++transferFrom++`]] +:_transfer-address-address-uint256: pass:normal[xref:#ERC20-_transfer-address-address-uint256-[`++_transfer++`]] +:_update-address-address-uint256: pass:normal[xref:#ERC20-_update-address-address-uint256-[`++_update++`]] +:_mint-address-uint256: pass:normal[xref:#ERC20-_mint-address-uint256-[`++_mint++`]] +:_burn-address-uint256: pass:normal[xref:#ERC20-_burn-address-uint256-[`++_burn++`]] +:_approve-address-address-uint256: pass:normal[xref:#ERC20-_approve-address-address-uint256-[`++_approve++`]] +:_approve-address-address-uint256-bool: pass:normal[xref:#ERC20-_approve-address-address-uint256-bool-[`++_approve++`]] +:_spendAllowance-address-address-uint256: pass:normal[xref:#ERC20-_spendAllowance-address-address-uint256-[`++_spendAllowance++`]] + [.contract] [[ERC20]] -=== `++ERC20++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/ERC20.sol[{github-icon},role=heading-link] +=== `++ERC20++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/ERC20.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -870,8 +901,7 @@ applications. Sets the values for {name} and {symbol}. -All two of these values are immutable: they can only be set once during -construction. +Both values are immutable: they can only be set once during construction. [.contract-item] [[ERC20-name--]] @@ -1012,7 +1042,7 @@ NOTE: This function is not virtual, {_update} should be overridden instead [[ERC20-_approve-address-address-uint256-]] ==== `[.contract-item-name]#++_approve++#++(address owner, address spender, uint256 value)++` [.item-kind]#internal# -Sets `value` as the allowance of `spender` over the `owner` s tokens. +Sets `value` as the allowance of `spender` over the `owner`'s tokens. This internal function is equivalent to `approve`, and can be used to e.g. set automatic allowances for certain subsystems, etc. @@ -1051,7 +1081,7 @@ Requirements are the same as {_approve}. [[ERC20-_spendAllowance-address-address-uint256-]] ==== `[.contract-item-name]#++_spendAllowance++#++(address owner, address spender, uint256 value)++` [.item-kind]#internal# -Updates `owner` s allowance for `spender` based on spent `value`. +Updates `owner`'s allowance for `spender` based on spent `value`. Does not update the allowance value in case of infinite allowance. Revert if not enough allowance is available. @@ -1064,9 +1094,13 @@ Does not emit an {Approval} event. :nonces: pass:normal[xref:#IERC20Permit-nonces-address-[`++nonces++`]] :DOMAIN_SEPARATOR: pass:normal[xref:#IERC20Permit-DOMAIN_SEPARATOR--[`++DOMAIN_SEPARATOR++`]] +:permit-address-address-uint256-uint256-uint8-bytes32-bytes32: pass:normal[xref:#IERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-[`++permit++`]] +:nonces-address: pass:normal[xref:#IERC20Permit-nonces-address-[`++nonces++`]] +:DOMAIN_SEPARATOR-: pass:normal[xref:#IERC20Permit-DOMAIN_SEPARATOR--[`++DOMAIN_SEPARATOR++`]] + [.contract] [[IERC20Permit]] -=== `++IERC20Permit++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/IERC20Permit.sol[{github-icon},role=heading-link] +=== `++IERC20Permit++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/IERC20Permit.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1166,9 +1200,14 @@ Returns the domain separator used in the encoding of the signature for {permit}, :nonces: pass:normal[xref:#ERC20Permit-nonces-address-[`++nonces++`]] :DOMAIN_SEPARATOR: pass:normal[xref:#ERC20Permit-DOMAIN_SEPARATOR--[`++DOMAIN_SEPARATOR++`]] +:constructor-string: pass:normal[xref:#ERC20Permit-constructor-string-[`++constructor++`]] +:permit-address-address-uint256-uint256-uint8-bytes32-bytes32: pass:normal[xref:#ERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-[`++permit++`]] +:nonces-address: pass:normal[xref:#ERC20Permit-nonces-address-[`++nonces++`]] +:DOMAIN_SEPARATOR-: pass:normal[xref:#ERC20Permit-DOMAIN_SEPARATOR--[`++DOMAIN_SEPARATOR++`]] + [.contract] [[ERC20Permit]] -=== `++ERC20Permit++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/ERC20Permit.sol[{github-icon},role=heading-link] +=== `++ERC20Permit++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/ERC20Permit.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1376,9 +1415,12 @@ Mismatched signature. :burn: pass:normal[xref:#ERC20Burnable-burn-uint256-[`++burn++`]] :burnFrom: pass:normal[xref:#ERC20Burnable-burnFrom-address-uint256-[`++burnFrom++`]] +:burn-uint256: pass:normal[xref:#ERC20Burnable-burn-uint256-[`++burn++`]] +:burnFrom-address-uint256: pass:normal[xref:#ERC20Burnable-burnFrom-address-uint256-[`++burnFrom++`]] + [.contract] [[ERC20Burnable]] -=== `++ERC20Burnable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/ERC20Burnable.sol[{github-icon},role=heading-link] +=== `++ERC20Burnable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/ERC20Burnable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1497,9 +1539,13 @@ Requirements: :cap: pass:normal[xref:#ERC20Capped-cap--[`++cap++`]] :_update: pass:normal[xref:#ERC20Capped-_update-address-address-uint256-[`++_update++`]] +:constructor-uint256: pass:normal[xref:#ERC20Capped-constructor-uint256-[`++constructor++`]] +:cap-: pass:normal[xref:#ERC20Capped-cap--[`++cap++`]] +:_update-address-address-uint256: pass:normal[xref:#ERC20Capped-_update-address-address-uint256-[`++_update++`]] + [.contract] [[ERC20Capped]] -=== `++ERC20Capped++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/ERC20Capped.sol[{github-icon},role=heading-link] +=== `++ERC20Capped++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/ERC20Capped.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1623,9 +1669,11 @@ The supplied cap is not a valid cap. :_update: pass:normal[xref:#ERC20Pausable-_update-address-address-uint256-[`++_update++`]] +:_update-address-address-uint256: pass:normal[xref:#ERC20Pausable-_update-address-address-uint256-[`++_update++`]] + [.contract] [[ERC20Pausable]] -=== `++ERC20Pausable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/ERC20Pausable.sol[{github-icon},role=heading-link] +=== `++ERC20Pausable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/ERC20Pausable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1757,9 +1805,15 @@ Requirements: :numCheckpoints: pass:normal[xref:#ERC20Votes-numCheckpoints-address-[`++numCheckpoints++`]] :checkpoints: pass:normal[xref:#ERC20Votes-checkpoints-address-uint32-[`++checkpoints++`]] +:_maxSupply-: pass:normal[xref:#ERC20Votes-_maxSupply--[`++_maxSupply++`]] +:_update-address-address-uint256: pass:normal[xref:#ERC20Votes-_update-address-address-uint256-[`++_update++`]] +:_getVotingUnits-address: pass:normal[xref:#ERC20Votes-_getVotingUnits-address-[`++_getVotingUnits++`]] +:numCheckpoints-address: pass:normal[xref:#ERC20Votes-numCheckpoints-address-[`++numCheckpoints++`]] +:checkpoints-address-uint32: pass:normal[xref:#ERC20Votes-checkpoints-address-uint32-[`++checkpoints++`]] + [.contract] [[ERC20Votes]] -=== `++ERC20Votes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/ERC20Votes.sol[{github-icon},role=heading-link] +=== `++ERC20Votes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/ERC20Votes.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2010,9 +2064,16 @@ Total supply cap has been exceeded, introducing a risk of votes overflowing. :withdrawTo: pass:normal[xref:#ERC20Wrapper-withdrawTo-address-uint256-[`++withdrawTo++`]] :_recover: pass:normal[xref:#ERC20Wrapper-_recover-address-[`++_recover++`]] +:constructor-contract-IERC20: pass:normal[xref:#ERC20Wrapper-constructor-contract-IERC20-[`++constructor++`]] +:decimals-: pass:normal[xref:#ERC20Wrapper-decimals--[`++decimals++`]] +:underlying-: pass:normal[xref:#ERC20Wrapper-underlying--[`++underlying++`]] +:depositFor-address-uint256: pass:normal[xref:#ERC20Wrapper-depositFor-address-uint256-[`++depositFor++`]] +:withdrawTo-address-uint256: pass:normal[xref:#ERC20Wrapper-withdrawTo-address-uint256-[`++withdrawTo++`]] +:_recover-address: pass:normal[xref:#ERC20Wrapper-_recover-address-[`++_recover++`]] + [.contract] [[ERC20Wrapper]] -=== `++ERC20Wrapper++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/ERC20Wrapper.sol[{github-icon},role=heading-link] +=== `++ERC20Wrapper++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/ERC20Wrapper.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2164,9 +2225,15 @@ The underlying token couldn't be wrapped. :_flashFeeReceiver: pass:normal[xref:#ERC20FlashMint-_flashFeeReceiver--[`++_flashFeeReceiver++`]] :flashLoan: pass:normal[xref:#ERC20FlashMint-flashLoan-contract-IERC3156FlashBorrower-address-uint256-bytes-[`++flashLoan++`]] +:maxFlashLoan-address: pass:normal[xref:#ERC20FlashMint-maxFlashLoan-address-[`++maxFlashLoan++`]] +:flashFee-address-uint256: pass:normal[xref:#ERC20FlashMint-flashFee-address-uint256-[`++flashFee++`]] +:_flashFee-address-uint256: pass:normal[xref:#ERC20FlashMint-_flashFee-address-uint256-[`++_flashFee++`]] +:_flashFeeReceiver-: pass:normal[xref:#ERC20FlashMint-_flashFeeReceiver--[`++_flashFeeReceiver++`]] +:flashLoan-contract-IERC3156FlashBorrower-address-uint256-bytes: pass:normal[xref:#ERC20FlashMint-flashLoan-contract-IERC3156FlashBorrower-address-uint256-bytes-[`++flashLoan++`]] + [.contract] [[ERC20FlashMint]] -=== `++ERC20FlashMint++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/ERC20FlashMint.sol[{github-icon},role=heading-link] +=== `++ERC20FlashMint++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/ERC20FlashMint.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2342,9 +2409,15 @@ The receiver of a flashloan is not a valid {IERC3156FlashBorrower-onFlashLoan} i :_temporaryApprove: pass:normal[xref:#ERC20TemporaryApproval-_temporaryApprove-address-address-uint256-[`++_temporaryApprove++`]] :_spendAllowance: pass:normal[xref:#ERC20TemporaryApproval-_spendAllowance-address-address-uint256-[`++_spendAllowance++`]] +:allowance-address-address: pass:normal[xref:#ERC20TemporaryApproval-allowance-address-address-[`++allowance++`]] +:_temporaryAllowance-address-address: pass:normal[xref:#ERC20TemporaryApproval-_temporaryAllowance-address-address-[`++_temporaryAllowance++`]] +:temporaryApprove-address-uint256: pass:normal[xref:#ERC20TemporaryApproval-temporaryApprove-address-uint256-[`++temporaryApprove++`]] +:_temporaryApprove-address-address-uint256: pass:normal[xref:#ERC20TemporaryApproval-_temporaryApprove-address-address-uint256-[`++_temporaryApprove++`]] +:_spendAllowance-address-address-uint256: pass:normal[xref:#ERC20TemporaryApproval-_spendAllowance-address-address-uint256-[`++_spendAllowance++`]] + [.contract] [[ERC20TemporaryApproval]] -=== `++ERC20TemporaryApproval++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol[{github-icon},role=heading-link] +=== `++ERC20TemporaryApproval++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2478,7 +2551,7 @@ Does NOT emit an {Approval} event. [[ERC20TemporaryApproval-_temporaryApprove-address-address-uint256-]] ==== `[.contract-item-name]#++_temporaryApprove++#++(address owner, address spender, uint256 value)++` [.item-kind]#internal# -Sets `value` as the temporary allowance of `spender` over the `owner` s tokens. +Sets `value` as the temporary allowance of `spender` over the `owner`'s tokens. This internal function is equivalent to `temporaryApprove`, and can be used to e.g. set automatic allowances for certain subsystems, etc. @@ -2509,9 +2582,17 @@ is enough to cover the spending. :approveAndCall: pass:normal[xref:#ERC1363-approveAndCall-address-uint256-[`++approveAndCall++`]] :approveAndCall: pass:normal[xref:#ERC1363-approveAndCall-address-uint256-bytes-[`++approveAndCall++`]] +:supportsInterface-bytes4: pass:normal[xref:#ERC1363-supportsInterface-bytes4-[`++supportsInterface++`]] +:transferAndCall-address-uint256: pass:normal[xref:#ERC1363-transferAndCall-address-uint256-[`++transferAndCall++`]] +:transferAndCall-address-uint256-bytes: pass:normal[xref:#ERC1363-transferAndCall-address-uint256-bytes-[`++transferAndCall++`]] +:transferFromAndCall-address-address-uint256: pass:normal[xref:#ERC1363-transferFromAndCall-address-address-uint256-[`++transferFromAndCall++`]] +:transferFromAndCall-address-address-uint256-bytes: pass:normal[xref:#ERC1363-transferFromAndCall-address-address-uint256-bytes-[`++transferFromAndCall++`]] +:approveAndCall-address-uint256: pass:normal[xref:#ERC1363-approveAndCall-address-uint256-[`++approveAndCall++`]] +:approveAndCall-address-uint256-bytes: pass:normal[xref:#ERC1363-approveAndCall-address-uint256-bytes-[`++approveAndCall++`]] + [.contract] [[ERC1363]] -=== `++ERC1363++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/ERC1363.sol[{github-icon},role=heading-link] +=== `++ERC1363++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/ERC1363.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2762,9 +2843,33 @@ Indicates a failure within the {approve} part of a approveAndCall operation. :_withdraw: pass:normal[xref:#ERC4626-_withdraw-address-address-address-uint256-uint256-[`++_withdraw++`]] :_decimalsOffset: pass:normal[xref:#ERC4626-_decimalsOffset--[`++_decimalsOffset++`]] +:constructor-contract-IERC20: pass:normal[xref:#ERC4626-constructor-contract-IERC20-[`++constructor++`]] +:decimals-: pass:normal[xref:#ERC4626-decimals--[`++decimals++`]] +:asset-: pass:normal[xref:#ERC4626-asset--[`++asset++`]] +:totalAssets-: pass:normal[xref:#ERC4626-totalAssets--[`++totalAssets++`]] +:convertToShares-uint256: pass:normal[xref:#ERC4626-convertToShares-uint256-[`++convertToShares++`]] +:convertToAssets-uint256: pass:normal[xref:#ERC4626-convertToAssets-uint256-[`++convertToAssets++`]] +:maxDeposit-address: pass:normal[xref:#ERC4626-maxDeposit-address-[`++maxDeposit++`]] +:maxMint-address: pass:normal[xref:#ERC4626-maxMint-address-[`++maxMint++`]] +:maxWithdraw-address: pass:normal[xref:#ERC4626-maxWithdraw-address-[`++maxWithdraw++`]] +:maxRedeem-address: pass:normal[xref:#ERC4626-maxRedeem-address-[`++maxRedeem++`]] +:previewDeposit-uint256: pass:normal[xref:#ERC4626-previewDeposit-uint256-[`++previewDeposit++`]] +:previewMint-uint256: pass:normal[xref:#ERC4626-previewMint-uint256-[`++previewMint++`]] +:previewWithdraw-uint256: pass:normal[xref:#ERC4626-previewWithdraw-uint256-[`++previewWithdraw++`]] +:previewRedeem-uint256: pass:normal[xref:#ERC4626-previewRedeem-uint256-[`++previewRedeem++`]] +:deposit-uint256-address: pass:normal[xref:#ERC4626-deposit-uint256-address-[`++deposit++`]] +:mint-uint256-address: pass:normal[xref:#ERC4626-mint-uint256-address-[`++mint++`]] +:withdraw-uint256-address-address: pass:normal[xref:#ERC4626-withdraw-uint256-address-address-[`++withdraw++`]] +:redeem-uint256-address-address: pass:normal[xref:#ERC4626-redeem-uint256-address-address-[`++redeem++`]] +:_convertToShares-uint256-enum-Math-Rounding: pass:normal[xref:#ERC4626-_convertToShares-uint256-enum-Math-Rounding-[`++_convertToShares++`]] +:_convertToAssets-uint256-enum-Math-Rounding: pass:normal[xref:#ERC4626-_convertToAssets-uint256-enum-Math-Rounding-[`++_convertToAssets++`]] +:_deposit-address-address-uint256-uint256: pass:normal[xref:#ERC4626-_deposit-address-address-uint256-uint256-[`++_deposit++`]] +:_withdraw-address-address-address-uint256-uint256: pass:normal[xref:#ERC4626-_withdraw-address-address-address-uint256-uint256-[`++_withdraw++`]] +:_decimalsOffset-: pass:normal[xref:#ERC4626-_decimalsOffset--[`++_decimalsOffset++`]] + [.contract] [[ERC4626]] -=== `++ERC4626++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/extensions/ERC4626.sol[{github-icon},role=heading-link] +=== `++ERC4626++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/extensions/ERC4626.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2796,7 +2901,7 @@ itself determines the initial exchange rate. While not fully preventing the atta offset (0) makes it non-profitable even if an attacker is able to capture value from multiple user deposits, as a result of the value being captured by the virtual shares (out of the attacker's donation) matching the attacker's expected gains. With a larger offset, the attack becomes orders of magnitude more expensive than it is profitable. More details about the -underlying math can be found xref:erc4626.adoc#inflation-attack[here]. +underlying math can be found xref:ROOT:erc4626.adoc#inflation-attack[here]. The drawback of this approach is that the virtual shares do capture (a very small) part of the value being accrued to the vault. Also, if the vault experiences losses, the users try to exit the vault, the virtual shares and assets @@ -3092,6 +3197,8 @@ Attempted to redeem more shares than the max amount for `receiver`. :SafeERC20FailedDecreaseAllowance: pass:normal[xref:#SafeERC20-SafeERC20FailedDecreaseAllowance-address-uint256-uint256-[`++SafeERC20FailedDecreaseAllowance++`]] :safeTransfer: pass:normal[xref:#SafeERC20-safeTransfer-contract-IERC20-address-uint256-[`++safeTransfer++`]] :safeTransferFrom: pass:normal[xref:#SafeERC20-safeTransferFrom-contract-IERC20-address-address-uint256-[`++safeTransferFrom++`]] +:trySafeTransfer: pass:normal[xref:#SafeERC20-trySafeTransfer-contract-IERC20-address-uint256-[`++trySafeTransfer++`]] +:trySafeTransferFrom: pass:normal[xref:#SafeERC20-trySafeTransferFrom-contract-IERC20-address-address-uint256-[`++trySafeTransferFrom++`]] :safeIncreaseAllowance: pass:normal[xref:#SafeERC20-safeIncreaseAllowance-contract-IERC20-address-uint256-[`++safeIncreaseAllowance++`]] :safeDecreaseAllowance: pass:normal[xref:#SafeERC20-safeDecreaseAllowance-contract-IERC20-address-uint256-[`++safeDecreaseAllowance++`]] :forceApprove: pass:normal[xref:#SafeERC20-forceApprove-contract-IERC20-address-uint256-[`++forceApprove++`]] @@ -3099,9 +3206,20 @@ Attempted to redeem more shares than the max amount for `receiver`. :transferFromAndCallRelaxed: pass:normal[xref:#SafeERC20-transferFromAndCallRelaxed-contract-IERC1363-address-address-uint256-bytes-[`++transferFromAndCallRelaxed++`]] :approveAndCallRelaxed: pass:normal[xref:#SafeERC20-approveAndCallRelaxed-contract-IERC1363-address-uint256-bytes-[`++approveAndCallRelaxed++`]] +:safeTransfer-contract-IERC20-address-uint256: pass:normal[xref:#SafeERC20-safeTransfer-contract-IERC20-address-uint256-[`++safeTransfer++`]] +:safeTransferFrom-contract-IERC20-address-address-uint256: pass:normal[xref:#SafeERC20-safeTransferFrom-contract-IERC20-address-address-uint256-[`++safeTransferFrom++`]] +:trySafeTransfer-contract-IERC20-address-uint256: pass:normal[xref:#SafeERC20-trySafeTransfer-contract-IERC20-address-uint256-[`++trySafeTransfer++`]] +:trySafeTransferFrom-contract-IERC20-address-address-uint256: pass:normal[xref:#SafeERC20-trySafeTransferFrom-contract-IERC20-address-address-uint256-[`++trySafeTransferFrom++`]] +:safeIncreaseAllowance-contract-IERC20-address-uint256: pass:normal[xref:#SafeERC20-safeIncreaseAllowance-contract-IERC20-address-uint256-[`++safeIncreaseAllowance++`]] +:safeDecreaseAllowance-contract-IERC20-address-uint256: pass:normal[xref:#SafeERC20-safeDecreaseAllowance-contract-IERC20-address-uint256-[`++safeDecreaseAllowance++`]] +:forceApprove-contract-IERC20-address-uint256: pass:normal[xref:#SafeERC20-forceApprove-contract-IERC20-address-uint256-[`++forceApprove++`]] +:transferAndCallRelaxed-contract-IERC1363-address-uint256-bytes: pass:normal[xref:#SafeERC20-transferAndCallRelaxed-contract-IERC1363-address-uint256-bytes-[`++transferAndCallRelaxed++`]] +:transferFromAndCallRelaxed-contract-IERC1363-address-address-uint256-bytes: pass:normal[xref:#SafeERC20-transferFromAndCallRelaxed-contract-IERC1363-address-address-uint256-bytes-[`++transferFromAndCallRelaxed++`]] +:approveAndCallRelaxed-contract-IERC1363-address-uint256-bytes: pass:normal[xref:#SafeERC20-approveAndCallRelaxed-contract-IERC1363-address-uint256-bytes-[`++approveAndCallRelaxed++`]] + [.contract] [[SafeERC20]] -=== `++SafeERC20++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/utils/SafeERC20.sol[{github-icon},role=heading-link] +=== `++SafeERC20++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/utils/SafeERC20.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3120,6 +3238,8 @@ which allows you to call the safe operations as `token.safeTransfer(...)`, etc. -- * {xref-SafeERC20-safeTransfer-contract-IERC20-address-uint256-}[`++safeTransfer(token, to, value)++`] * {xref-SafeERC20-safeTransferFrom-contract-IERC20-address-address-uint256-}[`++safeTransferFrom(token, from, to, value)++`] +* {xref-SafeERC20-trySafeTransfer-contract-IERC20-address-uint256-}[`++trySafeTransfer(token, to, value)++`] +* {xref-SafeERC20-trySafeTransferFrom-contract-IERC20-address-address-uint256-}[`++trySafeTransferFrom(token, from, to, value)++`] * {xref-SafeERC20-safeIncreaseAllowance-contract-IERC20-address-uint256-}[`++safeIncreaseAllowance(token, spender, value)++`] * {xref-SafeERC20-safeDecreaseAllowance-contract-IERC20-address-uint256-}[`++safeDecreaseAllowance(token, spender, requestedDecrease)++`] * {xref-SafeERC20-forceApprove-contract-IERC20-address-uint256-}[`++forceApprove(token, spender, value)++`] @@ -3151,6 +3271,18 @@ non-reverting calls are assumed to be successful. Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. +[.contract-item] +[[SafeERC20-trySafeTransfer-contract-IERC20-address-uint256-]] +==== `[.contract-item-name]#++trySafeTransfer++#++(contract IERC20 token, address to, uint256 value) → bool++` [.item-kind]#internal# + +Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful. + +[.contract-item] +[[SafeERC20-trySafeTransferFrom-contract-IERC20-address-address-uint256-]] +==== `[.contract-item-name]#++trySafeTransferFrom++#++(contract IERC20 token, address from, address to, uint256 value) → bool++` [.item-kind]#internal# + +Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful. + [.contract-item] [[SafeERC20-safeIncreaseAllowance-contract-IERC20-address-uint256-]] ==== `[.contract-item-name]#++safeIncreaseAllowance++#++(contract IERC20 token, address spender, uint256 value)++` [.item-kind]#internal# @@ -3238,9 +3370,12 @@ Indicates a failed `decreaseAllowance` request. :checkOnERC1363TransferReceived: pass:normal[xref:#ERC1363Utils-checkOnERC1363TransferReceived-address-address-address-uint256-bytes-[`++checkOnERC1363TransferReceived++`]] :checkOnERC1363ApprovalReceived: pass:normal[xref:#ERC1363Utils-checkOnERC1363ApprovalReceived-address-address-uint256-bytes-[`++checkOnERC1363ApprovalReceived++`]] +:checkOnERC1363TransferReceived-address-address-address-uint256-bytes: pass:normal[xref:#ERC1363Utils-checkOnERC1363TransferReceived-address-address-address-uint256-bytes-[`++checkOnERC1363TransferReceived++`]] +:checkOnERC1363ApprovalReceived-address-address-uint256-bytes: pass:normal[xref:#ERC1363Utils-checkOnERC1363ApprovalReceived-address-address-uint256-bytes-[`++checkOnERC1363ApprovalReceived++`]] + [.contract] [[ERC1363Utils]] -=== `++ERC1363Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC20/utils/ERC1363Utils.sol[{github-icon},role=heading-link] +=== `++ERC1363Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC20/utils/ERC1363Utils.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity diff --git a/docs/modules/api/pages/token/ERC6909.adoc b/docs/modules/api/pages/token/ERC6909.adoc new file mode 100644 index 000000000..637f5ac4c --- /dev/null +++ b/docs/modules/api/pages/token/ERC6909.adoc @@ -0,0 +1,891 @@ +:github-icon: pass:[] +:IERC6909: pass:normal[xref:interfaces.adoc#IERC6909[`IERC6909`]] +:IERC6909ContentURI: pass:normal[xref:interfaces.adoc#IERC6909ContentURI[`IERC6909ContentURI`]] +:IERC6909Metadata: pass:normal[xref:interfaces.adoc#IERC6909Metadata[`IERC6909Metadata`]] +:IERC6909TokenSupply: pass:normal[xref:interfaces.adoc#IERC6909TokenSupply[`IERC6909TokenSupply`]] +:xref-ERC6909-supportsInterface-bytes4-: xref:token/ERC6909.adoc#ERC6909-supportsInterface-bytes4- +:xref-ERC6909-balanceOf-address-uint256-: xref:token/ERC6909.adoc#ERC6909-balanceOf-address-uint256- +:xref-ERC6909-allowance-address-address-uint256-: xref:token/ERC6909.adoc#ERC6909-allowance-address-address-uint256- +:xref-ERC6909-isOperator-address-address-: xref:token/ERC6909.adoc#ERC6909-isOperator-address-address- +:xref-ERC6909-approve-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-approve-address-uint256-uint256- +:xref-ERC6909-setOperator-address-bool-: xref:token/ERC6909.adoc#ERC6909-setOperator-address-bool- +:xref-ERC6909-transfer-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-transfer-address-uint256-uint256- +:xref-ERC6909-transferFrom-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-transferFrom-address-address-uint256-uint256- +:xref-ERC6909-_mint-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_mint-address-uint256-uint256- +:xref-ERC6909-_transfer-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_transfer-address-address-uint256-uint256- +:xref-ERC6909-_burn-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_burn-address-uint256-uint256- +:xref-ERC6909-_update-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_update-address-address-uint256-uint256- +:xref-ERC6909-_approve-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_approve-address-address-uint256-uint256- +:xref-ERC6909-_setOperator-address-address-bool-: xref:token/ERC6909.adoc#ERC6909-_setOperator-address-address-bool- +:xref-ERC6909-_spendAllowance-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_spendAllowance-address-address-uint256-uint256- +:xref-IERC6909-Approval-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Approval-address-address-uint256-uint256- +:xref-IERC6909-OperatorSet-address-address-bool-: xref:interfaces.adoc#IERC6909-OperatorSet-address-address-bool- +:xref-IERC6909-Transfer-address-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Transfer-address-address-address-uint256-uint256- +:xref-ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256- +:xref-ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256- +:xref-ERC6909-ERC6909InvalidApprover-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidApprover-address- +:xref-ERC6909-ERC6909InvalidReceiver-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidReceiver-address- +:xref-ERC6909-ERC6909InvalidSender-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidSender-address- +:xref-ERC6909-ERC6909InvalidSpender-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidSpender-address- +:xref-ERC6909ContentURI-contractURI--: xref:token/ERC6909.adoc#ERC6909ContentURI-contractURI-- +:xref-ERC6909ContentURI-tokenURI-uint256-: xref:token/ERC6909.adoc#ERC6909ContentURI-tokenURI-uint256- +:xref-ERC6909ContentURI-_setContractURI-string-: xref:token/ERC6909.adoc#ERC6909ContentURI-_setContractURI-string- +:xref-ERC6909ContentURI-_setTokenURI-uint256-string-: xref:token/ERC6909.adoc#ERC6909ContentURI-_setTokenURI-uint256-string- +:xref-ERC6909-supportsInterface-bytes4-: xref:token/ERC6909.adoc#ERC6909-supportsInterface-bytes4- +:xref-ERC6909-balanceOf-address-uint256-: xref:token/ERC6909.adoc#ERC6909-balanceOf-address-uint256- +:xref-ERC6909-allowance-address-address-uint256-: xref:token/ERC6909.adoc#ERC6909-allowance-address-address-uint256- +:xref-ERC6909-isOperator-address-address-: xref:token/ERC6909.adoc#ERC6909-isOperator-address-address- +:xref-ERC6909-approve-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-approve-address-uint256-uint256- +:xref-ERC6909-setOperator-address-bool-: xref:token/ERC6909.adoc#ERC6909-setOperator-address-bool- +:xref-ERC6909-transfer-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-transfer-address-uint256-uint256- +:xref-ERC6909-transferFrom-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-transferFrom-address-address-uint256-uint256- +:xref-ERC6909-_mint-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_mint-address-uint256-uint256- +:xref-ERC6909-_transfer-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_transfer-address-address-uint256-uint256- +:xref-ERC6909-_burn-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_burn-address-uint256-uint256- +:xref-ERC6909-_update-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_update-address-address-uint256-uint256- +:xref-ERC6909-_approve-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_approve-address-address-uint256-uint256- +:xref-ERC6909-_setOperator-address-address-bool-: xref:token/ERC6909.adoc#ERC6909-_setOperator-address-address-bool- +:xref-ERC6909-_spendAllowance-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_spendAllowance-address-address-uint256-uint256- +:xref-ERC6909ContentURI-ContractURIUpdated--: xref:token/ERC6909.adoc#ERC6909ContentURI-ContractURIUpdated-- +:xref-ERC6909ContentURI-URI-string-uint256-: xref:token/ERC6909.adoc#ERC6909ContentURI-URI-string-uint256- +:xref-IERC6909-Approval-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Approval-address-address-uint256-uint256- +:xref-IERC6909-OperatorSet-address-address-bool-: xref:interfaces.adoc#IERC6909-OperatorSet-address-address-bool- +:xref-IERC6909-Transfer-address-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Transfer-address-address-address-uint256-uint256- +:xref-ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256- +:xref-ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256- +:xref-ERC6909-ERC6909InvalidApprover-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidApprover-address- +:xref-ERC6909-ERC6909InvalidReceiver-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidReceiver-address- +:xref-ERC6909-ERC6909InvalidSender-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidSender-address- +:xref-ERC6909-ERC6909InvalidSpender-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidSpender-address- +:IERC1155-URI: pass:normal[xref:token/ERC1155.adoc#IERC1155-URI-string-uint256-[`IERC1155.URI`]] +:xref-ERC6909Metadata-name-uint256-: xref:token/ERC6909.adoc#ERC6909Metadata-name-uint256- +:xref-ERC6909Metadata-symbol-uint256-: xref:token/ERC6909.adoc#ERC6909Metadata-symbol-uint256- +:xref-ERC6909Metadata-decimals-uint256-: xref:token/ERC6909.adoc#ERC6909Metadata-decimals-uint256- +:xref-ERC6909Metadata-_setName-uint256-string-: xref:token/ERC6909.adoc#ERC6909Metadata-_setName-uint256-string- +:xref-ERC6909Metadata-_setSymbol-uint256-string-: xref:token/ERC6909.adoc#ERC6909Metadata-_setSymbol-uint256-string- +:xref-ERC6909Metadata-_setDecimals-uint256-uint8-: xref:token/ERC6909.adoc#ERC6909Metadata-_setDecimals-uint256-uint8- +:xref-ERC6909-supportsInterface-bytes4-: xref:token/ERC6909.adoc#ERC6909-supportsInterface-bytes4- +:xref-ERC6909-balanceOf-address-uint256-: xref:token/ERC6909.adoc#ERC6909-balanceOf-address-uint256- +:xref-ERC6909-allowance-address-address-uint256-: xref:token/ERC6909.adoc#ERC6909-allowance-address-address-uint256- +:xref-ERC6909-isOperator-address-address-: xref:token/ERC6909.adoc#ERC6909-isOperator-address-address- +:xref-ERC6909-approve-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-approve-address-uint256-uint256- +:xref-ERC6909-setOperator-address-bool-: xref:token/ERC6909.adoc#ERC6909-setOperator-address-bool- +:xref-ERC6909-transfer-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-transfer-address-uint256-uint256- +:xref-ERC6909-transferFrom-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-transferFrom-address-address-uint256-uint256- +:xref-ERC6909-_mint-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_mint-address-uint256-uint256- +:xref-ERC6909-_transfer-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_transfer-address-address-uint256-uint256- +:xref-ERC6909-_burn-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_burn-address-uint256-uint256- +:xref-ERC6909-_update-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_update-address-address-uint256-uint256- +:xref-ERC6909-_approve-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_approve-address-address-uint256-uint256- +:xref-ERC6909-_setOperator-address-address-bool-: xref:token/ERC6909.adoc#ERC6909-_setOperator-address-address-bool- +:xref-ERC6909-_spendAllowance-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_spendAllowance-address-address-uint256-uint256- +:xref-ERC6909Metadata-ERC6909NameUpdated-uint256-string-: xref:token/ERC6909.adoc#ERC6909Metadata-ERC6909NameUpdated-uint256-string- +:xref-ERC6909Metadata-ERC6909SymbolUpdated-uint256-string-: xref:token/ERC6909.adoc#ERC6909Metadata-ERC6909SymbolUpdated-uint256-string- +:xref-ERC6909Metadata-ERC6909DecimalsUpdated-uint256-uint8-: xref:token/ERC6909.adoc#ERC6909Metadata-ERC6909DecimalsUpdated-uint256-uint8- +:xref-IERC6909-Approval-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Approval-address-address-uint256-uint256- +:xref-IERC6909-OperatorSet-address-address-bool-: xref:interfaces.adoc#IERC6909-OperatorSet-address-address-bool- +:xref-IERC6909-Transfer-address-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Transfer-address-address-address-uint256-uint256- +:xref-ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256- +:xref-ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256- +:xref-ERC6909-ERC6909InvalidApprover-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidApprover-address- +:xref-ERC6909-ERC6909InvalidReceiver-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidReceiver-address- +:xref-ERC6909-ERC6909InvalidSender-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidSender-address- +:xref-ERC6909-ERC6909InvalidSpender-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidSpender-address- +:xref-ERC6909TokenSupply-totalSupply-uint256-: xref:token/ERC6909.adoc#ERC6909TokenSupply-totalSupply-uint256- +:xref-ERC6909TokenSupply-_update-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909TokenSupply-_update-address-address-uint256-uint256- +:xref-ERC6909-supportsInterface-bytes4-: xref:token/ERC6909.adoc#ERC6909-supportsInterface-bytes4- +:xref-ERC6909-balanceOf-address-uint256-: xref:token/ERC6909.adoc#ERC6909-balanceOf-address-uint256- +:xref-ERC6909-allowance-address-address-uint256-: xref:token/ERC6909.adoc#ERC6909-allowance-address-address-uint256- +:xref-ERC6909-isOperator-address-address-: xref:token/ERC6909.adoc#ERC6909-isOperator-address-address- +:xref-ERC6909-approve-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-approve-address-uint256-uint256- +:xref-ERC6909-setOperator-address-bool-: xref:token/ERC6909.adoc#ERC6909-setOperator-address-bool- +:xref-ERC6909-transfer-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-transfer-address-uint256-uint256- +:xref-ERC6909-transferFrom-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-transferFrom-address-address-uint256-uint256- +:xref-ERC6909-_mint-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_mint-address-uint256-uint256- +:xref-ERC6909-_transfer-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_transfer-address-address-uint256-uint256- +:xref-ERC6909-_burn-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_burn-address-uint256-uint256- +:xref-ERC6909-_approve-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_approve-address-address-uint256-uint256- +:xref-ERC6909-_setOperator-address-address-bool-: xref:token/ERC6909.adoc#ERC6909-_setOperator-address-address-bool- +:xref-ERC6909-_spendAllowance-address-address-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-_spendAllowance-address-address-uint256-uint256- +:xref-IERC6909-Approval-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Approval-address-address-uint256-uint256- +:xref-IERC6909-OperatorSet-address-address-bool-: xref:interfaces.adoc#IERC6909-OperatorSet-address-address-bool- +:xref-IERC6909-Transfer-address-address-address-uint256-uint256-: xref:interfaces.adoc#IERC6909-Transfer-address-address-address-uint256-uint256- +:xref-ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256- +:xref-ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256-: xref:token/ERC6909.adoc#ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256- +:xref-ERC6909-ERC6909InvalidApprover-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidApprover-address- +:xref-ERC6909-ERC6909InvalidReceiver-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidReceiver-address- +:xref-ERC6909-ERC6909InvalidSender-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidSender-address- +:xref-ERC6909-ERC6909InvalidSpender-address-: xref:token/ERC6909.adoc#ERC6909-ERC6909InvalidSpender-address- += ERC-6909 + +[.readme-notice] +NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/token/erc6909 + +This set of interfaces and contracts are all related to the https://eips.ethereum.org/EIPS/eip-6909[ERC-6909 Minimal Multi-Token Interface]. + +The ERC consists of four interfaces which fulfill different roles--the interfaces are as follows: + +. {IERC6909}: Base interface for a vanilla ERC6909 token. +. {IERC6909ContentURI}: Extends the base interface and adds content URI (contract and token level) functionality. +. {IERC6909Metadata}: Extends the base interface and adds metadata functionality, which exposes a name, symbol, and decimals for each token id. +. {IERC6909TokenSupply}: Extends the base interface and adds total supply functionality for each token id. + +Implementations are provided for each of the 4 interfaces defined in the ERC. + +== Core + +:ERC6909InsufficientBalance: pass:normal[xref:#ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256-[`++ERC6909InsufficientBalance++`]] +:ERC6909InsufficientAllowance: pass:normal[xref:#ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256-[`++ERC6909InsufficientAllowance++`]] +:ERC6909InvalidApprover: pass:normal[xref:#ERC6909-ERC6909InvalidApprover-address-[`++ERC6909InvalidApprover++`]] +:ERC6909InvalidReceiver: pass:normal[xref:#ERC6909-ERC6909InvalidReceiver-address-[`++ERC6909InvalidReceiver++`]] +:ERC6909InvalidSender: pass:normal[xref:#ERC6909-ERC6909InvalidSender-address-[`++ERC6909InvalidSender++`]] +:ERC6909InvalidSpender: pass:normal[xref:#ERC6909-ERC6909InvalidSpender-address-[`++ERC6909InvalidSpender++`]] +:supportsInterface: pass:normal[xref:#ERC6909-supportsInterface-bytes4-[`++supportsInterface++`]] +:balanceOf: pass:normal[xref:#ERC6909-balanceOf-address-uint256-[`++balanceOf++`]] +:allowance: pass:normal[xref:#ERC6909-allowance-address-address-uint256-[`++allowance++`]] +:isOperator: pass:normal[xref:#ERC6909-isOperator-address-address-[`++isOperator++`]] +:approve: pass:normal[xref:#ERC6909-approve-address-uint256-uint256-[`++approve++`]] +:setOperator: pass:normal[xref:#ERC6909-setOperator-address-bool-[`++setOperator++`]] +:transfer: pass:normal[xref:#ERC6909-transfer-address-uint256-uint256-[`++transfer++`]] +:transferFrom: pass:normal[xref:#ERC6909-transferFrom-address-address-uint256-uint256-[`++transferFrom++`]] +:_mint: pass:normal[xref:#ERC6909-_mint-address-uint256-uint256-[`++_mint++`]] +:_transfer: pass:normal[xref:#ERC6909-_transfer-address-address-uint256-uint256-[`++_transfer++`]] +:_burn: pass:normal[xref:#ERC6909-_burn-address-uint256-uint256-[`++_burn++`]] +:_update: pass:normal[xref:#ERC6909-_update-address-address-uint256-uint256-[`++_update++`]] +:_approve: pass:normal[xref:#ERC6909-_approve-address-address-uint256-uint256-[`++_approve++`]] +:_setOperator: pass:normal[xref:#ERC6909-_setOperator-address-address-bool-[`++_setOperator++`]] +:_spendAllowance: pass:normal[xref:#ERC6909-_spendAllowance-address-address-uint256-uint256-[`++_spendAllowance++`]] + +:supportsInterface-bytes4: pass:normal[xref:#ERC6909-supportsInterface-bytes4-[`++supportsInterface++`]] +:balanceOf-address-uint256: pass:normal[xref:#ERC6909-balanceOf-address-uint256-[`++balanceOf++`]] +:allowance-address-address-uint256: pass:normal[xref:#ERC6909-allowance-address-address-uint256-[`++allowance++`]] +:isOperator-address-address: pass:normal[xref:#ERC6909-isOperator-address-address-[`++isOperator++`]] +:approve-address-uint256-uint256: pass:normal[xref:#ERC6909-approve-address-uint256-uint256-[`++approve++`]] +:setOperator-address-bool: pass:normal[xref:#ERC6909-setOperator-address-bool-[`++setOperator++`]] +:transfer-address-uint256-uint256: pass:normal[xref:#ERC6909-transfer-address-uint256-uint256-[`++transfer++`]] +:transferFrom-address-address-uint256-uint256: pass:normal[xref:#ERC6909-transferFrom-address-address-uint256-uint256-[`++transferFrom++`]] +:_mint-address-uint256-uint256: pass:normal[xref:#ERC6909-_mint-address-uint256-uint256-[`++_mint++`]] +:_transfer-address-address-uint256-uint256: pass:normal[xref:#ERC6909-_transfer-address-address-uint256-uint256-[`++_transfer++`]] +:_burn-address-uint256-uint256: pass:normal[xref:#ERC6909-_burn-address-uint256-uint256-[`++_burn++`]] +:_update-address-address-uint256-uint256: pass:normal[xref:#ERC6909-_update-address-address-uint256-uint256-[`++_update++`]] +:_approve-address-address-uint256-uint256: pass:normal[xref:#ERC6909-_approve-address-address-uint256-uint256-[`++_approve++`]] +:_setOperator-address-address-bool: pass:normal[xref:#ERC6909-_setOperator-address-address-bool-[`++_setOperator++`]] +:_spendAllowance-address-address-uint256-uint256: pass:normal[xref:#ERC6909-_spendAllowance-address-address-uint256-uint256-[`++_spendAllowance++`]] + +[.contract] +[[ERC6909]] +=== `++ERC6909++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC6909/draft-ERC6909.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/token/ERC6909/draft-ERC6909.sol"; +``` + +Implementation of ERC-6909. +See https://eips.ethereum.org/EIPS/eip-6909 + +[.contract-index] +.Functions +-- +* {xref-ERC6909-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] +* {xref-ERC6909-balanceOf-address-uint256-}[`++balanceOf(owner, id)++`] +* {xref-ERC6909-allowance-address-address-uint256-}[`++allowance(owner, spender, id)++`] +* {xref-ERC6909-isOperator-address-address-}[`++isOperator(owner, spender)++`] +* {xref-ERC6909-approve-address-uint256-uint256-}[`++approve(spender, id, amount)++`] +* {xref-ERC6909-setOperator-address-bool-}[`++setOperator(spender, approved)++`] +* {xref-ERC6909-transfer-address-uint256-uint256-}[`++transfer(receiver, id, amount)++`] +* {xref-ERC6909-transferFrom-address-address-uint256-uint256-}[`++transferFrom(sender, receiver, id, amount)++`] +* {xref-ERC6909-_mint-address-uint256-uint256-}[`++_mint(to, id, amount)++`] +* {xref-ERC6909-_transfer-address-address-uint256-uint256-}[`++_transfer(from, to, id, amount)++`] +* {xref-ERC6909-_burn-address-uint256-uint256-}[`++_burn(from, id, amount)++`] +* {xref-ERC6909-_update-address-address-uint256-uint256-}[`++_update(from, to, id, amount)++`] +* {xref-ERC6909-_approve-address-address-uint256-uint256-}[`++_approve(owner, spender, id, amount)++`] +* {xref-ERC6909-_setOperator-address-address-bool-}[`++_setOperator(owner, spender, approved)++`] +* {xref-ERC6909-_spendAllowance-address-address-uint256-uint256-}[`++_spendAllowance(owner, spender, id, amount)++`] + +[.contract-subindex-inherited] +.IERC6909 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Events +-- + +[.contract-subindex-inherited] +.IERC6909 +* {xref-IERC6909-Approval-address-address-uint256-uint256-}[`++Approval(owner, spender, id, amount)++`] +* {xref-IERC6909-OperatorSet-address-address-bool-}[`++OperatorSet(owner, spender, approved)++`] +* {xref-IERC6909-Transfer-address-address-address-uint256-uint256-}[`++Transfer(caller, sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Errors +-- +* {xref-ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256-}[`++ERC6909InsufficientBalance(sender, balance, needed, id)++`] +* {xref-ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256-}[`++ERC6909InsufficientAllowance(spender, allowance, needed, id)++`] +* {xref-ERC6909-ERC6909InvalidApprover-address-}[`++ERC6909InvalidApprover(approver)++`] +* {xref-ERC6909-ERC6909InvalidReceiver-address-}[`++ERC6909InvalidReceiver(receiver)++`] +* {xref-ERC6909-ERC6909InvalidSender-address-}[`++ERC6909InvalidSender(sender)++`] +* {xref-ERC6909-ERC6909InvalidSpender-address-}[`++ERC6909InvalidSpender(spender)++`] + +[.contract-subindex-inherited] +.IERC6909 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[ERC6909-supportsInterface-bytes4-]] +==== `[.contract-item-name]#++supportsInterface++#++(bytes4 interfaceId) → bool++` [.item-kind]#public# + +Returns true if this contract implements the interface defined by +`interfaceId`. See the corresponding +https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] +to learn more about how these ids are created. + +This function call must use less than 30 000 gas. + +[.contract-item] +[[ERC6909-balanceOf-address-uint256-]] +==== `[.contract-item-name]#++balanceOf++#++(address owner, uint256 id) → uint256++` [.item-kind]#public# + +Returns the amount of tokens of type `id` owned by `owner`. + +[.contract-item] +[[ERC6909-allowance-address-address-uint256-]] +==== `[.contract-item-name]#++allowance++#++(address owner, address spender, uint256 id) → uint256++` [.item-kind]#public# + +Returns the amount of tokens of type `id` that `spender` is allowed to spend on behalf of `owner`. + +NOTE: Does not include operator allowances. + +[.contract-item] +[[ERC6909-isOperator-address-address-]] +==== `[.contract-item-name]#++isOperator++#++(address owner, address spender) → bool++` [.item-kind]#public# + +Returns true if `spender` is set as an operator for `owner`. + +[.contract-item] +[[ERC6909-approve-address-uint256-uint256-]] +==== `[.contract-item-name]#++approve++#++(address spender, uint256 id, uint256 amount) → bool++` [.item-kind]#public# + +Sets an approval to `spender` for `amount` of tokens of type `id` from the caller's tokens. An `amount` of +`type(uint256).max` signifies an unlimited approval. + +Must return true. + +[.contract-item] +[[ERC6909-setOperator-address-bool-]] +==== `[.contract-item-name]#++setOperator++#++(address spender, bool approved) → bool++` [.item-kind]#public# + +Grants or revokes unlimited transfer permission of any token id to `spender` for the caller's tokens. + +Must return true. + +[.contract-item] +[[ERC6909-transfer-address-uint256-uint256-]] +==== `[.contract-item-name]#++transfer++#++(address receiver, uint256 id, uint256 amount) → bool++` [.item-kind]#public# + +Transfers `amount` of token type `id` from the caller's account to `receiver`. + +Must return true. + +[.contract-item] +[[ERC6909-transferFrom-address-address-uint256-uint256-]] +==== `[.contract-item-name]#++transferFrom++#++(address sender, address receiver, uint256 id, uint256 amount) → bool++` [.item-kind]#public# + +Transfers `amount` of token type `id` from `sender` to `receiver`. + +Must return true. + +[.contract-item] +[[ERC6909-_mint-address-uint256-uint256-]] +==== `[.contract-item-name]#++_mint++#++(address to, uint256 id, uint256 amount)++` [.item-kind]#internal# + +Creates `amount` of token `id` and assigns them to `account`, by transferring it from address(0). +Relies on the `_update` mechanism. + +Emits a {Transfer} event with `from` set to the zero address. + +NOTE: This function is not virtual, {_update} should be overridden instead. + +[.contract-item] +[[ERC6909-_transfer-address-address-uint256-uint256-]] +==== `[.contract-item-name]#++_transfer++#++(address from, address to, uint256 id, uint256 amount)++` [.item-kind]#internal# + +Moves `amount` of token `id` from `from` to `to` without checking for approvals. This function verifies +that neither the sender nor the receiver are address(0), which means it cannot mint or burn tokens. +Relies on the `_update` mechanism. + +Emits a {Transfer} event. + +NOTE: This function is not virtual, {_update} should be overridden instead. + +[.contract-item] +[[ERC6909-_burn-address-uint256-uint256-]] +==== `[.contract-item-name]#++_burn++#++(address from, uint256 id, uint256 amount)++` [.item-kind]#internal# + +Destroys a `amount` of token `id` from `account`. +Relies on the `_update` mechanism. + +Emits a {Transfer} event with `to` set to the zero address. + +NOTE: This function is not virtual, {_update} should be overridden instead + +[.contract-item] +[[ERC6909-_update-address-address-uint256-uint256-]] +==== `[.contract-item-name]#++_update++#++(address from, address to, uint256 id, uint256 amount)++` [.item-kind]#internal# + +Transfers `amount` of token `id` from `from` to `to`, or alternatively mints (or burns) if `from` +(or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding +this function. + +Emits a {Transfer} event. + +[.contract-item] +[[ERC6909-_approve-address-address-uint256-uint256-]] +==== `[.contract-item-name]#++_approve++#++(address owner, address spender, uint256 id, uint256 amount)++` [.item-kind]#internal# + +Sets `amount` as the allowance of `spender` over the `owner`'s `id` tokens. + +This internal function is equivalent to `approve`, and can be used to e.g. set automatic allowances for certain +subsystems, etc. + +Emits an {Approval} event. + +Requirements: + +- `owner` cannot be the zero address. +- `spender` cannot be the zero address. + +[.contract-item] +[[ERC6909-_setOperator-address-address-bool-]] +==== `[.contract-item-name]#++_setOperator++#++(address owner, address spender, bool approved)++` [.item-kind]#internal# + +Approve `spender` to operate on all of `owner`'s tokens + +This internal function is equivalent to `setOperator`, and can be used to e.g. set automatic allowances for +certain subsystems, etc. + +Emits an {OperatorSet} event. + +Requirements: + +- `owner` cannot be the zero address. +- `spender` cannot be the zero address. + +[.contract-item] +[[ERC6909-_spendAllowance-address-address-uint256-uint256-]] +==== `[.contract-item-name]#++_spendAllowance++#++(address owner, address spender, uint256 id, uint256 amount)++` [.item-kind]#internal# + +Updates `owner`'s allowance for `spender` based on spent `amount`. + +Does not update the allowance value in case of infinite allowance. +Revert if not enough allowance is available. + +Does not emit an {Approval} event. + +[.contract-item] +[[ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256-]] +==== `[.contract-item-name]#++ERC6909InsufficientBalance++#++(address sender, uint256 balance, uint256 needed, uint256 id)++` [.item-kind]#error# + +[.contract-item] +[[ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256-]] +==== `[.contract-item-name]#++ERC6909InsufficientAllowance++#++(address spender, uint256 allowance, uint256 needed, uint256 id)++` [.item-kind]#error# + +[.contract-item] +[[ERC6909-ERC6909InvalidApprover-address-]] +==== `[.contract-item-name]#++ERC6909InvalidApprover++#++(address approver)++` [.item-kind]#error# + +[.contract-item] +[[ERC6909-ERC6909InvalidReceiver-address-]] +==== `[.contract-item-name]#++ERC6909InvalidReceiver++#++(address receiver)++` [.item-kind]#error# + +[.contract-item] +[[ERC6909-ERC6909InvalidSender-address-]] +==== `[.contract-item-name]#++ERC6909InvalidSender++#++(address sender)++` [.item-kind]#error# + +[.contract-item] +[[ERC6909-ERC6909InvalidSpender-address-]] +==== `[.contract-item-name]#++ERC6909InvalidSpender++#++(address spender)++` [.item-kind]#error# + +== Extensions + +:ContractURIUpdated: pass:normal[xref:#ERC6909ContentURI-ContractURIUpdated--[`++ContractURIUpdated++`]] +:URI: pass:normal[xref:#ERC6909ContentURI-URI-string-uint256-[`++URI++`]] +:contractURI: pass:normal[xref:#ERC6909ContentURI-contractURI--[`++contractURI++`]] +:tokenURI: pass:normal[xref:#ERC6909ContentURI-tokenURI-uint256-[`++tokenURI++`]] +:_setContractURI: pass:normal[xref:#ERC6909ContentURI-_setContractURI-string-[`++_setContractURI++`]] +:_setTokenURI: pass:normal[xref:#ERC6909ContentURI-_setTokenURI-uint256-string-[`++_setTokenURI++`]] + +:contractURI-: pass:normal[xref:#ERC6909ContentURI-contractURI--[`++contractURI++`]] +:tokenURI-uint256: pass:normal[xref:#ERC6909ContentURI-tokenURI-uint256-[`++tokenURI++`]] +:_setContractURI-string: pass:normal[xref:#ERC6909ContentURI-_setContractURI-string-[`++_setContractURI++`]] +:_setTokenURI-uint256-string: pass:normal[xref:#ERC6909ContentURI-_setTokenURI-uint256-string-[`++_setTokenURI++`]] + +[.contract] +[[ERC6909ContentURI]] +=== `++ERC6909ContentURI++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC6909/extensions/draft-ERC6909ContentURI.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/token/ERC6909/extensions/draft-ERC6909ContentURI.sol"; +``` + +Implementation of the Content URI extension defined in ERC6909. + +[.contract-index] +.Functions +-- +* {xref-ERC6909ContentURI-contractURI--}[`++contractURI()++`] +* {xref-ERC6909ContentURI-tokenURI-uint256-}[`++tokenURI(id)++`] +* {xref-ERC6909ContentURI-_setContractURI-string-}[`++_setContractURI(newContractURI)++`] +* {xref-ERC6909ContentURI-_setTokenURI-uint256-string-}[`++_setTokenURI(id, newTokenURI)++`] + +[.contract-subindex-inherited] +.IERC6909ContentURI + +[.contract-subindex-inherited] +.ERC6909 +* {xref-ERC6909-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] +* {xref-ERC6909-balanceOf-address-uint256-}[`++balanceOf(owner, id)++`] +* {xref-ERC6909-allowance-address-address-uint256-}[`++allowance(owner, spender, id)++`] +* {xref-ERC6909-isOperator-address-address-}[`++isOperator(owner, spender)++`] +* {xref-ERC6909-approve-address-uint256-uint256-}[`++approve(spender, id, amount)++`] +* {xref-ERC6909-setOperator-address-bool-}[`++setOperator(spender, approved)++`] +* {xref-ERC6909-transfer-address-uint256-uint256-}[`++transfer(receiver, id, amount)++`] +* {xref-ERC6909-transferFrom-address-address-uint256-uint256-}[`++transferFrom(sender, receiver, id, amount)++`] +* {xref-ERC6909-_mint-address-uint256-uint256-}[`++_mint(to, id, amount)++`] +* {xref-ERC6909-_transfer-address-address-uint256-uint256-}[`++_transfer(from, to, id, amount)++`] +* {xref-ERC6909-_burn-address-uint256-uint256-}[`++_burn(from, id, amount)++`] +* {xref-ERC6909-_update-address-address-uint256-uint256-}[`++_update(from, to, id, amount)++`] +* {xref-ERC6909-_approve-address-address-uint256-uint256-}[`++_approve(owner, spender, id, amount)++`] +* {xref-ERC6909-_setOperator-address-address-bool-}[`++_setOperator(owner, spender, approved)++`] +* {xref-ERC6909-_spendAllowance-address-address-uint256-uint256-}[`++_spendAllowance(owner, spender, id, amount)++`] + +[.contract-subindex-inherited] +.IERC6909 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Events +-- +* {xref-ERC6909ContentURI-ContractURIUpdated--}[`++ContractURIUpdated()++`] +* {xref-ERC6909ContentURI-URI-string-uint256-}[`++URI(value, id)++`] + +[.contract-subindex-inherited] +.IERC6909ContentURI + +[.contract-subindex-inherited] +.ERC6909 + +[.contract-subindex-inherited] +.IERC6909 +* {xref-IERC6909-Approval-address-address-uint256-uint256-}[`++Approval(owner, spender, id, amount)++`] +* {xref-IERC6909-OperatorSet-address-address-bool-}[`++OperatorSet(owner, spender, approved)++`] +* {xref-IERC6909-Transfer-address-address-address-uint256-uint256-}[`++Transfer(caller, sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Errors +-- + +[.contract-subindex-inherited] +.IERC6909ContentURI + +[.contract-subindex-inherited] +.ERC6909 +* {xref-ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256-}[`++ERC6909InsufficientBalance(sender, balance, needed, id)++`] +* {xref-ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256-}[`++ERC6909InsufficientAllowance(spender, allowance, needed, id)++`] +* {xref-ERC6909-ERC6909InvalidApprover-address-}[`++ERC6909InvalidApprover(approver)++`] +* {xref-ERC6909-ERC6909InvalidReceiver-address-}[`++ERC6909InvalidReceiver(receiver)++`] +* {xref-ERC6909-ERC6909InvalidSender-address-}[`++ERC6909InvalidSender(sender)++`] +* {xref-ERC6909-ERC6909InvalidSpender-address-}[`++ERC6909InvalidSpender(spender)++`] + +[.contract-subindex-inherited] +.IERC6909 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[ERC6909ContentURI-contractURI--]] +==== `[.contract-item-name]#++contractURI++#++() → string++` [.item-kind]#public# + +Returns URI for the contract. + +[.contract-item] +[[ERC6909ContentURI-tokenURI-uint256-]] +==== `[.contract-item-name]#++tokenURI++#++(uint256 id) → string++` [.item-kind]#public# + +Returns the URI for the token of type `id`. + +[.contract-item] +[[ERC6909ContentURI-_setContractURI-string-]] +==== `[.contract-item-name]#++_setContractURI++#++(string newContractURI)++` [.item-kind]#internal# + +Sets the {contractURI} for the contract. + +Emits a {ContractURIUpdated} event. + +[.contract-item] +[[ERC6909ContentURI-_setTokenURI-uint256-string-]] +==== `[.contract-item-name]#++_setTokenURI++#++(uint256 id, string newTokenURI)++` [.item-kind]#internal# + +Sets the {tokenURI} for a given token of type `id`. + +Emits a {URI} event. + +[.contract-item] +[[ERC6909ContentURI-ContractURIUpdated--]] +==== `[.contract-item-name]#++ContractURIUpdated++#++()++` [.item-kind]#event# + +Event emitted when the contract URI is changed. See https://eips.ethereum.org/EIPS/eip-7572[ERC-7572] for details. + +[.contract-item] +[[ERC6909ContentURI-URI-string-uint256-]] +==== `[.contract-item-name]#++URI++#++(string value, uint256 indexed id)++` [.item-kind]#event# + +See {IERC1155-URI} + +:TokenMetadata: pass:normal[xref:#ERC6909Metadata-TokenMetadata[`++TokenMetadata++`]] +:ERC6909NameUpdated: pass:normal[xref:#ERC6909Metadata-ERC6909NameUpdated-uint256-string-[`++ERC6909NameUpdated++`]] +:ERC6909SymbolUpdated: pass:normal[xref:#ERC6909Metadata-ERC6909SymbolUpdated-uint256-string-[`++ERC6909SymbolUpdated++`]] +:ERC6909DecimalsUpdated: pass:normal[xref:#ERC6909Metadata-ERC6909DecimalsUpdated-uint256-uint8-[`++ERC6909DecimalsUpdated++`]] +:name: pass:normal[xref:#ERC6909Metadata-name-uint256-[`++name++`]] +:symbol: pass:normal[xref:#ERC6909Metadata-symbol-uint256-[`++symbol++`]] +:decimals: pass:normal[xref:#ERC6909Metadata-decimals-uint256-[`++decimals++`]] +:_setName: pass:normal[xref:#ERC6909Metadata-_setName-uint256-string-[`++_setName++`]] +:_setSymbol: pass:normal[xref:#ERC6909Metadata-_setSymbol-uint256-string-[`++_setSymbol++`]] +:_setDecimals: pass:normal[xref:#ERC6909Metadata-_setDecimals-uint256-uint8-[`++_setDecimals++`]] + +:name-uint256: pass:normal[xref:#ERC6909Metadata-name-uint256-[`++name++`]] +:symbol-uint256: pass:normal[xref:#ERC6909Metadata-symbol-uint256-[`++symbol++`]] +:decimals-uint256: pass:normal[xref:#ERC6909Metadata-decimals-uint256-[`++decimals++`]] +:_setName-uint256-string: pass:normal[xref:#ERC6909Metadata-_setName-uint256-string-[`++_setName++`]] +:_setSymbol-uint256-string: pass:normal[xref:#ERC6909Metadata-_setSymbol-uint256-string-[`++_setSymbol++`]] +:_setDecimals-uint256-uint8: pass:normal[xref:#ERC6909Metadata-_setDecimals-uint256-uint8-[`++_setDecimals++`]] + +[.contract] +[[ERC6909Metadata]] +=== `++ERC6909Metadata++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC6909/extensions/draft-ERC6909Metadata.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/token/ERC6909/extensions/draft-ERC6909Metadata.sol"; +``` + +Implementation of the Metadata extension defined in ERC6909. Exposes the name, symbol, and decimals of each token id. + +[.contract-index] +.Functions +-- +* {xref-ERC6909Metadata-name-uint256-}[`++name(id)++`] +* {xref-ERC6909Metadata-symbol-uint256-}[`++symbol(id)++`] +* {xref-ERC6909Metadata-decimals-uint256-}[`++decimals(id)++`] +* {xref-ERC6909Metadata-_setName-uint256-string-}[`++_setName(id, newName)++`] +* {xref-ERC6909Metadata-_setSymbol-uint256-string-}[`++_setSymbol(id, newSymbol)++`] +* {xref-ERC6909Metadata-_setDecimals-uint256-uint8-}[`++_setDecimals(id, newDecimals)++`] + +[.contract-subindex-inherited] +.IERC6909Metadata + +[.contract-subindex-inherited] +.ERC6909 +* {xref-ERC6909-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] +* {xref-ERC6909-balanceOf-address-uint256-}[`++balanceOf(owner, id)++`] +* {xref-ERC6909-allowance-address-address-uint256-}[`++allowance(owner, spender, id)++`] +* {xref-ERC6909-isOperator-address-address-}[`++isOperator(owner, spender)++`] +* {xref-ERC6909-approve-address-uint256-uint256-}[`++approve(spender, id, amount)++`] +* {xref-ERC6909-setOperator-address-bool-}[`++setOperator(spender, approved)++`] +* {xref-ERC6909-transfer-address-uint256-uint256-}[`++transfer(receiver, id, amount)++`] +* {xref-ERC6909-transferFrom-address-address-uint256-uint256-}[`++transferFrom(sender, receiver, id, amount)++`] +* {xref-ERC6909-_mint-address-uint256-uint256-}[`++_mint(to, id, amount)++`] +* {xref-ERC6909-_transfer-address-address-uint256-uint256-}[`++_transfer(from, to, id, amount)++`] +* {xref-ERC6909-_burn-address-uint256-uint256-}[`++_burn(from, id, amount)++`] +* {xref-ERC6909-_update-address-address-uint256-uint256-}[`++_update(from, to, id, amount)++`] +* {xref-ERC6909-_approve-address-address-uint256-uint256-}[`++_approve(owner, spender, id, amount)++`] +* {xref-ERC6909-_setOperator-address-address-bool-}[`++_setOperator(owner, spender, approved)++`] +* {xref-ERC6909-_spendAllowance-address-address-uint256-uint256-}[`++_spendAllowance(owner, spender, id, amount)++`] + +[.contract-subindex-inherited] +.IERC6909 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Events +-- +* {xref-ERC6909Metadata-ERC6909NameUpdated-uint256-string-}[`++ERC6909NameUpdated(id, newName)++`] +* {xref-ERC6909Metadata-ERC6909SymbolUpdated-uint256-string-}[`++ERC6909SymbolUpdated(id, newSymbol)++`] +* {xref-ERC6909Metadata-ERC6909DecimalsUpdated-uint256-uint8-}[`++ERC6909DecimalsUpdated(id, newDecimals)++`] + +[.contract-subindex-inherited] +.IERC6909Metadata + +[.contract-subindex-inherited] +.ERC6909 + +[.contract-subindex-inherited] +.IERC6909 +* {xref-IERC6909-Approval-address-address-uint256-uint256-}[`++Approval(owner, spender, id, amount)++`] +* {xref-IERC6909-OperatorSet-address-address-bool-}[`++OperatorSet(owner, spender, approved)++`] +* {xref-IERC6909-Transfer-address-address-address-uint256-uint256-}[`++Transfer(caller, sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Errors +-- + +[.contract-subindex-inherited] +.IERC6909Metadata + +[.contract-subindex-inherited] +.ERC6909 +* {xref-ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256-}[`++ERC6909InsufficientBalance(sender, balance, needed, id)++`] +* {xref-ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256-}[`++ERC6909InsufficientAllowance(spender, allowance, needed, id)++`] +* {xref-ERC6909-ERC6909InvalidApprover-address-}[`++ERC6909InvalidApprover(approver)++`] +* {xref-ERC6909-ERC6909InvalidReceiver-address-}[`++ERC6909InvalidReceiver(receiver)++`] +* {xref-ERC6909-ERC6909InvalidSender-address-}[`++ERC6909InvalidSender(sender)++`] +* {xref-ERC6909-ERC6909InvalidSpender-address-}[`++ERC6909InvalidSpender(spender)++`] + +[.contract-subindex-inherited] +.IERC6909 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[ERC6909Metadata-name-uint256-]] +==== `[.contract-item-name]#++name++#++(uint256 id) → string++` [.item-kind]#public# + +Returns the name of the token of type `id`. + +[.contract-item] +[[ERC6909Metadata-symbol-uint256-]] +==== `[.contract-item-name]#++symbol++#++(uint256 id) → string++` [.item-kind]#public# + +Returns the ticker symbol of the token of type `id`. + +[.contract-item] +[[ERC6909Metadata-decimals-uint256-]] +==== `[.contract-item-name]#++decimals++#++(uint256 id) → uint8++` [.item-kind]#public# + +Returns the number of decimals for the token of type `id`. + +[.contract-item] +[[ERC6909Metadata-_setName-uint256-string-]] +==== `[.contract-item-name]#++_setName++#++(uint256 id, string newName)++` [.item-kind]#internal# + +Sets the `name` for a given token of type `id`. + +Emits an {ERC6909NameUpdated} event. + +[.contract-item] +[[ERC6909Metadata-_setSymbol-uint256-string-]] +==== `[.contract-item-name]#++_setSymbol++#++(uint256 id, string newSymbol)++` [.item-kind]#internal# + +Sets the `symbol` for a given token of type `id`. + +Emits an {ERC6909SymbolUpdated} event. + +[.contract-item] +[[ERC6909Metadata-_setDecimals-uint256-uint8-]] +==== `[.contract-item-name]#++_setDecimals++#++(uint256 id, uint8 newDecimals)++` [.item-kind]#internal# + +Sets the `decimals` for a given token of type `id`. + +Emits an {ERC6909DecimalsUpdated} event. + +[.contract-item] +[[ERC6909Metadata-ERC6909NameUpdated-uint256-string-]] +==== `[.contract-item-name]#++ERC6909NameUpdated++#++(uint256 indexed id, string newName)++` [.item-kind]#event# + +The name of the token of type `id` was updated to `newName`. + +[.contract-item] +[[ERC6909Metadata-ERC6909SymbolUpdated-uint256-string-]] +==== `[.contract-item-name]#++ERC6909SymbolUpdated++#++(uint256 indexed id, string newSymbol)++` [.item-kind]#event# + +The symbol for the token of type `id` was updated to `newSymbol`. + +[.contract-item] +[[ERC6909Metadata-ERC6909DecimalsUpdated-uint256-uint8-]] +==== `[.contract-item-name]#++ERC6909DecimalsUpdated++#++(uint256 indexed id, uint8 newDecimals)++` [.item-kind]#event# + +The decimals value for token of type `id` was updated to `newDecimals`. + +:totalSupply: pass:normal[xref:#ERC6909TokenSupply-totalSupply-uint256-[`++totalSupply++`]] +:_update: pass:normal[xref:#ERC6909TokenSupply-_update-address-address-uint256-uint256-[`++_update++`]] + +:totalSupply-uint256: pass:normal[xref:#ERC6909TokenSupply-totalSupply-uint256-[`++totalSupply++`]] +:_update-address-address-uint256-uint256: pass:normal[xref:#ERC6909TokenSupply-_update-address-address-uint256-uint256-[`++_update++`]] + +[.contract] +[[ERC6909TokenSupply]] +=== `++ERC6909TokenSupply++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol"; +``` + +Implementation of the Token Supply extension defined in ERC6909. +Tracks the total supply of each token id individually. + +[.contract-index] +.Functions +-- +* {xref-ERC6909TokenSupply-totalSupply-uint256-}[`++totalSupply(id)++`] +* {xref-ERC6909TokenSupply-_update-address-address-uint256-uint256-}[`++_update(from, to, id, amount)++`] + +[.contract-subindex-inherited] +.IERC6909TokenSupply + +[.contract-subindex-inherited] +.ERC6909 +* {xref-ERC6909-supportsInterface-bytes4-}[`++supportsInterface(interfaceId)++`] +* {xref-ERC6909-balanceOf-address-uint256-}[`++balanceOf(owner, id)++`] +* {xref-ERC6909-allowance-address-address-uint256-}[`++allowance(owner, spender, id)++`] +* {xref-ERC6909-isOperator-address-address-}[`++isOperator(owner, spender)++`] +* {xref-ERC6909-approve-address-uint256-uint256-}[`++approve(spender, id, amount)++`] +* {xref-ERC6909-setOperator-address-bool-}[`++setOperator(spender, approved)++`] +* {xref-ERC6909-transfer-address-uint256-uint256-}[`++transfer(receiver, id, amount)++`] +* {xref-ERC6909-transferFrom-address-address-uint256-uint256-}[`++transferFrom(sender, receiver, id, amount)++`] +* {xref-ERC6909-_mint-address-uint256-uint256-}[`++_mint(to, id, amount)++`] +* {xref-ERC6909-_transfer-address-address-uint256-uint256-}[`++_transfer(from, to, id, amount)++`] +* {xref-ERC6909-_burn-address-uint256-uint256-}[`++_burn(from, id, amount)++`] +* {xref-ERC6909-_approve-address-address-uint256-uint256-}[`++_approve(owner, spender, id, amount)++`] +* {xref-ERC6909-_setOperator-address-address-bool-}[`++_setOperator(owner, spender, approved)++`] +* {xref-ERC6909-_spendAllowance-address-address-uint256-uint256-}[`++_spendAllowance(owner, spender, id, amount)++`] + +[.contract-subindex-inherited] +.IERC6909 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Events +-- + +[.contract-subindex-inherited] +.IERC6909TokenSupply + +[.contract-subindex-inherited] +.ERC6909 + +[.contract-subindex-inherited] +.IERC6909 +* {xref-IERC6909-Approval-address-address-uint256-uint256-}[`++Approval(owner, spender, id, amount)++`] +* {xref-IERC6909-OperatorSet-address-address-bool-}[`++OperatorSet(owner, spender, approved)++`] +* {xref-IERC6909-Transfer-address-address-address-uint256-uint256-}[`++Transfer(caller, sender, receiver, id, amount)++`] + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-index] +.Errors +-- + +[.contract-subindex-inherited] +.IERC6909TokenSupply + +[.contract-subindex-inherited] +.ERC6909 +* {xref-ERC6909-ERC6909InsufficientBalance-address-uint256-uint256-uint256-}[`++ERC6909InsufficientBalance(sender, balance, needed, id)++`] +* {xref-ERC6909-ERC6909InsufficientAllowance-address-uint256-uint256-uint256-}[`++ERC6909InsufficientAllowance(spender, allowance, needed, id)++`] +* {xref-ERC6909-ERC6909InvalidApprover-address-}[`++ERC6909InvalidApprover(approver)++`] +* {xref-ERC6909-ERC6909InvalidReceiver-address-}[`++ERC6909InvalidReceiver(receiver)++`] +* {xref-ERC6909-ERC6909InvalidSender-address-}[`++ERC6909InvalidSender(sender)++`] +* {xref-ERC6909-ERC6909InvalidSpender-address-}[`++ERC6909InvalidSpender(spender)++`] + +[.contract-subindex-inherited] +.IERC6909 + +[.contract-subindex-inherited] +.ERC165 + +[.contract-subindex-inherited] +.IERC165 + +-- + +[.contract-item] +[[ERC6909TokenSupply-totalSupply-uint256-]] +==== `[.contract-item-name]#++totalSupply++#++(uint256 id) → uint256++` [.item-kind]#public# + +Returns the total supply of the token of type `id`. + +[.contract-item] +[[ERC6909TokenSupply-_update-address-address-uint256-uint256-]] +==== `[.contract-item-name]#++_update++#++(address from, address to, uint256 id, uint256 amount)++` [.item-kind]#internal# + +Override the `_update` function to update the total supply of each token id as necessary. + diff --git a/docs/modules/api/pages/token/ERC721.adoc b/docs/modules/api/pages/token/ERC721.adoc index 10cf72827..c2b365f07 100644 --- a/docs/modules/api/pages/token/ERC721.adoc +++ b/docs/modules/api/pages/token/ERC721.adoc @@ -386,6 +386,7 @@ :xref-IERC721Errors-ERC721InvalidOperator-address-: xref:interfaces.adoc#IERC721Errors-ERC721InvalidOperator-address- :IERC165-supportsInterface: pass:normal[xref:utils.adoc#IERC165-supportsInterface-bytes4-[`IERC165.supportsInterface`]] :IERC721Metadata-tokenURI: pass:normal[xref:token/ERC721.adoc#IERC721Metadata-tokenURI-uint256-[`IERC721Metadata.tokenURI`]] +:IERC4906-MetadataUpdate: pass:normal[xref:interfaces.adoc#IERC4906-MetadataUpdate-uint256-[`IERC4906.MetadataUpdate`]] :Votes: pass:normal[xref:governance.adoc#Votes[`Votes`]] :xref-ERC721Votes-_update-address-uint256-address-: xref:token/ERC721.adoc#ERC721Votes-_update-address-uint256-address- :xref-ERC721Votes-_getVotingUnits-address-: xref:token/ERC721.adoc#ERC721Votes-_getVotingUnits-address- @@ -579,12 +580,13 @@ :IERC721Receiver-onERC721Received: pass:normal[xref:token/ERC721.adoc#IERC721Receiver-onERC721Received-address-address-uint256-bytes-[`IERC721Receiver.onERC721Received`]] :xref-ERC721Utils-checkOnERC721Received-address-address-address-uint256-bytes-: xref:token/ERC721.adoc#ERC721Utils-checkOnERC721Received-address-address-address-uint256-bytes- :IERC721Receiver-onERC721Received: pass:normal[xref:token/ERC721.adoc#IERC721Receiver-onERC721Received-address-address-uint256-bytes-[`IERC721Receiver.onERC721Received`]] +:IERC721Receiver-onERC721Received: pass:normal[xref:token/ERC721.adoc#IERC721Receiver-onERC721Received-address-address-uint256-bytes-[`IERC721Receiver.onERC721Received`]] = ERC-721 [.readme-notice] NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/token/erc721 -This set of interfaces, contracts, and utilities are all related to the https://eips.ethereum.org/EIPS/eip-721[ERC-721 Non-Fungible Token Standard]. +This set of interfaces, contracts, and utilities is all related to the https://eips.ethereum.org/EIPS/eip-721[ERC-721 Non-Fungible Token Standard]. TIP: For a walk through on how to create an ERC-721 token read our xref:ROOT:erc721.adoc[ERC-721 guide]. @@ -603,7 +605,7 @@ OpenZeppelin Contracts provides implementations of all four interfaces: Additionally there are a few of other extensions: -* {ERC721Consecutive}: An implementation of https://eips.ethereum.org/EIPS/eip-2309[ERC-2309] for minting batchs of tokens during construction, in accordance with ERC-721. +* {ERC721Consecutive}: An implementation of https://eips.ethereum.org/EIPS/eip-2309[ERC-2309] for minting batches of tokens during construction, in accordance with ERC-721. * {ERC721URIStorage}: A more flexible but more expensive way of storing metadata. * {ERC721Votes}: Support for voting and vote delegation. * {ERC721Royalty}: A way to signal royalty information following ERC-2981. @@ -628,9 +630,19 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel :getApproved: pass:normal[xref:#IERC721-getApproved-uint256-[`++getApproved++`]] :isApprovedForAll: pass:normal[xref:#IERC721-isApprovedForAll-address-address-[`++isApprovedForAll++`]] +:balanceOf-address: pass:normal[xref:#IERC721-balanceOf-address-[`++balanceOf++`]] +:ownerOf-uint256: pass:normal[xref:#IERC721-ownerOf-uint256-[`++ownerOf++`]] +:safeTransferFrom-address-address-uint256-bytes: pass:normal[xref:#IERC721-safeTransferFrom-address-address-uint256-bytes-[`++safeTransferFrom++`]] +:safeTransferFrom-address-address-uint256: pass:normal[xref:#IERC721-safeTransferFrom-address-address-uint256-[`++safeTransferFrom++`]] +:transferFrom-address-address-uint256: pass:normal[xref:#IERC721-transferFrom-address-address-uint256-[`++transferFrom++`]] +:approve-address-uint256: pass:normal[xref:#IERC721-approve-address-uint256-[`++approve++`]] +:setApprovalForAll-address-bool: pass:normal[xref:#IERC721-setApprovalForAll-address-bool-[`++setApprovalForAll++`]] +:getApproved-uint256: pass:normal[xref:#IERC721-getApproved-uint256-[`++getApproved++`]] +:isApprovedForAll-address-address: pass:normal[xref:#IERC721-isApprovedForAll-address-address-[`++isApprovedForAll++`]] + [.contract] [[IERC721]] -=== `++IERC721++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/IERC721.sol[{github-icon},role=heading-link] +=== `++IERC721++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/IERC721.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -810,9 +822,13 @@ Emitted when `owner` enables or disables (`approved`) `operator` to manage all o :symbol: pass:normal[xref:#IERC721Metadata-symbol--[`++symbol++`]] :tokenURI: pass:normal[xref:#IERC721Metadata-tokenURI-uint256-[`++tokenURI++`]] +:name-: pass:normal[xref:#IERC721Metadata-name--[`++name++`]] +:symbol-: pass:normal[xref:#IERC721Metadata-symbol--[`++symbol++`]] +:tokenURI-uint256: pass:normal[xref:#IERC721Metadata-tokenURI-uint256-[`++tokenURI++`]] + [.contract] [[IERC721Metadata]] -=== `++IERC721Metadata++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/extensions/IERC721Metadata.sol[{github-icon},role=heading-link] +=== `++IERC721Metadata++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/extensions/IERC721Metadata.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -883,9 +899,13 @@ Returns the Uniform Resource Identifier (URI) for `tokenId` token. :tokenOfOwnerByIndex: pass:normal[xref:#IERC721Enumerable-tokenOfOwnerByIndex-address-uint256-[`++tokenOfOwnerByIndex++`]] :tokenByIndex: pass:normal[xref:#IERC721Enumerable-tokenByIndex-uint256-[`++tokenByIndex++`]] +:totalSupply-: pass:normal[xref:#IERC721Enumerable-totalSupply--[`++totalSupply++`]] +:tokenOfOwnerByIndex-address-uint256: pass:normal[xref:#IERC721Enumerable-tokenOfOwnerByIndex-address-uint256-[`++tokenOfOwnerByIndex++`]] +:tokenByIndex-uint256: pass:normal[xref:#IERC721Enumerable-tokenByIndex-uint256-[`++tokenByIndex++`]] + [.contract] [[IERC721Enumerable]] -=== `++IERC721Enumerable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/extensions/IERC721Enumerable.sol[{github-icon},role=heading-link] +=== `++IERC721Enumerable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/extensions/IERC721Enumerable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -987,9 +1007,42 @@ Use along with {totalSupply} to enumerate all tokens. :_setApprovalForAll: pass:normal[xref:#ERC721-_setApprovalForAll-address-address-bool-[`++_setApprovalForAll++`]] :_requireOwned: pass:normal[xref:#ERC721-_requireOwned-uint256-[`++_requireOwned++`]] +:constructor-string-string: pass:normal[xref:#ERC721-constructor-string-string-[`++constructor++`]] +:supportsInterface-bytes4: pass:normal[xref:#ERC721-supportsInterface-bytes4-[`++supportsInterface++`]] +:balanceOf-address: pass:normal[xref:#ERC721-balanceOf-address-[`++balanceOf++`]] +:ownerOf-uint256: pass:normal[xref:#ERC721-ownerOf-uint256-[`++ownerOf++`]] +:name-: pass:normal[xref:#ERC721-name--[`++name++`]] +:symbol-: pass:normal[xref:#ERC721-symbol--[`++symbol++`]] +:tokenURI-uint256: pass:normal[xref:#ERC721-tokenURI-uint256-[`++tokenURI++`]] +:_baseURI-: pass:normal[xref:#ERC721-_baseURI--[`++_baseURI++`]] +:approve-address-uint256: pass:normal[xref:#ERC721-approve-address-uint256-[`++approve++`]] +:getApproved-uint256: pass:normal[xref:#ERC721-getApproved-uint256-[`++getApproved++`]] +:setApprovalForAll-address-bool: pass:normal[xref:#ERC721-setApprovalForAll-address-bool-[`++setApprovalForAll++`]] +:isApprovedForAll-address-address: pass:normal[xref:#ERC721-isApprovedForAll-address-address-[`++isApprovedForAll++`]] +:transferFrom-address-address-uint256: pass:normal[xref:#ERC721-transferFrom-address-address-uint256-[`++transferFrom++`]] +:safeTransferFrom-address-address-uint256: pass:normal[xref:#ERC721-safeTransferFrom-address-address-uint256-[`++safeTransferFrom++`]] +:safeTransferFrom-address-address-uint256-bytes: pass:normal[xref:#ERC721-safeTransferFrom-address-address-uint256-bytes-[`++safeTransferFrom++`]] +:_ownerOf-uint256: pass:normal[xref:#ERC721-_ownerOf-uint256-[`++_ownerOf++`]] +:_getApproved-uint256: pass:normal[xref:#ERC721-_getApproved-uint256-[`++_getApproved++`]] +:_isAuthorized-address-address-uint256: pass:normal[xref:#ERC721-_isAuthorized-address-address-uint256-[`++_isAuthorized++`]] +:_checkAuthorized-address-address-uint256: pass:normal[xref:#ERC721-_checkAuthorized-address-address-uint256-[`++_checkAuthorized++`]] +:_increaseBalance-address-uint128: pass:normal[xref:#ERC721-_increaseBalance-address-uint128-[`++_increaseBalance++`]] +:_update-address-uint256-address: pass:normal[xref:#ERC721-_update-address-uint256-address-[`++_update++`]] +:_mint-address-uint256: pass:normal[xref:#ERC721-_mint-address-uint256-[`++_mint++`]] +:_safeMint-address-uint256: pass:normal[xref:#ERC721-_safeMint-address-uint256-[`++_safeMint++`]] +:_safeMint-address-uint256-bytes: pass:normal[xref:#ERC721-_safeMint-address-uint256-bytes-[`++_safeMint++`]] +:_burn-uint256: pass:normal[xref:#ERC721-_burn-uint256-[`++_burn++`]] +:_transfer-address-address-uint256: pass:normal[xref:#ERC721-_transfer-address-address-uint256-[`++_transfer++`]] +:_safeTransfer-address-address-uint256: pass:normal[xref:#ERC721-_safeTransfer-address-address-uint256-[`++_safeTransfer++`]] +:_safeTransfer-address-address-uint256-bytes: pass:normal[xref:#ERC721-_safeTransfer-address-address-uint256-bytes-[`++_safeTransfer++`]] +:_approve-address-uint256-address: pass:normal[xref:#ERC721-_approve-address-uint256-address-[`++_approve++`]] +:_approve-address-uint256-address-bool: pass:normal[xref:#ERC721-_approve-address-uint256-address-bool-[`++_approve++`]] +:_setApprovalForAll-address-address-bool: pass:normal[xref:#ERC721-_setApprovalForAll-address-address-bool-[`++_setApprovalForAll++`]] +:_requireOwned-uint256: pass:normal[xref:#ERC721-_requireOwned-uint256-[`++_requireOwned++`]] + [.contract] [[ERC721]] -=== `++ERC721++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/ERC721.sol[{github-icon},role=heading-link] +=== `++ERC721++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/ERC721.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1405,9 +1458,16 @@ Overrides to ownership logic should be done to {_ownerOf}. :_update: pass:normal[xref:#ERC721Enumerable-_update-address-uint256-address-[`++_update++`]] :_increaseBalance: pass:normal[xref:#ERC721Enumerable-_increaseBalance-address-uint128-[`++_increaseBalance++`]] +:supportsInterface-bytes4: pass:normal[xref:#ERC721Enumerable-supportsInterface-bytes4-[`++supportsInterface++`]] +:tokenOfOwnerByIndex-address-uint256: pass:normal[xref:#ERC721Enumerable-tokenOfOwnerByIndex-address-uint256-[`++tokenOfOwnerByIndex++`]] +:totalSupply-: pass:normal[xref:#ERC721Enumerable-totalSupply--[`++totalSupply++`]] +:tokenByIndex-uint256: pass:normal[xref:#ERC721Enumerable-tokenByIndex-uint256-[`++tokenByIndex++`]] +:_update-address-uint256-address: pass:normal[xref:#ERC721Enumerable-_update-address-uint256-address-[`++_update++`]] +:_increaseBalance-address-uint128: pass:normal[xref:#ERC721Enumerable-_increaseBalance-address-uint128-[`++_increaseBalance++`]] + [.contract] [[ERC721Enumerable]] -=== `++ERC721Enumerable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/extensions/ERC721Enumerable.sol[{github-icon},role=heading-link] +=== `++ERC721Enumerable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/extensions/ERC721Enumerable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1598,9 +1658,11 @@ Batch mint is not allowed. :onERC721Received: pass:normal[xref:#IERC721Receiver-onERC721Received-address-address-uint256-bytes-[`++onERC721Received++`]] +:onERC721Received-address-address-uint256-bytes: pass:normal[xref:#IERC721Receiver-onERC721Received-address-address-uint256-bytes-[`++onERC721Received++`]] + [.contract] [[IERC721Receiver]] -=== `++IERC721Receiver++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/IERC721Receiver.sol[{github-icon},role=heading-link] +=== `++IERC721Receiver++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/IERC721Receiver.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1634,9 +1696,11 @@ The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received. :_update: pass:normal[xref:#ERC721Pausable-_update-address-uint256-address-[`++_update++`]] +:_update-address-uint256-address: pass:normal[xref:#ERC721Pausable-_update-address-uint256-address-[`++_update++`]] + [.contract] [[ERC721Pausable]] -=== `++ERC721Pausable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/extensions/ERC721Pausable.sol[{github-icon},role=heading-link] +=== `++ERC721Pausable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/extensions/ERC721Pausable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1799,9 +1863,11 @@ Requirements: :burn: pass:normal[xref:#ERC721Burnable-burn-uint256-[`++burn++`]] +:burn-uint256: pass:normal[xref:#ERC721Burnable-burn-uint256-[`++burn++`]] + [.contract] [[ERC721Burnable]] -=== `++ERC721Burnable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/extensions/ERC721Burnable.sol[{github-icon},role=heading-link] +=== `++ERC721Burnable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/extensions/ERC721Burnable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1945,9 +2011,15 @@ Requirements: :_update: pass:normal[xref:#ERC721Consecutive-_update-address-uint256-address-[`++_update++`]] :_firstConsecutiveId: pass:normal[xref:#ERC721Consecutive-_firstConsecutiveId--[`++_firstConsecutiveId++`]] +:_maxBatchSize-: pass:normal[xref:#ERC721Consecutive-_maxBatchSize--[`++_maxBatchSize++`]] +:_ownerOf-uint256: pass:normal[xref:#ERC721Consecutive-_ownerOf-uint256-[`++_ownerOf++`]] +:_mintConsecutive-address-uint96: pass:normal[xref:#ERC721Consecutive-_mintConsecutive-address-uint96-[`++_mintConsecutive++`]] +:_update-address-uint256-address: pass:normal[xref:#ERC721Consecutive-_update-address-uint256-address-[`++_update++`]] +:_firstConsecutiveId-: pass:normal[xref:#ERC721Consecutive-_firstConsecutiveId--[`++_firstConsecutiveId++`]] + [.contract] [[ERC721Consecutive]] -=== `++ERC721Consecutive++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/extensions/ERC721Consecutive.sol[{github-icon},role=heading-link] +=== `++ERC721Consecutive++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/extensions/ERC721Consecutive.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2153,7 +2225,7 @@ After construction, {_mintConsecutive} is no longer available and minting throug [[ERC721Consecutive-_firstConsecutiveId--]] ==== `[.contract-item-name]#++_firstConsecutiveId++#++() → uint96++` [.item-kind]#internal# -Used to offset the first token id in {_nextConsecutiveId} +Used to offset the first token id in `_nextConsecutiveId` [.contract-item] [[ERC721Consecutive-ERC721ForbiddenBatchMint--]] @@ -2185,9 +2257,13 @@ Batch burn is not supported. :tokenURI: pass:normal[xref:#ERC721URIStorage-tokenURI-uint256-[`++tokenURI++`]] :_setTokenURI: pass:normal[xref:#ERC721URIStorage-_setTokenURI-uint256-string-[`++_setTokenURI++`]] +:supportsInterface-bytes4: pass:normal[xref:#ERC721URIStorage-supportsInterface-bytes4-[`++supportsInterface++`]] +:tokenURI-uint256: pass:normal[xref:#ERC721URIStorage-tokenURI-uint256-[`++tokenURI++`]] +:_setTokenURI-uint256-string: pass:normal[xref:#ERC721URIStorage-_setTokenURI-uint256-string-[`++_setTokenURI++`]] + [.contract] [[ERC721URIStorage]] -=== `++ERC721URIStorage++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/extensions/ERC721URIStorage.sol[{github-icon},role=heading-link] +=== `++ERC721URIStorage++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/extensions/ERC721URIStorage.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2340,15 +2416,19 @@ See {IERC721Metadata-tokenURI}. Sets `_tokenURI` as the tokenURI of `tokenId`. -Emits {MetadataUpdate}. +Emits {IERC4906-MetadataUpdate}. :_update: pass:normal[xref:#ERC721Votes-_update-address-uint256-address-[`++_update++`]] :_getVotingUnits: pass:normal[xref:#ERC721Votes-_getVotingUnits-address-[`++_getVotingUnits++`]] :_increaseBalance: pass:normal[xref:#ERC721Votes-_increaseBalance-address-uint128-[`++_increaseBalance++`]] +:_update-address-uint256-address: pass:normal[xref:#ERC721Votes-_update-address-uint256-address-[`++_update++`]] +:_getVotingUnits-address: pass:normal[xref:#ERC721Votes-_getVotingUnits-address-[`++_getVotingUnits++`]] +:_increaseBalance-address-uint128: pass:normal[xref:#ERC721Votes-_increaseBalance-address-uint128-[`++_increaseBalance++`]] + [.contract] [[ERC721Votes]] -=== `++ERC721Votes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/extensions/ERC721Votes.sol[{github-icon},role=heading-link] +=== `++ERC721Votes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/extensions/ERC721Votes.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2594,9 +2674,11 @@ See {ERC721-_increaseBalance}. We need that to account tokens that were minted i :supportsInterface: pass:normal[xref:#ERC721Royalty-supportsInterface-bytes4-[`++supportsInterface++`]] +:supportsInterface-bytes4: pass:normal[xref:#ERC721Royalty-supportsInterface-bytes4-[`++supportsInterface++`]] + [.contract] [[ERC721Royalty]] -=== `++ERC721Royalty++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/extensions/ERC721Royalty.sol[{github-icon},role=heading-link] +=== `++ERC721Royalty++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/extensions/ERC721Royalty.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2769,9 +2851,16 @@ See {IERC165-supportsInterface}. :_recover: pass:normal[xref:#ERC721Wrapper-_recover-address-uint256-[`++_recover++`]] :underlying: pass:normal[xref:#ERC721Wrapper-underlying--[`++underlying++`]] +:constructor-contract-IERC721: pass:normal[xref:#ERC721Wrapper-constructor-contract-IERC721-[`++constructor++`]] +:depositFor-address-uint256--: pass:normal[xref:#ERC721Wrapper-depositFor-address-uint256---[`++depositFor++`]] +:withdrawTo-address-uint256--: pass:normal[xref:#ERC721Wrapper-withdrawTo-address-uint256---[`++withdrawTo++`]] +:onERC721Received-address-address-uint256-bytes: pass:normal[xref:#ERC721Wrapper-onERC721Received-address-address-uint256-bytes-[`++onERC721Received++`]] +:_recover-address-uint256: pass:normal[xref:#ERC721Wrapper-_recover-address-uint256-[`++_recover++`]] +:underlying-: pass:normal[xref:#ERC721Wrapper-underlying--[`++underlying++`]] + [.contract] [[ERC721Wrapper]] -=== `++ERC721Wrapper++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/extensions/ERC721Wrapper.sol[{github-icon},role=heading-link] +=== `++ERC721Wrapper++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/extensions/ERC721Wrapper.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2966,9 +3055,11 @@ The received ERC-721 token couldn't be wrapped. :onERC721Received: pass:normal[xref:#ERC721Holder-onERC721Received-address-address-uint256-bytes-[`++onERC721Received++`]] +:onERC721Received-address-address-uint256-bytes: pass:normal[xref:#ERC721Holder-onERC721Received-address-address-uint256-bytes-[`++onERC721Received++`]] + [.contract] [[ERC721Holder]] -=== `++ERC721Holder++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/utils/ERC721Holder.sol[{github-icon},role=heading-link] +=== `++ERC721Holder++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/utils/ERC721Holder.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3001,9 +3092,11 @@ Always returns `IERC721Receiver.onERC721Received.selector`. :checkOnERC721Received: pass:normal[xref:#ERC721Utils-checkOnERC721Received-address-address-address-uint256-bytes-[`++checkOnERC721Received++`]] +:checkOnERC721Received-address-address-address-uint256-bytes: pass:normal[xref:#ERC721Utils-checkOnERC721Received-address-address-address-uint256-bytes-[`++checkOnERC721Received++`]] + [.contract] [[ERC721Utils]] -=== `++ERC721Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/ERC721/utils/ERC721Utils.sol[{github-icon},role=heading-link] +=== `++ERC721Utils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/ERC721/utils/ERC721Utils.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3027,7 +3120,7 @@ _Available since v5.1._ [[ERC721Utils-checkOnERC721Received-address-address-address-uint256-bytes-]] ==== `[.contract-item-name]#++checkOnERC721Received++#++(address operator, address from, address to, uint256 tokenId, bytes data)++` [.item-kind]#internal# -Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received} +Performs an acceptance check for the provided `operator` by calling {IERC721Receiver-onERC721Received} on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). diff --git a/docs/modules/api/pages/token/common.adoc b/docs/modules/api/pages/token/common.adoc index d1622d1ae..f0fecc0b1 100644 --- a/docs/modules/api/pages/token/common.adoc +++ b/docs/modules/api/pages/token/common.adoc @@ -35,9 +35,17 @@ Functionality that is common to multiple token standards. :_setTokenRoyalty: pass:normal[xref:#ERC2981-_setTokenRoyalty-uint256-address-uint96-[`++_setTokenRoyalty++`]] :_resetTokenRoyalty: pass:normal[xref:#ERC2981-_resetTokenRoyalty-uint256-[`++_resetTokenRoyalty++`]] +:supportsInterface-bytes4: pass:normal[xref:#ERC2981-supportsInterface-bytes4-[`++supportsInterface++`]] +:royaltyInfo-uint256-uint256: pass:normal[xref:#ERC2981-royaltyInfo-uint256-uint256-[`++royaltyInfo++`]] +:_feeDenominator-: pass:normal[xref:#ERC2981-_feeDenominator--[`++_feeDenominator++`]] +:_setDefaultRoyalty-address-uint96: pass:normal[xref:#ERC2981-_setDefaultRoyalty-address-uint96-[`++_setDefaultRoyalty++`]] +:_deleteDefaultRoyalty-: pass:normal[xref:#ERC2981-_deleteDefaultRoyalty--[`++_deleteDefaultRoyalty++`]] +:_setTokenRoyalty-uint256-address-uint96: pass:normal[xref:#ERC2981-_setTokenRoyalty-uint256-address-uint96-[`++_setTokenRoyalty++`]] +:_resetTokenRoyalty-uint256: pass:normal[xref:#ERC2981-_resetTokenRoyalty-uint256-[`++_resetTokenRoyalty++`]] + [.contract] [[ERC2981]] -=== `++ERC2981++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/token/common/ERC2981.sol[{github-icon},role=heading-link] +=== `++ERC2981++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/token/common/ERC2981.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -171,7 +179,7 @@ The default royalty receiver is invalid. [[ERC2981-ERC2981InvalidTokenRoyalty-uint256-uint256-uint256-]] ==== `[.contract-item-name]#++ERC2981InvalidTokenRoyalty++#++(uint256 tokenId, uint256 numerator, uint256 denominator)++` [.item-kind]#error# -The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1). +The royalty set for a specific `tokenId` is invalid (eg. (numerator / denominator) >= 1). [.contract-item] [[ERC2981-ERC2981InvalidTokenRoyaltyReceiver-uint256-address-]] diff --git a/docs/modules/api/pages/utils.adoc b/docs/modules/api/pages/utils.adoc index 9414289da..2f807add6 100644 --- a/docs/modules/api/pages/utils.adoc +++ b/docs/modules/api/pages/utils.adoc @@ -33,8 +33,9 @@ :Arrays: pass:normal[xref:utils.adoc#Arrays[`Arrays`]] :Base64: pass:normal[xref:utils.adoc#Base64[`Base64`]] :Bytes: pass:normal[xref:utils.adoc#Bytes[`Bytes`]] +:Calldata: pass:normal[xref:utils.adoc#Calldata[`Calldata`]] :Strings: pass:normal[xref:utils.adoc#Strings[`Strings`]] -:ShortString: pass:normal[xref:utils.adoc#ShortString[`ShortString`]] +:ShortStrings: pass:normal[xref:utils.adoc#ShortStrings[`ShortStrings`]] :SlotDerivation: pass:normal[xref:utils.adoc#SlotDerivation[`SlotDerivation`]] :StorageSlot: pass:normal[xref:utils.adoc#StorageSlot[`StorageSlot`]] :TransientSlot: pass:normal[xref:utils.adoc#TransientSlot[`TransientSlot`]] @@ -48,11 +49,16 @@ :CAIP10: pass:normal[xref:utils.adoc#CAIP10[`CAIP10`]] :EnumerableMap: pass:normal[xref:utils.adoc#EnumerableMap[`EnumerableMap`]] :EnumerableSet: pass:normal[xref:utils.adoc#EnumerableSet[`EnumerableSet`]] +:xref-Math-add512-uint256-uint256-: xref:utils.adoc#Math-add512-uint256-uint256- +:xref-Math-mul512-uint256-uint256-: xref:utils.adoc#Math-mul512-uint256-uint256- :xref-Math-tryAdd-uint256-uint256-: xref:utils.adoc#Math-tryAdd-uint256-uint256- :xref-Math-trySub-uint256-uint256-: xref:utils.adoc#Math-trySub-uint256-uint256- :xref-Math-tryMul-uint256-uint256-: xref:utils.adoc#Math-tryMul-uint256-uint256- :xref-Math-tryDiv-uint256-uint256-: xref:utils.adoc#Math-tryDiv-uint256-uint256- :xref-Math-tryMod-uint256-uint256-: xref:utils.adoc#Math-tryMod-uint256-uint256- +:xref-Math-saturatingAdd-uint256-uint256-: xref:utils.adoc#Math-saturatingAdd-uint256-uint256- +:xref-Math-saturatingSub-uint256-uint256-: xref:utils.adoc#Math-saturatingSub-uint256-uint256- +:xref-Math-saturatingMul-uint256-uint256-: xref:utils.adoc#Math-saturatingMul-uint256-uint256- :xref-Math-ternary-bool-uint256-uint256-: xref:utils.adoc#Math-ternary-bool-uint256-uint256- :xref-Math-max-uint256-uint256-: xref:utils.adoc#Math-max-uint256-uint256- :xref-Math-min-uint256-uint256-: xref:utils.adoc#Math-min-uint256-uint256- @@ -60,6 +66,8 @@ :xref-Math-ceilDiv-uint256-uint256-: xref:utils.adoc#Math-ceilDiv-uint256-uint256- :xref-Math-mulDiv-uint256-uint256-uint256-: xref:utils.adoc#Math-mulDiv-uint256-uint256-uint256- :xref-Math-mulDiv-uint256-uint256-uint256-enum-Math-Rounding-: xref:utils.adoc#Math-mulDiv-uint256-uint256-uint256-enum-Math-Rounding- +:xref-Math-mulShr-uint256-uint256-uint8-: xref:utils.adoc#Math-mulShr-uint256-uint256-uint8- +:xref-Math-mulShr-uint256-uint256-uint8-enum-Math-Rounding-: xref:utils.adoc#Math-mulShr-uint256-uint256-uint8-enum-Math-Rounding- :xref-Math-invMod-uint256-uint256-: xref:utils.adoc#Math-invMod-uint256-uint256- :xref-Math-invModPrime-uint256-uint256-: xref:utils.adoc#Math-invModPrime-uint256-uint256- :xref-Math-modExp-uint256-uint256-uint256-: xref:utils.adoc#Math-modExp-uint256-uint256-uint256- @@ -189,6 +197,7 @@ :xref-MessageHashUtils-toEthSignedMessageHash-bytes32-: xref:utils.adoc#MessageHashUtils-toEthSignedMessageHash-bytes32- :xref-MessageHashUtils-toEthSignedMessageHash-bytes-: xref:utils.adoc#MessageHashUtils-toEthSignedMessageHash-bytes- :xref-MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes-: xref:utils.adoc#MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes- +:xref-MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes32-: xref:utils.adoc#MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes32- :xref-MessageHashUtils-toTypedDataHash-bytes32-bytes32-: xref:utils.adoc#MessageHashUtils-toTypedDataHash-bytes32-bytes32- :ECDSA-recover: pass:normal[xref:utils.adoc#ECDSA-recover-bytes32-uint8-bytes32-bytes32-[`ECDSA.recover`]] :ECDSA-recover: pass:normal[xref:utils.adoc#ECDSA-recover-bytes32-uint8-bytes32-bytes32-[`ECDSA.recover`]] @@ -197,6 +206,7 @@ :xref-SignatureChecker-isValidSignatureNow-address-bytes32-bytes-: xref:utils.adoc#SignatureChecker-isValidSignatureNow-address-bytes32-bytes- :xref-SignatureChecker-isValidERC1271SignatureNow-address-bytes32-bytes-: xref:utils.adoc#SignatureChecker-isValidERC1271SignatureNow-address-bytes32-bytes- :xref-Hashes-commutativeKeccak256-bytes32-bytes32-: xref:utils.adoc#Hashes-commutativeKeccak256-bytes32-bytes32- +:xref-Hashes-efficientKeccak256-bytes32-bytes32-: xref:utils.adoc#Hashes-efficientKeccak256-bytes32-bytes32- :xref-MerkleProof-verify-bytes32---bytes32-bytes32-: xref:utils.adoc#MerkleProof-verify-bytes32---bytes32-bytes32- :xref-MerkleProof-processProof-bytes32---bytes32-: xref:utils.adoc#MerkleProof-processProof-bytes32---bytes32- :xref-MerkleProof-verify-bytes32---bytes32-bytes32-function--bytes32-bytes32--view-returns--bytes32--: xref:utils.adoc#MerkleProof-verify-bytes32---bytes32-bytes32-function--bytes32-bytes32--view-returns--bytes32-- @@ -225,7 +235,6 @@ :xref-ReentrancyGuardTransient-ReentrancyGuardReentrantCall--: xref:utils.adoc#ReentrancyGuardTransient-ReentrancyGuardReentrantCall-- :xref-Pausable-whenNotPaused--: xref:utils.adoc#Pausable-whenNotPaused-- :xref-Pausable-whenPaused--: xref:utils.adoc#Pausable-whenPaused-- -:xref-Pausable-constructor--: xref:utils.adoc#Pausable-constructor-- :xref-Pausable-paused--: xref:utils.adoc#Pausable-paused-- :xref-Pausable-_requireNotPaused--: xref:utils.adoc#Pausable-_requireNotPaused-- :xref-Pausable-_requirePaused--: xref:utils.adoc#Pausable-_requirePaused-- @@ -275,6 +284,7 @@ :xref-BitMaps-unset-struct-BitMaps-BitMap-uint256-: xref:utils.adoc#BitMaps-unset-struct-BitMaps-BitMap-uint256- :xref-EnumerableMap-set-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-bytes32-: xref:utils.adoc#EnumerableMap-set-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-bytes32- :xref-EnumerableMap-remove-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-: xref:utils.adoc#EnumerableMap-remove-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32- +:xref-EnumerableMap-clear-struct-EnumerableMap-Bytes32ToBytes32Map-: xref:utils.adoc#EnumerableMap-clear-struct-EnumerableMap-Bytes32ToBytes32Map- :xref-EnumerableMap-contains-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-: xref:utils.adoc#EnumerableMap-contains-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32- :xref-EnumerableMap-length-struct-EnumerableMap-Bytes32ToBytes32Map-: xref:utils.adoc#EnumerableMap-length-struct-EnumerableMap-Bytes32ToBytes32Map- :xref-EnumerableMap-at-struct-EnumerableMap-Bytes32ToBytes32Map-uint256-: xref:utils.adoc#EnumerableMap-at-struct-EnumerableMap-Bytes32ToBytes32Map-uint256- @@ -283,6 +293,7 @@ :xref-EnumerableMap-keys-struct-EnumerableMap-Bytes32ToBytes32Map-: xref:utils.adoc#EnumerableMap-keys-struct-EnumerableMap-Bytes32ToBytes32Map- :xref-EnumerableMap-set-struct-EnumerableMap-UintToUintMap-uint256-uint256-: xref:utils.adoc#EnumerableMap-set-struct-EnumerableMap-UintToUintMap-uint256-uint256- :xref-EnumerableMap-remove-struct-EnumerableMap-UintToUintMap-uint256-: xref:utils.adoc#EnumerableMap-remove-struct-EnumerableMap-UintToUintMap-uint256- +:xref-EnumerableMap-clear-struct-EnumerableMap-UintToUintMap-: xref:utils.adoc#EnumerableMap-clear-struct-EnumerableMap-UintToUintMap- :xref-EnumerableMap-contains-struct-EnumerableMap-UintToUintMap-uint256-: xref:utils.adoc#EnumerableMap-contains-struct-EnumerableMap-UintToUintMap-uint256- :xref-EnumerableMap-length-struct-EnumerableMap-UintToUintMap-: xref:utils.adoc#EnumerableMap-length-struct-EnumerableMap-UintToUintMap- :xref-EnumerableMap-at-struct-EnumerableMap-UintToUintMap-uint256-: xref:utils.adoc#EnumerableMap-at-struct-EnumerableMap-UintToUintMap-uint256- @@ -291,6 +302,7 @@ :xref-EnumerableMap-keys-struct-EnumerableMap-UintToUintMap-: xref:utils.adoc#EnumerableMap-keys-struct-EnumerableMap-UintToUintMap- :xref-EnumerableMap-set-struct-EnumerableMap-UintToAddressMap-uint256-address-: xref:utils.adoc#EnumerableMap-set-struct-EnumerableMap-UintToAddressMap-uint256-address- :xref-EnumerableMap-remove-struct-EnumerableMap-UintToAddressMap-uint256-: xref:utils.adoc#EnumerableMap-remove-struct-EnumerableMap-UintToAddressMap-uint256- +:xref-EnumerableMap-clear-struct-EnumerableMap-UintToAddressMap-: xref:utils.adoc#EnumerableMap-clear-struct-EnumerableMap-UintToAddressMap- :xref-EnumerableMap-contains-struct-EnumerableMap-UintToAddressMap-uint256-: xref:utils.adoc#EnumerableMap-contains-struct-EnumerableMap-UintToAddressMap-uint256- :xref-EnumerableMap-length-struct-EnumerableMap-UintToAddressMap-: xref:utils.adoc#EnumerableMap-length-struct-EnumerableMap-UintToAddressMap- :xref-EnumerableMap-at-struct-EnumerableMap-UintToAddressMap-uint256-: xref:utils.adoc#EnumerableMap-at-struct-EnumerableMap-UintToAddressMap-uint256- @@ -299,6 +311,7 @@ :xref-EnumerableMap-keys-struct-EnumerableMap-UintToAddressMap-: xref:utils.adoc#EnumerableMap-keys-struct-EnumerableMap-UintToAddressMap- :xref-EnumerableMap-set-struct-EnumerableMap-UintToBytes32Map-uint256-bytes32-: xref:utils.adoc#EnumerableMap-set-struct-EnumerableMap-UintToBytes32Map-uint256-bytes32- :xref-EnumerableMap-remove-struct-EnumerableMap-UintToBytes32Map-uint256-: xref:utils.adoc#EnumerableMap-remove-struct-EnumerableMap-UintToBytes32Map-uint256- +:xref-EnumerableMap-clear-struct-EnumerableMap-UintToBytes32Map-: xref:utils.adoc#EnumerableMap-clear-struct-EnumerableMap-UintToBytes32Map- :xref-EnumerableMap-contains-struct-EnumerableMap-UintToBytes32Map-uint256-: xref:utils.adoc#EnumerableMap-contains-struct-EnumerableMap-UintToBytes32Map-uint256- :xref-EnumerableMap-length-struct-EnumerableMap-UintToBytes32Map-: xref:utils.adoc#EnumerableMap-length-struct-EnumerableMap-UintToBytes32Map- :xref-EnumerableMap-at-struct-EnumerableMap-UintToBytes32Map-uint256-: xref:utils.adoc#EnumerableMap-at-struct-EnumerableMap-UintToBytes32Map-uint256- @@ -307,6 +320,7 @@ :xref-EnumerableMap-keys-struct-EnumerableMap-UintToBytes32Map-: xref:utils.adoc#EnumerableMap-keys-struct-EnumerableMap-UintToBytes32Map- :xref-EnumerableMap-set-struct-EnumerableMap-AddressToUintMap-address-uint256-: xref:utils.adoc#EnumerableMap-set-struct-EnumerableMap-AddressToUintMap-address-uint256- :xref-EnumerableMap-remove-struct-EnumerableMap-AddressToUintMap-address-: xref:utils.adoc#EnumerableMap-remove-struct-EnumerableMap-AddressToUintMap-address- +:xref-EnumerableMap-clear-struct-EnumerableMap-AddressToUintMap-: xref:utils.adoc#EnumerableMap-clear-struct-EnumerableMap-AddressToUintMap- :xref-EnumerableMap-contains-struct-EnumerableMap-AddressToUintMap-address-: xref:utils.adoc#EnumerableMap-contains-struct-EnumerableMap-AddressToUintMap-address- :xref-EnumerableMap-length-struct-EnumerableMap-AddressToUintMap-: xref:utils.adoc#EnumerableMap-length-struct-EnumerableMap-AddressToUintMap- :xref-EnumerableMap-at-struct-EnumerableMap-AddressToUintMap-uint256-: xref:utils.adoc#EnumerableMap-at-struct-EnumerableMap-AddressToUintMap-uint256- @@ -315,6 +329,7 @@ :xref-EnumerableMap-keys-struct-EnumerableMap-AddressToUintMap-: xref:utils.adoc#EnumerableMap-keys-struct-EnumerableMap-AddressToUintMap- :xref-EnumerableMap-set-struct-EnumerableMap-AddressToAddressMap-address-address-: xref:utils.adoc#EnumerableMap-set-struct-EnumerableMap-AddressToAddressMap-address-address- :xref-EnumerableMap-remove-struct-EnumerableMap-AddressToAddressMap-address-: xref:utils.adoc#EnumerableMap-remove-struct-EnumerableMap-AddressToAddressMap-address- +:xref-EnumerableMap-clear-struct-EnumerableMap-AddressToAddressMap-: xref:utils.adoc#EnumerableMap-clear-struct-EnumerableMap-AddressToAddressMap- :xref-EnumerableMap-contains-struct-EnumerableMap-AddressToAddressMap-address-: xref:utils.adoc#EnumerableMap-contains-struct-EnumerableMap-AddressToAddressMap-address- :xref-EnumerableMap-length-struct-EnumerableMap-AddressToAddressMap-: xref:utils.adoc#EnumerableMap-length-struct-EnumerableMap-AddressToAddressMap- :xref-EnumerableMap-at-struct-EnumerableMap-AddressToAddressMap-uint256-: xref:utils.adoc#EnumerableMap-at-struct-EnumerableMap-AddressToAddressMap-uint256- @@ -323,6 +338,7 @@ :xref-EnumerableMap-keys-struct-EnumerableMap-AddressToAddressMap-: xref:utils.adoc#EnumerableMap-keys-struct-EnumerableMap-AddressToAddressMap- :xref-EnumerableMap-set-struct-EnumerableMap-AddressToBytes32Map-address-bytes32-: xref:utils.adoc#EnumerableMap-set-struct-EnumerableMap-AddressToBytes32Map-address-bytes32- :xref-EnumerableMap-remove-struct-EnumerableMap-AddressToBytes32Map-address-: xref:utils.adoc#EnumerableMap-remove-struct-EnumerableMap-AddressToBytes32Map-address- +:xref-EnumerableMap-clear-struct-EnumerableMap-AddressToBytes32Map-: xref:utils.adoc#EnumerableMap-clear-struct-EnumerableMap-AddressToBytes32Map- :xref-EnumerableMap-contains-struct-EnumerableMap-AddressToBytes32Map-address-: xref:utils.adoc#EnumerableMap-contains-struct-EnumerableMap-AddressToBytes32Map-address- :xref-EnumerableMap-length-struct-EnumerableMap-AddressToBytes32Map-: xref:utils.adoc#EnumerableMap-length-struct-EnumerableMap-AddressToBytes32Map- :xref-EnumerableMap-at-struct-EnumerableMap-AddressToBytes32Map-uint256-: xref:utils.adoc#EnumerableMap-at-struct-EnumerableMap-AddressToBytes32Map-uint256- @@ -331,6 +347,7 @@ :xref-EnumerableMap-keys-struct-EnumerableMap-AddressToBytes32Map-: xref:utils.adoc#EnumerableMap-keys-struct-EnumerableMap-AddressToBytes32Map- :xref-EnumerableMap-set-struct-EnumerableMap-Bytes32ToUintMap-bytes32-uint256-: xref:utils.adoc#EnumerableMap-set-struct-EnumerableMap-Bytes32ToUintMap-bytes32-uint256- :xref-EnumerableMap-remove-struct-EnumerableMap-Bytes32ToUintMap-bytes32-: xref:utils.adoc#EnumerableMap-remove-struct-EnumerableMap-Bytes32ToUintMap-bytes32- +:xref-EnumerableMap-clear-struct-EnumerableMap-Bytes32ToUintMap-: xref:utils.adoc#EnumerableMap-clear-struct-EnumerableMap-Bytes32ToUintMap- :xref-EnumerableMap-contains-struct-EnumerableMap-Bytes32ToUintMap-bytes32-: xref:utils.adoc#EnumerableMap-contains-struct-EnumerableMap-Bytes32ToUintMap-bytes32- :xref-EnumerableMap-length-struct-EnumerableMap-Bytes32ToUintMap-: xref:utils.adoc#EnumerableMap-length-struct-EnumerableMap-Bytes32ToUintMap- :xref-EnumerableMap-at-struct-EnumerableMap-Bytes32ToUintMap-uint256-: xref:utils.adoc#EnumerableMap-at-struct-EnumerableMap-Bytes32ToUintMap-uint256- @@ -339,6 +356,7 @@ :xref-EnumerableMap-keys-struct-EnumerableMap-Bytes32ToUintMap-: xref:utils.adoc#EnumerableMap-keys-struct-EnumerableMap-Bytes32ToUintMap- :xref-EnumerableMap-set-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-address-: xref:utils.adoc#EnumerableMap-set-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-address- :xref-EnumerableMap-remove-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-: xref:utils.adoc#EnumerableMap-remove-struct-EnumerableMap-Bytes32ToAddressMap-bytes32- +:xref-EnumerableMap-clear-struct-EnumerableMap-Bytes32ToAddressMap-: xref:utils.adoc#EnumerableMap-clear-struct-EnumerableMap-Bytes32ToAddressMap- :xref-EnumerableMap-contains-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-: xref:utils.adoc#EnumerableMap-contains-struct-EnumerableMap-Bytes32ToAddressMap-bytes32- :xref-EnumerableMap-length-struct-EnumerableMap-Bytes32ToAddressMap-: xref:utils.adoc#EnumerableMap-length-struct-EnumerableMap-Bytes32ToAddressMap- :xref-EnumerableMap-at-struct-EnumerableMap-Bytes32ToAddressMap-uint256-: xref:utils.adoc#EnumerableMap-at-struct-EnumerableMap-Bytes32ToAddressMap-uint256- @@ -348,18 +366,21 @@ :xref-EnumerableMap-EnumerableMapNonexistentKey-bytes32-: xref:utils.adoc#EnumerableMap-EnumerableMapNonexistentKey-bytes32- :xref-EnumerableSet-add-struct-EnumerableSet-Bytes32Set-bytes32-: xref:utils.adoc#EnumerableSet-add-struct-EnumerableSet-Bytes32Set-bytes32- :xref-EnumerableSet-remove-struct-EnumerableSet-Bytes32Set-bytes32-: xref:utils.adoc#EnumerableSet-remove-struct-EnumerableSet-Bytes32Set-bytes32- +:xref-EnumerableSet-clear-struct-EnumerableSet-Bytes32Set-: xref:utils.adoc#EnumerableSet-clear-struct-EnumerableSet-Bytes32Set- :xref-EnumerableSet-contains-struct-EnumerableSet-Bytes32Set-bytes32-: xref:utils.adoc#EnumerableSet-contains-struct-EnumerableSet-Bytes32Set-bytes32- :xref-EnumerableSet-length-struct-EnumerableSet-Bytes32Set-: xref:utils.adoc#EnumerableSet-length-struct-EnumerableSet-Bytes32Set- :xref-EnumerableSet-at-struct-EnumerableSet-Bytes32Set-uint256-: xref:utils.adoc#EnumerableSet-at-struct-EnumerableSet-Bytes32Set-uint256- :xref-EnumerableSet-values-struct-EnumerableSet-Bytes32Set-: xref:utils.adoc#EnumerableSet-values-struct-EnumerableSet-Bytes32Set- :xref-EnumerableSet-add-struct-EnumerableSet-AddressSet-address-: xref:utils.adoc#EnumerableSet-add-struct-EnumerableSet-AddressSet-address- :xref-EnumerableSet-remove-struct-EnumerableSet-AddressSet-address-: xref:utils.adoc#EnumerableSet-remove-struct-EnumerableSet-AddressSet-address- +:xref-EnumerableSet-clear-struct-EnumerableSet-AddressSet-: xref:utils.adoc#EnumerableSet-clear-struct-EnumerableSet-AddressSet- :xref-EnumerableSet-contains-struct-EnumerableSet-AddressSet-address-: xref:utils.adoc#EnumerableSet-contains-struct-EnumerableSet-AddressSet-address- :xref-EnumerableSet-length-struct-EnumerableSet-AddressSet-: xref:utils.adoc#EnumerableSet-length-struct-EnumerableSet-AddressSet- :xref-EnumerableSet-at-struct-EnumerableSet-AddressSet-uint256-: xref:utils.adoc#EnumerableSet-at-struct-EnumerableSet-AddressSet-uint256- :xref-EnumerableSet-values-struct-EnumerableSet-AddressSet-: xref:utils.adoc#EnumerableSet-values-struct-EnumerableSet-AddressSet- :xref-EnumerableSet-add-struct-EnumerableSet-UintSet-uint256-: xref:utils.adoc#EnumerableSet-add-struct-EnumerableSet-UintSet-uint256- :xref-EnumerableSet-remove-struct-EnumerableSet-UintSet-uint256-: xref:utils.adoc#EnumerableSet-remove-struct-EnumerableSet-UintSet-uint256- +:xref-EnumerableSet-clear-struct-EnumerableSet-UintSet-: xref:utils.adoc#EnumerableSet-clear-struct-EnumerableSet-UintSet- :xref-EnumerableSet-contains-struct-EnumerableSet-UintSet-uint256-: xref:utils.adoc#EnumerableSet-contains-struct-EnumerableSet-UintSet-uint256- :xref-EnumerableSet-length-struct-EnumerableSet-UintSet-: xref:utils.adoc#EnumerableSet-length-struct-EnumerableSet-UintSet- :xref-EnumerableSet-at-struct-EnumerableSet-UintSet-uint256-: xref:utils.adoc#EnumerableSet-at-struct-EnumerableSet-UintSet-uint256- @@ -432,12 +453,18 @@ :xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-function--bytes32-bytes32--view-returns--bytes32--: xref:utils.adoc#MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-function--bytes32-bytes32--view-returns--bytes32-- :xref-MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-: xref:utils.adoc#MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32- :xref-MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-function--bytes32-bytes32--view-returns--bytes32--: xref:utils.adoc#MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-function--bytes32-bytes32--view-returns--bytes32-- +:xref-MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---: xref:utils.adoc#MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32--- +:xref-MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32--: xref:utils.adoc#MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32-- :xref-MerkleTree-depth-struct-MerkleTree-Bytes32PushTree-: xref:utils.adoc#MerkleTree-depth-struct-MerkleTree-Bytes32PushTree- +:xref-MerkleTree-MerkleTreeUpdateInvalidIndex-uint256-uint256-: xref:utils.adoc#MerkleTree-MerkleTreeUpdateInvalidIndex-uint256-uint256- +:xref-MerkleTree-MerkleTreeUpdateInvalidProof--: xref:utils.adoc#MerkleTree-MerkleTreeUpdateInvalidProof-- :Hashes-commutativeKeccak256: pass:normal[xref:utils.adoc#Hashes-commutativeKeccak256-bytes32-bytes32-[`Hashes.commutativeKeccak256`]] :xref-MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-: xref:utils.adoc#MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32- :xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-: xref:utils.adoc#MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32- :Hashes-commutativeKeccak256: pass:normal[xref:utils.adoc#Hashes-commutativeKeccak256-bytes32-bytes32-[`Hashes.commutativeKeccak256`]] :xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-: xref:utils.adoc#MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32- +:Hashes-commutativeKeccak256: pass:normal[xref:utils.adoc#Hashes-commutativeKeccak256-bytes32-bytes32-[`Hashes.commutativeKeccak256`]] +:xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-: xref:utils.adoc#MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32- :xref-Create2-deploy-uint256-bytes32-bytes-: xref:utils.adoc#Create2-deploy-uint256-bytes32-bytes- :xref-Create2-computeAddress-bytes32-bytes32-: xref:utils.adoc#Create2-computeAddress-bytes32-bytes32- :xref-Create2-computeAddress-bytes32-bytes32-address-: xref:utils.adoc#Create2-computeAddress-bytes32-bytes32-address- @@ -478,6 +505,14 @@ :xref-Base64-encodeURL-bytes-: xref:utils.adoc#Base64-encodeURL-bytes- :xref-Base64-_TABLE-string: xref:utils.adoc#Base64-_TABLE-string :xref-Base64-_TABLE_URL-string: xref:utils.adoc#Base64-_TABLE_URL-string +:xref-Bytes-indexOf-bytes-bytes1-: xref:utils.adoc#Bytes-indexOf-bytes-bytes1- +:xref-Bytes-indexOf-bytes-bytes1-uint256-: xref:utils.adoc#Bytes-indexOf-bytes-bytes1-uint256- +:xref-Bytes-lastIndexOf-bytes-bytes1-: xref:utils.adoc#Bytes-lastIndexOf-bytes-bytes1- +:xref-Bytes-lastIndexOf-bytes-bytes1-uint256-: xref:utils.adoc#Bytes-lastIndexOf-bytes-bytes1-uint256- +:xref-Bytes-slice-bytes-uint256-: xref:utils.adoc#Bytes-slice-bytes-uint256- +:xref-Bytes-slice-bytes-uint256-uint256-: xref:utils.adoc#Bytes-slice-bytes-uint256-uint256- +:xref-Calldata-emptyBytes--: xref:utils.adoc#Calldata-emptyBytes-- +:xref-Calldata-emptyString--: xref:utils.adoc#Calldata-emptyString-- :xref-Strings-toString-uint256-: xref:utils.adoc#Strings-toString-uint256- :xref-Strings-toStringSigned-int256-: xref:utils.adoc#Strings-toStringSigned-int256- :xref-Strings-toHexString-uint256-: xref:utils.adoc#Strings-toHexString-uint256- @@ -501,6 +536,7 @@ :xref-Strings-parseAddress-string-uint256-uint256-: xref:utils.adoc#Strings-parseAddress-string-uint256-uint256- :xref-Strings-tryParseAddress-string-: xref:utils.adoc#Strings-tryParseAddress-string- :xref-Strings-tryParseAddress-string-uint256-uint256-: xref:utils.adoc#Strings-tryParseAddress-string-uint256-uint256- +:xref-Strings-escapeJSON-string-: xref:utils.adoc#Strings-escapeJSON-string- :xref-Strings-StringsInsufficientHexLength-uint256-uint256-: xref:utils.adoc#Strings-StringsInsufficientHexLength-uint256-uint256- :xref-Strings-StringsInvalidChar--: xref:utils.adoc#Strings-StringsInvalidChar-- :xref-Strings-StringsInvalidAddressFormat--: xref:utils.adoc#Strings-StringsInvalidAddressFormat-- @@ -549,7 +585,9 @@ :xref-TransientSlot-tstore-TransientSlot-Uint256Slot-uint256-: xref:utils.adoc#TransientSlot-tstore-TransientSlot-Uint256Slot-uint256- :xref-TransientSlot-tload-TransientSlot-Int256Slot-: xref:utils.adoc#TransientSlot-tload-TransientSlot-Int256Slot- :xref-TransientSlot-tstore-TransientSlot-Int256Slot-int256-: xref:utils.adoc#TransientSlot-tstore-TransientSlot-Int256Slot-int256- +:Context-_msgSender: pass:normal[xref:utils.adoc#Context-_msgSender--[`Context._msgSender`]] :ERC2771Context: pass:normal[xref:metatx.adoc#ERC2771Context[`ERC2771Context`]] +:Context-_msgSender: pass:normal[xref:utils.adoc#Context-_msgSender--[`Context._msgSender`]] :xref-Multicall-multicall-bytes---: xref:utils.adoc#Multicall-multicall-bytes--- :xref-Context-_msgSender--: xref:utils.adoc#Context-_msgSender-- :xref-Context-_msgData--: xref:utils.adoc#Context-_msgData-- @@ -780,6 +818,15 @@ :xref-Panic-INVALID_INTERNAL_FUNCTION-uint256: xref:utils.adoc#Panic-INVALID_INTERNAL_FUNCTION-uint256 :xref-Comparators-lt-uint256-uint256-: xref:utils.adoc#Comparators-lt-uint256-uint256- :xref-Comparators-gt-uint256-uint256-: xref:utils.adoc#Comparators-gt-uint256-uint256- +:xref-CAIP2-local--: xref:utils.adoc#CAIP2-local-- +:xref-CAIP2-format-string-string-: xref:utils.adoc#CAIP2-format-string-string- +:xref-CAIP2-parse-string-: xref:utils.adoc#CAIP2-parse-string- +:CAIP2: pass:normal[xref:utils.adoc#CAIP2[`CAIP2`]] +:Strings-toChecksumHexString: pass:normal[xref:utils.adoc#Strings-toChecksumHexString-address-[`Strings.toChecksumHexString`]] +:xref-CAIP10-local-address-: xref:utils.adoc#CAIP10-local-address- +:xref-CAIP10-format-string-string-: xref:utils.adoc#CAIP10-format-string-string- +:xref-CAIP10-parse-string-: xref:utils.adoc#CAIP10-parse-string- +:CAIP2: pass:normal[xref:utils.adoc#CAIP2[`CAIP2`]] = Utilities [.readme-notice] @@ -800,12 +847,12 @@ Miscellaneous contracts and libraries containing utility functions you can use t * {ReentrancyGuardTransient}: Variant of {ReentrancyGuard} that uses transient storage (https://eips.ethereum.org/EIPS/eip-1153[EIP-1153]). * {Pausable}: A common emergency response mechanism that can pause functionality while a remediation is pending. * {Nonces}: Utility for tracking and verifying address nonces that only increment. - * {NoncesKeyed}: Alternative to {Nonces}, that support key-ed nonces following https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337 speciciations]. + * {NoncesKeyed}: Alternative to {Nonces}, that support keyed nonces following https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337 specifications]. * {ERC165}, {ERC165Checker}: Utilities for inspecting interfaces supported by contracts. * {BitMaps}: A simple library to manage boolean value mapped to a numerical index in an efficient way. * {EnumerableMap}: A type like Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`], but with key-value _enumeration_: this will let you know how many entries a mapping has, and iterate over them (which is not possible with `mapping`). * {EnumerableSet}: Like {EnumerableMap}, but for https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets]. Can be used to store privileged accounts, issued IDs, etc. - * {DoubleEndedQueue}: An implementation of a https://en.wikipedia.org/wiki/Double-ended_queue[double ended queue] whose values can be removed added or remove from both sides. Useful for FIFO and LIFO structures. + * {DoubleEndedQueue}: An implementation of a https://en.wikipedia.org/wiki/Double-ended_queue[double ended queue] whose values can be added or removed from both sides. Useful for FIFO and LIFO structures. * {CircularBuffer}: A data structure to store the last N values pushed to it. * {Checkpoints}: A data structure to store values mapped to a strictly increasing key. Can be used for storing and accessing values over time. * {Heap}: A library that implements a https://en.wikipedia.org/wiki/Binary_heap[binary heap] in storage. @@ -815,8 +862,9 @@ Miscellaneous contracts and libraries containing utility functions you can use t * {Arrays}: Collection of functions that operate on https://docs.soliditylang.org/en/latest/types.html#arrays[`arrays`]. * {Base64}: On-chain base64 and base64URL encoding according to https://datatracker.ietf.org/doc/html/rfc4648[RFC-4648]. * {Bytes}: Common operations on bytes objects. + * {Calldata}: Helpers for manipulating calldata. * {Strings}: Common operations for strings formatting. - * {ShortString}: Library to encode (and decode) short strings into (or from) a single bytes32 slot for optimizing costs. Short strings are limited to 31 characters. + * {ShortStrings}: Library to encode (and decode) short strings into (or from) a single bytes32 slot for optimizing costs. Short strings are limited to 31 characters. * {SlotDerivation}: Methods for deriving storage slot from ERC-7201 namespaces as well as from constructions such as mapping and arrays. * {StorageSlot}: Methods for accessing specific storage slots formatted as common primitive types. * {TransientSlot}: Primitives for reading from and writing to transient storage (only value types are currently supported). @@ -824,7 +872,7 @@ Miscellaneous contracts and libraries containing utility functions you can use t * {Context}: A utility for abstracting the sender and calldata in the current execution context. * {Packing}: A library for packing and unpacking multiple values into bytes32 * {Panic}: A library to revert with https://docs.soliditylang.org/en/v0.8.20/control-structures.html#panic-via-assert-and-error-via-require[Solidity panic codes]. - * {Comparators}: A library that contains comparator functions to use with with the {Heap} library. + * {Comparators}: A library that contains comparator functions to use with the {Heap} library. * {CAIP2}, {CAIP10}: Libraries for formatting and parsing CAIP-2 and CAIP-10 identifiers. [NOTE] @@ -835,11 +883,16 @@ Because Solidity does not support generic types, {EnumerableMap} and {Enumerable == Math :Rounding: pass:normal[xref:#Math-Rounding[`++Rounding++`]] +:add512: pass:normal[xref:#Math-add512-uint256-uint256-[`++add512++`]] +:mul512: pass:normal[xref:#Math-mul512-uint256-uint256-[`++mul512++`]] :tryAdd: pass:normal[xref:#Math-tryAdd-uint256-uint256-[`++tryAdd++`]] :trySub: pass:normal[xref:#Math-trySub-uint256-uint256-[`++trySub++`]] :tryMul: pass:normal[xref:#Math-tryMul-uint256-uint256-[`++tryMul++`]] :tryDiv: pass:normal[xref:#Math-tryDiv-uint256-uint256-[`++tryDiv++`]] :tryMod: pass:normal[xref:#Math-tryMod-uint256-uint256-[`++tryMod++`]] +:saturatingAdd: pass:normal[xref:#Math-saturatingAdd-uint256-uint256-[`++saturatingAdd++`]] +:saturatingSub: pass:normal[xref:#Math-saturatingSub-uint256-uint256-[`++saturatingSub++`]] +:saturatingMul: pass:normal[xref:#Math-saturatingMul-uint256-uint256-[`++saturatingMul++`]] :ternary: pass:normal[xref:#Math-ternary-bool-uint256-uint256-[`++ternary++`]] :max: pass:normal[xref:#Math-max-uint256-uint256-[`++max++`]] :min: pass:normal[xref:#Math-min-uint256-uint256-[`++min++`]] @@ -847,6 +900,8 @@ Because Solidity does not support generic types, {EnumerableMap} and {Enumerable :ceilDiv: pass:normal[xref:#Math-ceilDiv-uint256-uint256-[`++ceilDiv++`]] :mulDiv: pass:normal[xref:#Math-mulDiv-uint256-uint256-uint256-[`++mulDiv++`]] :mulDiv: pass:normal[xref:#Math-mulDiv-uint256-uint256-uint256-enum-Math-Rounding-[`++mulDiv++`]] +:mulShr: pass:normal[xref:#Math-mulShr-uint256-uint256-uint8-[`++mulShr++`]] +:mulShr: pass:normal[xref:#Math-mulShr-uint256-uint256-uint8-enum-Math-Rounding-[`++mulShr++`]] :invMod: pass:normal[xref:#Math-invMod-uint256-uint256-[`++invMod++`]] :invModPrime: pass:normal[xref:#Math-invModPrime-uint256-uint256-[`++invModPrime++`]] :modExp: pass:normal[xref:#Math-modExp-uint256-uint256-uint256-[`++modExp++`]] @@ -863,9 +918,44 @@ Because Solidity does not support generic types, {EnumerableMap} and {Enumerable :log256: pass:normal[xref:#Math-log256-uint256-enum-Math-Rounding-[`++log256++`]] :unsignedRoundsUp: pass:normal[xref:#Math-unsignedRoundsUp-enum-Math-Rounding-[`++unsignedRoundsUp++`]] +:add512-uint256-uint256: pass:normal[xref:#Math-add512-uint256-uint256-[`++add512++`]] +:mul512-uint256-uint256: pass:normal[xref:#Math-mul512-uint256-uint256-[`++mul512++`]] +:tryAdd-uint256-uint256: pass:normal[xref:#Math-tryAdd-uint256-uint256-[`++tryAdd++`]] +:trySub-uint256-uint256: pass:normal[xref:#Math-trySub-uint256-uint256-[`++trySub++`]] +:tryMul-uint256-uint256: pass:normal[xref:#Math-tryMul-uint256-uint256-[`++tryMul++`]] +:tryDiv-uint256-uint256: pass:normal[xref:#Math-tryDiv-uint256-uint256-[`++tryDiv++`]] +:tryMod-uint256-uint256: pass:normal[xref:#Math-tryMod-uint256-uint256-[`++tryMod++`]] +:saturatingAdd-uint256-uint256: pass:normal[xref:#Math-saturatingAdd-uint256-uint256-[`++saturatingAdd++`]] +:saturatingSub-uint256-uint256: pass:normal[xref:#Math-saturatingSub-uint256-uint256-[`++saturatingSub++`]] +:saturatingMul-uint256-uint256: pass:normal[xref:#Math-saturatingMul-uint256-uint256-[`++saturatingMul++`]] +:ternary-bool-uint256-uint256: pass:normal[xref:#Math-ternary-bool-uint256-uint256-[`++ternary++`]] +:max-uint256-uint256: pass:normal[xref:#Math-max-uint256-uint256-[`++max++`]] +:min-uint256-uint256: pass:normal[xref:#Math-min-uint256-uint256-[`++min++`]] +:average-uint256-uint256: pass:normal[xref:#Math-average-uint256-uint256-[`++average++`]] +:ceilDiv-uint256-uint256: pass:normal[xref:#Math-ceilDiv-uint256-uint256-[`++ceilDiv++`]] +:mulDiv-uint256-uint256-uint256: pass:normal[xref:#Math-mulDiv-uint256-uint256-uint256-[`++mulDiv++`]] +:mulDiv-uint256-uint256-uint256-enum-Math-Rounding: pass:normal[xref:#Math-mulDiv-uint256-uint256-uint256-enum-Math-Rounding-[`++mulDiv++`]] +:mulShr-uint256-uint256-uint8: pass:normal[xref:#Math-mulShr-uint256-uint256-uint8-[`++mulShr++`]] +:mulShr-uint256-uint256-uint8-enum-Math-Rounding: pass:normal[xref:#Math-mulShr-uint256-uint256-uint8-enum-Math-Rounding-[`++mulShr++`]] +:invMod-uint256-uint256: pass:normal[xref:#Math-invMod-uint256-uint256-[`++invMod++`]] +:invModPrime-uint256-uint256: pass:normal[xref:#Math-invModPrime-uint256-uint256-[`++invModPrime++`]] +:modExp-uint256-uint256-uint256: pass:normal[xref:#Math-modExp-uint256-uint256-uint256-[`++modExp++`]] +:tryModExp-uint256-uint256-uint256: pass:normal[xref:#Math-tryModExp-uint256-uint256-uint256-[`++tryModExp++`]] +:modExp-bytes-bytes-bytes: pass:normal[xref:#Math-modExp-bytes-bytes-bytes-[`++modExp++`]] +:tryModExp-bytes-bytes-bytes: pass:normal[xref:#Math-tryModExp-bytes-bytes-bytes-[`++tryModExp++`]] +:sqrt-uint256: pass:normal[xref:#Math-sqrt-uint256-[`++sqrt++`]] +:sqrt-uint256-enum-Math-Rounding: pass:normal[xref:#Math-sqrt-uint256-enum-Math-Rounding-[`++sqrt++`]] +:log2-uint256: pass:normal[xref:#Math-log2-uint256-[`++log2++`]] +:log2-uint256-enum-Math-Rounding: pass:normal[xref:#Math-log2-uint256-enum-Math-Rounding-[`++log2++`]] +:log10-uint256: pass:normal[xref:#Math-log10-uint256-[`++log10++`]] +:log10-uint256-enum-Math-Rounding: pass:normal[xref:#Math-log10-uint256-enum-Math-Rounding-[`++log10++`]] +:log256-uint256: pass:normal[xref:#Math-log256-uint256-[`++log256++`]] +:log256-uint256-enum-Math-Rounding: pass:normal[xref:#Math-log256-uint256-enum-Math-Rounding-[`++log256++`]] +:unsignedRoundsUp-enum-Math-Rounding: pass:normal[xref:#Math-unsignedRoundsUp-enum-Math-Rounding-[`++unsignedRoundsUp++`]] + [.contract] [[Math]] -=== `++Math++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/math/Math.sol[{github-icon},role=heading-link] +=== `++Math++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/math/Math.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -877,11 +967,16 @@ Standard math utilities missing in the Solidity language. [.contract-index] .Functions -- +* {xref-Math-add512-uint256-uint256-}[`++add512(a, b)++`] +* {xref-Math-mul512-uint256-uint256-}[`++mul512(a, b)++`] * {xref-Math-tryAdd-uint256-uint256-}[`++tryAdd(a, b)++`] * {xref-Math-trySub-uint256-uint256-}[`++trySub(a, b)++`] * {xref-Math-tryMul-uint256-uint256-}[`++tryMul(a, b)++`] * {xref-Math-tryDiv-uint256-uint256-}[`++tryDiv(a, b)++`] * {xref-Math-tryMod-uint256-uint256-}[`++tryMod(a, b)++`] +* {xref-Math-saturatingAdd-uint256-uint256-}[`++saturatingAdd(a, b)++`] +* {xref-Math-saturatingSub-uint256-uint256-}[`++saturatingSub(a, b)++`] +* {xref-Math-saturatingMul-uint256-uint256-}[`++saturatingMul(a, b)++`] * {xref-Math-ternary-bool-uint256-uint256-}[`++ternary(condition, a, b)++`] * {xref-Math-max-uint256-uint256-}[`++max(a, b)++`] * {xref-Math-min-uint256-uint256-}[`++min(a, b)++`] @@ -889,6 +984,8 @@ Standard math utilities missing in the Solidity language. * {xref-Math-ceilDiv-uint256-uint256-}[`++ceilDiv(a, b)++`] * {xref-Math-mulDiv-uint256-uint256-uint256-}[`++mulDiv(x, y, denominator)++`] * {xref-Math-mulDiv-uint256-uint256-uint256-enum-Math-Rounding-}[`++mulDiv(x, y, denominator, rounding)++`] +* {xref-Math-mulShr-uint256-uint256-uint8-}[`++mulShr(x, y, n)++`] +* {xref-Math-mulShr-uint256-uint256-uint8-enum-Math-Rounding-}[`++mulShr(x, y, n, rounding)++`] * {xref-Math-invMod-uint256-uint256-}[`++invMod(a, n)++`] * {xref-Math-invModPrime-uint256-uint256-}[`++invModPrime(a, p)++`] * {xref-Math-modExp-uint256-uint256-uint256-}[`++modExp(b, e, m)++`] @@ -897,33 +994,49 @@ Standard math utilities missing in the Solidity language. * {xref-Math-tryModExp-bytes-bytes-bytes-}[`++tryModExp(b, e, m)++`] * {xref-Math-sqrt-uint256-}[`++sqrt(a)++`] * {xref-Math-sqrt-uint256-enum-Math-Rounding-}[`++sqrt(a, rounding)++`] -* {xref-Math-log2-uint256-}[`++log2(value)++`] +* {xref-Math-log2-uint256-}[`++log2(x)++`] * {xref-Math-log2-uint256-enum-Math-Rounding-}[`++log2(value, rounding)++`] * {xref-Math-log10-uint256-}[`++log10(value)++`] * {xref-Math-log10-uint256-enum-Math-Rounding-}[`++log10(value, rounding)++`] -* {xref-Math-log256-uint256-}[`++log256(value)++`] +* {xref-Math-log256-uint256-}[`++log256(x)++`] * {xref-Math-log256-uint256-enum-Math-Rounding-}[`++log256(value, rounding)++`] * {xref-Math-unsignedRoundsUp-enum-Math-Rounding-}[`++unsignedRoundsUp(rounding)++`] -- +[.contract-item] +[[Math-add512-uint256-uint256-]] +==== `[.contract-item-name]#++add512++#++(uint256 a, uint256 b) → uint256 high, uint256 low++` [.item-kind]#internal# + +Return the 512-bit addition of two uint256. + +The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low. + +[.contract-item] +[[Math-mul512-uint256-uint256-]] +==== `[.contract-item-name]#++mul512++#++(uint256 a, uint256 b) → uint256 high, uint256 low++` [.item-kind]#internal# + +Return the 512-bit multiplication of two uint256. + +The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low. + [.contract-item] [[Math-tryAdd-uint256-uint256-]] ==== `[.contract-item-name]#++tryAdd++#++(uint256 a, uint256 b) → bool success, uint256 result++` [.item-kind]#internal# -Returns the addition of two unsigned integers, with an success flag (no overflow). +Returns the addition of two unsigned integers, with a success flag (no overflow). [.contract-item] [[Math-trySub-uint256-uint256-]] ==== `[.contract-item-name]#++trySub++#++(uint256 a, uint256 b) → bool success, uint256 result++` [.item-kind]#internal# -Returns the subtraction of two unsigned integers, with an success flag (no overflow). +Returns the subtraction of two unsigned integers, with a success flag (no overflow). [.contract-item] [[Math-tryMul-uint256-uint256-]] ==== `[.contract-item-name]#++tryMul++#++(uint256 a, uint256 b) → bool success, uint256 result++` [.item-kind]#internal# -Returns the multiplication of two unsigned integers, with an success flag (no overflow). +Returns the multiplication of two unsigned integers, with a success flag (no overflow). [.contract-item] [[Math-tryDiv-uint256-uint256-]] @@ -937,6 +1050,24 @@ Returns the division of two unsigned integers, with a success flag (no division Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). +[.contract-item] +[[Math-saturatingAdd-uint256-uint256-]] +==== `[.contract-item-name]#++saturatingAdd++#++(uint256 a, uint256 b) → uint256++` [.item-kind]#internal# + +Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing. + +[.contract-item] +[[Math-saturatingSub-uint256-uint256-]] +==== `[.contract-item-name]#++saturatingSub++#++(uint256 a, uint256 b) → uint256++` [.item-kind]#internal# + +Unsigned saturating subtraction, bounds to zero instead of overflowing. + +[.contract-item] +[[Math-saturatingMul-uint256-uint256-]] +==== `[.contract-item-name]#++saturatingMul++#++(uint256 a, uint256 b) → uint256++` [.item-kind]#internal# + +Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing. + [.contract-item] [[Math-ternary-bool-uint256-uint256-]] ==== `[.contract-item-name]#++ternary++#++(bool condition, uint256 a, uint256 b) → uint256++` [.item-kind]#internal# @@ -991,6 +1122,18 @@ Uniswap Labs also under MIT license. Calculates x * y / denominator with full precision, following the selected rounding direction. +[.contract-item] +[[Math-mulShr-uint256-uint256-uint8-]] +==== `[.contract-item-name]#++mulShr++#++(uint256 x, uint256 y, uint8 n) → uint256 result++` [.item-kind]#internal# + +Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256. + +[.contract-item] +[[Math-mulShr-uint256-uint256-uint8-enum-Math-Rounding-]] +==== `[.contract-item-name]#++mulShr++#++(uint256 x, uint256 y, uint8 n, enum Math.Rounding rounding) → uint256++` [.item-kind]#internal# + +Calculates x * y >> n with full precision, following the selected rounding direction. + [.contract-item] [[Math-invMod-uint256-uint256-]] ==== `[.contract-item-name]#++invMod++#++(uint256 a, uint256 n) → uint256++` [.item-kind]#internal# @@ -1076,7 +1219,7 @@ Calculates sqrt(a), following the selected rounding direction. [.contract-item] [[Math-log2-uint256-]] -==== `[.contract-item-name]#++log2++#++(uint256 value) → uint256++` [.item-kind]#internal# +==== `[.contract-item-name]#++log2++#++(uint256 x) → uint256 r++` [.item-kind]#internal# Return the log in base 2 of a positive value rounded towards zero. Returns 0 if given 0. @@ -1104,7 +1247,7 @@ Returns 0 if given 0. [.contract-item] [[Math-log256-uint256-]] -==== `[.contract-item-name]#++log256++#++(uint256 value) → uint256++` [.item-kind]#internal# +==== `[.contract-item-name]#++log256++#++(uint256 x) → uint256 r++` [.item-kind]#internal# Return the log in base 256 of a positive value rounded towards zero. Returns 0 if given 0. @@ -1130,9 +1273,15 @@ Returns whether a provided rounding mode is considered rounding up for unsigned :average: pass:normal[xref:#SignedMath-average-int256-int256-[`++average++`]] :abs: pass:normal[xref:#SignedMath-abs-int256-[`++abs++`]] +:ternary-bool-int256-int256: pass:normal[xref:#SignedMath-ternary-bool-int256-int256-[`++ternary++`]] +:max-int256-int256: pass:normal[xref:#SignedMath-max-int256-int256-[`++max++`]] +:min-int256-int256: pass:normal[xref:#SignedMath-min-int256-int256-[`++min++`]] +:average-int256-int256: pass:normal[xref:#SignedMath-average-int256-int256-[`++average++`]] +:abs-int256: pass:normal[xref:#SignedMath-abs-int256-[`++abs++`]] + [.contract] [[SignedMath]] -=== `++SignedMath++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/math/SignedMath.sol[{github-icon},role=heading-link] +=== `++SignedMath++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/math/SignedMath.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -1257,9 +1406,75 @@ Returns the absolute unsigned value of a signed value. :toInt256: pass:normal[xref:#SafeCast-toInt256-uint256-[`++toInt256++`]] :toUint: pass:normal[xref:#SafeCast-toUint-bool-[`++toUint++`]] +:toUint248-uint256: pass:normal[xref:#SafeCast-toUint248-uint256-[`++toUint248++`]] +:toUint240-uint256: pass:normal[xref:#SafeCast-toUint240-uint256-[`++toUint240++`]] +:toUint232-uint256: pass:normal[xref:#SafeCast-toUint232-uint256-[`++toUint232++`]] +:toUint224-uint256: pass:normal[xref:#SafeCast-toUint224-uint256-[`++toUint224++`]] +:toUint216-uint256: pass:normal[xref:#SafeCast-toUint216-uint256-[`++toUint216++`]] +:toUint208-uint256: pass:normal[xref:#SafeCast-toUint208-uint256-[`++toUint208++`]] +:toUint200-uint256: pass:normal[xref:#SafeCast-toUint200-uint256-[`++toUint200++`]] +:toUint192-uint256: pass:normal[xref:#SafeCast-toUint192-uint256-[`++toUint192++`]] +:toUint184-uint256: pass:normal[xref:#SafeCast-toUint184-uint256-[`++toUint184++`]] +:toUint176-uint256: pass:normal[xref:#SafeCast-toUint176-uint256-[`++toUint176++`]] +:toUint168-uint256: pass:normal[xref:#SafeCast-toUint168-uint256-[`++toUint168++`]] +:toUint160-uint256: pass:normal[xref:#SafeCast-toUint160-uint256-[`++toUint160++`]] +:toUint152-uint256: pass:normal[xref:#SafeCast-toUint152-uint256-[`++toUint152++`]] +:toUint144-uint256: pass:normal[xref:#SafeCast-toUint144-uint256-[`++toUint144++`]] +:toUint136-uint256: pass:normal[xref:#SafeCast-toUint136-uint256-[`++toUint136++`]] +:toUint128-uint256: pass:normal[xref:#SafeCast-toUint128-uint256-[`++toUint128++`]] +:toUint120-uint256: pass:normal[xref:#SafeCast-toUint120-uint256-[`++toUint120++`]] +:toUint112-uint256: pass:normal[xref:#SafeCast-toUint112-uint256-[`++toUint112++`]] +:toUint104-uint256: pass:normal[xref:#SafeCast-toUint104-uint256-[`++toUint104++`]] +:toUint96-uint256: pass:normal[xref:#SafeCast-toUint96-uint256-[`++toUint96++`]] +:toUint88-uint256: pass:normal[xref:#SafeCast-toUint88-uint256-[`++toUint88++`]] +:toUint80-uint256: pass:normal[xref:#SafeCast-toUint80-uint256-[`++toUint80++`]] +:toUint72-uint256: pass:normal[xref:#SafeCast-toUint72-uint256-[`++toUint72++`]] +:toUint64-uint256: pass:normal[xref:#SafeCast-toUint64-uint256-[`++toUint64++`]] +:toUint56-uint256: pass:normal[xref:#SafeCast-toUint56-uint256-[`++toUint56++`]] +:toUint48-uint256: pass:normal[xref:#SafeCast-toUint48-uint256-[`++toUint48++`]] +:toUint40-uint256: pass:normal[xref:#SafeCast-toUint40-uint256-[`++toUint40++`]] +:toUint32-uint256: pass:normal[xref:#SafeCast-toUint32-uint256-[`++toUint32++`]] +:toUint24-uint256: pass:normal[xref:#SafeCast-toUint24-uint256-[`++toUint24++`]] +:toUint16-uint256: pass:normal[xref:#SafeCast-toUint16-uint256-[`++toUint16++`]] +:toUint8-uint256: pass:normal[xref:#SafeCast-toUint8-uint256-[`++toUint8++`]] +:toUint256-int256: pass:normal[xref:#SafeCast-toUint256-int256-[`++toUint256++`]] +:toInt248-int256: pass:normal[xref:#SafeCast-toInt248-int256-[`++toInt248++`]] +:toInt240-int256: pass:normal[xref:#SafeCast-toInt240-int256-[`++toInt240++`]] +:toInt232-int256: pass:normal[xref:#SafeCast-toInt232-int256-[`++toInt232++`]] +:toInt224-int256: pass:normal[xref:#SafeCast-toInt224-int256-[`++toInt224++`]] +:toInt216-int256: pass:normal[xref:#SafeCast-toInt216-int256-[`++toInt216++`]] +:toInt208-int256: pass:normal[xref:#SafeCast-toInt208-int256-[`++toInt208++`]] +:toInt200-int256: pass:normal[xref:#SafeCast-toInt200-int256-[`++toInt200++`]] +:toInt192-int256: pass:normal[xref:#SafeCast-toInt192-int256-[`++toInt192++`]] +:toInt184-int256: pass:normal[xref:#SafeCast-toInt184-int256-[`++toInt184++`]] +:toInt176-int256: pass:normal[xref:#SafeCast-toInt176-int256-[`++toInt176++`]] +:toInt168-int256: pass:normal[xref:#SafeCast-toInt168-int256-[`++toInt168++`]] +:toInt160-int256: pass:normal[xref:#SafeCast-toInt160-int256-[`++toInt160++`]] +:toInt152-int256: pass:normal[xref:#SafeCast-toInt152-int256-[`++toInt152++`]] +:toInt144-int256: pass:normal[xref:#SafeCast-toInt144-int256-[`++toInt144++`]] +:toInt136-int256: pass:normal[xref:#SafeCast-toInt136-int256-[`++toInt136++`]] +:toInt128-int256: pass:normal[xref:#SafeCast-toInt128-int256-[`++toInt128++`]] +:toInt120-int256: pass:normal[xref:#SafeCast-toInt120-int256-[`++toInt120++`]] +:toInt112-int256: pass:normal[xref:#SafeCast-toInt112-int256-[`++toInt112++`]] +:toInt104-int256: pass:normal[xref:#SafeCast-toInt104-int256-[`++toInt104++`]] +:toInt96-int256: pass:normal[xref:#SafeCast-toInt96-int256-[`++toInt96++`]] +:toInt88-int256: pass:normal[xref:#SafeCast-toInt88-int256-[`++toInt88++`]] +:toInt80-int256: pass:normal[xref:#SafeCast-toInt80-int256-[`++toInt80++`]] +:toInt72-int256: pass:normal[xref:#SafeCast-toInt72-int256-[`++toInt72++`]] +:toInt64-int256: pass:normal[xref:#SafeCast-toInt64-int256-[`++toInt64++`]] +:toInt56-int256: pass:normal[xref:#SafeCast-toInt56-int256-[`++toInt56++`]] +:toInt48-int256: pass:normal[xref:#SafeCast-toInt48-int256-[`++toInt48++`]] +:toInt40-int256: pass:normal[xref:#SafeCast-toInt40-int256-[`++toInt40++`]] +:toInt32-int256: pass:normal[xref:#SafeCast-toInt32-int256-[`++toInt32++`]] +:toInt24-int256: pass:normal[xref:#SafeCast-toInt24-int256-[`++toInt24++`]] +:toInt16-int256: pass:normal[xref:#SafeCast-toInt16-int256-[`++toInt16++`]] +:toInt8-int256: pass:normal[xref:#SafeCast-toInt8-int256-[`++toInt8++`]] +:toInt256-uint256: pass:normal[xref:#SafeCast-toInt256-uint256-[`++toInt256++`]] +:toUint-bool: pass:normal[xref:#SafeCast-toUint-bool-[`++toUint++`]] + [.contract] [[SafeCast]] -=== `++SafeCast++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/math/SafeCast.sol[{github-icon},role=heading-link] +=== `++SafeCast++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/math/SafeCast.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2258,9 +2473,16 @@ An uint value doesn't fit in an int of `bits` size. :tryRecover: pass:normal[xref:#ECDSA-tryRecover-bytes32-uint8-bytes32-bytes32-[`++tryRecover++`]] :recover: pass:normal[xref:#ECDSA-recover-bytes32-uint8-bytes32-bytes32-[`++recover++`]] +:tryRecover-bytes32-bytes: pass:normal[xref:#ECDSA-tryRecover-bytes32-bytes-[`++tryRecover++`]] +:recover-bytes32-bytes: pass:normal[xref:#ECDSA-recover-bytes32-bytes-[`++recover++`]] +:tryRecover-bytes32-bytes32-bytes32: pass:normal[xref:#ECDSA-tryRecover-bytes32-bytes32-bytes32-[`++tryRecover++`]] +:recover-bytes32-bytes32-bytes32: pass:normal[xref:#ECDSA-recover-bytes32-bytes32-bytes32-[`++recover++`]] +:tryRecover-bytes32-uint8-bytes32-bytes32: pass:normal[xref:#ECDSA-tryRecover-bytes32-uint8-bytes32-bytes32-[`++tryRecover++`]] +:recover-bytes32-uint8-bytes32-bytes32: pass:normal[xref:#ECDSA-recover-bytes32-uint8-bytes32-bytes32-[`++recover++`]] + [.contract] [[ECDSA]] -=== `++ECDSA++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/cryptography/ECDSA.sol[{github-icon},role=heading-link] +=== `++ECDSA++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/cryptography/ECDSA.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2393,9 +2615,15 @@ The signature has an S value that is in the upper half order. :recovery: pass:normal[xref:#P256-recovery-bytes32-uint8-bytes32-bytes32-[`++recovery++`]] :isValidPublicKey: pass:normal[xref:#P256-isValidPublicKey-bytes32-bytes32-[`++isValidPublicKey++`]] +:verify-bytes32-bytes32-bytes32-bytes32-bytes32: pass:normal[xref:#P256-verify-bytes32-bytes32-bytes32-bytes32-bytes32-[`++verify++`]] +:verifyNative-bytes32-bytes32-bytes32-bytes32-bytes32: pass:normal[xref:#P256-verifyNative-bytes32-bytes32-bytes32-bytes32-bytes32-[`++verifyNative++`]] +:verifySolidity-bytes32-bytes32-bytes32-bytes32-bytes32: pass:normal[xref:#P256-verifySolidity-bytes32-bytes32-bytes32-bytes32-bytes32-[`++verifySolidity++`]] +:recovery-bytes32-uint8-bytes32-bytes32: pass:normal[xref:#P256-recovery-bytes32-uint8-bytes32-bytes32-[`++recovery++`]] +:isValidPublicKey-bytes32-bytes32: pass:normal[xref:#P256-isValidPublicKey-bytes32-bytes32-[`++isValidPublicKey++`]] + [.contract] [[P256]] -=== `++P256++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/cryptography/P256.sol[{github-icon},role=heading-link] +=== `++P256++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/cryptography/P256.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2512,9 +2740,12 @@ B parameter of the weierstrass equation :pkcs1Sha256: pass:normal[xref:#RSA-pkcs1Sha256-bytes-bytes-bytes-bytes-[`++pkcs1Sha256++`]] :pkcs1Sha256: pass:normal[xref:#RSA-pkcs1Sha256-bytes32-bytes-bytes-bytes-[`++pkcs1Sha256++`]] +:pkcs1Sha256-bytes-bytes-bytes-bytes: pass:normal[xref:#RSA-pkcs1Sha256-bytes-bytes-bytes-bytes-[`++pkcs1Sha256++`]] +:pkcs1Sha256-bytes32-bytes-bytes-bytes: pass:normal[xref:#RSA-pkcs1Sha256-bytes32-bytes-bytes-bytes-[`++pkcs1Sha256++`]] + [.contract] [[RSA]] -=== `++RSA++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/cryptography/RSA.sol[{github-icon},role=heading-link] +=== `++RSA++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/cryptography/RSA.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2571,9 +2802,16 @@ using a low exponent out of security concerns. :_EIP712Name: pass:normal[xref:#EIP712-_EIP712Name--[`++_EIP712Name++`]] :_EIP712Version: pass:normal[xref:#EIP712-_EIP712Version--[`++_EIP712Version++`]] +:constructor-string-string: pass:normal[xref:#EIP712-constructor-string-string-[`++constructor++`]] +:_domainSeparatorV4-: pass:normal[xref:#EIP712-_domainSeparatorV4--[`++_domainSeparatorV4++`]] +:_hashTypedDataV4-bytes32: pass:normal[xref:#EIP712-_hashTypedDataV4-bytes32-[`++_hashTypedDataV4++`]] +:eip712Domain-: pass:normal[xref:#EIP712-eip712Domain--[`++eip712Domain++`]] +:_EIP712Name-: pass:normal[xref:#EIP712-_EIP712Name--[`++_EIP712Name++`]] +:_EIP712Version-: pass:normal[xref:#EIP712-_EIP712Version--[`++_EIP712Version++`]] + [.contract] [[EIP712]] -=== `++EIP712++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/cryptography/EIP712.sol[{github-icon},role=heading-link] +=== `++EIP712++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/cryptography/EIP712.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2669,7 +2907,8 @@ address signer = ECDSA.recover(digest, signature); [[EIP712-eip712Domain--]] ==== `[.contract-item-name]#++eip712Domain++#++() → bytes1 fields, string name, string version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] extensions++` [.item-kind]#public# -See {IERC-5267}. +returns the fields and values that describe the domain separator used by this contract for EIP-712 +signature. [.contract-item] [[EIP712-_EIP712Name--]] @@ -2692,11 +2931,18 @@ It only reads from storage if necessary (in case the value is too large to fit i :toEthSignedMessageHash: pass:normal[xref:#MessageHashUtils-toEthSignedMessageHash-bytes32-[`++toEthSignedMessageHash++`]] :toEthSignedMessageHash: pass:normal[xref:#MessageHashUtils-toEthSignedMessageHash-bytes-[`++toEthSignedMessageHash++`]] :toDataWithIntendedValidatorHash: pass:normal[xref:#MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes-[`++toDataWithIntendedValidatorHash++`]] +:toDataWithIntendedValidatorHash: pass:normal[xref:#MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes32-[`++toDataWithIntendedValidatorHash++`]] :toTypedDataHash: pass:normal[xref:#MessageHashUtils-toTypedDataHash-bytes32-bytes32-[`++toTypedDataHash++`]] +:toEthSignedMessageHash-bytes32: pass:normal[xref:#MessageHashUtils-toEthSignedMessageHash-bytes32-[`++toEthSignedMessageHash++`]] +:toEthSignedMessageHash-bytes: pass:normal[xref:#MessageHashUtils-toEthSignedMessageHash-bytes-[`++toEthSignedMessageHash++`]] +:toDataWithIntendedValidatorHash-address-bytes: pass:normal[xref:#MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes-[`++toDataWithIntendedValidatorHash++`]] +:toDataWithIntendedValidatorHash-address-bytes32: pass:normal[xref:#MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes32-[`++toDataWithIntendedValidatorHash++`]] +:toTypedDataHash-bytes32-bytes32: pass:normal[xref:#MessageHashUtils-toTypedDataHash-bytes32-bytes32-[`++toTypedDataHash++`]] + [.contract] [[MessageHashUtils]] -=== `++MessageHashUtils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/cryptography/MessageHashUtils.sol[{github-icon},role=heading-link] +=== `++MessageHashUtils++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/cryptography/MessageHashUtils.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2715,6 +2961,7 @@ specifications. * {xref-MessageHashUtils-toEthSignedMessageHash-bytes32-}[`++toEthSignedMessageHash(messageHash)++`] * {xref-MessageHashUtils-toEthSignedMessageHash-bytes-}[`++toEthSignedMessageHash(message)++`] * {xref-MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes-}[`++toDataWithIntendedValidatorHash(validator, data)++`] +* {xref-MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes32-}[`++toDataWithIntendedValidatorHash(validator, messageHash)++`] * {xref-MessageHashUtils-toTypedDataHash-bytes32-bytes32-}[`++toTypedDataHash(domainSeparator, structHash)++`] -- @@ -2728,7 +2975,7 @@ Returns the keccak256 digest of an ERC-191 signed data with version The digest is calculated by prefixing a bytes32 `messageHash` with `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the -hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. +hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method. NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with keccak256, although any bytes32 value can be safely used because the final digest will @@ -2745,7 +2992,7 @@ Returns the keccak256 digest of an ERC-191 signed data with version The digest is calculated by prefixing an arbitrary `message` with `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the -hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. +hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method. See {ECDSA-recover}. @@ -2761,6 +3008,12 @@ The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and See {ECDSA-recover}. +[.contract-item] +[[MessageHashUtils-toDataWithIntendedValidatorHash-address-bytes32-]] +==== `[.contract-item-name]#++toDataWithIntendedValidatorHash++#++(address validator, bytes32 messageHash) → bytes32 digest++` [.item-kind]#internal# + +Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32. + [.contract-item] [[MessageHashUtils-toTypedDataHash-bytes32-bytes32-]] ==== `[.contract-item-name]#++toTypedDataHash++#++(bytes32 domainSeparator, bytes32 structHash) → bytes32 digest++` [.item-kind]#internal# @@ -2776,9 +3029,12 @@ See {ECDSA-recover}. :isValidSignatureNow: pass:normal[xref:#SignatureChecker-isValidSignatureNow-address-bytes32-bytes-[`++isValidSignatureNow++`]] :isValidERC1271SignatureNow: pass:normal[xref:#SignatureChecker-isValidERC1271SignatureNow-address-bytes32-bytes-[`++isValidERC1271SignatureNow++`]] +:isValidSignatureNow-address-bytes32-bytes: pass:normal[xref:#SignatureChecker-isValidSignatureNow-address-bytes32-bytes-[`++isValidSignatureNow++`]] +:isValidERC1271SignatureNow-address-bytes32-bytes: pass:normal[xref:#SignatureChecker-isValidERC1271SignatureNow-address-bytes32-bytes-[`++isValidERC1271SignatureNow++`]] + [.contract] [[SignatureChecker]] -=== `++SignatureChecker++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/cryptography/SignatureChecker.sol[{github-icon},role=heading-link] +=== `++SignatureChecker++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/cryptography/SignatureChecker.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2818,10 +3074,14 @@ NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcom change through time. It could return true at block N and false at block N+1 (or the opposite). :commutativeKeccak256: pass:normal[xref:#Hashes-commutativeKeccak256-bytes32-bytes32-[`++commutativeKeccak256++`]] +:efficientKeccak256: pass:normal[xref:#Hashes-efficientKeccak256-bytes32-bytes32-[`++efficientKeccak256++`]] + +:commutativeKeccak256-bytes32-bytes32: pass:normal[xref:#Hashes-commutativeKeccak256-bytes32-bytes32-[`++commutativeKeccak256++`]] +:efficientKeccak256-bytes32-bytes32: pass:normal[xref:#Hashes-efficientKeccak256-bytes32-bytes32-[`++efficientKeccak256++`]] [.contract] [[Hashes]] -=== `++Hashes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/cryptography/Hashes.sol[{github-icon},role=heading-link] +=== `++Hashes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/cryptography/Hashes.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -2836,6 +3096,7 @@ _Available since v5.1._ .Functions -- * {xref-Hashes-commutativeKeccak256-bytes32-bytes32-}[`++commutativeKeccak256(a, b)++`] +* {xref-Hashes-efficientKeccak256-bytes32-bytes32-}[`++efficientKeccak256(a, b)++`] -- @@ -2847,6 +3108,12 @@ Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when wor NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. +[.contract-item] +[[Hashes-efficientKeccak256-bytes32-bytes32-]] +==== `[.contract-item-name]#++efficientKeccak256++#++(bytes32 a, bytes32 b) → bytes32 value++` [.item-kind]#internal# + +Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory. + :MerkleProofInvalidMultiproof: pass:normal[xref:#MerkleProof-MerkleProofInvalidMultiproof--[`++MerkleProofInvalidMultiproof++`]] :verify: pass:normal[xref:#MerkleProof-verify-bytes32---bytes32-bytes32-[`++verify++`]] :processProof: pass:normal[xref:#MerkleProof-processProof-bytes32---bytes32-[`++processProof++`]] @@ -2865,9 +3132,26 @@ NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppeli :multiProofVerifyCalldata: pass:normal[xref:#MerkleProof-multiProofVerifyCalldata-bytes32---bool---bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32--[`++multiProofVerifyCalldata++`]] :processMultiProofCalldata: pass:normal[xref:#MerkleProof-processMultiProofCalldata-bytes32---bool---bytes32---function--bytes32-bytes32--view-returns--bytes32--[`++processMultiProofCalldata++`]] +:verify-bytes32---bytes32-bytes32: pass:normal[xref:#MerkleProof-verify-bytes32---bytes32-bytes32-[`++verify++`]] +:processProof-bytes32---bytes32: pass:normal[xref:#MerkleProof-processProof-bytes32---bytes32-[`++processProof++`]] +:verify-bytes32---bytes32-bytes32-function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleProof-verify-bytes32---bytes32-bytes32-function--bytes32-bytes32--view-returns--bytes32--[`++verify++`]] +:processProof-bytes32---bytes32-function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleProof-processProof-bytes32---bytes32-function--bytes32-bytes32--view-returns--bytes32--[`++processProof++`]] +:verifyCalldata-bytes32---bytes32-bytes32: pass:normal[xref:#MerkleProof-verifyCalldata-bytes32---bytes32-bytes32-[`++verifyCalldata++`]] +:processProofCalldata-bytes32---bytes32: pass:normal[xref:#MerkleProof-processProofCalldata-bytes32---bytes32-[`++processProofCalldata++`]] +:verifyCalldata-bytes32---bytes32-bytes32-function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleProof-verifyCalldata-bytes32---bytes32-bytes32-function--bytes32-bytes32--view-returns--bytes32--[`++verifyCalldata++`]] +:processProofCalldata-bytes32---bytes32-function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleProof-processProofCalldata-bytes32---bytes32-function--bytes32-bytes32--view-returns--bytes32--[`++processProofCalldata++`]] +:multiProofVerify-bytes32---bool---bytes32-bytes32--: pass:normal[xref:#MerkleProof-multiProofVerify-bytes32---bool---bytes32-bytes32---[`++multiProofVerify++`]] +:processMultiProof-bytes32---bool---bytes32--: pass:normal[xref:#MerkleProof-processMultiProof-bytes32---bool---bytes32---[`++processMultiProof++`]] +:multiProofVerify-bytes32---bool---bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleProof-multiProofVerify-bytes32---bool---bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32--[`++multiProofVerify++`]] +:processMultiProof-bytes32---bool---bytes32---function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleProof-processMultiProof-bytes32---bool---bytes32---function--bytes32-bytes32--view-returns--bytes32--[`++processMultiProof++`]] +:multiProofVerifyCalldata-bytes32---bool---bytes32-bytes32--: pass:normal[xref:#MerkleProof-multiProofVerifyCalldata-bytes32---bool---bytes32-bytes32---[`++multiProofVerifyCalldata++`]] +:processMultiProofCalldata-bytes32---bool---bytes32--: pass:normal[xref:#MerkleProof-processMultiProofCalldata-bytes32---bool---bytes32---[`++processMultiProofCalldata++`]] +:multiProofVerifyCalldata-bytes32---bool---bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleProof-multiProofVerifyCalldata-bytes32---bool---bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32--[`++multiProofVerifyCalldata++`]] +:processMultiProofCalldata-bytes32---bool---bytes32---function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleProof-processMultiProofCalldata-bytes32---bool---bytes32---function--bytes32-bytes32--view-returns--bytes32--[`++processMultiProofCalldata++`]] + [.contract] [[MerkleProof]] -=== `++MerkleProof++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/cryptography/MerkleProof.sol[{github-icon},role=heading-link] +=== `++MerkleProof++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/cryptography/MerkleProof.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3157,9 +3441,12 @@ The multiproof provided is not valid. :nonReentrant: pass:normal[xref:#ReentrancyGuard-nonReentrant--[`++nonReentrant++`]] :_reentrancyGuardEntered: pass:normal[xref:#ReentrancyGuard-_reentrancyGuardEntered--[`++_reentrancyGuardEntered++`]] +:constructor-: pass:normal[xref:#ReentrancyGuard-constructor--[`++constructor++`]] +:_reentrancyGuardEntered-: pass:normal[xref:#ReentrancyGuard-_reentrancyGuardEntered--[`++_reentrancyGuardEntered++`]] + [.contract] [[ReentrancyGuard]] -=== `++ReentrancyGuard++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/ReentrancyGuard.sol[{github-icon},role=heading-link] +=== `++ReentrancyGuard++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/ReentrancyGuard.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3236,9 +3523,11 @@ Unauthorized reentrant call. :nonReentrant: pass:normal[xref:#ReentrancyGuardTransient-nonReentrant--[`++nonReentrant++`]] :_reentrancyGuardEntered: pass:normal[xref:#ReentrancyGuardTransient-_reentrancyGuardEntered--[`++_reentrancyGuardEntered++`]] +:_reentrancyGuardEntered-: pass:normal[xref:#ReentrancyGuardTransient-_reentrancyGuardEntered--[`++_reentrancyGuardEntered++`]] + [.contract] [[ReentrancyGuardTransient]] -=== `++ReentrancyGuardTransient++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/ReentrancyGuardTransient.sol[{github-icon},role=heading-link] +=== `++ReentrancyGuardTransient++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/ReentrancyGuardTransient.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3298,7 +3587,6 @@ Unauthorized reentrant call. :Unpaused: pass:normal[xref:#Pausable-Unpaused-address-[`++Unpaused++`]] :EnforcedPause: pass:normal[xref:#Pausable-EnforcedPause--[`++EnforcedPause++`]] :ExpectedPause: pass:normal[xref:#Pausable-ExpectedPause--[`++ExpectedPause++`]] -:constructor: pass:normal[xref:#Pausable-constructor--[`++constructor++`]] :whenNotPaused: pass:normal[xref:#Pausable-whenNotPaused--[`++whenNotPaused++`]] :whenPaused: pass:normal[xref:#Pausable-whenPaused--[`++whenPaused++`]] :paused: pass:normal[xref:#Pausable-paused--[`++paused++`]] @@ -3307,9 +3595,15 @@ Unauthorized reentrant call. :_pause: pass:normal[xref:#Pausable-_pause--[`++_pause++`]] :_unpause: pass:normal[xref:#Pausable-_unpause--[`++_unpause++`]] +:paused-: pass:normal[xref:#Pausable-paused--[`++paused++`]] +:_requireNotPaused-: pass:normal[xref:#Pausable-_requireNotPaused--[`++_requireNotPaused++`]] +:_requirePaused-: pass:normal[xref:#Pausable-_requirePaused--[`++_requirePaused++`]] +:_pause-: pass:normal[xref:#Pausable-_pause--[`++_pause++`]] +:_unpause-: pass:normal[xref:#Pausable-_unpause--[`++_unpause++`]] + [.contract] [[Pausable]] -=== `++Pausable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Pausable.sol[{github-icon},role=heading-link] +=== `++Pausable++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Pausable.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3334,7 +3628,6 @@ simply including this module, only once the modifiers are put in place. [.contract-index] .Functions -- -* {xref-Pausable-constructor--}[`++constructor()++`] * {xref-Pausable-paused--}[`++paused()++`] * {xref-Pausable-_requireNotPaused--}[`++_requireNotPaused()++`] * {xref-Pausable-_requirePaused--}[`++_requirePaused()++`] @@ -3379,12 +3672,6 @@ Requirements: - The contract must be paused. -[.contract-item] -[[Pausable-constructor--]] -==== `[.contract-item-name]#++constructor++#++()++` [.item-kind]#internal# - -Initializes the contract in unpaused state. - [.contract-item] [[Pausable-paused--]] ==== `[.contract-item-name]#++paused++#++() → bool++` [.item-kind]#public# @@ -3452,9 +3739,13 @@ The operation failed because the contract is not paused. :_useNonce: pass:normal[xref:#Nonces-_useNonce-address-[`++_useNonce++`]] :_useCheckedNonce: pass:normal[xref:#Nonces-_useCheckedNonce-address-uint256-[`++_useCheckedNonce++`]] +:nonces-address: pass:normal[xref:#Nonces-nonces-address-[`++nonces++`]] +:_useNonce-address: pass:normal[xref:#Nonces-_useNonce-address-[`++_useNonce++`]] +:_useCheckedNonce-address-uint256: pass:normal[xref:#Nonces-_useCheckedNonce-address-uint256-[`++_useCheckedNonce++`]] + [.contract] [[Nonces]] -=== `++Nonces++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Nonces.sol[{github-icon},role=heading-link] +=== `++Nonces++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Nonces.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3510,9 +3801,14 @@ The nonce used for an `account` is not the expected current nonce. :_useCheckedNonce: pass:normal[xref:#NoncesKeyed-_useCheckedNonce-address-uint256-[`++_useCheckedNonce++`]] :_useCheckedNonce: pass:normal[xref:#NoncesKeyed-_useCheckedNonce-address-uint192-uint64-[`++_useCheckedNonce++`]] +:nonces-address-uint192: pass:normal[xref:#NoncesKeyed-nonces-address-uint192-[`++nonces++`]] +:_useNonce-address-uint192: pass:normal[xref:#NoncesKeyed-_useNonce-address-uint192-[`++_useNonce++`]] +:_useCheckedNonce-address-uint256: pass:normal[xref:#NoncesKeyed-_useCheckedNonce-address-uint256-[`++_useCheckedNonce++`]] +:_useCheckedNonce-address-uint192-uint64: pass:normal[xref:#NoncesKeyed-_useCheckedNonce-address-uint192-uint64-[`++_useCheckedNonce++`]] + [.contract] [[NoncesKeyed]] -=== `++NoncesKeyed++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/NoncesKeyed.sol[{github-icon},role=heading-link] +=== `++NoncesKeyed++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/NoncesKeyed.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3593,9 +3889,11 @@ Ethereum contracts have no native concept of an interface, so applications must :supportsInterface: pass:normal[xref:#IERC165-supportsInterface-bytes4-[`++supportsInterface++`]] +:supportsInterface-bytes4: pass:normal[xref:#IERC165-supportsInterface-bytes4-[`++supportsInterface++`]] + [.contract] [[IERC165]] -=== `++IERC165++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/introspection/IERC165.sol[{github-icon},role=heading-link] +=== `++IERC165++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/introspection/IERC165.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3630,9 +3928,11 @@ This function call must use less than 30 000 gas. :supportsInterface: pass:normal[xref:#ERC165-supportsInterface-bytes4-[`++supportsInterface++`]] +:supportsInterface-bytes4: pass:normal[xref:#ERC165-supportsInterface-bytes4-[`++supportsInterface++`]] + [.contract] [[ERC165]] -=== `++ERC165++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/introspection/ERC165.sol[{github-icon},role=heading-link] +=== `++ERC165++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/introspection/ERC165.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3672,9 +3972,15 @@ See {IERC165-supportsInterface}. :supportsAllInterfaces: pass:normal[xref:#ERC165Checker-supportsAllInterfaces-address-bytes4---[`++supportsAllInterfaces++`]] :supportsERC165InterfaceUnchecked: pass:normal[xref:#ERC165Checker-supportsERC165InterfaceUnchecked-address-bytes4-[`++supportsERC165InterfaceUnchecked++`]] +:supportsERC165-address: pass:normal[xref:#ERC165Checker-supportsERC165-address-[`++supportsERC165++`]] +:supportsInterface-address-bytes4: pass:normal[xref:#ERC165Checker-supportsInterface-address-bytes4-[`++supportsInterface++`]] +:getSupportedInterfaces-address-bytes4--: pass:normal[xref:#ERC165Checker-getSupportedInterfaces-address-bytes4---[`++getSupportedInterfaces++`]] +:supportsAllInterfaces-address-bytes4--: pass:normal[xref:#ERC165Checker-supportsAllInterfaces-address-bytes4---[`++supportsAllInterfaces++`]] +:supportsERC165InterfaceUnchecked-address-bytes4: pass:normal[xref:#ERC165Checker-supportsERC165InterfaceUnchecked-address-bytes4-[`++supportsERC165InterfaceUnchecked++`]] + [.contract] [[ERC165Checker]] -=== `++ERC165Checker++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/introspection/ERC165Checker.sol[{github-icon},role=heading-link] +=== `++ERC165Checker++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/introspection/ERC165Checker.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3757,9 +4063,14 @@ Interface identification is specified in ERC-165. :set: pass:normal[xref:#BitMaps-set-struct-BitMaps-BitMap-uint256-[`++set++`]] :unset: pass:normal[xref:#BitMaps-unset-struct-BitMaps-BitMap-uint256-[`++unset++`]] +:get-struct-BitMaps-BitMap-uint256: pass:normal[xref:#BitMaps-get-struct-BitMaps-BitMap-uint256-[`++get++`]] +:setTo-struct-BitMaps-BitMap-uint256-bool: pass:normal[xref:#BitMaps-setTo-struct-BitMaps-BitMap-uint256-bool-[`++setTo++`]] +:set-struct-BitMaps-BitMap-uint256: pass:normal[xref:#BitMaps-set-struct-BitMaps-BitMap-uint256-[`++set++`]] +:unset-struct-BitMaps-BitMap-uint256: pass:normal[xref:#BitMaps-unset-struct-BitMaps-BitMap-uint256-[`++unset++`]] + [.contract] [[BitMaps]] -=== `++BitMaps++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/structs/BitMaps.sol[{github-icon},role=heading-link] +=== `++BitMaps++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/structs/BitMaps.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3816,6 +4127,7 @@ Unsets the bit at `index`. :Bytes32ToBytes32Map: pass:normal[xref:#EnumerableMap-Bytes32ToBytes32Map[`++Bytes32ToBytes32Map++`]] :set: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-bytes32-[`++set++`]] :remove: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-Bytes32ToBytes32Map-[`++clear++`]] :contains: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-[`++contains++`]] :length: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-Bytes32ToBytes32Map-[`++length++`]] :at: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-Bytes32ToBytes32Map-uint256-[`++at++`]] @@ -3825,6 +4137,7 @@ Unsets the bit at `index`. :UintToUintMap: pass:normal[xref:#EnumerableMap-UintToUintMap[`++UintToUintMap++`]] :set: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-UintToUintMap-uint256-uint256-[`++set++`]] :remove: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-UintToUintMap-uint256-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-UintToUintMap-[`++clear++`]] :contains: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-UintToUintMap-uint256-[`++contains++`]] :length: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-UintToUintMap-[`++length++`]] :at: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-UintToUintMap-uint256-[`++at++`]] @@ -3834,6 +4147,7 @@ Unsets the bit at `index`. :UintToAddressMap: pass:normal[xref:#EnumerableMap-UintToAddressMap[`++UintToAddressMap++`]] :set: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-UintToAddressMap-uint256-address-[`++set++`]] :remove: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-UintToAddressMap-uint256-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-UintToAddressMap-[`++clear++`]] :contains: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-UintToAddressMap-uint256-[`++contains++`]] :length: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-UintToAddressMap-[`++length++`]] :at: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-UintToAddressMap-uint256-[`++at++`]] @@ -3843,6 +4157,7 @@ Unsets the bit at `index`. :UintToBytes32Map: pass:normal[xref:#EnumerableMap-UintToBytes32Map[`++UintToBytes32Map++`]] :set: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-UintToBytes32Map-uint256-bytes32-[`++set++`]] :remove: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-UintToBytes32Map-uint256-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-UintToBytes32Map-[`++clear++`]] :contains: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-UintToBytes32Map-uint256-[`++contains++`]] :length: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-UintToBytes32Map-[`++length++`]] :at: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-UintToBytes32Map-uint256-[`++at++`]] @@ -3852,6 +4167,7 @@ Unsets the bit at `index`. :AddressToUintMap: pass:normal[xref:#EnumerableMap-AddressToUintMap[`++AddressToUintMap++`]] :set: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-AddressToUintMap-address-uint256-[`++set++`]] :remove: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-AddressToUintMap-address-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-AddressToUintMap-[`++clear++`]] :contains: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-AddressToUintMap-address-[`++contains++`]] :length: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-AddressToUintMap-[`++length++`]] :at: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-AddressToUintMap-uint256-[`++at++`]] @@ -3861,6 +4177,7 @@ Unsets the bit at `index`. :AddressToAddressMap: pass:normal[xref:#EnumerableMap-AddressToAddressMap[`++AddressToAddressMap++`]] :set: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-AddressToAddressMap-address-address-[`++set++`]] :remove: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-AddressToAddressMap-address-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-AddressToAddressMap-[`++clear++`]] :contains: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-AddressToAddressMap-address-[`++contains++`]] :length: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-AddressToAddressMap-[`++length++`]] :at: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-AddressToAddressMap-uint256-[`++at++`]] @@ -3870,6 +4187,7 @@ Unsets the bit at `index`. :AddressToBytes32Map: pass:normal[xref:#EnumerableMap-AddressToBytes32Map[`++AddressToBytes32Map++`]] :set: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-AddressToBytes32Map-address-bytes32-[`++set++`]] :remove: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-AddressToBytes32Map-address-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-AddressToBytes32Map-[`++clear++`]] :contains: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-AddressToBytes32Map-address-[`++contains++`]] :length: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-AddressToBytes32Map-[`++length++`]] :at: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-AddressToBytes32Map-uint256-[`++at++`]] @@ -3879,6 +4197,7 @@ Unsets the bit at `index`. :Bytes32ToUintMap: pass:normal[xref:#EnumerableMap-Bytes32ToUintMap[`++Bytes32ToUintMap++`]] :set: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-Bytes32ToUintMap-bytes32-uint256-[`++set++`]] :remove: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-Bytes32ToUintMap-bytes32-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-Bytes32ToUintMap-[`++clear++`]] :contains: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-Bytes32ToUintMap-bytes32-[`++contains++`]] :length: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-Bytes32ToUintMap-[`++length++`]] :at: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-Bytes32ToUintMap-uint256-[`++at++`]] @@ -3888,6 +4207,7 @@ Unsets the bit at `index`. :Bytes32ToAddressMap: pass:normal[xref:#EnumerableMap-Bytes32ToAddressMap[`++Bytes32ToAddressMap++`]] :set: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-address-[`++set++`]] :remove: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-Bytes32ToAddressMap-[`++clear++`]] :contains: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-[`++contains++`]] :length: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-Bytes32ToAddressMap-[`++length++`]] :at: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-Bytes32ToAddressMap-uint256-[`++at++`]] @@ -3895,9 +4215,91 @@ Unsets the bit at `index`. :get: pass:normal[xref:#EnumerableMap-get-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-[`++get++`]] :keys: pass:normal[xref:#EnumerableMap-keys-struct-EnumerableMap-Bytes32ToAddressMap-[`++keys++`]] +:set-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-bytes32: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-bytes32-[`++set++`]] +:remove-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-[`++remove++`]] +:clear-struct-EnumerableMap-Bytes32ToBytes32Map: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-Bytes32ToBytes32Map-[`++clear++`]] +:contains-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-[`++contains++`]] +:length-struct-EnumerableMap-Bytes32ToBytes32Map: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-Bytes32ToBytes32Map-[`++length++`]] +:at-struct-EnumerableMap-Bytes32ToBytes32Map-uint256: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-Bytes32ToBytes32Map-uint256-[`++at++`]] +:tryGet-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32: pass:normal[xref:#EnumerableMap-tryGet-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-[`++tryGet++`]] +:get-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32: pass:normal[xref:#EnumerableMap-get-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-[`++get++`]] +:keys-struct-EnumerableMap-Bytes32ToBytes32Map: pass:normal[xref:#EnumerableMap-keys-struct-EnumerableMap-Bytes32ToBytes32Map-[`++keys++`]] +:set-struct-EnumerableMap-UintToUintMap-uint256-uint256: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-UintToUintMap-uint256-uint256-[`++set++`]] +:remove-struct-EnumerableMap-UintToUintMap-uint256: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-UintToUintMap-uint256-[`++remove++`]] +:clear-struct-EnumerableMap-UintToUintMap: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-UintToUintMap-[`++clear++`]] +:contains-struct-EnumerableMap-UintToUintMap-uint256: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-UintToUintMap-uint256-[`++contains++`]] +:length-struct-EnumerableMap-UintToUintMap: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-UintToUintMap-[`++length++`]] +:at-struct-EnumerableMap-UintToUintMap-uint256: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-UintToUintMap-uint256-[`++at++`]] +:tryGet-struct-EnumerableMap-UintToUintMap-uint256: pass:normal[xref:#EnumerableMap-tryGet-struct-EnumerableMap-UintToUintMap-uint256-[`++tryGet++`]] +:get-struct-EnumerableMap-UintToUintMap-uint256: pass:normal[xref:#EnumerableMap-get-struct-EnumerableMap-UintToUintMap-uint256-[`++get++`]] +:keys-struct-EnumerableMap-UintToUintMap: pass:normal[xref:#EnumerableMap-keys-struct-EnumerableMap-UintToUintMap-[`++keys++`]] +:set-struct-EnumerableMap-UintToAddressMap-uint256-address: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-UintToAddressMap-uint256-address-[`++set++`]] +:remove-struct-EnumerableMap-UintToAddressMap-uint256: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-UintToAddressMap-uint256-[`++remove++`]] +:clear-struct-EnumerableMap-UintToAddressMap: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-UintToAddressMap-[`++clear++`]] +:contains-struct-EnumerableMap-UintToAddressMap-uint256: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-UintToAddressMap-uint256-[`++contains++`]] +:length-struct-EnumerableMap-UintToAddressMap: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-UintToAddressMap-[`++length++`]] +:at-struct-EnumerableMap-UintToAddressMap-uint256: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-UintToAddressMap-uint256-[`++at++`]] +:tryGet-struct-EnumerableMap-UintToAddressMap-uint256: pass:normal[xref:#EnumerableMap-tryGet-struct-EnumerableMap-UintToAddressMap-uint256-[`++tryGet++`]] +:get-struct-EnumerableMap-UintToAddressMap-uint256: pass:normal[xref:#EnumerableMap-get-struct-EnumerableMap-UintToAddressMap-uint256-[`++get++`]] +:keys-struct-EnumerableMap-UintToAddressMap: pass:normal[xref:#EnumerableMap-keys-struct-EnumerableMap-UintToAddressMap-[`++keys++`]] +:set-struct-EnumerableMap-UintToBytes32Map-uint256-bytes32: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-UintToBytes32Map-uint256-bytes32-[`++set++`]] +:remove-struct-EnumerableMap-UintToBytes32Map-uint256: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-UintToBytes32Map-uint256-[`++remove++`]] +:clear-struct-EnumerableMap-UintToBytes32Map: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-UintToBytes32Map-[`++clear++`]] +:contains-struct-EnumerableMap-UintToBytes32Map-uint256: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-UintToBytes32Map-uint256-[`++contains++`]] +:length-struct-EnumerableMap-UintToBytes32Map: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-UintToBytes32Map-[`++length++`]] +:at-struct-EnumerableMap-UintToBytes32Map-uint256: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-UintToBytes32Map-uint256-[`++at++`]] +:tryGet-struct-EnumerableMap-UintToBytes32Map-uint256: pass:normal[xref:#EnumerableMap-tryGet-struct-EnumerableMap-UintToBytes32Map-uint256-[`++tryGet++`]] +:get-struct-EnumerableMap-UintToBytes32Map-uint256: pass:normal[xref:#EnumerableMap-get-struct-EnumerableMap-UintToBytes32Map-uint256-[`++get++`]] +:keys-struct-EnumerableMap-UintToBytes32Map: pass:normal[xref:#EnumerableMap-keys-struct-EnumerableMap-UintToBytes32Map-[`++keys++`]] +:set-struct-EnumerableMap-AddressToUintMap-address-uint256: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-AddressToUintMap-address-uint256-[`++set++`]] +:remove-struct-EnumerableMap-AddressToUintMap-address: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-AddressToUintMap-address-[`++remove++`]] +:clear-struct-EnumerableMap-AddressToUintMap: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-AddressToUintMap-[`++clear++`]] +:contains-struct-EnumerableMap-AddressToUintMap-address: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-AddressToUintMap-address-[`++contains++`]] +:length-struct-EnumerableMap-AddressToUintMap: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-AddressToUintMap-[`++length++`]] +:at-struct-EnumerableMap-AddressToUintMap-uint256: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-AddressToUintMap-uint256-[`++at++`]] +:tryGet-struct-EnumerableMap-AddressToUintMap-address: pass:normal[xref:#EnumerableMap-tryGet-struct-EnumerableMap-AddressToUintMap-address-[`++tryGet++`]] +:get-struct-EnumerableMap-AddressToUintMap-address: pass:normal[xref:#EnumerableMap-get-struct-EnumerableMap-AddressToUintMap-address-[`++get++`]] +:keys-struct-EnumerableMap-AddressToUintMap: pass:normal[xref:#EnumerableMap-keys-struct-EnumerableMap-AddressToUintMap-[`++keys++`]] +:set-struct-EnumerableMap-AddressToAddressMap-address-address: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-AddressToAddressMap-address-address-[`++set++`]] +:remove-struct-EnumerableMap-AddressToAddressMap-address: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-AddressToAddressMap-address-[`++remove++`]] +:clear-struct-EnumerableMap-AddressToAddressMap: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-AddressToAddressMap-[`++clear++`]] +:contains-struct-EnumerableMap-AddressToAddressMap-address: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-AddressToAddressMap-address-[`++contains++`]] +:length-struct-EnumerableMap-AddressToAddressMap: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-AddressToAddressMap-[`++length++`]] +:at-struct-EnumerableMap-AddressToAddressMap-uint256: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-AddressToAddressMap-uint256-[`++at++`]] +:tryGet-struct-EnumerableMap-AddressToAddressMap-address: pass:normal[xref:#EnumerableMap-tryGet-struct-EnumerableMap-AddressToAddressMap-address-[`++tryGet++`]] +:get-struct-EnumerableMap-AddressToAddressMap-address: pass:normal[xref:#EnumerableMap-get-struct-EnumerableMap-AddressToAddressMap-address-[`++get++`]] +:keys-struct-EnumerableMap-AddressToAddressMap: pass:normal[xref:#EnumerableMap-keys-struct-EnumerableMap-AddressToAddressMap-[`++keys++`]] +:set-struct-EnumerableMap-AddressToBytes32Map-address-bytes32: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-AddressToBytes32Map-address-bytes32-[`++set++`]] +:remove-struct-EnumerableMap-AddressToBytes32Map-address: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-AddressToBytes32Map-address-[`++remove++`]] +:clear-struct-EnumerableMap-AddressToBytes32Map: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-AddressToBytes32Map-[`++clear++`]] +:contains-struct-EnumerableMap-AddressToBytes32Map-address: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-AddressToBytes32Map-address-[`++contains++`]] +:length-struct-EnumerableMap-AddressToBytes32Map: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-AddressToBytes32Map-[`++length++`]] +:at-struct-EnumerableMap-AddressToBytes32Map-uint256: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-AddressToBytes32Map-uint256-[`++at++`]] +:tryGet-struct-EnumerableMap-AddressToBytes32Map-address: pass:normal[xref:#EnumerableMap-tryGet-struct-EnumerableMap-AddressToBytes32Map-address-[`++tryGet++`]] +:get-struct-EnumerableMap-AddressToBytes32Map-address: pass:normal[xref:#EnumerableMap-get-struct-EnumerableMap-AddressToBytes32Map-address-[`++get++`]] +:keys-struct-EnumerableMap-AddressToBytes32Map: pass:normal[xref:#EnumerableMap-keys-struct-EnumerableMap-AddressToBytes32Map-[`++keys++`]] +:set-struct-EnumerableMap-Bytes32ToUintMap-bytes32-uint256: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-Bytes32ToUintMap-bytes32-uint256-[`++set++`]] +:remove-struct-EnumerableMap-Bytes32ToUintMap-bytes32: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-Bytes32ToUintMap-bytes32-[`++remove++`]] +:clear-struct-EnumerableMap-Bytes32ToUintMap: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-Bytes32ToUintMap-[`++clear++`]] +:contains-struct-EnumerableMap-Bytes32ToUintMap-bytes32: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-Bytes32ToUintMap-bytes32-[`++contains++`]] +:length-struct-EnumerableMap-Bytes32ToUintMap: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-Bytes32ToUintMap-[`++length++`]] +:at-struct-EnumerableMap-Bytes32ToUintMap-uint256: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-Bytes32ToUintMap-uint256-[`++at++`]] +:tryGet-struct-EnumerableMap-Bytes32ToUintMap-bytes32: pass:normal[xref:#EnumerableMap-tryGet-struct-EnumerableMap-Bytes32ToUintMap-bytes32-[`++tryGet++`]] +:get-struct-EnumerableMap-Bytes32ToUintMap-bytes32: pass:normal[xref:#EnumerableMap-get-struct-EnumerableMap-Bytes32ToUintMap-bytes32-[`++get++`]] +:keys-struct-EnumerableMap-Bytes32ToUintMap: pass:normal[xref:#EnumerableMap-keys-struct-EnumerableMap-Bytes32ToUintMap-[`++keys++`]] +:set-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-address: pass:normal[xref:#EnumerableMap-set-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-address-[`++set++`]] +:remove-struct-EnumerableMap-Bytes32ToAddressMap-bytes32: pass:normal[xref:#EnumerableMap-remove-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-[`++remove++`]] +:clear-struct-EnumerableMap-Bytes32ToAddressMap: pass:normal[xref:#EnumerableMap-clear-struct-EnumerableMap-Bytes32ToAddressMap-[`++clear++`]] +:contains-struct-EnumerableMap-Bytes32ToAddressMap-bytes32: pass:normal[xref:#EnumerableMap-contains-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-[`++contains++`]] +:length-struct-EnumerableMap-Bytes32ToAddressMap: pass:normal[xref:#EnumerableMap-length-struct-EnumerableMap-Bytes32ToAddressMap-[`++length++`]] +:at-struct-EnumerableMap-Bytes32ToAddressMap-uint256: pass:normal[xref:#EnumerableMap-at-struct-EnumerableMap-Bytes32ToAddressMap-uint256-[`++at++`]] +:tryGet-struct-EnumerableMap-Bytes32ToAddressMap-bytes32: pass:normal[xref:#EnumerableMap-tryGet-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-[`++tryGet++`]] +:get-struct-EnumerableMap-Bytes32ToAddressMap-bytes32: pass:normal[xref:#EnumerableMap-get-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-[`++get++`]] +:keys-struct-EnumerableMap-Bytes32ToAddressMap: pass:normal[xref:#EnumerableMap-keys-struct-EnumerableMap-Bytes32ToAddressMap-[`++keys++`]] + [.contract] [[EnumerableMap]] -=== `++EnumerableMap++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/structs/EnumerableMap.sol[{github-icon},role=heading-link] +=== `++EnumerableMap++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/structs/EnumerableMap.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -3913,6 +4315,7 @@ Maps have the following properties: - Entries are added, removed, and checked for existence in constant time (O(1)). - Entries are enumerated in O(n). No guarantees are made on the ordering. +- Map can be cleared (all entries removed) in O(n). ```solidity contract Example { @@ -3951,6 +4354,7 @@ array of EnumerableMap. -- * {xref-EnumerableMap-set-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-bytes32-}[`++set(map, key, value)++`] * {xref-EnumerableMap-remove-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-}[`++remove(map, key)++`] +* {xref-EnumerableMap-clear-struct-EnumerableMap-Bytes32ToBytes32Map-}[`++clear(map)++`] * {xref-EnumerableMap-contains-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-}[`++contains(map, key)++`] * {xref-EnumerableMap-length-struct-EnumerableMap-Bytes32ToBytes32Map-}[`++length(map)++`] * {xref-EnumerableMap-at-struct-EnumerableMap-Bytes32ToBytes32Map-uint256-}[`++at(map, index)++`] @@ -3959,6 +4363,7 @@ array of EnumerableMap. * {xref-EnumerableMap-keys-struct-EnumerableMap-Bytes32ToBytes32Map-}[`++keys(map)++`] * {xref-EnumerableMap-set-struct-EnumerableMap-UintToUintMap-uint256-uint256-}[`++set(map, key, value)++`] * {xref-EnumerableMap-remove-struct-EnumerableMap-UintToUintMap-uint256-}[`++remove(map, key)++`] +* {xref-EnumerableMap-clear-struct-EnumerableMap-UintToUintMap-}[`++clear(map)++`] * {xref-EnumerableMap-contains-struct-EnumerableMap-UintToUintMap-uint256-}[`++contains(map, key)++`] * {xref-EnumerableMap-length-struct-EnumerableMap-UintToUintMap-}[`++length(map)++`] * {xref-EnumerableMap-at-struct-EnumerableMap-UintToUintMap-uint256-}[`++at(map, index)++`] @@ -3967,6 +4372,7 @@ array of EnumerableMap. * {xref-EnumerableMap-keys-struct-EnumerableMap-UintToUintMap-}[`++keys(map)++`] * {xref-EnumerableMap-set-struct-EnumerableMap-UintToAddressMap-uint256-address-}[`++set(map, key, value)++`] * {xref-EnumerableMap-remove-struct-EnumerableMap-UintToAddressMap-uint256-}[`++remove(map, key)++`] +* {xref-EnumerableMap-clear-struct-EnumerableMap-UintToAddressMap-}[`++clear(map)++`] * {xref-EnumerableMap-contains-struct-EnumerableMap-UintToAddressMap-uint256-}[`++contains(map, key)++`] * {xref-EnumerableMap-length-struct-EnumerableMap-UintToAddressMap-}[`++length(map)++`] * {xref-EnumerableMap-at-struct-EnumerableMap-UintToAddressMap-uint256-}[`++at(map, index)++`] @@ -3975,6 +4381,7 @@ array of EnumerableMap. * {xref-EnumerableMap-keys-struct-EnumerableMap-UintToAddressMap-}[`++keys(map)++`] * {xref-EnumerableMap-set-struct-EnumerableMap-UintToBytes32Map-uint256-bytes32-}[`++set(map, key, value)++`] * {xref-EnumerableMap-remove-struct-EnumerableMap-UintToBytes32Map-uint256-}[`++remove(map, key)++`] +* {xref-EnumerableMap-clear-struct-EnumerableMap-UintToBytes32Map-}[`++clear(map)++`] * {xref-EnumerableMap-contains-struct-EnumerableMap-UintToBytes32Map-uint256-}[`++contains(map, key)++`] * {xref-EnumerableMap-length-struct-EnumerableMap-UintToBytes32Map-}[`++length(map)++`] * {xref-EnumerableMap-at-struct-EnumerableMap-UintToBytes32Map-uint256-}[`++at(map, index)++`] @@ -3983,6 +4390,7 @@ array of EnumerableMap. * {xref-EnumerableMap-keys-struct-EnumerableMap-UintToBytes32Map-}[`++keys(map)++`] * {xref-EnumerableMap-set-struct-EnumerableMap-AddressToUintMap-address-uint256-}[`++set(map, key, value)++`] * {xref-EnumerableMap-remove-struct-EnumerableMap-AddressToUintMap-address-}[`++remove(map, key)++`] +* {xref-EnumerableMap-clear-struct-EnumerableMap-AddressToUintMap-}[`++clear(map)++`] * {xref-EnumerableMap-contains-struct-EnumerableMap-AddressToUintMap-address-}[`++contains(map, key)++`] * {xref-EnumerableMap-length-struct-EnumerableMap-AddressToUintMap-}[`++length(map)++`] * {xref-EnumerableMap-at-struct-EnumerableMap-AddressToUintMap-uint256-}[`++at(map, index)++`] @@ -3991,6 +4399,7 @@ array of EnumerableMap. * {xref-EnumerableMap-keys-struct-EnumerableMap-AddressToUintMap-}[`++keys(map)++`] * {xref-EnumerableMap-set-struct-EnumerableMap-AddressToAddressMap-address-address-}[`++set(map, key, value)++`] * {xref-EnumerableMap-remove-struct-EnumerableMap-AddressToAddressMap-address-}[`++remove(map, key)++`] +* {xref-EnumerableMap-clear-struct-EnumerableMap-AddressToAddressMap-}[`++clear(map)++`] * {xref-EnumerableMap-contains-struct-EnumerableMap-AddressToAddressMap-address-}[`++contains(map, key)++`] * {xref-EnumerableMap-length-struct-EnumerableMap-AddressToAddressMap-}[`++length(map)++`] * {xref-EnumerableMap-at-struct-EnumerableMap-AddressToAddressMap-uint256-}[`++at(map, index)++`] @@ -3999,6 +4408,7 @@ array of EnumerableMap. * {xref-EnumerableMap-keys-struct-EnumerableMap-AddressToAddressMap-}[`++keys(map)++`] * {xref-EnumerableMap-set-struct-EnumerableMap-AddressToBytes32Map-address-bytes32-}[`++set(map, key, value)++`] * {xref-EnumerableMap-remove-struct-EnumerableMap-AddressToBytes32Map-address-}[`++remove(map, key)++`] +* {xref-EnumerableMap-clear-struct-EnumerableMap-AddressToBytes32Map-}[`++clear(map)++`] * {xref-EnumerableMap-contains-struct-EnumerableMap-AddressToBytes32Map-address-}[`++contains(map, key)++`] * {xref-EnumerableMap-length-struct-EnumerableMap-AddressToBytes32Map-}[`++length(map)++`] * {xref-EnumerableMap-at-struct-EnumerableMap-AddressToBytes32Map-uint256-}[`++at(map, index)++`] @@ -4007,6 +4417,7 @@ array of EnumerableMap. * {xref-EnumerableMap-keys-struct-EnumerableMap-AddressToBytes32Map-}[`++keys(map)++`] * {xref-EnumerableMap-set-struct-EnumerableMap-Bytes32ToUintMap-bytes32-uint256-}[`++set(map, key, value)++`] * {xref-EnumerableMap-remove-struct-EnumerableMap-Bytes32ToUintMap-bytes32-}[`++remove(map, key)++`] +* {xref-EnumerableMap-clear-struct-EnumerableMap-Bytes32ToUintMap-}[`++clear(map)++`] * {xref-EnumerableMap-contains-struct-EnumerableMap-Bytes32ToUintMap-bytes32-}[`++contains(map, key)++`] * {xref-EnumerableMap-length-struct-EnumerableMap-Bytes32ToUintMap-}[`++length(map)++`] * {xref-EnumerableMap-at-struct-EnumerableMap-Bytes32ToUintMap-uint256-}[`++at(map, index)++`] @@ -4015,6 +4426,7 @@ array of EnumerableMap. * {xref-EnumerableMap-keys-struct-EnumerableMap-Bytes32ToUintMap-}[`++keys(map)++`] * {xref-EnumerableMap-set-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-address-}[`++set(map, key, value)++`] * {xref-EnumerableMap-remove-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-}[`++remove(map, key)++`] +* {xref-EnumerableMap-clear-struct-EnumerableMap-Bytes32ToAddressMap-}[`++clear(map)++`] * {xref-EnumerableMap-contains-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-}[`++contains(map, key)++`] * {xref-EnumerableMap-length-struct-EnumerableMap-Bytes32ToAddressMap-}[`++length(map)++`] * {xref-EnumerableMap-at-struct-EnumerableMap-Bytes32ToAddressMap-uint256-}[`++at(map, index)++`] @@ -4049,6 +4461,15 @@ Removes a key-value pair from a map. O(1). Returns true if the key was removed from the map, that is if it was present. +[.contract-item] +[[EnumerableMap-clear-struct-EnumerableMap-Bytes32ToBytes32Map-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableMap.Bytes32ToBytes32Map map)++` [.item-kind]#internal# + +Removes all the entries from a map. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableMap-contains-struct-EnumerableMap-Bytes32ToBytes32Map-bytes32-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableMap.Bytes32ToBytes32Map map, bytes32 key) → bool++` [.item-kind]#internal# @@ -4120,6 +4541,15 @@ Removes a value from a map. O(1). Returns true if the key was removed from the map, that is if it was present. +[.contract-item] +[[EnumerableMap-clear-struct-EnumerableMap-UintToUintMap-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableMap.UintToUintMap map)++` [.item-kind]#internal# + +Removes all the entries from a map. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableMap-contains-struct-EnumerableMap-UintToUintMap-uint256-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableMap.UintToUintMap map, uint256 key) → bool++` [.item-kind]#internal# @@ -4190,6 +4620,15 @@ Removes a value from a map. O(1). Returns true if the key was removed from the map, that is if it was present. +[.contract-item] +[[EnumerableMap-clear-struct-EnumerableMap-UintToAddressMap-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableMap.UintToAddressMap map)++` [.item-kind]#internal# + +Removes all the entries from a map. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableMap-contains-struct-EnumerableMap-UintToAddressMap-uint256-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableMap.UintToAddressMap map, uint256 key) → bool++` [.item-kind]#internal# @@ -4260,6 +4699,15 @@ Removes a value from a map. O(1). Returns true if the key was removed from the map, that is if it was present. +[.contract-item] +[[EnumerableMap-clear-struct-EnumerableMap-UintToBytes32Map-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableMap.UintToBytes32Map map)++` [.item-kind]#internal# + +Removes all the entries from a map. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableMap-contains-struct-EnumerableMap-UintToBytes32Map-uint256-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableMap.UintToBytes32Map map, uint256 key) → bool++` [.item-kind]#internal# @@ -4330,6 +4778,15 @@ Removes a value from a map. O(1). Returns true if the key was removed from the map, that is if it was present. +[.contract-item] +[[EnumerableMap-clear-struct-EnumerableMap-AddressToUintMap-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableMap.AddressToUintMap map)++` [.item-kind]#internal# + +Removes all the entries from a map. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableMap-contains-struct-EnumerableMap-AddressToUintMap-address-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableMap.AddressToUintMap map, address key) → bool++` [.item-kind]#internal# @@ -4400,6 +4857,15 @@ Removes a value from a map. O(1). Returns true if the key was removed from the map, that is if it was present. +[.contract-item] +[[EnumerableMap-clear-struct-EnumerableMap-AddressToAddressMap-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableMap.AddressToAddressMap map)++` [.item-kind]#internal# + +Removes all the entries from a map. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableMap-contains-struct-EnumerableMap-AddressToAddressMap-address-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableMap.AddressToAddressMap map, address key) → bool++` [.item-kind]#internal# @@ -4470,6 +4936,15 @@ Removes a value from a map. O(1). Returns true if the key was removed from the map, that is if it was present. +[.contract-item] +[[EnumerableMap-clear-struct-EnumerableMap-AddressToBytes32Map-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableMap.AddressToBytes32Map map)++` [.item-kind]#internal# + +Removes all the entries from a map. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableMap-contains-struct-EnumerableMap-AddressToBytes32Map-address-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableMap.AddressToBytes32Map map, address key) → bool++` [.item-kind]#internal# @@ -4540,6 +5015,15 @@ Removes a value from a map. O(1). Returns true if the key was removed from the map, that is if it was present. +[.contract-item] +[[EnumerableMap-clear-struct-EnumerableMap-Bytes32ToUintMap-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableMap.Bytes32ToUintMap map)++` [.item-kind]#internal# + +Removes all the entries from a map. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableMap-contains-struct-EnumerableMap-Bytes32ToUintMap-bytes32-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableMap.Bytes32ToUintMap map, bytes32 key) → bool++` [.item-kind]#internal# @@ -4610,6 +5094,15 @@ Removes a value from a map. O(1). Returns true if the key was removed from the map, that is if it was present. +[.contract-item] +[[EnumerableMap-clear-struct-EnumerableMap-Bytes32ToAddressMap-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableMap.Bytes32ToAddressMap map)++` [.item-kind]#internal# + +Removes all the entries from a map. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableMap-contains-struct-EnumerableMap-Bytes32ToAddressMap-bytes32-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableMap.Bytes32ToAddressMap map, bytes32 key) → bool++` [.item-kind]#internal# @@ -4672,6 +5165,7 @@ Query for a nonexistent map key. :Bytes32Set: pass:normal[xref:#EnumerableSet-Bytes32Set[`++Bytes32Set++`]] :add: pass:normal[xref:#EnumerableSet-add-struct-EnumerableSet-Bytes32Set-bytes32-[`++add++`]] :remove: pass:normal[xref:#EnumerableSet-remove-struct-EnumerableSet-Bytes32Set-bytes32-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableSet-clear-struct-EnumerableSet-Bytes32Set-[`++clear++`]] :contains: pass:normal[xref:#EnumerableSet-contains-struct-EnumerableSet-Bytes32Set-bytes32-[`++contains++`]] :length: pass:normal[xref:#EnumerableSet-length-struct-EnumerableSet-Bytes32Set-[`++length++`]] :at: pass:normal[xref:#EnumerableSet-at-struct-EnumerableSet-Bytes32Set-uint256-[`++at++`]] @@ -4679,6 +5173,7 @@ Query for a nonexistent map key. :AddressSet: pass:normal[xref:#EnumerableSet-AddressSet[`++AddressSet++`]] :add: pass:normal[xref:#EnumerableSet-add-struct-EnumerableSet-AddressSet-address-[`++add++`]] :remove: pass:normal[xref:#EnumerableSet-remove-struct-EnumerableSet-AddressSet-address-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableSet-clear-struct-EnumerableSet-AddressSet-[`++clear++`]] :contains: pass:normal[xref:#EnumerableSet-contains-struct-EnumerableSet-AddressSet-address-[`++contains++`]] :length: pass:normal[xref:#EnumerableSet-length-struct-EnumerableSet-AddressSet-[`++length++`]] :at: pass:normal[xref:#EnumerableSet-at-struct-EnumerableSet-AddressSet-uint256-[`++at++`]] @@ -4686,14 +5181,37 @@ Query for a nonexistent map key. :UintSet: pass:normal[xref:#EnumerableSet-UintSet[`++UintSet++`]] :add: pass:normal[xref:#EnumerableSet-add-struct-EnumerableSet-UintSet-uint256-[`++add++`]] :remove: pass:normal[xref:#EnumerableSet-remove-struct-EnumerableSet-UintSet-uint256-[`++remove++`]] +:clear: pass:normal[xref:#EnumerableSet-clear-struct-EnumerableSet-UintSet-[`++clear++`]] :contains: pass:normal[xref:#EnumerableSet-contains-struct-EnumerableSet-UintSet-uint256-[`++contains++`]] :length: pass:normal[xref:#EnumerableSet-length-struct-EnumerableSet-UintSet-[`++length++`]] :at: pass:normal[xref:#EnumerableSet-at-struct-EnumerableSet-UintSet-uint256-[`++at++`]] :values: pass:normal[xref:#EnumerableSet-values-struct-EnumerableSet-UintSet-[`++values++`]] +:add-struct-EnumerableSet-Bytes32Set-bytes32: pass:normal[xref:#EnumerableSet-add-struct-EnumerableSet-Bytes32Set-bytes32-[`++add++`]] +:remove-struct-EnumerableSet-Bytes32Set-bytes32: pass:normal[xref:#EnumerableSet-remove-struct-EnumerableSet-Bytes32Set-bytes32-[`++remove++`]] +:clear-struct-EnumerableSet-Bytes32Set: pass:normal[xref:#EnumerableSet-clear-struct-EnumerableSet-Bytes32Set-[`++clear++`]] +:contains-struct-EnumerableSet-Bytes32Set-bytes32: pass:normal[xref:#EnumerableSet-contains-struct-EnumerableSet-Bytes32Set-bytes32-[`++contains++`]] +:length-struct-EnumerableSet-Bytes32Set: pass:normal[xref:#EnumerableSet-length-struct-EnumerableSet-Bytes32Set-[`++length++`]] +:at-struct-EnumerableSet-Bytes32Set-uint256: pass:normal[xref:#EnumerableSet-at-struct-EnumerableSet-Bytes32Set-uint256-[`++at++`]] +:values-struct-EnumerableSet-Bytes32Set: pass:normal[xref:#EnumerableSet-values-struct-EnumerableSet-Bytes32Set-[`++values++`]] +:add-struct-EnumerableSet-AddressSet-address: pass:normal[xref:#EnumerableSet-add-struct-EnumerableSet-AddressSet-address-[`++add++`]] +:remove-struct-EnumerableSet-AddressSet-address: pass:normal[xref:#EnumerableSet-remove-struct-EnumerableSet-AddressSet-address-[`++remove++`]] +:clear-struct-EnumerableSet-AddressSet: pass:normal[xref:#EnumerableSet-clear-struct-EnumerableSet-AddressSet-[`++clear++`]] +:contains-struct-EnumerableSet-AddressSet-address: pass:normal[xref:#EnumerableSet-contains-struct-EnumerableSet-AddressSet-address-[`++contains++`]] +:length-struct-EnumerableSet-AddressSet: pass:normal[xref:#EnumerableSet-length-struct-EnumerableSet-AddressSet-[`++length++`]] +:at-struct-EnumerableSet-AddressSet-uint256: pass:normal[xref:#EnumerableSet-at-struct-EnumerableSet-AddressSet-uint256-[`++at++`]] +:values-struct-EnumerableSet-AddressSet: pass:normal[xref:#EnumerableSet-values-struct-EnumerableSet-AddressSet-[`++values++`]] +:add-struct-EnumerableSet-UintSet-uint256: pass:normal[xref:#EnumerableSet-add-struct-EnumerableSet-UintSet-uint256-[`++add++`]] +:remove-struct-EnumerableSet-UintSet-uint256: pass:normal[xref:#EnumerableSet-remove-struct-EnumerableSet-UintSet-uint256-[`++remove++`]] +:clear-struct-EnumerableSet-UintSet: pass:normal[xref:#EnumerableSet-clear-struct-EnumerableSet-UintSet-[`++clear++`]] +:contains-struct-EnumerableSet-UintSet-uint256: pass:normal[xref:#EnumerableSet-contains-struct-EnumerableSet-UintSet-uint256-[`++contains++`]] +:length-struct-EnumerableSet-UintSet: pass:normal[xref:#EnumerableSet-length-struct-EnumerableSet-UintSet-[`++length++`]] +:at-struct-EnumerableSet-UintSet-uint256: pass:normal[xref:#EnumerableSet-at-struct-EnumerableSet-UintSet-uint256-[`++at++`]] +:values-struct-EnumerableSet-UintSet: pass:normal[xref:#EnumerableSet-values-struct-EnumerableSet-UintSet-[`++values++`]] + [.contract] [[EnumerableSet]] -=== `++EnumerableSet++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/structs/EnumerableSet.sol[{github-icon},role=heading-link] +=== `++EnumerableSet++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/structs/EnumerableSet.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -4709,6 +5227,7 @@ Sets have the following properties: - Elements are added, removed, and checked for existence in constant time (O(1)). - Elements are enumerated in O(n). No guarantees are made on the ordering. +- Set can be cleared (all elements removed) in O(n). ```solidity contract Example { @@ -4738,18 +5257,21 @@ array of EnumerableSet. -- * {xref-EnumerableSet-add-struct-EnumerableSet-Bytes32Set-bytes32-}[`++add(set, value)++`] * {xref-EnumerableSet-remove-struct-EnumerableSet-Bytes32Set-bytes32-}[`++remove(set, value)++`] +* {xref-EnumerableSet-clear-struct-EnumerableSet-Bytes32Set-}[`++clear(set)++`] * {xref-EnumerableSet-contains-struct-EnumerableSet-Bytes32Set-bytes32-}[`++contains(set, value)++`] * {xref-EnumerableSet-length-struct-EnumerableSet-Bytes32Set-}[`++length(set)++`] * {xref-EnumerableSet-at-struct-EnumerableSet-Bytes32Set-uint256-}[`++at(set, index)++`] * {xref-EnumerableSet-values-struct-EnumerableSet-Bytes32Set-}[`++values(set)++`] * {xref-EnumerableSet-add-struct-EnumerableSet-AddressSet-address-}[`++add(set, value)++`] * {xref-EnumerableSet-remove-struct-EnumerableSet-AddressSet-address-}[`++remove(set, value)++`] +* {xref-EnumerableSet-clear-struct-EnumerableSet-AddressSet-}[`++clear(set)++`] * {xref-EnumerableSet-contains-struct-EnumerableSet-AddressSet-address-}[`++contains(set, value)++`] * {xref-EnumerableSet-length-struct-EnumerableSet-AddressSet-}[`++length(set)++`] * {xref-EnumerableSet-at-struct-EnumerableSet-AddressSet-uint256-}[`++at(set, index)++`] * {xref-EnumerableSet-values-struct-EnumerableSet-AddressSet-}[`++values(set)++`] * {xref-EnumerableSet-add-struct-EnumerableSet-UintSet-uint256-}[`++add(set, value)++`] * {xref-EnumerableSet-remove-struct-EnumerableSet-UintSet-uint256-}[`++remove(set, value)++`] +* {xref-EnumerableSet-clear-struct-EnumerableSet-UintSet-}[`++clear(set)++`] * {xref-EnumerableSet-contains-struct-EnumerableSet-UintSet-uint256-}[`++contains(set, value)++`] * {xref-EnumerableSet-length-struct-EnumerableSet-UintSet-}[`++length(set)++`] * {xref-EnumerableSet-at-struct-EnumerableSet-UintSet-uint256-}[`++at(set, index)++`] @@ -4775,6 +5297,15 @@ Removes a value from a set. O(1). Returns true if the value was removed from the set, that is if it was present. +[.contract-item] +[[EnumerableSet-clear-struct-EnumerableSet-Bytes32Set-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableSet.Bytes32Set set)++` [.item-kind]#internal# + +Removes all the values from a set. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableSet-contains-struct-EnumerableSet-Bytes32Set-bytes32-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableSet.Bytes32Set set, bytes32 value) → bool++` [.item-kind]#internal# @@ -4829,6 +5360,15 @@ Removes a value from a set. O(1). Returns true if the value was removed from the set, that is if it was present. +[.contract-item] +[[EnumerableSet-clear-struct-EnumerableSet-AddressSet-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableSet.AddressSet set)++` [.item-kind]#internal# + +Removes all the values from a set. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableSet-contains-struct-EnumerableSet-AddressSet-address-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableSet.AddressSet set, address value) → bool++` [.item-kind]#internal# @@ -4883,6 +5423,15 @@ Removes a value from a set. O(1). Returns true if the value was removed from the set, that is if it was present. +[.contract-item] +[[EnumerableSet-clear-struct-EnumerableSet-UintSet-]] +==== `[.contract-item-name]#++clear++#++(struct EnumerableSet.UintSet set)++` [.item-kind]#internal# + +Removes all the values from a set. O(n). + +WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the +function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + [.contract-item] [[EnumerableSet-contains-struct-EnumerableSet-UintSet-uint256-]] ==== `[.contract-item-name]#++contains++#++(struct EnumerableSet.UintSet set, uint256 value) → bool++` [.item-kind]#internal# @@ -4931,9 +5480,20 @@ uncallable if the set grows to a point where copying to memory consumes too much :length: pass:normal[xref:#DoubleEndedQueue-length-struct-DoubleEndedQueue-Bytes32Deque-[`++length++`]] :empty: pass:normal[xref:#DoubleEndedQueue-empty-struct-DoubleEndedQueue-Bytes32Deque-[`++empty++`]] +:pushBack-struct-DoubleEndedQueue-Bytes32Deque-bytes32: pass:normal[xref:#DoubleEndedQueue-pushBack-struct-DoubleEndedQueue-Bytes32Deque-bytes32-[`++pushBack++`]] +:popBack-struct-DoubleEndedQueue-Bytes32Deque: pass:normal[xref:#DoubleEndedQueue-popBack-struct-DoubleEndedQueue-Bytes32Deque-[`++popBack++`]] +:pushFront-struct-DoubleEndedQueue-Bytes32Deque-bytes32: pass:normal[xref:#DoubleEndedQueue-pushFront-struct-DoubleEndedQueue-Bytes32Deque-bytes32-[`++pushFront++`]] +:popFront-struct-DoubleEndedQueue-Bytes32Deque: pass:normal[xref:#DoubleEndedQueue-popFront-struct-DoubleEndedQueue-Bytes32Deque-[`++popFront++`]] +:front-struct-DoubleEndedQueue-Bytes32Deque: pass:normal[xref:#DoubleEndedQueue-front-struct-DoubleEndedQueue-Bytes32Deque-[`++front++`]] +:back-struct-DoubleEndedQueue-Bytes32Deque: pass:normal[xref:#DoubleEndedQueue-back-struct-DoubleEndedQueue-Bytes32Deque-[`++back++`]] +:at-struct-DoubleEndedQueue-Bytes32Deque-uint256: pass:normal[xref:#DoubleEndedQueue-at-struct-DoubleEndedQueue-Bytes32Deque-uint256-[`++at++`]] +:clear-struct-DoubleEndedQueue-Bytes32Deque: pass:normal[xref:#DoubleEndedQueue-clear-struct-DoubleEndedQueue-Bytes32Deque-[`++clear++`]] +:length-struct-DoubleEndedQueue-Bytes32Deque: pass:normal[xref:#DoubleEndedQueue-length-struct-DoubleEndedQueue-Bytes32Deque-[`++length++`]] +:empty-struct-DoubleEndedQueue-Bytes32Deque: pass:normal[xref:#DoubleEndedQueue-empty-struct-DoubleEndedQueue-Bytes32Deque-[`++empty++`]] + [.contract] [[DoubleEndedQueue]] -=== `++DoubleEndedQueue++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/structs/DoubleEndedQueue.sol[{github-icon},role=heading-link] +=== `++DoubleEndedQueue++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/structs/DoubleEndedQueue.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -5055,9 +5615,17 @@ Returns true if the queue is empty. :last: pass:normal[xref:#CircularBuffer-last-struct-CircularBuffer-Bytes32CircularBuffer-uint256-[`++last++`]] :includes: pass:normal[xref:#CircularBuffer-includes-struct-CircularBuffer-Bytes32CircularBuffer-bytes32-[`++includes++`]] +:setup-struct-CircularBuffer-Bytes32CircularBuffer-uint256: pass:normal[xref:#CircularBuffer-setup-struct-CircularBuffer-Bytes32CircularBuffer-uint256-[`++setup++`]] +:clear-struct-CircularBuffer-Bytes32CircularBuffer: pass:normal[xref:#CircularBuffer-clear-struct-CircularBuffer-Bytes32CircularBuffer-[`++clear++`]] +:push-struct-CircularBuffer-Bytes32CircularBuffer-bytes32: pass:normal[xref:#CircularBuffer-push-struct-CircularBuffer-Bytes32CircularBuffer-bytes32-[`++push++`]] +:count-struct-CircularBuffer-Bytes32CircularBuffer: pass:normal[xref:#CircularBuffer-count-struct-CircularBuffer-Bytes32CircularBuffer-[`++count++`]] +:length-struct-CircularBuffer-Bytes32CircularBuffer: pass:normal[xref:#CircularBuffer-length-struct-CircularBuffer-Bytes32CircularBuffer-[`++length++`]] +:last-struct-CircularBuffer-Bytes32CircularBuffer-uint256: pass:normal[xref:#CircularBuffer-last-struct-CircularBuffer-Bytes32CircularBuffer-uint256-[`++last++`]] +:includes-struct-CircularBuffer-Bytes32CircularBuffer-bytes32: pass:normal[xref:#CircularBuffer-includes-struct-CircularBuffer-Bytes32CircularBuffer-bytes32-[`++includes++`]] + [.contract] [[CircularBuffer]] -=== `++CircularBuffer++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/structs/CircularBuffer.sol[{github-icon},role=heading-link] +=== `++CircularBuffer++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/structs/CircularBuffer.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -5119,7 +5687,7 @@ _Available since v5.1._ [[CircularBuffer-setup-struct-CircularBuffer-Bytes32CircularBuffer-uint256-]] ==== `[.contract-item-name]#++setup++#++(struct CircularBuffer.Bytes32CircularBuffer self, uint256 size)++` [.item-kind]#internal# -Initialize a new CircularBuffer of given size. +Initialize a new CircularBuffer of a given size. If the CircularBuffer was already setup and used, calling that function again will reset it to a blank state. @@ -5205,9 +5773,34 @@ Error emitted when trying to setup a buffer with a size of 0. :length: pass:normal[xref:#Checkpoints-length-struct-Checkpoints-Trace160-[`++length++`]] :at: pass:normal[xref:#Checkpoints-at-struct-Checkpoints-Trace160-uint32-[`++at++`]] +:push-struct-Checkpoints-Trace224-uint32-uint224: pass:normal[xref:#Checkpoints-push-struct-Checkpoints-Trace224-uint32-uint224-[`++push++`]] +:lowerLookup-struct-Checkpoints-Trace224-uint32: pass:normal[xref:#Checkpoints-lowerLookup-struct-Checkpoints-Trace224-uint32-[`++lowerLookup++`]] +:upperLookup-struct-Checkpoints-Trace224-uint32: pass:normal[xref:#Checkpoints-upperLookup-struct-Checkpoints-Trace224-uint32-[`++upperLookup++`]] +:upperLookupRecent-struct-Checkpoints-Trace224-uint32: pass:normal[xref:#Checkpoints-upperLookupRecent-struct-Checkpoints-Trace224-uint32-[`++upperLookupRecent++`]] +:latest-struct-Checkpoints-Trace224: pass:normal[xref:#Checkpoints-latest-struct-Checkpoints-Trace224-[`++latest++`]] +:latestCheckpoint-struct-Checkpoints-Trace224: pass:normal[xref:#Checkpoints-latestCheckpoint-struct-Checkpoints-Trace224-[`++latestCheckpoint++`]] +:length-struct-Checkpoints-Trace224: pass:normal[xref:#Checkpoints-length-struct-Checkpoints-Trace224-[`++length++`]] +:at-struct-Checkpoints-Trace224-uint32: pass:normal[xref:#Checkpoints-at-struct-Checkpoints-Trace224-uint32-[`++at++`]] +:push-struct-Checkpoints-Trace208-uint48-uint208: pass:normal[xref:#Checkpoints-push-struct-Checkpoints-Trace208-uint48-uint208-[`++push++`]] +:lowerLookup-struct-Checkpoints-Trace208-uint48: pass:normal[xref:#Checkpoints-lowerLookup-struct-Checkpoints-Trace208-uint48-[`++lowerLookup++`]] +:upperLookup-struct-Checkpoints-Trace208-uint48: pass:normal[xref:#Checkpoints-upperLookup-struct-Checkpoints-Trace208-uint48-[`++upperLookup++`]] +:upperLookupRecent-struct-Checkpoints-Trace208-uint48: pass:normal[xref:#Checkpoints-upperLookupRecent-struct-Checkpoints-Trace208-uint48-[`++upperLookupRecent++`]] +:latest-struct-Checkpoints-Trace208: pass:normal[xref:#Checkpoints-latest-struct-Checkpoints-Trace208-[`++latest++`]] +:latestCheckpoint-struct-Checkpoints-Trace208: pass:normal[xref:#Checkpoints-latestCheckpoint-struct-Checkpoints-Trace208-[`++latestCheckpoint++`]] +:length-struct-Checkpoints-Trace208: pass:normal[xref:#Checkpoints-length-struct-Checkpoints-Trace208-[`++length++`]] +:at-struct-Checkpoints-Trace208-uint32: pass:normal[xref:#Checkpoints-at-struct-Checkpoints-Trace208-uint32-[`++at++`]] +:push-struct-Checkpoints-Trace160-uint96-uint160: pass:normal[xref:#Checkpoints-push-struct-Checkpoints-Trace160-uint96-uint160-[`++push++`]] +:lowerLookup-struct-Checkpoints-Trace160-uint96: pass:normal[xref:#Checkpoints-lowerLookup-struct-Checkpoints-Trace160-uint96-[`++lowerLookup++`]] +:upperLookup-struct-Checkpoints-Trace160-uint96: pass:normal[xref:#Checkpoints-upperLookup-struct-Checkpoints-Trace160-uint96-[`++upperLookup++`]] +:upperLookupRecent-struct-Checkpoints-Trace160-uint96: pass:normal[xref:#Checkpoints-upperLookupRecent-struct-Checkpoints-Trace160-uint96-[`++upperLookupRecent++`]] +:latest-struct-Checkpoints-Trace160: pass:normal[xref:#Checkpoints-latest-struct-Checkpoints-Trace160-[`++latest++`]] +:latestCheckpoint-struct-Checkpoints-Trace160: pass:normal[xref:#Checkpoints-latestCheckpoint-struct-Checkpoints-Trace160-[`++latestCheckpoint++`]] +:length-struct-Checkpoints-Trace160: pass:normal[xref:#Checkpoints-length-struct-Checkpoints-Trace160-[`++length++`]] +:at-struct-Checkpoints-Trace160-uint32: pass:normal[xref:#Checkpoints-at-struct-Checkpoints-Trace160-uint32-[`++at++`]] + [.contract] [[Checkpoints]] -=== `++Checkpoints++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/structs/Checkpoints.sol[{github-icon},role=heading-link] +=== `++Checkpoints++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/structs/Checkpoints.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -5309,7 +5902,7 @@ in the most recent checkpoint. [[Checkpoints-length-struct-Checkpoints-Trace224-]] ==== `[.contract-item-name]#++length++#++(struct Checkpoints.Trace224 self) → uint256++` [.item-kind]#internal# -Returns the number of checkpoint. +Returns the number of checkpoints. [.contract-item] [[Checkpoints-at-struct-Checkpoints-Trace224-uint32-]] @@ -5369,7 +5962,7 @@ in the most recent checkpoint. [[Checkpoints-length-struct-Checkpoints-Trace208-]] ==== `[.contract-item-name]#++length++#++(struct Checkpoints.Trace208 self) → uint256++` [.item-kind]#internal# -Returns the number of checkpoint. +Returns the number of checkpoints. [.contract-item] [[Checkpoints-at-struct-Checkpoints-Trace208-uint32-]] @@ -5429,7 +6022,7 @@ in the most recent checkpoint. [[Checkpoints-length-struct-Checkpoints-Trace160-]] ==== `[.contract-item-name]#++length++#++(struct Checkpoints.Trace160 self) → uint256++` [.item-kind]#internal# -Returns the number of checkpoint. +Returns the number of checkpoints. [.contract-item] [[Checkpoints-at-struct-Checkpoints-Trace160-uint32-]] @@ -5454,9 +6047,19 @@ A value was attempted to be inserted on a past checkpoint. :length: pass:normal[xref:#Heap-length-struct-Heap-Uint256Heap-[`++length++`]] :clear: pass:normal[xref:#Heap-clear-struct-Heap-Uint256Heap-[`++clear++`]] +:peek-struct-Heap-Uint256Heap: pass:normal[xref:#Heap-peek-struct-Heap-Uint256Heap-[`++peek++`]] +:pop-struct-Heap-Uint256Heap: pass:normal[xref:#Heap-pop-struct-Heap-Uint256Heap-[`++pop++`]] +:pop-struct-Heap-Uint256Heap-function--uint256-uint256--view-returns--bool-: pass:normal[xref:#Heap-pop-struct-Heap-Uint256Heap-function--uint256-uint256--view-returns--bool--[`++pop++`]] +:insert-struct-Heap-Uint256Heap-uint256: pass:normal[xref:#Heap-insert-struct-Heap-Uint256Heap-uint256-[`++insert++`]] +:insert-struct-Heap-Uint256Heap-uint256-function--uint256-uint256--view-returns--bool-: pass:normal[xref:#Heap-insert-struct-Heap-Uint256Heap-uint256-function--uint256-uint256--view-returns--bool--[`++insert++`]] +:replace-struct-Heap-Uint256Heap-uint256: pass:normal[xref:#Heap-replace-struct-Heap-Uint256Heap-uint256-[`++replace++`]] +:replace-struct-Heap-Uint256Heap-uint256-function--uint256-uint256--view-returns--bool-: pass:normal[xref:#Heap-replace-struct-Heap-Uint256Heap-uint256-function--uint256-uint256--view-returns--bool--[`++replace++`]] +:length-struct-Heap-Uint256Heap: pass:normal[xref:#Heap-length-struct-Heap-Uint256Heap-[`++length++`]] +:clear-struct-Heap-Uint256Heap: pass:normal[xref:#Heap-clear-struct-Heap-Uint256Heap-[`++clear++`]] + [.contract] [[Heap]] -=== `++Heap++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/structs/Heap.sol[{github-icon},role=heading-link] +=== `++Heap++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/structs/Heap.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -5578,16 +6181,28 @@ Returns the number of elements in the heap. Removes all elements in the heap. +:MerkleTreeUpdateInvalidIndex: pass:normal[xref:#MerkleTree-MerkleTreeUpdateInvalidIndex-uint256-uint256-[`++MerkleTreeUpdateInvalidIndex++`]] +:MerkleTreeUpdateInvalidProof: pass:normal[xref:#MerkleTree-MerkleTreeUpdateInvalidProof--[`++MerkleTreeUpdateInvalidProof++`]] :Bytes32PushTree: pass:normal[xref:#MerkleTree-Bytes32PushTree[`++Bytes32PushTree++`]] :setup: pass:normal[xref:#MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-[`++setup++`]] :setup: pass:normal[xref:#MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-function--bytes32-bytes32--view-returns--bytes32--[`++setup++`]] :push: pass:normal[xref:#MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-[`++push++`]] :push: pass:normal[xref:#MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-function--bytes32-bytes32--view-returns--bytes32--[`++push++`]] +:update: pass:normal[xref:#MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---[`++update++`]] +:update: pass:normal[xref:#MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32--[`++update++`]] :depth: pass:normal[xref:#MerkleTree-depth-struct-MerkleTree-Bytes32PushTree-[`++depth++`]] +:setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32: pass:normal[xref:#MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-[`++setup++`]] +:setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-function--bytes32-bytes32--view-returns--bytes32--[`++setup++`]] +:push-struct-MerkleTree-Bytes32PushTree-bytes32: pass:normal[xref:#MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-[`++push++`]] +:push-struct-MerkleTree-Bytes32PushTree-bytes32-function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-function--bytes32-bytes32--view-returns--bytes32--[`++push++`]] +:update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32--: pass:normal[xref:#MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---[`++update++`]] +:update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32-: pass:normal[xref:#MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32--[`++update++`]] +:depth-struct-MerkleTree-Bytes32PushTree: pass:normal[xref:#MerkleTree-depth-struct-MerkleTree-Bytes32PushTree-[`++depth++`]] + [.contract] [[MerkleTree]] -=== `++MerkleTree++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/structs/MerkleTree.sol[{github-icon},role=heading-link] +=== `++MerkleTree++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/structs/MerkleTree.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -5619,10 +6234,20 @@ _Available since v5.1._ * {xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-function--bytes32-bytes32--view-returns--bytes32--}[`++setup(self, treeDepth, zero, fnHash)++`] * {xref-MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-}[`++push(self, leaf)++`] * {xref-MerkleTree-push-struct-MerkleTree-Bytes32PushTree-bytes32-function--bytes32-bytes32--view-returns--bytes32--}[`++push(self, leaf, fnHash)++`] +* {xref-MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---}[`++update(self, index, oldValue, newValue, proof)++`] +* {xref-MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32--}[`++update(self, index, oldValue, newValue, proof, fnHash)++`] * {xref-MerkleTree-depth-struct-MerkleTree-Bytes32PushTree-}[`++depth(self)++`] -- +[.contract-index] +.Errors +-- +* {xref-MerkleTree-MerkleTreeUpdateInvalidIndex-uint256-uint256-}[`++MerkleTreeUpdateInvalidIndex(index, length)++`] +* {xref-MerkleTree-MerkleTreeUpdateInvalidProof--}[`++MerkleTreeUpdateInvalidProof()++`] + +-- + [.contract-item] [[MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-]] ==== `[.contract-item-name]#++setup++#++(struct MerkleTree.Bytes32PushTree self, uint8 treeDepth, bytes32 zero) → bytes32 initialRoot++` [.item-kind]#internal# @@ -5680,12 +6305,55 @@ second pre-image attacks. This variant uses a custom hashing function to hash internal nodes. It should only be called with the same function as the one used during the initial setup of the merkle tree. +[.contract-item] +[[MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---]] +==== `[.contract-item-name]#++update++#++(struct MerkleTree.Bytes32PushTree self, uint256 index, bytes32 oldValue, bytes32 newValue, bytes32[] proof) → bytes32 oldRoot, bytes32 newRoot++` [.item-kind]#internal# + +Change the value of the leaf at position `index` from `oldValue` to `newValue`. Returns the recomputed "old" +root (before the update) and "new" root (after the update). The caller must verify that the reconstructed old +root is the last known one. + +The `proof` must be an up-to-date inclusion proof for the leaf being updated. This means that this function is +vulnerable to front-running. Any {push} or {update} operation (that changes the root of the tree) would render +all "in flight" updates invalid. + +This variant uses {Hashes-commutativeKeccak256} to hash internal nodes. It should only be used on merkle trees +that were setup using the same (default) hashing function (i.e. by calling +{xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-}[the default setup] function). + +[.contract-item] +[[MerkleTree-update-struct-MerkleTree-Bytes32PushTree-uint256-bytes32-bytes32-bytes32---function--bytes32-bytes32--view-returns--bytes32--]] +==== `[.contract-item-name]#++update++#++(struct MerkleTree.Bytes32PushTree self, uint256 index, bytes32 oldValue, bytes32 newValue, bytes32[] proof, function (bytes32,bytes32) view returns (bytes32) fnHash) → bytes32 oldRoot, bytes32 newRoot++` [.item-kind]#internal# + +Change the value of the leaf at position `index` from `oldValue` to `newValue`. Returns the recomputed "old" +root (before the update) and "new" root (after the update). The caller must verify that the reconstructed old +root is the last known one. + +The `proof` must be an up-to-date inclusion proof for the leaf being update. This means that this function is +vulnerable to front-running. Any {push} or {update} operation (that changes the root of the tree) would render +all "in flight" updates invalid. + +This variant uses a custom hashing function to hash internal nodes. It should only be called with the same +function as the one used during the initial setup of the merkle tree. + [.contract-item] [[MerkleTree-depth-struct-MerkleTree-Bytes32PushTree-]] ==== `[.contract-item-name]#++depth++#++(struct MerkleTree.Bytes32PushTree self) → uint256++` [.item-kind]#internal# Tree's depth (set at initialization) +[.contract-item] +[[MerkleTree-MerkleTreeUpdateInvalidIndex-uint256-uint256-]] +==== `[.contract-item-name]#++MerkleTreeUpdateInvalidIndex++#++(uint256 index, uint256 length)++` [.item-kind]#error# + +Error emitted when trying to update a leaf that was not previously pushed. + +[.contract-item] +[[MerkleTree-MerkleTreeUpdateInvalidProof--]] +==== `[.contract-item-name]#++MerkleTreeUpdateInvalidProof++#++()++` [.item-kind]#error# + +Error emitted when the proof used during an update is invalid (could not reproduce the side). + == Libraries :Create2EmptyBytecode: pass:normal[xref:#Create2-Create2EmptyBytecode--[`++Create2EmptyBytecode++`]] @@ -5693,9 +6361,13 @@ Tree's depth (set at initialization) :computeAddress: pass:normal[xref:#Create2-computeAddress-bytes32-bytes32-[`++computeAddress++`]] :computeAddress: pass:normal[xref:#Create2-computeAddress-bytes32-bytes32-address-[`++computeAddress++`]] +:deploy-uint256-bytes32-bytes: pass:normal[xref:#Create2-deploy-uint256-bytes32-bytes-[`++deploy++`]] +:computeAddress-bytes32-bytes32: pass:normal[xref:#Create2-computeAddress-bytes32-bytes32-[`++computeAddress++`]] +:computeAddress-bytes32-bytes32-address: pass:normal[xref:#Create2-computeAddress-bytes32-bytes32-address-[`++computeAddress++`]] + [.contract] [[Create2]] -=== `++Create2++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Create2.sol[{github-icon},role=heading-link] +=== `++Create2++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Create2.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -5772,9 +6444,17 @@ There's no code to deploy. :verifyCallResultFromTarget: pass:normal[xref:#Address-verifyCallResultFromTarget-address-bool-bytes-[`++verifyCallResultFromTarget++`]] :verifyCallResult: pass:normal[xref:#Address-verifyCallResult-bool-bytes-[`++verifyCallResult++`]] +:sendValue-address-payable-uint256: pass:normal[xref:#Address-sendValue-address-payable-uint256-[`++sendValue++`]] +:functionCall-address-bytes: pass:normal[xref:#Address-functionCall-address-bytes-[`++functionCall++`]] +:functionCallWithValue-address-bytes-uint256: pass:normal[xref:#Address-functionCallWithValue-address-bytes-uint256-[`++functionCallWithValue++`]] +:functionStaticCall-address-bytes: pass:normal[xref:#Address-functionStaticCall-address-bytes-[`++functionStaticCall++`]] +:functionDelegateCall-address-bytes: pass:normal[xref:#Address-functionDelegateCall-address-bytes-[`++functionDelegateCall++`]] +:verifyCallResultFromTarget-address-bool-bytes: pass:normal[xref:#Address-verifyCallResultFromTarget-address-bool-bytes-[`++verifyCallResultFromTarget++`]] +:verifyCallResult-bool-bytes: pass:normal[xref:#Address-verifyCallResult-bool-bytes-[`++verifyCallResult++`]] + [.contract] [[Address]] -=== `++Address++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Address.sol[{github-icon},role=heading-link] +=== `++Address++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Address.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -5911,9 +6591,30 @@ There's no code at `target` (it is not a contract). :unsafeSetLength: pass:normal[xref:#Arrays-unsafeSetLength-bytes32---uint256-[`++unsafeSetLength++`]] :unsafeSetLength: pass:normal[xref:#Arrays-unsafeSetLength-uint256---uint256-[`++unsafeSetLength++`]] +:sort-uint256---function--uint256-uint256--pure-returns--bool-: pass:normal[xref:#Arrays-sort-uint256---function--uint256-uint256--pure-returns--bool--[`++sort++`]] +:sort-uint256--: pass:normal[xref:#Arrays-sort-uint256---[`++sort++`]] +:sort-address---function--address-address--pure-returns--bool-: pass:normal[xref:#Arrays-sort-address---function--address-address--pure-returns--bool--[`++sort++`]] +:sort-address--: pass:normal[xref:#Arrays-sort-address---[`++sort++`]] +:sort-bytes32---function--bytes32-bytes32--pure-returns--bool-: pass:normal[xref:#Arrays-sort-bytes32---function--bytes32-bytes32--pure-returns--bool--[`++sort++`]] +:sort-bytes32--: pass:normal[xref:#Arrays-sort-bytes32---[`++sort++`]] +:findUpperBound-uint256---uint256: pass:normal[xref:#Arrays-findUpperBound-uint256---uint256-[`++findUpperBound++`]] +:lowerBound-uint256---uint256: pass:normal[xref:#Arrays-lowerBound-uint256---uint256-[`++lowerBound++`]] +:upperBound-uint256---uint256: pass:normal[xref:#Arrays-upperBound-uint256---uint256-[`++upperBound++`]] +:lowerBoundMemory-uint256---uint256: pass:normal[xref:#Arrays-lowerBoundMemory-uint256---uint256-[`++lowerBoundMemory++`]] +:upperBoundMemory-uint256---uint256: pass:normal[xref:#Arrays-upperBoundMemory-uint256---uint256-[`++upperBoundMemory++`]] +:unsafeAccess-address---uint256: pass:normal[xref:#Arrays-unsafeAccess-address---uint256-[`++unsafeAccess++`]] +:unsafeAccess-bytes32---uint256: pass:normal[xref:#Arrays-unsafeAccess-bytes32---uint256-[`++unsafeAccess++`]] +:unsafeAccess-uint256---uint256: pass:normal[xref:#Arrays-unsafeAccess-uint256---uint256-[`++unsafeAccess++`]] +:unsafeMemoryAccess-address---uint256: pass:normal[xref:#Arrays-unsafeMemoryAccess-address---uint256-[`++unsafeMemoryAccess++`]] +:unsafeMemoryAccess-bytes32---uint256: pass:normal[xref:#Arrays-unsafeMemoryAccess-bytes32---uint256-[`++unsafeMemoryAccess++`]] +:unsafeMemoryAccess-uint256---uint256: pass:normal[xref:#Arrays-unsafeMemoryAccess-uint256---uint256-[`++unsafeMemoryAccess++`]] +:unsafeSetLength-address---uint256: pass:normal[xref:#Arrays-unsafeSetLength-address---uint256-[`++unsafeSetLength++`]] +:unsafeSetLength-bytes32---uint256: pass:normal[xref:#Arrays-unsafeSetLength-bytes32---uint256-[`++unsafeSetLength++`]] +:unsafeSetLength-uint256---uint256: pass:normal[xref:#Arrays-unsafeSetLength-uint256---uint256-[`++unsafeSetLength++`]] + [.contract] [[Arrays]] -=== `++Arrays++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Arrays.sol[{github-icon},role=heading-link] +=== `++Arrays++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Arrays.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -6116,7 +6817,7 @@ WARNING: Only use if you are certain `pos` is lower than the array length. [[Arrays-unsafeSetLength-address---uint256-]] ==== `[.contract-item-name]#++unsafeSetLength++#++(address[] array, uint256 len)++` [.item-kind]#internal# -Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. +Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. @@ -6124,7 +6825,7 @@ WARNING: this does not clear elements if length is reduced, of initialize elemen [[Arrays-unsafeSetLength-bytes32---uint256-]] ==== `[.contract-item-name]#++unsafeSetLength++#++(bytes32[] array, uint256 len)++` [.item-kind]#internal# -Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. +Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. @@ -6132,7 +6833,7 @@ WARNING: this does not clear elements if length is reduced, of initialize elemen [[Arrays-unsafeSetLength-uint256---uint256-]] ==== `[.contract-item-name]#++unsafeSetLength++#++(uint256[] array, uint256 len)++` [.item-kind]#internal# -Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. +Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden. WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. @@ -6141,9 +6842,12 @@ WARNING: this does not clear elements if length is reduced, of initialize elemen :encode: pass:normal[xref:#Base64-encode-bytes-[`++encode++`]] :encodeURL: pass:normal[xref:#Base64-encodeURL-bytes-[`++encodeURL++`]] +:encode-bytes: pass:normal[xref:#Base64-encode-bytes-[`++encode++`]] +:encodeURL-bytes: pass:normal[xref:#Base64-encodeURL-bytes-[`++encodeURL++`]] + [.contract] [[Base64]] -=== `++Base64++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Base64.sol[{github-icon},role=heading-link] +=== `++Base64++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Base64.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -6192,6 +6896,134 @@ See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648 [[Base64-_TABLE_URL-string]] ==== `string [.contract-item-name]#++_TABLE_URL++#` [.item-kind]#internal constant# +:indexOf: pass:normal[xref:#Bytes-indexOf-bytes-bytes1-[`++indexOf++`]] +:indexOf: pass:normal[xref:#Bytes-indexOf-bytes-bytes1-uint256-[`++indexOf++`]] +:lastIndexOf: pass:normal[xref:#Bytes-lastIndexOf-bytes-bytes1-[`++lastIndexOf++`]] +:lastIndexOf: pass:normal[xref:#Bytes-lastIndexOf-bytes-bytes1-uint256-[`++lastIndexOf++`]] +:slice: pass:normal[xref:#Bytes-slice-bytes-uint256-[`++slice++`]] +:slice: pass:normal[xref:#Bytes-slice-bytes-uint256-uint256-[`++slice++`]] + +:indexOf-bytes-bytes1: pass:normal[xref:#Bytes-indexOf-bytes-bytes1-[`++indexOf++`]] +:indexOf-bytes-bytes1-uint256: pass:normal[xref:#Bytes-indexOf-bytes-bytes1-uint256-[`++indexOf++`]] +:lastIndexOf-bytes-bytes1: pass:normal[xref:#Bytes-lastIndexOf-bytes-bytes1-[`++lastIndexOf++`]] +:lastIndexOf-bytes-bytes1-uint256: pass:normal[xref:#Bytes-lastIndexOf-bytes-bytes1-uint256-[`++lastIndexOf++`]] +:slice-bytes-uint256: pass:normal[xref:#Bytes-slice-bytes-uint256-[`++slice++`]] +:slice-bytes-uint256-uint256: pass:normal[xref:#Bytes-slice-bytes-uint256-uint256-[`++slice++`]] + +[.contract] +[[Bytes]] +=== `++Bytes++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Bytes.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/utils/Bytes.sol"; +``` + +Bytes operations. + +[.contract-index] +.Functions +-- +* {xref-Bytes-indexOf-bytes-bytes1-}[`++indexOf(buffer, s)++`] +* {xref-Bytes-indexOf-bytes-bytes1-uint256-}[`++indexOf(buffer, s, pos)++`] +* {xref-Bytes-lastIndexOf-bytes-bytes1-}[`++lastIndexOf(buffer, s)++`] +* {xref-Bytes-lastIndexOf-bytes-bytes1-uint256-}[`++lastIndexOf(buffer, s, pos)++`] +* {xref-Bytes-slice-bytes-uint256-}[`++slice(buffer, start)++`] +* {xref-Bytes-slice-bytes-uint256-uint256-}[`++slice(buffer, start, end)++`] + +-- + +[.contract-item] +[[Bytes-indexOf-bytes-bytes1-]] +==== `[.contract-item-name]#++indexOf++#++(bytes buffer, bytes1 s) → uint256++` [.item-kind]#internal# + +Forward search for `s` in `buffer` +* If `s` is present in the buffer, returns the index of the first instance +* If `s` is not present in the buffer, returns type(uint256).max + +NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf[Javascript's `Array.indexOf`] + +[.contract-item] +[[Bytes-indexOf-bytes-bytes1-uint256-]] +==== `[.contract-item-name]#++indexOf++#++(bytes buffer, bytes1 s, uint256 pos) → uint256++` [.item-kind]#internal# + +Forward search for `s` in `buffer` starting at position `pos` +* If `s` is present in the buffer (at or after `pos`), returns the index of the next instance +* If `s` is not present in the buffer (at or after `pos`), returns type(uint256).max + +NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf[Javascript's `Array.indexOf`] + +[.contract-item] +[[Bytes-lastIndexOf-bytes-bytes1-]] +==== `[.contract-item-name]#++lastIndexOf++#++(bytes buffer, bytes1 s) → uint256++` [.item-kind]#internal# + +Backward search for `s` in `buffer` +* If `s` is present in the buffer, returns the index of the last instance +* If `s` is not present in the buffer, returns type(uint256).max + +NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf[Javascript's `Array.lastIndexOf`] + +[.contract-item] +[[Bytes-lastIndexOf-bytes-bytes1-uint256-]] +==== `[.contract-item-name]#++lastIndexOf++#++(bytes buffer, bytes1 s, uint256 pos) → uint256++` [.item-kind]#internal# + +Backward search for `s` in `buffer` starting at position `pos` +* If `s` is present in the buffer (at or before `pos`), returns the index of the previous instance +* If `s` is not present in the buffer (at or before `pos`), returns type(uint256).max + +NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf[Javascript's `Array.lastIndexOf`] + +[.contract-item] +[[Bytes-slice-bytes-uint256-]] +==== `[.contract-item-name]#++slice++#++(bytes buffer, uint256 start) → bytes++` [.item-kind]#internal# + +Copies the content of `buffer`, from `start` (included) to the end of `buffer` into a new bytes object in +memory. + +NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`] + +[.contract-item] +[[Bytes-slice-bytes-uint256-uint256-]] +==== `[.contract-item-name]#++slice++#++(bytes buffer, uint256 start, uint256 end) → bytes++` [.item-kind]#internal# + +Copies the content of `buffer`, from `start` (included) to `end` (excluded) into a new bytes object in +memory. + +NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`] + +:emptyBytes: pass:normal[xref:#Calldata-emptyBytes--[`++emptyBytes++`]] +:emptyString: pass:normal[xref:#Calldata-emptyString--[`++emptyString++`]] + +:emptyBytes-: pass:normal[xref:#Calldata-emptyBytes--[`++emptyBytes++`]] +:emptyString-: pass:normal[xref:#Calldata-emptyString--[`++emptyString++`]] + +[.contract] +[[Calldata]] +=== `++Calldata++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Calldata.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/utils/Calldata.sol"; +``` + +Helper library for manipulating objects in calldata. + +[.contract-index] +.Functions +-- +* {xref-Calldata-emptyBytes--}[`++emptyBytes()++`] +* {xref-Calldata-emptyString--}[`++emptyString()++`] + +-- + +[.contract-item] +[[Calldata-emptyBytes--]] +==== `[.contract-item-name]#++emptyBytes++#++() → bytes result++` [.item-kind]#internal# + +[.contract-item] +[[Calldata-emptyString--]] +==== `[.contract-item-name]#++emptyString++#++() → string result++` [.item-kind]#internal# + :StringsInsufficientHexLength: pass:normal[xref:#Strings-StringsInsufficientHexLength-uint256-uint256-[`++StringsInsufficientHexLength++`]] :StringsInvalidChar: pass:normal[xref:#Strings-StringsInvalidChar--[`++StringsInvalidChar++`]] :StringsInvalidAddressFormat: pass:normal[xref:#Strings-StringsInvalidAddressFormat--[`++StringsInvalidAddressFormat++`]] @@ -6218,10 +7050,36 @@ See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648 :parseAddress: pass:normal[xref:#Strings-parseAddress-string-uint256-uint256-[`++parseAddress++`]] :tryParseAddress: pass:normal[xref:#Strings-tryParseAddress-string-[`++tryParseAddress++`]] :tryParseAddress: pass:normal[xref:#Strings-tryParseAddress-string-uint256-uint256-[`++tryParseAddress++`]] +:escapeJSON: pass:normal[xref:#Strings-escapeJSON-string-[`++escapeJSON++`]] + +:toString-uint256: pass:normal[xref:#Strings-toString-uint256-[`++toString++`]] +:toStringSigned-int256: pass:normal[xref:#Strings-toStringSigned-int256-[`++toStringSigned++`]] +:toHexString-uint256: pass:normal[xref:#Strings-toHexString-uint256-[`++toHexString++`]] +:toHexString-uint256-uint256: pass:normal[xref:#Strings-toHexString-uint256-uint256-[`++toHexString++`]] +:toHexString-address: pass:normal[xref:#Strings-toHexString-address-[`++toHexString++`]] +:toChecksumHexString-address: pass:normal[xref:#Strings-toChecksumHexString-address-[`++toChecksumHexString++`]] +:equal-string-string: pass:normal[xref:#Strings-equal-string-string-[`++equal++`]] +:parseUint-string: pass:normal[xref:#Strings-parseUint-string-[`++parseUint++`]] +:parseUint-string-uint256-uint256: pass:normal[xref:#Strings-parseUint-string-uint256-uint256-[`++parseUint++`]] +:tryParseUint-string: pass:normal[xref:#Strings-tryParseUint-string-[`++tryParseUint++`]] +:tryParseUint-string-uint256-uint256: pass:normal[xref:#Strings-tryParseUint-string-uint256-uint256-[`++tryParseUint++`]] +:parseInt-string: pass:normal[xref:#Strings-parseInt-string-[`++parseInt++`]] +:parseInt-string-uint256-uint256: pass:normal[xref:#Strings-parseInt-string-uint256-uint256-[`++parseInt++`]] +:tryParseInt-string: pass:normal[xref:#Strings-tryParseInt-string-[`++tryParseInt++`]] +:tryParseInt-string-uint256-uint256: pass:normal[xref:#Strings-tryParseInt-string-uint256-uint256-[`++tryParseInt++`]] +:parseHexUint-string: pass:normal[xref:#Strings-parseHexUint-string-[`++parseHexUint++`]] +:parseHexUint-string-uint256-uint256: pass:normal[xref:#Strings-parseHexUint-string-uint256-uint256-[`++parseHexUint++`]] +:tryParseHexUint-string: pass:normal[xref:#Strings-tryParseHexUint-string-[`++tryParseHexUint++`]] +:tryParseHexUint-string-uint256-uint256: pass:normal[xref:#Strings-tryParseHexUint-string-uint256-uint256-[`++tryParseHexUint++`]] +:parseAddress-string: pass:normal[xref:#Strings-parseAddress-string-[`++parseAddress++`]] +:parseAddress-string-uint256-uint256: pass:normal[xref:#Strings-parseAddress-string-uint256-uint256-[`++parseAddress++`]] +:tryParseAddress-string: pass:normal[xref:#Strings-tryParseAddress-string-[`++tryParseAddress++`]] +:tryParseAddress-string-uint256-uint256: pass:normal[xref:#Strings-tryParseAddress-string-uint256-uint256-[`++tryParseAddress++`]] +:escapeJSON-string: pass:normal[xref:#Strings-escapeJSON-string-[`++escapeJSON++`]] [.contract] [[Strings]] -=== `++Strings++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Strings.sol[{github-icon},role=heading-link] +=== `++Strings++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Strings.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -6256,6 +7114,7 @@ String operations. * {xref-Strings-parseAddress-string-uint256-uint256-}[`++parseAddress(input, begin, end)++`] * {xref-Strings-tryParseAddress-string-}[`++tryParseAddress(input)++`] * {xref-Strings-tryParseAddress-string-uint256-uint256-}[`++tryParseAddress(input, begin, end)++`] +* {xref-Strings-escapeJSON-string-}[`++escapeJSON(input)++`] -- @@ -6326,7 +7185,7 @@ Requirements: [[Strings-parseUint-string-uint256-uint256-]] ==== `[.contract-item-name]#++parseUint++#++(string input, uint256 begin, uint256 end) → uint256++` [.item-kind]#internal# -Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and +Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and `end` (excluded). Requirements: @@ -6403,7 +7262,7 @@ Requirements: [[Strings-parseHexUint-string-uint256-uint256-]] ==== `[.contract-item-name]#++parseHexUint++#++(string input, uint256 begin, uint256 end) → uint256++` [.item-kind]#internal# -Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and +Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and `end` (excluded). Requirements: @@ -6440,7 +7299,7 @@ Requirements: [[Strings-parseAddress-string-uint256-uint256-]] ==== `[.contract-item-name]#++parseAddress++#++(string input, uint256 begin, uint256 end) → address++` [.item-kind]#internal# -Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and +Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and `end` (excluded). Requirements: @@ -6451,14 +7310,26 @@ Requirements: ==== `[.contract-item-name]#++tryParseAddress++#++(string input) → bool success, address value++` [.item-kind]#internal# Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly -formatted address. See {parseAddress} requirements. +formatted address. See {parseAddress-string} requirements. [.contract-item] [[Strings-tryParseAddress-string-uint256-uint256-]] ==== `[.contract-item-name]#++tryParseAddress++#++(string input, uint256 begin, uint256 end) → bool success, address value++` [.item-kind]#internal# Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly -formatted address. See {parseAddress} requirements. +formatted address. See {parseAddress-string-uint256-uint256} requirements. + +[.contract-item] +[[Strings-escapeJSON-string-]] +==== `[.contract-item-name]#++escapeJSON++#++(string input) → string++` [.item-kind]#internal# + +Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata. + +WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped. + +NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of +RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode +characters that are not in this range, but other tooling may provide different results. [.contract-item] [[Strings-StringsInsufficientHexLength-uint256-uint256-]] @@ -6487,9 +7358,16 @@ The string being parsed is not a properly formatted address. :toStringWithFallback: pass:normal[xref:#ShortStrings-toStringWithFallback-ShortString-string-[`++toStringWithFallback++`]] :byteLengthWithFallback: pass:normal[xref:#ShortStrings-byteLengthWithFallback-ShortString-string-[`++byteLengthWithFallback++`]] +:toShortString-string: pass:normal[xref:#ShortStrings-toShortString-string-[`++toShortString++`]] +:toString-ShortString: pass:normal[xref:#ShortStrings-toString-ShortString-[`++toString++`]] +:byteLength-ShortString: pass:normal[xref:#ShortStrings-byteLength-ShortString-[`++byteLength++`]] +:toShortStringWithFallback-string-string: pass:normal[xref:#ShortStrings-toShortStringWithFallback-string-string-[`++toShortStringWithFallback++`]] +:toStringWithFallback-ShortString-string: pass:normal[xref:#ShortStrings-toStringWithFallback-ShortString-string-[`++toStringWithFallback++`]] +:byteLengthWithFallback-ShortString-string: pass:normal[xref:#ShortStrings-byteLengthWithFallback-ShortString-string-[`++byteLengthWithFallback++`]] + [.contract] [[ShortStrings]] -=== `++ShortStrings++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/ShortStrings.sol[{github-icon},role=heading-link] +=== `++ShortStrings++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/ShortStrings.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -6573,14 +7451,14 @@ Encode a string into a `ShortString`, or write it to storage if it is too long. [[ShortStrings-toStringWithFallback-ShortString-string-]] ==== `[.contract-item-name]#++toStringWithFallback++#++(ShortString value, string store) → string++` [.item-kind]#internal# -Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. +Decode a string that was encoded to `ShortString` or written to storage using {toShortStringWithFallback}. [.contract-item] [[ShortStrings-byteLengthWithFallback-ShortString-string-]] ==== `[.contract-item-name]#++byteLengthWithFallback++#++(ShortString value, string store) → uint256++` [.item-kind]#internal# Return the length of a string that was encoded to `ShortString` or written to storage using -{setWithFallback}. +{toShortStringWithFallback}. WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of actual characters as the UTF-8 encoding of a single character can span over multiple bytes. @@ -6604,9 +7482,20 @@ actual characters as the UTF-8 encoding of a single character can span over mult :deriveMapping: pass:normal[xref:#SlotDerivation-deriveMapping-bytes32-string-[`++deriveMapping++`]] :deriveMapping: pass:normal[xref:#SlotDerivation-deriveMapping-bytes32-bytes-[`++deriveMapping++`]] +:erc7201Slot-string: pass:normal[xref:#SlotDerivation-erc7201Slot-string-[`++erc7201Slot++`]] +:offset-bytes32-uint256: pass:normal[xref:#SlotDerivation-offset-bytes32-uint256-[`++offset++`]] +:deriveArray-bytes32: pass:normal[xref:#SlotDerivation-deriveArray-bytes32-[`++deriveArray++`]] +:deriveMapping-bytes32-address: pass:normal[xref:#SlotDerivation-deriveMapping-bytes32-address-[`++deriveMapping++`]] +:deriveMapping-bytes32-bool: pass:normal[xref:#SlotDerivation-deriveMapping-bytes32-bool-[`++deriveMapping++`]] +:deriveMapping-bytes32-bytes32: pass:normal[xref:#SlotDerivation-deriveMapping-bytes32-bytes32-[`++deriveMapping++`]] +:deriveMapping-bytes32-uint256: pass:normal[xref:#SlotDerivation-deriveMapping-bytes32-uint256-[`++deriveMapping++`]] +:deriveMapping-bytes32-int256: pass:normal[xref:#SlotDerivation-deriveMapping-bytes32-int256-[`++deriveMapping++`]] +:deriveMapping-bytes32-string: pass:normal[xref:#SlotDerivation-deriveMapping-bytes32-string-[`++deriveMapping++`]] +:deriveMapping-bytes32-bytes: pass:normal[xref:#SlotDerivation-deriveMapping-bytes32-bytes-[`++deriveMapping++`]] + [.contract] [[SlotDerivation]] -=== `++SlotDerivation++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/SlotDerivation.sol[{github-icon},role=heading-link] +=== `++SlotDerivation++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/SlotDerivation.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -6627,7 +7516,7 @@ contract Example { using SlotDerivation for bytes32; // Declare a namespace - string private constant _NAMESPACE = "" // eg. OpenZeppelin.Slot + string private constant _NAMESPACE = ""; // eg. OpenZeppelin.Slot function setValueInNamespace(uint256 key, address newValue) internal { _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue; @@ -6739,9 +7628,19 @@ Derive the location of a mapping element from the key. :getBytesSlot: pass:normal[xref:#StorageSlot-getBytesSlot-bytes32-[`++getBytesSlot++`]] :getBytesSlot: pass:normal[xref:#StorageSlot-getBytesSlot-bytes-[`++getBytesSlot++`]] +:getAddressSlot-bytes32: pass:normal[xref:#StorageSlot-getAddressSlot-bytes32-[`++getAddressSlot++`]] +:getBooleanSlot-bytes32: pass:normal[xref:#StorageSlot-getBooleanSlot-bytes32-[`++getBooleanSlot++`]] +:getBytes32Slot-bytes32: pass:normal[xref:#StorageSlot-getBytes32Slot-bytes32-[`++getBytes32Slot++`]] +:getUint256Slot-bytes32: pass:normal[xref:#StorageSlot-getUint256Slot-bytes32-[`++getUint256Slot++`]] +:getInt256Slot-bytes32: pass:normal[xref:#StorageSlot-getInt256Slot-bytes32-[`++getInt256Slot++`]] +:getStringSlot-bytes32: pass:normal[xref:#StorageSlot-getStringSlot-bytes32-[`++getStringSlot++`]] +:getStringSlot-string: pass:normal[xref:#StorageSlot-getStringSlot-string-[`++getStringSlot++`]] +:getBytesSlot-bytes32: pass:normal[xref:#StorageSlot-getBytesSlot-bytes32-[`++getBytesSlot++`]] +:getBytesSlot-bytes: pass:normal[xref:#StorageSlot-getBytesSlot-bytes-[`++getBytesSlot++`]] + [.contract] [[StorageSlot]] -=== `++StorageSlot++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/StorageSlot.sol[{github-icon},role=heading-link] +=== `++StorageSlot++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/StorageSlot.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -6864,9 +7763,25 @@ Returns an `BytesSlot` representation of the bytes storage pointer `store`. :tload: pass:normal[xref:#TransientSlot-tload-TransientSlot-Int256Slot-[`++tload++`]] :tstore: pass:normal[xref:#TransientSlot-tstore-TransientSlot-Int256Slot-int256-[`++tstore++`]] +:asAddress-bytes32: pass:normal[xref:#TransientSlot-asAddress-bytes32-[`++asAddress++`]] +:asBoolean-bytes32: pass:normal[xref:#TransientSlot-asBoolean-bytes32-[`++asBoolean++`]] +:asBytes32-bytes32: pass:normal[xref:#TransientSlot-asBytes32-bytes32-[`++asBytes32++`]] +:asUint256-bytes32: pass:normal[xref:#TransientSlot-asUint256-bytes32-[`++asUint256++`]] +:asInt256-bytes32: pass:normal[xref:#TransientSlot-asInt256-bytes32-[`++asInt256++`]] +:tload-TransientSlot-AddressSlot: pass:normal[xref:#TransientSlot-tload-TransientSlot-AddressSlot-[`++tload++`]] +:tstore-TransientSlot-AddressSlot-address: pass:normal[xref:#TransientSlot-tstore-TransientSlot-AddressSlot-address-[`++tstore++`]] +:tload-TransientSlot-BooleanSlot: pass:normal[xref:#TransientSlot-tload-TransientSlot-BooleanSlot-[`++tload++`]] +:tstore-TransientSlot-BooleanSlot-bool: pass:normal[xref:#TransientSlot-tstore-TransientSlot-BooleanSlot-bool-[`++tstore++`]] +:tload-TransientSlot-Bytes32Slot: pass:normal[xref:#TransientSlot-tload-TransientSlot-Bytes32Slot-[`++tload++`]] +:tstore-TransientSlot-Bytes32Slot-bytes32: pass:normal[xref:#TransientSlot-tstore-TransientSlot-Bytes32Slot-bytes32-[`++tstore++`]] +:tload-TransientSlot-Uint256Slot: pass:normal[xref:#TransientSlot-tload-TransientSlot-Uint256Slot-[`++tload++`]] +:tstore-TransientSlot-Uint256Slot-uint256: pass:normal[xref:#TransientSlot-tstore-TransientSlot-Uint256Slot-uint256-[`++tstore++`]] +:tload-TransientSlot-Int256Slot: pass:normal[xref:#TransientSlot-tload-TransientSlot-Int256Slot-[`++tload++`]] +:tstore-TransientSlot-Int256Slot-int256: pass:normal[xref:#TransientSlot-tstore-TransientSlot-Int256Slot-int256-[`++tstore++`]] + [.contract] [[TransientSlot]] -=== `++TransientSlot++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/TransientSlot.sol[{github-icon},role=heading-link] +=== `++TransientSlot++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/TransientSlot.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -7011,9 +7926,11 @@ Store `value` at location `slot` in transient storage. :multicall: pass:normal[xref:#Multicall-multicall-bytes---[`++multicall++`]] +:multicall-bytes--: pass:normal[xref:#Multicall-multicall-bytes---[`++multicall++`]] + [.contract] [[Multicall]] -=== `++Multicall++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Multicall.sol[{github-icon},role=heading-link] +=== `++Multicall++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Multicall.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -7026,10 +7943,10 @@ Consider any assumption about calldata validation performed by the sender may be careful about sending transactions invoking {multicall}. For example, a relay address that filters function selectors won't filter calls nested within a {multicall} operation. -NOTE: Since 5.0.1 and 4.9.4, this contract identifies non-canonical contexts (i.e. `msg.sender` is not {_msgSender}). +NOTE: Since 5.0.1 and 4.9.4, this contract identifies non-canonical contexts (i.e. `msg.sender` is not {Context-_msgSender}). If a non-canonical context is identified, the following self `delegatecall` appends the last bytes of `msg.data` to the subcall. This makes it safe to use with {ERC2771Context}. Contexts that don't affect the resolution of -{_msgSender} are not propagated to subcalls. +{Context-_msgSender} are not propagated to subcalls. [.contract-index] .Functions @@ -7048,9 +7965,13 @@ Receives and executes a batch of function calls on this contract. :_msgData: pass:normal[xref:#Context-_msgData--[`++_msgData++`]] :_contextSuffixLength: pass:normal[xref:#Context-_contextSuffixLength--[`++_contextSuffixLength++`]] +:_msgSender-: pass:normal[xref:#Context-_msgSender--[`++_msgSender++`]] +:_msgData-: pass:normal[xref:#Context-_msgData--[`++_msgData++`]] +:_contextSuffixLength-: pass:normal[xref:#Context-_contextSuffixLength--[`++_contextSuffixLength++`]] + [.contract] [[Context]] -=== `++Context++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Context.sol[{github-icon},role=heading-link] +=== `++Context++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Context.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -7301,9 +8222,222 @@ This contract is only required for intermediate, library-like contracts. :extract_32_28: pass:normal[xref:#Packing-extract_32_28-bytes32-uint8-[`++extract_32_28++`]] :replace_32_28: pass:normal[xref:#Packing-replace_32_28-bytes32-bytes28-uint8-[`++replace_32_28++`]] +:pack_1_1-bytes1-bytes1: pass:normal[xref:#Packing-pack_1_1-bytes1-bytes1-[`++pack_1_1++`]] +:pack_2_2-bytes2-bytes2: pass:normal[xref:#Packing-pack_2_2-bytes2-bytes2-[`++pack_2_2++`]] +:pack_2_4-bytes2-bytes4: pass:normal[xref:#Packing-pack_2_4-bytes2-bytes4-[`++pack_2_4++`]] +:pack_2_6-bytes2-bytes6: pass:normal[xref:#Packing-pack_2_6-bytes2-bytes6-[`++pack_2_6++`]] +:pack_2_8-bytes2-bytes8: pass:normal[xref:#Packing-pack_2_8-bytes2-bytes8-[`++pack_2_8++`]] +:pack_2_10-bytes2-bytes10: pass:normal[xref:#Packing-pack_2_10-bytes2-bytes10-[`++pack_2_10++`]] +:pack_2_20-bytes2-bytes20: pass:normal[xref:#Packing-pack_2_20-bytes2-bytes20-[`++pack_2_20++`]] +:pack_2_22-bytes2-bytes22: pass:normal[xref:#Packing-pack_2_22-bytes2-bytes22-[`++pack_2_22++`]] +:pack_4_2-bytes4-bytes2: pass:normal[xref:#Packing-pack_4_2-bytes4-bytes2-[`++pack_4_2++`]] +:pack_4_4-bytes4-bytes4: pass:normal[xref:#Packing-pack_4_4-bytes4-bytes4-[`++pack_4_4++`]] +:pack_4_6-bytes4-bytes6: pass:normal[xref:#Packing-pack_4_6-bytes4-bytes6-[`++pack_4_6++`]] +:pack_4_8-bytes4-bytes8: pass:normal[xref:#Packing-pack_4_8-bytes4-bytes8-[`++pack_4_8++`]] +:pack_4_12-bytes4-bytes12: pass:normal[xref:#Packing-pack_4_12-bytes4-bytes12-[`++pack_4_12++`]] +:pack_4_16-bytes4-bytes16: pass:normal[xref:#Packing-pack_4_16-bytes4-bytes16-[`++pack_4_16++`]] +:pack_4_20-bytes4-bytes20: pass:normal[xref:#Packing-pack_4_20-bytes4-bytes20-[`++pack_4_20++`]] +:pack_4_24-bytes4-bytes24: pass:normal[xref:#Packing-pack_4_24-bytes4-bytes24-[`++pack_4_24++`]] +:pack_4_28-bytes4-bytes28: pass:normal[xref:#Packing-pack_4_28-bytes4-bytes28-[`++pack_4_28++`]] +:pack_6_2-bytes6-bytes2: pass:normal[xref:#Packing-pack_6_2-bytes6-bytes2-[`++pack_6_2++`]] +:pack_6_4-bytes6-bytes4: pass:normal[xref:#Packing-pack_6_4-bytes6-bytes4-[`++pack_6_4++`]] +:pack_6_6-bytes6-bytes6: pass:normal[xref:#Packing-pack_6_6-bytes6-bytes6-[`++pack_6_6++`]] +:pack_6_10-bytes6-bytes10: pass:normal[xref:#Packing-pack_6_10-bytes6-bytes10-[`++pack_6_10++`]] +:pack_6_16-bytes6-bytes16: pass:normal[xref:#Packing-pack_6_16-bytes6-bytes16-[`++pack_6_16++`]] +:pack_6_22-bytes6-bytes22: pass:normal[xref:#Packing-pack_6_22-bytes6-bytes22-[`++pack_6_22++`]] +:pack_8_2-bytes8-bytes2: pass:normal[xref:#Packing-pack_8_2-bytes8-bytes2-[`++pack_8_2++`]] +:pack_8_4-bytes8-bytes4: pass:normal[xref:#Packing-pack_8_4-bytes8-bytes4-[`++pack_8_4++`]] +:pack_8_8-bytes8-bytes8: pass:normal[xref:#Packing-pack_8_8-bytes8-bytes8-[`++pack_8_8++`]] +:pack_8_12-bytes8-bytes12: pass:normal[xref:#Packing-pack_8_12-bytes8-bytes12-[`++pack_8_12++`]] +:pack_8_16-bytes8-bytes16: pass:normal[xref:#Packing-pack_8_16-bytes8-bytes16-[`++pack_8_16++`]] +:pack_8_20-bytes8-bytes20: pass:normal[xref:#Packing-pack_8_20-bytes8-bytes20-[`++pack_8_20++`]] +:pack_8_24-bytes8-bytes24: pass:normal[xref:#Packing-pack_8_24-bytes8-bytes24-[`++pack_8_24++`]] +:pack_10_2-bytes10-bytes2: pass:normal[xref:#Packing-pack_10_2-bytes10-bytes2-[`++pack_10_2++`]] +:pack_10_6-bytes10-bytes6: pass:normal[xref:#Packing-pack_10_6-bytes10-bytes6-[`++pack_10_6++`]] +:pack_10_10-bytes10-bytes10: pass:normal[xref:#Packing-pack_10_10-bytes10-bytes10-[`++pack_10_10++`]] +:pack_10_12-bytes10-bytes12: pass:normal[xref:#Packing-pack_10_12-bytes10-bytes12-[`++pack_10_12++`]] +:pack_10_22-bytes10-bytes22: pass:normal[xref:#Packing-pack_10_22-bytes10-bytes22-[`++pack_10_22++`]] +:pack_12_4-bytes12-bytes4: pass:normal[xref:#Packing-pack_12_4-bytes12-bytes4-[`++pack_12_4++`]] +:pack_12_8-bytes12-bytes8: pass:normal[xref:#Packing-pack_12_8-bytes12-bytes8-[`++pack_12_8++`]] +:pack_12_10-bytes12-bytes10: pass:normal[xref:#Packing-pack_12_10-bytes12-bytes10-[`++pack_12_10++`]] +:pack_12_12-bytes12-bytes12: pass:normal[xref:#Packing-pack_12_12-bytes12-bytes12-[`++pack_12_12++`]] +:pack_12_16-bytes12-bytes16: pass:normal[xref:#Packing-pack_12_16-bytes12-bytes16-[`++pack_12_16++`]] +:pack_12_20-bytes12-bytes20: pass:normal[xref:#Packing-pack_12_20-bytes12-bytes20-[`++pack_12_20++`]] +:pack_16_4-bytes16-bytes4: pass:normal[xref:#Packing-pack_16_4-bytes16-bytes4-[`++pack_16_4++`]] +:pack_16_6-bytes16-bytes6: pass:normal[xref:#Packing-pack_16_6-bytes16-bytes6-[`++pack_16_6++`]] +:pack_16_8-bytes16-bytes8: pass:normal[xref:#Packing-pack_16_8-bytes16-bytes8-[`++pack_16_8++`]] +:pack_16_12-bytes16-bytes12: pass:normal[xref:#Packing-pack_16_12-bytes16-bytes12-[`++pack_16_12++`]] +:pack_16_16-bytes16-bytes16: pass:normal[xref:#Packing-pack_16_16-bytes16-bytes16-[`++pack_16_16++`]] +:pack_20_2-bytes20-bytes2: pass:normal[xref:#Packing-pack_20_2-bytes20-bytes2-[`++pack_20_2++`]] +:pack_20_4-bytes20-bytes4: pass:normal[xref:#Packing-pack_20_4-bytes20-bytes4-[`++pack_20_4++`]] +:pack_20_8-bytes20-bytes8: pass:normal[xref:#Packing-pack_20_8-bytes20-bytes8-[`++pack_20_8++`]] +:pack_20_12-bytes20-bytes12: pass:normal[xref:#Packing-pack_20_12-bytes20-bytes12-[`++pack_20_12++`]] +:pack_22_2-bytes22-bytes2: pass:normal[xref:#Packing-pack_22_2-bytes22-bytes2-[`++pack_22_2++`]] +:pack_22_6-bytes22-bytes6: pass:normal[xref:#Packing-pack_22_6-bytes22-bytes6-[`++pack_22_6++`]] +:pack_22_10-bytes22-bytes10: pass:normal[xref:#Packing-pack_22_10-bytes22-bytes10-[`++pack_22_10++`]] +:pack_24_4-bytes24-bytes4: pass:normal[xref:#Packing-pack_24_4-bytes24-bytes4-[`++pack_24_4++`]] +:pack_24_8-bytes24-bytes8: pass:normal[xref:#Packing-pack_24_8-bytes24-bytes8-[`++pack_24_8++`]] +:pack_28_4-bytes28-bytes4: pass:normal[xref:#Packing-pack_28_4-bytes28-bytes4-[`++pack_28_4++`]] +:extract_2_1-bytes2-uint8: pass:normal[xref:#Packing-extract_2_1-bytes2-uint8-[`++extract_2_1++`]] +:replace_2_1-bytes2-bytes1-uint8: pass:normal[xref:#Packing-replace_2_1-bytes2-bytes1-uint8-[`++replace_2_1++`]] +:extract_4_1-bytes4-uint8: pass:normal[xref:#Packing-extract_4_1-bytes4-uint8-[`++extract_4_1++`]] +:replace_4_1-bytes4-bytes1-uint8: pass:normal[xref:#Packing-replace_4_1-bytes4-bytes1-uint8-[`++replace_4_1++`]] +:extract_4_2-bytes4-uint8: pass:normal[xref:#Packing-extract_4_2-bytes4-uint8-[`++extract_4_2++`]] +:replace_4_2-bytes4-bytes2-uint8: pass:normal[xref:#Packing-replace_4_2-bytes4-bytes2-uint8-[`++replace_4_2++`]] +:extract_6_1-bytes6-uint8: pass:normal[xref:#Packing-extract_6_1-bytes6-uint8-[`++extract_6_1++`]] +:replace_6_1-bytes6-bytes1-uint8: pass:normal[xref:#Packing-replace_6_1-bytes6-bytes1-uint8-[`++replace_6_1++`]] +:extract_6_2-bytes6-uint8: pass:normal[xref:#Packing-extract_6_2-bytes6-uint8-[`++extract_6_2++`]] +:replace_6_2-bytes6-bytes2-uint8: pass:normal[xref:#Packing-replace_6_2-bytes6-bytes2-uint8-[`++replace_6_2++`]] +:extract_6_4-bytes6-uint8: pass:normal[xref:#Packing-extract_6_4-bytes6-uint8-[`++extract_6_4++`]] +:replace_6_4-bytes6-bytes4-uint8: pass:normal[xref:#Packing-replace_6_4-bytes6-bytes4-uint8-[`++replace_6_4++`]] +:extract_8_1-bytes8-uint8: pass:normal[xref:#Packing-extract_8_1-bytes8-uint8-[`++extract_8_1++`]] +:replace_8_1-bytes8-bytes1-uint8: pass:normal[xref:#Packing-replace_8_1-bytes8-bytes1-uint8-[`++replace_8_1++`]] +:extract_8_2-bytes8-uint8: pass:normal[xref:#Packing-extract_8_2-bytes8-uint8-[`++extract_8_2++`]] +:replace_8_2-bytes8-bytes2-uint8: pass:normal[xref:#Packing-replace_8_2-bytes8-bytes2-uint8-[`++replace_8_2++`]] +:extract_8_4-bytes8-uint8: pass:normal[xref:#Packing-extract_8_4-bytes8-uint8-[`++extract_8_4++`]] +:replace_8_4-bytes8-bytes4-uint8: pass:normal[xref:#Packing-replace_8_4-bytes8-bytes4-uint8-[`++replace_8_4++`]] +:extract_8_6-bytes8-uint8: pass:normal[xref:#Packing-extract_8_6-bytes8-uint8-[`++extract_8_6++`]] +:replace_8_6-bytes8-bytes6-uint8: pass:normal[xref:#Packing-replace_8_6-bytes8-bytes6-uint8-[`++replace_8_6++`]] +:extract_10_1-bytes10-uint8: pass:normal[xref:#Packing-extract_10_1-bytes10-uint8-[`++extract_10_1++`]] +:replace_10_1-bytes10-bytes1-uint8: pass:normal[xref:#Packing-replace_10_1-bytes10-bytes1-uint8-[`++replace_10_1++`]] +:extract_10_2-bytes10-uint8: pass:normal[xref:#Packing-extract_10_2-bytes10-uint8-[`++extract_10_2++`]] +:replace_10_2-bytes10-bytes2-uint8: pass:normal[xref:#Packing-replace_10_2-bytes10-bytes2-uint8-[`++replace_10_2++`]] +:extract_10_4-bytes10-uint8: pass:normal[xref:#Packing-extract_10_4-bytes10-uint8-[`++extract_10_4++`]] +:replace_10_4-bytes10-bytes4-uint8: pass:normal[xref:#Packing-replace_10_4-bytes10-bytes4-uint8-[`++replace_10_4++`]] +:extract_10_6-bytes10-uint8: pass:normal[xref:#Packing-extract_10_6-bytes10-uint8-[`++extract_10_6++`]] +:replace_10_6-bytes10-bytes6-uint8: pass:normal[xref:#Packing-replace_10_6-bytes10-bytes6-uint8-[`++replace_10_6++`]] +:extract_10_8-bytes10-uint8: pass:normal[xref:#Packing-extract_10_8-bytes10-uint8-[`++extract_10_8++`]] +:replace_10_8-bytes10-bytes8-uint8: pass:normal[xref:#Packing-replace_10_8-bytes10-bytes8-uint8-[`++replace_10_8++`]] +:extract_12_1-bytes12-uint8: pass:normal[xref:#Packing-extract_12_1-bytes12-uint8-[`++extract_12_1++`]] +:replace_12_1-bytes12-bytes1-uint8: pass:normal[xref:#Packing-replace_12_1-bytes12-bytes1-uint8-[`++replace_12_1++`]] +:extract_12_2-bytes12-uint8: pass:normal[xref:#Packing-extract_12_2-bytes12-uint8-[`++extract_12_2++`]] +:replace_12_2-bytes12-bytes2-uint8: pass:normal[xref:#Packing-replace_12_2-bytes12-bytes2-uint8-[`++replace_12_2++`]] +:extract_12_4-bytes12-uint8: pass:normal[xref:#Packing-extract_12_4-bytes12-uint8-[`++extract_12_4++`]] +:replace_12_4-bytes12-bytes4-uint8: pass:normal[xref:#Packing-replace_12_4-bytes12-bytes4-uint8-[`++replace_12_4++`]] +:extract_12_6-bytes12-uint8: pass:normal[xref:#Packing-extract_12_6-bytes12-uint8-[`++extract_12_6++`]] +:replace_12_6-bytes12-bytes6-uint8: pass:normal[xref:#Packing-replace_12_6-bytes12-bytes6-uint8-[`++replace_12_6++`]] +:extract_12_8-bytes12-uint8: pass:normal[xref:#Packing-extract_12_8-bytes12-uint8-[`++extract_12_8++`]] +:replace_12_8-bytes12-bytes8-uint8: pass:normal[xref:#Packing-replace_12_8-bytes12-bytes8-uint8-[`++replace_12_8++`]] +:extract_12_10-bytes12-uint8: pass:normal[xref:#Packing-extract_12_10-bytes12-uint8-[`++extract_12_10++`]] +:replace_12_10-bytes12-bytes10-uint8: pass:normal[xref:#Packing-replace_12_10-bytes12-bytes10-uint8-[`++replace_12_10++`]] +:extract_16_1-bytes16-uint8: pass:normal[xref:#Packing-extract_16_1-bytes16-uint8-[`++extract_16_1++`]] +:replace_16_1-bytes16-bytes1-uint8: pass:normal[xref:#Packing-replace_16_1-bytes16-bytes1-uint8-[`++replace_16_1++`]] +:extract_16_2-bytes16-uint8: pass:normal[xref:#Packing-extract_16_2-bytes16-uint8-[`++extract_16_2++`]] +:replace_16_2-bytes16-bytes2-uint8: pass:normal[xref:#Packing-replace_16_2-bytes16-bytes2-uint8-[`++replace_16_2++`]] +:extract_16_4-bytes16-uint8: pass:normal[xref:#Packing-extract_16_4-bytes16-uint8-[`++extract_16_4++`]] +:replace_16_4-bytes16-bytes4-uint8: pass:normal[xref:#Packing-replace_16_4-bytes16-bytes4-uint8-[`++replace_16_4++`]] +:extract_16_6-bytes16-uint8: pass:normal[xref:#Packing-extract_16_6-bytes16-uint8-[`++extract_16_6++`]] +:replace_16_6-bytes16-bytes6-uint8: pass:normal[xref:#Packing-replace_16_6-bytes16-bytes6-uint8-[`++replace_16_6++`]] +:extract_16_8-bytes16-uint8: pass:normal[xref:#Packing-extract_16_8-bytes16-uint8-[`++extract_16_8++`]] +:replace_16_8-bytes16-bytes8-uint8: pass:normal[xref:#Packing-replace_16_8-bytes16-bytes8-uint8-[`++replace_16_8++`]] +:extract_16_10-bytes16-uint8: pass:normal[xref:#Packing-extract_16_10-bytes16-uint8-[`++extract_16_10++`]] +:replace_16_10-bytes16-bytes10-uint8: pass:normal[xref:#Packing-replace_16_10-bytes16-bytes10-uint8-[`++replace_16_10++`]] +:extract_16_12-bytes16-uint8: pass:normal[xref:#Packing-extract_16_12-bytes16-uint8-[`++extract_16_12++`]] +:replace_16_12-bytes16-bytes12-uint8: pass:normal[xref:#Packing-replace_16_12-bytes16-bytes12-uint8-[`++replace_16_12++`]] +:extract_20_1-bytes20-uint8: pass:normal[xref:#Packing-extract_20_1-bytes20-uint8-[`++extract_20_1++`]] +:replace_20_1-bytes20-bytes1-uint8: pass:normal[xref:#Packing-replace_20_1-bytes20-bytes1-uint8-[`++replace_20_1++`]] +:extract_20_2-bytes20-uint8: pass:normal[xref:#Packing-extract_20_2-bytes20-uint8-[`++extract_20_2++`]] +:replace_20_2-bytes20-bytes2-uint8: pass:normal[xref:#Packing-replace_20_2-bytes20-bytes2-uint8-[`++replace_20_2++`]] +:extract_20_4-bytes20-uint8: pass:normal[xref:#Packing-extract_20_4-bytes20-uint8-[`++extract_20_4++`]] +:replace_20_4-bytes20-bytes4-uint8: pass:normal[xref:#Packing-replace_20_4-bytes20-bytes4-uint8-[`++replace_20_4++`]] +:extract_20_6-bytes20-uint8: pass:normal[xref:#Packing-extract_20_6-bytes20-uint8-[`++extract_20_6++`]] +:replace_20_6-bytes20-bytes6-uint8: pass:normal[xref:#Packing-replace_20_6-bytes20-bytes6-uint8-[`++replace_20_6++`]] +:extract_20_8-bytes20-uint8: pass:normal[xref:#Packing-extract_20_8-bytes20-uint8-[`++extract_20_8++`]] +:replace_20_8-bytes20-bytes8-uint8: pass:normal[xref:#Packing-replace_20_8-bytes20-bytes8-uint8-[`++replace_20_8++`]] +:extract_20_10-bytes20-uint8: pass:normal[xref:#Packing-extract_20_10-bytes20-uint8-[`++extract_20_10++`]] +:replace_20_10-bytes20-bytes10-uint8: pass:normal[xref:#Packing-replace_20_10-bytes20-bytes10-uint8-[`++replace_20_10++`]] +:extract_20_12-bytes20-uint8: pass:normal[xref:#Packing-extract_20_12-bytes20-uint8-[`++extract_20_12++`]] +:replace_20_12-bytes20-bytes12-uint8: pass:normal[xref:#Packing-replace_20_12-bytes20-bytes12-uint8-[`++replace_20_12++`]] +:extract_20_16-bytes20-uint8: pass:normal[xref:#Packing-extract_20_16-bytes20-uint8-[`++extract_20_16++`]] +:replace_20_16-bytes20-bytes16-uint8: pass:normal[xref:#Packing-replace_20_16-bytes20-bytes16-uint8-[`++replace_20_16++`]] +:extract_22_1-bytes22-uint8: pass:normal[xref:#Packing-extract_22_1-bytes22-uint8-[`++extract_22_1++`]] +:replace_22_1-bytes22-bytes1-uint8: pass:normal[xref:#Packing-replace_22_1-bytes22-bytes1-uint8-[`++replace_22_1++`]] +:extract_22_2-bytes22-uint8: pass:normal[xref:#Packing-extract_22_2-bytes22-uint8-[`++extract_22_2++`]] +:replace_22_2-bytes22-bytes2-uint8: pass:normal[xref:#Packing-replace_22_2-bytes22-bytes2-uint8-[`++replace_22_2++`]] +:extract_22_4-bytes22-uint8: pass:normal[xref:#Packing-extract_22_4-bytes22-uint8-[`++extract_22_4++`]] +:replace_22_4-bytes22-bytes4-uint8: pass:normal[xref:#Packing-replace_22_4-bytes22-bytes4-uint8-[`++replace_22_4++`]] +:extract_22_6-bytes22-uint8: pass:normal[xref:#Packing-extract_22_6-bytes22-uint8-[`++extract_22_6++`]] +:replace_22_6-bytes22-bytes6-uint8: pass:normal[xref:#Packing-replace_22_6-bytes22-bytes6-uint8-[`++replace_22_6++`]] +:extract_22_8-bytes22-uint8: pass:normal[xref:#Packing-extract_22_8-bytes22-uint8-[`++extract_22_8++`]] +:replace_22_8-bytes22-bytes8-uint8: pass:normal[xref:#Packing-replace_22_8-bytes22-bytes8-uint8-[`++replace_22_8++`]] +:extract_22_10-bytes22-uint8: pass:normal[xref:#Packing-extract_22_10-bytes22-uint8-[`++extract_22_10++`]] +:replace_22_10-bytes22-bytes10-uint8: pass:normal[xref:#Packing-replace_22_10-bytes22-bytes10-uint8-[`++replace_22_10++`]] +:extract_22_12-bytes22-uint8: pass:normal[xref:#Packing-extract_22_12-bytes22-uint8-[`++extract_22_12++`]] +:replace_22_12-bytes22-bytes12-uint8: pass:normal[xref:#Packing-replace_22_12-bytes22-bytes12-uint8-[`++replace_22_12++`]] +:extract_22_16-bytes22-uint8: pass:normal[xref:#Packing-extract_22_16-bytes22-uint8-[`++extract_22_16++`]] +:replace_22_16-bytes22-bytes16-uint8: pass:normal[xref:#Packing-replace_22_16-bytes22-bytes16-uint8-[`++replace_22_16++`]] +:extract_22_20-bytes22-uint8: pass:normal[xref:#Packing-extract_22_20-bytes22-uint8-[`++extract_22_20++`]] +:replace_22_20-bytes22-bytes20-uint8: pass:normal[xref:#Packing-replace_22_20-bytes22-bytes20-uint8-[`++replace_22_20++`]] +:extract_24_1-bytes24-uint8: pass:normal[xref:#Packing-extract_24_1-bytes24-uint8-[`++extract_24_1++`]] +:replace_24_1-bytes24-bytes1-uint8: pass:normal[xref:#Packing-replace_24_1-bytes24-bytes1-uint8-[`++replace_24_1++`]] +:extract_24_2-bytes24-uint8: pass:normal[xref:#Packing-extract_24_2-bytes24-uint8-[`++extract_24_2++`]] +:replace_24_2-bytes24-bytes2-uint8: pass:normal[xref:#Packing-replace_24_2-bytes24-bytes2-uint8-[`++replace_24_2++`]] +:extract_24_4-bytes24-uint8: pass:normal[xref:#Packing-extract_24_4-bytes24-uint8-[`++extract_24_4++`]] +:replace_24_4-bytes24-bytes4-uint8: pass:normal[xref:#Packing-replace_24_4-bytes24-bytes4-uint8-[`++replace_24_4++`]] +:extract_24_6-bytes24-uint8: pass:normal[xref:#Packing-extract_24_6-bytes24-uint8-[`++extract_24_6++`]] +:replace_24_6-bytes24-bytes6-uint8: pass:normal[xref:#Packing-replace_24_6-bytes24-bytes6-uint8-[`++replace_24_6++`]] +:extract_24_8-bytes24-uint8: pass:normal[xref:#Packing-extract_24_8-bytes24-uint8-[`++extract_24_8++`]] +:replace_24_8-bytes24-bytes8-uint8: pass:normal[xref:#Packing-replace_24_8-bytes24-bytes8-uint8-[`++replace_24_8++`]] +:extract_24_10-bytes24-uint8: pass:normal[xref:#Packing-extract_24_10-bytes24-uint8-[`++extract_24_10++`]] +:replace_24_10-bytes24-bytes10-uint8: pass:normal[xref:#Packing-replace_24_10-bytes24-bytes10-uint8-[`++replace_24_10++`]] +:extract_24_12-bytes24-uint8: pass:normal[xref:#Packing-extract_24_12-bytes24-uint8-[`++extract_24_12++`]] +:replace_24_12-bytes24-bytes12-uint8: pass:normal[xref:#Packing-replace_24_12-bytes24-bytes12-uint8-[`++replace_24_12++`]] +:extract_24_16-bytes24-uint8: pass:normal[xref:#Packing-extract_24_16-bytes24-uint8-[`++extract_24_16++`]] +:replace_24_16-bytes24-bytes16-uint8: pass:normal[xref:#Packing-replace_24_16-bytes24-bytes16-uint8-[`++replace_24_16++`]] +:extract_24_20-bytes24-uint8: pass:normal[xref:#Packing-extract_24_20-bytes24-uint8-[`++extract_24_20++`]] +:replace_24_20-bytes24-bytes20-uint8: pass:normal[xref:#Packing-replace_24_20-bytes24-bytes20-uint8-[`++replace_24_20++`]] +:extract_24_22-bytes24-uint8: pass:normal[xref:#Packing-extract_24_22-bytes24-uint8-[`++extract_24_22++`]] +:replace_24_22-bytes24-bytes22-uint8: pass:normal[xref:#Packing-replace_24_22-bytes24-bytes22-uint8-[`++replace_24_22++`]] +:extract_28_1-bytes28-uint8: pass:normal[xref:#Packing-extract_28_1-bytes28-uint8-[`++extract_28_1++`]] +:replace_28_1-bytes28-bytes1-uint8: pass:normal[xref:#Packing-replace_28_1-bytes28-bytes1-uint8-[`++replace_28_1++`]] +:extract_28_2-bytes28-uint8: pass:normal[xref:#Packing-extract_28_2-bytes28-uint8-[`++extract_28_2++`]] +:replace_28_2-bytes28-bytes2-uint8: pass:normal[xref:#Packing-replace_28_2-bytes28-bytes2-uint8-[`++replace_28_2++`]] +:extract_28_4-bytes28-uint8: pass:normal[xref:#Packing-extract_28_4-bytes28-uint8-[`++extract_28_4++`]] +:replace_28_4-bytes28-bytes4-uint8: pass:normal[xref:#Packing-replace_28_4-bytes28-bytes4-uint8-[`++replace_28_4++`]] +:extract_28_6-bytes28-uint8: pass:normal[xref:#Packing-extract_28_6-bytes28-uint8-[`++extract_28_6++`]] +:replace_28_6-bytes28-bytes6-uint8: pass:normal[xref:#Packing-replace_28_6-bytes28-bytes6-uint8-[`++replace_28_6++`]] +:extract_28_8-bytes28-uint8: pass:normal[xref:#Packing-extract_28_8-bytes28-uint8-[`++extract_28_8++`]] +:replace_28_8-bytes28-bytes8-uint8: pass:normal[xref:#Packing-replace_28_8-bytes28-bytes8-uint8-[`++replace_28_8++`]] +:extract_28_10-bytes28-uint8: pass:normal[xref:#Packing-extract_28_10-bytes28-uint8-[`++extract_28_10++`]] +:replace_28_10-bytes28-bytes10-uint8: pass:normal[xref:#Packing-replace_28_10-bytes28-bytes10-uint8-[`++replace_28_10++`]] +:extract_28_12-bytes28-uint8: pass:normal[xref:#Packing-extract_28_12-bytes28-uint8-[`++extract_28_12++`]] +:replace_28_12-bytes28-bytes12-uint8: pass:normal[xref:#Packing-replace_28_12-bytes28-bytes12-uint8-[`++replace_28_12++`]] +:extract_28_16-bytes28-uint8: pass:normal[xref:#Packing-extract_28_16-bytes28-uint8-[`++extract_28_16++`]] +:replace_28_16-bytes28-bytes16-uint8: pass:normal[xref:#Packing-replace_28_16-bytes28-bytes16-uint8-[`++replace_28_16++`]] +:extract_28_20-bytes28-uint8: pass:normal[xref:#Packing-extract_28_20-bytes28-uint8-[`++extract_28_20++`]] +:replace_28_20-bytes28-bytes20-uint8: pass:normal[xref:#Packing-replace_28_20-bytes28-bytes20-uint8-[`++replace_28_20++`]] +:extract_28_22-bytes28-uint8: pass:normal[xref:#Packing-extract_28_22-bytes28-uint8-[`++extract_28_22++`]] +:replace_28_22-bytes28-bytes22-uint8: pass:normal[xref:#Packing-replace_28_22-bytes28-bytes22-uint8-[`++replace_28_22++`]] +:extract_28_24-bytes28-uint8: pass:normal[xref:#Packing-extract_28_24-bytes28-uint8-[`++extract_28_24++`]] +:replace_28_24-bytes28-bytes24-uint8: pass:normal[xref:#Packing-replace_28_24-bytes28-bytes24-uint8-[`++replace_28_24++`]] +:extract_32_1-bytes32-uint8: pass:normal[xref:#Packing-extract_32_1-bytes32-uint8-[`++extract_32_1++`]] +:replace_32_1-bytes32-bytes1-uint8: pass:normal[xref:#Packing-replace_32_1-bytes32-bytes1-uint8-[`++replace_32_1++`]] +:extract_32_2-bytes32-uint8: pass:normal[xref:#Packing-extract_32_2-bytes32-uint8-[`++extract_32_2++`]] +:replace_32_2-bytes32-bytes2-uint8: pass:normal[xref:#Packing-replace_32_2-bytes32-bytes2-uint8-[`++replace_32_2++`]] +:extract_32_4-bytes32-uint8: pass:normal[xref:#Packing-extract_32_4-bytes32-uint8-[`++extract_32_4++`]] +:replace_32_4-bytes32-bytes4-uint8: pass:normal[xref:#Packing-replace_32_4-bytes32-bytes4-uint8-[`++replace_32_4++`]] +:extract_32_6-bytes32-uint8: pass:normal[xref:#Packing-extract_32_6-bytes32-uint8-[`++extract_32_6++`]] +:replace_32_6-bytes32-bytes6-uint8: pass:normal[xref:#Packing-replace_32_6-bytes32-bytes6-uint8-[`++replace_32_6++`]] +:extract_32_8-bytes32-uint8: pass:normal[xref:#Packing-extract_32_8-bytes32-uint8-[`++extract_32_8++`]] +:replace_32_8-bytes32-bytes8-uint8: pass:normal[xref:#Packing-replace_32_8-bytes32-bytes8-uint8-[`++replace_32_8++`]] +:extract_32_10-bytes32-uint8: pass:normal[xref:#Packing-extract_32_10-bytes32-uint8-[`++extract_32_10++`]] +:replace_32_10-bytes32-bytes10-uint8: pass:normal[xref:#Packing-replace_32_10-bytes32-bytes10-uint8-[`++replace_32_10++`]] +:extract_32_12-bytes32-uint8: pass:normal[xref:#Packing-extract_32_12-bytes32-uint8-[`++extract_32_12++`]] +:replace_32_12-bytes32-bytes12-uint8: pass:normal[xref:#Packing-replace_32_12-bytes32-bytes12-uint8-[`++replace_32_12++`]] +:extract_32_16-bytes32-uint8: pass:normal[xref:#Packing-extract_32_16-bytes32-uint8-[`++extract_32_16++`]] +:replace_32_16-bytes32-bytes16-uint8: pass:normal[xref:#Packing-replace_32_16-bytes32-bytes16-uint8-[`++replace_32_16++`]] +:extract_32_20-bytes32-uint8: pass:normal[xref:#Packing-extract_32_20-bytes32-uint8-[`++extract_32_20++`]] +:replace_32_20-bytes32-bytes20-uint8: pass:normal[xref:#Packing-replace_32_20-bytes32-bytes20-uint8-[`++replace_32_20++`]] +:extract_32_22-bytes32-uint8: pass:normal[xref:#Packing-extract_32_22-bytes32-uint8-[`++extract_32_22++`]] +:replace_32_22-bytes32-bytes22-uint8: pass:normal[xref:#Packing-replace_32_22-bytes32-bytes22-uint8-[`++replace_32_22++`]] +:extract_32_24-bytes32-uint8: pass:normal[xref:#Packing-extract_32_24-bytes32-uint8-[`++extract_32_24++`]] +:replace_32_24-bytes32-bytes24-uint8: pass:normal[xref:#Packing-replace_32_24-bytes32-bytes24-uint8-[`++replace_32_24++`]] +:extract_32_28-bytes32-uint8: pass:normal[xref:#Packing-extract_32_28-bytes32-uint8-[`++extract_32_28++`]] +:replace_32_28-bytes32-bytes28-uint8: pass:normal[xref:#Packing-replace_32_28-bytes32-bytes28-uint8-[`++replace_32_28++`]] + [.contract] [[Packing]] -=== `++Packing++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Packing.sol[{github-icon},role=heading-link] +=== `++Packing++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Packing.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -8426,9 +9560,11 @@ _Available since v5.1._ :INVALID_INTERNAL_FUNCTION: pass:normal[xref:#Panic-INVALID_INTERNAL_FUNCTION-uint256[`++INVALID_INTERNAL_FUNCTION++`]] :panic: pass:normal[xref:#Panic-panic-uint256-[`++panic++`]] +:panic-uint256: pass:normal[xref:#Panic-panic-uint256-[`++panic++`]] + [.contract] [[Panic]] -=== `++Panic++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Panic.sol[{github-icon},role=heading-link] +=== `++Panic++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Panic.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -8546,9 +9682,12 @@ calling invalid internal function :lt: pass:normal[xref:#Comparators-lt-uint256-uint256-[`++lt++`]] :gt: pass:normal[xref:#Comparators-gt-uint256-uint256-[`++gt++`]] +:lt-uint256-uint256: pass:normal[xref:#Comparators-lt-uint256-uint256-[`++lt++`]] +:gt-uint256-uint256: pass:normal[xref:#Comparators-gt-uint256-uint256-[`++gt++`]] + [.contract] [[Comparators]] -=== `++Comparators++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/utils/Comparators.sol[{github-icon},role=heading-link] +=== `++Comparators++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/Comparators.sol[{github-icon},role=heading-link] [.hljs-theme-light.nopadding] ```solidity @@ -8575,3 +9714,125 @@ _Available since v5.1._ [[Comparators-gt-uint256-uint256-]] ==== `[.contract-item-name]#++gt++#++(uint256 a, uint256 b) → bool++` [.item-kind]#internal# +:local: pass:normal[xref:#CAIP2-local--[`++local++`]] +:format: pass:normal[xref:#CAIP2-format-string-string-[`++format++`]] +:parse: pass:normal[xref:#CAIP2-parse-string-[`++parse++`]] + +:local-: pass:normal[xref:#CAIP2-local--[`++local++`]] +:format-string-string: pass:normal[xref:#CAIP2-format-string-string-[`++format++`]] +:parse-string: pass:normal[xref:#CAIP2-parse-string-[`++parse++`]] + +[.contract] +[[CAIP2]] +=== `++CAIP2++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/CAIP2.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/utils/CAIP2.sol"; +``` + +Helper library to format and parse CAIP-2 identifiers + +https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md[CAIP-2] defines chain identifiers as: +chain_id: namespace + ":" + reference +namespace: [-a-z0-9]{3,8} +reference: [-_a-zA-Z0-9]{1,32} + +WARNING: In some cases, multiple CAIP-2 identifiers may all be valid representation of a single chain. +For EVM chains, it is recommended to use `eip155:xxx` as the canonical representation (where `xxx` is +the EIP-155 chain id). Consider the possible ambiguity when processing CAIP-2 identifiers or when using them +in the context of hashes. + +[.contract-index] +.Functions +-- +* {xref-CAIP2-local--}[`++local()++`] +* {xref-CAIP2-format-string-string-}[`++format(namespace, ref)++`] +* {xref-CAIP2-parse-string-}[`++parse(caip2)++`] + +-- + +[.contract-item] +[[CAIP2-local--]] +==== `[.contract-item-name]#++local++#++() → string++` [.item-kind]#internal# + +Return the CAIP-2 identifier for the current (local) chain. + +[.contract-item] +[[CAIP2-format-string-string-]] +==== `[.contract-item-name]#++format++#++(string namespace, string ref) → string++` [.item-kind]#internal# + +Return the CAIP-2 identifier for a given namespace and reference. + +NOTE: This function does not verify that the inputs are properly formatted. + +[.contract-item] +[[CAIP2-parse-string-]] +==== `[.contract-item-name]#++parse++#++(string caip2) → string namespace, string ref++` [.item-kind]#internal# + +Parse a CAIP-2 identifier into its components. + +NOTE: This function does not verify that the CAIP-2 input is properly formatted. + +:local: pass:normal[xref:#CAIP10-local-address-[`++local++`]] +:format: pass:normal[xref:#CAIP10-format-string-string-[`++format++`]] +:parse: pass:normal[xref:#CAIP10-parse-string-[`++parse++`]] + +:local-address: pass:normal[xref:#CAIP10-local-address-[`++local++`]] +:format-string-string: pass:normal[xref:#CAIP10-format-string-string-[`++format++`]] +:parse-string: pass:normal[xref:#CAIP10-parse-string-[`++parse++`]] + +[.contract] +[[CAIP10]] +=== `++CAIP10++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.3.0/contracts/utils/CAIP10.sol[{github-icon},role=heading-link] + +[.hljs-theme-light.nopadding] +```solidity +import "@openzeppelin/contracts/utils/CAIP10.sol"; +``` + +Helper library to format and parse CAIP-10 identifiers + +https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md[CAIP-10] defines account identifiers as: +account_id: chain_id + ":" + account_address +chain_id: [-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32} (See {CAIP2}) +account_address: [-.%a-zA-Z0-9]{1,128} + +WARNING: According to [CAIP-10's canonicalization section](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md#canonicalization), +the implementation remains at the developer's discretion. Please note that case variations may introduce ambiguity. +For example, when building hashes to identify accounts or data associated to them, multiple representations of the +same account would derive to different hashes. For EVM chains, we recommend using checksummed addresses for the +"account_address" part. They can be generated onchain using {Strings-toChecksumHexString}. + +[.contract-index] +.Functions +-- +* {xref-CAIP10-local-address-}[`++local(account)++`] +* {xref-CAIP10-format-string-string-}[`++format(caip2, account)++`] +* {xref-CAIP10-parse-string-}[`++parse(caip10)++`] + +-- + +[.contract-item] +[[CAIP10-local-address-]] +==== `[.contract-item-name]#++local++#++(address account) → string++` [.item-kind]#internal# + +Return the CAIP-10 identifier for an account on the current (local) chain. + +[.contract-item] +[[CAIP10-format-string-string-]] +==== `[.contract-item-name]#++format++#++(string caip2, string account) → string++` [.item-kind]#internal# + +Return the CAIP-10 identifier for a given caip2 chain and account. + +NOTE: This function does not verify that the inputs are properly formatted. + +[.contract-item] +[[CAIP10-parse-string-]] +==== `[.contract-item-name]#++parse++#++(string caip10) → string caip2, string account++` [.item-kind]#internal# + +Parse a CAIP-10 identifier into its components. + +NOTE: This function does not verify that the CAIP-10 input is properly formatted. The `caip2` return can be +parsed using the {CAIP2} library. + diff --git a/docs/templates/contract.hbs b/docs/templates/contract.hbs index aaca0a3cc..458b511b0 100644 --- a/docs/templates/contract.hbs +++ b/docs/templates/contract.hbs @@ -2,6 +2,10 @@ :{{name}}: pass:normal[xref:#{{anchor}}[`++{{name}}++`]] {{/each}} +{{#each functions}} +:{{fullname}}: pass:normal[xref:#{{anchor}}[`++{{name}}++`]] +{{/each}} + [.contract] [[{{anchor}}]] === `++{{name}}++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v{{oz-version}}/{{__item_context.file.absolutePath}}[{github-icon},role=heading-link] diff --git a/docs/templates/properties.js b/docs/templates/properties.js index 52eebac54..8d6b2867d 100644 --- a/docs/templates/properties.js +++ b/docs/templates/properties.js @@ -17,6 +17,22 @@ module.exports.anchor = function anchor({ item, contract }) { return res; }; +module.exports.fullname = function fullname({ item }) { + let res = ''; + res += item.name; + if ('parameters' in item) { + const signature = item.parameters.parameters.map(v => v.typeName.typeDescriptions.typeString).join(','); + res += slug('(' + signature + ')'); + } + if (isNodeType('VariableDeclaration', item)) { + res += '-' + slug(item.typeName.typeDescriptions.typeString); + } + if (res.charAt(res.length - 1) === '-') { + return res.slice(0, -1); + } + return res; +}; + module.exports.inheritance = function ({ item, build }) { if (!isNodeType('ContractDefinition', item)) { throw new Error('used inherited-items on non-contract'); diff --git a/fv-requirements.txt b/fv-requirements.txt index 608b4de24..5aeb1225a 100644 --- a/fv-requirements.txt +++ b/fv-requirements.txt @@ -1,4 +1,4 @@ certora-cli==4.13.1 # File uses a custom name (fv-requirements.txt) so that it isn't picked by Netlify's build # whose latest Python version is 0.3.8, incompatible with most recent versions of Halmos -halmos==0.2.0 +halmos==0.2.4 diff --git a/hardhat.config.js b/hardhat.config.js index d39d3d073..30c19ca6d 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -90,7 +90,6 @@ module.exports = { 'initcode-size': 'off', }, '*': { - 'code-size': true, 'unused-param': !argv.coverage, // coverage causes unused-param warnings 'transient-storage': false, default: 'error', @@ -103,6 +102,7 @@ module.exports = { // we rely on the `code-size` compiler warning, that will cause a compilation error. allowUnlimitedContractSize: true, initialBaseFeePerGas: argv.coverage ? 0 : undefined, + enableRip7212: true, }, }, exposed: { diff --git a/hardhat/async-test-sanity.js b/hardhat/async-test-sanity.js index c05e5bd48..8e60f70d5 100644 --- a/hardhat/async-test-sanity.js +++ b/hardhat/async-test-sanity.js @@ -1,3 +1,10 @@ process.on('unhandledRejection', reason => { - throw new Error(reason); + // If the reason is already an Error object, throw it directly to preserve the stack trace. + if (reason instanceof Error) { + throw reason; + } else { + // If the reason is not an Error (e.g., a string, number, or other primitive), + // create a new Error object with the reason as its message. + throw new Error(`Unhandled rejection: ${reason}`); + } }); diff --git a/hardhat/common-contracts.js b/hardhat/common-contracts.js new file mode 100644 index 000000000..fd4ef1dba --- /dev/null +++ b/hardhat/common-contracts.js @@ -0,0 +1,63 @@ +const { task } = require('hardhat/config'); +const { TASK_TEST_SETUP_TEST_ENVIRONMENT } = require('hardhat/builtin-tasks/task-names'); +const { setCode } = require('@nomicfoundation/hardhat-network-helpers'); + +const fs = require('fs'); +const path = require('path'); + +const INSTANCES = { + // ERC-4337 Entrypoints + entrypoint: { + v07: { + address: '0x0000000071727De22E5E9d8BAf0edAc6f37da032', + abi: JSON.parse(fs.readFileSync(path.resolve(__dirname, '../test/bin/EntryPoint070.abi'), 'utf-8')), + bytecode: fs.readFileSync(path.resolve(__dirname, '../test/bin/EntryPoint070.bytecode'), 'hex'), + }, + v08: { + address: '0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108', + abi: JSON.parse(fs.readFileSync(path.resolve(__dirname, '../test/bin/EntryPoint080.abi'), 'utf-8')), + bytecode: fs.readFileSync(path.resolve(__dirname, '../test/bin/EntryPoint080.bytecode'), 'hex'), + }, + }, + senderCreator: { + v07: { + address: '0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C', + abi: JSON.parse(fs.readFileSync(path.resolve(__dirname, '../test/bin/SenderCreator070.abi'), 'utf-8')), + bytecode: fs.readFileSync(path.resolve(__dirname, '../test/bin/SenderCreator070.bytecode'), 'hex'), + }, + v08: { + address: '0x449ED7C3e6Fee6a97311d4b55475DF59C44AdD33', + abi: JSON.parse(fs.readFileSync(path.resolve(__dirname, '../test/bin/SenderCreator080.abi'), 'utf-8')), + bytecode: fs.readFileSync(path.resolve(__dirname, '../test/bin/SenderCreator080.bytecode'), 'hex'), + }, + }, + deployer: { + // Arachnid's deterministic deployment proxy + // See: https://github.com/Arachnid/deterministic-deployment-proxy/tree/master + arachnid: { + address: '0x4e59b44847b379578588920cA78FbF26c0B4956C', + abi: [], + bytecode: + '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3', + }, + // Micah's deployer + micah: { + address: '0x7A0D94F55792C434d74a40883C6ed8545E406D12', + abi: [], + bytecode: '0x60003681823780368234f58015156014578182fd5b80825250506014600cf3', + }, + }, +}; + +const setup = (input, ethers) => + input.address && input.abi && input.bytecode + ? setCode(input.address, '0x' + input.bytecode.replace(/0x/, '')).then(() => + ethers.getContractAt(input.abi, input.address), + ) + : Promise.all( + Object.entries(input).map(([name, entry]) => setup(entry, ethers).then(result => [name, result])), + ).then(Object.fromEntries); + +task(TASK_TEST_SETUP_TEST_ENVIRONMENT).setAction((_, env, runSuper) => + runSuper().then(() => setup(INSTANCES, env.ethers).then(result => Object.assign(env, result))), +); diff --git a/hardhat/ignore-unreachable-warnings.js b/hardhat/ignore-unreachable-warnings.js index 8e3e34340..eeacf0a1a 100644 --- a/hardhat/ignore-unreachable-warnings.js +++ b/hardhat/ignore-unreachable-warnings.js @@ -3,7 +3,7 @@ // with hardhat-ignore-warnings we are not able to selectively ignore them without potentially ignoring relevant // warnings that we don't want to miss. // Thus, we need to handle these warnings separately. We force Hardhat to compile them in a separate compilation job and -// then ignore the warnings about unreachable code that come from that compilation job. +// then ignore the warnings about unreachable code coming from that compilation job. const { task } = require('hardhat/config'); const { diff --git a/lib/forge-std b/lib/forge-std index 8f24d6b04..1eea5bae1 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 8f24d6b04c92975e0795b5868aa0d783251cdeaa +Subproject commit 1eea5bae12ae557d589f9f0f0edae2faa47cb262 diff --git a/package-lock.json b/package-lock.json index 6066b617f..e89558df7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "openzeppelin-solidity", - "version": "5.1.0", + "version": "5.3.0-rc.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "openzeppelin-solidity", - "version": "5.1.0", + "version": "5.3.0-rc.0", "license": "MIT", "devDependencies": { "@changesets/changelog-github": "^0.5.0", @@ -24,17 +24,19 @@ "chai": "^4.2.0", "eslint": "^9.0.0", "eslint-config-prettier": "^9.0.0", - "ethers": "^6.7.1", + "ethers": "^6.13.4", "glob": "^11.0.0", "globals": "^15.3.0", "graphlib": "^2.1.8", - "hardhat": "^2.22.2", + "hardhat": "^2.22.7", "hardhat-exposed": "^0.3.15", - "hardhat-gas-reporter": "^2.0.0", + "hardhat-gas-reporter": "^2.1.0", "hardhat-ignore-warnings": "^0.2.11", + "husky": "^9.1.7", + "lint-staged": "^15.2.10", "lodash.startcase": "^4.4.0", "micromatch": "^4.0.2", - "p-limit": "^3.1.0", + "p-limit": "^6.0.0", "prettier": "^3.0.0", "prettier-plugin-solidity": "^1.1.0", "rimraf": "^6.0.0", @@ -44,7 +46,7 @@ "solidity-ast": "^0.4.50", "solidity-coverage": "^0.8.5", "solidity-docgen": "^0.6.0-beta.29", - "undici": "^6.11.1", + "undici": "^7.0.0", "yargs": "^17.0.0" } }, @@ -58,10 +60,11 @@ } }, "node_modules/@adraffy/ens-normalize": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.9.2.tgz", - "integrity": "sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg==", - "dev": true + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "dev": true, + "license": "MIT" }, "node_modules/@babel/code-frame": { "version": "7.22.13", @@ -1550,165 +1553,90 @@ } }, "node_modules/@nomicfoundation/edr": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.3.3.tgz", - "integrity": "sha512-zP+e+3B1nEUx6bW5BPnIzCQbkhmYfdMBJdiVggTqqTfAA82sOkdOG7wsOMcz5qF3fYfx/irNRM1kgc9HVFIbpQ==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.5.2.tgz", + "integrity": "sha512-hW/iLvUQZNTVjFyX/I40rtKvvDOqUEyIi96T28YaLfmPL+3LW2lxmYLUXEJ6MI14HzqxDqrLyhf6IbjAa2r3Dw==", "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/edr-darwin-arm64": "0.5.2", + "@nomicfoundation/edr-darwin-x64": "0.5.2", + "@nomicfoundation/edr-linux-arm64-gnu": "0.5.2", + "@nomicfoundation/edr-linux-arm64-musl": "0.5.2", + "@nomicfoundation/edr-linux-x64-gnu": "0.5.2", + "@nomicfoundation/edr-linux-x64-musl": "0.5.2", + "@nomicfoundation/edr-win32-x64-msvc": "0.5.2" + }, "engines": { "node": ">= 18" - }, - "optionalDependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.3.3", - "@nomicfoundation/edr-darwin-x64": "0.3.3", - "@nomicfoundation/edr-linux-arm64-gnu": "0.3.3", - "@nomicfoundation/edr-linux-arm64-musl": "0.3.3", - "@nomicfoundation/edr-linux-x64-gnu": "0.3.3", - "@nomicfoundation/edr-linux-x64-musl": "0.3.3", - "@nomicfoundation/edr-win32-arm64-msvc": "0.3.3", - "@nomicfoundation/edr-win32-ia32-msvc": "0.3.3", - "@nomicfoundation/edr-win32-x64-msvc": "0.3.3" } }, "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.3.tgz", - "integrity": "sha512-E9VGsUD+1Ga4mn/5ooHsMi8JEfhZbKP6CXN/BhJ8kXbIC10NqTD1RuhCKGRtYq4vqH/3Nfq25Xg8E8RWOF4KBQ==", - "cpu": [ - "arm64" - ], + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.5.2.tgz", + "integrity": "sha512-Gm4wOPKhbDjGTIRyFA2QUAPfCXA1AHxYOKt3yLSGJkQkdy9a5WW+qtqKeEKHc/+4wpJSLtsGQfpzyIzggFfo/A==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.3.tgz", - "integrity": "sha512-vkZXZ1ydPg+Ijb2iyqENA+KCkxGTCUWG5itCSliiA0Li2YE7ujDMGhheEpFp1WVlZadviz0bfk1rZXbCqlirpg==", - "cpu": [ - "x64" - ], + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.5.2.tgz", + "integrity": "sha512-ClyABq2dFCsrYEED3/UIO0c7p4H1/4vvlswFlqUyBpOkJccr75qIYvahOSJRM62WgUFRhbSS0OJXFRwc/PwmVg==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.3.tgz", - "integrity": "sha512-gdIg0Yj1qqS9wVuywc5B/+DqKylfUGB6/CQn/shMqwAfsAVAVpchkhy66PR+REEx7fh/GkNctxLlENXPeLzDiA==", - "cpu": [ - "arm64" - ], + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.5.2.tgz", + "integrity": "sha512-HWMTVk1iOabfvU2RvrKLDgtFjJZTC42CpHiw2h6rfpsgRqMahvIlx2jdjWYzFNy1jZKPTN1AStQ/91MRrg5KnA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.3.tgz", - "integrity": "sha512-AXZ08MFvhNeBZbOBNmz1SJ/DMrMOE2mHEJtaNnsctlxIunjxfrWww4q+WXB34jbr9iaVYYlPsaWe5sueuw6s3Q==", - "cpu": [ - "arm64" - ], + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.5.2.tgz", + "integrity": "sha512-CwsQ10xFx/QAD5y3/g5alm9+jFVuhc7uYMhrZAu9UVF+KtVjeCvafj0PaVsZ8qyijjqVuVsJ8hD1x5ob7SMcGg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.3.tgz", - "integrity": "sha512-xElOs1U+E6lBLtv1mnJ+E8nr2MxZgKiLo8bZAgBboy9odYtmkDVwhMjtsFKSuZbGxFtsSyGRT4cXw3JAbtUDeA==", - "cpu": [ - "x64" - ], + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.5.2.tgz", + "integrity": "sha512-CWVCEdhWJ3fmUpzWHCRnC0/VLBDbqtqTGTR6yyY1Ep3S3BOrHEAvt7h5gx85r2vLcztisu2vlDq51auie4IU1A==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.3.tgz", - "integrity": "sha512-2Fe6gwm1RAGQ/PfMYiaSba2OrFp8zzYWh+am9lYObOFjV9D+A1zhIzfy0UC74glPks5eV8eY4pBPrVR042m2Nw==", - "cpu": [ - "x64" - ], + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.5.2.tgz", + "integrity": "sha512-+aJDfwhkddy2pP5u1ISg3IZVAm0dO836tRlDTFWtvvSMQ5hRGqPcWwlsbobhDQsIxhPJyT7phL0orCg5W3WMeA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 18" - } - }, - "node_modules/@nomicfoundation/edr-win32-arm64-msvc": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-arm64-msvc/-/edr-win32-arm64-msvc-0.3.3.tgz", - "integrity": "sha512-8NHyxIsFrl0ufSQ/ErqF2lKIa/gz1gaaa1a2vKkDEqvqCUcPhBTYhA5NHgTPhLETFTnCFr0z+YbctFCyjh4qrA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/edr-win32-ia32-msvc": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-ia32-msvc/-/edr-win32-ia32-msvc-0.3.3.tgz", - "integrity": "sha512-0F6hM0kGia4dQVb/kauho9JcP1ozWisY2/She+ISR5ceuhzmAwQJluM0g+0TYDME0LtxBxiMPq/yPiZMQeq31w==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.3.tgz", - "integrity": "sha512-d75q1uaMb6z9i+GQZoblbOfFBvlBnWc+5rB13UWRkCOJSnoYwyFWhGJx5GeM59gC7aIblc5VD9qOAhHuvM9N+w==", - "cpu": [ - "x64" - ], + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.5.2.tgz", + "integrity": "sha512-CcvvuA3sAv7liFNPsIR/68YlH6rrybKzYttLlMr80d4GKJjwJ5OKb3YgE6FdZZnOfP19HEHhsLcE0DPLtY3r0w==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "license": "MIT", "engines": { "node": ">= 18" } @@ -2609,12 +2537,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", - "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/normalize-package-data": { @@ -3587,6 +3516,65 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -3648,6 +3636,12 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3664,7 +3658,8 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commander": { "version": "10.0.1", @@ -4145,6 +4140,18 @@ "node": ">=6" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -4618,6 +4625,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", @@ -4647,6 +4670,19 @@ "node": ">=8" } }, + "node_modules/eslint/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/espree": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", @@ -4823,9 +4859,9 @@ "dev": true }, "node_modules/ethers": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.7.1.tgz", - "integrity": "sha512-qX5kxIFMfg1i+epfgb0xF4WM7IqapIIu50pOJ17aebkxxa4BacW5jFrQRmCJpDEg2ZK2oNtR5QjrQ1WDBF29dA==", + "version": "6.13.4", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.4.tgz", + "integrity": "sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==", "dev": true, "funding": [ { @@ -4837,36 +4873,45 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@adraffy/ens-normalize": "1.9.2", - "@noble/hashes": "1.1.2", - "@noble/secp256k1": "1.7.1", - "@types/node": "18.15.13", + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "22.7.5", "aes-js": "4.0.0-beta.5", - "tslib": "2.4.0", - "ws": "8.5.0" + "tslib": "2.7.0", + "ws": "8.17.1" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/ethers/node_modules/@noble/hashes": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz", - "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==", + "node_modules/ethers/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, - "node_modules/ethers/node_modules/@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", - "dev": true + "node_modules/ethers/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/ethers/node_modules/aes-js": { "version": "4.0.0-beta.5", @@ -4875,22 +4920,24 @@ "dev": true }, "node_modules/ethers/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" }, "node_modules/ethers/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -4935,6 +4982,12 @@ "npm": ">=3" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -4945,6 +4998,53 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/extendable-error": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", @@ -5257,6 +5357,18 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", @@ -5572,14 +5684,15 @@ } }, "node_modules/hardhat": { - "version": "2.22.2", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.2.tgz", - "integrity": "sha512-0xZ7MdCZ5sJem4MrvpQWLR3R3zGDoHw5lsR+pBFimqwagimIOn3bWuZv69KA+veXClwI1s/zpqgwPwiFrd4Dxw==", + "version": "2.22.7", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.7.tgz", + "integrity": "sha512-nrXQAl+qUr75TsCLDo8P41YXLc+5U7qQMMCIrbbmy1/uQaVPncdjDrD5BR0CENvHRj7EBqO+JkofpozXoIfJKg==", "dev": true, + "license": "MIT", "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/edr": "^0.3.1", + "@nomicfoundation/edr": "^0.5.0", "@nomicfoundation/ethereumjs-common": "4.0.4", "@nomicfoundation/ethereumjs-tx": "5.0.4", "@nomicfoundation/ethereumjs-util": "9.0.4", @@ -5613,7 +5726,7 @@ "raw-body": "^2.4.1", "resolve": "1.17.0", "semver": "^6.3.0", - "solc": "0.7.3", + "solc": "0.8.26", "source-map-support": "^0.5.13", "stacktrace-parser": "^0.1.10", "tsort": "0.0.1", @@ -5655,6 +5768,7 @@ "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-2.1.0.tgz", "integrity": "sha512-d/WU/qHhBFnbweAm2fAAjcaaE0M7BKZ4r+/bqcFlfP6um28BXtlv2FrJ6oyQUGSFD0ttbmB7sH4ZFDzkYw5GzA==", "dev": true, + "license": "MIT", "dependencies": { "@ethersproject/abi": "^5.7.0", "@ethersproject/bytes": "^5.7.0", @@ -6030,12 +6144,6 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, - "node_modules/hardhat/node_modules/commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "dev": true - }, "node_modules/hardhat/node_modules/ethereum-cryptography": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", @@ -6064,7 +6172,9 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -6080,15 +6190,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/hardhat/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/hardhat/node_modules/locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -6144,27 +6245,6 @@ "node": ">=4" } }, - "node_modules/hardhat/node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hardhat/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/hardhat/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -6174,51 +6254,6 @@ "semver": "bin/semver.js" } }, - "node_modules/hardhat/node_modules/solc": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", - "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", - "dev": true, - "dependencies": { - "command-exists": "^1.2.8", - "commander": "3.0.2", - "follow-redirects": "^1.12.1", - "fs-extra": "^0.30.0", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "require-from-string": "^2.0.0", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "bin": { - "solcjs": "solcjs" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/hardhat/node_modules/undici": { "version": "5.28.4", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", @@ -6446,6 +6481,30 @@ "integrity": "sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==", "dev": true }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -6678,6 +6737,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -6782,6 +6853,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -7019,15 +7102,6 @@ "node": ">=0.10.0" } }, - "node_modules/klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.9" - } - }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -7065,12 +7139,168 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/lint-staged": { + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", + "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", + "dev": true, + "dependencies": { + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.6", + "execa": "~8.0.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.5.0" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/lint-staged/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/lint-staged/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/listr2": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/load-yaml-file": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/load-yaml-file/-/load-yaml-file-0.2.0.tgz", @@ -7214,6 +7444,127 @@ "node": ">=8" } }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/loupe": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", @@ -7328,6 +7679,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -7344,12 +7701,12 @@ "dev": true }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -7377,6 +7734,30 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", @@ -7683,6 +8064,22 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mocha/node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", @@ -7754,6 +8151,19 @@ "node": ">=10" } }, + "node_modules/mocha/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -7905,6 +8315,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", @@ -7976,6 +8413,21 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -8045,15 +8497,16 @@ } }, "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.0.0.tgz", + "integrity": "sha512-Dx+NzOuILWwjJE9OYtEKuQRy0i3c5QVAmDsVrvvRSgyNnPuB27D2DyEjl6QTNyeePaAHjaPk+ya0yA0Frld8RA==", "dev": true, + "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "yocto-queue": "^1.1.1" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8261,6 +8714,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -8337,6 +8802,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/preferred-pm/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/preferred-pm/node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", @@ -8352,6 +8833,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/preferred-pm/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -8773,6 +9267,49 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -8792,6 +9329,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, "node_modules/rimraf": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.0.tgz", @@ -9457,6 +10000,48 @@ "node": ">=8" } }, + "node_modules/solc": { + "version": "0.8.26", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", + "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "command-exists": "^1.2.8", + "commander": "^8.1.0", + "follow-redirects": "^1.12.1", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solc.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/solc/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/solc/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/solhint": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/solhint/-/solhint-5.0.0.tgz", @@ -10130,6 +10715,32 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/string-width-cjs": { "name": "string-width", "version": "4.2.3", @@ -10154,6 +10765,39 @@ "node": ">=8" } }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", @@ -10233,6 +10877,18 @@ "node": ">=4" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -10719,19 +11375,21 @@ } }, "node_modules/undici": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.12.0.tgz", - "integrity": "sha512-d87yk8lqSFUYtR5fTFe2frpkMIrUEz+lgoJmhcL+J3StVl+8fj8ytE4lLnJOTPCE12YbumNGzf4LYsQyusdV5g==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.0.0.tgz", + "integrity": "sha512-c4xi3kWnQJrb7h2q8aJYKvUzmz7boCgz1cUCC6OwdeM5Tr2P0hDuthr2iut4ggqsz+Cnh20U/LoTzbKIdDS/Nw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=18.0" + "node": ">=20.18.1" } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" }, "node_modules/universalify": { "version": "0.1.2", @@ -11250,10 +11908,11 @@ "dev": true }, "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.3.0" }, @@ -11279,6 +11938,18 @@ "node": ">=10" } }, + "node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -11399,12 +12070,13 @@ } }, "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11413,7 +12085,10 @@ "scripts/solhint-custom": { "name": "solhint-plugin-openzeppelin", "version": "0.0.0", - "dev": true + "dev": true, + "dependencies": { + "minimatch": "^3.1.2" + } } } } diff --git a/package.json b/package.json index 4db5ac0a1..2096a0877 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "openzeppelin-solidity", "description": "Secure Smart Contract library for Solidity", - "version": "5.2.0", + "version": "5.3.0", "private": true, "files": [ "/contracts/**/*.sol", @@ -13,7 +13,7 @@ "coverage": "scripts/checks/coverage.sh", "docs": "npm run prepare-docs && oz-docs", "docs:watch": "oz-docs watch contracts docs/templates docs/config.js", - "prepare": "scripts/prepare.sh", + "prepare": "husky", "prepare-docs": "scripts/prepare-docs.sh", "lint": "npm run lint:js && npm run lint:sol", "lint:fix": "npm run lint:js:fix && npm run lint:sol:fix", @@ -25,7 +25,7 @@ "prepack": "scripts/prepack.sh", "generate": "scripts/generate/run.js", "version": "scripts/release/version.sh", - "test": "hardhat test", + "test": ". scripts/set-max-old-space-size.sh && hardhat test", "test:generation": "scripts/checks/generation.sh", "test:inheritance": "scripts/checks/inheritance-ordering.js artifacts/build-info/*", "test:pragma": "scripts/checks/pragma-consistency.js artifacts/build-info/*", @@ -66,17 +66,19 @@ "chai": "^4.2.0", "eslint": "^9.0.0", "eslint-config-prettier": "^9.0.0", - "ethers": "^6.7.1", - "globals": "^15.3.0", + "ethers": "^6.13.4", "glob": "^11.0.0", + "globals": "^15.3.0", "graphlib": "^2.1.8", - "hardhat": "^2.22.2", + "hardhat": "^2.22.7", "hardhat-exposed": "^0.3.15", - "hardhat-gas-reporter": "^2.0.0", + "hardhat-gas-reporter": "^2.1.0", "hardhat-ignore-warnings": "^0.2.11", + "husky": "^9.1.7", + "lint-staged": "^15.2.10", "lodash.startcase": "^4.4.0", "micromatch": "^4.0.2", - "p-limit": "^3.1.0", + "p-limit": "^6.0.0", "prettier": "^3.0.0", "prettier-plugin-solidity": "^1.1.0", "rimraf": "^6.0.0", @@ -86,7 +88,17 @@ "solidity-ast": "^0.4.50", "solidity-coverage": "^0.8.5", "solidity-docgen": "^0.6.0-beta.29", - "undici": "^6.11.1", + "undici": "^7.0.0", "yargs": "^17.0.0" + }, + "lint-staged": { + "*.{js,ts}": [ + "prettier --log-level warn --ignore-path .gitignore --check", + "eslint" + ], + "*.sol": [ + "prettier --log-level warn --ignore-path .gitignore --check", + "solhint" + ] } } diff --git a/scripts/checks/coverage.sh b/scripts/checks/coverage.sh index a591069c4..fd8b9e843 100755 --- a/scripts/checks/coverage.sh +++ b/scripts/checks/coverage.sh @@ -5,6 +5,8 @@ set -euo pipefail export COVERAGE=true export FOUNDRY_FUZZ_RUNS=10 +. scripts/set-max-old-space-size.sh + # Hardhat coverage hardhat coverage @@ -12,7 +14,11 @@ if [ "${CI:-"false"}" == "true" ]; then # Foundry coverage forge coverage --report lcov --ir-minimum # Remove zero hits - sed -i '/,0/d' lcov.info + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' '/,0/d' lcov.info + else + sed -i '/,0/d' lcov.info + fi fi # Reports are then uploaded to Codecov automatically by workflow, and merged. diff --git a/scripts/checks/inheritance-ordering.js b/scripts/checks/inheritance-ordering.js index 4ed2deec4..fbeac9ea7 100755 --- a/scripts/checks/inheritance-ordering.js +++ b/scripts/checks/inheritance-ordering.js @@ -31,7 +31,7 @@ for (const artifact of artifacts) { } /// graphlib.alg.findCycles will not find minimal cycles. - /// We are only interested int cycles of lengths 2 (needs proof) + /// We are only interested in cycles of lengths 2 (needs proof) graph.nodes().forEach((x, i, nodes) => nodes .slice(i + 1) diff --git a/scripts/checks/pragma-consistency.js b/scripts/checks/pragma-consistency.js index f2f3c548f..cf74cd27a 100755 --- a/scripts/checks/pragma-consistency.js +++ b/scripts/checks/pragma-consistency.js @@ -31,7 +31,7 @@ for (const artifact of artifacts) { const minVersion = semver.minVersion(pragma[source]); // loop over all imports in source for (const { absolutePath } of findAll('ImportDirective', solcOutput.sources[source].ast)) { - // So files that only import without declaring anything cause issues, because they don't shop in in "pragma" + // So files that only import without declaring anything cause issues, because they don't shop in "pragma" if (!pragma[absolutePath]) continue; // Check that the minVersion for source satisfies the requirements of the imported files if (!semver.satisfies(minVersion, pragma[absolutePath])) { diff --git a/scripts/fetch-common-contracts.js b/scripts/fetch-common-contracts.js new file mode 100755 index 000000000..af904243b --- /dev/null +++ b/scripts/fetch-common-contracts.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node + +// This script snapshots the bytecode and ABI for the `hardhat/common-contracts.js` script. +// - Bytecode is fetched directly from the blockchain by querying the provided client endpoint. If no endpoint is +// provided, ethers default provider is used instead. +// - ABI is fetched from etherscan's API using the provided etherscan API key. If no API key is provided, ABI will not +// be fetched and saved. +// +// The produced artifacts are stored in the `output` folder ('test/bin' by default). For each contract, two files are +// produced: +// - `.bytecode` containing the contract bytecode (in binary encoding) +// - `.abi` containing the ABI (in utf-8 encoding) + +const fs = require('fs'); +const path = require('path'); +const { ethers } = require('ethers'); +const { request } = require('undici'); +const { hideBin } = require('yargs/helpers'); +const { argv } = require('yargs/yargs')(hideBin(process.argv)) + .env('') + .options({ + output: { type: 'string', default: 'test/bin/' }, + client: { type: 'string' }, + etherscan: { type: 'string' }, + }); + +// List of contract names and addresses to fetch +const config = { + EntryPoint070: '0x0000000071727De22E5E9d8BAf0edAc6f37da032', + SenderCreator070: '0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C', + EntryPoint080: '0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108', + SenderCreator080: '0x449ED7C3e6Fee6a97311d4b55475DF59C44AdD33', +}; + +Promise.all( + Object.entries(config).flatMap(([name, addr]) => + Promise.all([ + argv.etherscan && + request(`https://api.etherscan.io/api?module=contract&action=getabi&address=${addr}&apikey=${argv.etherscan}`) + .then(({ body }) => body.json()) + .then(({ result: abi }) => fs.writeFile(path.join(argv.output, `${name}.abi`), abi, 'utf-8', () => {})), + ethers + .getDefaultProvider(argv.client) + .getCode(addr) + .then(bytecode => + fs.writeFile(path.join(argv.output, `${name}.bytecode`), ethers.getBytes(bytecode), 'binary', () => {}), + ), + ]), + ), +); diff --git a/scripts/generate/templates/Arrays.js b/scripts/generate/templates/Arrays.js index 0d3676a72..6b3a9a6a3 100644 --- a/scripts/generate/templates/Arrays.js +++ b/scripts/generate/templates/Arrays.js @@ -346,7 +346,7 @@ function unsafeMemoryAccess(${type}[] memory arr, uint256 pos) internal pure ret const unsafeSetLength = type => `\ /** - * @dev Helper to set the length of an dynamic array. Directly writing to \`.length\` is forbidden. + * @dev Helper to set the length of a dynamic array. Directly writing to \`.length\` is forbidden. * * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. */ diff --git a/scripts/generate/templates/Checkpoints.js b/scripts/generate/templates/Checkpoints.js index 7ec4a7253..eb0f5c8f3 100644 --- a/scripts/generate/templates/Checkpoints.js +++ b/scripts/generate/templates/Checkpoints.js @@ -119,7 +119,7 @@ function latestCheckpoint(${opts.historyTypeName} storage self) internal view re } /** - * @dev Returns the number of checkpoint. + * @dev Returns the number of checkpoints. */ function length(${opts.historyTypeName} storage self) internal view returns (uint256) { return self.${opts.checkpointFieldName}.length; diff --git a/scripts/generate/templates/Checkpoints.t.js b/scripts/generate/templates/Checkpoints.t.js index edd2e9f98..77a9cd31a 100644 --- a/scripts/generate/templates/Checkpoints.t.js +++ b/scripts/generate/templates/Checkpoints.t.js @@ -14,7 +14,7 @@ import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol const template = opts => `\ using Checkpoints for Checkpoints.${opts.historyTypeName}; -// Maximum gap between keys used during the fuzzing tests: the \`_prepareKeys\` function with make sure that +// Maximum gap between keys used during the fuzzing tests: the \`_prepareKeys\` function will make sure that // key#n+1 is in the [key#n, key#n + _KEY_MAX_GAP] range. uint8 internal constant _KEY_MAX_GAP = 64; @@ -36,7 +36,7 @@ function _prepareKeys(${opts.keyTypeName}[] memory keys, ${opts.keyTypeName} max } } -function _assertLatestCheckpoint(bool exist, ${opts.keyTypeName} key, ${opts.valueTypeName} value) internal { +function _assertLatestCheckpoint(bool exist, ${opts.keyTypeName} key, ${opts.valueTypeName} value) internal view { (bool _exist, ${opts.keyTypeName} _key, ${opts.valueTypeName} _value) = _ckpts.latestCheckpoint(); assertEq(_exist, exist); assertEq(_key, key); diff --git a/scripts/generate/templates/EnumerableMap.js b/scripts/generate/templates/EnumerableMap.js index c9cad6c1b..284e5ac02 100644 --- a/scripts/generate/templates/EnumerableMap.js +++ b/scripts/generate/templates/EnumerableMap.js @@ -17,6 +17,7 @@ import {EnumerableSet} from "./EnumerableSet.sol"; * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. + * - Map can be cleared (all entries removed) in O(n). * * \`\`\`solidity * contract Example { @@ -91,6 +92,20 @@ function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns ( return map._keys.remove(key); } +/** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ +function clear(Bytes32ToBytes32Map storage map) internal { + uint256 len = length(map); + for (uint256 i = 0; i < len; ++i) { + delete map._values[map._keys.at(i)]; + } + map._keys.clear(); +} + /** * @dev Returns true if the key is in the map. O(1). */ @@ -188,6 +203,16 @@ function remove(${name} storage map, ${keyType} key) internal returns (bool) { return remove(map._inner, ${toBytes32(keyType, 'key')}); } +/** + * @dev Removes all the entries from a map. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block. + */ +function clear(${name} storage map) internal { + clear(map._inner); +} + /** * @dev Returns true if the key is in the map. O(1). */ diff --git a/scripts/generate/templates/EnumerableSet.js b/scripts/generate/templates/EnumerableSet.js index 02eccd0df..3169d6a46 100644 --- a/scripts/generate/templates/EnumerableSet.js +++ b/scripts/generate/templates/EnumerableSet.js @@ -5,6 +5,8 @@ const { TYPES } = require('./EnumerableSet.opts'); const header = `\ pragma solidity ^0.8.20; +import {Arrays} from "../Arrays.sol"; + /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive @@ -15,6 +17,7 @@ pragma solidity ^0.8.20; * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * - Set can be cleared (all elements removed) in O(n). * * \`\`\`solidity * contract Example { @@ -117,6 +120,20 @@ function _remove(Set storage set, bytes32 value) private returns (bool) { } } +/** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ +function _clear(Set storage set) private { + uint256 len = _length(set); + for (uint256 i = 0; i < len; ++i) { + delete set._positions[set._values[i]]; + } + Arrays.unsafeSetLength(set._values, 0); +} + /** * @dev Returns true if the value is in the set. O(1). */ @@ -185,6 +202,16 @@ function remove(${name} storage set, ${type} value) internal returns (bool) { return _remove(set._inner, ${toBytes32(type, 'value')}); } +/** + * @dev Removes all the values from a set. O(n). + * + * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the + * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block. + */ +function clear(${name} storage set) internal { + _clear(set._inner); +} + /** * @dev Returns true if the value is in the set. O(1). */ diff --git a/scripts/generate/templates/SlotDerivation.js b/scripts/generate/templates/SlotDerivation.js index ec4d244b9..a00e98167 100644 --- a/scripts/generate/templates/SlotDerivation.js +++ b/scripts/generate/templates/SlotDerivation.js @@ -20,7 +20,7 @@ pragma solidity ^0.8.20; * using SlotDerivation for bytes32; * * // Declare a namespace - * string private constant _NAMESPACE = "" // eg. OpenZeppelin.Slot + * string private constant _NAMESPACE = ""; // eg. OpenZeppelin.Slot * * function setValueInNamespace(uint256 key, address newValue) internal { * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue; diff --git a/scripts/generate/templates/SlotDerivation.t.js b/scripts/generate/templates/SlotDerivation.t.js index f03e1fc25..824af079a 100644 --- a/scripts/generate/templates/SlotDerivation.t.js +++ b/scripts/generate/templates/SlotDerivation.t.js @@ -45,7 +45,7 @@ function _assertDeriveArray(uint256 length, uint256 offset) public { const mapping = ({ type, name }) => `\ mapping(${type} => bytes) private _${type}Mapping; -function testSymbolicDeriveMapping${name}(${type} key) public { +function testSymbolicDeriveMapping${name}(${type} key) public view { bytes32 baseSlot; assembly { baseSlot := _${type}Mapping.slot @@ -76,15 +76,15 @@ function testSymbolicDeriveMapping${name}Dirty(bytes32 dirtyKey) public { const boundedMapping = ({ type, name }) => `\ mapping(${type} => bytes) private _${type}Mapping; -function testDeriveMapping${name}(${type} memory key) public { +function testDeriveMapping${name}(${type} memory key) public view { _assertDeriveMapping${name}(key); } -function symbolicDeriveMapping${name}() public { +function symbolicDeriveMapping${name}() public view { _assertDeriveMapping${name}(svm.create${name}(256, "DeriveMapping${name}Input")); } -function _assertDeriveMapping${name}(${type} memory key) internal { +function _assertDeriveMapping${name}(${type} memory key) internal view { bytes32 baseSlot; assembly { baseSlot := _${type}Mapping.slot diff --git a/scripts/generate/templates/TransientSlot.js b/scripts/generate/templates/TransientSlot.js index 8e291bc13..9ede32f85 100644 --- a/scripts/generate/templates/TransientSlot.js +++ b/scripts/generate/templates/TransientSlot.js @@ -34,7 +34,7 @@ pragma solidity ^0.8.24; const udvt = ({ type, name }) => `\ /** - * @dev UDVT that represent a slot holding a ${type}. + * @dev UDVT that represents a slot holding ${type == 'address' ? 'an' : 'a'} ${type}. */ type ${name}Slot is bytes32; diff --git a/scripts/prepare-docs.sh b/scripts/prepare-docs.sh index d1317b092..0ff5b94dc 100755 --- a/scripts/prepare-docs.sh +++ b/scripts/prepare-docs.sh @@ -18,7 +18,7 @@ examples_source_dir="contracts/mocks/docs" examples_target_dir="docs/modules/api/examples" for f in "$examples_source_dir"/**/*.sol; do - name="${f/#"$examples_source_dir/"/}" + name="${f/#"$examples_source_dir"/}" mkdir -p "$examples_target_dir/$(dirname "$name")" sed -Ee '/^import/s|"(\.\./)+|"@openzeppelin/contracts/|' "$f" > "$examples_target_dir/$name" done diff --git a/scripts/prepare.sh b/scripts/prepare.sh deleted file mode 100755 index a7d74227d..000000000 --- a/scripts/prepare.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -if git status &>/dev/null; then git config core.hooksPath .githooks; fi diff --git a/scripts/release/format-changelog.js b/scripts/release/format-changelog.js index b8bcc8c71..c96dc924a 100755 --- a/scripts/release/format-changelog.js +++ b/scripts/release/format-changelog.js @@ -27,7 +27,7 @@ const formatted = changelog .replace(RELEASE_LINE_REGEX, (_, pr, entry) => (pr ? `- ${entry} (${pr})` : `- ${entry}`)) // Add date to new version .replace(VERSION_TITLE_REGEX, `\n## $1 (${new Date().toISOString().split('T')[0]})`) - // Conditionally allow vX.Y.Z.rc-.W sections only in prerelease + // Conditionally allow vX.Y.Z-rc.W sections only in prerelease .replace(/^## \d\.\d\.\d-rc\S+[^]+?(?=^#)/gm, section => (isPrerelease ? section : '')); fs.writeFileSync('CHANGELOG.md', formatted); diff --git a/scripts/set-max-old-space-size.sh b/scripts/set-max-old-space-size.sh new file mode 100755 index 000000000..f56b11dc3 --- /dev/null +++ b/scripts/set-max-old-space-size.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env sh + +# This script sets the node `--max-old-space-size` to 8192 if it is not set already. +# All existing `NODE_OPTIONS` are retained as is. + +export NODE_OPTIONS="${NODE_OPTIONS:-}" + +if [ "${NODE_OPTIONS##*--max-old-space-size*}" = "$NODE_OPTIONS" ]; then + export NODE_OPTIONS="${NODE_OPTIONS} --max-old-space-size=8192" +fi diff --git a/scripts/solhint-custom/package.json b/scripts/solhint-custom/package.json index 075eb929d..ce9690d74 100644 --- a/scripts/solhint-custom/package.json +++ b/scripts/solhint-custom/package.json @@ -1,5 +1,8 @@ { "name": "solhint-plugin-openzeppelin", "version": "0.0.0", - "private": true + "private": true, + "dependencies": { + "minimatch": "^3.1.2" + } } diff --git a/scripts/upgradeable/upgradeable.patch b/scripts/upgradeable/upgradeable.patch index 458ecd435..5d54ef420 100644 --- a/scripts/upgradeable/upgradeable.patch +++ b/scripts/upgradeable/upgradeable.patch @@ -59,7 +59,7 @@ index ff596b0c3..000000000 - - diff --git a/README.md b/README.md -index fa7b4e31e..4799b6376 100644 +index 60d0a430a..0e4f91a6d 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,9 @@ @@ -110,7 +110,7 @@ index fa7b4e31e..4799b6376 100644 } ``` diff --git a/contracts/package.json b/contracts/package.json -index 845e8c403..8dc181b91 100644 +index 3682eadeb..4f870d094 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,5 +1,5 @@ @@ -118,7 +118,7 @@ index 845e8c403..8dc181b91 100644 - "name": "@openzeppelin/contracts", + "name": "@openzeppelin/contracts-upgradeable", "description": "Secure Smart Contract library for Solidity", - "version": "5.0.2", + "version": "5.2.0", "files": [ @@ -13,7 +13,7 @@ }, @@ -140,7 +140,7 @@ index 845e8c403..8dc181b91 100644 + } } diff --git a/contracts/utils/cryptography/EIP712.sol b/contracts/utils/cryptography/EIP712.sol -index 77c4c8990..602467f40 100644 +index bcb67c87a..7195c3bbd 100644 --- a/contracts/utils/cryptography/EIP712.sol +++ b/contracts/utils/cryptography/EIP712.sol @@ -4,7 +4,6 @@ @@ -151,7 +151,7 @@ index 77c4c8990..602467f40 100644 import {IERC5267} from "../../interfaces/IERC5267.sol"; /** -@@ -28,28 +27,18 @@ import {IERC5267} from "../../interfaces/IERC5267.sol"; +@@ -28,30 +27,18 @@ import {IERC5267} from "../../interfaces/IERC5267.sol"; * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. @@ -177,14 +177,16 @@ index 77c4c8990..602467f40 100644 - ShortString private immutable _name; - ShortString private immutable _version; +- // slither-disable-next-line constable-states - string private _nameFallback; +- // slither-disable-next-line constable-states - string private _versionFallback; + string private _name; + string private _version; /** * @dev Initializes the domain separator and parameter caches. -@@ -64,29 +53,23 @@ abstract contract EIP712 is IERC5267 { +@@ -66,29 +53,23 @@ abstract contract EIP712 is IERC5267 { * contract upgrade]. */ constructor(string memory name, string memory version) { @@ -222,7 +224,7 @@ index 77c4c8990..602467f40 100644 } /** -@@ -125,6 +108,10 @@ abstract contract EIP712 is IERC5267 { +@@ -127,6 +108,10 @@ abstract contract EIP712 is IERC5267 { uint256[] memory extensions ) { @@ -233,7 +235,7 @@ index 77c4c8990..602467f40 100644 return ( hex"0f", // 01111 _EIP712Name(), -@@ -139,22 +126,62 @@ abstract contract EIP712 is IERC5267 { +@@ -141,22 +126,62 @@ abstract contract EIP712 is IERC5267 { /** * @dev The name parameter for the EIP712 domain. * @@ -307,10 +309,10 @@ index 77c4c8990..602467f40 100644 } } diff --git a/package.json b/package.json -index c4b358e10..96ab2559c 100644 +index f9e7d9205..c35020d51 100644 --- a/package.json +++ b/package.json -@@ -32,7 +32,7 @@ +@@ -34,7 +34,7 @@ }, "repository": { "type": "git", diff --git a/slither.config.json b/slither.config.json index fa52f4dd1..47892af07 100644 --- a/slither.config.json +++ b/slither.config.json @@ -1,5 +1,4 @@ { "detectors_to_run": "arbitrary-send-erc20,array-by-reference,incorrect-shift,name-reused,rtlo,suicidal,uninitialized-state,uninitialized-storage,arbitrary-send-erc20-permit,controlled-array-length,controlled-delegatecall,delegatecall-loop,msg-value-loop,reentrancy-eth,unchecked-transfer,weak-prng,domain-separator-collision,erc20-interface,erc721-interface,locked-ether,mapping-deletion,shadowing-abstract,tautology,write-after-write,boolean-cst,reentrancy-no-eth,reused-constructor,tx-origin,unchecked-lowlevel,unchecked-send,variable-scope,void-cst,events-access,events-maths,incorrect-unary,boolean-equal,cyclomatic-complexity,deprecated-standards,erc20-indexed,function-init-state,pragma,unused-state,reentrancy-unlimited-gas,constable-states,immutable-states,var-read-using-this", - "filter_paths": "contracts/mocks,contracts/vendor,contracts-exposed", - "compile_force_framework": "hardhat" + "filter_paths": "contracts/mocks,contracts/vendor,contracts-exposed" } diff --git a/solhint.config.js b/solhint.config.js index f0bd7994f..47c1cebfe 100644 --- a/solhint.config.js +++ b/solhint.config.js @@ -1,4 +1,4 @@ -const customRules = require('./scripts/solhint-custom'); +const customRules = require('solhint-plugin-openzeppelin'); const rules = [ 'avoid-tx-origin', diff --git a/test/TESTING.md b/test/TESTING.md index a5ee9323f..321c7e592 100644 --- a/test/TESTING.md +++ b/test/TESTING.md @@ -1,3 +1,3 @@ ## Testing -Unit test are critical to OpenZeppelin Contracts. They help ensure code quality and mitigate against security vulnerabilities. The directory structure within the `/test` directory corresponds to the `/contracts` directory. +Unit tests are critical to OpenZeppelin Contracts. They help ensure code quality and mitigate against security vulnerabilities. The directory structure within the `/test` directory corresponds to the `/contracts` directory. diff --git a/test/access/AccessControl.behavior.js b/test/access/AccessControl.behavior.js index b7ae2a950..c596e6a2e 100644 --- a/test/access/AccessControl.behavior.js +++ b/test/access/AccessControl.behavior.js @@ -21,7 +21,7 @@ function shouldBehaveLikeAccessControl() { expect(await this.mock.hasRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin)).to.be.true; }); - it("other roles's admin is the default admin role", async function () { + it("other role's admin is the default admin role", async function () { expect(await this.mock.getRoleAdmin(ROLE)).to.equal(DEFAULT_ADMIN_ROLE); }); diff --git a/test/access/manager/AuthorityUtils.test.js b/test/access/manager/AuthorityUtils.test.js index 905913f14..465f617ad 100644 --- a/test/access/manager/AuthorityUtils.test.js +++ b/test/access/manager/AuthorityUtils.test.js @@ -2,6 +2,8 @@ const { ethers } = require('hardhat'); const { expect } = require('chai'); const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); +const { MAX_UINT32, MAX_UINT64 } = require('../../helpers/constants'); + async function fixture() { const [user, other] = await ethers.getSigners(); @@ -70,7 +72,7 @@ describe('AuthorityUtils', function () { }); for (const immediate of [true, false]) { - for (const delay of [0n, 42n]) { + for (const delay of [0n, 42n, MAX_UINT32]) { it(`returns (immediate=${immediate}, delay=${delay})`, async function () { await this.authority._setImmediate(immediate); await this.authority._setDelay(delay); @@ -80,6 +82,14 @@ describe('AuthorityUtils', function () { }); } } + + it('out of bound delay', async function () { + await this.authority._setImmediate(false); + await this.authority._setDelay(MAX_UINT64); // bigger than the expected uint32 + const result = await this.mock.$canCallWithDelay(this.authority, this.user, this.other, '0x12345678'); + expect(result.immediate).to.equal(false); + expect(result.delay).to.equal(0n); + }); }); describe('when authority replies with empty data', function () { diff --git a/test/account/utils/draft-ERC4337Utils.test.js b/test/account/utils/draft-ERC4337Utils.test.js index 7c292910d..ab4f345d2 100644 --- a/test/account/utils/draft-ERC4337Utils.test.js +++ b/test/account/utils/draft-ERC4337Utils.test.js @@ -1,19 +1,18 @@ -const { ethers } = require('hardhat'); +const { ethers, entrypoint } = require('hardhat'); const { expect } = require('chai'); const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); const { packValidationData, UserOperation } = require('../../helpers/erc4337'); -const { deployEntrypoint } = require('../../helpers/erc4337-entrypoint'); const { MAX_UINT48 } = require('../../helpers/constants'); const ADDRESS_ONE = '0x0000000000000000000000000000000000000001'; const fixture = async () => { - const { entrypoint } = await deployEntrypoint(); const [authorizer, sender, factory, paymaster] = await ethers.getSigners(); const utils = await ethers.deployContract('$ERC4337Utils'); const SIG_VALIDATION_SUCCESS = await utils.$SIG_VALIDATION_SUCCESS(); const SIG_VALIDATION_FAILED = await utils.$SIG_VALIDATION_FAILED(); - return { utils, authorizer, sender, entrypoint, factory, paymaster, SIG_VALIDATION_SUCCESS, SIG_VALIDATION_FAILED }; + + return { utils, authorizer, sender, factory, paymaster, SIG_VALIDATION_SUCCESS, SIG_VALIDATION_FAILED }; }; describe('ERC4337Utils', function () { @@ -21,6 +20,16 @@ describe('ERC4337Utils', function () { Object.assign(this, await loadFixture(fixture)); }); + describe('entrypoint', function () { + it('v0.7.0', async function () { + await expect(this.utils.$ENTRYPOINT_V07()).to.eventually.equal(entrypoint.v07); + }); + + it('v0.8.0', async function () { + await expect(this.utils.$ENTRYPOINT_V08()).to.eventually.equal(entrypoint.v08); + }); + }); + describe('parseValidationData', function () { it('parses the validation data', async function () { const authorizer = this.authorizer; @@ -28,7 +37,7 @@ describe('ERC4337Utils', function () { const validAfter = 0x9abcdef0n; const validationData = packValidationData(validAfter, validUntil, authorizer); - expect(this.utils.$parseValidationData(validationData)).to.eventually.deep.equal([ + await expect(this.utils.$parseValidationData(validationData)).to.eventually.deep.equal([ authorizer.address, validAfter, validUntil, @@ -40,7 +49,7 @@ describe('ERC4337Utils', function () { const validAfter = 0x12345678n; const validationData = packValidationData(validAfter, 0, authorizer); - expect(this.utils.$parseValidationData(validationData)).to.eventually.deep.equal([ + await expect(this.utils.$parseValidationData(validationData)).to.eventually.deep.equal([ authorizer.address, validAfter, MAX_UINT48, @@ -48,13 +57,13 @@ describe('ERC4337Utils', function () { }); it('parse canonical values', async function () { - expect(this.utils.$parseValidationData(this.SIG_VALIDATION_SUCCESS)).to.eventually.deep.equal([ + await expect(this.utils.$parseValidationData(this.SIG_VALIDATION_SUCCESS)).to.eventually.deep.equal([ ethers.ZeroAddress, 0n, MAX_UINT48, ]); - expect(this.utils.$parseValidationData(this.SIG_VALIDATION_FAILED)).to.eventually.deep.equal([ + await expect(this.utils.$parseValidationData(this.SIG_VALIDATION_FAILED)).to.eventually.deep.equal([ ADDRESS_ONE, 0n, MAX_UINT48, @@ -69,7 +78,7 @@ describe('ERC4337Utils', function () { const validAfter = 0x9abcdef0n; const validationData = packValidationData(validAfter, validUntil, authorizer); - expect( + await expect( this.utils.$packValidationData(ethers.Typed.address(authorizer), validAfter, validUntil), ).to.eventually.equal(validationData); }); @@ -80,22 +89,22 @@ describe('ERC4337Utils', function () { const validAfter = 0x9abcdef0n; const validationData = packValidationData(validAfter, validUntil, false); - expect(this.utils.$packValidationData(ethers.Typed.bool(success), validAfter, validUntil)).to.eventually.equal( - validationData, - ); + await expect( + this.utils.$packValidationData(ethers.Typed.bool(success), validAfter, validUntil), + ).to.eventually.equal(validationData); }); it('packing reproduced canonical values', async function () { - expect(this.utils.$packValidationData(ethers.Typed.address(ethers.ZeroAddress), 0n, 0n)).to.eventually.equal( + await expect( + this.utils.$packValidationData(ethers.Typed.address(ethers.ZeroAddress), 0n, 0n), + ).to.eventually.equal(this.SIG_VALIDATION_SUCCESS); + await expect(this.utils.$packValidationData(ethers.Typed.bool(true), 0n, 0n)).to.eventually.equal( this.SIG_VALIDATION_SUCCESS, ); - expect(this.utils.$packValidationData(ethers.Typed.bool(true), 0n, 0n)).to.eventually.equal( - this.SIG_VALIDATION_SUCCESS, - ); - expect(this.utils.$packValidationData(ethers.Typed.address(ADDRESS_ONE), 0n, 0n)).to.eventually.equal( + await expect(this.utils.$packValidationData(ethers.Typed.address(ADDRESS_ONE), 0n, 0n)).to.eventually.equal( this.SIG_VALIDATION_FAILED, ); - expect(this.utils.$packValidationData(ethers.Typed.bool(false), 0n, 0n)).to.eventually.equal( + await expect(this.utils.$packValidationData(ethers.Typed.bool(false), 0n, 0n)).to.eventually.equal( this.SIG_VALIDATION_FAILED, ); }); @@ -113,8 +122,8 @@ describe('ERC4337Utils', function () { const expected = packValidationData(validAfter2, validUntil1, true); // check symmetry - expect(this.utils.$combineValidationData(validationData1, validationData2)).to.eventually.equal(expected); - expect(this.utils.$combineValidationData(validationData2, validationData1)).to.eventually.equal(expected); + await expect(this.utils.$combineValidationData(validationData1, validationData2)).to.eventually.equal(expected); + await expect(this.utils.$combineValidationData(validationData2, validationData1)).to.eventually.equal(expected); }); for (const [authorizer1, authorizer2] of [ @@ -127,8 +136,8 @@ describe('ERC4337Utils', function () { const expected = packValidationData(validAfter2, validUntil1, false); // check symmetry - expect(this.utils.$combineValidationData(validationData1, validationData2)).to.eventually.equal(expected); - expect(this.utils.$combineValidationData(validationData2, validationData1)).to.eventually.equal(expected); + await expect(this.utils.$combineValidationData(validationData1, validationData2)).to.eventually.equal(expected); + await expect(this.utils.$combineValidationData(validationData2, validationData1)).to.eventually.equal(expected); }); } }); @@ -140,7 +149,7 @@ describe('ERC4337Utils', function () { const validUntil = MAX_UINT48; const validationData = packValidationData(validAfter, validUntil, aggregator); - expect(this.utils.$getValidationData(validationData)).to.eventually.deep.equal([aggregator.address, false]); + await expect(this.utils.$getValidationData(validationData)).to.eventually.deep.equal([aggregator.address, false]); }); it('returns the validation data with invalid validity range (expired)', async function () { @@ -149,7 +158,7 @@ describe('ERC4337Utils', function () { const validUntil = 1; const validationData = packValidationData(validAfter, validUntil, aggregator); - expect(this.utils.$getValidationData(validationData)).to.eventually.deep.equal([aggregator.address, true]); + await expect(this.utils.$getValidationData(validationData)).to.eventually.deep.equal([aggregator.address, true]); }); it('returns the validation data with invalid validity range (not yet valid)', async function () { @@ -158,31 +167,23 @@ describe('ERC4337Utils', function () { const validUntil = MAX_UINT48; const validationData = packValidationData(validAfter, validUntil, aggregator); - expect(this.utils.$getValidationData(validationData)).to.eventually.deep.equal([aggregator.address, true]); + await expect(this.utils.$getValidationData(validationData)).to.eventually.deep.equal([aggregator.address, true]); }); - it('returns address(0) and false for validationData = 0', function () { - expect(this.utils.$getValidationData(0n)).to.eventually.deep.equal([ethers.ZeroAddress, false]); + it('returns address(0) and false for validationData = 0', async function () { + await expect(this.utils.$getValidationData(0n)).to.eventually.deep.equal([ethers.ZeroAddress, false]); }); }); describe('hash', function () { - it('returns the operation hash with specified entrypoint and chainId', async function () { - const userOp = new UserOperation({ sender: this.sender, nonce: 1 }); - const chainId = await ethers.provider.getNetwork().then(({ chainId }) => chainId); - const otherChainId = 0xdeadbeef; + for (const [version, instance] of Object.entries(entrypoint)) { + it(`returns the operation hash for entrypoint ${version}`, async function () { + const userOp = new UserOperation({ sender: this.sender, nonce: 1 }); + const expected = await userOp.hash(instance); - // check that helper matches entrypoint logic - expect(this.entrypoint.getUserOpHash(userOp.packed)).to.eventually.equal(userOp.hash(this.entrypoint, chainId)); - - // check library against helper - expect(this.utils.$hash(userOp.packed, this.entrypoint, chainId)).to.eventually.equal( - userOp.hash(this.entrypoint, chainId), - ); - expect(this.utils.$hash(userOp.packed, this.entrypoint, otherChainId)).to.eventually.equal( - userOp.hash(this.entrypoint, otherChainId), - ); - }); + await expect(this.utils.$hash(userOp.packed, instance)).to.eventually.equal(expected); + }); + } }); describe('userOp values', function () { @@ -203,34 +204,34 @@ describe('ERC4337Utils', function () { }); it('returns factory', async function () { - expect(this.utils.$factory(this.userOp.packed)).to.eventually.equal(this.factory); - expect(this.utils.$factory(this.emptyUserOp.packed)).to.eventually.equal(ethers.ZeroAddress); + await expect(this.utils.$factory(this.userOp.packed)).to.eventually.equal(this.factory); + await expect(this.utils.$factory(this.emptyUserOp.packed)).to.eventually.equal(ethers.ZeroAddress); }); it('returns factoryData', async function () { - expect(this.utils.$factoryData(this.userOp.packed)).to.eventually.equal('0x123456'); - expect(this.utils.$factoryData(this.emptyUserOp.packed)).to.eventually.equal('0x'); + await expect(this.utils.$factoryData(this.userOp.packed)).to.eventually.equal('0x123456'); + await expect(this.utils.$factoryData(this.emptyUserOp.packed)).to.eventually.equal('0x'); }); }); it('returns verificationGasLimit', async function () { const userOp = new UserOperation({ sender: this.sender, nonce: 1, verificationGas: 0x12345678n }); - expect(this.utils.$verificationGasLimit(userOp.packed)).to.eventually.equal(userOp.verificationGas); + await expect(this.utils.$verificationGasLimit(userOp.packed)).to.eventually.equal(userOp.verificationGas); }); it('returns callGasLimit', async function () { const userOp = new UserOperation({ sender: this.sender, nonce: 1, callGas: 0x12345678n }); - expect(this.utils.$callGasLimit(userOp.packed)).to.eventually.equal(userOp.callGas); + await expect(this.utils.$callGasLimit(userOp.packed)).to.eventually.equal(userOp.callGas); }); it('returns maxPriorityFeePerGas', async function () { const userOp = new UserOperation({ sender: this.sender, nonce: 1, maxPriorityFee: 0x12345678n }); - expect(this.utils.$maxPriorityFeePerGas(userOp.packed)).to.eventually.equal(userOp.maxPriorityFee); + await expect(this.utils.$maxPriorityFeePerGas(userOp.packed)).to.eventually.equal(userOp.maxPriorityFee); }); it('returns maxFeePerGas', async function () { const userOp = new UserOperation({ sender: this.sender, nonce: 1, maxFeePerGas: 0x12345678n }); - expect(this.utils.$maxFeePerGas(userOp.packed)).to.eventually.equal(userOp.maxFeePerGas); + await expect(this.utils.$maxFeePerGas(userOp.packed)).to.eventually.equal(userOp.maxFeePerGas); }); it('returns gasPrice', async function () { @@ -240,7 +241,7 @@ describe('ERC4337Utils', function () { maxPriorityFee: 0x12345678n, maxFeePerGas: 0x87654321n, }); - expect(this.utils.$gasPrice(userOp.packed)).to.eventually.equal(userOp.maxPriorityFee); + await expect(this.utils.$gasPrice(userOp.packed)).to.eventually.equal(userOp.maxPriorityFee); }); describe('paymasterAndData', function () { @@ -261,27 +262,27 @@ describe('ERC4337Utils', function () { }); it('returns paymaster', async function () { - expect(this.utils.$paymaster(this.userOp.packed)).to.eventually.equal(this.userOp.paymaster); - expect(this.utils.$paymaster(this.emptyUserOp.packed)).to.eventually.equal(ethers.ZeroAddress); + await expect(this.utils.$paymaster(this.userOp.packed)).to.eventually.equal(this.userOp.paymaster); + await expect(this.utils.$paymaster(this.emptyUserOp.packed)).to.eventually.equal(ethers.ZeroAddress); }); it('returns verificationGasLimit', async function () { - expect(this.utils.$paymasterVerificationGasLimit(this.userOp.packed)).to.eventually.equal( + await expect(this.utils.$paymasterVerificationGasLimit(this.userOp.packed)).to.eventually.equal( this.userOp.paymasterVerificationGasLimit, ); - expect(this.utils.$paymasterVerificationGasLimit(this.emptyUserOp.packed)).to.eventually.equal(0n); + await expect(this.utils.$paymasterVerificationGasLimit(this.emptyUserOp.packed)).to.eventually.equal(0n); }); it('returns postOpGasLimit', async function () { - expect(this.utils.$paymasterPostOpGasLimit(this.userOp.packed)).to.eventually.equal( + await expect(this.utils.$paymasterPostOpGasLimit(this.userOp.packed)).to.eventually.equal( this.userOp.paymasterPostOpGasLimit, ); - expect(this.utils.$paymasterPostOpGasLimit(this.emptyUserOp.packed)).to.eventually.equal(0n); + await expect(this.utils.$paymasterPostOpGasLimit(this.emptyUserOp.packed)).to.eventually.equal(0n); }); it('returns data', async function () { - expect(this.utils.$paymasterData(this.userOp.packed)).to.eventually.equal(this.userOp.paymasterData); - expect(this.utils.$paymasterData(this.emptyUserOp.packed)).to.eventually.equal('0x'); + await expect(this.utils.$paymasterData(this.userOp.packed)).to.eventually.equal(this.userOp.paymasterData); + await expect(this.utils.$paymasterData(this.emptyUserOp.packed)).to.eventually.equal('0x'); }); }); }); diff --git a/test/account/utils/draft-ERC7579Utils.t.sol b/test/account/utils/draft-ERC7579Utils.t.sol index fdd4edf59..bc69e4c34 100644 --- a/test/account/utils/draft-ERC7579Utils.t.sol +++ b/test/account/utils/draft-ERC7579Utils.t.sol @@ -20,8 +20,6 @@ contract SampleAccount is IAccount, Ownable { using ERC4337Utils for *; using ERC7579Utils for *; - IEntryPoint internal constant ENTRY_POINT = IEntryPoint(payable(0x0000000071727De22E5E9d8BAf0edAc6f37da032)); - event Log(bool duringValidation, Execution[] calls); error UnsupportedCallType(CallType callType); @@ -33,7 +31,7 @@ contract SampleAccount is IAccount, Ownable { bytes32 userOpHash, uint256 missingAccountFunds ) external override returns (uint256 validationData) { - require(msg.sender == address(ENTRY_POINT), "only from EP"); + require(msg.sender == address(ERC4337Utils.ENTRYPOINT_V07), "only from EP"); // Check signature if (userOpHash.toEthSignedMessageHash().recover(userOp.signature) != owner()) { revert OwnableUnauthorizedAccount(_msgSender()); @@ -66,7 +64,7 @@ contract SampleAccount is IAccount, Ownable { // builtin decoder for the `execute` function. // This is where the vulnerability from ExecutionLib results in a different result between validation - // andexecution. + // and execution. emit Log(true, executionCalldata.decodeBatch()); } @@ -81,7 +79,7 @@ contract SampleAccount is IAccount, Ownable { } function execute(Mode mode, bytes calldata executionCalldata) external payable { - require(msg.sender == address(this) || msg.sender == address(ENTRY_POINT), "not auth"); + require(msg.sender == address(this) || msg.sender == address(ERC4337Utils.ENTRYPOINT_V07), "not auth"); (CallType callType, ExecType execType, , ) = mode.decodeMode(); @@ -105,7 +103,6 @@ contract ERC7579UtilsTest is Test { using ERC4337Utils for *; using ERC7579Utils for *; - IEntryPoint private constant ENTRYPOINT = IEntryPoint(payable(0x0000000071727De22E5E9d8BAf0edAc6f37da032)); address private _owner; uint256 private _ownerKey; address private _account; @@ -166,7 +163,7 @@ contract ERC7579UtilsTest is Test { userOps[0].signature = abi.encodePacked(r, s, v); vm.recordLogs(); - ENTRYPOINT.handleOps(userOps, payable(_beneficiary)); + ERC4337Utils.ENTRYPOINT_V07.handleOps(userOps, payable(_beneficiary)); assertEq(_recipient1.balance, 1 wei); assertEq(_recipient2.balance, 1 wei); @@ -224,7 +221,7 @@ contract ERC7579UtilsTest is Test { abi.encodeWithSelector(ERC7579Utils.ERC7579DecodingError.selector) ) ); - ENTRYPOINT.handleOps(userOps, payable(_beneficiary)); + ERC4337Utils.ENTRYPOINT_V07.handleOps(userOps, payable(_beneficiary)); _collectAndPrintLogs(false); } @@ -282,7 +279,7 @@ contract ERC7579UtilsTest is Test { abi.encodeWithSelector(ERC7579Utils.ERC7579DecodingError.selector) ) ); - ENTRYPOINT.handleOps(userOps, payable(_beneficiary)); + ERC4337Utils.ENTRYPOINT_V07.handleOps(userOps, payable(_beneficiary)); _collectAndPrintLogs(true); } @@ -378,7 +375,7 @@ contract ERC7579UtilsTest is Test { } function hashUserOperation(PackedUserOperation calldata useroperation) public view returns (bytes32) { - return useroperation.hash(address(ENTRYPOINT), block.chainid); + return useroperation.hash(address(ERC4337Utils.ENTRYPOINT_V07)); } function _collectAndPrintLogs(bool includeTotalValue) internal { diff --git a/test/account/utils/draft-ERC7579Utils.test.js b/test/account/utils/draft-ERC7579Utils.test.js index 7419c667b..b0ca86c46 100644 --- a/test/account/utils/draft-ERC7579Utils.test.js +++ b/test/account/utils/draft-ERC7579Utils.test.js @@ -2,13 +2,14 @@ const { ethers } = require('hardhat'); const { expect } = require('chai'); const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); const { + CALL_TYPE_CALL, + CALL_TYPE_BATCH, + CALL_TYPE_DELEGATE, EXEC_TYPE_DEFAULT, EXEC_TYPE_TRY, encodeSingle, encodeBatch, encodeDelegate, - CALL_TYPE_CALL, - CALL_TYPE_BATCH, encodeMode, } = require('../../helpers/erc7579'); const { selector } = require('../../helpers/methods'); @@ -29,6 +30,14 @@ describe('ERC7579Utils', function () { Object.assign(this, await loadFixture(fixture)); }); + it('constants', async function () { + await expect(this.utils.$CALLTYPE_SINGLE()).to.eventually.equal(CALL_TYPE_CALL); + await expect(this.utils.$CALLTYPE_BATCH()).to.eventually.equal(CALL_TYPE_BATCH); + await expect(this.utils.$CALLTYPE_DELEGATECALL()).to.eventually.equal(CALL_TYPE_DELEGATE); + await expect(this.utils.$EXECTYPE_DEFAULT()).to.eventually.equal(EXEC_TYPE_DEFAULT); + await expect(this.utils.$EXECTYPE_TRY()).to.eventually.equal(EXEC_TYPE_TRY); + }); + describe('execSingle', function () { it('calls the target with value', async function () { const value = 0x012; @@ -36,7 +45,7 @@ describe('ERC7579Utils', function () { await expect(this.utils.$execSingle(data, EXEC_TYPE_DEFAULT)).to.emit(this.target, 'MockFunctionCalled'); - expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value); + await expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value); }); it('calls the target with value and args', async function () { @@ -51,7 +60,19 @@ describe('ERC7579Utils', function () { .to.emit(this.target, 'MockFunctionCalledWithArgs') .withArgs(42, '0x1234'); - expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value); + await expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value); + }); + + it('default to calling self is target is address(0) (ERC-7821 calldata compression)', async function () { + const data = encodeSingle( + ethers.ZeroAddress, // address(0) + 0, + this.utils.interface.encodeFunctionData('$CALLTYPE_SINGLE', []), + ); + + await expect(this.utils.$execSingle(data, EXEC_TYPE_DEFAULT)) + .to.emit(this.utils, 'return$execSingle') + .withArgs([ethers.zeroPadBytes(CALL_TYPE_CALL, 32)]); }); it('reverts when target reverts in default ExecType', async function () { @@ -107,8 +128,8 @@ describe('ERC7579Utils', function () { .to.emit(this.target, 'MockFunctionCalled') .to.emit(this.anotherTarget, 'MockFunctionCalled'); - expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value1); - expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(value2); + await expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value1); + await expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(value2); }); it('calls the targets with value and args', async function () { @@ -127,8 +148,19 @@ describe('ERC7579Utils', function () { .to.emit(this.target, 'MockFunctionCalledWithArgs') .to.emit(this.anotherTarget, 'MockFunctionCalledWithArgs'); - expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value1); - expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(value2); + await expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value1); + await expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(value2); + }); + + it('default to calling self is target is address(0) (ERC-7821 calldata compression)', async function () { + const data = encodeBatch( + [ethers.ZeroAddress, 0, this.utils.interface.encodeFunctionData('$CALLTYPE_SINGLE', [])], + [ethers.ZeroAddress, 0, this.utils.interface.encodeFunctionData('$CALLTYPE_BATCH', [])], + ); + + await expect(this.utils.$execBatch(data, EXEC_TYPE_DEFAULT)) + .to.emit(this.utils, 'return$execBatch') + .withArgs([ethers.zeroPadBytes(CALL_TYPE_CALL, 32), ethers.zeroPadBytes(CALL_TYPE_BATCH, 32)]); }); it('reverts when any target reverts in default ExecType', async function () { @@ -161,8 +193,8 @@ describe('ERC7579Utils', function () { ); // Check balances - expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value1); - expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(0); + await expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value1); + await expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(0); }); it('reverts with an invalid exec type', async function () { @@ -188,9 +220,20 @@ describe('ERC7579Utils', function () { this.target.interface.encodeFunctionData('mockFunctionWritesStorage', [slot, value]), ); - expect(ethers.provider.getStorage(this.utils.target, slot)).to.eventually.equal(ethers.ZeroHash); + await expect(ethers.provider.getStorage(this.utils.target, slot)).to.eventually.equal(ethers.ZeroHash); await this.utils.$execDelegateCall(data, EXEC_TYPE_DEFAULT); - expect(ethers.provider.getStorage(this.utils.target, slot)).to.eventually.equal(value); + await expect(ethers.provider.getStorage(this.utils.target, slot)).to.eventually.equal(value); + }); + + it('default to calling self is target is address(0) (ERC-7821 calldata compression)', async function () { + const data = encodeDelegate( + ethers.ZeroAddress, + this.utils.interface.encodeFunctionData('$CALLTYPE_DELEGATECALL', []), + ); + + await expect(this.utils.$execDelegateCall(data, EXEC_TYPE_DEFAULT)) + .to.emit(this.utils, 'return$execDelegateCall') + .withArgs([ethers.zeroPadBytes(CALL_TYPE_DELEGATE, 32)]); }); it('reverts when target reverts in default ExecType', async function () { @@ -227,7 +270,7 @@ describe('ERC7579Utils', function () { const selector = '0x12345678'; const payload = ethers.toBeHex(0, 22); - expect(this.utils.$encodeMode(callType, execType, selector, payload)).to.eventually.equal( + await expect(this.utils.$encodeMode(callType, execType, selector, payload)).to.eventually.equal( encodeMode({ callType, execType, @@ -243,7 +286,7 @@ describe('ERC7579Utils', function () { const selector = '0x12345678'; const payload = ethers.toBeHex(0, 22); - expect( + await expect( this.utils.$decodeMode( encodeMode({ callType, @@ -260,7 +303,7 @@ describe('ERC7579Utils', function () { const value = 0x123; const data = '0x12345678'; - expect(this.utils.$encodeSingle(target, value, data)).to.eventually.equal(encodeSingle(target, value, data)); + await expect(this.utils.$encodeSingle(target, value, data)).to.eventually.equal(encodeSingle(target, value, data)); }); it('decodes single', async function () { @@ -268,7 +311,7 @@ describe('ERC7579Utils', function () { const value = 0x123; const data = '0x12345678'; - expect(this.utils.$decodeSingle(encodeSingle(target, value, data))).to.eventually.deep.equal([ + await expect(this.utils.$decodeSingle(encodeSingle(target, value, data))).to.eventually.deep.equal([ target.target, value, data, @@ -281,7 +324,7 @@ describe('ERC7579Utils', function () { [this.anotherTarget, 0x456, '0x12345678'], ]; - expect(this.utils.$encodeBatch(entries)).to.eventually.equal(encodeBatch(...entries)); + await expect(this.utils.$encodeBatch(entries)).to.eventually.equal(encodeBatch(...entries)); }); it('decodes batch', async function () { @@ -290,63 +333,66 @@ describe('ERC7579Utils', function () { [this.anotherTarget.target, 0x456, '0x12345678'], ]; - expect(this.utils.$decodeBatch(encodeBatch(...entries))).to.eventually.deep.equal(entries); + await expect(this.utils.$decodeBatch(encodeBatch(...entries))).to.eventually.deep.equal(entries); }); it('encodes delegate', async function () { const target = this.target; const data = '0x12345678'; - expect(this.utils.$encodeDelegate(target, data)).to.eventually.equal(encodeDelegate(target, data)); + await expect(this.utils.$encodeDelegate(target, data)).to.eventually.equal(encodeDelegate(target, data)); }); it('decodes delegate', async function () { const target = this.target; const data = '0x12345678'; - expect(this.utils.$decodeDelegate(encodeDelegate(target, data))).to.eventually.deep.equal([target.target, data]); + await expect(this.utils.$decodeDelegate(encodeDelegate(target, data))).to.eventually.deep.equal([ + target.target, + data, + ]); }); describe('global', function () { describe('eqCallTypeGlobal', function () { it('returns true if both call types are equal', async function () { - expect(this.utilsGlobal.$eqCallTypeGlobal(CALL_TYPE_BATCH, CALL_TYPE_BATCH)).to.eventually.be.true; + await expect(this.utilsGlobal.$eqCallTypeGlobal(CALL_TYPE_BATCH, CALL_TYPE_BATCH)).to.eventually.be.true; }); it('returns false if both call types are different', async function () { - expect(this.utilsGlobal.$eqCallTypeGlobal(CALL_TYPE_CALL, CALL_TYPE_BATCH)).to.eventually.be.false; + await expect(this.utilsGlobal.$eqCallTypeGlobal(CALL_TYPE_CALL, CALL_TYPE_BATCH)).to.eventually.be.false; }); }); describe('eqExecTypeGlobal', function () { it('returns true if both exec types are equal', async function () { - expect(this.utilsGlobal.$eqExecTypeGlobal(EXEC_TYPE_TRY, EXEC_TYPE_TRY)).to.eventually.be.true; + await expect(this.utilsGlobal.$eqExecTypeGlobal(EXEC_TYPE_TRY, EXEC_TYPE_TRY)).to.eventually.be.true; }); it('returns false if both exec types are different', async function () { - expect(this.utilsGlobal.$eqExecTypeGlobal(EXEC_TYPE_DEFAULT, EXEC_TYPE_TRY)).to.eventually.be.false; + await expect(this.utilsGlobal.$eqExecTypeGlobal(EXEC_TYPE_DEFAULT, EXEC_TYPE_TRY)).to.eventually.be.false; }); }); describe('eqModeSelectorGlobal', function () { it('returns true if both selectors are equal', async function () { - expect(this.utilsGlobal.$eqModeSelectorGlobal('0x12345678', '0x12345678')).to.eventually.be.true; + await expect(this.utilsGlobal.$eqModeSelectorGlobal('0x12345678', '0x12345678')).to.eventually.be.true; }); it('returns false if both selectors are different', async function () { - expect(this.utilsGlobal.$eqModeSelectorGlobal('0x12345678', '0x87654321')).to.eventually.be.false; + await expect(this.utilsGlobal.$eqModeSelectorGlobal('0x12345678', '0x87654321')).to.eventually.be.false; }); }); describe('eqModePayloadGlobal', function () { it('returns true if both payloads are equal', async function () { - expect(this.utilsGlobal.$eqModePayloadGlobal(ethers.toBeHex(0, 22), ethers.toBeHex(0, 22))).to.eventually.be - .true; + await expect(this.utilsGlobal.$eqModePayloadGlobal(ethers.toBeHex(0, 22), ethers.toBeHex(0, 22))).to.eventually + .be.true; }); it('returns false if both payloads are different', async function () { - expect(this.utilsGlobal.$eqModePayloadGlobal(ethers.toBeHex(0, 22), ethers.toBeHex(1, 22))).to.eventually.be - .false; + await expect(this.utilsGlobal.$eqModePayloadGlobal(ethers.toBeHex(0, 22), ethers.toBeHex(1, 22))).to.eventually + .be.false; }); }); }); diff --git a/test/bin/EntryPoint080.abi b/test/bin/EntryPoint080.abi new file mode 100644 index 000000000..22fd32c46 --- /dev/null +++ b/test/bin/EntryPoint080.abi @@ -0,0 +1 @@ +[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"ret","type":"bytes"}],"name":"DelegateAndRevert","type":"error"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"}],"name":"FailedOp","type":"error"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"inner","type":"bytes"}],"name":"FailedOpWithRevert","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"bytes","name":"returnData","type":"bytes"}],"name":"PostOpReverted","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderAddressResult","type":"error"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"}],"name":"SignatureValidationFailed","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"factory","type":"address"},{"indexed":false,"internalType":"address","name":"paymaster","type":"address"}],"name":"AccountDeployed","type":"event"},{"anonymous":false,"inputs":[],"name":"BeforeExecution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalDeposit","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"revertReason","type":"bytes"}],"name":"PostOpRevertReason","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"aggregator","type":"address"}],"name":"SignatureAggregatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalStaked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"name":"StakeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawTime","type":"uint256"}],"name":"StakeUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"paymaster","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint256","name":"actualGasCost","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"actualGasUsed","type":"uint256"}],"name":"UserOperationEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"UserOperationPrefundTooLow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"revertReason","type":"bytes"}],"name":"UserOperationRevertReason","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"}],"name":"addStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"delegateAndRevert","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"depositTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getDepositInfo","outputs":[{"components":[{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"bool","name":"staked","type":"bool"},{"internalType":"uint112","name":"stake","type":"uint112"},{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"},{"internalType":"uint48","name":"withdrawTime","type":"uint48"}],"internalType":"struct IStakeManager.DepositInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeparatorV4","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint192","name":"key","type":"uint192"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPackedUserOpTypeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"initCode","type":"bytes"}],"name":"getSenderAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation","name":"userOp","type":"tuple"}],"name":"getUserOpHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation[]","name":"userOps","type":"tuple[]"},{"internalType":"contract IAggregator","name":"aggregator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct IEntryPoint.UserOpsPerAggregator[]","name":"opsPerAggregator","type":"tuple[]"},{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"handleAggregatedOps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation[]","name":"ops","type":"tuple[]"},{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"handleOps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint192","name":"key","type":"uint192"}],"name":"incrementNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"callData","type":"bytes"},{"components":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterVerificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterPostOpGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"address","name":"paymaster","type":"address"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"}],"internalType":"struct EntryPoint.MemoryUserOp","name":"mUserOp","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"prefund","type":"uint256"},{"internalType":"uint256","name":"contextOffset","type":"uint256"},{"internalType":"uint256","name":"preOpGas","type":"uint256"}],"internalType":"struct EntryPoint.UserOpInfo","name":"opInfo","type":"tuple"},{"internalType":"bytes","name":"context","type":"bytes"}],"name":"innerHandleOp","outputs":[{"internalType":"uint256","name":"actualGasCost","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint192","name":"","type":"uint192"}],"name":"nonceSequenceNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"senderCreator","outputs":[{"internalType":"contract ISenderCreator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"}],"name":"withdrawStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"},{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/test/bin/EntryPoint080.bytecode b/test/bin/EntryPoint080.bytecode new file mode 100644 index 000000000..f3f3bd1c1 Binary files /dev/null and b/test/bin/EntryPoint080.bytecode differ diff --git a/test/bin/SenderCreator080.abi b/test/bin/SenderCreator080.abi new file mode 100644 index 000000000..e169340ac --- /dev/null +++ b/test/bin/SenderCreator080.abi @@ -0,0 +1 @@ +[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"inner","type":"bytes"}],"name":"FailedOpWithRevert","type":"error"},{"inputs":[{"internalType":"bytes","name":"initCode","type":"bytes"}],"name":"createSender","outputs":[{"internalType":"address","name":"sender","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"entryPoint","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"initCallData","type":"bytes"}],"name":"initEip7702Sender","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/test/bin/SenderCreator080.bytecode b/test/bin/SenderCreator080.bytecode new file mode 100644 index 000000000..0a8c61fb5 Binary files /dev/null and b/test/bin/SenderCreator080.bytecode differ diff --git a/test/governance/Governor.t.sol b/test/governance/Governor.t.sol index 958461abb..66b684d26 100644 --- a/test/governance/Governor.t.sol +++ b/test/governance/Governor.t.sol @@ -9,7 +9,11 @@ import {Governor} from "@openzeppelin/contracts/governance/Governor.sol"; contract GovernorInternalTest is Test, Governor { constructor() Governor("") {} - function testValidDescriptionForProposer(string memory description, address proposer, bool includeProposer) public { + function testValidDescriptionForProposer( + string memory description, + address proposer, + bool includeProposer + ) public view { if (includeProposer) { description = string.concat(description, "#proposer=", Strings.toHexString(proposer)); } @@ -20,7 +24,7 @@ contract GovernorInternalTest is Test, Governor { string memory description, address commitProposer, address actualProposer - ) public { + ) public view { vm.assume(commitProposer != actualProposer); description = string.concat(description, "#proposer=", Strings.toHexString(commitProposer)); assertFalse(_isValidDescriptionForProposer(actualProposer, description)); diff --git a/test/governance/Governor.test.js b/test/governance/Governor.test.js index 3e48ccfee..0e4283c3b 100644 --- a/test/governance/Governor.test.js +++ b/test/governance/Governor.test.js @@ -96,7 +96,7 @@ describe('Governor', function () { ); }); - shouldSupportInterfaces(['ERC1155Receiver', 'Governor']); + shouldSupportInterfaces(['ERC1155Receiver', 'Governor', 'Governor_5_3']); shouldBehaveLikeERC6372(mode); it('deployment check', async function () { @@ -624,8 +624,8 @@ describe('Governor', function () { await this.helper.connect(this.proposer).propose(); await expect(this.helper.connect(this.owner).cancel('external')) - .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyProposer') - .withArgs(this.owner); + .to.be.revertedWithCustomError(this.mock, 'GovernorUnableToCancel') + .withArgs(this.proposal.id, this.owner); }); it('after vote started', async function () { @@ -633,12 +633,8 @@ describe('Governor', function () { await this.helper.waitForSnapshot(1n); // snapshot + 1 block await expect(this.helper.cancel('external')) - .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') - .withArgs( - this.proposal.id, - ProposalState.Active, - GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]), - ); + .to.be.revertedWithCustomError(this.mock, 'GovernorUnableToCancel') + .withArgs(this.proposal.id, this.owner); }); it('after vote', async function () { @@ -647,12 +643,8 @@ describe('Governor', function () { await this.helper.connect(this.voter1).vote({ support: VoteType.For }); await expect(this.helper.cancel('external')) - .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') - .withArgs( - this.proposal.id, - ProposalState.Active, - GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]), - ); + .to.be.revertedWithCustomError(this.mock, 'GovernorUnableToCancel') + .withArgs(this.proposal.id, this.voter1); }); it('after deadline', async function () { @@ -662,12 +654,8 @@ describe('Governor', function () { await this.helper.waitForDeadline(); await expect(this.helper.cancel('external')) - .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') - .withArgs( - this.proposal.id, - ProposalState.Succeeded, - GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]), - ); + .to.be.revertedWithCustomError(this.mock, 'GovernorUnableToCancel') + .withArgs(this.proposal.id, this.voter1); }); it('after execution', async function () { @@ -678,12 +666,8 @@ describe('Governor', function () { await this.helper.execute(); await expect(this.helper.cancel('external')) - .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') - .withArgs( - this.proposal.id, - ProposalState.Executed, - GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]), - ); + .to.be.revertedWithCustomError(this.mock, 'GovernorUnableToCancel') + .withArgs(this.proposal.id, this.voter1); }); }); }); diff --git a/test/governance/extensions/GovernorCountingFractional.test.js b/test/governance/extensions/GovernorCountingFractional.test.js index 393dbad79..a46de210b 100644 --- a/test/governance/extensions/GovernorCountingFractional.test.js +++ b/test/governance/extensions/GovernorCountingFractional.test.js @@ -27,7 +27,7 @@ describe('GovernorCountingFractional', function () { const [owner, proposer, voter1, voter2, voter3, voter4, other] = await ethers.getSigners(); const receiver = await ethers.deployContract('CallReceiverMock'); - const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]); + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); const mock = await ethers.deployContract('$GovernorFractionalMock', [ name, // name votingDelay, // initialVotingDelay diff --git a/test/governance/extensions/GovernorCountingOverridable.test.js b/test/governance/extensions/GovernorCountingOverridable.test.js index 32ee47439..fd1032b9e 100644 --- a/test/governance/extensions/GovernorCountingOverridable.test.js +++ b/test/governance/extensions/GovernorCountingOverridable.test.js @@ -264,7 +264,7 @@ describe('GovernorCountingOverridable', function () { .to.emit(this.mock, 'OverrideVoteCast') .withArgs(this.voter1, this.helper.id, VoteType.Against, ethers.parseEther('10'), ''); await expect(this.mock.connect(this.voter1).castOverrideVote(this.helper.id, VoteType.Abstain, '')) - .to.be.revertedWithCustomError(this.mock, 'GovernorAlreadyOverridenVote') + .to.be.revertedWithCustomError(this.mock, 'GovernorAlreadyOverriddenVote') .withArgs(this.voter1.address); }); diff --git a/test/governance/extensions/GovernorERC721.test.js b/test/governance/extensions/GovernorERC721.test.js index 1ae5508d7..15910b8fe 100644 --- a/test/governance/extensions/GovernorERC721.test.js +++ b/test/governance/extensions/GovernorERC721.test.js @@ -29,7 +29,7 @@ describe('GovernorERC721', function () { const [owner, voter1, voter2, voter3, voter4] = await ethers.getSigners(); const receiver = await ethers.deployContract('CallReceiverMock'); - const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]); + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); const mock = await ethers.deployContract('$GovernorMock', [ name, // name votingDelay, // initialVotingDelay diff --git a/test/governance/extensions/GovernorPreventLateQuorum.test.js b/test/governance/extensions/GovernorPreventLateQuorum.test.js index aac0e6898..761087aa9 100644 --- a/test/governance/extensions/GovernorPreventLateQuorum.test.js +++ b/test/governance/extensions/GovernorPreventLateQuorum.test.js @@ -28,7 +28,7 @@ describe('GovernorPreventLateQuorum', function () { const [owner, proposer, voter1, voter2, voter3, voter4] = await ethers.getSigners(); const receiver = await ethers.deployContract('CallReceiverMock'); - const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]); + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); const mock = await ethers.deployContract('$GovernorPreventLateQuorumMock', [ name, // name votingDelay, // initialVotingDelay diff --git a/test/governance/extensions/GovernorProposalGuardian.test.js b/test/governance/extensions/GovernorProposalGuardian.test.js new file mode 100644 index 000000000..1741072c3 --- /dev/null +++ b/test/governance/extensions/GovernorProposalGuardian.test.js @@ -0,0 +1,132 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); + +const { impersonate } = require('../../helpers/account'); +const { GovernorHelper } = require('../../helpers/governance'); +const { ProposalState } = require('../../helpers/enums'); + +const TOKENS = [ + { Token: '$ERC20Votes', mode: 'blocknumber' }, + { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' }, +]; +const name = 'Proposal Guardian Governor'; +const version = '1'; +const tokenName = 'MockToken'; +const tokenSymbol = 'MTKN'; +const tokenSupply = ethers.parseEther('100'); +const votingDelay = 4n; +const votingPeriod = 16n; +const value = ethers.parseEther('1'); + +describe('GovernorProposalGuardian', function () { + for (const { Token, mode } of TOKENS) { + const fixture = async () => { + const [owner, proposer, guardian, voter1, voter2, voter3, voter4, other] = await ethers.getSigners(); + const receiver = await ethers.deployContract('CallReceiverMock'); + + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); + const mock = await ethers.deployContract('$GovernorProposalGuardianMock', [ + name, // name + votingDelay, // initialVotingDelay + votingPeriod, // initialVotingPeriod + 0n, // initialProposalThreshold + token, // tokenAddress + 10n, // quorumNumeratorValue + ]); + + await impersonate(mock.target); + await owner.sendTransaction({ to: mock, value }); + await token.$_mint(owner, tokenSupply); + + const helper = new GovernorHelper(mock, mode); + await helper.connect(owner).delegate({ token, to: voter1, value: ethers.parseEther('10') }); + await helper.connect(owner).delegate({ token, to: voter2, value: ethers.parseEther('7') }); + await helper.connect(owner).delegate({ token, to: voter3, value: ethers.parseEther('5') }); + await helper.connect(owner).delegate({ token, to: voter4, value: ethers.parseEther('2') }); + + return { owner, proposer, guardian, voter1, voter2, voter3, voter4, other, receiver, token, mock, helper }; + }; + + describe(`using ${Token}`, function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)); + + // default proposal + this.proposal = this.helper.setProposal( + [ + { + target: this.receiver.target, + value, + data: this.receiver.interface.encodeFunctionData('mockFunction'), + }, + ], + '', + ); + }); + + it('deployment check', async function () { + await expect(this.mock.name()).to.eventually.equal(name); + await expect(this.mock.token()).to.eventually.equal(this.token); + await expect(this.mock.votingDelay()).to.eventually.equal(votingDelay); + await expect(this.mock.votingPeriod()).to.eventually.equal(votingPeriod); + }); + + describe('set proposal guardian', function () { + it('from governance', async function () { + const governorSigner = await ethers.getSigner(this.mock.target); + await expect(this.mock.connect(governorSigner).setProposalGuardian(this.guardian)) + .to.emit(this.mock, 'ProposalGuardianSet') + .withArgs(ethers.ZeroAddress, this.guardian); + await expect(this.mock.proposalGuardian()).to.eventually.equal(this.guardian); + }); + + it('from non-governance', async function () { + await expect(this.mock.connect(this.other).setProposalGuardian(this.guardian)) + .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor') + .withArgs(this.other); + }); + }); + + it('cancel proposal during pending state from proposer when proposal guardian is non-zero', async function () { + await this.mock.$_setProposalGuardian(this.guardian); + await this.helper.connect(this.proposer).propose(); + await expect(this.helper.connect(this.proposer).cancel()) + .to.emit(this.mock, 'ProposalCanceled') + .withArgs(this.proposal.id); + }); + + describe('cancel proposal during active state', function () { + beforeEach(async function () { + await this.helper.connect(this.proposer).propose(); + await this.helper.waitForSnapshot(1n); + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Active); + }); + + it('from proposal guardian', async function () { + await this.mock.$_setProposalGuardian(this.guardian); + + await expect(this.helper.connect(this.guardian).cancel()) + .to.emit(this.mock, 'ProposalCanceled') + .withArgs(this.proposal.id); + }); + + it('from proposer when proposal guardian is non-zero', async function () { + await this.mock.$_setProposalGuardian(this.guardian); + + await expect(this.helper.connect(this.proposer).cancel()) + .to.be.revertedWithCustomError(this.mock, 'GovernorUnableToCancel') + .withArgs(this.proposal.id, this.proposer); + }); + + it('from proposer when proposal guardian is zero', async function () { + await this.mock.$_setProposalGuardian(ethers.ZeroAddress); + + await expect(this.helper.connect(this.proposer).cancel()) + .to.emit(this.mock, 'ProposalCanceled') + .withArgs(this.proposal.id); + }); + }); + }); + } +}); diff --git a/test/governance/extensions/GovernorSequentialProposalId.test.js b/test/governance/extensions/GovernorSequentialProposalId.test.js new file mode 100644 index 000000000..81bc6eb09 --- /dev/null +++ b/test/governance/extensions/GovernorSequentialProposalId.test.js @@ -0,0 +1,202 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); +const { anyValue } = require('@nomicfoundation/hardhat-chai-matchers/withArgs'); + +const { GovernorHelper } = require('../../helpers/governance'); +const { VoteType } = require('../../helpers/enums'); +const iterate = require('../../helpers/iterate'); + +const TOKENS = [ + { Token: '$ERC20Votes', mode: 'blocknumber' }, + { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' }, +]; + +const name = 'OZ-Governor'; +const version = '1'; +const tokenName = 'MockToken'; +const tokenSymbol = 'MTKN'; +const tokenSupply = ethers.parseEther('100'); +const votingDelay = 4n; +const votingPeriod = 16n; +const value = ethers.parseEther('1'); + +async function deployToken(contractName) { + try { + return await ethers.deployContract(contractName, [tokenName, tokenSymbol, tokenName, version]); + } catch (error) { + if (error.message == 'incorrect number of arguments to constructor') { + // ERC20VotesLegacyMock has a different construction that uses version='1' by default. + return ethers.deployContract(contractName, [tokenName, tokenSymbol, tokenName]); + } + throw error; + } +} + +describe('GovernorSequentialProposalId', function () { + for (const { Token, mode } of TOKENS) { + const fixture = async () => { + const [owner, proposer, voter1, voter2, voter3, voter4, userEOA] = await ethers.getSigners(); + const receiver = await ethers.deployContract('CallReceiverMock'); + + const token = await deployToken(Token, [tokenName, tokenSymbol, version]); + const mock = await ethers.deployContract('$GovernorSequentialProposalIdMock', [ + name, // name + votingDelay, // initialVotingDelay + votingPeriod, // initialVotingPeriod + 0n, // initialProposalThreshold + token, // tokenAddress + 10n, // quorumNumeratorValue + ]); + + await owner.sendTransaction({ to: mock, value }); + await token.$_mint(owner, tokenSupply); + + const helper = new GovernorHelper(mock, mode); + await helper.connect(owner).delegate({ token: token, to: voter1, value: ethers.parseEther('10') }); + await helper.connect(owner).delegate({ token: token, to: voter2, value: ethers.parseEther('7') }); + await helper.connect(owner).delegate({ token: token, to: voter3, value: ethers.parseEther('5') }); + await helper.connect(owner).delegate({ token: token, to: voter4, value: ethers.parseEther('2') }); + + return { + owner, + proposer, + voter1, + voter2, + voter3, + voter4, + userEOA, + receiver, + token, + mock, + helper, + }; + }; + + describe(`using ${Token}`, function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)); + + this.proposal = this.helper.setProposal( + [ + { + target: this.receiver.target, + data: this.receiver.interface.encodeFunctionData('mockFunction'), + value, + }, + ], + '', + ); + }); + + it('sequential proposal ids', async function () { + for (const i of iterate.range(1, 10)) { + this.proposal.description = ``; + + await expect(this.mock.hashProposal(...this.proposal.shortProposal)).to.eventually.equal(this.proposal.hash); + await expect(this.mock.getProposalId(...this.proposal.shortProposal)).revertedWithCustomError( + this.mock, + 'GovernorNonexistentProposal', + ); + await expect(this.mock.latestProposalId()).to.eventually.equal(i - 1); + + await expect(this.helper.connect(this.proposer).propose()) + .to.emit(this.mock, 'ProposalCreated') + .withArgs( + i, + this.proposer, + this.proposal.targets, + this.proposal.values, + this.proposal.signatures, + this.proposal.data, + anyValue, + anyValue, + this.proposal.description, + ); + + await expect(this.mock.hashProposal(...this.proposal.shortProposal)).to.eventually.equal(this.proposal.hash); + await expect(this.mock.getProposalId(...this.proposal.shortProposal)).to.eventually.equal(i); + await expect(this.mock.latestProposalId()).to.eventually.equal(i); + } + }); + + it('sequential proposal ids with offset start', async function () { + const offset = 69420; + await this.mock.$_initializeLatestProposalId(offset); + + for (const i of iterate.range(offset + 1, offset + 10)) { + this.proposal.description = ``; + + await expect(this.mock.hashProposal(...this.proposal.shortProposal)).to.eventually.equal(this.proposal.hash); + await expect(this.mock.getProposalId(...this.proposal.shortProposal)).revertedWithCustomError( + this.mock, + 'GovernorNonexistentProposal', + ); + await expect(this.mock.latestProposalId()).to.eventually.equal(i - 1); + + await expect(this.helper.connect(this.proposer).propose()) + .to.emit(this.mock, 'ProposalCreated') + .withArgs( + i, + this.proposer, + this.proposal.targets, + this.proposal.values, + this.proposal.signatures, + this.proposal.data, + anyValue, + anyValue, + this.proposal.description, + ); + + await expect(this.mock.hashProposal(...this.proposal.shortProposal)).to.eventually.equal(this.proposal.hash); + await expect(this.mock.getProposalId(...this.proposal.shortProposal)).to.eventually.equal(i); + await expect(this.mock.latestProposalId()).to.eventually.equal(i); + } + }); + + it('can only initialize latest proposal id from 0', async function () { + await this.helper.propose(); + await expect(this.mock.latestProposalId()).to.eventually.equal(1); + await expect(this.mock.$_initializeLatestProposalId(2)).to.be.revertedWithCustomError( + this.mock, + 'GovernorAlreadyInitializedLatestProposalId', + ); + }); + + it('cannot repropose same proposal', async function () { + await this.helper.connect(this.proposer).propose(); + await expect(this.helper.connect(this.proposer).propose()) + .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState') + .withArgs(await this.proposal.id, 0, ethers.ZeroHash); + }); + + it('nominal workflow', async function () { + await this.helper.connect(this.proposer).propose(); + await this.helper.waitForSnapshot(); + + await expect(this.mock.connect(this.voter1).castVote(1, VoteType.For)) + .to.emit(this.mock, 'VoteCast') + .withArgs(this.voter1, 1, VoteType.For, ethers.parseEther('10'), ''); + + await expect(this.mock.connect(this.voter2).castVote(1, VoteType.For)) + .to.emit(this.mock, 'VoteCast') + .withArgs(this.voter2, 1, VoteType.For, ethers.parseEther('7'), ''); + + await expect(this.mock.connect(this.voter3).castVote(1, VoteType.For)) + .to.emit(this.mock, 'VoteCast') + .withArgs(this.voter3, 1, VoteType.For, ethers.parseEther('5'), ''); + + await expect(this.mock.connect(this.voter4).castVote(1, VoteType.Abstain)) + .to.emit(this.mock, 'VoteCast') + .withArgs(this.voter4, 1, VoteType.Abstain, ethers.parseEther('2'), ''); + + await this.helper.waitForDeadline(); + + await expect(this.helper.execute()) + .to.eventually.emit(this.mock, 'ProposalExecuted') + .withArgs(1) + .emit(this.receiver, 'MockFunctionCalled'); + }); + }); + } +}); diff --git a/test/governance/extensions/GovernorStorage.test.js b/test/governance/extensions/GovernorStorage.test.js index ef56fa53e..f079405b5 100644 --- a/test/governance/extensions/GovernorStorage.test.js +++ b/test/governance/extensions/GovernorStorage.test.js @@ -33,7 +33,7 @@ describe('GovernorStorage', function () { const [deployer, owner, proposer, voter1, voter2, voter3, voter4] = await ethers.getSigners(); const receiver = await ethers.deployContract('CallReceiverMock'); - const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]); + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); const timelock = await ethers.deployContract('TimelockController', [delay, [], [], deployer]); const mock = await ethers.deployContract('$GovernorStorageMock', [ name, diff --git a/test/governance/extensions/GovernorSuperQuorum.test.js b/test/governance/extensions/GovernorSuperQuorum.test.js new file mode 100644 index 000000000..9a8b8455c --- /dev/null +++ b/test/governance/extensions/GovernorSuperQuorum.test.js @@ -0,0 +1,168 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); + +const { GovernorHelper } = require('../../helpers/governance'); +const { ProposalState, VoteType } = require('../../helpers/enums'); +const time = require('../../helpers/time'); + +const TOKENS = [ + { Token: '$ERC20Votes', mode: 'blocknumber' }, + { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' }, +]; + +const DEFAULT_ADMIN_ROLE = ethers.ZeroHash; +const PROPOSER_ROLE = ethers.id('PROPOSER_ROLE'); +const EXECUTOR_ROLE = ethers.id('EXECUTOR_ROLE'); +const CANCELLER_ROLE = ethers.id('CANCELLER_ROLE'); + +const name = 'OZ-Governor'; +const version = '1'; +const tokenName = 'MockToken'; +const tokenSymbol = 'MTKN'; +const tokenSupply = ethers.parseEther('100'); +const votingDelay = 4n; +const votingPeriod = 16n; +const quorum = 10n; +const superQuorum = 40n; +const value = ethers.parseEther('1'); +const delay = time.duration.hours(1n); + +describe('GovernorSuperQuorum', function () { + for (const { Token, mode } of TOKENS) { + const fixture = async () => { + const [proposer, voter1, voter2, voter3, voter4, voter5] = await ethers.getSigners(); + const receiver = await ethers.deployContract('CallReceiverMock'); + + const timelock = await ethers.deployContract('TimelockController', [delay, [], [], proposer]); + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); + const mock = await ethers.deployContract('$GovernorSuperQuorumMock', [ + name, + votingDelay, // initialVotingDelay + votingPeriod, // initialVotingPeriod + 0n, // initialProposalThreshold + token, + timelock, + quorum, + superQuorum, + ]); + + await proposer.sendTransaction({ to: timelock, value }); + await token.$_mint(proposer, tokenSupply); + await timelock.grantRole(PROPOSER_ROLE, mock); + await timelock.grantRole(PROPOSER_ROLE, proposer); + await timelock.grantRole(CANCELLER_ROLE, mock); + await timelock.grantRole(CANCELLER_ROLE, proposer); + await timelock.grantRole(EXECUTOR_ROLE, ethers.ZeroAddress); + await timelock.revokeRole(DEFAULT_ADMIN_ROLE, proposer); + + const helper = new GovernorHelper(mock, mode); + await helper.connect(proposer).delegate({ token, to: voter1, value: 40 }); + await helper.connect(proposer).delegate({ token, to: voter2, value: 30 }); + await helper.connect(proposer).delegate({ token, to: voter3, value: 20 }); + await helper.connect(proposer).delegate({ token, to: voter4, value: 15 }); + await helper.connect(proposer).delegate({ token, to: voter5, value: 5 }); + + return { proposer, voter1, voter2, voter3, voter4, voter5, receiver, token, mock, timelock, helper }; + }; + + describe(`using ${Token}`, function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)); + + // default proposal + this.proposal = this.helper.setProposal( + [ + { + target: this.receiver.target, + value, + data: this.receiver.interface.encodeFunctionData('mockFunction'), + }, + ], + '', + ); + }); + + it('deployment check', async function () { + await expect(this.mock.name()).to.eventually.equal(name); + await expect(this.mock.token()).to.eventually.equal(this.token); + await expect(this.mock.quorum(0)).to.eventually.equal(quorum); + await expect(this.mock.superQuorum(0)).to.eventually.equal(superQuorum); + }); + + it('proposal succeeds early when super quorum is reached', async function () { + await this.helper.connect(this.proposer).propose(); + await this.helper.waitForSnapshot(); + + // Vote with voter2 (30) - above quorum (10) but below super quorum (40) + await this.helper.connect(this.voter2).vote({ support: VoteType.For }); + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Active); + + // Vote with voter3 (20) to reach super quorum (50 total > 40) + await this.helper.connect(this.voter3).vote({ support: VoteType.For }); + + await expect(this.mock.proposalEta(this.proposal.id)).to.eventually.equal(0); + + // Should be succeeded since we reached super quorum and no eta is set + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Succeeded); + }); + + it('proposal remains active if super quorum is not reached', async function () { + await this.helper.connect(this.proposer).propose(); + await this.helper.waitForSnapshot(); + + // Vote with voter4 (15) - below super quorum (40) but above quorum (10) + await this.helper.connect(this.voter4).vote({ support: VoteType.For }); + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Active); + + // Vote with voter5 (5) - still below super quorum (total 20 < 40) + await this.helper.connect(this.voter5).vote({ support: VoteType.For }); + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Active); + + // Wait for deadline + await this.helper.waitForDeadline(1n); + + // Should succeed since deadline passed and we have enough support (20 > 10 quorum) + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Succeeded); + }); + + it('proposal remains active if super quorum is reached but vote fails', async function () { + await this.helper.connect(this.proposer).propose(); + await this.helper.waitForSnapshot(); + + // Vote against with voter2 and voter3 (50) + await this.helper.connect(this.voter2).vote({ support: VoteType.Against }); + await this.helper.connect(this.voter3).vote({ support: VoteType.Against }); + + // Vote for with voter1 (40) (reaching super quorum) + await this.helper.connect(this.voter1).vote({ support: VoteType.For }); + + // should be active since super quorum is reached but vote fails + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Active); + + // wait for deadline + await this.helper.waitForDeadline(1n); + + // should be defeated since against votes are higher + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Defeated); + }); + + it('proposal is queued if super quorum is reached and eta is set', async function () { + await this.helper.connect(this.proposer).propose(); + + await this.helper.waitForSnapshot(); + + // Vote with voter1 (40) - reaching super quorum + await this.helper.connect(this.voter1).vote({ support: VoteType.For }); + + await this.helper.queue(); + + // Queueing should set eta + await expect(this.mock.proposalEta(this.proposal.id)).to.eventually.not.equal(0); + + // Should be queued since we reached super quorum and eta is set + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Queued); + }); + }); + } +}); diff --git a/test/governance/extensions/GovernorSuperQuorumGreaterThanQuorum.t.sol b/test/governance/extensions/GovernorSuperQuorumGreaterThanQuorum.t.sol new file mode 100644 index 000000000..eb0409c8e --- /dev/null +++ b/test/governance/extensions/GovernorSuperQuorumGreaterThanQuorum.t.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {GovernorVotesSuperQuorumFractionMock} from "../../../contracts/mocks/governance/GovernorVotesSuperQuorumFractionMock.sol"; +import {GovernorVotesQuorumFraction} from "../../../contracts/governance/extensions/GovernorVotesQuorumFraction.sol"; +import {GovernorVotesSuperQuorumFraction} from "../../../contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol"; +import {GovernorSettings} from "../../../contracts/governance/extensions/GovernorSettings.sol"; +import {GovernorVotes} from "../../../contracts/governance/extensions/GovernorVotes.sol"; +import {Governor} from "../../../contracts/governance/Governor.sol"; +import {IVotes} from "../../../contracts/governance/utils/IVotes.sol"; +import {ERC20VotesExtendedTimestampMock} from "../../../contracts/mocks/token/ERC20VotesAdditionalCheckpointsMock.sol"; +import {EIP712} from "../../../contracts/utils/cryptography/EIP712.sol"; +import {ERC20} from "../../../contracts/token/ERC20/ERC20.sol"; + +contract TokenMock is ERC20VotesExtendedTimestampMock { + constructor() ERC20("Mock Token", "MTK") EIP712("Mock Token", "1") {} +} + +/** + * Main responsibility: expose the functions that are relevant to the simulation + */ +contract GovernorHandler is GovernorVotesSuperQuorumFractionMock { + constructor( + string memory name_, + uint48 votingDelay_, + uint32 votingPeriod_, + uint256 proposalThreshold_, + IVotes token_, + uint256 quorumNumerator_, + uint256 superQuorumNumerator_ + ) + Governor(name_) + GovernorSettings(votingDelay_, votingPeriod_, proposalThreshold_) + GovernorVotes(token_) + GovernorVotesQuorumFraction(quorumNumerator_) + GovernorVotesSuperQuorumFraction(superQuorumNumerator_) + {} + + // solhint-disable-next-line func-name-mixedcase + function $_updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) public { + _updateSuperQuorumNumerator(newSuperQuorumNumerator); + } + + // solhint-disable-next-line func-name-mixedcase + function $_updateQuorumNumerator(uint256 newQuorumNumerator) public { + _updateQuorumNumerator(newQuorumNumerator); + } +} + +contract GovernorSuperQuorumGreaterThanQuorum is Test { + GovernorHandler private _governorHandler; + + function setUp() external { + _governorHandler = new GovernorHandler( + "GovernorName", + 0, // votingDelay + 1e4, // votingPeriod + 0, // proposalThreshold + new TokenMock(), // token + 10, // quorumNumerator + 50 // superQuorumNumerator + ); + + // limit the fuzzer scope + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = GovernorHandler.$_updateSuperQuorumNumerator.selector; + selectors[1] = GovernorHandler.$_updateQuorumNumerator.selector; + + targetContract(address(_governorHandler)); + targetSelector(FuzzSelector(address(_governorHandler), selectors)); + } + + // solhint-disable-next-line func-name-mixedcase + function invariant_superQuorumGreaterThanQuorum() external view { + assertGe(_governorHandler.superQuorumNumerator(), _governorHandler.quorumNumerator()); + } +} diff --git a/test/governance/extensions/GovernorTimelockAccess.test.js b/test/governance/extensions/GovernorTimelockAccess.test.js index c3d3b3268..5eea6478a 100644 --- a/test/governance/extensions/GovernorTimelockAccess.test.js +++ b/test/governance/extensions/GovernorTimelockAccess.test.js @@ -40,7 +40,7 @@ describe('GovernorTimelockAccess', function () { const manager = await ethers.deployContract('$AccessManager', [admin]); const receiver = await ethers.deployContract('$AccessManagedTarget', [manager]); - const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]); + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); const mock = await ethers.deployContract('$GovernorTimelockAccessMock', [ name, votingDelay, diff --git a/test/governance/extensions/GovernorTimelockCompound.test.js b/test/governance/extensions/GovernorTimelockCompound.test.js index 545bf359d..cd82481d5 100644 --- a/test/governance/extensions/GovernorTimelockCompound.test.js +++ b/test/governance/extensions/GovernorTimelockCompound.test.js @@ -28,7 +28,7 @@ describe('GovernorTimelockCompound', function () { const [deployer, owner, voter1, voter2, voter3, voter4, other] = await ethers.getSigners(); const receiver = await ethers.deployContract('CallReceiverMock'); - const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]); + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); const predictGovernor = await deployer .getNonce() .then(nonce => ethers.getCreateAddress({ from: deployer.address, nonce: nonce + 1 })); diff --git a/test/governance/extensions/GovernorTimelockControl.test.js b/test/governance/extensions/GovernorTimelockControl.test.js index c1156a509..507c7e278 100644 --- a/test/governance/extensions/GovernorTimelockControl.test.js +++ b/test/governance/extensions/GovernorTimelockControl.test.js @@ -34,7 +34,7 @@ describe('GovernorTimelockControl', function () { const [deployer, owner, voter1, voter2, voter3, voter4, other] = await ethers.getSigners(); const receiver = await ethers.deployContract('CallReceiverMock'); - const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]); + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); const timelock = await ethers.deployContract('TimelockController', [delay, [], [], deployer]); const mock = await ethers.deployContract('$GovernorTimelockControlMock', [ name, diff --git a/test/governance/extensions/GovernorVotesQuorumFraction.test.js b/test/governance/extensions/GovernorVotesQuorumFraction.test.js index 368e396f9..99afd3931 100644 --- a/test/governance/extensions/GovernorVotesQuorumFraction.test.js +++ b/test/governance/extensions/GovernorVotesQuorumFraction.test.js @@ -29,7 +29,7 @@ describe('GovernorVotesQuorumFraction', function () { const receiver = await ethers.deployContract('CallReceiverMock'); - const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]); + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); const mock = await ethers.deployContract('$GovernorMock', [name, votingDelay, votingPeriod, 0n, token, ratio]); await owner.sendTransaction({ to: mock, value }); diff --git a/test/governance/extensions/GovernorVotesSuperQuorumFraction.test.js b/test/governance/extensions/GovernorVotesSuperQuorumFraction.test.js new file mode 100644 index 000000000..10a444848 --- /dev/null +++ b/test/governance/extensions/GovernorVotesSuperQuorumFraction.test.js @@ -0,0 +1,160 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); + +const { GovernorHelper } = require('../../helpers/governance'); +const { ProposalState, VoteType } = require('../../helpers/enums'); +const time = require('../../helpers/time'); + +const TOKENS = [ + { Token: '$ERC20Votes', mode: 'blocknumber' }, + { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' }, +]; + +const name = 'OZ-Governor'; +const version = '1'; +const tokenName = 'MockToken'; +const tokenSymbol = 'MTKN'; +const tokenSupply = ethers.parseEther('100'); +const quorumRatio = 8n; // percents +const superQuorumRatio = 50n; // percents +const newSuperQuorumRatio = 15n; // percents +const votingDelay = 4n; +const votingPeriod = 16n; +const value = ethers.parseEther('1'); + +describe('GovernorVotesSuperQuorumFraction', function () { + for (const { Token, mode } of TOKENS) { + const fixture = async () => { + const [owner, voter1, voter2, voter3, voter4] = await ethers.getSigners(); + const receiver = await ethers.deployContract('CallReceiverMock'); + + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); + const mock = await ethers.deployContract('$GovernorVotesSuperQuorumFractionMock', [ + name, + votingDelay, + votingPeriod, + 0n, + token, + quorumRatio, + superQuorumRatio, + ]); + + await owner.sendTransaction({ to: mock, value }); + await token.$_mint(owner, tokenSupply); + + const helper = new GovernorHelper(mock, mode); + await helper.connect(owner).delegate({ token, to: voter1, value: ethers.parseEther('30') }); + await helper.connect(owner).delegate({ token, to: voter2, value: ethers.parseEther('20') }); + await helper.connect(owner).delegate({ token, to: voter3, value: ethers.parseEther('15') }); + await helper.connect(owner).delegate({ token, to: voter4, value: ethers.parseEther('5') }); + + return { owner, voter1, voter2, voter3, voter4, receiver, token, mock, helper }; + }; + + describe(`using ${Token}`, function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)); + + // default proposal + this.proposal = this.helper.setProposal( + [ + { + target: this.receiver.target, + value, + data: this.receiver.interface.encodeFunctionData('mockFunction'), + }, + ], + '', + ); + }); + + it('deployment check', async function () { + await expect(this.mock.name()).to.eventually.equal(name); + await expect(this.mock.token()).to.eventually.equal(this.token); + await expect(this.mock.votingDelay()).to.eventually.equal(votingDelay); + await expect(this.mock.votingPeriod()).to.eventually.equal(votingPeriod); + await expect(this.mock.quorumNumerator()).to.eventually.equal(quorumRatio); + await expect(this.mock.superQuorumNumerator()).to.eventually.equal(superQuorumRatio); + await expect(this.mock.quorumDenominator()).to.eventually.equal(100n); + await expect(time.clock[mode]().then(clock => this.mock.superQuorum(clock - 1n))).to.eventually.equal( + (tokenSupply * superQuorumRatio) / 100n, + ); + }); + + it('proposal remains active until super quorum is reached', async function () { + await this.helper.propose(); + await this.helper.waitForSnapshot(); + + // Vote with voter1 (30%) - above quorum (8%) but below super quorum (50%) + await this.helper.connect(this.voter1).vote({ support: VoteType.For }); + + // Check proposal is still active + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Active); + + // Vote with voter2 (20%) - now matches super quorum + await this.helper.connect(this.voter2).vote({ support: VoteType.For }); + + // Proposal should no longer be active + await expect(this.mock.state(this.proposal.id)).to.eventually.equal(ProposalState.Succeeded); + }); + + describe('super quorum updates', function () { + it('updateSuperQuorumNumerator is protected', async function () { + await expect(this.mock.connect(this.owner).updateSuperQuorumNumerator(newSuperQuorumRatio)) + .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor') + .withArgs(this.owner); + }); + + it('can update super quorum through governance', async function () { + this.helper.setProposal( + [ + { + target: this.mock.target, + data: this.mock.interface.encodeFunctionData('updateSuperQuorumNumerator', [newSuperQuorumRatio]), + }, + ], + '', + ); + + await this.helper.propose(); + await this.helper.waitForSnapshot(); + await this.helper.connect(this.voter1).vote({ support: VoteType.For }); + await this.helper.connect(this.voter2).vote({ support: VoteType.For }); + await this.helper.waitForDeadline(); + + await expect(this.helper.execute()) + .to.emit(this.mock, 'SuperQuorumNumeratorUpdated') + .withArgs(superQuorumRatio, newSuperQuorumRatio); + + await expect(this.mock.superQuorumNumerator()).to.eventually.equal(newSuperQuorumRatio); + }); + + it('cannot set super quorum below quorum', async function () { + const invalidSuperQuorum = quorumRatio - 1n; + + await expect(this.mock.$_updateSuperQuorumNumerator(invalidSuperQuorum)) + .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidSuperQuorumTooSmall') + .withArgs(invalidSuperQuorum, quorumRatio); + }); + + it('cannot set super quorum above denominator', async function () { + const denominator = await this.mock.quorumDenominator(); + const invalidSuperQuorum = BigInt(denominator) + 1n; + + await expect(this.mock.$_updateSuperQuorumNumerator(invalidSuperQuorum)) + .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidSuperQuorumFraction') + .withArgs(invalidSuperQuorum, denominator); + }); + + it('cannot set quorum above super quorum', async function () { + const invalidQuorum = superQuorumRatio + 1n; + + await expect(this.mock.$_updateQuorumNumerator(invalidQuorum)) + .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidQuorumTooLarge') + .withArgs(invalidQuorum, superQuorumRatio); + }); + }); + }); + } +}); diff --git a/test/governance/extensions/GovernorWithParams.test.js b/test/governance/extensions/GovernorWithParams.test.js index 37e15f5c2..db19bc616 100644 --- a/test/governance/extensions/GovernorWithParams.test.js +++ b/test/governance/extensions/GovernorWithParams.test.js @@ -31,7 +31,7 @@ describe('GovernorWithParams', function () { const [owner, proposer, voter1, voter2, voter3, voter4, other] = await ethers.getSigners(); const receiver = await ethers.deployContract('CallReceiverMock'); - const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]); + const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]); const mock = await ethers.deployContract('$GovernorWithParamsMock', [name, token]); await owner.sendTransaction({ to: mock, value }); diff --git a/test/helpers/constants.js b/test/helpers/constants.js index 4dfda5eab..eb9b43e55 100644 --- a/test/helpers/constants.js +++ b/test/helpers/constants.js @@ -1,4 +1,5 @@ module.exports = { + MAX_UINT32: 2n ** 32n - 1n, MAX_UINT48: 2n ** 48n - 1n, MAX_UINT64: 2n ** 64n - 1n, }; diff --git a/test/helpers/enums.js b/test/helpers/enums.js index f95767ab7..6adbf64ad 100644 --- a/test/helpers/enums.js +++ b/test/helpers/enums.js @@ -1,12 +1,14 @@ -function Enum(...options) { - return Object.fromEntries(options.map((key, i) => [key, BigInt(i)])); -} +const { ethers } = require('ethers'); + +const Enum = (...options) => Object.fromEntries(options.map((key, i) => [key, BigInt(i)])); +const EnumTyped = (...options) => Object.fromEntries(options.map((key, i) => [key, ethers.Typed.uint8(i)])); module.exports = { Enum, + EnumTyped, ProposalState: Enum('Pending', 'Active', 'Canceled', 'Defeated', 'Succeeded', 'Queued', 'Expired', 'Executed'), VoteType: Object.assign(Enum('Against', 'For', 'Abstain'), { Parameters: 255n }), - Rounding: Enum('Floor', 'Ceil', 'Trunc', 'Expand'), + Rounding: EnumTyped('Floor', 'Ceil', 'Trunc', 'Expand'), OperationState: Enum('Unset', 'Waiting', 'Ready', 'Done'), - RevertType: Enum('None', 'RevertWithoutMessage', 'RevertWithMessage', 'RevertWithCustomError', 'Panic'), + RevertType: EnumTyped('None', 'RevertWithoutMessage', 'RevertWithMessage', 'RevertWithCustomError', 'Panic'), }; diff --git a/test/helpers/erc4337-entrypoint.js b/test/helpers/erc4337-entrypoint.js deleted file mode 100644 index aba49f4c4..000000000 --- a/test/helpers/erc4337-entrypoint.js +++ /dev/null @@ -1,31 +0,0 @@ -const { ethers } = require('hardhat'); -const { setCode } = require('@nomicfoundation/hardhat-network-helpers'); -const fs = require('fs'); -const path = require('path'); - -const INSTANCES = { - entrypoint: { - address: '0x0000000071727De22E5E9d8BAf0edAc6f37da032', - abi: JSON.parse(fs.readFileSync(path.resolve(__dirname, '../bin/EntryPoint070.abi'), 'utf-8')), - bytecode: fs.readFileSync(path.resolve(__dirname, '../bin/EntryPoint070.bytecode'), 'hex'), - }, - sendercreator: { - address: '0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C', - abi: JSON.parse(fs.readFileSync(path.resolve(__dirname, '../bin/SenderCreator070.abi'), 'utf-8')), - bytecode: fs.readFileSync(path.resolve(__dirname, '../bin/SenderCreator070.bytecode'), 'hex'), - }, -}; - -function deployEntrypoint() { - return Promise.all( - Object.entries(INSTANCES).map(([name, { address, abi, bytecode }]) => - setCode(address, '0x' + bytecode.replace(/0x/, '')) - .then(() => ethers.getContractAt(abi, address)) - .then(instance => ({ [name]: instance })), - ), - ).then(namedInstances => Object.assign(...namedInstances)); -} - -module.exports = { - deployEntrypoint, -}; diff --git a/test/helpers/erc4337.js b/test/helpers/erc4337.js index 50a3b4a04..2d5cbe1a0 100644 --- a/test/helpers/erc4337.js +++ b/test/helpers/erc4337.js @@ -78,26 +78,8 @@ class UserOperation { }; } - hash(entrypoint, chainId) { - const p = this.packed; - const h = ethers.keccak256( - ethers.AbiCoder.defaultAbiCoder().encode( - ['address', 'uint256', 'bytes32', 'bytes32', 'uint256', 'uint256', 'uint256', 'uint256'], - [ - p.sender, - p.nonce, - ethers.keccak256(p.initCode), - ethers.keccak256(p.callData), - p.accountGasLimits, - p.preVerificationGas, - p.gasFees, - ethers.keccak256(p.paymasterAndData), - ], - ), - ); - return ethers.keccak256( - ethers.AbiCoder.defaultAbiCoder().encode(['bytes32', 'address', 'uint256'], [h, getAddress(entrypoint), chainId]), - ); + hash(entrypoint) { + return entrypoint.getUserOpHash(this.packed); } } diff --git a/test/helpers/governance.js b/test/helpers/governance.js index 540967af4..e0686445c 100644 --- a/test/helpers/governance.js +++ b/test/helpers/governance.js @@ -35,12 +35,16 @@ class GovernorHelper { return this; } - get id() { + get hash() { return ethers.keccak256( ethers.AbiCoder.defaultAbiCoder().encode(['address[]', 'uint256[]', 'bytes[]', 'bytes32'], this.shortProposal), ); } + get id() { + return this.governor.latestProposalId ? this.governor.getProposalId(...this.shortProposal) : this.hash; + } + // used for checking events get signatures() { return this.data.map(() => ''); @@ -106,10 +110,10 @@ class GovernorHelper { async vote(vote = {}) { let method = 'castVote'; // default - let args = [this.id, vote.support]; // base + let args = [await this.id, vote.support]; // base if (vote.signature) { - const sign = await vote.signature(this.governor, this.forgeMessage(vote)); + const sign = await this.forgeMessage(vote).then(msg => vote.signature(this.governor, msg)); if (vote.params || vote.reason) { method = 'castVoteWithReasonAndParamsBySig'; args.push(vote.voter, vote.reason ?? '', vote.params ?? '0x', sign); @@ -130,14 +134,12 @@ class GovernorHelper { async overrideVote(vote = {}) { let method = 'castOverrideVote'; - let args = [this.id, vote.support]; + let args = [await this.id, vote.support]; vote.reason = vote.reason ?? ''; if (vote.signature) { - let message = this.forgeMessage(vote); - message.reason = message.reason ?? ''; - const sign = await vote.signature(this.governor, message); + const sign = await this.forgeMessage(vote).then(msg => vote.signature(this.governor, { reason: '', ...msg })); method = 'castOverrideVoteBySig'; args.push(vote.voter, vote.reason ?? '', sign); } @@ -147,23 +149,23 @@ class GovernorHelper { /// Clock helpers async waitForSnapshot(offset = 0n) { - const timepoint = await this.governor.proposalSnapshot(this.id); + const timepoint = await this.governor.proposalSnapshot(await this.id); return time.increaseTo[this.mode](timepoint + offset); } async waitForDeadline(offset = 0n) { - const timepoint = await this.governor.proposalDeadline(this.id); + const timepoint = await this.governor.proposalDeadline(await this.id); return time.increaseTo[this.mode](timepoint + offset); } async waitForEta(offset = 0n) { - const timestamp = await this.governor.proposalEta(this.id); + const timestamp = await this.governor.proposalEta(await this.id); return time.increaseTo.timestamp(timestamp + offset); } /// Other helpers - forgeMessage(vote = {}) { - const message = { proposalId: this.id, support: vote.support, voter: vote.voter, nonce: vote.nonce }; + async forgeMessage(vote = {}) { + const message = { proposalId: await this.id, support: vote.support, voter: vote.voter, nonce: vote.nonce }; if (vote.params || vote.reason) { message.reason = vote.reason ?? ''; diff --git a/test/helpers/iterate.js b/test/helpers/iterate.js index c7403d523..8c8e9649d 100644 --- a/test/helpers/iterate.js +++ b/test/helpers/iterate.js @@ -30,7 +30,12 @@ module.exports = { // ================================================ Object helpers ================================================= - // Create a new object by mapping the values through a function, keeping the keys + // Create a new object by mapping the values through a function, keeping the keys. Second function can be used to pre-filter entries // Example: mapValues({a:1,b:2,c:3}, x => x**2) → {a:1,b:4,c:9} - mapValues: (obj, fn) => Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, fn(v)])), + mapValues: (obj, fn, fn2 = () => true) => + Object.fromEntries( + Object.entries(obj) + .filter(fn2) + .map(([k, v]) => [k, fn(v)]), + ), }; diff --git a/test/helpers/precompiles.js b/test/helpers/precompiles.js new file mode 100644 index 000000000..fb6b7132a --- /dev/null +++ b/test/helpers/precompiles.js @@ -0,0 +1,12 @@ +module.exports = { + ecRecover: '0x0000000000000000000000000000000000000001', + SHA2_256: '0x0000000000000000000000000000000000000002', + RIPEMD_160: '0x0000000000000000000000000000000000000003', + identity: '0x0000000000000000000000000000000000000004', + modexp: '0x0000000000000000000000000000000000000005', + ecAdd: '0x0000000000000000000000000000000000000006', + ecMul: '0x0000000000000000000000000000000000000007', + ecPairing: '0x0000000000000000000000000000000000000008', + blake2f: '0x0000000000000000000000000000000000000009', + pointEvaluation: '0x000000000000000000000000000000000000000a', +}; diff --git a/test/helpers/time.js b/test/helpers/time.js index f6ccc3cab..574170c13 100644 --- a/test/helpers/time.js +++ b/test/helpers/time.js @@ -7,8 +7,11 @@ const clock = { timestamp: () => time.latest().then(ethers.toBigInt), }; const clockFromReceipt = { - blocknumber: receipt => Promise.resolve(ethers.toBigInt(receipt.blockNumber)), - timestamp: receipt => ethers.provider.getBlock(receipt.blockNumber).then(block => ethers.toBigInt(block.timestamp)), + blocknumber: receipt => Promise.resolve(receipt).then(({ blockNumber }) => ethers.toBigInt(blockNumber)), + timestamp: receipt => + Promise.resolve(receipt) + .then(({ blockNumber }) => ethers.provider.getBlock(blockNumber)) + .then(({ timestamp }) => ethers.toBigInt(timestamp)), }; const increaseBy = { blockNumber: mine, diff --git a/test/metatx/ERC2771Context.test.js b/test/metatx/ERC2771Context.test.js index 15da61dad..ce139961c 100644 --- a/test/metatx/ERC2771Context.test.js +++ b/test/metatx/ERC2771Context.test.js @@ -11,7 +11,7 @@ const { shouldBehaveLikeRegularContext } = require('../utils/Context.behavior'); async function fixture() { const [sender, other] = await ethers.getSigners(); - const forwarder = await ethers.deployContract('ERC2771Forwarder', []); + const forwarder = await ethers.deployContract('ERC2771Forwarder', ['ERC2771Forwarder']); const forwarderAsSigner = await impersonate(forwarder.target); const context = await ethers.deployContract('ERC2771ContextMock', [forwarder]); const domain = await getDomain(forwarder); @@ -109,7 +109,7 @@ describe('ERC2771Context', function () { const nonce = await this.forwarder.nonces(this.sender); const data = this.context.interface.encodeFunctionData('multicall', [ [ - // poisonned call to 'msgSender()' + // poisoned call to 'msgSender()' ethers.concat([this.context.interface.encodeFunctionData('msgSender'), this.other.address]), ], ]); diff --git a/test/metatx/ERC2771Forwarder.t.sol b/test/metatx/ERC2771Forwarder.t.sol index e6baac6f0..605ae6209 100644 --- a/test/metatx/ERC2771Forwarder.t.sol +++ b/test/metatx/ERC2771Forwarder.t.sol @@ -171,7 +171,7 @@ contract ERC2771ForwarderTest is Test { uint256 refundExpected = 0; uint256 nonce = _erc2771Forwarder.nonces(_signer); - // create an sign array or requests (that may fail) + // create an array of signed requests (that may fail) ERC2771Forwarder.ForwardRequestData[] memory requests = new ERC2771Forwarder.ForwardRequestData[](batchSize); for (uint256 i = 0; i < batchSize; ++i) { bool failure = (seed >> i) & 0x1 == 0x1; @@ -229,7 +229,7 @@ contract ERC2771ForwarderTest is Test { TamperType tamper = _asTamper(_tamper); uint256 nonce = _erc2771Forwarder.nonces(_signer); - // create an sign array or requests + // create an array of signed requests ERC2771Forwarder.ForwardRequestData[] memory requests = new ERC2771Forwarder.ForwardRequestData[](3); for (uint256 i = 0; i < requests.length; ++i) { requests[i] = _forgeRequestData({ @@ -252,7 +252,7 @@ contract ERC2771ForwarderTest is Test { TamperType tamper = _asTamper(_tamper); uint256 nonce = _erc2771Forwarder.nonces(_signer); - // create an sign array or requests + // create an array of signed requests ERC2771Forwarder.ForwardRequestData[] memory requests = new ERC2771Forwarder.ForwardRequestData[](3); for (uint256 i = 0; i < requests.length; ++i) { requests[i] = _forgeRequestData({ diff --git a/test/proxy/Clones.t.sol b/test/proxy/Clones.t.sol index e589ba906..5da6d56d5 100644 --- a/test/proxy/Clones.t.sol +++ b/test/proxy/Clones.t.sol @@ -10,7 +10,7 @@ contract ClonesTest is Test { return 42; } - function testSymbolicPredictDeterministicAddressSpillage(address implementation, bytes32 salt) public { + function testSymbolicPredictDeterministicAddressSpillage(address implementation, bytes32 salt) public view { address predicted = Clones.predictDeterministicAddress(implementation, salt); bytes32 spillage; assembly ("memory-safe") { @@ -23,7 +23,7 @@ contract ClonesTest is Test { address implementation, bytes32 salt, bytes memory args - ) public { + ) public view { vm.assume(args.length < 0xbfd3); address predicted = Clones.predictDeterministicAddressWithImmutableArgs(implementation, args, salt); @@ -59,7 +59,7 @@ contract ClonesTest is Test { assertEq(ClonesTest(cloneDirty).getNumber(), this.getNumber()); } - function testPredictDeterministicAddressDirty(bytes32 salt) external { + function testPredictDeterministicAddressDirty(bytes32 salt) external view { address predictClean = Clones.predictDeterministicAddress(address(this), salt); address predictDirty = Clones.predictDeterministicAddress(_dirty(address(this)), salt); diff --git a/test/proxy/beacon/BeaconProxy.test.js b/test/proxy/beacon/BeaconProxy.test.js index 0a0878446..d64023bbc 100644 --- a/test/proxy/beacon/BeaconProxy.test.js +++ b/test/proxy/beacon/BeaconProxy.test.js @@ -34,7 +34,7 @@ describe('BeaconProxy', function () { it('non-compliant beacon', async function () { const badBeacon = await ethers.deployContract('BadBeaconNoImpl'); - // BadBeaconNoImpl does not provide `implementation()` has no fallback. + // BadBeaconNoImpl does not provide `implementation()` and has no fallback. // This causes ERC1967Utils._setBeacon to revert. await expect(this.newBeaconProxy(badBeacon, '0x')).to.be.revertedWithoutReason(); }); diff --git a/test/token/ERC20/extensions/ERC20Wrapper.test.js b/test/token/ERC20/extensions/ERC20Wrapper.test.js index 9e72e1a92..2f630e638 100644 --- a/test/token/ERC20/extensions/ERC20Wrapper.test.js +++ b/test/token/ERC20/extensions/ERC20Wrapper.test.js @@ -77,7 +77,7 @@ describe('ERC20Wrapper', function () { .withArgs(this.token, 0, initialSupply); }); - it('reverts when inssuficient balance', async function () { + it('reverts when insufficient balance', async function () { await this.underlying.connect(this.holder).approve(this.token, ethers.MaxUint256); await expect(this.token.connect(this.holder).depositFor(this.holder, ethers.MaxUint256)) @@ -117,7 +117,7 @@ describe('ERC20Wrapper', function () { await this.token.connect(this.holder).depositFor(this.holder, initialSupply); }); - it('reverts when inssuficient balance', async function () { + it('reverts when insufficient balance', async function () { await expect(this.token.connect(this.holder).withdrawTo(this.holder, ethers.MaxInt256)) .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance') .withArgs(this.holder, initialSupply, ethers.MaxInt256); diff --git a/test/token/ERC20/extensions/ERC4626.test.js b/test/token/ERC20/extensions/ERC4626.test.js index 71c7cbaaf..ad8c92691 100644 --- a/test/token/ERC20/extensions/ERC4626.test.js +++ b/test/token/ERC20/extensions/ERC4626.test.js @@ -130,10 +130,10 @@ describe('ERC4626', function () { expect(await this.vault.previewWithdraw(value)).to.equal(sharesForWithdraw); }); - // Donate newly minted tokens to the vault during the reentracy causes the share price to increase. - // Still, the deposit that trigger the reentracy is not affected and get the previewed price. + // Donate newly minted tokens to the vault during the reentrancy causes the share price to increase. + // Still, the deposit that trigger the reentrancy is not affected and get the previewed price. // Further deposits will get a different price (getting fewer shares for the same value of assets) - it('share price change during reentracy does not affect deposit', async function () { + it('share price change during reentrancy does not affect deposit', async function () { // Schedules a reentrancy from the token contract that mess up the share price await this.token.scheduleReenter( reenterType.Before, @@ -154,10 +154,10 @@ describe('ERC4626', function () { expect(await this.vault.previewDeposit(value)).to.lt(sharesBefore); }); - // Burn some tokens from the vault during the reentracy causes the share price to drop. - // Still, the withdraw that trigger the reentracy is not affected and get the previewed price. + // Burn some tokens from the vault during the reentrancy causes the share price to drop. + // Still, the withdraw that trigger the reentrancy is not affected and get the previewed price. // Further withdraw will get a different price (needing more shares for the same value of assets) - it('share price change during reentracy does not affect withdraw', async function () { + it('share price change during reentrancy does not affect withdraw', async function () { await this.vault.connect(this.holder).deposit(value, this.holder); await this.vault.connect(this.other).deposit(value, this.other); diff --git a/test/token/ERC20/utils/SafeERC20.test.js b/test/token/ERC20/utils/SafeERC20.test.js index 16b72bd6b..0ae94630d 100644 --- a/test/token/ERC20/utils/SafeERC20.test.js +++ b/test/token/ERC20/utils/SafeERC20.test.js @@ -60,12 +60,24 @@ describe('SafeERC20', function () { .withArgs(this.token); }); + it('returns false on trySafeTransfer', async function () { + await expect(this.mock.$trySafeTransfer(this.token, this.receiver, 0n)) + .to.emit(this.mock, 'return$trySafeTransfer') + .withArgs(false); + }); + it('reverts on transferFrom', async function () { await expect(this.mock.$safeTransferFrom(this.token, this.mock, this.receiver, 0n)) .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation') .withArgs(this.token); }); + it('returns false on trySafeTransferFrom', async function () { + await expect(this.mock.$trySafeTransferFrom(this.token, this.mock, this.receiver, 0n)) + .to.emit(this.mock, 'return$trySafeTransferFrom') + .withArgs(false); + }); + it('reverts on increaseAllowance', async function () { // Call to 'token.allowance' does not return any data, resulting in a decoding error (revert without reason) await expect(this.mock.$safeIncreaseAllowance(this.token, this.spender, 0n)).to.be.revertedWithoutReason(); @@ -94,12 +106,24 @@ describe('SafeERC20', function () { .withArgs(this.token); }); + it('returns false on trySafeTransfer', async function () { + await expect(this.mock.$trySafeTransfer(this.token, this.receiver, 0n)) + .to.emit(this.mock, 'return$trySafeTransfer') + .withArgs(false); + }); + it('reverts on transferFrom', async function () { await expect(this.mock.$safeTransferFrom(this.token, this.mock, this.receiver, 0n)) .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation') .withArgs(this.token); }); + it('returns false on trySafeTransferFrom', async function () { + await expect(this.mock.$trySafeTransferFrom(this.token, this.mock, this.receiver, 0n)) + .to.emit(this.mock, 'return$trySafeTransferFrom') + .withArgs(false); + }); + it('reverts on increaseAllowance', async function () { await expect(this.mock.$safeIncreaseAllowance(this.token, this.spender, 0n)) .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation') @@ -357,11 +381,23 @@ function shouldOnlyRevertOnErrors() { .withArgs(this.mock, this.receiver, 10n); }); + it('returns true on trySafeTransfer', async function () { + await expect(this.mock.$trySafeTransfer(this.token, this.receiver, 10n)) + .to.emit(this.mock, 'return$trySafeTransfer') + .withArgs(true); + }); + it("doesn't revert on transferFrom", async function () { await expect(this.mock.$safeTransferFrom(this.token, this.owner, this.receiver, 10n)) .to.emit(this.token, 'Transfer') .withArgs(this.owner, this.receiver, 10n); }); + + it('returns true on trySafeTransferFrom', async function () { + await expect(this.mock.$trySafeTransferFrom(this.token, this.owner, this.receiver, 10n)) + .to.emit(this.mock, 'return$trySafeTransferFrom') + .withArgs(true); + }); }); describe('approvals', function () { diff --git a/test/token/ERC6909/ERC6909.behavior.js b/test/token/ERC6909/ERC6909.behavior.js new file mode 100644 index 000000000..adfe15a32 --- /dev/null +++ b/test/token/ERC6909/ERC6909.behavior.js @@ -0,0 +1,216 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); + +const { shouldSupportInterfaces } = require('../../utils/introspection/SupportsInterface.behavior'); + +function shouldBehaveLikeERC6909() { + const firstTokenId = 1n; + const secondTokenId = 2n; + const randomTokenId = 125523n; + + const firstTokenSupply = 2000n; + const secondTokenSupply = 3000n; + const amount = 100n; + + describe('like an ERC6909', function () { + describe('balanceOf', function () { + describe("when accounts don't own tokens", function () { + it('return zero', async function () { + await expect(this.token.balanceOf(this.holder, firstTokenId)).to.eventually.be.equal(0n); + await expect(this.token.balanceOf(this.holder, secondTokenId)).to.eventually.be.equal(0n); + await expect(this.token.balanceOf(this.other, randomTokenId)).to.eventually.be.equal(0n); + }); + }); + + describe('when accounts own some tokens', function () { + beforeEach(async function () { + await this.token.$_mint(this.holder, firstTokenId, firstTokenSupply); + await this.token.$_mint(this.holder, secondTokenId, secondTokenSupply); + }); + + it('returns amount owned by the given address', async function () { + await expect(this.token.balanceOf(this.holder, firstTokenId)).to.eventually.be.equal(firstTokenSupply); + await expect(this.token.balanceOf(this.holder, secondTokenId)).to.eventually.be.equal(secondTokenSupply); + await expect(this.token.balanceOf(this.other, firstTokenId)).to.eventually.be.equal(0n); + }); + }); + }); + + describe('setOperator', function () { + it('emits an OperatorSet event and updated the value', async function () { + await expect(this.token.connect(this.holder).setOperator(this.operator, true)) + .to.emit(this.token, 'OperatorSet') + .withArgs(this.holder, this.operator, true); + + // operator for holder + await expect(this.token.isOperator(this.holder, this.operator)).to.eventually.be.true; + + // not operator for other account + await expect(this.token.isOperator(this.other, this.operator)).to.eventually.be.false; + }); + + it('can unset the operator approval', async function () { + await this.token.connect(this.holder).setOperator(this.operator, true); + + // before + await expect(this.token.isOperator(this.holder, this.operator)).to.eventually.be.true; + + // unset + await expect(this.token.connect(this.holder).setOperator(this.operator, false)) + .to.emit(this.token, 'OperatorSet') + .withArgs(this.holder, this.operator, false); + + // after + await expect(this.token.isOperator(this.holder, this.operator)).to.eventually.be.false; + }); + + it('cannot set address(0) as an operator', async function () { + await expect(this.token.connect(this.holder).setOperator(ethers.ZeroAddress, true)) + .to.be.revertedWithCustomError(this.token, 'ERC6909InvalidSpender') + .withArgs(ethers.ZeroAddress); + }); + }); + + describe('approve', function () { + it('emits an Approval event and updates allowance', async function () { + await expect(this.token.connect(this.holder).approve(this.operator, firstTokenId, firstTokenSupply)) + .to.emit(this.token, 'Approval') + .withArgs(this.holder, this.operator, firstTokenId, firstTokenSupply); + + // approved + await expect(this.token.allowance(this.holder, this.operator, firstTokenId)).to.eventually.be.equal( + firstTokenSupply, + ); + // other account is not approved + await expect(this.token.allowance(this.other, this.operator, firstTokenId)).to.eventually.be.equal(0n); + }); + + it('can unset the approval', async function () { + await expect(this.token.connect(this.holder).approve(this.operator, firstTokenId, 0n)) + .to.emit(this.token, 'Approval') + .withArgs(this.holder, this.operator, firstTokenId, 0n); + await expect(this.token.allowance(this.holder, this.operator, firstTokenId)).to.eventually.be.equal(0n); + }); + + it('cannot give allowance to address(0)', async function () { + await expect(this.token.connect(this.holder).approve(ethers.ZeroAddress, firstTokenId, firstTokenSupply)) + .to.be.revertedWithCustomError(this.token, 'ERC6909InvalidSpender') + .withArgs(ethers.ZeroAddress); + }); + }); + + describe('transfer', function () { + beforeEach(async function () { + await this.token.$_mint(this.holder, firstTokenId, firstTokenSupply); + await this.token.$_mint(this.holder, secondTokenId, secondTokenSupply); + }); + + it('transfers to the zero address are blocked', async function () { + await expect(this.token.connect(this.holder).transfer(ethers.ZeroAddress, firstTokenId, firstTokenSupply)) + .to.be.revertedWithCustomError(this.token, 'ERC6909InvalidReceiver') + .withArgs(ethers.ZeroAddress); + }); + + it('reverts when insufficient balance', async function () { + await expect(this.token.connect(this.holder).transfer(this.recipient, firstTokenId, firstTokenSupply + 1n)) + .to.be.revertedWithCustomError(this.token, 'ERC6909InsufficientBalance') + .withArgs(this.holder, firstTokenSupply, firstTokenSupply + 1n, firstTokenId); + }); + + it('emits event and transfers tokens', async function () { + await expect(this.token.connect(this.holder).transfer(this.recipient, firstTokenId, amount)) + .to.emit(this.token, 'Transfer') + .withArgs(this.holder, this.holder, this.recipient, firstTokenId, amount); + + await expect(this.token.balanceOf(this.holder, firstTokenId)).to.eventually.equal(firstTokenSupply - amount); + await expect(this.token.balanceOf(this.recipient, firstTokenId)).to.eventually.equal(amount); + }); + }); + + describe('transferFrom', function () { + beforeEach(async function () { + await this.token.$_mint(this.holder, firstTokenId, firstTokenSupply); + await this.token.$_mint(this.holder, secondTokenId, secondTokenSupply); + }); + + it('transfer from self', async function () { + await expect(this.token.connect(this.holder).transferFrom(this.holder, this.recipient, firstTokenId, amount)) + .to.emit(this.token, 'Transfer') + .withArgs(this.holder, this.holder, this.recipient, firstTokenId, amount); + + await expect(this.token.balanceOf(this.holder, firstTokenId)).to.eventually.equal(firstTokenSupply - amount); + await expect(this.token.balanceOf(this.recipient, firstTokenId)).to.eventually.equal(amount); + }); + + describe('with approval', async function () { + beforeEach(async function () { + await this.token.connect(this.holder).approve(this.operator, firstTokenId, amount); + }); + + it('reverts when insufficient allowance', async function () { + await expect( + this.token.connect(this.operator).transferFrom(this.holder, this.recipient, firstTokenId, amount + 1n), + ) + .to.be.revertedWithCustomError(this.token, 'ERC6909InsufficientAllowance') + .withArgs(this.operator, amount, amount + 1n, firstTokenId); + }); + + it('should emit transfer event and update approval (without an Approval event)', async function () { + await expect( + this.token.connect(this.operator).transferFrom(this.holder, this.recipient, firstTokenId, amount - 1n), + ) + .to.emit(this.token, 'Transfer') + .withArgs(this.operator, this.holder, this.recipient, firstTokenId, amount - 1n) + .to.not.emit(this.token, 'Approval'); + + await expect(this.token.allowance(this.holder, this.operator, firstTokenId)).to.eventually.equal(1n); + }); + + it("shouldn't reduce allowance when infinite", async function () { + await this.token.connect(this.holder).approve(this.operator, firstTokenId, ethers.MaxUint256); + + await this.token.connect(this.operator).transferFrom(this.holder, this.recipient, firstTokenId, amount); + + await expect(this.token.allowance(this.holder, this.operator, firstTokenId)).to.eventually.equal( + ethers.MaxUint256, + ); + }); + }); + }); + + describe('with operator approval', function () { + beforeEach(async function () { + await this.token.connect(this.holder).setOperator(this.operator, true); + await this.token.$_mint(this.holder, firstTokenId, firstTokenSupply); + }); + + it('operator can transfer', async function () { + await expect(this.token.connect(this.operator).transferFrom(this.holder, this.recipient, firstTokenId, amount)) + .to.emit(this.token, 'Transfer') + .withArgs(this.operator, this.holder, this.recipient, firstTokenId, amount); + + await expect(this.token.balanceOf(this.holder, firstTokenId)).to.eventually.equal(firstTokenSupply - amount); + await expect(this.token.balanceOf(this.recipient, firstTokenId)).to.eventually.equal(amount); + }); + + it('operator transfer does not reduce allowance', async function () { + // Also give allowance + await this.token.connect(this.holder).approve(this.operator, firstTokenId, firstTokenSupply); + + await expect(this.token.connect(this.operator).transferFrom(this.holder, this.recipient, firstTokenId, amount)) + .to.emit(this.token, 'Transfer') + .withArgs(this.operator, this.holder, this.recipient, firstTokenId, amount); + + await expect(this.token.allowance(this.holder, this.operator, firstTokenId)).to.eventually.equal( + firstTokenSupply, + ); + }); + }); + + shouldSupportInterfaces(['ERC6909']); + }); +} + +module.exports = { + shouldBehaveLikeERC6909, +}; diff --git a/test/token/ERC6909/ERC6909.test.js b/test/token/ERC6909/ERC6909.test.js new file mode 100644 index 000000000..fa41145aa --- /dev/null +++ b/test/token/ERC6909/ERC6909.test.js @@ -0,0 +1,104 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); + +const { shouldBehaveLikeERC6909 } = require('./ERC6909.behavior'); + +async function fixture() { + const [holder, operator, recipient, other] = await ethers.getSigners(); + const token = await ethers.deployContract('$ERC6909'); + return { token, holder, operator, recipient, other }; +} + +describe('ERC6909', function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)); + }); + + shouldBehaveLikeERC6909(); + + describe('internal functions', function () { + const tokenId = 1990n; + const mintValue = 9001n; + const burnValue = 3000n; + + describe('_mint', function () { + it('reverts with a zero destination address', async function () { + await expect(this.token.$_mint(ethers.ZeroAddress, tokenId, mintValue)) + .to.be.revertedWithCustomError(this.token, 'ERC6909InvalidReceiver') + .withArgs(ethers.ZeroAddress); + }); + + describe('with minted tokens', function () { + beforeEach(async function () { + this.tx = await this.token.connect(this.operator).$_mint(this.holder, tokenId, mintValue); + }); + + it('emits a Transfer event from 0 address', async function () { + await expect(this.tx) + .to.emit(this.token, 'Transfer') + .withArgs(this.operator, ethers.ZeroAddress, this.holder, tokenId, mintValue); + }); + + it('credits the minted token value', async function () { + await expect(this.token.balanceOf(this.holder, tokenId)).to.eventually.be.equal(mintValue); + }); + }); + }); + + describe('_transfer', function () { + it('reverts when transferring from the zero address', async function () { + await expect(this.token.$_transfer(ethers.ZeroAddress, this.holder, 1n, 1n)) + .to.be.revertedWithCustomError(this.token, 'ERC6909InvalidSender') + .withArgs(ethers.ZeroAddress); + }); + + it('reverts when transferring to the zero address', async function () { + await expect(this.token.$_transfer(this.holder, ethers.ZeroAddress, 1n, 1n)) + .to.be.revertedWithCustomError(this.token, 'ERC6909InvalidReceiver') + .withArgs(ethers.ZeroAddress); + }); + }); + + describe('_burn', function () { + it('reverts with a zero from address', async function () { + await expect(this.token.$_burn(ethers.ZeroAddress, tokenId, burnValue)) + .to.be.revertedWithCustomError(this.token, 'ERC6909InvalidSender') + .withArgs(ethers.ZeroAddress); + }); + + describe('with burned tokens', function () { + beforeEach(async function () { + await this.token.connect(this.operator).$_mint(this.holder, tokenId, mintValue); + this.tx = await this.token.connect(this.operator).$_burn(this.holder, tokenId, burnValue); + }); + + it('emits a Transfer event to 0 address', async function () { + await expect(this.tx) + .to.emit(this.token, 'Transfer') + .withArgs(this.operator, this.holder, ethers.ZeroAddress, tokenId, burnValue); + }); + + it('debits the burned token value', async function () { + await expect(this.token.balanceOf(this.holder, tokenId)).to.eventually.be.equal(mintValue - burnValue); + }); + }); + }); + + describe('_approve', function () { + it('reverts when the owner is the zero address', async function () { + await expect(this.token.$_approve(ethers.ZeroAddress, this.recipient, 1n, 1n)) + .to.be.revertedWithCustomError(this.token, 'ERC6909InvalidApprover') + .withArgs(ethers.ZeroAddress); + }); + }); + + describe('_setOperator', function () { + it('reverts when the owner is the zero address', async function () { + await expect(this.token.$_setOperator(ethers.ZeroAddress, this.operator, true)) + .to.be.revertedWithCustomError(this.token, 'ERC6909InvalidApprover') + .withArgs(ethers.ZeroAddress); + }); + }); + }); +}); diff --git a/test/token/ERC6909/extensions/ERC6909ContentURI.test.js b/test/token/ERC6909/extensions/ERC6909ContentURI.test.js new file mode 100644 index 000000000..2a54e2216 --- /dev/null +++ b/test/token/ERC6909/extensions/ERC6909ContentURI.test.js @@ -0,0 +1,49 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); + +async function fixture() { + const token = await ethers.deployContract('$ERC6909ContentURI'); + return { token }; +} + +describe('ERC6909ContentURI', function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)); + }); + + describe('contractURI', function () { + it('is empty string by default', async function () { + await expect(this.token.contractURI()).to.eventually.equal(''); + }); + + it('is settable by internal setter', async function () { + await this.token.$_setContractURI('https://example.com'); + await expect(this.token.contractURI()).to.eventually.equal('https://example.com'); + }); + + it('emits an event when set', async function () { + await expect(this.token.$_setContractURI('https://example.com')).to.emit(this.token, 'ContractURIUpdated'); + }); + }); + + describe('tokenURI', function () { + it('is empty string by default', async function () { + await expect(this.token.tokenURI(1n)).to.eventually.equal(''); + }); + + it('can be set by dedicated setter', async function () { + await this.token.$_setTokenURI(1n, 'https://example.com/1'); + await expect(this.token.tokenURI(1n)).to.eventually.equal('https://example.com/1'); + + // Only set for the specified token ID + await expect(this.token.tokenURI(2n)).to.eventually.equal(''); + }); + + it('emits an event when set', async function () { + await expect(this.token.$_setTokenURI(1n, 'https://example.com/1')) + .to.emit(this.token, 'URI') + .withArgs('https://example.com/1', 1n); + }); + }); +}); diff --git a/test/token/ERC6909/extensions/ERC6909Metadata.test.js b/test/token/ERC6909/extensions/ERC6909Metadata.test.js new file mode 100644 index 000000000..e6d3dd9f3 --- /dev/null +++ b/test/token/ERC6909/extensions/ERC6909Metadata.test.js @@ -0,0 +1,58 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); + +async function fixture() { + const token = await ethers.deployContract('$ERC6909Metadata'); + return { token }; +} + +describe('ERC6909Metadata', function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)); + }); + + describe('name', function () { + it('is empty string be default', async function () { + await expect(this.token.name(1n)).to.eventually.equal(''); + }); + + it('can be set by dedicated setter', async function () { + await expect(this.token.$_setName(1n, 'My Token')) + .to.emit(this.token, 'ERC6909NameUpdated') + .withArgs(1n, 'My Token'); + await expect(this.token.name(1n)).to.eventually.equal('My Token'); + + // Only set for the specified token ID + await expect(this.token.name(2n)).to.eventually.equal(''); + }); + }); + + describe('symbol', function () { + it('is empty string be default', async function () { + await expect(this.token.symbol(1n)).to.eventually.equal(''); + }); + + it('can be set by dedicated setter', async function () { + await expect(this.token.$_setSymbol(1n, 'MTK')).to.emit(this.token, 'ERC6909SymbolUpdated').withArgs(1n, 'MTK'); + await expect(this.token.symbol(1n)).to.eventually.equal('MTK'); + + // Only set for the specified token ID + await expect(this.token.symbol(2n)).to.eventually.equal(''); + }); + }); + + describe('decimals', function () { + it('is 0 by default', async function () { + await expect(this.token.decimals(1n)).to.eventually.equal(0); + }); + + it('can be set by dedicated setter', async function () { + await expect(this.token.$_setDecimals(1n, 18)).to.emit(this.token, 'ERC6909DecimalsUpdated').withArgs(1n, 18); + await expect(this.token.decimals(1n)).to.eventually.equal(18); + + // Only set for the specified token ID + await expect(this.token.decimals(2n)).to.eventually.equal(0); + }); + }); +}); diff --git a/test/token/ERC6909/extensions/ERC6909TokenSupply.test.js b/test/token/ERC6909/extensions/ERC6909TokenSupply.test.js new file mode 100644 index 000000000..0b8b053d0 --- /dev/null +++ b/test/token/ERC6909/extensions/ERC6909TokenSupply.test.js @@ -0,0 +1,53 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); + +const { shouldBehaveLikeERC6909 } = require('../ERC6909.behavior'); + +async function fixture() { + const [holder, operator, recipient, other] = await ethers.getSigners(); + const token = await ethers.deployContract('$ERC6909TokenSupply'); + return { token, holder, operator, recipient, other }; +} + +describe('ERC6909TokenSupply', function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)); + }); + + shouldBehaveLikeERC6909(); + + describe('totalSupply', function () { + it('is zero before any mint', async function () { + await expect(this.token.totalSupply(1n)).to.eventually.be.equal(0n); + }); + + it('minting tokens increases the total supply', async function () { + await this.token.$_mint(this.holder, 1n, 17n); + await expect(this.token.totalSupply(1n)).to.eventually.be.equal(17n); + }); + + describe('with tokens minted', function () { + const supply = 1000n; + + beforeEach(async function () { + await this.token.$_mint(this.holder, 1n, supply); + }); + + it('burning tokens decreases the total supply', async function () { + await this.token.$_burn(this.holder, 1n, 17n); + await expect(this.token.totalSupply(1n)).to.eventually.be.equal(supply - 17n); + }); + + it('supply unaffected by transfers', async function () { + await this.token.$_transfer(this.holder, this.recipient, 1n, 42n); + await expect(this.token.totalSupply(1n)).to.eventually.be.equal(supply); + }); + + it('supply unaffected by no-op', async function () { + await this.token.$_update(ethers.ZeroAddress, ethers.ZeroAddress, 1n, 42n); + await expect(this.token.totalSupply(1n)).to.eventually.be.equal(supply); + }); + }); + }); +}); diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index b9dd80d6d..433ffe005 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -10,7 +10,6 @@ const firstTokenId = 5042n; const secondTokenId = 79217n; const nonExistentTokenId = 13n; const fourthTokenId = 4n; -const baseURI = 'https://api.example.com/v1/'; const RECEIVER_MAGIC_VALUE = '0x150b7a02'; @@ -936,31 +935,6 @@ function shouldBehaveLikeERC721Metadata(name, symbol) { .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken') .withArgs(nonExistentTokenId); }); - - describe('base URI', function () { - beforeEach(function () { - if (!this.token.interface.hasFunction('setBaseURI')) { - this.skip(); - } - }); - - it('base URI can be set', async function () { - await this.token.setBaseURI(baseURI); - expect(await this.token.baseURI()).to.equal(baseURI); - }); - - it('base URI is added as a prefix to the token URI', async function () { - await this.token.setBaseURI(baseURI); - expect(await this.token.tokenURI(firstTokenId)).to.equal(baseURI + firstTokenId.toString()); - }); - - it('token URI can be changed by changing the base URI', async function () { - await this.token.setBaseURI(baseURI); - const newBaseURI = 'https://api.example.com/v2/'; - await this.token.setBaseURI(newBaseURI); - expect(await this.token.tokenURI(firstTokenId)).to.equal(newBaseURI + firstTokenId.toString()); - }); - }); }); }); } diff --git a/test/token/ERC721/extensions/ERC721Consecutive.test.js b/test/token/ERC721/extensions/ERC721Consecutive.test.js index f62d6dc5b..8d8a30378 100644 --- a/test/token/ERC721/extensions/ERC721Consecutive.test.js +++ b/test/token/ERC721/extensions/ERC721Consecutive.test.js @@ -217,14 +217,6 @@ describe('ERC721Consecutive', function () { ).to.be.revertedWithCustomError(factory, 'ERC721ForbiddenMint'); }); - it('cannot use single minting during construction', async function () { - const factory = await ethers.getContractFactory('$ERC721ConsecutiveNoConstructorMintMock'); - - await expect( - ethers.deployContract('$ERC721ConsecutiveNoConstructorMintMock', [name, symbol]), - ).to.be.revertedWithCustomError(factory, 'ERC721ForbiddenMint'); - }); - it('consecutive mint not compatible with enumerability', async function () { const factory = await ethers.getContractFactory('$ERC721ConsecutiveEnumerableMock'); diff --git a/test/utils/Arrays.t.sol b/test/utils/Arrays.t.sol index 09c7b66b6..e45d29c91 100644 --- a/test/utils/Arrays.t.sol +++ b/test/utils/Arrays.t.sol @@ -7,12 +7,12 @@ import {SymTest} from "halmos-cheatcodes/SymTest.sol"; import {Arrays} from "@openzeppelin/contracts/utils/Arrays.sol"; contract ArraysTest is Test, SymTest { - function testSort(uint256[] memory values) public { + function testSort(uint256[] memory values) public pure { Arrays.sort(values); _assertSort(values); } - function symbolicSort() public { + function symbolicSort() public pure { uint256[] memory values = new uint256[](3); for (uint256 i = 0; i < 3; i++) { values[i] = svm.createUint256("arrayElement"); @@ -23,7 +23,7 @@ contract ArraysTest is Test, SymTest { /// Asserts - function _assertSort(uint256[] memory values) internal { + function _assertSort(uint256[] memory values) internal pure { for (uint256 i = 1; i < values.length; ++i) { assertLe(values[i - 1], values[i]); } diff --git a/test/utils/Base64.t.sol b/test/utils/Base64.t.sol index 021ae03af..b8aa7ac61 100644 --- a/test/utils/Base64.t.sol +++ b/test/utils/Base64.t.sol @@ -6,11 +6,11 @@ import {Test} from "forge-std/Test.sol"; import {Base64} from "@openzeppelin/contracts/utils/Base64.sol"; contract Base64Test is Test { - function testEncode(bytes memory input) external { + function testEncode(bytes memory input) external pure { assertEq(Base64.encode(input), vm.toBase64(input)); } - function testEncodeURL(bytes memory input) external { + function testEncodeURL(bytes memory input) external pure { assertEq(Base64.encodeURL(input), _removePadding(vm.toBase64URL(input))); } diff --git a/test/utils/Calldata.test.js b/test/utils/Calldata.test.js new file mode 100644 index 000000000..7e9d3d478 --- /dev/null +++ b/test/utils/Calldata.test.js @@ -0,0 +1,22 @@ +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); + +async function fixture() { + const mock = await ethers.deployContract('$Calldata'); + return { mock }; +} + +describe('Calldata utilities', function () { + beforeEach(async function () { + Object.assign(this, await loadFixture(fixture)); + }); + + it('emptyBytes', async function () { + await expect(this.mock.$emptyBytes()).to.eventually.equal('0x'); + }); + + it('emptyString', async function () { + await expect(this.mock.$emptyString()).to.eventually.equal(''); + }); +}); diff --git a/test/utils/Create2.t.sol b/test/utils/Create2.t.sol index 6cc037a3b..b73db9f9a 100644 --- a/test/utils/Create2.t.sol +++ b/test/utils/Create2.t.sol @@ -6,7 +6,7 @@ import {Test} from "forge-std/Test.sol"; import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; contract Create2Test is Test { - function testSymbolicComputeAddressSpillage(bytes32 salt, bytes32 bytecodeHash, address deployer) public { + function testSymbolicComputeAddressSpillage(bytes32 salt, bytes32 bytecodeHash, address deployer) public pure { address predicted = Create2.computeAddress(salt, bytecodeHash, deployer); bytes32 spillage; assembly ("memory-safe") { diff --git a/test/utils/Nonces.behavior.js b/test/utils/Nonces.behavior.js index 32201f690..c62864ea2 100644 --- a/test/utils/Nonces.behavior.js +++ b/test/utils/Nonces.behavior.js @@ -20,39 +20,39 @@ function shouldBehaveLikeNonces() { await expect(this.mock.$_useNonce(sender)).to.emit(this.mock, eventName).withArgs(0n); - expect(this.mock.nonces(sender)).to.eventually.equal(1n); + await expect(this.mock.nonces(sender)).to.eventually.equal(1n); }); it("increments only sender's nonce", async function () { - expect(this.mock.nonces(sender)).to.eventually.equal(0n); - expect(this.mock.nonces(other)).to.eventually.equal(0n); + await expect(this.mock.nonces(sender)).to.eventually.equal(0n); + await expect(this.mock.nonces(other)).to.eventually.equal(0n); await this.mock.$_useNonce(sender); - expect(this.mock.nonces(sender)).to.eventually.equal(1n); - expect(this.mock.nonces(other)).to.eventually.equal(0n); + await expect(this.mock.nonces(sender)).to.eventually.equal(1n); + await expect(this.mock.nonces(other)).to.eventually.equal(0n); }); }); describe('_useCheckedNonce', function () { it('increments a nonce', async function () { // current nonce is 0n - expect(this.mock.nonces(sender)).to.eventually.equal(0n); + await expect(this.mock.nonces(sender)).to.eventually.equal(0n); await this.mock.$_useCheckedNonce(sender, 0n); - expect(this.mock.nonces(sender)).to.eventually.equal(1n); + await expect(this.mock.nonces(sender)).to.eventually.equal(1n); }); it("increments only sender's nonce", async function () { // current nonce is 0n - expect(this.mock.nonces(sender)).to.eventually.equal(0n); - expect(this.mock.nonces(other)).to.eventually.equal(0n); + await expect(this.mock.nonces(sender)).to.eventually.equal(0n); + await expect(this.mock.nonces(other)).to.eventually.equal(0n); await this.mock.$_useCheckedNonce(sender, 0n); - expect(this.mock.nonces(sender)).to.eventually.equal(1n); - expect(this.mock.nonces(other)).to.eventually.equal(0n); + await expect(this.mock.nonces(sender)).to.eventually.equal(1n); + await expect(this.mock.nonces(other)).to.eventually.equal(0n); }); it('reverts when nonce is not the expected', async function () { @@ -73,14 +73,14 @@ function shouldBehaveLikeNoncesKeyed() { const keyOffset = key => key << 64n; it('gets a nonce', async function () { - expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n); - expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n); }); describe('_useNonce', function () { it('default variant uses key 0', async function () { - expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n); - expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n); await expect(this.mock.$_useNonce(sender)).to.emit(this.mock, 'return$_useNonce_address').withArgs(0n); @@ -88,13 +88,13 @@ function shouldBehaveLikeNoncesKeyed() { .to.emit(this.mock, 'return$_useNonce_address_uint192') .withArgs(keyOffset(0n) + 1n); - expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 2n); - expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 2n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n); }); it('use nonce at another key', async function () { - expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n); - expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n); await expect(this.mock.$_useNonce(sender, ethers.Typed.uint192(17n))) .to.emit(this.mock, 'return$_useNonce_address_uint192') @@ -104,8 +104,8 @@ function shouldBehaveLikeNoncesKeyed() { .to.emit(this.mock, 'return$_useNonce_address_uint192') .withArgs(keyOffset(17n) + 1n); - expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n); - expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 2n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 2n); }); }); @@ -115,7 +115,7 @@ function shouldBehaveLikeNoncesKeyed() { await this.mock.$_useCheckedNonce(sender, currentNonce); - expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(currentNonce + 1n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(currentNonce + 1n); }); it('use nonce at another key', async function () { @@ -123,7 +123,7 @@ function shouldBehaveLikeNoncesKeyed() { await this.mock.$_useCheckedNonce(sender, currentNonce); - expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(currentNonce + 1n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(currentNonce + 1n); }); it('reverts when nonce is not the expected', async function () { @@ -152,7 +152,7 @@ function shouldBehaveLikeNoncesKeyed() { await this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(0n), currentNonce); - expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(currentNonce + 1n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(currentNonce + 1n); }); it('use nonce at another key', async function () { @@ -160,7 +160,7 @@ function shouldBehaveLikeNoncesKeyed() { await this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(17n), currentNonce & MASK); - expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(currentNonce + 1n); + await expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(currentNonce + 1n); }); it('reverts when nonce is not the expected', async function () { diff --git a/test/utils/ShortStrings.t.sol b/test/utils/ShortStrings.t.sol index 4aeafd721..80313bf7c 100644 --- a/test/utils/ShortStrings.t.sol +++ b/test/utils/ShortStrings.t.sol @@ -10,12 +10,12 @@ import {ShortStrings, ShortString} from "@openzeppelin/contracts/utils/ShortStri contract ShortStringsTest is Test, SymTest { string _fallback; - function testRoundtripShort(string memory input) external { + function testRoundtripShort(string memory input) external pure { vm.assume(_isShort(input)); _assertRoundtripShort(input); } - function symbolicRoundtripShort() external { + function symbolicRoundtripShort() external pure { string memory input = svm.createString(31, "RoundtripShortInput"); _assertRoundtripShort(input); } @@ -41,12 +41,12 @@ contract ShortStringsTest is Test, SymTest { _assertRevertLong(input); } - function testLengthShort(string memory input) external { + function testLengthShort(string memory input) external pure { vm.assume(_isShort(input)); _assertLengthShort(input); } - function symbolicLengthShort() external { + function symbolicLengthShort() external pure { string memory input = svm.createString(31, "LengthShortInput"); _assertLengthShort(input); } @@ -66,7 +66,7 @@ contract ShortStringsTest is Test, SymTest { /// Assertions - function _assertRoundtripShort(string memory input) internal { + function _assertRoundtripShort(string memory input) internal pure { ShortString short = ShortStrings.toShortString(input); string memory output = ShortStrings.toString(short); assertEq(input, output); @@ -84,7 +84,7 @@ contract ShortStringsTest is Test, SymTest { this.toShortString(input); } - function _assertLengthShort(string memory input) internal { + function _assertLengthShort(string memory input) internal pure { ShortString short = ShortStrings.toShortString(input); uint256 shortLength = ShortStrings.byteLength(short); uint256 inputLength = bytes(input).length; diff --git a/test/utils/SlotDerivation.t.sol b/test/utils/SlotDerivation.t.sol index 4021f0f87..a0846e332 100644 --- a/test/utils/SlotDerivation.t.sol +++ b/test/utils/SlotDerivation.t.sol @@ -42,7 +42,7 @@ contract SlotDerivationTest is Test, SymTest { mapping(address => bytes) private _addressMapping; - function testSymbolicDeriveMappingAddress(address key) public { + function testSymbolicDeriveMappingAddress(address key) public view { bytes32 baseSlot; assembly { baseSlot := _addressMapping.slot @@ -59,7 +59,7 @@ contract SlotDerivationTest is Test, SymTest { mapping(bool => bytes) private _boolMapping; - function testSymbolicDeriveMappingBoolean(bool key) public { + function testSymbolicDeriveMappingBoolean(bool key) public view { bytes32 baseSlot; assembly { baseSlot := _boolMapping.slot @@ -76,7 +76,7 @@ contract SlotDerivationTest is Test, SymTest { mapping(bytes32 => bytes) private _bytes32Mapping; - function testSymbolicDeriveMappingBytes32(bytes32 key) public { + function testSymbolicDeriveMappingBytes32(bytes32 key) public view { bytes32 baseSlot; assembly { baseSlot := _bytes32Mapping.slot @@ -93,7 +93,7 @@ contract SlotDerivationTest is Test, SymTest { mapping(bytes4 => bytes) private _bytes4Mapping; - function testSymbolicDeriveMappingBytes4(bytes4 key) public { + function testSymbolicDeriveMappingBytes4(bytes4 key) public view { bytes32 baseSlot; assembly { baseSlot := _bytes4Mapping.slot @@ -110,7 +110,7 @@ contract SlotDerivationTest is Test, SymTest { mapping(uint256 => bytes) private _uint256Mapping; - function testSymbolicDeriveMappingUint256(uint256 key) public { + function testSymbolicDeriveMappingUint256(uint256 key) public view { bytes32 baseSlot; assembly { baseSlot := _uint256Mapping.slot @@ -127,7 +127,7 @@ contract SlotDerivationTest is Test, SymTest { mapping(uint32 => bytes) private _uint32Mapping; - function testSymbolicDeriveMappingUint32(uint32 key) public { + function testSymbolicDeriveMappingUint32(uint32 key) public view { bytes32 baseSlot; assembly { baseSlot := _uint32Mapping.slot @@ -144,7 +144,7 @@ contract SlotDerivationTest is Test, SymTest { mapping(int256 => bytes) private _int256Mapping; - function testSymbolicDeriveMappingInt256(int256 key) public { + function testSymbolicDeriveMappingInt256(int256 key) public view { bytes32 baseSlot; assembly { baseSlot := _int256Mapping.slot @@ -161,7 +161,7 @@ contract SlotDerivationTest is Test, SymTest { mapping(int32 => bytes) private _int32Mapping; - function testSymbolicDeriveMappingInt32(int32 key) public { + function testSymbolicDeriveMappingInt32(int32 key) public view { bytes32 baseSlot; assembly { baseSlot := _int32Mapping.slot @@ -178,15 +178,15 @@ contract SlotDerivationTest is Test, SymTest { mapping(string => bytes) private _stringMapping; - function testDeriveMappingString(string memory key) public { + function testDeriveMappingString(string memory key) public view { _assertDeriveMappingString(key); } - function symbolicDeriveMappingString() public { + function symbolicDeriveMappingString() public view { _assertDeriveMappingString(svm.createString(256, "DeriveMappingStringInput")); } - function _assertDeriveMappingString(string memory key) internal { + function _assertDeriveMappingString(string memory key) internal view { bytes32 baseSlot; assembly { baseSlot := _stringMapping.slot @@ -203,15 +203,15 @@ contract SlotDerivationTest is Test, SymTest { mapping(bytes => bytes) private _bytesMapping; - function testDeriveMappingBytes(bytes memory key) public { + function testDeriveMappingBytes(bytes memory key) public view { _assertDeriveMappingBytes(key); } - function symbolicDeriveMappingBytes() public { + function symbolicDeriveMappingBytes() public view { _assertDeriveMappingBytes(svm.createBytes(256, "DeriveMappingBytesInput")); } - function _assertDeriveMappingBytes(bytes memory key) internal { + function _assertDeriveMappingBytes(bytes memory key) internal view { bytes32 baseSlot; assembly { baseSlot := _bytesMapping.slot diff --git a/test/utils/Strings.t.sol b/test/utils/Strings.t.sol index f59e675cd..fe3c90bd1 100644 --- a/test/utils/Strings.t.sol +++ b/test/utils/Strings.t.sol @@ -9,19 +9,19 @@ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; contract StringsTest is Test { using Strings for *; - function testParse(uint256 value) external { + function testParse(uint256 value) external pure { assertEq(value, value.toString().parseUint()); } - function testParseSigned(int256 value) external { + function testParseSigned(int256 value) external pure { assertEq(value, value.toStringSigned().parseInt()); } - function testParseHex(uint256 value) external { + function testParseHex(uint256 value) external pure { assertEq(value, value.toHexString().parseHexUint()); } - function testParseChecksumHex(address value) external { + function testParseChecksumHex(address value) external pure { assertEq(value, value.toChecksumHexString().parseAddress()); } diff --git a/test/utils/Strings.test.js b/test/utils/Strings.test.js index 0b2d87190..8d5e2401a 100644 --- a/test/utils/Strings.test.js +++ b/test/utils/Strings.test.js @@ -339,4 +339,11 @@ describe('Strings', function () { } }); }); + + describe('Escape JSON string', function () { + for (const input of ['', 'a', '{"a":"b/c"}', 'a\tb\nc\\d"e\rf/g\fh\bi']) + it(`escape ${JSON.stringify(input)}`, async function () { + await expect(this.mock.$escapeJSON(input)).to.eventually.equal(JSON.stringify(input).slice(1, -1)); + }); + }); }); diff --git a/test/utils/cryptography/MessageHashUtils.t.sol b/test/utils/cryptography/MessageHashUtils.t.sol new file mode 100644 index 000000000..4259c8839 --- /dev/null +++ b/test/utils/cryptography/MessageHashUtils.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; + +contract MessageHashUtilsTest is Test { + function testToDataWithIntendedValidatorHash(address validator, bytes memory data) external pure { + assertEq( + MessageHashUtils.toDataWithIntendedValidatorHash(validator, data), + MessageHashUtils.toDataWithIntendedValidatorHash(_dirty(validator), data) + ); + } + + function testToDataWithIntendedValidatorHash(address validator, bytes32 messageHash) external pure { + assertEq( + MessageHashUtils.toDataWithIntendedValidatorHash(validator, messageHash), + MessageHashUtils.toDataWithIntendedValidatorHash(_dirty(validator), messageHash) + ); + + assertEq( + MessageHashUtils.toDataWithIntendedValidatorHash(validator, messageHash), + MessageHashUtils.toDataWithIntendedValidatorHash(validator, abi.encodePacked(messageHash)) + ); + } + + function _dirty(address input) private pure returns (address output) { + assembly ("memory-safe") { + output := or(input, shl(160, not(0))) + } + } +} diff --git a/test/utils/cryptography/MessageHashUtils.test.js b/test/utils/cryptography/MessageHashUtils.test.js index f20f5a3ca..57e82867e 100644 --- a/test/utils/cryptography/MessageHashUtils.test.js +++ b/test/utils/cryptography/MessageHashUtils.test.js @@ -19,14 +19,16 @@ describe('MessageHashUtils', function () { const message = ethers.randomBytes(32); const expectedHash = ethers.hashMessage(message); - expect(await this.mock.getFunction('$toEthSignedMessageHash(bytes32)')(message)).to.equal(expectedHash); + await expect(this.mock.getFunction('$toEthSignedMessageHash(bytes32)')(message)).to.eventually.equal( + expectedHash, + ); }); it('prefixes dynamic length data correctly', async function () { const message = ethers.randomBytes(128); const expectedHash = ethers.hashMessage(message); - expect(await this.mock.getFunction('$toEthSignedMessageHash(bytes)')(message)).to.equal(expectedHash); + await expect(this.mock.getFunction('$toEthSignedMessageHash(bytes)')(message)).to.eventually.equal(expectedHash); }); it('version match for bytes32', async function () { @@ -39,7 +41,20 @@ describe('MessageHashUtils', function () { }); describe('toDataWithIntendedValidatorHash', function () { - it('returns the digest correctly', async function () { + it('returns the digest of `bytes32 messageHash` correctly', async function () { + const verifier = ethers.Wallet.createRandom().address; + const message = ethers.randomBytes(32); + const expectedHash = ethers.solidityPackedKeccak256( + ['string', 'address', 'bytes32'], + ['\x19\x00', verifier, message], + ); + + await expect( + this.mock.getFunction('$toDataWithIntendedValidatorHash(address,bytes32)')(verifier, message), + ).to.eventually.equal(expectedHash); + }); + + it('returns the digest of `bytes memory message` correctly', async function () { const verifier = ethers.Wallet.createRandom().address; const message = ethers.randomBytes(128); const expectedHash = ethers.solidityPackedKeccak256( @@ -47,7 +62,21 @@ describe('MessageHashUtils', function () { ['\x19\x00', verifier, message], ); - expect(await this.mock.$toDataWithIntendedValidatorHash(verifier, message)).to.equal(expectedHash); + await expect( + this.mock.getFunction('$toDataWithIntendedValidatorHash(address,bytes)')(verifier, message), + ).to.eventually.equal(expectedHash); + }); + + it('version match for bytes32', async function () { + const verifier = ethers.Wallet.createRandom().address; + const message = ethers.randomBytes(32); + const fixed = await this.mock.getFunction('$toDataWithIntendedValidatorHash(address,bytes)')(verifier, message); + const dynamic = await this.mock.getFunction('$toDataWithIntendedValidatorHash(address,bytes32)')( + verifier, + message, + ); + + expect(fixed).to.equal(dynamic); }); }); @@ -62,7 +91,7 @@ describe('MessageHashUtils', function () { const structhash = ethers.randomBytes(32); const expectedHash = hashTypedData(domain, structhash); - expect(await this.mock.$toTypedDataHash(domainSeparator(domain), structhash)).to.equal(expectedHash); + await expect(this.mock.$toTypedDataHash(domainSeparator(domain), structhash)).to.eventually.equal(expectedHash); }); }); }); diff --git a/test/utils/cryptography/P256.t.sol b/test/utils/cryptography/P256.t.sol index 0c9b2c78a..768f9087f 100644 --- a/test/utils/cryptography/P256.t.sol +++ b/test/utils/cryptography/P256.t.sol @@ -6,10 +6,11 @@ import {Test} from "forge-std/Test.sol"; import {P256} from "@openzeppelin/contracts/utils/cryptography/P256.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import {Errors} from "@openzeppelin/contracts/utils/Errors.sol"; contract P256Test is Test { /// forge-config: default.fuzz.runs = 512 - function testVerify(bytes32 digest, uint256 seed) public { + function testVerify(bytes32 digest, uint256 seed) public view { uint256 privateKey = _asPrivateKey(seed); (uint256 x, uint256 y) = vm.publicKeyP256(privateKey); @@ -20,7 +21,7 @@ contract P256Test is Test { } /// forge-config: default.fuzz.runs = 512 - function testRecover(bytes32 digest, uint256 seed) public { + function testRecover(bytes32 digest, uint256 seed) public view { uint256 privateKey = _asPrivateKey(seed); (uint256 x, uint256 y) = vm.publicKeyP256(privateKey); @@ -31,6 +32,22 @@ contract P256Test is Test { assertTrue((qx0 == bytes32(x) && qy0 == bytes32(y)) || (qx1 == bytes32(x) && qy1 == bytes32(y))); } + function testVerifyNativeUnsupportedRIP7212(bytes32 digest, uint256 seed) public { + // By default, the precompile at address 0x100 is not supported. + + uint256 privateKey = _asPrivateKey(seed); + + (uint256 x, uint256 y) = vm.publicKeyP256(privateKey); + (bytes32 r, bytes32 s) = vm.signP256(privateKey, digest); + s = _ensureLowerS(s); + + (bool success, bytes memory returndata) = address(this).call( + abi.encodeCall(P256Test.verifyNative, (digest, r, s, bytes32(x), bytes32(y))) + ); + assertFalse(success); + assertEq(returndata, abi.encodeWithSelector(Errors.MissingPrecompile.selector, address(0x100))); + } + function _asPrivateKey(uint256 seed) private pure returns (uint256) { return bound(seed, 1, P256.N - 1); } @@ -41,4 +58,9 @@ contract P256Test is Test { return _s > P256.N / 2 ? bytes32(P256.N - _s) : s; } } + + // See https://github.com/foundry-rs/foundry/issues/10237 + function verifyNative(bytes32 digest, bytes32 r, bytes32 s, bytes32 x, bytes32 y) external view { + P256.verifyNative(digest, r, s, x, y); + } } diff --git a/test/utils/cryptography/P256.test.js b/test/utils/cryptography/P256.test.js index b9655cad3..a75d527be 100644 --- a/test/utils/cryptography/P256.test.js +++ b/test/utils/cryptography/P256.test.js @@ -44,26 +44,52 @@ describe('P256', function () { }); it('verify valid signature', async function () { - expect(await this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.be.true; - expect(await this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.be.true; - await expect(this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey)) - .to.be.revertedWithCustomError(this.mock, 'MissingPrecompile') - .withArgs('0x0000000000000000000000000000000000000100'); + await expect(this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be.true; + await expect(this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be + .true; + await expect(this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be + .true; + }); + + it('verify improper signature', async function () { + const signature = this.signature; + this.signature[0] = ethers.toBeHex(N, 0x20); // r = N + await expect(this.mock.$verify(this.messageHash, ...signature, ...this.publicKey)).to.eventually.be.false; + await expect(this.mock.$verifySolidity(this.messageHash, ...signature, ...this.publicKey)).to.eventually.be.false; + await expect(this.mock.$verifyNative(this.messageHash, ...signature, ...this.publicKey)).to.eventually.be.false; }); it('recover public key', async function () { - expect(await this.mock.$recovery(this.messageHash, this.recovery, ...this.signature)).to.deep.equal( + await expect(this.mock.$recovery(this.messageHash, this.recovery, ...this.signature)).to.eventually.deep.equal( this.publicKey, ); }); + it('recovers (0,0) for invalid recovery bit', async function () { + await expect(this.mock.$recovery(this.messageHash, 2, ...this.signature)).to.eventually.deep.equal([ + ethers.ZeroHash, + ethers.ZeroHash, + ]); + }); + + it('recovers (0,0) for improper signature', async function () { + const signature = this.signature; + this.signature[0] = ethers.toBeHex(N, 0x20); // r = N + await expect(this.mock.$recovery(this.messageHash, this.recovery, ...signature)).to.eventually.deep.equal([ + ethers.ZeroHash, + ethers.ZeroHash, + ]); + }); + it('reject signature with flipped public key coordinates ([x,y] >> [y,x])', async function () { // flip public key this.publicKey.reverse(); - expect(await this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false; - expect(await this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false; - expect(await this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false; // Flipped public key is not in the curve + await expect(this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be.false; + await expect(this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be + .false; + await expect(this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be + .false; }); it('reject signature with flipped signature values ([r,s] >> [s,r])', async function () { @@ -81,42 +107,42 @@ describe('P256', function () { ]; // Make sure it works - expect(await this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.be.true; + await expect(this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be.true; // Flip signature this.signature.reverse(); - expect(await this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false; - expect(await this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false; - await expect(this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey)) - .to.be.revertedWithCustomError(this.mock, 'MissingPrecompile') - .withArgs('0x0000000000000000000000000000000000000100'); - expect(await this.mock.$recovery(this.messageHash, this.recovery, ...this.signature)).to.not.deep.equal( - this.publicKey, - ); + await expect(this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be.false; + await expect(this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be + .false; + await expect(this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be + .false; + await expect( + this.mock.$recovery(this.messageHash, this.recovery, ...this.signature), + ).to.eventually.not.deep.equal(this.publicKey); }); it('reject signature with invalid message hash', async function () { // random message hash this.messageHash = ethers.hexlify(ethers.randomBytes(32)); - expect(await this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false; - expect(await this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false; - await expect(this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey)) - .to.be.revertedWithCustomError(this.mock, 'MissingPrecompile') - .withArgs('0x0000000000000000000000000000000000000100'); - expect(await this.mock.$recovery(this.messageHash, this.recovery, ...this.signature)).to.not.deep.equal( - this.publicKey, - ); + await expect(this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be.false; + await expect(this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be + .false; + await expect(this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey)).to.eventually.be + .false; + await expect( + this.mock.$recovery(this.messageHash, this.recovery, ...this.signature), + ).to.eventually.not.deep.equal(this.publicKey); }); it('fail to recover signature with invalid recovery bit', async function () { // flip recovery bit this.recovery = 1 - this.recovery; - expect(await this.mock.$recovery(this.messageHash, this.recovery, ...this.signature)).to.not.deep.equal( - this.publicKey, - ); + await expect( + this.mock.$recovery(this.messageHash, this.recovery, ...this.signature), + ).to.eventually.not.deep.equal(this.publicKey); }); }); @@ -148,7 +174,7 @@ describe('P256', function () { const messageHash = ethers.sha256('0x' + msg); // check verify - expect(await this.mock.$verify(messageHash, r, s, x, y)).to.equal(result == 'valid'); + await expect(this.mock.$verify(messageHash, r, s, x, y)).to.eventually.equal(result == 'valid'); }); } } diff --git a/test/utils/cryptography/SignatureChecker.test.js b/test/utils/cryptography/SignatureChecker.test.js index e6a08491a..2b14f2f4c 100644 --- a/test/utils/cryptography/SignatureChecker.test.js +++ b/test/utils/cryptography/SignatureChecker.test.js @@ -2,6 +2,8 @@ const { ethers } = require('hardhat'); const { expect } = require('chai'); const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); +const precompile = require('../../helpers/precompiles'); + const TEST_MESSAGE = ethers.id('OpenZeppelin'); const TEST_MESSAGE_HASH = ethers.hashMessage(TEST_MESSAGE); @@ -25,15 +27,18 @@ describe('SignatureChecker (ERC1271)', function () { describe('EOA account', function () { it('with matching signer and signature', async function () { - expect(await this.mock.$isValidSignatureNow(this.signer, TEST_MESSAGE_HASH, this.signature)).to.be.true; + await expect(this.mock.$isValidSignatureNow(this.signer, TEST_MESSAGE_HASH, this.signature)).to.eventually.be + .true; }); it('with invalid signer', async function () { - expect(await this.mock.$isValidSignatureNow(this.other, TEST_MESSAGE_HASH, this.signature)).to.be.false; + await expect(this.mock.$isValidSignatureNow(this.other, TEST_MESSAGE_HASH, this.signature)).to.eventually.be + .false; }); it('with invalid signature', async function () { - expect(await this.mock.$isValidSignatureNow(this.signer, WRONG_MESSAGE_HASH, this.signature)).to.be.false; + await expect(this.mock.$isValidSignatureNow(this.signer, WRONG_MESSAGE_HASH, this.signature)).to.eventually.be + .false; }); }); @@ -41,19 +46,28 @@ describe('SignatureChecker (ERC1271)', function () { for (const fn of ['isValidERC1271SignatureNow', 'isValidSignatureNow']) { describe(fn, function () { it('with matching signer and signature', async function () { - expect(await this.mock.getFunction(`$${fn}`)(this.wallet, TEST_MESSAGE_HASH, this.signature)).to.be.true; + await expect(this.mock.getFunction(`$${fn}`)(this.wallet, TEST_MESSAGE_HASH, this.signature)).to.eventually.be + .true; }); it('with invalid signer', async function () { - expect(await this.mock.getFunction(`$${fn}`)(this.mock, TEST_MESSAGE_HASH, this.signature)).to.be.false; + await expect(this.mock.getFunction(`$${fn}`)(this.mock, TEST_MESSAGE_HASH, this.signature)).to.eventually.be + .false; + }); + + it('with identity precompile', async function () { + await expect(this.mock.getFunction(`$${fn}`)(precompile.identity, TEST_MESSAGE_HASH, this.signature)).to + .eventually.be.false; }); it('with invalid signature', async function () { - expect(await this.mock.getFunction(`$${fn}`)(this.wallet, WRONG_MESSAGE_HASH, this.signature)).to.be.false; + await expect(this.mock.getFunction(`$${fn}`)(this.wallet, WRONG_MESSAGE_HASH, this.signature)).to.eventually + .be.false; }); it('with malicious wallet', async function () { - expect(await this.mock.getFunction(`$${fn}`)(this.malicious, TEST_MESSAGE_HASH, this.signature)).to.be.false; + await expect(this.mock.getFunction(`$${fn}`)(this.malicious, TEST_MESSAGE_HASH, this.signature)).to.eventually + .be.false; }); }); } diff --git a/test/utils/introspection/SupportsInterface.behavior.js b/test/utils/introspection/SupportsInterface.behavior.js index 8a7bc4b5e..6e716d130 100644 --- a/test/utils/introspection/SupportsInterface.behavior.js +++ b/test/utils/introspection/SupportsInterface.behavior.js @@ -3,6 +3,34 @@ const { interfaceId } = require('../../helpers/methods'); const { mapValues } = require('../../helpers/iterate'); const INVALID_ID = '0xffffffff'; +const GOVERNOR_INTERFACE = [ + 'name()', + 'version()', + 'COUNTING_MODE()', + 'hashProposal(address[],uint256[],bytes[],bytes32)', + 'state(uint256)', + 'proposalThreshold()', + 'proposalSnapshot(uint256)', + 'proposalDeadline(uint256)', + 'proposalProposer(uint256)', + 'proposalEta(uint256)', + 'proposalNeedsQueuing(uint256)', + 'votingDelay()', + 'votingPeriod()', + 'quorum(uint256)', + 'getVotes(address,uint256)', + 'getVotesWithParams(address,uint256,bytes)', + 'hasVoted(uint256,address)', + 'propose(address[],uint256[],bytes[],string)', + 'queue(address[],uint256[],bytes[],bytes32)', + 'execute(address[],uint256[],bytes[],bytes32)', + 'cancel(address[],uint256[],bytes[],bytes32)', + 'castVote(uint256,uint8)', + 'castVoteWithReason(uint256,uint8,string)', + 'castVoteWithReasonAndParams(uint256,uint8,string,bytes)', + 'castVoteBySig(uint256,uint8,address,bytes)', + 'castVoteWithReasonAndParamsBySig(uint256,uint8,address,string,bytes,bytes)', +]; const SIGNATURES = { ERC165: ['supportsInterface(bytes4)'], ERC721: [ @@ -59,41 +87,32 @@ const SIGNATURES = { 'acceptDefaultAdminTransfer()', 'cancelDefaultAdminTransfer()', ], - Governor: [ - 'name()', - 'version()', - 'COUNTING_MODE()', - 'hashProposal(address[],uint256[],bytes[],bytes32)', - 'state(uint256)', - 'proposalThreshold()', - 'proposalSnapshot(uint256)', - 'proposalDeadline(uint256)', - 'proposalProposer(uint256)', - 'proposalEta(uint256)', - 'proposalNeedsQueuing(uint256)', - 'votingDelay()', - 'votingPeriod()', - 'quorum(uint256)', - 'getVotes(address,uint256)', - 'getVotesWithParams(address,uint256,bytes)', - 'hasVoted(uint256,address)', - 'propose(address[],uint256[],bytes[],string)', - 'queue(address[],uint256[],bytes[],bytes32)', - 'execute(address[],uint256[],bytes[],bytes32)', - 'cancel(address[],uint256[],bytes[],bytes32)', - 'castVote(uint256,uint8)', - 'castVoteWithReason(uint256,uint8,string)', - 'castVoteWithReasonAndParams(uint256,uint8,string,bytes)', - 'castVoteBySig(uint256,uint8,address,bytes)', - 'castVoteWithReasonAndParamsBySig(uint256,uint8,address,string,bytes,bytes)', - ], + Governor: GOVERNOR_INTERFACE, + Governor_5_3: GOVERNOR_INTERFACE.concat('getProposalId(address[],uint256[],bytes[],bytes32)'), ERC2981: ['royaltyInfo(uint256,uint256)'], + ERC6909: [ + 'balanceOf(address,uint256)', + 'allowance(address,address,uint256)', + 'isOperator(address,address)', + 'transfer(address,uint256,uint256)', + 'transferFrom(address,address,uint256,uint256)', + 'approve(address,uint256,uint256)', + 'setOperator(address,bool)', + ], }; const INTERFACE_IDS = mapValues(SIGNATURES, interfaceId); -function shouldSupportInterfaces(interfaces = []) { +function shouldSupportInterfaces(interfaces = [], signatures = SIGNATURES) { + // case where only signatures are provided + if (!Array.isArray(interfaces)) { + signatures = interfaces; + interfaces = Object.keys(interfaces); + } + interfaces.unshift('ERC165'); + signatures.ERC165 = SIGNATURES.ERC165; + const interfaceIds = mapValues(signatures, interfaceId, ([name]) => interfaces.includes(name)); describe('ERC165', function () { beforeEach(function () { @@ -103,14 +122,14 @@ function shouldSupportInterfaces(interfaces = []) { describe('when the interfaceId is supported', function () { it('uses less than 30k gas', async function () { for (const k of interfaces) { - const interfaceId = INTERFACE_IDS[k] ?? k; + const interfaceId = interfaceIds[k] ?? k; expect(await this.contractUnderTest.supportsInterface.estimateGas(interfaceId)).to.lte(30_000n); } }); it('returns true', async function () { for (const k of interfaces) { - const interfaceId = INTERFACE_IDS[k] ?? k; + const interfaceId = interfaceIds[k] ?? k; expect(await this.contractUnderTest.supportsInterface(interfaceId), `does not support ${k}`).to.be.true; } }); @@ -129,10 +148,10 @@ function shouldSupportInterfaces(interfaces = []) { it('all interface functions are in ABI', async function () { for (const k of interfaces) { // skip interfaces for which we don't have a function list - if (SIGNATURES[k] === undefined) continue; + if (signatures[k] === undefined) continue; // Check the presence of each function in the contract's interface - for (const fnSig of SIGNATURES[k]) { + for (const fnSig of signatures[k]) { expect(this.contractUnderTest.interface.hasFunction(fnSig), `did not find ${fnSig}`).to.be.true; } } @@ -141,5 +160,7 @@ function shouldSupportInterfaces(interfaces = []) { } module.exports = { + SIGNATURES, + INTERFACE_IDS, shouldSupportInterfaces, }; diff --git a/test/utils/math/Math.t.sol b/test/utils/math/Math.t.sol index 3d4932eea..3c83febe9 100644 --- a/test/utils/math/Math.t.sol +++ b/test/utils/math/Math.t.sol @@ -7,18 +7,60 @@ import {Test, stdError} from "forge-std/Test.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; contract MathTest is Test { - function testSymbolicTernary(bool f, uint256 a, uint256 b) public { + function testSymbolicTernary(bool f, uint256 a, uint256 b) public pure { assertEq(Math.ternary(f, a, b), f ? a : b); } + // ADD512 & MUL512 + function testAdd512(uint256 a, uint256 b) public pure { + (uint256 high, uint256 low) = Math.add512(a, b); + + // test against tryAdd + (bool success, uint256 result) = Math.tryAdd(a, b); + if (success) { + assertEq(high, 0); + assertEq(low, result); + } else { + assertEq(high, 1); + } + + // test against unchecked + unchecked { + assertEq(low, a + b); // unchecked allow overflow + } + } + + function testMul512(uint256 a, uint256 b) public pure { + (uint256 high, uint256 low) = Math.mul512(a, b); + + // test against tryMul + (bool success, uint256 result) = Math.tryMul(a, b); + if (success) { + assertEq(high, 0); + assertEq(low, result); + } else { + assertGt(high, 0); + } + + // test against unchecked + unchecked { + assertEq(low, a * b); // unchecked allow overflow + } + + // test against alternative method + (uint256 _high, uint256 _low) = _mulKaratsuba(a, b); + assertEq(high, _high); + assertEq(low, _low); + } + // MIN & MAX - function testSymbolicMinMax(uint256 a, uint256 b) public { + function testSymbolicMinMax(uint256 a, uint256 b) public pure { assertEq(Math.min(a, b), a < b ? a : b); assertEq(Math.max(a, b), a > b ? a : b); } // CEILDIV - function testCeilDiv(uint256 a, uint256 b) public { + function testCeilDiv(uint256 a, uint256 b) public pure { vm.assume(b > 0); uint256 result = Math.ceilDiv(a, b); @@ -35,7 +77,7 @@ contract MathTest is Test { } // SQRT - function testSqrt(uint256 input, uint8 r) public { + function testSqrt(uint256 input, uint8 r) public pure { Math.Rounding rounding = _asRounding(r); uint256 result = Math.sqrt(input, rounding); @@ -66,31 +108,31 @@ contract MathTest is Test { } // INV - function testInvMod(uint256 value, uint256 p) public { + function testInvMod(uint256 value, uint256 p) public pure { _testInvMod(value, p, true); } - function testInvMod2(uint256 seed) public { + function testInvMod2(uint256 seed) public pure { uint256 p = 2; // prime _testInvMod(bound(seed, 1, p - 1), p, false); } - function testInvMod17(uint256 seed) public { + function testInvMod17(uint256 seed) public pure { uint256 p = 17; // prime _testInvMod(bound(seed, 1, p - 1), p, false); } - function testInvMod65537(uint256 seed) public { + function testInvMod65537(uint256 seed) public pure { uint256 p = 65537; // prime _testInvMod(bound(seed, 1, p - 1), p, false); } - function testInvModP256(uint256 seed) public { + function testInvModP256(uint256 seed) public pure { uint256 p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff; // prime _testInvMod(bound(seed, 1, p - 1), p, false); } - function _testInvMod(uint256 value, uint256 p, bool allowZero) private { + function _testInvMod(uint256 value, uint256 p, bool allowZero) private pure { uint256 inverse = Math.invMod(value, p); if (inverse != 0) { assertEq(mulmod(value, inverse, p), 1); @@ -101,7 +143,7 @@ contract MathTest is Test { } // LOG2 - function testLog2(uint256 input, uint8 r) public { + function testLog2(uint256 input, uint8 r) public pure { Math.Rounding rounding = _asRounding(r); uint256 result = Math.log2(input, rounding); @@ -128,7 +170,7 @@ contract MathTest is Test { } // LOG10 - function testLog10(uint256 input, uint8 r) public { + function testLog10(uint256 input, uint8 r) public pure { Math.Rounding rounding = _asRounding(r); uint256 result = Math.log10(input, rounding); @@ -155,7 +197,7 @@ contract MathTest is Test { } // LOG256 - function testLog256(uint256 input, uint8 r) public { + function testLog256(uint256 input, uint8 r) public pure { Math.Rounding rounding = _asRounding(r); uint256 result = Math.log256(input, rounding); @@ -182,9 +224,9 @@ contract MathTest is Test { } // MULDIV - function testMulDiv(uint256 x, uint256 y, uint256 d) public { + function testMulDiv(uint256 x, uint256 y, uint256 d) public pure { // Full precision for x * y - (uint256 xyHi, uint256 xyLo) = _mulHighLow(x, y); + (uint256 xyHi, uint256 xyLo) = Math.mul512(x, y); // Assume result won't overflow (see {testMulDivDomain}) // This also checks that `d` is positive @@ -194,9 +236,9 @@ contract MathTest is Test { uint256 q = Math.mulDiv(x, y, d); // Full precision for q * d - (uint256 qdHi, uint256 qdLo) = _mulHighLow(q, d); + (uint256 qdHi, uint256 qdLo) = Math.mul512(q, d); // Add remainder of x * y / d (computed as rem = (x * y % d)) - (uint256 qdRemLo, uint256 c) = _addCarry(qdLo, mulmod(x, y, d)); + (uint256 c, uint256 qdRemLo) = Math.add512(qdLo, mulmod(x, y, d)); uint256 qdRemHi = qdHi + c; // Full precision check that x * y = q * d + rem @@ -204,8 +246,9 @@ contract MathTest is Test { assertEq(xyLo, qdRemLo); } + /// forge-config: default.allow_internal_expect_revert = true function testMulDivDomain(uint256 x, uint256 y, uint256 d) public { - (uint256 xyHi, ) = _mulHighLow(x, y); + (uint256 xyHi, ) = Math.mul512(x, y); // Violate {testMulDiv} assumption (covers d is 0 and result overflow) vm.assume(xyHi >= d); @@ -216,6 +259,7 @@ contract MathTest is Test { } // MOD EXP + /// forge-config: default.allow_internal_expect_revert = true function testModExp(uint256 b, uint256 e, uint256 m) public { if (m == 0) { vm.expectRevert(stdError.divisionError); @@ -225,7 +269,7 @@ contract MathTest is Test { assertEq(result, _nativeModExp(b, e, m)); } - function testTryModExp(uint256 b, uint256 e, uint256 m) public { + function testTryModExp(uint256 b, uint256 e, uint256 m) public view { (bool success, uint256 result) = Math.tryModExp(b, e, m); assertEq(success, m != 0); if (success) { @@ -236,6 +280,7 @@ contract MathTest is Test { } } + /// forge-config: default.allow_internal_expect_revert = true function testModExpMemory(uint256 b, uint256 e, uint256 m) public { if (m == 0) { vm.expectRevert(stdError.divisionError); @@ -247,7 +292,7 @@ contract MathTest is Test { assertEq(res, _nativeModExp(b, e, m)); } - function testTryModExpMemory(uint256 b, uint256 e, uint256 m) public { + function testTryModExpMemory(uint256 b, uint256 e, uint256 m) public view { (bool success, bytes memory result) = Math.tryModExp( abi.encodePacked(b), abi.encodePacked(e), @@ -263,26 +308,13 @@ contract MathTest is Test { } } - function _nativeModExp(uint256 b, uint256 e, uint256 m) private pure returns (uint256) { - if (m == 1) return 0; - uint256 r = 1; - while (e > 0) { - if (e % 2 > 0) { - r = mulmod(r, b, m); - } - b = mulmod(b, b, m); - e >>= 1; - } - return r; - } - // Helpers function _asRounding(uint8 r) private pure returns (Math.Rounding) { vm.assume(r < uint8(type(Math.Rounding).max)); return Math.Rounding(r); } - function _mulHighLow(uint256 x, uint256 y) private pure returns (uint256 high, uint256 low) { + function _mulKaratsuba(uint256 x, uint256 y) private pure returns (uint256 high, uint256 low) { (uint256 x0, uint256 x1) = (x & type(uint128).max, x >> 128); (uint256 y0, uint256 y1) = (y & type(uint128).max, y >> 128); @@ -302,10 +334,16 @@ contract MathTest is Test { } } - function _addCarry(uint256 x, uint256 y) private pure returns (uint256 res, uint256 carry) { - unchecked { - res = x + y; + function _nativeModExp(uint256 b, uint256 e, uint256 m) private pure returns (uint256) { + if (m == 1) return 0; + uint256 r = 1; + while (e > 0) { + if (e % 2 > 0) { + r = mulmod(r, b, m); + } + b = mulmod(b, b, m); + e >>= 1; } - carry = res < x ? 1 : 0; + return r; } } diff --git a/test/utils/math/Math.test.js b/test/utils/math/Math.test.js index f38f2f318..6a0993814 100644 --- a/test/utils/math/Math.test.js +++ b/test/utils/math/Math.test.js @@ -16,10 +16,13 @@ const uint256 = value => ethers.Typed.uint256(value); bytes.zero = '0x'; uint256.zero = 0n; -async function testCommutative(fn, lhs, rhs, expected, ...extra) { - expect(await fn(lhs, rhs, ...extra)).to.deep.equal(expected); - expect(await fn(rhs, lhs, ...extra)).to.deep.equal(expected); -} +const testCommutative = (fn, lhs, rhs, expected, ...extra) => + Promise.all([ + expect(fn(lhs, rhs, ...extra)).to.eventually.deep.equal(expected), + expect(fn(rhs, lhs, ...extra)).to.eventually.deep.equal(expected), + ]); + +const splitHighLow = n => [n / (1n << 256n), n % (1n << 256n)]; async function fixture() { const mock = await ethers.deployContract('$Math'); @@ -39,6 +42,24 @@ describe('Math', function () { Object.assign(this, await loadFixture(fixture)); }); + describe('add512', function () { + it('adds correctly without reverting', async function () { + const values = [0n, 1n, 17n, 42n, ethers.MaxUint256 - 1n, ethers.MaxUint256]; + for (const [a, b] of product(values, values)) { + await expect(this.mock.$add512(a, b)).to.eventually.deep.equal(splitHighLow(a + b)); + } + }); + }); + + describe('mul512', function () { + it('multiplies correctly without reverting', async function () { + const values = [0n, 1n, 17n, 42n, ethers.MaxUint256 - 1n, ethers.MaxUint256]; + for (const [a, b] of product(values, values)) { + await expect(this.mock.$mul512(a, b)).to.eventually.deep.equal(splitHighLow(a * b)); + } + }); + }); + describe('tryAdd', function () { it('adds correctly', async function () { const a = 5678n; @@ -57,13 +78,13 @@ describe('Math', function () { it('subtracts correctly', async function () { const a = 5678n; const b = 1234n; - expect(await this.mock.$trySub(a, b)).to.deep.equal([true, a - b]); + await expect(this.mock.$trySub(a, b)).to.eventually.deep.equal([true, a - b]); }); it('reverts if subtraction result would be negative', async function () { const a = 1234n; const b = 5678n; - expect(await this.mock.$trySub(a, b)).to.deep.equal([false, 0n]); + await expect(this.mock.$trySub(a, b)).to.eventually.deep.equal([false, 0n]); }); }); @@ -91,25 +112,25 @@ describe('Math', function () { it('divides correctly', async function () { const a = 5678n; const b = 5678n; - expect(await this.mock.$tryDiv(a, b)).to.deep.equal([true, a / b]); + await expect(this.mock.$tryDiv(a, b)).to.eventually.deep.equal([true, a / b]); }); it('divides zero correctly', async function () { const a = 0n; const b = 5678n; - expect(await this.mock.$tryDiv(a, b)).to.deep.equal([true, a / b]); + await expect(this.mock.$tryDiv(a, b)).to.eventually.deep.equal([true, a / b]); }); it('returns complete number result on non-even division', async function () { const a = 7000n; const b = 5678n; - expect(await this.mock.$tryDiv(a, b)).to.deep.equal([true, a / b]); + await expect(this.mock.$tryDiv(a, b)).to.eventually.deep.equal([true, a / b]); }); it('reverts on division by zero', async function () { const a = 5678n; const b = 0n; - expect(await this.mock.$tryDiv(a, b)).to.deep.equal([false, 0n]); + await expect(this.mock.$tryDiv(a, b)).to.eventually.deep.equal([false, 0n]); }); }); @@ -118,32 +139,88 @@ describe('Math', function () { it('when the dividend is smaller than the divisor', async function () { const a = 284n; const b = 5678n; - expect(await this.mock.$tryMod(a, b)).to.deep.equal([true, a % b]); + await expect(this.mock.$tryMod(a, b)).to.eventually.deep.equal([true, a % b]); }); it('when the dividend is equal to the divisor', async function () { const a = 5678n; const b = 5678n; - expect(await this.mock.$tryMod(a, b)).to.deep.equal([true, a % b]); + await expect(this.mock.$tryMod(a, b)).to.eventually.deep.equal([true, a % b]); }); it('when the dividend is larger than the divisor', async function () { const a = 7000n; const b = 5678n; - expect(await this.mock.$tryMod(a, b)).to.deep.equal([true, a % b]); + await expect(this.mock.$tryMod(a, b)).to.eventually.deep.equal([true, a % b]); }); it('when the dividend is a multiple of the divisor', async function () { const a = 17034n; // 17034 == 5678 * 3 const b = 5678n; - expect(await this.mock.$tryMod(a, b)).to.deep.equal([true, a % b]); + await expect(this.mock.$tryMod(a, b)).to.eventually.deep.equal([true, a % b]); }); }); it('reverts with a 0 divisor', async function () { const a = 5678n; const b = 0n; - expect(await this.mock.$tryMod(a, b)).to.deep.equal([false, 0n]); + await expect(this.mock.$tryMod(a, b)).to.eventually.deep.equal([false, 0n]); + }); + }); + + describe('saturatingAdd', function () { + it('adds correctly', async function () { + const a = 5678n; + const b = 1234n; + await testCommutative(this.mock.$saturatingAdd, a, b, a + b); + await testCommutative(this.mock.$saturatingAdd, a, 0n, a); + await testCommutative(this.mock.$saturatingAdd, ethers.MaxUint256, 0n, ethers.MaxUint256); + }); + + it('bounds on addition overflow', async function () { + await testCommutative(this.mock.$saturatingAdd, ethers.MaxUint256, 1n, ethers.MaxUint256); + await expect(this.mock.$saturatingAdd(ethers.MaxUint256, ethers.MaxUint256)).to.eventually.equal( + ethers.MaxUint256, + ); + }); + }); + + describe('saturatingSub', function () { + it('subtracts correctly', async function () { + const a = 5678n; + const b = 1234n; + await expect(this.mock.$saturatingSub(a, b)).to.eventually.equal(a - b); + await expect(this.mock.$saturatingSub(a, a)).to.eventually.equal(0n); + await expect(this.mock.$saturatingSub(a, 0n)).to.eventually.equal(a); + await expect(this.mock.$saturatingSub(0n, a)).to.eventually.equal(0n); + await expect(this.mock.$saturatingSub(ethers.MaxUint256, 1n)).to.eventually.equal(ethers.MaxUint256 - 1n); + }); + + it('bounds on subtraction overflow', async function () { + await expect(this.mock.$saturatingSub(0n, 1n)).to.eventually.equal(0n); + await expect(this.mock.$saturatingSub(1n, 2n)).to.eventually.equal(0n); + await expect(this.mock.$saturatingSub(1n, ethers.MaxUint256)).to.eventually.equal(0n); + await expect(this.mock.$saturatingSub(ethers.MaxUint256 - 1n, ethers.MaxUint256)).to.eventually.equal(0n); + }); + }); + + describe('saturatingMul', function () { + it('multiplies correctly', async function () { + const a = 1234n; + const b = 5678n; + await testCommutative(this.mock.$saturatingMul, a, b, a * b); + }); + + it('multiplies by zero correctly', async function () { + const a = 0n; + const b = 5678n; + await testCommutative(this.mock.$saturatingMul, a, b, 0n); + }); + + it('bounds on multiplication overflow', async function () { + const a = ethers.MaxUint256; + const b = 2n; + await testCommutative(this.mock.$saturatingMul, a, b, ethers.MaxUint256); }); }); @@ -163,24 +240,24 @@ describe('Math', function () { it('is correctly calculated with two odd numbers', async function () { const a = 57417n; const b = 95431n; - expect(await this.mock.$average(a, b)).to.equal((a + b) / 2n); + await expect(this.mock.$average(a, b)).to.eventually.equal((a + b) / 2n); }); it('is correctly calculated with two even numbers', async function () { const a = 42304n; const b = 84346n; - expect(await this.mock.$average(a, b)).to.equal((a + b) / 2n); + await expect(this.mock.$average(a, b)).to.eventually.equal((a + b) / 2n); }); it('is correctly calculated with one even and one odd number', async function () { const a = 57417n; const b = 84346n; - expect(await this.mock.$average(a, b)).to.equal((a + b) / 2n); + await expect(this.mock.$average(a, b)).to.eventually.equal((a + b) / 2n); }); it('is correctly calculated with two max uint256 numbers', async function () { const a = ethers.MaxUint256; - expect(await this.mock.$average(a, a)).to.equal(a); + await expect(this.mock.$average(a, a)).to.eventually.equal(a); }); }); @@ -196,35 +273,35 @@ describe('Math', function () { const a = 0n; const b = 2n; const r = 0n; - expect(await this.mock.$ceilDiv(a, b)).to.equal(r); + await expect(this.mock.$ceilDiv(a, b)).to.eventually.equal(r); }); it('does not round up on exact division', async function () { const a = 10n; const b = 5n; const r = 2n; - expect(await this.mock.$ceilDiv(a, b)).to.equal(r); + await expect(this.mock.$ceilDiv(a, b)).to.eventually.equal(r); }); it('rounds up on division with remainders', async function () { const a = 42n; const b = 13n; const r = 4n; - expect(await this.mock.$ceilDiv(a, b)).to.equal(r); + await expect(this.mock.$ceilDiv(a, b)).to.eventually.equal(r); }); it('does not overflow', async function () { const a = ethers.MaxUint256; const b = 2n; const r = 1n << 255n; - expect(await this.mock.$ceilDiv(a, b)).to.equal(r); + await expect(this.mock.$ceilDiv(a, b)).to.eventually.equal(r); }); it('correctly computes max uint256 divided by 1', async function () { const a = ethers.MaxUint256; const b = 1n; const r = ethers.MaxUint256; - expect(await this.mock.$ceilDiv(a, b)).to.equal(r); + await expect(this.mock.$ceilDiv(a, b)).to.eventually.equal(r); }); }); @@ -248,28 +325,97 @@ describe('Math', function () { describe('does round down', function () { it('small values', async function () { for (const rounding of RoundingDown) { - expect(await this.mock.$mulDiv(3n, 4n, 5n, rounding)).to.equal(2n); - expect(await this.mock.$mulDiv(3n, 5n, 5n, rounding)).to.equal(3n); + await expect(this.mock.$mulDiv(3n, 4n, 5n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$mulDiv(3n, 5n, 5n, rounding)).to.eventually.equal(3n); } }); it('large values', async function () { for (const rounding of RoundingDown) { - expect(await this.mock.$mulDiv(42n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding)).to.equal(41n); + await expect(this.mock.$mulDiv(42n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding)).to.eventually.equal( + 41n, + ); - expect(await this.mock.$mulDiv(17n, ethers.MaxUint256, ethers.MaxUint256, rounding)).to.equal(17n); + await expect(this.mock.$mulDiv(17n, ethers.MaxUint256, ethers.MaxUint256, rounding)).to.eventually.equal(17n); - expect( - await this.mock.$mulDiv(ethers.MaxUint256 - 1n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding), - ).to.equal(ethers.MaxUint256 - 2n); + await expect( + this.mock.$mulDiv(ethers.MaxUint256 - 1n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding), + ).to.eventually.equal(ethers.MaxUint256 - 2n); - expect( - await this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding), - ).to.equal(ethers.MaxUint256 - 1n); + await expect( + this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding), + ).to.eventually.equal(ethers.MaxUint256 - 1n); - expect(await this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256, ethers.MaxUint256, rounding)).to.equal( + await expect( + this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256, ethers.MaxUint256, rounding), + ).to.eventually.equal(ethers.MaxUint256); + } + }); + }); + + describe('does round up', function () { + it('small values', async function () { + for (const rounding of RoundingUp) { + await expect(this.mock.$mulDiv(3n, 4n, 5n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$mulDiv(3n, 5n, 5n, rounding)).to.eventually.equal(3n); + } + }); + + it('large values', async function () { + for (const rounding of RoundingUp) { + await expect(this.mock.$mulDiv(42n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding)).to.eventually.equal( + 42n, + ); + + await expect(this.mock.$mulDiv(17n, ethers.MaxUint256, ethers.MaxUint256, rounding)).to.eventually.equal(17n); + + await expect( + this.mock.$mulDiv(ethers.MaxUint256 - 1n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding), + ).to.eventually.equal(ethers.MaxUint256 - 1n); + + await expect( + this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding), + ).to.eventually.equal(ethers.MaxUint256 - 1n); + + await expect( + this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256, ethers.MaxUint256, rounding), + ).to.eventually.equal(ethers.MaxUint256); + } + }); + }); + }); + + describe('mulShr', function () { + it('reverts with result higher than 2 ^ 256', async function () { + const a = 5n; + const b = ethers.MaxUint256; + const c = 1n; + await expect(this.mock.$mulShr(a, b, c, Rounding.Floor)).to.be.revertedWithPanic( + PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW, + ); + }); + + describe('does round down', function () { + it('small values', async function () { + for (const rounding of RoundingDown) { + await expect(this.mock.$mulShr(3n, 5n, 1n, rounding)).to.eventually.equal(7n); + await expect(this.mock.$mulShr(3n, 5n, 2n, rounding)).to.eventually.equal(3n); + } + }); + + it('large values', async function () { + for (const rounding of RoundingDown) { + await expect(this.mock.$mulShr(42n, ethers.MaxUint256, 255n, rounding)).to.eventually.equal(83n); + + await expect(this.mock.$mulShr(17n, ethers.MaxUint256, 255n, rounding)).to.eventually.equal(33n); + + await expect(this.mock.$mulShr(ethers.MaxUint256, ethers.MaxInt256 + 1n, 255n, rounding)).to.eventually.equal( ethers.MaxUint256, ); + + await expect(this.mock.$mulShr(ethers.MaxUint256, ethers.MaxInt256, 255n, rounding)).to.eventually.equal( + ethers.MaxUint256 - 2n, + ); } }); }); @@ -277,28 +423,24 @@ describe('Math', function () { describe('does round up', function () { it('small values', async function () { for (const rounding of RoundingUp) { - expect(await this.mock.$mulDiv(3n, 4n, 5n, rounding)).to.equal(3n); - expect(await this.mock.$mulDiv(3n, 5n, 5n, rounding)).to.equal(3n); + await expect(this.mock.$mulShr(3n, 5n, 1n, rounding)).to.eventually.equal(8n); + await expect(this.mock.$mulShr(3n, 5n, 2n, rounding)).to.eventually.equal(4n); } }); it('large values', async function () { for (const rounding of RoundingUp) { - expect(await this.mock.$mulDiv(42n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding)).to.equal(42n); + await expect(this.mock.$mulShr(42n, ethers.MaxUint256, 255n, rounding)).to.eventually.equal(84n); - expect(await this.mock.$mulDiv(17n, ethers.MaxUint256, ethers.MaxUint256, rounding)).to.equal(17n); + await expect(this.mock.$mulShr(17n, ethers.MaxUint256, 255n, rounding)).to.eventually.equal(34n); - expect( - await this.mock.$mulDiv(ethers.MaxUint256 - 1n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding), - ).to.equal(ethers.MaxUint256 - 1n); - - expect( - await this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding), - ).to.equal(ethers.MaxUint256 - 1n); - - expect(await this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256, ethers.MaxUint256, rounding)).to.equal( + await expect(this.mock.$mulShr(ethers.MaxUint256, ethers.MaxInt256 + 1n, 255n, rounding)).to.eventually.equal( ethers.MaxUint256, ); + + await expect(this.mock.$mulShr(ethers.MaxUint256, ethers.MaxInt256, 255n, rounding)).to.eventually.equal( + ethers.MaxUint256 - 1n, + ); } }); }); @@ -320,8 +462,8 @@ describe('Math', function () { describe(`using p=${p} which is ${p > 1 && factors.length > 1 ? 'not ' : ''}a prime`, function () { it('trying to inverse 0 returns 0', async function () { - expect(await this.mock.$invMod(0, p)).to.equal(0n); - expect(await this.mock.$invMod(p, p)).to.equal(0n); // p is 0 mod p + await expect(this.mock.$invMod(0, p)).to.eventually.equal(0n); + await expect(this.mock.$invMod(p, p)).to.eventually.equal(0n); // p is 0 mod p }); if (p != 0) { @@ -349,7 +491,7 @@ describe('Math', function () { const e = 200n; const m = 50n; - expect(await this.mock.$modExp(type(b), type(e), type(m))).to.equal(type(b ** e % m).value); + await expect(this.mock.$modExp(type(b), type(e), type(m))).to.eventually.equal(type(b ** e % m).value); }); it('is correctly reverting when modulus is zero', async function () { @@ -373,7 +515,9 @@ describe('Math', function () { it(`calculates b ** e % m (b=2**${log2b}+1) (e=2**${log2e}+1) (m=2**${log2m}+1)`, async function () { const mLength = ethers.dataLength(ethers.toBeHex(m)); - expect(await this.mock.$modExp(bytes(b), bytes(e), bytes(m))).to.equal(bytes(modExp(b, e, m), mLength).value); + await expect(this.mock.$modExp(bytes(b), bytes(e), bytes(m))).to.eventually.equal( + bytes(modExp(b, e, m), mLength).value, + ); }); } }); @@ -387,7 +531,10 @@ describe('Math', function () { const e = 200n; const m = 50n; - expect(await this.mock.$tryModExp(type(b), type(e), type(m))).to.deep.equal([true, type(b ** e % m).value]); + await expect(this.mock.$tryModExp(type(b), type(e), type(m))).to.eventually.deep.equal([ + true, + type(b ** e % m).value, + ]); }); it('is correctly reverting when modulus is zero', async function () { @@ -395,7 +542,7 @@ describe('Math', function () { const e = 200n; const m = 0n; - expect(await this.mock.$tryModExp(type(b), type(e), type(m))).to.deep.equal([false, type.zero]); + await expect(this.mock.$tryModExp(type(b), type(e), type(m))).to.eventually.deep.equal([false, type.zero]); }); }); } @@ -409,7 +556,7 @@ describe('Math', function () { it(`calculates b ** e % m (b=2**${log2b}+1) (e=2**${log2e}+1) (m=2**${log2m}+1)`, async function () { const mLength = ethers.dataLength(ethers.toBeHex(m)); - expect(await this.mock.$tryModExp(bytes(b), bytes(e), bytes(m))).to.deep.equal([ + await expect(this.mock.$tryModExp(bytes(b), bytes(e), bytes(m))).to.eventually.deep.equal([ true, bytes(modExp(b, e, m), mLength).value, ]); @@ -421,35 +568,39 @@ describe('Math', function () { describe('sqrt', function () { it('rounds down', async function () { for (const rounding of RoundingDown) { - expect(await this.mock.$sqrt(0n, rounding)).to.equal(0n); - expect(await this.mock.$sqrt(1n, rounding)).to.equal(1n); - expect(await this.mock.$sqrt(2n, rounding)).to.equal(1n); - expect(await this.mock.$sqrt(3n, rounding)).to.equal(1n); - expect(await this.mock.$sqrt(4n, rounding)).to.equal(2n); - expect(await this.mock.$sqrt(144n, rounding)).to.equal(12n); - expect(await this.mock.$sqrt(999999n, rounding)).to.equal(999n); - expect(await this.mock.$sqrt(1000000n, rounding)).to.equal(1000n); - expect(await this.mock.$sqrt(1000001n, rounding)).to.equal(1000n); - expect(await this.mock.$sqrt(1002000n, rounding)).to.equal(1000n); - expect(await this.mock.$sqrt(1002001n, rounding)).to.equal(1001n); - expect(await this.mock.$sqrt(ethers.MaxUint256, rounding)).to.equal(340282366920938463463374607431768211455n); + await expect(this.mock.$sqrt(0n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$sqrt(1n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$sqrt(2n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$sqrt(3n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$sqrt(4n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$sqrt(144n, rounding)).to.eventually.equal(12n); + await expect(this.mock.$sqrt(999999n, rounding)).to.eventually.equal(999n); + await expect(this.mock.$sqrt(1000000n, rounding)).to.eventually.equal(1000n); + await expect(this.mock.$sqrt(1000001n, rounding)).to.eventually.equal(1000n); + await expect(this.mock.$sqrt(1002000n, rounding)).to.eventually.equal(1000n); + await expect(this.mock.$sqrt(1002001n, rounding)).to.eventually.equal(1001n); + await expect(this.mock.$sqrt(ethers.MaxUint256, rounding)).to.eventually.equal( + 340282366920938463463374607431768211455n, + ); } }); it('rounds up', async function () { for (const rounding of RoundingUp) { - expect(await this.mock.$sqrt(0n, rounding)).to.equal(0n); - expect(await this.mock.$sqrt(1n, rounding)).to.equal(1n); - expect(await this.mock.$sqrt(2n, rounding)).to.equal(2n); - expect(await this.mock.$sqrt(3n, rounding)).to.equal(2n); - expect(await this.mock.$sqrt(4n, rounding)).to.equal(2n); - expect(await this.mock.$sqrt(144n, rounding)).to.equal(12n); - expect(await this.mock.$sqrt(999999n, rounding)).to.equal(1000n); - expect(await this.mock.$sqrt(1000000n, rounding)).to.equal(1000n); - expect(await this.mock.$sqrt(1000001n, rounding)).to.equal(1001n); - expect(await this.mock.$sqrt(1002000n, rounding)).to.equal(1001n); - expect(await this.mock.$sqrt(1002001n, rounding)).to.equal(1001n); - expect(await this.mock.$sqrt(ethers.MaxUint256, rounding)).to.equal(340282366920938463463374607431768211456n); + await expect(this.mock.$sqrt(0n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$sqrt(1n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$sqrt(2n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$sqrt(3n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$sqrt(4n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$sqrt(144n, rounding)).to.eventually.equal(12n); + await expect(this.mock.$sqrt(999999n, rounding)).to.eventually.equal(1000n); + await expect(this.mock.$sqrt(1000000n, rounding)).to.eventually.equal(1000n); + await expect(this.mock.$sqrt(1000001n, rounding)).to.eventually.equal(1001n); + await expect(this.mock.$sqrt(1002000n, rounding)).to.eventually.equal(1001n); + await expect(this.mock.$sqrt(1002001n, rounding)).to.eventually.equal(1001n); + await expect(this.mock.$sqrt(ethers.MaxUint256, rounding)).to.eventually.equal( + 340282366920938463463374607431768211456n, + ); } }); }); @@ -458,33 +609,33 @@ describe('Math', function () { describe('log2', function () { it('rounds down', async function () { for (const rounding of RoundingDown) { - expect(await this.mock.$log2(0n, rounding)).to.equal(0n); - expect(await this.mock.$log2(1n, rounding)).to.equal(0n); - expect(await this.mock.$log2(2n, rounding)).to.equal(1n); - expect(await this.mock.$log2(3n, rounding)).to.equal(1n); - expect(await this.mock.$log2(4n, rounding)).to.equal(2n); - expect(await this.mock.$log2(5n, rounding)).to.equal(2n); - expect(await this.mock.$log2(6n, rounding)).to.equal(2n); - expect(await this.mock.$log2(7n, rounding)).to.equal(2n); - expect(await this.mock.$log2(8n, rounding)).to.equal(3n); - expect(await this.mock.$log2(9n, rounding)).to.equal(3n); - expect(await this.mock.$log2(ethers.MaxUint256, rounding)).to.equal(255n); + await expect(this.mock.$log2(0n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log2(1n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log2(2n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log2(3n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log2(4n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log2(5n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log2(6n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log2(7n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log2(8n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log2(9n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log2(ethers.MaxUint256, rounding)).to.eventually.equal(255n); } }); it('rounds up', async function () { for (const rounding of RoundingUp) { - expect(await this.mock.$log2(0n, rounding)).to.equal(0n); - expect(await this.mock.$log2(1n, rounding)).to.equal(0n); - expect(await this.mock.$log2(2n, rounding)).to.equal(1n); - expect(await this.mock.$log2(3n, rounding)).to.equal(2n); - expect(await this.mock.$log2(4n, rounding)).to.equal(2n); - expect(await this.mock.$log2(5n, rounding)).to.equal(3n); - expect(await this.mock.$log2(6n, rounding)).to.equal(3n); - expect(await this.mock.$log2(7n, rounding)).to.equal(3n); - expect(await this.mock.$log2(8n, rounding)).to.equal(3n); - expect(await this.mock.$log2(9n, rounding)).to.equal(4n); - expect(await this.mock.$log2(ethers.MaxUint256, rounding)).to.equal(256n); + await expect(this.mock.$log2(0n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log2(1n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log2(2n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log2(3n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log2(4n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log2(5n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log2(6n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log2(7n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log2(8n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log2(9n, rounding)).to.eventually.equal(4n); + await expect(this.mock.$log2(ethers.MaxUint256, rounding)).to.eventually.equal(256n); } }); }); @@ -492,37 +643,37 @@ describe('Math', function () { describe('log10', function () { it('rounds down', async function () { for (const rounding of RoundingDown) { - expect(await this.mock.$log10(0n, rounding)).to.equal(0n); - expect(await this.mock.$log10(1n, rounding)).to.equal(0n); - expect(await this.mock.$log10(2n, rounding)).to.equal(0n); - expect(await this.mock.$log10(9n, rounding)).to.equal(0n); - expect(await this.mock.$log10(10n, rounding)).to.equal(1n); - expect(await this.mock.$log10(11n, rounding)).to.equal(1n); - expect(await this.mock.$log10(99n, rounding)).to.equal(1n); - expect(await this.mock.$log10(100n, rounding)).to.equal(2n); - expect(await this.mock.$log10(101n, rounding)).to.equal(2n); - expect(await this.mock.$log10(999n, rounding)).to.equal(2n); - expect(await this.mock.$log10(1000n, rounding)).to.equal(3n); - expect(await this.mock.$log10(1001n, rounding)).to.equal(3n); - expect(await this.mock.$log10(ethers.MaxUint256, rounding)).to.equal(77n); + await expect(this.mock.$log10(0n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log10(1n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log10(2n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log10(9n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log10(10n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log10(11n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log10(99n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log10(100n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log10(101n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log10(999n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log10(1000n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log10(1001n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log10(ethers.MaxUint256, rounding)).to.eventually.equal(77n); } }); it('rounds up', async function () { for (const rounding of RoundingUp) { - expect(await this.mock.$log10(0n, rounding)).to.equal(0n); - expect(await this.mock.$log10(1n, rounding)).to.equal(0n); - expect(await this.mock.$log10(2n, rounding)).to.equal(1n); - expect(await this.mock.$log10(9n, rounding)).to.equal(1n); - expect(await this.mock.$log10(10n, rounding)).to.equal(1n); - expect(await this.mock.$log10(11n, rounding)).to.equal(2n); - expect(await this.mock.$log10(99n, rounding)).to.equal(2n); - expect(await this.mock.$log10(100n, rounding)).to.equal(2n); - expect(await this.mock.$log10(101n, rounding)).to.equal(3n); - expect(await this.mock.$log10(999n, rounding)).to.equal(3n); - expect(await this.mock.$log10(1000n, rounding)).to.equal(3n); - expect(await this.mock.$log10(1001n, rounding)).to.equal(4n); - expect(await this.mock.$log10(ethers.MaxUint256, rounding)).to.equal(78n); + await expect(this.mock.$log10(0n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log10(1n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log10(2n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log10(9n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log10(10n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log10(11n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log10(99n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log10(100n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log10(101n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log10(999n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log10(1000n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log10(1001n, rounding)).to.eventually.equal(4n); + await expect(this.mock.$log10(ethers.MaxUint256, rounding)).to.eventually.equal(78n); } }); }); @@ -530,31 +681,31 @@ describe('Math', function () { describe('log256', function () { it('rounds down', async function () { for (const rounding of RoundingDown) { - expect(await this.mock.$log256(0n, rounding)).to.equal(0n); - expect(await this.mock.$log256(1n, rounding)).to.equal(0n); - expect(await this.mock.$log256(2n, rounding)).to.equal(0n); - expect(await this.mock.$log256(255n, rounding)).to.equal(0n); - expect(await this.mock.$log256(256n, rounding)).to.equal(1n); - expect(await this.mock.$log256(257n, rounding)).to.equal(1n); - expect(await this.mock.$log256(65535n, rounding)).to.equal(1n); - expect(await this.mock.$log256(65536n, rounding)).to.equal(2n); - expect(await this.mock.$log256(65537n, rounding)).to.equal(2n); - expect(await this.mock.$log256(ethers.MaxUint256, rounding)).to.equal(31n); + await expect(this.mock.$log256(0n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log256(1n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log256(2n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log256(255n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log256(256n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log256(257n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log256(65535n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log256(65536n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log256(65537n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log256(ethers.MaxUint256, rounding)).to.eventually.equal(31n); } }); it('rounds up', async function () { for (const rounding of RoundingUp) { - expect(await this.mock.$log256(0n, rounding)).to.equal(0n); - expect(await this.mock.$log256(1n, rounding)).to.equal(0n); - expect(await this.mock.$log256(2n, rounding)).to.equal(1n); - expect(await this.mock.$log256(255n, rounding)).to.equal(1n); - expect(await this.mock.$log256(256n, rounding)).to.equal(1n); - expect(await this.mock.$log256(257n, rounding)).to.equal(2n); - expect(await this.mock.$log256(65535n, rounding)).to.equal(2n); - expect(await this.mock.$log256(65536n, rounding)).to.equal(2n); - expect(await this.mock.$log256(65537n, rounding)).to.equal(3n); - expect(await this.mock.$log256(ethers.MaxUint256, rounding)).to.equal(32n); + await expect(this.mock.$log256(0n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log256(1n, rounding)).to.eventually.equal(0n); + await expect(this.mock.$log256(2n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log256(255n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log256(256n, rounding)).to.eventually.equal(1n); + await expect(this.mock.$log256(257n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log256(65535n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log256(65536n, rounding)).to.eventually.equal(2n); + await expect(this.mock.$log256(65537n, rounding)).to.eventually.equal(3n); + await expect(this.mock.$log256(ethers.MaxUint256, rounding)).to.eventually.equal(32n); } }); }); diff --git a/test/utils/math/SignedMath.t.sol b/test/utils/math/SignedMath.t.sol index bbad109b7..98a40a139 100644 --- a/test/utils/math/SignedMath.t.sol +++ b/test/utils/math/SignedMath.t.sol @@ -8,18 +8,18 @@ import {Math} from "../../../contracts/utils/math/Math.sol"; import {SignedMath} from "../../../contracts/utils/math/SignedMath.sol"; contract SignedMathTest is Test { - function testSymbolicTernary(bool f, int256 a, int256 b) public { + function testSymbolicTernary(bool f, int256 a, int256 b) public pure { assertEq(SignedMath.ternary(f, a, b), f ? a : b); } // MIN & MAX - function testSymbolicMinMax(int256 a, int256 b) public { + function testSymbolicMinMax(int256 a, int256 b) public pure { assertEq(SignedMath.min(a, b), a < b ? a : b); assertEq(SignedMath.max(a, b), a > b ? a : b); } // MIN - function testSymbolicMin(int256 a, int256 b) public { + function testSymbolicMin(int256 a, int256 b) public pure { int256 result = SignedMath.min(a, b); assertLe(result, a); @@ -28,7 +28,7 @@ contract SignedMathTest is Test { } // MAX - function testSymbolicMax(int256 a, int256 b) public { + function testSymbolicMax(int256 a, int256 b) public pure { int256 result = SignedMath.max(a, b); assertGe(result, a); @@ -38,7 +38,7 @@ contract SignedMathTest is Test { // AVERAGE // 1. simple test, not full int256 range - function testAverage1(int256 a, int256 b) public { + function testAverage1(int256 a, int256 b) public pure { a = bound(a, type(int256).min / 2, type(int256).max / 2); b = bound(b, type(int256).min / 2, type(int256).max / 2); @@ -48,7 +48,7 @@ contract SignedMathTest is Test { } // 2. more complex test, full int256 range - function testAverage2(int256 a, int256 b) public { + function testAverage2(int256 a, int256 b) public pure { (int256 result, int256 min, int256 max) = ( SignedMath.average(a, b), SignedMath.min(a, b), @@ -69,7 +69,7 @@ contract SignedMathTest is Test { } // ABS - function testSymbolicAbs(int256 a) public { + function testSymbolicAbs(int256 a) public pure { uint256 result = SignedMath.abs(a); unchecked { diff --git a/test/utils/structs/Checkpoints.t.sol b/test/utils/structs/Checkpoints.t.sol index 1f4b344c5..74d8fb8b8 100644 --- a/test/utils/structs/Checkpoints.t.sol +++ b/test/utils/structs/Checkpoints.t.sol @@ -10,7 +10,7 @@ import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol contract CheckpointsTrace224Test is Test { using Checkpoints for Checkpoints.Trace224; - // Maximum gap between keys used during the fuzzing tests: the `_prepareKeys` function with make sure that + // Maximum gap between keys used during the fuzzing tests: the `_prepareKeys` function will make sure that // key#n+1 is in the [key#n, key#n + _KEY_MAX_GAP] range. uint8 internal constant _KEY_MAX_GAP = 64; @@ -30,7 +30,7 @@ contract CheckpointsTrace224Test is Test { } } - function _assertLatestCheckpoint(bool exist, uint32 key, uint224 value) internal { + function _assertLatestCheckpoint(bool exist, uint32 key, uint224 value) internal view { (bool _exist, uint32 _key, uint224 _value) = _ckpts.latestCheckpoint(); assertEq(_exist, exist); assertEq(_key, key); @@ -118,7 +118,7 @@ contract CheckpointsTrace224Test is Test { contract CheckpointsTrace208Test is Test { using Checkpoints for Checkpoints.Trace208; - // Maximum gap between keys used during the fuzzing tests: the `_prepareKeys` function with make sure that + // Maximum gap between keys used during the fuzzing tests: the `_prepareKeys` function will make sure that // key#n+1 is in the [key#n, key#n + _KEY_MAX_GAP] range. uint8 internal constant _KEY_MAX_GAP = 64; @@ -138,7 +138,7 @@ contract CheckpointsTrace208Test is Test { } } - function _assertLatestCheckpoint(bool exist, uint48 key, uint208 value) internal { + function _assertLatestCheckpoint(bool exist, uint48 key, uint208 value) internal view { (bool _exist, uint48 _key, uint208 _value) = _ckpts.latestCheckpoint(); assertEq(_exist, exist); assertEq(_key, key); @@ -226,7 +226,7 @@ contract CheckpointsTrace208Test is Test { contract CheckpointsTrace160Test is Test { using Checkpoints for Checkpoints.Trace160; - // Maximum gap between keys used during the fuzzing tests: the `_prepareKeys` function with make sure that + // Maximum gap between keys used during the fuzzing tests: the `_prepareKeys` function will make sure that // key#n+1 is in the [key#n, key#n + _KEY_MAX_GAP] range. uint8 internal constant _KEY_MAX_GAP = 64; @@ -246,7 +246,7 @@ contract CheckpointsTrace160Test is Test { } } - function _assertLatestCheckpoint(bool exist, uint96 key, uint160 value) internal { + function _assertLatestCheckpoint(bool exist, uint96 key, uint160 value) internal view { (bool _exist, uint96 _key, uint160 _value) = _ckpts.latestCheckpoint(); assertEq(_exist, exist); assertEq(_key, key); diff --git a/test/utils/structs/EnumerableMap.behavior.js b/test/utils/structs/EnumerableMap.behavior.js index 37da41795..c80eec934 100644 --- a/test/utils/structs/EnumerableMap.behavior.js +++ b/test/utils/structs/EnumerableMap.behavior.js @@ -117,6 +117,49 @@ function shouldBehaveLikeMap() { }); }); + describe('clear', function () { + it('clears a single entry', async function () { + await this.methods.set(this.keyA, this.valueA); + + await this.methods.clear(); + + expect(await this.methods.contains(this.keyA)).to.be.false; + await expectMembersMatch(this.methods, [], []); + }); + + it('clears multiple entries', async function () { + await this.methods.set(this.keyA, this.valueA); + await this.methods.set(this.keyB, this.valueB); + await this.methods.set(this.keyC, this.valueC); + + await this.methods.clear(); + + expect(await this.methods.contains(this.keyA)).to.be.false; + expect(await this.methods.contains(this.keyB)).to.be.false; + expect(await this.methods.contains(this.keyC)).to.be.false; + await expectMembersMatch(this.methods, [], []); + }); + + it('does not revert on empty map', async function () { + await this.methods.clear(); + }); + + it('clear then add entry', async function () { + await this.methods.set(this.keyA, this.valueA); + await this.methods.set(this.keyB, this.valueB); + await this.methods.set(this.keyC, this.valueC); + + await this.methods.clear(); + + await this.methods.set(this.keyA, this.valueA); + + expect(await this.methods.contains(this.keyA)).to.be.true; + expect(await this.methods.contains(this.keyB)).to.be.false; + expect(await this.methods.contains(this.keyC)).to.be.false; + await expectMembersMatch(this.methods, [this.keyA], [this.valueA]); + }); + }); + describe('read', function () { beforeEach(async function () { await this.methods.set(this.keyA, this.valueA); diff --git a/test/utils/structs/EnumerableMap.test.js b/test/utils/structs/EnumerableMap.test.js index 5362e873a..cb4b77a65 100644 --- a/test/utils/structs/EnumerableMap.test.js +++ b/test/utils/structs/EnumerableMap.test.js @@ -26,6 +26,7 @@ async function fixture() { get: `$get_EnumerableMap_${name}(uint256,${keyType})`, tryGet: `$tryGet_EnumerableMap_${name}(uint256,${keyType})`, remove: `$remove_EnumerableMap_${name}(uint256,${keyType})`, + clear: `$clear_EnumerableMap_${name}(uint256)`, length: `$length_EnumerableMap_${name}(uint256)`, at: `$at_EnumerableMap_${name}(uint256,uint256)`, contains: `$contains_EnumerableMap_${name}(uint256,${keyType})`, diff --git a/test/utils/structs/EnumerableSet.behavior.js b/test/utils/structs/EnumerableSet.behavior.js index d3d4f26d5..fb932680c 100644 --- a/test/utils/structs/EnumerableSet.behavior.js +++ b/test/utils/structs/EnumerableSet.behavior.js @@ -47,7 +47,7 @@ function shouldBehaveLikeSet() { it('retrieves existing element', async function () { await this.methods.add(this.valueA); - expect(await this.methods.at(0)).to.equal(this.valueA); + expect(await this.methods.at(0)).to.deep.equal(this.valueA); }); }); @@ -109,6 +109,49 @@ function shouldBehaveLikeSet() { expect(await this.methods.contains(this.valueB)).to.be.false; }); }); + + describe('clear', function () { + it('clears a single value', async function () { + await this.methods.add(this.valueA); + + await this.methods.clear(); + + expect(await this.methods.contains(this.valueA)).to.be.false; + await expectMembersMatch(this.methods, []); + }); + + it('clears multiple values', async function () { + await this.methods.add(this.valueA); + await this.methods.add(this.valueB); + await this.methods.add(this.valueC); + + await this.methods.clear(); + + expect(await this.methods.contains(this.valueA)).to.be.false; + expect(await this.methods.contains(this.valueB)).to.be.false; + expect(await this.methods.contains(this.valueC)).to.be.false; + await expectMembersMatch(this.methods, []); + }); + + it('does not revert on empty set', async function () { + await this.methods.clear(); + }); + + it('clear then add value', async function () { + await this.methods.add(this.valueA); + await this.methods.add(this.valueB); + await this.methods.add(this.valueC); + + await this.methods.clear(); + + await this.methods.add(this.valueA); + + expect(await this.methods.contains(this.valueA)).to.be.true; + expect(await this.methods.contains(this.valueB)).to.be.false; + expect(await this.methods.contains(this.valueC)).to.be.false; + await expectMembersMatch(this.methods, [this.valueA]); + }); + }); } module.exports = { diff --git a/test/utils/structs/EnumerableSet.test.js b/test/utils/structs/EnumerableSet.test.js index 66d666058..1f92727a4 100644 --- a/test/utils/structs/EnumerableSet.test.js +++ b/test/utils/structs/EnumerableSet.test.js @@ -27,6 +27,7 @@ async function fixture() { methods: getMethods(mock, { add: `$add(uint256,${type})`, remove: `$remove(uint256,${type})`, + clear: `$clear_EnumerableSet_${name}(uint256)`, contains: `$contains(uint256,${type})`, length: `$length_EnumerableSet_${name}(uint256)`, at: `$at_EnumerableSet_${name}(uint256,uint256)`, diff --git a/test/utils/structs/Heap.t.sol b/test/utils/structs/Heap.t.sol index 434f37f66..ba7d77012 100644 --- a/test/utils/structs/Heap.t.sol +++ b/test/utils/structs/Heap.t.sol @@ -12,7 +12,7 @@ contract Uint256HeapTest is Test { Heap.Uint256Heap internal heap; - function _validateHeap(function(uint256, uint256) view returns (bool) comp) internal { + function _validateHeap(function(uint256, uint256) view returns (bool) comp) internal view { for (uint32 i = 1; i < heap.length(); ++i) { assertFalse(comp(heap.tree[i], heap.tree[(i - 1) / 2])); } diff --git a/test/utils/structs/MerkleTree.test.js b/test/utils/structs/MerkleTree.test.js index bec39ceea..f0380ed02 100644 --- a/test/utils/structs/MerkleTree.test.js +++ b/test/utils/structs/MerkleTree.test.js @@ -5,18 +5,23 @@ const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic'); const { StandardMerkleTree } = require('@openzeppelin/merkle-tree'); const { generators } = require('../../helpers/random'); +const { range } = require('../../helpers/iterate'); -const makeTree = (leaves = [ethers.ZeroHash]) => +const DEPTH = 4; // 16 slots + +const makeTree = (leaves = [], length = 2 ** DEPTH, zero = ethers.ZeroHash) => StandardMerkleTree.of( - leaves.map(leaf => [leaf]), + [] + .concat( + leaves, + Array.from({ length: length - leaves.length }, () => zero), + ) + .map(leaf => [leaf]), ['bytes32'], { sortLeaves: false }, ); -const hashLeaf = leaf => makeTree().leafHash([leaf]); - -const DEPTH = 4n; // 16 slots -const ZERO = hashLeaf(ethers.ZeroHash); +const ZERO = makeTree().leafHash([ethers.ZeroHash]); async function fixture() { const mock = await ethers.deployContract('MerkleTreeMock'); @@ -30,57 +35,132 @@ describe('MerkleTree', function () { }); it('sets initial values at setup', async function () { - const merkleTree = makeTree(Array.from({ length: 2 ** Number(DEPTH) }, () => ethers.ZeroHash)); + const merkleTree = makeTree(); - expect(await this.mock.root()).to.equal(merkleTree.root); - expect(await this.mock.depth()).to.equal(DEPTH); - expect(await this.mock.nextLeafIndex()).to.equal(0n); + await expect(this.mock.root()).to.eventually.equal(merkleTree.root); + await expect(this.mock.depth()).to.eventually.equal(DEPTH); + await expect(this.mock.nextLeafIndex()).to.eventually.equal(0n); }); describe('push', function () { - it('tree is correctly updated', async function () { - const leaves = Array.from({ length: 2 ** Number(DEPTH) }, () => ethers.ZeroHash); + it('pushing correctly updates the tree', async function () { + const leaves = []; // for each leaf slot - for (const i in leaves) { - // generate random leaf and hash it - const hashedLeaf = hashLeaf((leaves[i] = generators.bytes32())); + for (const i in range(2 ** DEPTH)) { + // generate random leaf + leaves.push(generators.bytes32()); - // update leaf list and rebuild tree. + // rebuild tree. const tree = makeTree(leaves); + const hash = tree.leafHash(tree.at(i)); // push value to tree - await expect(this.mock.push(hashedLeaf)).to.emit(this.mock, 'LeafInserted').withArgs(hashedLeaf, i, tree.root); + await expect(this.mock.push(hash)).to.emit(this.mock, 'LeafInserted').withArgs(hash, i, tree.root); // check tree - expect(await this.mock.root()).to.equal(tree.root); - expect(await this.mock.nextLeafIndex()).to.equal(BigInt(i) + 1n); + await expect(this.mock.root()).to.eventually.equal(tree.root); + await expect(this.mock.nextLeafIndex()).to.eventually.equal(BigInt(i) + 1n); } }); - it('revert when tree is full', async function () { + it('pushing to a full tree reverts', async function () { await Promise.all(Array.from({ length: 2 ** Number(DEPTH) }).map(() => this.mock.push(ethers.ZeroHash))); await expect(this.mock.push(ethers.ZeroHash)).to.be.revertedWithPanic(PANIC_CODES.TOO_MUCH_MEMORY_ALLOCATED); }); }); + describe('update', function () { + for (const { leafCount, leafIndex } of range(2 ** DEPTH + 1).flatMap(leafCount => + range(leafCount).map(leafIndex => ({ leafCount, leafIndex })), + )) + it(`updating a leaf correctly updates the tree (leaf #${leafIndex + 1}/${leafCount})`, async function () { + // initial tree + const leaves = Array.from({ length: leafCount }, generators.bytes32); + const oldTree = makeTree(leaves); + + // fill tree and verify root + for (const i in leaves) { + await this.mock.push(oldTree.leafHash(oldTree.at(i))); + } + await expect(this.mock.root()).to.eventually.equal(oldTree.root); + + // create updated tree + leaves[leafIndex] = generators.bytes32(); + const newTree = makeTree(leaves); + + const oldLeafHash = oldTree.leafHash(oldTree.at(leafIndex)); + const newLeafHash = newTree.leafHash(newTree.at(leafIndex)); + + // perform update + await expect(this.mock.update(leafIndex, oldLeafHash, newLeafHash, oldTree.getProof(leafIndex))) + .to.emit(this.mock, 'LeafUpdated') + .withArgs(oldLeafHash, newLeafHash, leafIndex, newTree.root); + + // verify updated root + await expect(this.mock.root()).to.eventually.equal(newTree.root); + + // if there is still room in the tree, fill it + for (const i of range(leafCount, 2 ** DEPTH)) { + // push new value and rebuild tree + leaves.push(generators.bytes32()); + const nextTree = makeTree(leaves); + + // push and verify root + await this.mock.push(nextTree.leafHash(nextTree.at(i))); + await expect(this.mock.root()).to.eventually.equal(nextTree.root); + } + }); + + it('replacing a leaf that was not previously pushed reverts', async function () { + // changing leaf 0 on an empty tree + await expect(this.mock.update(1, ZERO, ZERO, [])) + .to.be.revertedWithCustomError(this.mock, 'MerkleTreeUpdateInvalidIndex') + .withArgs(1, 0); + }); + + it('replacing a leaf using an invalid proof reverts', async function () { + const leafCount = 4; + const leafIndex = 2; + + const leaves = Array.from({ length: leafCount }, generators.bytes32); + const tree = makeTree(leaves); + + // fill tree and verify root + for (const i in leaves) { + await this.mock.push(tree.leafHash(tree.at(i))); + } + await expect(this.mock.root()).to.eventually.equal(tree.root); + + const oldLeafHash = tree.leafHash(tree.at(leafIndex)); + const newLeafHash = generators.bytes32(); + const proof = tree.getProof(leafIndex); + // invalid proof (tamper) + proof[1] = generators.bytes32(); + + await expect(this.mock.update(leafIndex, oldLeafHash, newLeafHash, proof)).to.be.revertedWithCustomError( + this.mock, + 'MerkleTreeUpdateInvalidProof', + ); + }); + }); + it('reset', async function () { // empty tree - const zeroLeaves = Array.from({ length: 2 ** Number(DEPTH) }, () => ethers.ZeroHash); - const zeroTree = makeTree(zeroLeaves); + const emptyTree = makeTree(); // tree with one element - const leaves = Array.from({ length: 2 ** Number(DEPTH) }, () => ethers.ZeroHash); - const hashedLeaf = hashLeaf((leaves[0] = generators.bytes32())); // fill first leaf and hash it + const leaves = [generators.bytes32()]; const tree = makeTree(leaves); + const hash = tree.leafHash(tree.at(0)); // root should be that of a zero tree - expect(await this.mock.root()).to.equal(zeroTree.root); + expect(await this.mock.root()).to.equal(emptyTree.root); expect(await this.mock.nextLeafIndex()).to.equal(0n); // push leaf and check root - await expect(this.mock.push(hashedLeaf)).to.emit(this.mock, 'LeafInserted').withArgs(hashedLeaf, 0, tree.root); + await expect(this.mock.push(hash)).to.emit(this.mock, 'LeafInserted').withArgs(hash, 0, tree.root); expect(await this.mock.root()).to.equal(tree.root); expect(await this.mock.nextLeafIndex()).to.equal(1n); @@ -88,11 +168,11 @@ describe('MerkleTree', function () { // reset tree await this.mock.setup(DEPTH, ZERO); - expect(await this.mock.root()).to.equal(zeroTree.root); + expect(await this.mock.root()).to.equal(emptyTree.root); expect(await this.mock.nextLeafIndex()).to.equal(0n); // re-push leaf and check root - await expect(this.mock.push(hashedLeaf)).to.emit(this.mock, 'LeafInserted').withArgs(hashedLeaf, 0, tree.root); + await expect(this.mock.push(hash)).to.emit(this.mock, 'LeafInserted').withArgs(hash, 0, tree.root); expect(await this.mock.root()).to.equal(tree.root); expect(await this.mock.nextLeafIndex()).to.equal(1n);