github-actions преди 2 години
родител
ревизия
6db3408885
променени са 100 файла, в които са добавени 1456 реда и са изтрити 433 реда
  1. 1 0
      .codecov.yml
  2. 1 1
      .editorconfig
  3. 1 1
      .eslintrc
  4. 49 0
      .github/actions/gas-compare/action.yml
  5. 28 0
      .github/workflows/changelog.yml
  6. 38 6
      .github/workflows/checks.yml
  7. 3 0
      .gitmodules
  8. 82 7
      CHANGELOG.md
  9. 7 6
      README.md
  10. 15 16
      certora/specs/GovernorBase.spec
  11. 2 2
      contracts/access/AccessControl.sol
  12. 57 0
      contracts/access/Ownable2Step.sol
  13. 1 1
      contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol
  14. 1 2
      contracts/crosschain/arbitrum/LibArbitrumL1.sol
  15. 1 1
      contracts/crosschain/arbitrum/LibArbitrumL2.sol
  16. 12 3
      contracts/finance/PaymentSplitter.sol
  17. 25 11
      contracts/finance/VestingWallet.sol
  18. 5 4
      contracts/governance/Governor.sol
  19. 2 2
      contracts/governance/IGovernor.sol
  20. 2 2
      contracts/governance/README.adoc
  21. 19 13
      contracts/governance/TimelockController.sol
  22. 1 5
      contracts/governance/compatibility/GovernorCompatibilityBravo.sol
  23. 13 13
      contracts/governance/extensions/GovernorCountingSimple.sol
  24. 2 2
      contracts/governance/extensions/GovernorVotesQuorumFraction.sol
  25. 5 5
      contracts/governance/utils/Votes.sol
  26. 21 0
      contracts/interfaces/IERC2309.sol
  27. 3 3
      contracts/interfaces/IERC4626.sol
  28. 6 0
      contracts/interfaces/README.adoc
  29. 3 3
      contracts/metatx/MinimalForwarder.sol
  30. 1 1
      contracts/mocks/AccessControlCrossChainMock.sol
  31. 0 19
      contracts/mocks/ArraysImpl.sol
  32. 51 0
      contracts/mocks/ArraysMock.sol
  33. 0 27
      contracts/mocks/CheckpointsImpl.sol
  34. 120 0
      contracts/mocks/CheckpointsMock.sol
  35. 1 1
      contracts/mocks/EIP712External.sol
  36. 1 1
      contracts/mocks/ERC1155PausableMock.sol
  37. 1 1
      contracts/mocks/ERC1155SupplyMock.sol
  38. 1 1
      contracts/mocks/ERC1155URIStorageMock.sol
  39. 1 1
      contracts/mocks/ERC165/ERC165MaliciousData.sol
  40. 1 1
      contracts/mocks/ERC165/ERC165ReturnBomb.sol
  41. 4 0
      contracts/mocks/ERC165CheckerMock.sol
  42. 1 1
      contracts/mocks/ERC20DecimalsMock.sol
  43. 1 2
      contracts/mocks/ERC20FlashMintMock.sol
  44. 2 2
      contracts/mocks/ERC2771ContextMock.sol
  45. 39 1
      contracts/mocks/ERC4626Mock.sol
  46. 55 0
      contracts/mocks/ERC721ConsecutiveEnumerableMock.sol
  47. 86 0
      contracts/mocks/ERC721ConsecutiveMock.sol
  48. 1 1
      contracts/mocks/ERC721EnumerableMock.sol
  49. 1 1
      contracts/mocks/ERC721URIStorageMock.sol
  50. 1 1
      contracts/mocks/ERC721VotesMock.sol
  51. 2 0
      contracts/mocks/EnumerableMapMock.sol
  52. 1 0
      contracts/mocks/EnumerableSetMock.sol
  53. 6 9
      contracts/mocks/GovernorCompatibilityBravoMock.sol
  54. 1 1
      contracts/mocks/GovernorMock.sol
  55. 3 4
      contracts/mocks/GovernorPreventLateQuorumMock.sol
  56. 3 5
      contracts/mocks/GovernorTimelockCompoundMock.sol
  57. 4 11
      contracts/mocks/GovernorTimelockControlMock.sol
  58. 2 2
      contracts/mocks/GovernorWithParamsMock.sol
  59. 8 0
      contracts/mocks/InitializableMock.sol
  60. 12 0
      contracts/mocks/MathMock.sol
  61. 1 1
      contracts/mocks/MulticallTest.sol
  62. 2 2
      contracts/mocks/MultipleInheritanceInitializableMocks.sol
  63. 7 0
      contracts/mocks/Ownable2StepMock.sol
  64. 1 0
      contracts/mocks/SafeCastMock.sol
  65. 2 2
      contracts/mocks/SafeERC20Helper.sol
  66. 4 4
      contracts/mocks/StringsMock.sol
  67. 2 2
      contracts/mocks/UUPS/UUPSLegacy.sol
  68. 3 3
      contracts/mocks/UUPS/UUPSUpgradeableMock.sol
  69. 1 1
      contracts/mocks/VotesMock.sol
  70. 1 1
      contracts/mocks/crosschain/bridges.sol
  71. 1 1
      contracts/package.json
  72. 20 18
      contracts/proxy/Clones.sol
  73. 1 1
      contracts/proxy/README.adoc
  74. 32 5
      contracts/proxy/utils/Initializable.sol
  75. 2 2
      contracts/proxy/utils/UUPSUpgradeable.sol
  76. 2 2
      contracts/security/PullPayment.sol
  77. 10 4
      contracts/security/ReentrancyGuard.sol
  78. 5 5
      contracts/token/ERC1155/ERC1155.sol
  79. 3 3
      contracts/token/ERC1155/extensions/ERC1155Burnable.sol
  80. 11 5
      contracts/token/ERC20/ERC20.sol
  81. 17 4
      contracts/token/ERC20/extensions/ERC20FlashMint.sol
  82. 32 9
      contracts/token/ERC20/extensions/ERC20Votes.sol
  83. 77 26
      contracts/token/ERC20/extensions/ERC4626.sol
  84. 2 2
      contracts/token/ERC20/extensions/draft-ERC20Permit.sol
  85. 2 2
      contracts/token/ERC20/utils/SafeERC20.sol
  86. 80 31
      contracts/token/ERC721/ERC721.sol
  87. 1 1
      contracts/token/ERC721/IERC721.sol
  88. 3 0
      contracts/token/ERC721/README.adoc
  89. 2 2
      contracts/token/ERC721/extensions/ERC721Burnable.sol
  90. 143 0
      contracts/token/ERC721/extensions/ERC721Consecutive.sol
  91. 12 16
      contracts/token/ERC721/extensions/ERC721Enumerable.sol
  92. 4 3
      contracts/token/ERC721/extensions/ERC721Pausable.sol
  93. 3 3
      contracts/token/ERC721/extensions/ERC721Royalty.sol
  94. 41 0
      contracts/token/ERC721/extensions/ERC721Votes.sol
  95. 4 35
      contracts/token/ERC721/extensions/draft-ERC721Votes.sol
  96. 4 3
      contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol
  97. 2 2
      contracts/token/ERC777/ERC777.sol
  98. 3 3
      contracts/token/ERC777/IERC777.sol
  99. 45 23
      contracts/utils/Address.sol
  100. 51 3
      contracts/utils/Arrays.sol

+ 1 - 0
.codecov.yml

@@ -6,6 +6,7 @@ coverage:
     patch:
       default:
         target: 95%
+        only_pulls: true
     project:
       default:
         threshold: 1%

+ 1 - 1
.editorconfig

@@ -17,5 +17,5 @@ indent_size = 4
 [*.js]
 indent_size = 2
 
-[*.adoc]
+[*.{adoc,md}]
 max_line_length = 0

+ 1 - 1
.eslintrc

@@ -57,6 +57,6 @@
     "promise/avoid-new": "off",
   },
   "parserOptions": {
-    "ecmaVersion": 2018
+    "ecmaVersion": 2020
   }
 }

+ 49 - 0
.github/actions/gas-compare/action.yml

@@ -0,0 +1,49 @@
+name: Compare gas costs
+inputs:
+  token:
+    description: github token
+    required: true
+  report:
+    description: report to read from
+    required: false
+    default: gasReporterOutput.json
+  out_report:
+    description: report to read
+    required: false
+    default: ${{ github.ref_name }}.gasreport.json
+  ref_report:
+    description: report to read from
+    required: false
+    default: ${{ github.base_ref }}.gasreport.json
+
+runs:
+  using: composite
+  steps:
+    - name: Download reference report
+      if: github.event_name == 'pull_request'
+      run: |
+        RUN_ID=`gh run list --repo ${{ github.repository }} --branch ${{ github.base_ref }} --workflow ${{ github.workflow }} --limit 100 --json 'conclusion,databaseId,event' --jq 'map(select(.conclusion=="success" and .event!="pull_request"))[0].databaseId'`
+        gh run download ${RUN_ID} --repo ${{ github.repository }} -n gasreport
+      env:
+        GITHUB_TOKEN: ${{ inputs.token }}
+      shell: bash
+      continue-on-error: true
+      id: reference
+    - name: Compare reports
+      if: steps.reference.outcome == 'success' && github.event_name == 'pull_request'
+      run: |
+        node scripts/checks/compareGasReports.js ${{ inputs.report }} ${{ inputs.ref_report }} >> $GITHUB_STEP_SUMMARY
+      env:
+        STYLE: markdown
+      shell: bash
+    - name: Rename report for upload
+      if: github.event_name != 'pull_request'
+      run: |
+        mv ${{ inputs.report }} ${{ inputs.out_report }}
+      shell: bash
+    - name: Save report
+      if: github.event_name != 'pull_request'
+      uses: actions/upload-artifact@v3
+      with:
+        name: gasreport
+        path: ${{ inputs.out_report }}

+ 28 - 0
.github/workflows/changelog.yml

@@ -0,0 +1,28 @@
+name: changelog
+
+on:
+  pull_request:
+    types:
+      - opened
+      - synchronize
+      - labeled
+      - unlabeled
+
+concurrency:
+  group: changelog-${{ github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  check:
+    runs-on: ubuntu-latest
+    if: ${{ !contains(github.event.pull_request.labels.*.name, 'ignore-changelog') }}
+    steps:
+      - uses: actions/checkout@v3
+      - name: Check diff
+        run: |
+          git fetch origin ${{ github.base_ref }} --depth=1
+          if git diff --exit-code origin/${{ github.base_ref }} -- CHANGELOG.md ; then
+            echo 'Missing changelog entry'
+            exit 1
+          fi
+

+ 38 - 6
.github/workflows/checks.yml

@@ -24,17 +24,38 @@ jobs:
 
   tests:
     runs-on: ubuntu-latest
+    env:
+      FORCE_COLOR: 1
+      GAS: true
     steps:
       - uses: actions/checkout@v3
       - name: Set up environment
         uses: ./.github/actions/setup
-      - run: npm run test
-        env:
-          FORCE_COLOR: 1
-          ENABLE_GAS_REPORT: true
-      - run: npm run test:inheritance
-      - run: npm run test:generation
+      - name: Run tests and generate gas report
+        run: npm run test
+      - name: Check linearisation of the inheritance graph
+        run: npm run test:inheritance
+      - name: Check proceduraly generated contracts are up-to-date
         if: github.repository != 'OpenZeppelin/openzeppelin-contracts-upgradeable'
+        run: npm run test:generation
+      - name: Compare gas costs
+        uses: ./.github/actions/gas-compare
+        with:
+          token: ${{ github.token }}
+
+  foundry-tests:
+    if: github.repository != 'OpenZeppelin/openzeppelin-contracts-upgradeable'
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          submodules: recursive
+      - name: Install Foundry
+        uses: foundry-rs/foundry-toolchain@v1
+        with:
+          version: nightly
+      - name: Run tests
+        run: forge test -vv
 
   coverage:
     if: github.repository != 'OpenZeppelin/openzeppelin-contracts-upgradeable'
@@ -56,3 +77,14 @@ jobs:
       - name: Set up environment
         uses: ./.github/actions/setup
       - uses: crytic/slither-action@v0.1.1
+
+  codespell:
+    if: github.repository != 'OpenZeppelin/openzeppelin-contracts-upgradeable'
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - name: Run CodeSpell
+        uses: codespell-project/actions-codespell@v1.0
+        with:
+          check_filenames: true
+          skip: package-lock.json

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
+[submodule "lib/forge-std"]
+	path = lib/forge-std
+	url = https://github.com/foundry-rs/forge-std

+ 82 - 7
CHANGELOG.md

@@ -1,18 +1,93 @@
 # Changelog
 
-## 4.7.3 (2022-08-10)
+## 4.8.0 (2022-11-08)
+
+ * `TimelockController`: Added a new `admin` constructor parameter that is assigned the admin role instead of the deployer account. ([#3722](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3722))
+ * `Initializable`: add internal functions `_getInitializedVersion` and `_isInitializing` ([#3598](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3598))
+ * `ERC165Checker`: add `supportsERC165InterfaceUnchecked` for consulting individual interfaces without the full ERC165 protocol. ([#3339](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3339))
+ * `Address`: optimize `functionCall` by calling `functionCallWithValue` directly. ([#3468](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3468))
+ * `Address`: optimize `functionCall` functions by checking contract size only if there is no returned data. ([#3469](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3469))
+ * `Governor`: make the `relay` function payable, and add support for EOA payments. ([#3730](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3730))
+ * `GovernorCompatibilityBravo`: remove unused `using` statements. ([#3506](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3506))
+ * `ERC20`: optimize `_transfer`, `_mint` and `_burn` by using `unchecked` arithmetic when possible. ([#3513](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3513))
+ * `ERC20Votes`, `ERC721Votes`: optimize `getPastVotes` for looking up recent checkpoints. ([#3673](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3673))
+ * `ERC20FlashMint`: add an internal `_flashFee` function for overriding. ([#3551](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3551))
+ * `ERC4626`: use the same `decimals()` as the underlying asset by default (if available). ([#3639](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3639))
+ * `ERC4626`: add internal `_initialConvertToShares` and `_initialConvertToAssets` functions to customize empty vaults behavior. ([#3639](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3639))
+ * `ERC721`: optimize transfers by making approval clearing implicit instead of emitting an event. ([#3481](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3481))
+ * `ERC721`: optimize burn by making approval clearing implicit instead of emitting an event. ([#3538](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3538))
+ * `ERC721`: Fix balance accounting when a custom `_beforeTokenTransfer` hook results in a transfer of the token under consideration. ([#3611](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3611))
+ * `ERC721`: use unchecked arithmetic for balance updates. ([#3524](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3524))
+ * `ERC721Consecutive`: Implementation of EIP-2309 that allows batch minting of ERC721 tokens during construction. ([#3311](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3311))
+ * `ReentrancyGuard`: Reduce code size impact of the modifier by using internal functions. ([#3515](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3515))
+ * `SafeCast`: optimize downcasting of signed integers. ([#3565](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3565))
+ * `ECDSA`: Remove redundant check on the `v` value. ([#3591](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3591))
+ * `VestingWallet`: add `releasable` getters. ([#3580](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3580))
+ * `VestingWallet`: remove unused library `Math.sol`. ([#3605](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3605))
+ * `VestingWallet`: make constructor payable. ([#3665](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3665))
+ * `Create2`: optimize address computation by using assembly instead of `abi.encodePacked`. ([#3600](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3600))
+ * `Clones`: optimized the assembly to use only the scratch space during deployments, and optimized `predictDeterministicAddress` to use fewer operations. ([#3640](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3640))
+ * `Checkpoints`: Use procedural generation to support multiple key/value lengths. ([#3589](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3589))
+ * `Checkpoints`: Add new lookup mechanisms. ([#3589](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3589))
+ * `Arrays`: Add `unsafeAccess` functions that allow reading and writing to an element in a storage array bypassing Solidity's "out-of-bounds" check. ([#3589](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3589))
+ * `Strings`: optimize `toString`. ([#3573](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3573))
+ * `Ownable2Step`: extension of `Ownable` that makes the ownership transfers a two step process. ([#3620](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3620))
+ * `Math` and `SignedMath`: optimize function `max` by using `>` instead of `>=`. ([#3679](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3679))
+ * `Math`: Add `log2`, `log10` and `log256`. ([#3670](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3670))
+ * Arbitrum: Update the vendored arbitrum contracts to match the nitro upgrade. ([#3692](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3692))
+
+### Breaking changes
+
+ * `ERC721`: In order to add support for batch minting via `ERC721Consecutive` it was necessary to make a minor breaking change in the internal interface of `ERC721`. Namely, the hooks `_beforeTokenTransfer` and `_afterTokenTransfer` have one additional argument that may need to be added to overrides:
+
+```diff
+ function _beforeTokenTransfer(
+     address from,
+     address to,
+     uint256 tokenId,
++    uint256 batchSize
+ ) internal virtual override
+```
+
+ * `ERC4626`: Conversion from shares to assets (and vice-versa) in an empty vault used to consider the possible mismatch between the underlying asset's and the vault's decimals. This initial conversion rate is now set to 1-to-1 irrespective of decimals, which are meant for usability purposes only. The vault now uses the assets decimals by default, so off-chain the numbers should appear the same. Developers overriding the vault decimals to a value that does not match the underlying asset may want to override the `_initialConvertToShares` and `_initialConvertToAssets` to replicate the previous behavior.
+
+ * `TimelockController`: During deployment, the TimelockController used to grant the `TIMELOCK_ADMIN_ROLE` to the deployer and to the timelock itself. The deployer was then expected to renounce this role once configuration of the timelock is over. Failing to renounce that role allows the deployer to change the timelock permissions (but not to bypass the delay for any time-locked actions). The role is no longer given to the deployer by default. A new parameter `admin` can be set to a non-zero address to grant the admin role during construction (to the deployer or any other address). Just like previously, this admin role should be renounced after configuration. If this param is given `address(0)`, the role is not allocated and doesn't need to be revoked. In any case, the timelock itself continues to have this role.
+
+### Deprecations
+
+ * `EIP712`: Added the file `EIP712.sol` and deprecated `draft-EIP712.sol` since the EIP is no longer a Draft. Developers are encouraged to update their imports. ([#3621](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3621))
+
+```diff
+-import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
++import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
+```
+
+ * `ERC721Votes`: Added the file `ERC721Votes.sol` and deprecated `draft-ERC721Votes.sol` since it no longer depends on a Draft EIP (EIP-712). Developers are encouraged to update their imports. ([#3699](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3699))
+
+```diff
+-import "@openzeppelin/contracts/token/ERC721/extensions/draft-ERC721Votes.sol";
++import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Votes.sol";
+```
+
+### ERC-721 Compatibility Note
+
+ERC-721 integrators that interpret contract state from events should make sure that they implement the clearing of approval that is implicit in every transfer according to the EIP. Previous versions of OpenZeppelin Contracts emitted an explicit `Approval` event even though it was not required by the specification, and this is no longer the case.
+
+With the new `ERC721Consecutive` extension, the internal workings of `ERC721` are slightly changed. Custom extensions to ERC721 should be reviewed to ensure they remain correct. The internal functions that should be considered are `_ownerOf` (new), `_beforeTokenTransfer`, and `_afterTokenTransfer`.
+
+## 4.7.3
 
 ### Breaking changes
 
  * `ECDSA`: `recover(bytes32,bytes)` and `tryRecover(bytes32,bytes)` no longer accept compact signatures to prevent malleability. Compact signature support remains available using `recover(bytes32,bytes32,bytes32)` and `tryRecover(bytes32,bytes32,bytes32)`.
 
-## 4.7.2 (2022-07-27)
+## 4.7.2
 
  * `LibArbitrumL2`, `CrossChainEnabledArbitrumL2`: Fixed detection of cross-chain calls for EOAs. Previously, calls from EOAs would be classified as cross-chain calls. ([#3578](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3578))
  * `GovernorVotesQuorumFraction`: Fixed quorum updates so they do not affect past proposals that failed due to lack of quorum. ([#3561](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3561))
  * `ERC165Checker`: Added protection against large returndata. ([#3587](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3587))
 
-## 4.7.1 (2022-07-19)
+## 4.7.1
 
  * `SignatureChecker`: Fix an issue that causes `isValidSignatureNow` to revert when the target contract returns ill-encoded data. ([#3552](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3552))
  * `ERC165Checker`: Fix an issue that causes `supportsInterface` to revert when the target contract returns ill-encoded data. ([#3552](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3552))
@@ -72,7 +147,7 @@
 ### Breaking changes
 
 * `Governor`: Adds internal virtual `_getVotes` method that must be implemented; this is a breaking change for existing concrete extensions to `Governor`. To fix this on an existing voting module extension, rename `getVotes` to `_getVotes` and add a `bytes memory` argument. ([#3043](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3043))
-* `Governor`: Adds `params` parameter to internal virtual `_countVote ` method; this is a breaking change for existing concrete extensions to `Governor`. To fix this on an existing counting module extension, add a `bytes memory` argument to `_countVote`. ([#3043](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3043))
+* `Governor`: Adds `params` parameter to internal virtual `_countVote` method; this is a breaking change for existing concrete extensions to `Governor`. To fix this on an existing counting module extension, add a `bytes memory` argument to `_countVote`. ([#3043](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3043))
 * `Governor`: Does not emit `VoteCast` event when params data is non-empty; instead emits `VoteCastWithParams` event. To fix this on an integration that consumes the `VoteCast` event, also fetch/monitor `VoteCastWithParams` events. ([#3043](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3043))
 * `Votes`: The internal virtual function `_getVotingUnits` was made `view` (which was accidentally missing). Any overrides should now be updated so they are `view` as well.
 
@@ -95,7 +170,7 @@
  * `ERC777`: do not update allowance on `transferFrom` when allowance is `type(uint256).max`. ([#3085](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3085))
  * `ERC777`: add a `_spendAllowance` internal function. ([#3170](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3170))
  * `SignedMath`: a new signed version of the Math library with `max`, `min`,  and `average`. ([#2686](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2686))
- * `SignedMath`: add a `abs(int256)` method that returns the unsigned absolute value of a signed value. ([#2984](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2984))
+ * `SignedMath`: add an `abs(int256)` method that returns the unsigned absolute value of a signed value. ([#2984](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2984))
  * `ERC1967Upgrade`: Refactor the secure upgrade to use `ERC1822` instead of the previous rollback mechanism. This reduces code complexity and attack surface with similar security guarantees. ([#3021](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3021))
  * `UUPSUpgradeable`: Add `ERC1822` compliance to support the updated secure upgrade mechanism. ([#3021](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3021))
  * Some more functions have been made virtual to customize them via overrides. In many cases this will not imply that other functions in the contract will automatically adapt to the overridden definitions. People who wish to override should consult the source code to understand the impact and if they need to override any additional functions to achieve the desired behavior.
@@ -199,7 +274,7 @@ It is no longer possible to call an `initializer`-protected function from within
  * `SignatureChecker`: add a signature verification library that supports both EOA and ERC1271 compliant contracts as signers. ([#2532](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2532))
  * `Multicall`: add abstract contract with `multicall(bytes[] calldata data)` function to bundle multiple calls together ([#2608](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2608))
  * `ECDSA`: add support for ERC2098 short-signatures. ([#2582](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2582))
- * `AccessControl`: add a `onlyRole` modifier to restrict specific function to callers bearing a specific role. ([#2609](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2609))
+ * `AccessControl`: add an `onlyRole` modifier to restrict specific function to callers bearing a specific role. ([#2609](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2609))
  * `StorageSlot`: add a library for reading and writing primitive types to specific storage slots. ([#2542](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2542))
  * UUPS Proxies: add `UUPSUpgradeable` to implement the UUPS proxy pattern together with `EIP1967Proxy`. ([#2542](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2542))
 
@@ -517,7 +592,7 @@ Refer to the table below to adjust your inheritance list.
  * Now conforming to a 4-space indentation code style. ([1508](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1508))
  * `ERC20`: more gas efficient due to removed redundant `require`s. ([#1409](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1409))
  * `ERC721`: fixed a bug that prevented internal data structures from being properly cleaned, missing potential gas refunds. ([#1539](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1539) and [#1549](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1549))
- * `ERC721`: general gas savings on `transferFrom`, `_mint` and `_burn`, due to redudant `require`s and `SSTORE`s. ([#1549](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1549))
+ * `ERC721`: general gas savings on `transferFrom`, `_mint` and `_burn`, due to redundant `require`s and `SSTORE`s. ([#1549](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1549))
 
 ### Bugfixes
 

+ 7 - 6
README.md

@@ -3,6 +3,7 @@
 [![Docs](https://img.shields.io/badge/docs-%F0%9F%93%84-blue)](https://docs.openzeppelin.com/contracts)
 [![NPM Package](https://img.shields.io/npm/v/@openzeppelin/contracts.svg)](https://www.npmjs.org/package/@openzeppelin/contracts)
 [![Coverage Status](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts/graph/badge.svg)](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts)
+[![gitpoap badge](https://public-api.gitpoap.io/v1/repo/OpenZeppelin/openzeppelin-contracts/badge)](https://www.gitpoap.io/gh/OpenZeppelin/openzeppelin-contracts)
 
 **A library for secure smart contract development.** Build on a solid foundation of community-vetted code.
 
@@ -22,9 +23,9 @@
 $ npm install @openzeppelin/contracts
 ```
 
-OpenZeppelin Contracts features a [stable API](https://docs.openzeppelin.com/contracts/releases-stability#api-stability), which means your contracts won't break unexpectedly when upgrading to a newer minor version.
+OpenZeppelin Contracts features a [stable API](https://docs.openzeppelin.com/contracts/releases-stability#api-stability), which means that your contracts won't break unexpectedly when upgrading to a newer minor version.
 
-An alternative to npm is to use the GitHub repository `openzeppelin/openzeppelin-contracts` to retrieve the contracts. When doing this, make sure to specify the tag for a release such as `v4.5.0`, instead of using the `master` branch.
+An alternative to npm is to use the GitHub repository (`openzeppelin/openzeppelin-contracts`) to retrieve the contracts. When doing this, make sure to specify the tag for a release such as `v4.5.0`, instead of using the `master` branch.
 
 ### Usage
 
@@ -43,20 +44,20 @@ contract MyCollectible is ERC721 {
 
 _If you're new to smart contract development, head to [Developing Smart Contracts](https://docs.openzeppelin.com/learn/developing-smart-contracts) to learn about creating a new project and compiling your contracts._
 
-To keep your system secure, you should **always** use the installed code as-is, and neither copy-paste it from online sources, nor modify it yourself. The library is designed so that only the contracts and functions you use are deployed, so you don't need to worry about it needlessly increasing gas costs.
+To keep your system secure, you should **always** use the installed code as-is, and neither copy-paste it from online sources nor modify it yourself. The library is designed so that only the contracts and functions you use are deployed, so you don't need to worry about it needlessly increasing gas costs.
 
 ## Learn More
 
-The guides in the [docs site](https://docs.openzeppelin.com/contracts) will teach about different concepts, and how to use the related contracts that OpenZeppelin Contracts provides:
+The guides in the [documentation site](https://docs.openzeppelin.com/contracts) will teach about different concepts, and how to use the related contracts that OpenZeppelin Contracts provides:
 
 * [Access Control](https://docs.openzeppelin.com/contracts/access-control): decide who can perform each of the actions on your system.
 * [Tokens](https://docs.openzeppelin.com/contracts/tokens): create tradeable assets or collectives, and distribute them via [Crowdsales](https://docs.openzeppelin.com/contracts/crowdsales).
 * [Gas Station Network](https://docs.openzeppelin.com/contracts/gsn): let your users interact with your contracts without having to pay for gas themselves.
-* [Utilities](https://docs.openzeppelin.com/contracts/utilities): generic useful tools, including non-overflowing math, signature verification, and trustless paying systems.
+* [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).
 
-Finally, you may want to take a look at the [guides on our blog](https://blog.openzeppelin.com/guides), 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.
+Finally, you may want to take a look at the [guides on our blog](https://blog.openzeppelin.com/guides), 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.
 
 * [The Hitchhiker’s Guide to Smart Contracts in Ethereum](https://blog.openzeppelin.com/the-hitchhikers-guide-to-smart-contracts-in-ethereum-848f08001f05) will help you get an overview of the various tools available for smart contract development, and help you set up your environment.
 * [A Gentle Introduction to Ethereum Programming, Part 1](https://blog.openzeppelin.com/a-gentle-introduction-to-ethereum-programming-part-1-783cc7796094) provides very useful information on an introductory level, including many basic concepts from the Ethereum platform.

+ 15 - 16
certora/specs/GovernorBase.spec

@@ -98,26 +98,26 @@ function helperFunctionsWithRevert(uint256 proposalId, method f, env e) {
  // To use env with general preserved block disable type checking [--disableLocalTypeChecking]
 invariant startAndEndDatesNonZero(uint256 pId)
         proposalSnapshot(pId) != 0 <=> proposalDeadline(pId) != 0
-        { preserved with (env e){   
+        { preserved with (env e){
                 require e.block.number > 0;
         }}
-        
+
 
 /*
- * If a proposal is canceled it must have a start and an end date 
+ * If a proposal is canceled it must have a start and an end date
  */
  // To use env with general preserved block disable type checking [--disableLocalTypeChecking]
 invariant canceledImplyStartAndEndDateNonZero(uint pId)
         isCanceled(pId) => proposalSnapshot(pId) != 0
-        {preserved with (env e){               
+        {preserved with (env e){
                 require e.block.number > 0;
         }}
 
 
 /*
- * If a proposal is executed it must have a start and an end date 
+ * If a proposal is executed it must have a start and an end date
  */
- // To use env with general preserved block disable type checking [--disableLocalTypeChecking] 
+ // To use env with general preserved block disable type checking [--disableLocalTypeChecking]
 invariant executedImplyStartAndEndDateNonZero(uint pId)
         isExecuted(pId) => proposalSnapshot(pId) != 0
         { preserved with (env e){
@@ -143,7 +143,7 @@ invariant voteStartBeforeVoteEnd(uint256 pId)
 /*
  * A proposal cannot be both executed and canceled simultaneously.
  */
-invariant noBothExecutedAndCanceled(uint256 pId) 
+invariant noBothExecutedAndCanceled(uint256 pId)
         !isExecuted(pId) || !isCanceled(pId)
 
 
@@ -154,10 +154,10 @@ rule executionOnlyIfQuoromReachedAndVoteSucceeded(uint256 pId, env e, method f){
     bool isExecutedBefore = isExecuted(pId);
     bool quorumReachedBefore = _quorumReached(e, pId);
     bool voteSucceededBefore = _voteSucceeded(pId);
-    
+
     calldataarg args;
     f(e, args);
-    
+
     bool isExecutedAfter = isExecuted(pId);
     assert (!isExecutedBefore && isExecutedAfter) => (quorumReachedBefore && voteSucceededBefore), "quorum was changed";
 }
@@ -177,16 +177,16 @@ rule executionOnlyIfQuoromReachedAndVoteSucceeded(uint256 pId, env e, method f){
  // the fact that the 3 functions themselves makes no changes, but rather call an internal function to execute.
  // That means that we do not check those 3 functions directly, however for castVote & castVoteWithReason it is quite trivial
  // to understand why this is ok. For castVoteBySig we basically assume that the signature referendum is correct without checking it.
- // We could check each function separately and pass the rule, but that would have uglyfied the code with no concrete 
+ // We could check each function separately and pass the rule, but that would have uglyfied the code with no concrete
  // benefit, as it is evident that nothing is happening in the first 2 functions (calling a view function), and we do not desire to check the signature verification.
 rule doubleVoting(uint256 pId, uint8 sup, method f) {
     env e;
-    address user = e.msg.sender;        
+    address user = e.msg.sender;
     bool votedCheck = hasVoted(e, pId, user);
 
     castVote@withrevert(e, pId, sup);
 
-    assert votedCheck => lastReverted, "double voting accured";
+    assert votedCheck => lastReverted, "double voting occurred";
 }
 
 
@@ -207,7 +207,7 @@ rule immutableFieldsAfterProposalCreation(uint256 pId, method f) {
     uint256 _voteEnd = proposalDeadline(pId);
 
     require proposalCreated(pId); // startDate > 0
-    
+
     env e; calldataarg arg;
     f(e, arg);
 
@@ -226,7 +226,7 @@ rule noStartBeforeCreation(uint256 pId) {
     // This line makes sure that we see only cases where start date is changed from 0, i.e. creation of proposal
     // We proved in immutableFieldsAfterProposalCreation that once dates set for proposal, it cannot be changed
     require !proposalCreated(pId); // previousStart == 0;
-    
+
     env e; calldataarg args;
     propose(e, args);
 
@@ -273,7 +273,7 @@ rule noExecuteOrCancelBeforeDeadline(uint256 pId, method f){
  * All proposal specific (non-view) functions should revert if proposal is executed
  */
  // In this rule we show that if a function is executed, i.e. execute() was called on the proposal ID,
- // non of the proposal specific functions can make changes again. In executedOnlyAfterExecuteFunc 
+ // non of the proposal specific functions can make changes again. In executedOnlyAfterExecuteFunc
  // we connected the executed attribute to the execute() function, showing that only execute() can
  // change it, and that it will always change it.
 rule allFunctionsRevertIfExecuted(method f) filtered { f ->
@@ -331,4 +331,3 @@ rule executedOnlyAfterExecuteFunc(address[] targets, uint256[] values, bytes[] c
     bool executedAfter = isExecuted(pId);
     assert(executedAfter != executedBefore => f.selector == execute(address[], uint256[], bytes[], bytes32).selector, "isExecuted only changes in the execute method");
 }
-

+ 2 - 2
contracts/access/AccessControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)
 
 pragma solidity ^0.8.0;
 
@@ -110,7 +110,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
                 string(
                     abi.encodePacked(
                         "AccessControl: account ",
-                        Strings.toHexString(uint160(account), 20),
+                        Strings.toHexString(account),
                         " is missing role ",
                         Strings.toHexString(uint256(role), 32)
                     )

+ 57 - 0
contracts/access/Ownable2Step.sol

@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol)
+
+pragma solidity ^0.8.0;
+
+import "./Ownable.sol";
+
+/**
+ * @dev Contract module which provides access control mechanism, where
+ * there is an account (an owner) that can be granted exclusive access to
+ * specific functions.
+ *
+ * By default, the owner account will be the one that deploys the contract. This
+ * can later be changed with {transferOwnership} and {acceptOwnership}.
+ *
+ * This module is used through inheritance. It will make available all functions
+ * from parent (Ownable).
+ */
+abstract contract Ownable2Step is Ownable {
+    address private _pendingOwner;
+
+    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
+
+    /**
+     * @dev Returns the address of the pending owner.
+     */
+    function pendingOwner() public view virtual returns (address) {
+        return _pendingOwner;
+    }
+
+    /**
+     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
+     * Can only be called by the current owner.
+     */
+    function transferOwnership(address newOwner) public virtual override onlyOwner {
+        _pendingOwner = newOwner;
+        emit OwnershipTransferStarted(owner(), newOwner);
+    }
+
+    /**
+     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
+     * Internal function without access restriction.
+     */
+    function _transferOwnership(address newOwner) internal virtual override {
+        delete _pendingOwner;
+        super._transferOwnership(newOwner);
+    }
+
+    /**
+     * @dev The new owner accepts the ownership transfer.
+     */
+    function acceptOwnership() external {
+        address sender = _msgSender();
+        require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
+        _transferOwnership(sender);
+    }
+}

+ 1 - 1
contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol)
 
 pragma solidity ^0.8.4;
 

+ 1 - 2
contracts/crosschain/arbitrum/LibArbitrumL1.sol

@@ -1,10 +1,9 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (crosschain/arbitrum/LibArbitrumL1.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (crosschain/arbitrum/LibArbitrumL1.sol)
 
 pragma solidity ^0.8.4;
 
 import {IBridge as ArbitrumL1_Bridge} from "../../vendor/arbitrum/IBridge.sol";
-import {IInbox as ArbitrumL1_Inbox} from "../../vendor/arbitrum/IInbox.sol";
 import {IOutbox as ArbitrumL1_Outbox} from "../../vendor/arbitrum/IOutbox.sol";
 import "../errors.sol";
 

+ 1 - 1
contracts/crosschain/arbitrum/LibArbitrumL2.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.2) (crosschain/arbitrum/LibArbitrumL2.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (crosschain/arbitrum/LibArbitrumL2.sol)
 
 pragma solidity ^0.8.4;
 

+ 12 - 3
contracts/finance/PaymentSplitter.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (finance/PaymentSplitter.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (finance/PaymentSplitter.sol)
 
 pragma solidity ^0.8.0;
 
@@ -149,8 +149,12 @@ contract PaymentSplitter is Context {
 
         require(payment != 0, "PaymentSplitter: account is not due payment");
 
-        _released[account] += payment;
+        // _totalReleased is the sum of all values in _released.
+        // If "_totalReleased += payment" does not overflow, then "_released[account] += payment" cannot overflow.
         _totalReleased += payment;
+        unchecked {
+            _released[account] += payment;
+        }
 
         Address.sendValue(account, payment);
         emit PaymentReleased(account, payment);
@@ -168,8 +172,13 @@ contract PaymentSplitter is Context {
 
         require(payment != 0, "PaymentSplitter: account is not due payment");
 
-        _erc20Released[token][account] += payment;
+        // _erc20TotalReleased[token] is the sum of all values in _erc20Released[token].
+        // If "_erc20TotalReleased[token] += payment" does not overflow, then "_erc20Released[token][account] += payment"
+        // cannot overflow.
         _erc20TotalReleased[token] += payment;
+        unchecked {
+            _erc20Released[token][account] += payment;
+        }
 
         SafeERC20.safeTransfer(token, account, payment);
         emit ERC20PaymentReleased(token, account, payment);

+ 25 - 11
contracts/finance/VestingWallet.sol

@@ -1,11 +1,10 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (finance/VestingWallet.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (finance/VestingWallet.sol)
 pragma solidity ^0.8.0;
 
 import "../token/ERC20/utils/SafeERC20.sol";
 import "../utils/Address.sol";
 import "../utils/Context.sol";
-import "../utils/math/Math.sol";
 
 /**
  * @title VestingWallet
@@ -34,7 +33,7 @@ contract VestingWallet is Context {
         address beneficiaryAddress,
         uint64 startTimestamp,
         uint64 durationSeconds
-    ) {
+    ) payable {
         require(beneficiaryAddress != address(0), "VestingWallet: beneficiary is zero address");
         _beneficiary = beneficiaryAddress;
         _start = startTimestamp;
@@ -81,16 +80,31 @@ contract VestingWallet is Context {
         return _erc20Released[token];
     }
 
+    /**
+     * @dev Getter for the amount of releasable eth.
+     */
+    function releasable() public view virtual returns (uint256) {
+        return vestedAmount(uint64(block.timestamp)) - released();
+    }
+
+    /**
+     * @dev Getter for the amount of releasable `token` tokens. `token` should be the address of an
+     * IERC20 contract.
+     */
+    function releasable(address token) public view virtual returns (uint256) {
+        return vestedAmount(token, uint64(block.timestamp)) - released(token);
+    }
+
     /**
      * @dev Release the native token (ether) that have already vested.
      *
      * Emits a {EtherReleased} event.
      */
     function release() public virtual {
-        uint256 releasable = vestedAmount(uint64(block.timestamp)) - released();
-        _released += releasable;
-        emit EtherReleased(releasable);
-        Address.sendValue(payable(beneficiary()), releasable);
+        uint256 amount = releasable();
+        _released += amount;
+        emit EtherReleased(amount);
+        Address.sendValue(payable(beneficiary()), amount);
     }
 
     /**
@@ -99,10 +113,10 @@ contract VestingWallet is Context {
      * Emits a {ERC20Released} event.
      */
     function release(address token) public virtual {
-        uint256 releasable = vestedAmount(token, uint64(block.timestamp)) - released(token);
-        _erc20Released[token] += releasable;
-        emit ERC20Released(token, releasable);
-        SafeERC20.safeTransfer(IERC20(token), beneficiary(), releasable);
+        uint256 amount = releasable(token);
+        _erc20Released[token] += amount;
+        emit ERC20Released(token, amount);
+        SafeERC20.safeTransfer(IERC20(token), beneficiary(), amount);
     }
 
     /**

+ 5 - 4
contracts/governance/Governor.sol

@@ -1,12 +1,12 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.2) (governance/Governor.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (governance/Governor.sol)
 
 pragma solidity ^0.8.0;
 
 import "../token/ERC721/IERC721Receiver.sol";
 import "../token/ERC1155/IERC1155Receiver.sol";
 import "../utils/cryptography/ECDSA.sol";
-import "../utils/cryptography/draft-EIP712.sol";
+import "../utils/cryptography/EIP712.sol";
 import "../utils/introspection/ERC165.sol";
 import "../utils/math/SafeCast.sol";
 import "../utils/structs/DoubleEndedQueue.sol";
@@ -544,8 +544,9 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receive
         address target,
         uint256 value,
         bytes calldata data
-    ) external virtual onlyGovernance {
-        Address.functionCallWithValue(target, data, value);
+    ) external payable virtual onlyGovernance {
+        (bool success, bytes memory returndata) = target.call{value: value}(data);
+        Address.verifyCallResult(success, returndata, "Governor: relay reverted without message");
     }
 
     /**

+ 2 - 2
contracts/governance/IGovernor.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.2) (governance/IGovernor.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)
 
 pragma solidity ^0.8.0;
 
@@ -184,7 +184,7 @@ abstract contract IGovernor is IERC165 {
 
     /**
      * @notice module:voting
-     * @dev Returns weither `account` has cast a vote on `proposalId`.
+     * @dev Returns whether `account` has cast a vote on `proposalId`.
      */
     function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);
 

+ 2 - 2
contracts/governance/README.adoc

@@ -118,7 +118,7 @@ Both operations contain:
 
 * *Target*, the address of the smart contract that the timelock should operate on.
 * *Value*, in wei, that should be sent with the transaction. Most of the time this will be 0. Ether can be deposited before-end or passed along when executing the transaction.
-* *Data*, containing the encoded function selector and parameters of the call. This can be produced using a number of tools. For example, a maintenance operation granting role `ROLE` to `ACCOUNT` can be encode using web3js as follows:
+* *Data*, containing the encoded function selector and parameters of the call. This can be produced using a number of tools. For example, a maintenance operation granting role `ROLE` to `ACCOUNT` can be encoded using web3js as follows:
 
 ```javascript
 const data = timelock.contract.methods.grantRole(ROLE, ACCOUNT).encodeABI()
@@ -153,7 +153,7 @@ Operations status can be queried using the functions:
 [[timelock-admin]]
 ===== Admin
 
-The admins are in charge of managing proposers and executors. For the timelock to be self-governed, this role should only be given to the timelock itself. Upon deployment, both the timelock and the deployer have this role. After further configuration and testing, the deployer can renounce this role such that all further maintenance operations have to go through the timelock process.
+The admins are in charge of managing proposers and executors. For the timelock to be self-governed, this role should only be given to the timelock itself. Upon deployment, the admin role can be granted to any address (in addition to the timelock itself). After further configuration and testing, this optional admin should renounce its role such that all further maintenance operations have to go through the timelock process.
 
 This role is identified by the *TIMELOCK_ADMIN_ROLE* value: `0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5`
 

+ 19 - 13
contracts/governance/TimelockController.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (governance/TimelockController.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (governance/TimelockController.sol)
 
 pragma solidity ^0.8.0;
 
@@ -62,31 +62,37 @@ contract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver
     event MinDelayChange(uint256 oldDuration, uint256 newDuration);
 
     /**
-     * @dev Initializes the contract with a given `minDelay`, and a list of
-     * initial proposers and executors. The proposers receive both the
-     * proposer and the canceller role (for backward compatibility). The
-     * executors receive the executor role.
+     * @dev Initializes the contract with the following parameters:
      *
-     * NOTE: At construction, both the deployer and the timelock itself are
-     * administrators. This helps further configuration of the timelock by the
-     * deployer. After configuration is done, it is recommended that the
-     * deployer renounces its admin position and relies on timelocked
-     * operations to perform future maintenance.
+     * - `minDelay`: initial minimum delay for operations
+     * - `proposers`: accounts to be granted proposer and canceller roles
+     * - `executors`: accounts to be granted executor role
+     * - `admin`: optional account to be granted admin role; disable with zero address
+     *
+     * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment
+     * without being subject to delay, but this role should be subsequently renounced in favor of
+     * administration through timelocked proposals. Previous versions of this contract would assign
+     * this admin to the deployer automatically and should be renounced as well.
      */
     constructor(
         uint256 minDelay,
         address[] memory proposers,
-        address[] memory executors
+        address[] memory executors,
+        address admin
     ) {
         _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);
         _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);
         _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);
         _setRoleAdmin(CANCELLER_ROLE, TIMELOCK_ADMIN_ROLE);
 
-        // deployer + self administration
-        _setupRole(TIMELOCK_ADMIN_ROLE, _msgSender());
+        // self administration
         _setupRole(TIMELOCK_ADMIN_ROLE, address(this));
 
+        // optional admin
+        if (admin != address(0)) {
+            _setupRole(TIMELOCK_ADMIN_ROLE, admin);
+        }
+
         // register proposers and cancellers
         for (uint256 i = 0; i < proposers.length; ++i) {
             _setupRole(PROPOSER_ROLE, proposers[i]);

+ 1 - 5
contracts/governance/compatibility/GovernorCompatibilityBravo.sol

@@ -1,9 +1,8 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.6.0) (governance/compatibility/GovernorCompatibilityBravo.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (governance/compatibility/GovernorCompatibilityBravo.sol)
 
 pragma solidity ^0.8.0;
 
-import "../../utils/Counters.sol";
 import "../../utils/math/SafeCast.sol";
 import "../extensions/IGovernorTimelock.sol";
 import "../Governor.sol";
@@ -20,9 +19,6 @@ import "./IGovernorCompatibilityBravo.sol";
  * _Available since v4.3._
  */
 abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorCompatibilityBravo, Governor {
-    using Counters for Counters.Counter;
-    using Timers for Timers.BlockNumber;
-
     enum VoteType {
         Against,
         For,

+ 13 - 13
contracts/governance/extensions/GovernorCountingSimple.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (governance/extensions/GovernorCountingSimple.sol)
 
 pragma solidity ^0.8.0;
 
@@ -57,26 +57,26 @@ abstract contract GovernorCountingSimple is Governor {
             uint256 abstainVotes
         )
     {
-        ProposalVote storage proposalvote = _proposalVotes[proposalId];
-        return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);
+        ProposalVote storage proposalVote = _proposalVotes[proposalId];
+        return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes);
     }
 
     /**
      * @dev See {Governor-_quorumReached}.
      */
     function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
-        ProposalVote storage proposalvote = _proposalVotes[proposalId];
+        ProposalVote storage proposalVote = _proposalVotes[proposalId];
 
-        return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;
+        return quorum(proposalSnapshot(proposalId)) <= proposalVote.forVotes + proposalVote.abstainVotes;
     }
 
     /**
      * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
      */
     function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
-        ProposalVote storage proposalvote = _proposalVotes[proposalId];
+        ProposalVote storage proposalVote = _proposalVotes[proposalId];
 
-        return proposalvote.forVotes > proposalvote.againstVotes;
+        return proposalVote.forVotes > proposalVote.againstVotes;
     }
 
     /**
@@ -89,17 +89,17 @@ abstract contract GovernorCountingSimple is Governor {
         uint256 weight,
         bytes memory // params
     ) internal virtual override {
-        ProposalVote storage proposalvote = _proposalVotes[proposalId];
+        ProposalVote storage proposalVote = _proposalVotes[proposalId];
 
-        require(!proposalvote.hasVoted[account], "GovernorVotingSimple: vote already cast");
-        proposalvote.hasVoted[account] = true;
+        require(!proposalVote.hasVoted[account], "GovernorVotingSimple: vote already cast");
+        proposalVote.hasVoted[account] = true;
 
         if (support == uint8(VoteType.Against)) {
-            proposalvote.againstVotes += weight;
+            proposalVote.againstVotes += weight;
         } else if (support == uint8(VoteType.For)) {
-            proposalvote.forVotes += weight;
+            proposalVote.forVotes += weight;
         } else if (support == uint8(VoteType.Abstain)) {
-            proposalvote.abstainVotes += weight;
+            proposalVote.abstainVotes += weight;
         } else {
             revert("GovernorVotingSimple: invalid value for enum VoteType");
         }

+ 2 - 2
contracts/governance/extensions/GovernorVotesQuorumFraction.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.2) (governance/extensions/GovernorVotesQuorumFraction.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (governance/extensions/GovernorVotesQuorumFraction.sol)
 
 pragma solidity ^0.8.0;
 
@@ -55,7 +55,7 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes {
             return latest._value;
         }
 
-        // Otherwize, do the binary search
+        // Otherwise, do the binary search
         return _quorumNumeratorHistory.getAtBlock(blockNumber);
     }
 

+ 5 - 5
contracts/governance/utils/Votes.sol

@@ -1,11 +1,11 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.6.0) (governance/utils/Votes.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (governance/utils/Votes.sol)
 pragma solidity ^0.8.0;
 
 import "../../utils/Context.sol";
 import "../../utils/Counters.sol";
 import "../../utils/Checkpoints.sol";
-import "../../utils/cryptography/draft-EIP712.sol";
+import "../../utils/cryptography/EIP712.sol";
 import "./IVotes.sol";
 
 /**
@@ -56,7 +56,7 @@ abstract contract Votes is IVotes, Context, EIP712 {
      * - `blockNumber` must have been already mined
      */
     function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
-        return _delegateCheckpoints[account].getAtBlock(blockNumber);
+        return _delegateCheckpoints[account].getAtProbablyRecentBlock(blockNumber);
     }
 
     /**
@@ -72,7 +72,7 @@ abstract contract Votes is IVotes, Context, EIP712 {
      */
     function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {
         require(blockNumber < block.number, "Votes: block not yet mined");
-        return _totalCheckpoints.getAtBlock(blockNumber);
+        return _totalCheckpoints.getAtProbablyRecentBlock(blockNumber);
     }
 
     /**
@@ -122,7 +122,7 @@ abstract contract Votes is IVotes, Context, EIP712 {
     /**
      * @dev Delegate all of `account`'s voting units to `delegatee`.
      *
-     * Emits events {DelegateChanged} and {DelegateVotesChanged}.
+     * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.
      */
     function _delegate(address account, address delegatee) internal virtual {
         address oldDelegate = delegates(account);

+ 21 - 0
contracts/interfaces/IERC2309.sol

@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.8.0) (interfaces/IERC2309.sol)
+
+pragma solidity ^0.8.0;
+
+/**
+ * @dev ERC-2309: ERC-721 Consecutive Transfer Extension.
+ *
+ * _Available since v4.8._
+ */
+interface IERC2309 {
+    /**
+     * @dev Emitted when the tokens from `fromTokenId` to `toTokenId` are transferred from `fromAddress` to `toAddress`.
+     */
+    event ConsecutiveTransfer(
+        uint256 indexed fromTokenId,
+        uint256 toTokenId,
+        address indexed fromAddress,
+        address indexed toAddress
+    );
+}

+ 3 - 3
contracts/interfaces/IERC4626.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (interfaces/IERC4626.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (interfaces/IERC4626.sol)
 
 pragma solidity ^0.8.0;
 
@@ -13,10 +13,10 @@ import "../token/ERC20/extensions/IERC20Metadata.sol";
  * _Available since v4.7._
  */
 interface IERC4626 is IERC20, IERC20Metadata {
-    event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);
+    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
 
     event Withdraw(
-        address indexed caller,
+        address indexed sender,
         address indexed receiver,
         address indexed owner,
         uint256 assets,

+ 6 - 0
contracts/interfaces/README.adoc

@@ -24,10 +24,12 @@ are useful to interact with third party contracts that implement them.
 - {IERC1363}
 - {IERC1820Implementer}
 - {IERC1820Registry}
+- {IERC1822Proxiable}
 - {IERC2612}
 - {IERC2981}
 - {IERC3156FlashLender}
 - {IERC3156FlashBorrower}
+- {IERC4626}
 
 == Detailed ABI
 
@@ -41,6 +43,8 @@ are useful to interact with third party contracts that implement them.
 
 {{IERC1820Registry}}
 
+{{IERC1822Proxiable}}
+
 {{IERC2612}}
 
 {{IERC2981}}
@@ -48,3 +52,5 @@ are useful to interact with third party contracts that implement them.
 {{IERC3156FlashLender}}
 
 {{IERC3156FlashBorrower}}
+
+{{IERC4626}}

+ 3 - 3
contracts/metatx/MinimalForwarder.sol

@@ -1,10 +1,10 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (metatx/MinimalForwarder.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (metatx/MinimalForwarder.sol)
 
 pragma solidity ^0.8.0;
 
 import "../utils/cryptography/ECDSA.sol";
-import "../utils/cryptography/draft-EIP712.sol";
+import "../utils/cryptography/EIP712.sol";
 
 /**
  * @dev Simple minimal forwarder to be used together with an ERC2771 compatible contract. See {ERC2771Context}.
@@ -57,7 +57,7 @@ contract MinimalForwarder is EIP712 {
         );
 
         // Validate that the relayer has sent enough gas for the call.
-        // See https://ronan.eth.link/blog/ethereum-gas-dangers/
+        // See https://ronan.eth.limo/blog/ethereum-gas-dangers/
         if (gasleft() <= req.gas / 63) {
             // We explicitly trigger invalid opcode to consume all gas and bubble-up the effects, since
             // neither revert or assert consume all gas since Solidity 0.8.0

+ 1 - 1
contracts/mocks/AccessControlCrossChainMock.sol

@@ -16,7 +16,7 @@ contract AccessControlCrossChainMock is AccessControlCrossChain, CrossChainEnabl
 
     function senderProtected(bytes32 roleId) public onlyRole(roleId) {}
 
-    function crossChainRoleAlias(bytes32 role) public pure virtual returns (bytes32) {
+    function crossChainRoleAlias(bytes32 role) public pure returns (bytes32) {
         return _crossChainRoleAlias(role);
     }
 }

+ 0 - 19
contracts/mocks/ArraysImpl.sol

@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: MIT
-
-pragma solidity ^0.8.0;
-
-import "../utils/Arrays.sol";
-
-contract ArraysImpl {
-    using Arrays for uint256[];
-
-    uint256[] private _array;
-
-    constructor(uint256[] memory array) {
-        _array = array;
-    }
-
-    function findUpperBound(uint256 element) external view returns (uint256) {
-        return _array.findUpperBound(element);
-    }
-}

+ 51 - 0
contracts/mocks/ArraysMock.sol

@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../utils/Arrays.sol";
+
+contract Uint256ArraysMock {
+    using Arrays for uint256[];
+
+    uint256[] private _array;
+
+    constructor(uint256[] memory array) {
+        _array = array;
+    }
+
+    function findUpperBound(uint256 element) external view returns (uint256) {
+        return _array.findUpperBound(element);
+    }
+
+    function unsafeAccess(uint256 pos) external view returns (uint256) {
+        return _array.unsafeAccess(pos).value;
+    }
+}
+
+contract AddressArraysMock {
+    using Arrays for address[];
+
+    address[] private _array;
+
+    constructor(address[] memory array) {
+        _array = array;
+    }
+
+    function unsafeAccess(uint256 pos) external view returns (address) {
+        return _array.unsafeAccess(pos).value;
+    }
+}
+
+contract Bytes32ArraysMock {
+    using Arrays for bytes32[];
+
+    bytes32[] private _array;
+
+    constructor(bytes32[] memory array) {
+        _array = array;
+    }
+
+    function unsafeAccess(uint256 pos) external view returns (bytes32) {
+        return _array.unsafeAccess(pos).value;
+    }
+}

+ 0 - 27
contracts/mocks/CheckpointsImpl.sol

@@ -1,27 +0,0 @@
-// SPDX-License-Identifier: MIT
-
-pragma solidity ^0.8.0;
-
-import "../utils/Checkpoints.sol";
-
-contract CheckpointsImpl {
-    using Checkpoints for Checkpoints.History;
-
-    Checkpoints.History private _totalCheckpoints;
-
-    function latest() public view returns (uint256) {
-        return _totalCheckpoints.latest();
-    }
-
-    function getAtBlock(uint256 blockNumber) public view returns (uint256) {
-        return _totalCheckpoints.getAtBlock(blockNumber);
-    }
-
-    function push(uint256 value) public returns (uint256, uint256) {
-        return _totalCheckpoints.push(value);
-    }
-
-    function length() public view returns (uint256) {
-        return _totalCheckpoints._checkpoints.length;
-    }
-}

+ 120 - 0
contracts/mocks/CheckpointsMock.sol

@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: MIT
+// This file was procedurally generated from scripts/generate/templates/CheckpointsMock.js.
+
+pragma solidity ^0.8.0;
+
+import "../utils/Checkpoints.sol";
+
+contract CheckpointsMock {
+    using Checkpoints for Checkpoints.History;
+
+    Checkpoints.History private _totalCheckpoints;
+
+    function latest() public view returns (uint256) {
+        return _totalCheckpoints.latest();
+    }
+
+    function latestCheckpoint()
+        public
+        view
+        returns (
+            bool,
+            uint256,
+            uint256
+        )
+    {
+        return _totalCheckpoints.latestCheckpoint();
+    }
+
+    function length() public view returns (uint256) {
+        return _totalCheckpoints.length();
+    }
+
+    function push(uint256 value) public returns (uint256, uint256) {
+        return _totalCheckpoints.push(value);
+    }
+
+    function getAtBlock(uint256 blockNumber) public view returns (uint256) {
+        return _totalCheckpoints.getAtBlock(blockNumber);
+    }
+
+    function getAtProbablyRecentBlock(uint256 blockNumber) public view returns (uint256) {
+        return _totalCheckpoints.getAtProbablyRecentBlock(blockNumber);
+    }
+}
+
+contract Checkpoints224Mock {
+    using Checkpoints for Checkpoints.Trace224;
+
+    Checkpoints.Trace224 private _totalCheckpoints;
+
+    function latest() public view returns (uint224) {
+        return _totalCheckpoints.latest();
+    }
+
+    function latestCheckpoint()
+        public
+        view
+        returns (
+            bool,
+            uint32,
+            uint224
+        )
+    {
+        return _totalCheckpoints.latestCheckpoint();
+    }
+
+    function length() public view returns (uint256) {
+        return _totalCheckpoints.length();
+    }
+
+    function push(uint32 key, uint224 value) public returns (uint224, uint224) {
+        return _totalCheckpoints.push(key, value);
+    }
+
+    function lowerLookup(uint32 key) public view returns (uint224) {
+        return _totalCheckpoints.lowerLookup(key);
+    }
+
+    function upperLookup(uint32 key) public view returns (uint224) {
+        return _totalCheckpoints.upperLookup(key);
+    }
+}
+
+contract Checkpoints160Mock {
+    using Checkpoints for Checkpoints.Trace160;
+
+    Checkpoints.Trace160 private _totalCheckpoints;
+
+    function latest() public view returns (uint160) {
+        return _totalCheckpoints.latest();
+    }
+
+    function latestCheckpoint()
+        public
+        view
+        returns (
+            bool,
+            uint96,
+            uint160
+        )
+    {
+        return _totalCheckpoints.latestCheckpoint();
+    }
+
+    function length() public view returns (uint256) {
+        return _totalCheckpoints.length();
+    }
+
+    function push(uint96 key, uint160 value) public returns (uint160, uint160) {
+        return _totalCheckpoints.push(key, value);
+    }
+
+    function lowerLookup(uint96 key) public view returns (uint160) {
+        return _totalCheckpoints.lowerLookup(key);
+    }
+
+    function upperLookup(uint96 key) public view returns (uint160) {
+        return _totalCheckpoints.upperLookup(key);
+    }
+}

+ 1 - 1
contracts/mocks/EIP712External.sol

@@ -2,8 +2,8 @@
 
 pragma solidity ^0.8.0;
 
-import "../utils/cryptography/draft-EIP712.sol";
 import "../utils/cryptography/ECDSA.sol";
+import "../utils/cryptography/EIP712.sol";
 
 contract EIP712External is EIP712 {
     constructor(string memory name, string memory version) EIP712(name, version) {}

+ 1 - 1
contracts/mocks/ERC1155PausableMock.sol

@@ -23,7 +23,7 @@ contract ERC1155PausableMock is ERC1155Mock, ERC1155Pausable {
         uint256[] memory ids,
         uint256[] memory amounts,
         bytes memory data
-    ) internal virtual override(ERC1155, ERC1155Pausable) {
+    ) internal override(ERC1155, ERC1155Pausable) {
         super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
     }
 }

+ 1 - 1
contracts/mocks/ERC1155SupplyMock.sol

@@ -15,7 +15,7 @@ contract ERC1155SupplyMock is ERC1155Mock, ERC1155Supply {
         uint256[] memory ids,
         uint256[] memory amounts,
         bytes memory data
-    ) internal virtual override(ERC1155, ERC1155Supply) {
+    ) internal override(ERC1155, ERC1155Supply) {
         super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
     }
 }

+ 1 - 1
contracts/mocks/ERC1155URIStorageMock.sol

@@ -8,7 +8,7 @@ import "../token/ERC1155/extensions/ERC1155URIStorage.sol";
 contract ERC1155URIStorageMock is ERC1155Mock, ERC1155URIStorage {
     constructor(string memory _uri) ERC1155Mock(_uri) {}
 
-    function uri(uint256 tokenId) public view virtual override(ERC1155, ERC1155URIStorage) returns (string memory) {
+    function uri(uint256 tokenId) public view override(ERC1155, ERC1155URIStorage) returns (string memory) {
         return ERC1155URIStorage.uri(tokenId);
     }
 

+ 1 - 1
contracts/mocks/ERC165/ERC165MaliciousData.sol

@@ -3,7 +3,7 @@
 pragma solidity ^0.8.0;
 
 contract ERC165MaliciousData {
-    function supportsInterface(bytes4) public view returns (bool) {
+    function supportsInterface(bytes4) public pure returns (bool) {
         assembly {
             mstore(0, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
             return(0, 32)

+ 1 - 1
contracts/mocks/ERC165/ERC165ReturnBomb.sol

@@ -5,7 +5,7 @@ pragma solidity ^0.8.0;
 import "../../utils/introspection/IERC165.sol";
 
 contract ERC165ReturnBombMock is IERC165 {
-    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
+    function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
         if (interfaceId == type(IERC165).interfaceId) {
             assembly {
                 mstore(0, 1)

+ 4 - 0
contracts/mocks/ERC165CheckerMock.sol

@@ -22,4 +22,8 @@ contract ERC165CheckerMock {
     function getSupportedInterfaces(address account, bytes4[] memory interfaceIds) public view returns (bool[] memory) {
         return account.getSupportedInterfaces(interfaceIds);
     }
+
+    function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) public view returns (bool) {
+        return account.supportsERC165InterfaceUnchecked(interfaceId);
+    }
 }

+ 1 - 1
contracts/mocks/ERC20DecimalsMock.sol

@@ -15,7 +15,7 @@ contract ERC20DecimalsMock is ERC20 {
         _decimals = decimals_;
     }
 
-    function decimals() public view virtual override returns (uint8) {
+    function decimals() public view override returns (uint8) {
         return _decimals;
     }
 

+ 1 - 2
contracts/mocks/ERC20FlashMintMock.sol

@@ -25,8 +25,7 @@ contract ERC20FlashMintMock is ERC20FlashMint {
         _flashFeeAmount = amount;
     }
 
-    function flashFee(address token, uint256 amount) public view virtual override returns (uint256) {
-        super.flashFee(token, amount);
+    function _flashFee(address, uint256) internal view override returns (uint256) {
         return _flashFeeAmount;
     }
 

+ 2 - 2
contracts/mocks/ERC2771ContextMock.sol

@@ -12,11 +12,11 @@ contract ERC2771ContextMock is ContextMock, ERC2771Context {
         emit Sender(_msgSender()); // _msgSender() should be accessible during construction
     }
 
-    function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address) {
+    function _msgSender() internal view override(Context, ERC2771Context) returns (address) {
         return ERC2771Context._msgSender();
     }
 
-    function _msgData() internal view virtual override(Context, ERC2771Context) returns (bytes calldata) {
+    function _msgData() internal view override(Context, ERC2771Context) returns (bytes calldata) {
         return ERC2771Context._msgData();
     }
 }

+ 39 - 1
contracts/mocks/ERC4626Mock.sol

@@ -4,7 +4,6 @@ pragma solidity ^0.8.0;
 
 import "../token/ERC20/extensions/ERC4626.sol";
 
-// mock class using ERC20
 contract ERC4626Mock is ERC4626 {
     constructor(
         IERC20Metadata asset,
@@ -20,3 +19,42 @@ contract ERC4626Mock is ERC4626 {
         _burn(account, amount);
     }
 }
+
+contract ERC4626DecimalMock is ERC4626Mock {
+    using Math for uint256;
+
+    uint8 private immutable _decimals;
+
+    constructor(
+        IERC20Metadata asset,
+        string memory name,
+        string memory symbol,
+        uint8 decimalsOverride
+    ) ERC4626Mock(asset, name, symbol) {
+        _decimals = decimalsOverride;
+    }
+
+    function decimals() public view virtual override returns (uint8) {
+        return _decimals;
+    }
+
+    function _initialConvertToShares(uint256 assets, Math.Rounding rounding)
+        internal
+        view
+        virtual
+        override
+        returns (uint256 shares)
+    {
+        return assets.mulDiv(10**decimals(), 10**super.decimals(), rounding);
+    }
+
+    function _initialConvertToAssets(uint256 shares, Math.Rounding rounding)
+        internal
+        view
+        virtual
+        override
+        returns (uint256 assets)
+    {
+        return shares.mulDiv(10**super.decimals(), 10**decimals(), rounding);
+    }
+}

+ 55 - 0
contracts/mocks/ERC721ConsecutiveEnumerableMock.sol

@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../token/ERC721/extensions/ERC721Consecutive.sol";
+import "../token/ERC721/extensions/ERC721Enumerable.sol";
+
+contract ERC721ConsecutiveEnumerableMock is ERC721Consecutive, ERC721Enumerable {
+    constructor(
+        string memory name,
+        string memory symbol,
+        address[] memory receivers,
+        uint96[] memory amounts
+    ) ERC721(name, symbol) {
+        for (uint256 i = 0; i < receivers.length; ++i) {
+            _mintConsecutive(receivers[i], amounts[i]);
+        }
+    }
+
+    function supportsInterface(bytes4 interfaceId)
+        public
+        view
+        virtual
+        override(ERC721, ERC721Enumerable)
+        returns (bool)
+    {
+        return super.supportsInterface(interfaceId);
+    }
+
+    function _ownerOf(uint256 tokenId) internal view virtual override(ERC721, ERC721Consecutive) returns (address) {
+        return super._ownerOf(tokenId);
+    }
+
+    function _mint(address to, uint256 tokenId) internal virtual override(ERC721, ERC721Consecutive) {
+        super._mint(to, tokenId);
+    }
+
+    function _beforeTokenTransfer(
+        address from,
+        address to,
+        uint256 firstTokenId,
+        uint256 batchSize
+    ) internal virtual override(ERC721, ERC721Enumerable) {
+        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
+    }
+
+    function _afterTokenTransfer(
+        address from,
+        address to,
+        uint256 firstTokenId,
+        uint256 batchSize
+    ) internal virtual override(ERC721, ERC721Consecutive) {
+        super._afterTokenTransfer(from, to, firstTokenId, batchSize);
+    }
+}

+ 86 - 0
contracts/mocks/ERC721ConsecutiveMock.sol

@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../token/ERC721/extensions/ERC721Burnable.sol";
+import "../token/ERC721/extensions/ERC721Consecutive.sol";
+import "../token/ERC721/extensions/ERC721Enumerable.sol";
+import "../token/ERC721/extensions/ERC721Pausable.sol";
+import "../token/ERC721/extensions/ERC721Votes.sol";
+
+/**
+ * @title ERC721ConsecutiveMock
+ */
+contract ERC721ConsecutiveMock is ERC721Burnable, ERC721Consecutive, ERC721Pausable, ERC721Votes {
+    constructor(
+        string memory name,
+        string memory symbol,
+        address[] memory delegates,
+        address[] memory receivers,
+        uint96[] memory amounts
+    ) ERC721(name, symbol) EIP712(name, "1") {
+        for (uint256 i = 0; i < delegates.length; ++i) {
+            _delegate(delegates[i], delegates[i]);
+        }
+
+        for (uint256 i = 0; i < receivers.length; ++i) {
+            _mintConsecutive(receivers[i], amounts[i]);
+        }
+    }
+
+    function pause() external {
+        _pause();
+    }
+
+    function unpause() external {
+        _unpause();
+    }
+
+    function exists(uint256 tokenId) public view returns (bool) {
+        return _exists(tokenId);
+    }
+
+    function mint(address to, uint256 tokenId) public {
+        _mint(to, tokenId);
+    }
+
+    function mintConsecutive(address to, uint96 amount) public {
+        _mintConsecutive(to, amount);
+    }
+
+    function safeMint(address to, uint256 tokenId) public {
+        _safeMint(to, tokenId);
+    }
+
+    function _ownerOf(uint256 tokenId) internal view virtual override(ERC721, ERC721Consecutive) returns (address) {
+        return super._ownerOf(tokenId);
+    }
+
+    function _mint(address to, uint256 tokenId) internal virtual override(ERC721, ERC721Consecutive) {
+        super._mint(to, tokenId);
+    }
+
+    function _beforeTokenTransfer(
+        address from,
+        address to,
+        uint256 firstTokenId,
+        uint256 batchSize
+    ) internal virtual override(ERC721, ERC721Pausable) {
+        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
+    }
+
+    function _afterTokenTransfer(
+        address from,
+        address to,
+        uint256 firstTokenId,
+        uint256 batchSize
+    ) internal virtual override(ERC721, ERC721Votes, ERC721Consecutive) {
+        super._afterTokenTransfer(from, to, firstTokenId, batchSize);
+    }
+}
+
+contract ERC721ConsecutiveNoConstructorMintMock is ERC721Consecutive {
+    constructor(string memory name, string memory symbol) ERC721(name, symbol) {
+        _mint(msg.sender, 0);
+    }
+}

+ 1 - 1
contracts/mocks/ERC721EnumerableMock.sol

@@ -13,7 +13,7 @@ contract ERC721EnumerableMock is ERC721Enumerable {
 
     constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
 
-    function _baseURI() internal view virtual override returns (string memory) {
+    function _baseURI() internal view override returns (string memory) {
         return _baseTokenURI;
     }
 

+ 1 - 1
contracts/mocks/ERC721URIStorageMock.sol

@@ -13,7 +13,7 @@ contract ERC721URIStorageMock is ERC721URIStorage {
 
     constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
 
-    function _baseURI() internal view virtual override returns (string memory) {
+    function _baseURI() internal view override returns (string memory) {
         return _baseTokenURI;
     }
 

+ 1 - 1
contracts/mocks/ERC721VotesMock.sol

@@ -2,7 +2,7 @@
 
 pragma solidity ^0.8.0;
 
-import "../token/ERC721/extensions/draft-ERC721Votes.sol";
+import "../token/ERC721/extensions/ERC721Votes.sol";
 
 contract ERC721VotesMock is ERC721Votes {
     constructor(string memory name, string memory symbol) ERC721(name, symbol) EIP712(name, "1") {}

+ 2 - 0
contracts/mocks/EnumerableMapMock.sol

@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: MIT
+// This file was procedurally generated from scripts/generate/templates/EnumerableMapMock.js.
 
 pragma solidity ^0.8.0;
 
@@ -90,6 +91,7 @@ contract AddressToUintMapMock {
     }
 }
 
+// Bytes32ToBytes32Map
 contract Bytes32ToBytes32MapMock {
     using EnumerableMap for EnumerableMap.Bytes32ToBytes32Map;
 

+ 1 - 0
contracts/mocks/EnumerableSetMock.sol

@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: MIT
+// This file was procedurally generated from scripts/generate/templates/EnumerableSetMock.js.
 
 pragma solidity ^0.8.0;
 

+ 6 - 9
contracts/mocks/GovernorCompatibilityBravoMock.sol

@@ -30,7 +30,6 @@ contract GovernorCompatibilityBravoMock is
     function supportsInterface(bytes4 interfaceId)
         public
         view
-        virtual
         override(IERC165, Governor, GovernorTimelockCompound)
         returns (bool)
     {
@@ -44,7 +43,6 @@ contract GovernorCompatibilityBravoMock is
     function state(uint256 proposalId)
         public
         view
-        virtual
         override(IGovernor, Governor, GovernorTimelockCompound)
         returns (ProposalState)
     {
@@ -54,7 +52,6 @@ contract GovernorCompatibilityBravoMock is
     function proposalEta(uint256 proposalId)
         public
         view
-        virtual
         override(IGovernorTimelock, GovernorTimelockCompound)
         returns (uint256)
     {
@@ -70,7 +67,7 @@ contract GovernorCompatibilityBravoMock is
         uint256[] memory values,
         bytes[] memory calldatas,
         string memory description
-    ) public virtual override(IGovernor, Governor, GovernorCompatibilityBravo) returns (uint256) {
+    ) public override(IGovernor, Governor, GovernorCompatibilityBravo) returns (uint256) {
         return super.propose(targets, values, calldatas, description);
     }
 
@@ -79,7 +76,7 @@ contract GovernorCompatibilityBravoMock is
         uint256[] memory values,
         bytes[] memory calldatas,
         bytes32 salt
-    ) public virtual override(IGovernorTimelock, GovernorTimelockCompound) returns (uint256) {
+    ) public override(IGovernorTimelock, GovernorTimelockCompound) returns (uint256) {
         return super.queue(targets, values, calldatas, salt);
     }
 
@@ -88,7 +85,7 @@ contract GovernorCompatibilityBravoMock is
         uint256[] memory values,
         bytes[] memory calldatas,
         bytes32 salt
-    ) public payable virtual override(IGovernor, Governor) returns (uint256) {
+    ) public payable override(IGovernor, Governor) returns (uint256) {
         return super.execute(targets, values, calldatas, salt);
     }
 
@@ -98,7 +95,7 @@ contract GovernorCompatibilityBravoMock is
         uint256[] memory values,
         bytes[] memory calldatas,
         bytes32 descriptionHash
-    ) internal virtual override(Governor, GovernorTimelockCompound) {
+    ) internal override(Governor, GovernorTimelockCompound) {
         super._execute(proposalId, targets, values, calldatas, descriptionHash);
     }
 
@@ -120,11 +117,11 @@ contract GovernorCompatibilityBravoMock is
         uint256[] memory values,
         bytes[] memory calldatas,
         bytes32 salt
-    ) internal virtual override(Governor, GovernorTimelockCompound) returns (uint256 proposalId) {
+    ) internal override(Governor, GovernorTimelockCompound) returns (uint256 proposalId) {
         return super._cancel(targets, values, calldatas, salt);
     }
 
-    function _executor() internal view virtual override(Governor, GovernorTimelockCompound) returns (address) {
+    function _executor() internal view override(Governor, GovernorTimelockCompound) returns (address) {
         return super._executor();
     }
 }

+ 1 - 1
contracts/mocks/GovernorMock.sol

@@ -44,7 +44,7 @@ contract GovernorMock is
         uint256[] memory values,
         bytes[] memory calldatas,
         string memory description
-    ) public virtual override(Governor, GovernorProposalThreshold) returns (uint256) {
+    ) public override(Governor, GovernorProposalThreshold) returns (uint256) {
         return super.propose(targets, values, calldatas, description);
     }
 }

+ 3 - 4
contracts/mocks/GovernorPreventLateQuorumMock.sol

@@ -31,21 +31,20 @@ contract GovernorPreventLateQuorumMock is
         _quorum = quorum_;
     }
 
-    function quorum(uint256) public view virtual override returns (uint256) {
+    function quorum(uint256) public view override returns (uint256) {
         return _quorum;
     }
 
     function proposalDeadline(uint256 proposalId)
         public
         view
-        virtual
         override(Governor, GovernorPreventLateQuorum)
         returns (uint256)
     {
         return super.proposalDeadline(proposalId);
     }
 
-    function proposalThreshold() public view virtual override(Governor, GovernorSettings) returns (uint256) {
+    function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
         return super.proposalThreshold();
     }
 
@@ -55,7 +54,7 @@ contract GovernorPreventLateQuorumMock is
         uint8 support,
         string memory reason,
         bytes memory params
-    ) internal virtual override(Governor, GovernorPreventLateQuorum) returns (uint256) {
+    ) internal override(Governor, GovernorPreventLateQuorum) returns (uint256) {
         return super._castVote(proposalId, account, support, reason, params);
     }
 }

+ 3 - 5
contracts/mocks/GovernorTimelockCompoundMock.sol

@@ -31,7 +31,6 @@ contract GovernorTimelockCompoundMock is
     function supportsInterface(bytes4 interfaceId)
         public
         view
-        virtual
         override(Governor, GovernorTimelockCompound)
         returns (bool)
     {
@@ -62,7 +61,6 @@ contract GovernorTimelockCompoundMock is
     function state(uint256 proposalId)
         public
         view
-        virtual
         override(Governor, GovernorTimelockCompound)
         returns (ProposalState)
     {
@@ -79,7 +77,7 @@ contract GovernorTimelockCompoundMock is
         uint256[] memory values,
         bytes[] memory calldatas,
         bytes32 descriptionHash
-    ) internal virtual override(Governor, GovernorTimelockCompound) {
+    ) internal override(Governor, GovernorTimelockCompound) {
         super._execute(proposalId, targets, values, calldatas, descriptionHash);
     }
 
@@ -88,11 +86,11 @@ contract GovernorTimelockCompoundMock is
         uint256[] memory values,
         bytes[] memory calldatas,
         bytes32 salt
-    ) internal virtual override(Governor, GovernorTimelockCompound) returns (uint256 proposalId) {
+    ) internal override(Governor, GovernorTimelockCompound) returns (uint256 proposalId) {
         return super._cancel(targets, values, calldatas, salt);
     }
 
-    function _executor() internal view virtual override(Governor, GovernorTimelockCompound) returns (address) {
+    function _executor() internal view override(Governor, GovernorTimelockCompound) returns (address) {
         return super._executor();
     }
 }

+ 4 - 11
contracts/mocks/GovernorTimelockControlMock.sol

@@ -31,7 +31,6 @@ contract GovernorTimelockControlMock is
     function supportsInterface(bytes4 interfaceId)
         public
         view
-        virtual
         override(Governor, GovernorTimelockControl)
         returns (bool)
     {
@@ -59,13 +58,7 @@ contract GovernorTimelockControlMock is
     /**
      * Overriding nightmare
      */
-    function state(uint256 proposalId)
-        public
-        view
-        virtual
-        override(Governor, GovernorTimelockControl)
-        returns (ProposalState)
-    {
+    function state(uint256 proposalId) public view override(Governor, GovernorTimelockControl) returns (ProposalState) {
         return super.state(proposalId);
     }
 
@@ -79,7 +72,7 @@ contract GovernorTimelockControlMock is
         uint256[] memory values,
         bytes[] memory calldatas,
         bytes32 descriptionHash
-    ) internal virtual override(Governor, GovernorTimelockControl) {
+    ) internal override(Governor, GovernorTimelockControl) {
         super._execute(proposalId, targets, values, calldatas, descriptionHash);
     }
 
@@ -88,11 +81,11 @@ contract GovernorTimelockControlMock is
         uint256[] memory values,
         bytes[] memory calldatas,
         bytes32 descriptionHash
-    ) internal virtual override(Governor, GovernorTimelockControl) returns (uint256 proposalId) {
+    ) internal override(Governor, GovernorTimelockControl) returns (uint256 proposalId) {
         return super._cancel(targets, values, calldatas, descriptionHash);
     }
 
-    function _executor() internal view virtual override(Governor, GovernorTimelockControl) returns (address) {
+    function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) {
         return super._executor();
     }
 

+ 2 - 2
contracts/mocks/GovernorWithParamsMock.sol

@@ -26,7 +26,7 @@ contract GovernorWithParamsMock is GovernorVotes, GovernorCountingSimple {
         address account,
         uint256 blockNumber,
         bytes memory params
-    ) internal view virtual override(Governor, GovernorVotes) returns (uint256) {
+    ) internal view override(Governor, GovernorVotes) returns (uint256) {
         uint256 reduction = 0;
         // If the user provides parameters, we reduce the voting weight by the amount of the integer param
         if (params.length > 0) {
@@ -42,7 +42,7 @@ contract GovernorWithParamsMock is GovernorVotes, GovernorCountingSimple {
         uint8 support,
         uint256 weight,
         bytes memory params
-    ) internal virtual override(Governor, GovernorCountingSimple) {
+    ) internal override(Governor, GovernorCountingSimple) {
         if (params.length > 0) {
             (uint256 _uintParam, string memory _strParam) = abi.decode(params, (uint256, string));
             emit CountParams(_uintParam, _strParam);

+ 8 - 0
contracts/mocks/InitializableMock.sol

@@ -13,6 +13,10 @@ contract InitializableMock is Initializable {
     bool public onlyInitializingRan;
     uint256 public x;
 
+    function isInitializing() public view returns (bool) {
+        return _isInitializing();
+    }
+
     function initialize() public initializer {
         initializerRan = true;
     }
@@ -75,6 +79,10 @@ contract ChildConstructorInitializableMock is ConstructorInitializableMock {
 contract ReinitializerMock is Initializable {
     uint256 public counter;
 
+    function getInitializedVersion() public view returns (uint8) {
+        return _getInitializedVersion();
+    }
+
     function initialize() public initializer {
         doStuff();
     }

+ 12 - 0
contracts/mocks/MathMock.sol

@@ -33,4 +33,16 @@ contract MathMock {
     function sqrt(uint256 a, Math.Rounding direction) public pure returns (uint256) {
         return Math.sqrt(a, direction);
     }
+
+    function log2(uint256 a, Math.Rounding direction) public pure returns (uint256) {
+        return Math.log2(a, direction);
+    }
+
+    function log10(uint256 a, Math.Rounding direction) public pure returns (uint256) {
+        return Math.log10(a, direction);
+    }
+
+    function log256(uint256 a, Math.Rounding direction) public pure returns (uint256) {
+        return Math.log256(a, direction);
+    }
 }

+ 1 - 1
contracts/mocks/MulticallTest.sol

@@ -5,7 +5,7 @@ pragma solidity ^0.8.0;
 import "./MulticallTokenMock.sol";
 
 contract MulticallTest {
-    function testReturnValues(
+    function checkReturnValues(
         MulticallTokenMock multicallToken,
         address[] calldata recipients,
         uint256[] calldata amounts

+ 2 - 2
contracts/mocks/MultipleInheritanceInitializableMocks.sol

@@ -42,7 +42,7 @@ contract SampleHuman is Initializable {
 contract SampleMother is Initializable, SampleHuman {
     uint256 public mother;
 
-    function initialize(uint256 value) public virtual initializer {
+    function initialize(uint256 value) public initializer {
         __SampleMother_init(value);
     }
 
@@ -64,7 +64,7 @@ contract SampleMother is Initializable, SampleHuman {
 contract SampleGramps is Initializable, SampleHuman {
     string public gramps;
 
-    function initialize(string memory value) public virtual initializer {
+    function initialize(string memory value) public initializer {
         __SampleGramps_init(value);
     }
 

+ 7 - 0
contracts/mocks/Ownable2StepMock.sol

@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../access/Ownable2Step.sol";
+
+contract Ownable2StepMock is Ownable2Step {}

+ 1 - 0
contracts/mocks/SafeCastMock.sol

@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: MIT
+// This file was procedurally generated from scripts/generate/templates/SafeCastMock.js.
 
 pragma solidity ^0.8.0;
 

+ 2 - 2
contracts/mocks/SafeERC20Helper.sol

@@ -122,7 +122,7 @@ contract ERC20PermitNoRevertMock is
         uint8 v,
         bytes32 r,
         bytes32 s
-    ) public virtual {
+    ) public {
         super.permit(owner, spender, value, deadline, v, r, s);
     }
 
@@ -134,7 +134,7 @@ contract ERC20PermitNoRevertMock is
         uint8 v,
         bytes32 r,
         bytes32 s
-    ) public virtual override {
+    ) public override {
         try this.permitThatMayRevert(owner, spender, value, deadline, v, r, s) {
             // do nothing
         } catch {

+ 4 - 4
contracts/mocks/StringsMock.sol

@@ -5,19 +5,19 @@ pragma solidity ^0.8.0;
 import "../utils/Strings.sol";
 
 contract StringsMock {
-    function fromUint256(uint256 value) public pure returns (string memory) {
+    function toString(uint256 value) public pure returns (string memory) {
         return Strings.toString(value);
     }
 
-    function fromUint256Hex(uint256 value) public pure returns (string memory) {
+    function toHexString(uint256 value) public pure returns (string memory) {
         return Strings.toHexString(value);
     }
 
-    function fromUint256HexFixed(uint256 value, uint256 length) public pure returns (string memory) {
+    function toHexString(uint256 value, uint256 length) public pure returns (string memory) {
         return Strings.toHexString(value, length);
     }
 
-    function fromAddressHexFixed(address addr) public pure returns (string memory) {
+    function toHexString(address addr) public pure returns (string memory) {
         return Strings.toHexString(addr);
     }
 }

+ 2 - 2
contracts/mocks/UUPS/UUPSLegacy.sol

@@ -48,11 +48,11 @@ contract UUPSUpgradeableLegacyMock is UUPSUpgradeableMock {
     }
 
     // hooking into the old mechanism
-    function upgradeTo(address newImplementation) external virtual override {
+    function upgradeTo(address newImplementation) external override {
         _upgradeToAndCallSecureLegacyV1(newImplementation, bytes(""), false);
     }
 
-    function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual override {
+    function upgradeToAndCall(address newImplementation, bytes memory data) external payable override {
         _upgradeToAndCallSecureLegacyV1(newImplementation, data, false);
     }
 }

+ 3 - 3
contracts/mocks/UUPS/UUPSUpgradeableMock.sol

@@ -7,15 +7,15 @@ import "../../proxy/utils/UUPSUpgradeable.sol";
 
 contract UUPSUpgradeableMock is CountersImpl, UUPSUpgradeable {
     // Not having any checks in this function is dangerous! Do not do this outside tests!
-    function _authorizeUpgrade(address) internal virtual override {}
+    function _authorizeUpgrade(address) internal override {}
 }
 
 contract UUPSUpgradeableUnsafeMock is UUPSUpgradeableMock {
-    function upgradeTo(address newImplementation) external virtual override {
+    function upgradeTo(address newImplementation) external override {
         ERC1967Upgrade._upgradeToAndCall(newImplementation, bytes(""), false);
     }
 
-    function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual override {
+    function upgradeToAndCall(address newImplementation, bytes memory data) external payable override {
         ERC1967Upgrade._upgradeToAndCall(newImplementation, data, false);
     }
 }

+ 1 - 1
contracts/mocks/VotesMock.sol

@@ -18,7 +18,7 @@ contract VotesMock is Votes {
         return _delegate(account, newDelegation);
     }
 
-    function _getVotingUnits(address account) internal view virtual override returns (uint256) {
+    function _getVotingUnits(address account) internal view override returns (uint256) {
         return _balances[account];
     }
 

+ 1 - 1
contracts/mocks/crosschain/bridges.sol

@@ -22,7 +22,7 @@ abstract contract BaseRelayMock {
         _currentSender = sender;
 
         (bool success, bytes memory returndata) = target.call(data);
-        Address.verifyCallResult(success, returndata, "low-level call reverted");
+        Address.verifyCallResultFromTarget(target, success, returndata, "low-level call reverted");
 
         _currentSender = previousSender;
     }

+ 1 - 1
contracts/package.json

@@ -1,7 +1,7 @@
 {
   "name": "@openzeppelin/contracts",
   "description": "Secure Smart Contract library for Solidity",
-  "version": "4.7.3",
+  "version": "4.8.0",
   "files": [
     "**/*.sol",
     "/build/contracts/*.json",

+ 20 - 18
contracts/proxy/Clones.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (proxy/Clones.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (proxy/Clones.sol)
 
 pragma solidity ^0.8.0;
 
@@ -25,11 +25,12 @@ library Clones {
     function clone(address implementation) internal returns (address instance) {
         /// @solidity memory-safe-assembly
         assembly {
-            let ptr := mload(0x40)
-            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
-            mstore(add(ptr, 0x14), shl(0x60, implementation))
-            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
-            instance := create(0, ptr, 0x37)
+            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
+            // of the `implementation` address with the bytecode before the address.
+            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
+            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
+            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
+            instance := create(0, 0x09, 0x37)
         }
         require(instance != address(0), "ERC1167: create failed");
     }
@@ -44,11 +45,12 @@ library Clones {
     function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
         /// @solidity memory-safe-assembly
         assembly {
-            let ptr := mload(0x40)
-            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
-            mstore(add(ptr, 0x14), shl(0x60, implementation))
-            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
-            instance := create2(0, ptr, 0x37, salt)
+            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
+            // of the `implementation` address with the bytecode before the address.
+            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
+            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
+            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
+            instance := create2(0, 0x09, 0x37, salt)
         }
         require(instance != address(0), "ERC1167: create2 failed");
     }
@@ -64,13 +66,13 @@ library Clones {
         /// @solidity memory-safe-assembly
         assembly {
             let ptr := mload(0x40)
-            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
-            mstore(add(ptr, 0x14), shl(0x60, implementation))
-            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
-            mstore(add(ptr, 0x38), shl(0x60, deployer))
-            mstore(add(ptr, 0x4c), salt)
-            mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
-            predicted := keccak256(add(ptr, 0x37), 0x55)
+            mstore(add(ptr, 0x38), deployer)
+            mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
+            mstore(add(ptr, 0x14), implementation)
+            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
+            mstore(add(ptr, 0x58), salt)
+            mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
+            predicted := keccak256(add(ptr, 0x43), 0x55)
         }
     }
 

+ 1 - 1
contracts/proxy/README.adoc

@@ -26,7 +26,7 @@ A different family of proxies are beacon proxies. This pattern, popularized by D
 - {BeaconProxy}: A proxy that retrieves its implementation from a beacon contract.
 - {UpgradeableBeacon}: A beacon contract with a built in admin that can upgrade the {BeaconProxy} pointing to it.
 
-In this pattern, the proxy contract doesn't hold the implementation address in storage like an ERC1967 proxy, instead the address is stored in a separate beacon contract. The `upgrade` operations that are sent to the beacon instead of to the proxy contract, and all proxies that follow that beacon are automatically upgraded.
+In this pattern, the proxy contract doesn't hold the implementation address in storage like an ERC1967 proxy. Instead, the address is stored in a separate beacon contract. The `upgrade` operations are sent to the beacon instead of to the proxy contract, and all proxies that follow that beacon are automatically upgraded.
 
 Outside the realm of upgradeability, proxies can also be useful to make cheap contract clones, such as those created by an on-chain factory contract that creates many instances of the same contract. These instances are designed to be both cheap to deploy, and cheap to call.
 

+ 32 - 5
contracts/proxy/utils/Initializable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)
 
 pragma solidity ^0.8.2;
 
@@ -73,7 +73,12 @@ abstract contract Initializable {
 
     /**
      * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
-     * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
+     * `onlyInitializing` functions can be used to initialize parent contracts.
+     *
+     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
+     * constructor.
+     *
+     * Emits an {Initialized} event.
      */
     modifier initializer() {
         bool isTopLevelCall = !_initializing;
@@ -97,12 +102,18 @@ abstract contract Initializable {
      * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
      * used to initialize parent contracts.
      *
-     * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
-     * initialization step. This is essential to configure modules that are added through upgrades and that require
-     * initialization.
+     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
+     * are added through upgrades and that require initialization.
+     *
+     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
+     * cannot be nested. If one is invoked in the context of another, execution will revert.
      *
      * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
      * a contract, executing them in the right order is up to the developer or operator.
+     *
+     * WARNING: setting the version to 255 will prevent any future reinitialization.
+     *
+     * Emits an {Initialized} event.
      */
     modifier reinitializer(uint8 version) {
         require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
@@ -127,6 +138,8 @@ abstract contract Initializable {
      * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
      * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
      * through proxies.
+     *
+     * Emits an {Initialized} event the first time it is successfully executed.
      */
     function _disableInitializers() internal virtual {
         require(!_initializing, "Initializable: contract is initializing");
@@ -135,4 +148,18 @@ abstract contract Initializable {
             emit Initialized(type(uint8).max);
         }
     }
+
+    /**
+     * @dev Internal function that returns the initialized version. Returns `_initialized`
+     */
+    function _getInitializedVersion() internal view returns (uint8) {
+        return _initialized;
+    }
+
+    /**
+     * @dev Internal function that returns the initialized version. Returns `_initializing`
+     */
+    function _isInitializing() internal view returns (bool) {
+        return _initializing;
+    }
 }

+ 2 - 2
contracts/proxy/utils/UUPSUpgradeable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/UUPSUpgradeable.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)
 
 pragma solidity ^0.8.0;
 
@@ -46,7 +46,7 @@ abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {
 
     /**
      * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
-     * implementation. It is used to validate that the this implementation remains valid after an upgrade.
+     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.
      *
      * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
      * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this

+ 2 - 2
contracts/security/PullPayment.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (security/PullPayment.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (security/PullPayment.sol)
 
 pragma solidity ^0.8.0;
 
@@ -7,7 +7,7 @@ import "../utils/escrow/Escrow.sol";
 
 /**
  * @dev Simple implementation of a
- * https://consensys.github.io/smart-contract-best-practices/recommendations/#favor-pull-over-push-for-external-calls[pull-payment]
+ * https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/external-calls/#favor-pull-over-push-for-external-calls[pull-payment]
  * strategy, where the paying contract doesn't interact directly with the
  * receiver account, which must withdraw its payments itself.
  *

+ 10 - 4
contracts/security/ReentrancyGuard.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
 
 pragma solidity ^0.8.0;
 
@@ -48,14 +48,20 @@ abstract contract ReentrancyGuard {
      * `private` function that does the actual work.
      */
     modifier nonReentrant() {
-        // On the first call to nonReentrant, _notEntered will be true
+        _nonReentrantBefore();
+        _;
+        _nonReentrantAfter();
+    }
+
+    function _nonReentrantBefore() private {
+        // On the first call to nonReentrant, _status will be _NOT_ENTERED
         require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
 
         // Any calls to nonReentrant after this point will fail
         _status = _ENTERED;
+    }
 
-        _;
-
+    function _nonReentrantAfter() private {
         // By storing the original value once again, a refund is triggered (see
         // https://eips.ethereum.org/EIPS/eip-2200)
         _status = _NOT_ENTERED;

+ 5 - 5
contracts/token/ERC1155/ERC1155.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol)
 
 pragma solidity ^0.8.0;
 
@@ -123,7 +123,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
     ) public virtual override {
         require(
             from == _msgSender() || isApprovedForAll(from, _msgSender()),
-            "ERC1155: caller is not token owner nor approved"
+            "ERC1155: caller is not token owner or approved"
         );
         _safeTransferFrom(from, to, id, amount, data);
     }
@@ -140,7 +140,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
     ) public virtual override {
         require(
             from == _msgSender() || isApprovedForAll(from, _msgSender()),
-            "ERC1155: caller is not token owner nor approved"
+            "ERC1155: caller is not token owner or approved"
         );
         _safeBatchTransferFrom(from, to, ids, amounts, data);
     }
@@ -480,7 +480,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
             } catch Error(string memory reason) {
                 revert(reason);
             } catch {
-                revert("ERC1155: transfer to non ERC1155Receiver implementer");
+                revert("ERC1155: transfer to non-ERC1155Receiver implementer");
             }
         }
     }
@@ -503,7 +503,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
             } catch Error(string memory reason) {
                 revert(reason);
             } catch {
-                revert("ERC1155: transfer to non ERC1155Receiver implementer");
+                revert("ERC1155: transfer to non-ERC1155Receiver implementer");
             }
         }
     }

+ 3 - 3
contracts/token/ERC1155/extensions/ERC1155Burnable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/extensions/ERC1155Burnable.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/extensions/ERC1155Burnable.sol)
 
 pragma solidity ^0.8.0;
 
@@ -19,7 +19,7 @@ abstract contract ERC1155Burnable is ERC1155 {
     ) public virtual {
         require(
             account == _msgSender() || isApprovedForAll(account, _msgSender()),
-            "ERC1155: caller is not token owner nor approved"
+            "ERC1155: caller is not token owner or approved"
         );
 
         _burn(account, id, value);
@@ -32,7 +32,7 @@ abstract contract ERC1155Burnable is ERC1155 {
     ) public virtual {
         require(
             account == _msgSender() || isApprovedForAll(account, _msgSender()),
-            "ERC1155: caller is not token owner nor approved"
+            "ERC1155: caller is not token owner or approved"
         );
 
         _burnBatch(account, ids, values);

+ 11 - 5
contracts/token/ERC20/ERC20.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)
 
 pragma solidity ^0.8.0;
 
@@ -15,7 +15,7 @@ import "../../utils/Context.sol";
  * For a generic mechanism see {ERC20PresetMinterPauser}.
  *
  * TIP: For a detailed writeup see our guide
- * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
+ * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
  * to implement supply mechanisms].
  *
  * We have followed general OpenZeppelin Contracts guidelines: functions revert
@@ -237,8 +237,10 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
         require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
         unchecked {
             _balances[from] = fromBalance - amount;
+            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
+            // decrementing then incrementing.
+            _balances[to] += amount;
         }
-        _balances[to] += amount;
 
         emit Transfer(from, to, amount);
 
@@ -260,7 +262,10 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
         _beforeTokenTransfer(address(0), account, amount);
 
         _totalSupply += amount;
-        _balances[account] += amount;
+        unchecked {
+            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
+            _balances[account] += amount;
+        }
         emit Transfer(address(0), account, amount);
 
         _afterTokenTransfer(address(0), account, amount);
@@ -286,8 +291,9 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
         require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
         unchecked {
             _balances[account] = accountBalance - amount;
+            // Overflow not possible: amount <= accountBalance <= totalSupply.
+            _totalSupply -= amount;
         }
-        _totalSupply -= amount;
 
         emit Transfer(account, address(0), amount);
 

+ 17 - 4
contracts/token/ERC20/extensions/ERC20FlashMint.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/extensions/ERC20FlashMint.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/ERC20FlashMint.sol)
 
 pragma solidity ^0.8.0;
 
@@ -28,6 +28,19 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
         return token == address(this) ? type(uint256).max - ERC20.totalSupply() : 0;
     }
 
+    /**
+     * @dev Returns the fee applied when doing flash loans. This function calls
+     * the {_flashFee} function which returns the fee applied when doing flash
+     * loans.
+     * @param token The token to be flash loaned.
+     * @param amount The amount of tokens to be loaned.
+     * @return The fees applied to the corresponding flash loan.
+     */
+    function flashFee(address token, uint256 amount) public view virtual override returns (uint256) {
+        require(token == address(this), "ERC20FlashMint: wrong token");
+        return _flashFee(token, amount);
+    }
+
     /**
      * @dev Returns the fee applied when doing flash loans. By default this
      * implementation has 0 fees. This function can be overloaded to make
@@ -36,9 +49,9 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
      * @param amount The amount of tokens to be loaned.
      * @return The fees applied to the corresponding flash loan.
      */
-    function flashFee(address token, uint256 amount) public view virtual override returns (uint256) {
-        require(token == address(this), "ERC20FlashMint: wrong token");
+    function _flashFee(address token, uint256 amount) internal view virtual returns (uint256) {
         // silence warning about unused variable without the addition of bytecode.
+        token;
         amount;
         return 0;
     }
@@ -60,7 +73,7 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
      * amount + fee tokens and have them approved back to the token contract itself so
      * they can be burned.
      * @param receiver The receiver of the flash loan. Should implement the
-     * {IERC3156FlashBorrower.onFlashLoan} interface.
+     * {IERC3156FlashBorrower-onFlashLoan} interface.
      * @param token The token to be flash loaned. Only `address(this)` is
      * supported.
      * @param amount The amount of tokens to be loaned.

+ 32 - 9
contracts/token/ERC20/extensions/ERC20Votes.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/ERC20Votes.sol)
 
 pragma solidity ^0.8.0;
 
@@ -97,6 +97,7 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
     function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {
         // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.
         //
+        // Initially we check if the block is recent to narrow the search range.
         // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).
         // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.
         // - If the middle checkpoint is after `blockNumber`, we look in [low, mid)
@@ -106,18 +107,30 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
         // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is
         // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out
         // the same.
-        uint256 high = ckpts.length;
+        uint256 length = ckpts.length;
+
         uint256 low = 0;
+        uint256 high = length;
+
+        if (length > 5) {
+            uint256 mid = length - Math.sqrt(length);
+            if (_unsafeAccess(ckpts, mid).fromBlock > blockNumber) {
+                high = mid;
+            } else {
+                low = mid + 1;
+            }
+        }
+
         while (low < high) {
             uint256 mid = Math.average(low, high);
-            if (ckpts[mid].fromBlock > blockNumber) {
+            if (_unsafeAccess(ckpts, mid).fromBlock > blockNumber) {
                 high = mid;
             } else {
                 low = mid + 1;
             }
         }
 
-        return high == 0 ? 0 : ckpts[high - 1].votes;
+        return high == 0 ? 0 : _unsafeAccess(ckpts, high - 1).votes;
     }
 
     /**
@@ -178,7 +191,7 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
     /**
      * @dev Move voting power when tokens are transferred.
      *
-     * Emits a {DelegateVotesChanged} event.
+     * Emits a {IVotes-DelegateVotesChanged} event.
      */
     function _afterTokenTransfer(
         address from,
@@ -193,7 +206,7 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
     /**
      * @dev Change delegation for `delegator` to `delegatee`.
      *
-     * Emits events {DelegateChanged} and {DelegateVotesChanged}.
+     * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.
      */
     function _delegate(address delegator, address delegatee) internal virtual {
         address currentDelegate = delegates(delegator);
@@ -229,11 +242,14 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
         uint256 delta
     ) private returns (uint256 oldWeight, uint256 newWeight) {
         uint256 pos = ckpts.length;
-        oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes;
+
+        Checkpoint memory oldCkpt = pos == 0 ? Checkpoint(0, 0) : _unsafeAccess(ckpts, pos - 1);
+
+        oldWeight = oldCkpt.votes;
         newWeight = op(oldWeight, delta);
 
-        if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) {
-            ckpts[pos - 1].votes = SafeCast.toUint224(newWeight);
+        if (pos > 0 && oldCkpt.fromBlock == block.number) {
+            _unsafeAccess(ckpts, pos - 1).votes = SafeCast.toUint224(newWeight);
         } else {
             ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)}));
         }
@@ -246,4 +262,11 @@ abstract contract ERC20Votes is IVotes, ERC20Permit {
     function _subtract(uint256 a, uint256 b) private pure returns (uint256) {
         return a - b;
     }
+
+    function _unsafeAccess(Checkpoint[] storage ckpts, uint256 pos) private pure returns (Checkpoint storage result) {
+        assembly {
+            mstore(0, ckpts.slot)
+            result.slot := add(keccak256(0, 0x20), pos)
+        }
+    }
 }

+ 77 - 26
contracts/token/ERC20/extensions/ERC4626.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/extensions/ERC4626.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/ERC4626.sol)
 
 pragma solidity ^0.8.0;
 
@@ -26,76 +26,105 @@ import "../../../utils/math/Math.sol";
 abstract contract ERC4626 is ERC20, IERC4626 {
     using Math for uint256;
 
-    IERC20Metadata private immutable _asset;
+    IERC20 private immutable _asset;
+    uint8 private immutable _decimals;
 
     /**
      * @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC20 or ERC777).
      */
-    constructor(IERC20Metadata asset_) {
+    constructor(IERC20 asset_) {
+        (bool success, uint8 assetDecimals) = _tryGetAssetDecimals(asset_);
+        _decimals = success ? assetDecimals : super.decimals();
         _asset = asset_;
     }
 
-    /** @dev See {IERC4262-asset}. */
+    /**
+     * @dev Attempts to fetch the asset decimals. A return value of false indicates that the attempt failed in some way.
+     */
+    function _tryGetAssetDecimals(IERC20 asset_) private returns (bool, uint8) {
+        (bool success, bytes memory encodedDecimals) = address(asset_).call(
+            abi.encodeWithSelector(IERC20Metadata.decimals.selector)
+        );
+        if (success && encodedDecimals.length >= 32) {
+            uint256 returnedDecimals = abi.decode(encodedDecimals, (uint256));
+            if (returnedDecimals <= type(uint8).max) {
+                return (true, uint8(returnedDecimals));
+            }
+        }
+        return (false, 0);
+    }
+
+    /**
+     * @dev Decimals are read from the underlying asset in the constructor and cached. If this fails (e.g., the asset
+     * has not been created yet), the cached value is set to a default obtained by `super.decimals()` (which depends on
+     * inheritance but is most likely 18). Override this function in order to set a guaranteed hardcoded value.
+     * See {IERC20Metadata-decimals}.
+     */
+    function decimals() public view virtual override(IERC20Metadata, ERC20) returns (uint8) {
+        return _decimals;
+    }
+
+    /** @dev See {IERC4626-asset}. */
     function asset() public view virtual override returns (address) {
         return address(_asset);
     }
 
-    /** @dev See {IERC4262-totalAssets}. */
+    /** @dev See {IERC4626-totalAssets}. */
     function totalAssets() public view virtual override returns (uint256) {
         return _asset.balanceOf(address(this));
     }
 
-    /** @dev See {IERC4262-convertToShares}. */
+    /** @dev See {IERC4626-convertToShares}. */
     function convertToShares(uint256 assets) public view virtual override returns (uint256 shares) {
         return _convertToShares(assets, Math.Rounding.Down);
     }
 
-    /** @dev See {IERC4262-convertToAssets}. */
+    /** @dev See {IERC4626-convertToAssets}. */
     function convertToAssets(uint256 shares) public view virtual override returns (uint256 assets) {
         return _convertToAssets(shares, Math.Rounding.Down);
     }
 
-    /** @dev See {IERC4262-maxDeposit}. */
+    /** @dev See {IERC4626-maxDeposit}. */
     function maxDeposit(address) public view virtual override returns (uint256) {
         return _isVaultCollateralized() ? type(uint256).max : 0;
     }
 
-    /** @dev See {IERC4262-maxMint}. */
+    /** @dev See {IERC4626-maxMint}. */
     function maxMint(address) public view virtual override returns (uint256) {
         return type(uint256).max;
     }
 
-    /** @dev See {IERC4262-maxWithdraw}. */
+    /** @dev See {IERC4626-maxWithdraw}. */
     function maxWithdraw(address owner) public view virtual override returns (uint256) {
         return _convertToAssets(balanceOf(owner), Math.Rounding.Down);
     }
 
-    /** @dev See {IERC4262-maxRedeem}. */
+    /** @dev See {IERC4626-maxRedeem}. */
     function maxRedeem(address owner) public view virtual override returns (uint256) {
         return balanceOf(owner);
     }
 
-    /** @dev See {IERC4262-previewDeposit}. */
+    /** @dev See {IERC4626-previewDeposit}. */
     function previewDeposit(uint256 assets) public view virtual override returns (uint256) {
         return _convertToShares(assets, Math.Rounding.Down);
     }
 
-    /** @dev See {IERC4262-previewMint}. */
+    /** @dev See {IERC4626-previewMint}. */
     function previewMint(uint256 shares) public view virtual override returns (uint256) {
         return _convertToAssets(shares, Math.Rounding.Up);
     }
 
-    /** @dev See {IERC4262-previewWithdraw}. */
+    /** @dev See {IERC4626-previewWithdraw}. */
     function previewWithdraw(uint256 assets) public view virtual override returns (uint256) {
         return _convertToShares(assets, Math.Rounding.Up);
     }
 
-    /** @dev See {IERC4262-previewRedeem}. */
+    /** @dev See {IERC4626-previewRedeem}. */
     function previewRedeem(uint256 shares) public view virtual override returns (uint256) {
         return _convertToAssets(shares, Math.Rounding.Down);
     }
 
-    /** @dev See {IERC4262-deposit}. */
+    /** @dev See {IERC4626-deposit}. */
     function deposit(uint256 assets, address receiver) public virtual override returns (uint256) {
         require(assets <= maxDeposit(receiver), "ERC4626: deposit more than max");
 
@@ -105,7 +134,7 @@ abstract contract ERC4626 is ERC20, IERC4626 {
         return shares;
     }
 
-    /** @dev See {IERC4262-mint}. */
+    /** @dev See {IERC4626-mint}. */
     function mint(uint256 shares, address receiver) public virtual override returns (uint256) {
         require(shares <= maxMint(receiver), "ERC4626: mint more than max");
 
@@ -115,7 +144,7 @@ abstract contract ERC4626 is ERC20, IERC4626 {
         return assets;
     }
 
-    /** @dev See {IERC4262-withdraw}. */
+    /** @dev See {IERC4626-withdraw}. */
     function withdraw(
         uint256 assets,
         address receiver,
@@ -129,7 +158,7 @@ abstract contract ERC4626 is ERC20, IERC4626 {
         return shares;
     }
 
-    /** @dev See {IERC4262-redeem}. */
+    /** @dev See {IERC4626-redeem}. */
     function redeem(
         uint256 shares,
         address receiver,
@@ -147,25 +176,47 @@ abstract contract ERC4626 is ERC20, IERC4626 {
      * @dev Internal conversion function (from assets to shares) with support for rounding direction.
      *
      * Will revert if assets > 0, totalSupply > 0 and totalAssets = 0. That corresponds to a case where any asset
-     * would represent an infinite amout of shares.
+     * would represent an infinite amount of shares.
      */
     function _convertToShares(uint256 assets, Math.Rounding rounding) internal view virtual returns (uint256 shares) {
         uint256 supply = totalSupply();
         return
             (assets == 0 || supply == 0)
-                ? assets.mulDiv(10**decimals(), 10**_asset.decimals(), rounding)
+                ? _initialConvertToShares(assets, rounding)
                 : assets.mulDiv(supply, totalAssets(), rounding);
     }
 
+    /**
+     * @dev Internal conversion function (from assets to shares) to apply when the vault is empty.
+     *
+     * NOTE: Make sure to keep this function consistent with {_initialConvertToAssets} when overriding it.
+     */
+    function _initialConvertToShares(
+        uint256 assets,
+        Math.Rounding /*rounding*/
+    ) internal view virtual returns (uint256 shares) {
+        return assets;
+    }
+
     /**
      * @dev Internal conversion function (from shares to assets) with support for rounding direction.
      */
     function _convertToAssets(uint256 shares, Math.Rounding rounding) internal view virtual returns (uint256 assets) {
         uint256 supply = totalSupply();
         return
-            (supply == 0)
-                ? shares.mulDiv(10**_asset.decimals(), 10**decimals(), rounding)
-                : shares.mulDiv(totalAssets(), supply, rounding);
+            (supply == 0) ? _initialConvertToAssets(shares, rounding) : shares.mulDiv(totalAssets(), supply, rounding);
+    }
+
+    /**
+     * @dev Internal conversion function (from shares to assets) to apply when the vault is empty.
+     *
+     * NOTE: Make sure to keep this function consistent with {_initialConvertToShares} when overriding it.
+     */
+    function _initialConvertToAssets(
+        uint256 shares,
+        Math.Rounding /*rounding*/
+    ) internal view virtual returns (uint256 assets) {
+        return shares;
     }
 
     /**
@@ -182,7 +233,7 @@ abstract contract ERC4626 is ERC20, IERC4626 {
         // 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 transfered and before the shares are minted, which is a valid state.
+        // 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);
         _mint(receiver, shares);
@@ -209,7 +260,7 @@ abstract contract ERC4626 is ERC20, IERC4626 {
         // 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 transfered, which is a valid state.
+        // shares are burned and after the assets are transferred, which is a valid state.
         _burn(owner, shares);
         SafeERC20.safeTransfer(_asset, receiver, assets);
 

+ 2 - 2
contracts/token/ERC20/extensions/draft-ERC20Permit.sol

@@ -1,12 +1,12 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/draft-ERC20Permit.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol)
 
 pragma solidity ^0.8.0;
 
 import "./draft-IERC20Permit.sol";
 import "../ERC20.sol";
-import "../../../utils/cryptography/draft-EIP712.sol";
 import "../../../utils/cryptography/ECDSA.sol";
+import "../../../utils/cryptography/EIP712.sol";
 import "../../../utils/Counters.sol";
 
 /**

+ 2 - 2
contracts/token/ERC20/utils/SafeERC20.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
 
 pragma solidity ^0.8.0;
 
@@ -104,7 +104,7 @@ library SafeERC20 {
      */
     function _callOptionalReturn(IERC20 token, bytes memory data) private {
         // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
-        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
+        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
         // the target address contains contract code and also asserts for success in the low-level call.
 
         bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");

+ 80 - 31
contracts/token/ERC721/ERC721.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)
 
 pragma solidity ^0.8.0;
 
@@ -68,7 +68,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
      * @dev See {IERC721-ownerOf}.
      */
     function ownerOf(uint256 tokenId) public view virtual override returns (address) {
-        address owner = _owners[tokenId];
+        address owner = _ownerOf(tokenId);
         require(owner != address(0), "ERC721: invalid token ID");
         return owner;
     }
@@ -115,7 +115,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
 
         require(
             _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
-            "ERC721: approve caller is not token owner nor approved for all"
+            "ERC721: approve caller is not token owner or approved for all"
         );
 
         _approve(to, tokenId);
@@ -153,7 +153,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
         uint256 tokenId
     ) public virtual override {
         //solhint-disable-next-line max-line-length
-        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
+        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
 
         _transfer(from, to, tokenId);
     }
@@ -178,7 +178,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
         uint256 tokenId,
         bytes memory data
     ) public virtual override {
-        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
+        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
         _safeTransfer(from, to, tokenId, data);
     }
 
@@ -210,6 +210,13 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
         require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
     }
 
+    /**
+     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
+     */
+    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
+        return _owners[tokenId];
+    }
+
     /**
      * @dev Returns whether `tokenId` exists.
      *
@@ -219,7 +226,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
      * and stop existing when they are burned (`_burn`).
      */
     function _exists(uint256 tokenId) internal view virtual returns (bool) {
-        return _owners[tokenId] != address(0);
+        return _ownerOf(tokenId) != address(0);
     }
 
     /**
@@ -280,19 +287,30 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
         require(to != address(0), "ERC721: mint to the zero address");
         require(!_exists(tokenId), "ERC721: token already minted");
 
-        _beforeTokenTransfer(address(0), to, tokenId);
+        _beforeTokenTransfer(address(0), to, tokenId, 1);
+
+        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
+        require(!_exists(tokenId), "ERC721: token already minted");
+
+        unchecked {
+            // Will not overflow unless all 2**256 token ids are minted to the same owner.
+            // Given that tokens are minted one by one, it is impossible in practice that
+            // this ever happens. Might change if we allow batch minting.
+            // The ERC fails to describe this case.
+            _balances[to] += 1;
+        }
 
-        _balances[to] += 1;
         _owners[tokenId] = to;
 
         emit Transfer(address(0), to, tokenId);
 
-        _afterTokenTransfer(address(0), to, tokenId);
+        _afterTokenTransfer(address(0), to, tokenId, 1);
     }
 
     /**
      * @dev Destroys `tokenId`.
      * The approval is cleared when the token is burned.
+     * This is an internal function that does not check if the sender is authorized to operate on the token.
      *
      * Requirements:
      *
@@ -303,17 +321,24 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
     function _burn(uint256 tokenId) internal virtual {
         address owner = ERC721.ownerOf(tokenId);
 
-        _beforeTokenTransfer(owner, address(0), tokenId);
+        _beforeTokenTransfer(owner, address(0), tokenId, 1);
+
+        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
+        owner = ERC721.ownerOf(tokenId);
 
         // Clear approvals
-        _approve(address(0), tokenId);
+        delete _tokenApprovals[tokenId];
 
-        _balances[owner] -= 1;
+        unchecked {
+            // Cannot overflow, as that would require more tokens to be burned/transferred
+            // out than the owner initially received through minting and transferring in.
+            _balances[owner] -= 1;
+        }
         delete _owners[tokenId];
 
         emit Transfer(owner, address(0), tokenId);
 
-        _afterTokenTransfer(owner, address(0), tokenId);
+        _afterTokenTransfer(owner, address(0), tokenId, 1);
     }
 
     /**
@@ -335,18 +360,28 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
         require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
         require(to != address(0), "ERC721: transfer to the zero address");
 
-        _beforeTokenTransfer(from, to, tokenId);
+        _beforeTokenTransfer(from, to, tokenId, 1);
 
-        // Clear approvals from the previous owner
-        _approve(address(0), tokenId);
+        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
+        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
 
-        _balances[from] -= 1;
-        _balances[to] += 1;
+        // Clear approvals from the previous owner
+        delete _tokenApprovals[tokenId];
+
+        unchecked {
+            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
+            // `from`'s balance is the number of token held, which is at least one before the current
+            // transfer.
+            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
+            // all 2**256 token ids to be minted, which in practice is impossible.
+            _balances[from] -= 1;
+            _balances[to] += 1;
+        }
         _owners[tokenId] = to;
 
         emit Transfer(from, to, tokenId);
 
-        _afterTokenTransfer(from, to, tokenId);
+        _afterTokenTransfer(from, to, tokenId, 1);
     }
 
     /**
@@ -416,39 +451,53 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
     }
 
     /**
-     * @dev Hook that is called before any token transfer. This includes minting
-     * and burning.
+     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
+     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
      *
      * Calling conditions:
      *
-     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
-     * transferred to `to`.
-     * - When `from` is zero, `tokenId` will be minted for `to`.
-     * - When `to` is zero, ``from``'s `tokenId` will be burned.
+     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
+     * - When `from` is zero, the tokens will be minted for `to`.
+     * - When `to` is zero, ``from``'s tokens will be burned.
      * - `from` and `to` are never both zero.
+     * - `batchSize` is non-zero.
      *
      * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
      */
     function _beforeTokenTransfer(
         address from,
         address to,
-        uint256 tokenId
-    ) internal virtual {}
+        uint256, /* firstTokenId */
+        uint256 batchSize
+    ) internal virtual {
+        if (batchSize > 1) {
+            if (from != address(0)) {
+                _balances[from] -= batchSize;
+            }
+            if (to != address(0)) {
+                _balances[to] += batchSize;
+            }
+        }
+    }
 
     /**
-     * @dev Hook that is called after any transfer of tokens. This includes
-     * minting and burning.
+     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
+     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
      *
      * Calling conditions:
      *
-     * - when `from` and `to` are both non-zero.
+     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
+     * - When `from` is zero, the tokens were minted for `to`.
+     * - When `to` is zero, ``from``'s tokens were burned.
      * - `from` and `to` are never both zero.
+     * - `batchSize` is non-zero.
      *
      * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
      */
     function _afterTokenTransfer(
         address from,
         address to,
-        uint256 tokenId
+        uint256 firstTokenId,
+        uint256 batchSize
     ) internal virtual {}
 }

+ 1 - 1
contracts/token/ERC721/IERC721.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)
 
 pragma solidity ^0.8.0;
 

+ 3 - 0
contracts/token/ERC721/README.adoc

@@ -22,6 +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[ERC2309] for minting batchs of tokens during construction, in accordance with ERC721.
 * {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 ERC2981.
@@ -50,6 +51,8 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel
 
 {{ERC721Burnable}}
 
+{{ERC721Consecutive}}
+
 {{ERC721URIStorage}}
 
 {{ERC721Votes}}

+ 2 - 2
contracts/token/ERC721/extensions/ERC721Burnable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/extensions/ERC721Burnable.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Burnable.sol)
 
 pragma solidity ^0.8.0;
 
@@ -20,7 +20,7 @@ abstract contract ERC721Burnable is Context, ERC721 {
      */
     function burn(uint256 tokenId) public virtual {
         //solhint-disable-next-line max-line-length
-        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
+        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
         _burn(tokenId);
     }
 }

+ 143 - 0
contracts/token/ERC721/extensions/ERC721Consecutive.sol

@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Consecutive.sol)
+
+pragma solidity ^0.8.0;
+
+import "../ERC721.sol";
+import "../../../interfaces/IERC2309.sol";
+import "../../../utils/Checkpoints.sol";
+import "../../../utils/structs/BitMaps.sol";
+
+/**
+ * @dev Implementation of the ERC2309 "Consecutive Transfer Extension" as defined in
+ * https://eips.ethereum.org/EIPS/eip-2309[EIP-2309].
+ *
+ * This extension allows the minting of large batches of tokens, during contract construction only. For upgradeable
+ * contracts this implies that batch minting is only available during proxy deployment, and not in subsequent upgrades.
+ * These batches are limited to 5000 tokens at a time by default to accommodate off-chain indexers.
+ *
+ * Using this extension removes the ability to mint single tokens during contract construction. This ability is
+ * regained after construction. During construction, only batch minting is allowed.
+ *
+ * IMPORTANT: This extension bypasses the hooks {_beforeTokenTransfer} and {_afterTokenTransfer} for tokens minted in
+ * batch. When using this extension, you should consider the {_beforeConsecutiveTokenTransfer} and
+ * {_afterConsecutiveTokenTransfer} hooks in addition to {_beforeTokenTransfer} and {_afterTokenTransfer}.
+ *
+ * IMPORTANT: When overriding {_afterTokenTransfer}, be careful about call ordering. {ownerOf} may return invalid
+ * values during the {_afterTokenTransfer} execution if the super call is not called first. To be safe, execute the
+ * super call before your custom logic.
+ *
+ * _Available since v4.8._
+ */
+abstract contract ERC721Consecutive is IERC2309, ERC721 {
+    using BitMaps for BitMaps.BitMap;
+    using Checkpoints for Checkpoints.Trace160;
+
+    Checkpoints.Trace160 private _sequentialOwnership;
+    BitMaps.BitMap private _sequentialBurn;
+
+    /**
+     * @dev Maximum size of a batch of consecutive tokens. This is designed to limit stress on off-chain indexing
+     * services that have to record one entry per token, and have protections against "unreasonably large" batches of
+     * tokens.
+     *
+     * NOTE: Overriding the default value of 5000 will not cause on-chain issues, but may result in the asset not being
+     * correctly supported by off-chain indexing services (including marketplaces).
+     */
+    function _maxBatchSize() internal view virtual returns (uint96) {
+        return 5000;
+    }
+
+    /**
+     * @dev See {ERC721-_ownerOf}. Override that checks the sequential ownership structure for tokens that have
+     * been minted as part of a batch, and not yet transferred.
+     */
+    function _ownerOf(uint256 tokenId) internal view virtual override returns (address) {
+        address owner = super._ownerOf(tokenId);
+
+        // If token is owned by the core, or beyond consecutive range, return base value
+        if (owner != address(0) || tokenId > type(uint96).max) {
+            return owner;
+        }
+
+        // Otherwise, check the token was not burned, and fetch ownership from the anchors
+        // Note: no need for safe cast, we know that tokenId <= type(uint96).max
+        return _sequentialBurn.get(tokenId) ? address(0) : address(_sequentialOwnership.lowerLookup(uint96(tokenId)));
+    }
+
+    /**
+     * @dev Mint a batch of tokens of length `batchSize` for `to`. Returns the token id of the first token minted in the
+     * batch; if `batchSize` is 0, returns the number of consecutive ids minted so far.
+     *
+     * Requirements:
+     *
+     * - `batchSize` must not be greater than {_maxBatchSize}.
+     * - The function is called in the constructor of the contract (directly or indirectly).
+     *
+     * CAUTION: Does not emit a `Transfer` event. This is ERC721 compliant as long as it is done outside of the
+     * constructor, which is enforced by this function.
+     *
+     * CAUTION: Does not invoke `onERC721Received` on the receiver.
+     *
+     * Emits a {IERC2309-ConsecutiveTransfer} event.
+     */
+    function _mintConsecutive(address to, uint96 batchSize) internal virtual returns (uint96) {
+        uint96 first = _totalConsecutiveSupply();
+
+        // minting a batch of size 0 is a no-op
+        if (batchSize > 0) {
+            require(!Address.isContract(address(this)), "ERC721Consecutive: batch minting restricted to constructor");
+            require(to != address(0), "ERC721Consecutive: mint to the zero address");
+            require(batchSize <= _maxBatchSize(), "ERC721Consecutive: batch too large");
+
+            // hook before
+            _beforeTokenTransfer(address(0), to, first, batchSize);
+
+            // push an ownership checkpoint & emit event
+            uint96 last = first + batchSize - 1;
+            _sequentialOwnership.push(last, uint160(to));
+            emit ConsecutiveTransfer(first, last, address(0), to);
+
+            // hook after
+            _afterTokenTransfer(address(0), to, first, batchSize);
+        }
+
+        return first;
+    }
+
+    /**
+     * @dev See {ERC721-_mint}. Override version that restricts normal minting to after construction.
+     *
+     * Warning: Using {ERC721Consecutive} prevents using {_mint} during construction in favor of {_mintConsecutive}.
+     * After construction, {_mintConsecutive} is no longer available and {_mint} becomes available.
+     */
+    function _mint(address to, uint256 tokenId) internal virtual override {
+        require(Address.isContract(address(this)), "ERC721Consecutive: can't mint during construction");
+        super._mint(to, tokenId);
+    }
+
+    /**
+     * @dev See {ERC721-_afterTokenTransfer}. Burning of tokens that have been sequentially minted must be explicit.
+     */
+    function _afterTokenTransfer(
+        address from,
+        address to,
+        uint256 firstTokenId,
+        uint256 batchSize
+    ) internal virtual override {
+        if (
+            to == address(0) && // if we burn
+            firstTokenId < _totalConsecutiveSupply() && // and the tokenId was minted in a batch
+            !_sequentialBurn.get(firstTokenId) // and the token was never marked as burnt
+        ) {
+            require(batchSize == 1, "ERC721Consecutive: batch burn not supported");
+            _sequentialBurn.set(firstTokenId);
+        }
+        super._afterTokenTransfer(from, to, firstTokenId, batchSize);
+    }
+
+    function _totalConsecutiveSupply() private view returns (uint96) {
+        (bool exists, uint96 latestId, ) = _sequentialOwnership.latestCheckpoint();
+        return exists ? latestId + 1 : 0;
+    }
+}

+ 12 - 16
contracts/token/ERC721/extensions/ERC721Enumerable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol)
 
 pragma solidity ^0.8.0;
 
@@ -55,26 +55,22 @@ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
     }
 
     /**
-     * @dev Hook that is called before any token transfer. This includes minting
-     * and burning.
-     *
-     * Calling conditions:
-     *
-     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
-     * transferred to `to`.
-     * - When `from` is zero, `tokenId` will be minted for `to`.
-     * - When `to` is zero, ``from``'s `tokenId` will be burned.
-     * - `from` cannot be the zero address.
-     * - `to` cannot be the zero address.
-     *
-     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
+     * @dev See {ERC721-_beforeTokenTransfer}.
      */
     function _beforeTokenTransfer(
         address from,
         address to,
-        uint256 tokenId
+        uint256 firstTokenId,
+        uint256 batchSize
     ) internal virtual override {
-        super._beforeTokenTransfer(from, to, tokenId);
+        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
+
+        if (batchSize > 1) {
+            // Will only trigger during construction. Batch transferring (minting) is not available afterwards.
+            revert("ERC721Enumerable: consecutive transfers not supported");
+        }
+
+        uint256 tokenId = firstTokenId;
 
         if (from == address(0)) {
             _addTokenToAllTokensEnumeration(tokenId);

+ 4 - 3
contracts/token/ERC721/extensions/ERC721Pausable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Pausable.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Pausable.sol)
 
 pragma solidity ^0.8.0;
 
@@ -24,9 +24,10 @@ abstract contract ERC721Pausable is ERC721, Pausable {
     function _beforeTokenTransfer(
         address from,
         address to,
-        uint256 tokenId
+        uint256 firstTokenId,
+        uint256 batchSize
     ) internal virtual override {
-        super._beforeTokenTransfer(from, to, tokenId);
+        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
 
         require(!paused(), "ERC721Pausable: token transfer while paused");
     }

+ 3 - 3
contracts/token/ERC721/extensions/ERC721Royalty.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/ERC721Royalty.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Royalty.sol)
 
 pragma solidity ^0.8.0;
 
@@ -11,8 +11,8 @@ import "../../../utils/introspection/ERC165.sol";
  * @dev Extension of ERC721 with the ERC2981 NFT Royalty Standard, a standardized way to retrieve royalty payment
  * information.
  *
- * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
- * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
+ * Royalty information can be specified globally for all token ids via {ERC2981-_setDefaultRoyalty}, and/or individually for
+ * specific token ids via {ERC2981-_setTokenRoyalty}. The latter takes precedence over the first.
  *
  * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
  * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to

+ 41 - 0
contracts/token/ERC721/extensions/ERC721Votes.sol

@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Votes.sol)
+
+pragma solidity ^0.8.0;
+
+import "../ERC721.sol";
+import "../../../governance/utils/Votes.sol";
+
+/**
+ * @dev Extension of ERC721 to support voting and delegation as implemented by {Votes}, where each individual NFT counts
+ * as 1 vote unit.
+ *
+ * Tokens do not count as votes until they are delegated, because votes must be tracked which incurs an additional cost
+ * on every transfer. Token holders can either delegate to a trusted representative who will decide how to make use of
+ * the votes in governance decisions, or they can delegate to themselves to be their own representative.
+ *
+ * _Available since v4.5._
+ */
+abstract contract ERC721Votes is ERC721, Votes {
+    /**
+     * @dev See {ERC721-_afterTokenTransfer}. Adjusts votes when tokens are transferred.
+     *
+     * Emits a {IVotes-DelegateVotesChanged} event.
+     */
+    function _afterTokenTransfer(
+        address from,
+        address to,
+        uint256 firstTokenId,
+        uint256 batchSize
+    ) internal virtual override {
+        _transferVotingUnits(from, to, batchSize);
+        super._afterTokenTransfer(from, to, firstTokenId, batchSize);
+    }
+
+    /**
+     * @dev Returns the balance of `account`.
+     */
+    function _getVotingUnits(address account) internal view virtual override returns (uint256) {
+        return balanceOf(account);
+    }
+}

+ 4 - 35
contracts/token/ERC721/extensions/draft-ERC721Votes.sol

@@ -1,40 +1,9 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/extensions/draft-ERC721Votes.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/draft-ERC721Votes.sol)
 
 pragma solidity ^0.8.0;
 
-import "../ERC721.sol";
-import "../../../governance/utils/Votes.sol";
+// ERC721Votes was marked as draft due to the EIP-712 dependency.
+// EIP-712 is Final as of 2022-08-11. This file is deprecated.
 
-/**
- * @dev Extension of ERC721 to support voting and delegation as implemented by {Votes}, where each individual NFT counts
- * as 1 vote unit.
- *
- * Tokens do not count as votes until they are delegated, because votes must be tracked which incurs an additional cost
- * on every transfer. Token holders can either delegate to a trusted representative who will decide how to make use of
- * the votes in governance decisions, or they can delegate to themselves to be their own representative.
- *
- * _Available since v4.5._
- */
-abstract contract ERC721Votes is ERC721, Votes {
-    /**
-     * @dev Adjusts votes when tokens are transferred.
-     *
-     * Emits a {Votes-DelegateVotesChanged} event.
-     */
-    function _afterTokenTransfer(
-        address from,
-        address to,
-        uint256 tokenId
-    ) internal virtual override {
-        _transferVotingUnits(from, to, 1);
-        super._afterTokenTransfer(from, to, tokenId);
-    }
-
-    /**
-     * @dev Returns the balance of `account`.
-     */
-    function _getVotingUnits(address account) internal view virtual override returns (uint256) {
-        return balanceOf(account);
-    }
-}
+import "./ERC721Votes.sol";

+ 4 - 3
contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol)
 
 pragma solidity ^0.8.0;
 
@@ -119,9 +119,10 @@ contract ERC721PresetMinterPauserAutoId is
     function _beforeTokenTransfer(
         address from,
         address to,
-        uint256 tokenId
+        uint256 firstTokenId,
+        uint256 batchSize
     ) internal virtual override(ERC721, ERC721Enumerable, ERC721Pausable) {
-        super._beforeTokenTransfer(from, to, tokenId);
+        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
     }
 
     /**

+ 2 - 2
contracts/token/ERC777/ERC777.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC777/ERC777.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC777/ERC777.sol)
 
 pragma solidity ^0.8.0;
 
@@ -508,7 +508,7 @@ contract ERC777 is Context, IERC777, IERC20 {
      * Does not update the allowance amount in case of infinite allowance.
      * Revert if not enough allowance is available.
      *
-     * Might emit an {Approval} event.
+     * Might emit an {IERC20-Approval} event.
      */
     function _spendAllowance(
         address owner,

+ 3 - 3
contracts/token/ERC777/IERC777.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC777/IERC777.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC777/IERC777.sol)
 
 pragma solidity ^0.8.0;
 
@@ -28,12 +28,12 @@ interface IERC777 {
     event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
 
     /**
-     * @dev Emitted when `operator` is made operator for `tokenHolder`
+     * @dev Emitted when `operator` is made operator for `tokenHolder`.
      */
     event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
 
     /**
-     * @dev Emitted when `operator` is revoked its operator status for `tokenHolder`
+     * @dev Emitted when `operator` is revoked its operator status for `tokenHolder`.
      */
     event RevokedOperator(address indexed operator, address indexed tokenHolder);
 

+ 45 - 23
contracts/utils/Address.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
 
 pragma solidity ^0.8.1;
 
@@ -83,7 +83,7 @@ library Address {
      * _Available since v3.1._
      */
     function functionCall(address target, bytes memory data) internal returns (bytes memory) {
-        return functionCall(target, data, "Address: low-level call failed");
+        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
     }
 
     /**
@@ -132,10 +132,8 @@ library Address {
         string memory errorMessage
     ) internal returns (bytes memory) {
         require(address(this).balance >= value, "Address: insufficient balance for call");
-        require(isContract(target), "Address: call to non-contract");
-
         (bool success, bytes memory returndata) = target.call{value: value}(data);
-        return verifyCallResult(success, returndata, errorMessage);
+        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
     }
 
     /**
@@ -159,10 +157,8 @@ library Address {
         bytes memory data,
         string memory errorMessage
     ) internal view returns (bytes memory) {
-        require(isContract(target), "Address: static call to non-contract");
-
         (bool success, bytes memory returndata) = target.staticcall(data);
-        return verifyCallResult(success, returndata, errorMessage);
+        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
     }
 
     /**
@@ -186,15 +182,37 @@ library Address {
         bytes memory data,
         string memory errorMessage
     ) internal returns (bytes memory) {
-        require(isContract(target), "Address: delegate call to non-contract");
-
         (bool success, bytes memory returndata) = target.delegatecall(data);
-        return verifyCallResult(success, returndata, errorMessage);
+        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
+    }
+
+    /**
+     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
+     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
+     *
+     * _Available since v4.8._
+     */
+    function verifyCallResultFromTarget(
+        address target,
+        bool success,
+        bytes memory returndata,
+        string memory errorMessage
+    ) internal view returns (bytes memory) {
+        if (success) {
+            if (returndata.length == 0) {
+                // only check isContract if the call was successful and the return data is empty
+                // otherwise we already know that it was a contract
+                require(isContract(target), "Address: call to non-contract");
+            }
+            return returndata;
+        } else {
+            _revert(returndata, errorMessage);
+        }
     }
 
     /**
-     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
-     * revert reason using the provided one.
+     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
+     * revert reason or using the provided one.
      *
      * _Available since v4.3._
      */
@@ -206,17 +224,21 @@ library Address {
         if (success) {
             return returndata;
         } else {
-            // Look for revert reason and bubble it up if present
-            if (returndata.length > 0) {
-                // The easiest way to bubble the revert reason is using memory via assembly
-                /// @solidity memory-safe-assembly
-                assembly {
-                    let returndata_size := mload(returndata)
-                    revert(add(32, returndata), returndata_size)
-                }
-            } else {
-                revert(errorMessage);
+            _revert(returndata, errorMessage);
+        }
+    }
+
+    function _revert(bytes memory returndata, string memory errorMessage) private pure {
+        // Look for revert reason and bubble it up if present
+        if (returndata.length > 0) {
+            // The easiest way to bubble the revert reason is using memory via assembly
+            /// @solidity memory-safe-assembly
+            assembly {
+                let returndata_size := mload(returndata)
+                revert(add(32, returndata), returndata_size)
             }
+        } else {
+            revert(errorMessage);
         }
     }
 }

+ 51 - 3
contracts/utils/Arrays.sol

@@ -1,14 +1,17 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/Arrays.sol)
+// OpenZeppelin Contracts (last updated v4.8.0) (utils/Arrays.sol)
 
 pragma solidity ^0.8.0;
 
+import "./StorageSlot.sol";
 import "./math/Math.sol";
 
 /**
  * @dev Collection of functions related to array types.
  */
 library Arrays {
+    using StorageSlot for bytes32;
+
     /**
      * @dev Searches a sorted `array` and returns the first index that contains
      * a value greater or equal to `element`. If no such index exists (i.e. all
@@ -31,7 +34,7 @@ library Arrays {
 
             // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
             // because Math.average rounds down (it does integer division with truncation).
-            if (array[mid] > element) {
+            if (unsafeAccess(array, mid).value > element) {
                 high = mid;
             } else {
                 low = mid + 1;
@@ -39,10 +42,55 @@ library Arrays {
         }
 
         // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
-        if (low > 0 && array[low - 1] == element) {
+        if (low > 0 && unsafeAccess(array, low - 1).value == element) {
             return low - 1;
         } else {
             return low;
         }
     }
+
+    /**
+     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
+     *
+     * WARNING: Only use if you are certain `pos` is lower than the array length.
+     */
+    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
+        bytes32 slot;
+        /// @solidity memory-safe-assembly
+        assembly {
+            mstore(0, arr.slot)
+            slot := add(keccak256(0, 0x20), pos)
+        }
+        return slot.getAddressSlot();
+    }
+
+    /**
+     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
+     *
+     * WARNING: Only use if you are certain `pos` is lower than the array length.
+     */
+    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
+        bytes32 slot;
+        /// @solidity memory-safe-assembly
+        assembly {
+            mstore(0, arr.slot)
+            slot := add(keccak256(0, 0x20), pos)
+        }
+        return slot.getBytes32Slot();
+    }
+
+    /**
+     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
+     *
+     * WARNING: Only use if you are certain `pos` is lower than the array length.
+     */
+    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
+        bytes32 slot;
+        /// @solidity memory-safe-assembly
+        assembly {
+            mstore(0, arr.slot)
+            slot := add(keccak256(0, 0x20), pos)
+        }
+        return slot.getUint256Slot();
+    }
 }

Някои файлове не бяха показани, защото твърде много файлове са промени