github-actions 3 жил өмнө
parent
commit
84526a0944
100 өөрчлөгдсөн 2680 нэмэгдсэн , 427 устгасан
  1. 3 5
      .eslintrc
  2. 2 2
      .github/ISSUE_TEMPLATE/config.yml
  3. 3 3
      .github/workflows/docs.yml
  4. 30 7
      .github/workflows/test.yml
  5. 3 0
      .prettierrc
  6. 31 1
      CHANGELOG.md
  7. 1 1
      CONTRIBUTING.md
  8. 1 1
      LICENSE
  9. 4 0
      README.md
  10. 1 1
      audit/2017-03.md
  11. 1 1
      certora/applyHarness.patch
  12. 3 3
      certora/specs/GovernorBase.spec
  13. 5 5
      certora/specs/GovernorCountingSimple.spec
  14. 14 2
      contracts/access/AccessControl.sol
  15. 45 0
      contracts/access/AccessControlCrossChain.sol
  16. 2 0
      contracts/access/README.adoc
  17. 54 0
      contracts/crosschain/CrossChainEnabled.sol
  18. 34 0
      contracts/crosschain/README.adoc
  19. 48 0
      contracts/crosschain/amb/CrossChainEnabledAMB.sol
  20. 35 0
      contracts/crosschain/amb/LibAMB.sol
  21. 44 0
      contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL1.sol
  22. 35 0
      contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol
  23. 43 0
      contracts/crosschain/arbitrum/LibArbitrumL1.sol
  24. 43 0
      contracts/crosschain/arbitrum/LibArbitrumL2.sol
  25. 7 0
      contracts/crosschain/errors.sol
  26. 41 0
      contracts/crosschain/optimism/CrossChainEnabledOptimism.sol
  27. 36 0
      contracts/crosschain/optimism/LibOptimism.sol
  28. 72 0
      contracts/crosschain/polygon/CrossChainEnabledPolygonChild.sol
  29. 2 2
      contracts/finance/VestingWallet.sol
  30. 227 16
      contracts/governance/Governor.sol
  31. 67 9
      contracts/governance/IGovernor.sol
  32. 1 1
      contracts/governance/README.adoc
  33. 78 16
      contracts/governance/TimelockController.sol
  34. 3 2
      contracts/governance/compatibility/GovernorCompatibilityBravo.sol
  35. 3 2
      contracts/governance/extensions/GovernorCountingSimple.sol
  36. 4 3
      contracts/governance/extensions/GovernorPreventLateQuorum.sol
  37. 5 58
      contracts/governance/extensions/GovernorTimelockCompound.sol
  38. 7 4
      contracts/governance/extensions/GovernorTimelockControl.sol
  39. 7 3
      contracts/governance/extensions/GovernorVotes.sol
  40. 7 3
      contracts/governance/extensions/GovernorVotesComp.sol
  41. 2 2
      contracts/governance/utils/Votes.sol
  42. 2 2
      contracts/interfaces/IERC2981.sol
  43. 22 0
      contracts/mocks/AccessControlCrossChainMock.sol
  44. 58 0
      contracts/mocks/DoubleEndedQueueMock.sol
  45. 22 0
      contracts/mocks/ERC1155URIStorageMock.sol
  46. 8 0
      contracts/mocks/ERC20DecimalsMock.sol
  47. 87 1
      contracts/mocks/EnumerableMapMock.sol
  48. 0 10
      contracts/mocks/GovernorCompMock.sol
  49. 0 10
      contracts/mocks/GovernorCompatibilityBravoMock.sol
  50. 0 10
      contracts/mocks/GovernorMock.sol
  51. 3 2
      contracts/mocks/GovernorPreventLateQuorumMock.sol
  52. 0 10
      contracts/mocks/GovernorTimelockCompoundMock.sol
  53. 2 10
      contracts/mocks/GovernorTimelockControlMock.sol
  54. 0 10
      contracts/mocks/GovernorVoteMock.sol
  55. 61 0
      contracts/mocks/GovernorWithParamsMock.sol
  56. 29 0
      contracts/mocks/InitializableMock.sol
  57. 1 1
      contracts/mocks/VotesMock.sol
  58. 106 0
      contracts/mocks/crosschain/bridges.sol
  59. 54 0
      contracts/mocks/crosschain/receivers.sol
  60. 0 9
      contracts/mocks/wizard/MyGovernor1.sol
  61. 0 9
      contracts/mocks/wizard/MyGovernor2.sol
  62. 0 9
      contracts/mocks/wizard/MyGovernor3.sol
  63. 1 1
      contracts/package.json
  64. 4 4
      contracts/proxy/Proxy.sol
  65. 1 1
      contracts/proxy/README.adoc
  66. 87 18
      contracts/proxy/utils/Initializable.sol
  67. 51 4
      contracts/token/ERC1155/ERC1155.sol
  68. 2 0
      contracts/token/ERC1155/README.adoc
  69. 8 2
      contracts/token/ERC1155/extensions/ERC1155Supply.sol
  70. 63 0
      contracts/token/ERC1155/extensions/ERC1155URIStorage.sol
  71. 4 4
      contracts/token/ERC20/ERC20.sol
  72. 15 15
      contracts/token/ERC20/IERC20.sol
  73. 1 1
      contracts/token/ERC20/README.adoc
  74. 7 6
      contracts/token/ERC20/extensions/ERC20FlashMint.sol
  75. 2 2
      contracts/token/ERC20/extensions/ERC20Snapshot.sol
  76. 13 2
      contracts/token/ERC20/extensions/ERC20Wrapper.sol
  77. 10 2
      contracts/token/ERC20/extensions/draft-ERC20Permit.sol
  78. 3 3
      contracts/token/ERC721/ERC721.sol
  79. 29 29
      contracts/token/ERC721/IERC721.sol
  80. 2 2
      contracts/token/ERC721/IERC721Receiver.sol
  81. 2 2
      contracts/token/ERC721/extensions/draft-ERC721Votes.sol
  82. 6 25
      contracts/token/ERC777/ERC777.sol
  83. 25 9
      contracts/token/ERC777/IERC777.sol
  84. 2 8
      contracts/token/common/ERC2981.sol
  85. 2 0
      contracts/utils/README.adoc
  86. 7 2
      contracts/utils/cryptography/MerkleProof.sol
  87. 5 5
      contracts/utils/introspection/IERC1820Registry.sol
  88. 2 2
      contracts/utils/math/SafeMath.sol
  89. 170 0
      contracts/utils/structs/DoubleEndedQueue.sol
  90. 125 28
      contracts/utils/structs/EnumerableMap.sol
  91. 4 4
      contracts/utils/structs/EnumerableSet.sol
  92. 49 0
      contracts/vendor/amb/IAMB.sol
  93. 99 0
      contracts/vendor/arbitrum/IArbSys.sol
  94. 66 0
      contracts/vendor/arbitrum/IBridge.sol
  95. 92 0
      contracts/vendor/arbitrum/IInbox.sol
  96. 26 0
      contracts/vendor/arbitrum/IMessageProvider.sol
  97. 51 0
      contracts/vendor/arbitrum/IOutbox.sol
  98. 86 0
      contracts/vendor/compound/ICompoundTimelock.sol
  99. 11 0
      contracts/vendor/compound/LICENSE
  100. 38 0
      contracts/vendor/optimism/ICrossDomainMessenger.sol

+ 3 - 5
.eslintrc

@@ -1,11 +1,9 @@
 {
   "extends" : [
-    "standard",
-    "plugin:promise/recommended",
+    "standard"
   ],
   "plugins": [
-    "mocha-no-only",
-    "promise",
+    "mocha"
   ],
   "env": {
     "browser" : true,
@@ -53,7 +51,7 @@
     "semi": ["error", "always"],
     "space-before-function-paren": ["error", "always"],
 
-    "mocha-no-only/mocha-no-only": ["error"],
+    "mocha/no-exclusive-tests": ["error"],
 
     "promise/always-return": "off",
     "promise/avoid-new": "off",

+ 2 - 2
.github/ISSUE_TEMPLATE/config.yml

@@ -1,4 +1,4 @@
 contact_links:
-  - name: Support request
+  - name: Questions & Support Requests
     url: https://forum.openzeppelin.com/c/support/contracts/18
-    about: Ask the community in the Community Forum
+    about: Ask in the OpenZeppelin Forum

+ 3 - 3
.github/workflows/docs.yml

@@ -8,11 +8,11 @@ jobs:
   build:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-node@v2
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
         with:
           node-version: 12.x
-      - uses: actions/cache@v2
+      - uses: actions/cache@v3
         id: cache
         with:
           path: '**/node_modules'

+ 30 - 7
.github/workflows/test.yml

@@ -12,11 +12,11 @@ jobs:
   test:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-node@v2
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
         with:
           node-version: 12.x
-      - uses: actions/cache@v2
+      - uses: actions/cache@v3
         id: cache
         with:
           path: '**/node_modules'
@@ -29,20 +29,20 @@ jobs:
         env:
           FORCE_COLOR: 1
           ENABLE_GAS_REPORT: true
-      - run: npm run test:inheritance 
+      - run: npm run test:inheritance
       - name: Print gas report
         run: cat gas-report.txt
 
   coverage:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
         with:
           fetch-depth: 2
-      - uses: actions/setup-node@v2
+      - uses: actions/setup-node@v3
         with:
           node-version: 12.x
-      - uses: actions/cache@v2
+      - uses: actions/cache@v3
         id: cache
         with:
           path: '**/node_modules'
@@ -54,3 +54,26 @@ jobs:
         env:
           NODE_OPTIONS: --max_old_space_size=4096
       - uses: codecov/codecov-action@v2
+
+  slither:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
+        with:
+          node-version: 12.x
+      - uses: actions/cache@v3
+        id: cache
+        with:
+          path: '**/node_modules'
+          key: npm-v2-${{ hashFiles('**/package-lock.json') }}
+          restore-keys: npm-v2-
+      - run: npm ci
+        if: steps.cache.outputs.cache-hit != 'true'
+      - name: Set up Python
+        uses: actions/setup-python@v2
+
+      - name: Install dependencies
+        run: pip3 install slither-analyzer
+      - name: Summary of static analysis
+        run: npm run slither

+ 3 - 0
.prettierrc

@@ -1,8 +1,11 @@
 {
+  "singleQuote": true,
+  "trailingComma": "all",
   "overrides": [
     {
       "files": "*.sol",
       "options": {
+        "singleQuote": false,
         "printWidth": 120,
         "explicitTypes": "always"
       }

+ 31 - 1
CHANGELOG.md

@@ -1,5 +1,35 @@
 # Changelog
 
+## 4.6.0 (2022-04-26)
+
+ * `crosschain`: Add a new set of contracts for cross-chain applications. `CrossChainEnabled` is a base contract with instantiations for several chains and bridges, and `AccessControlCrossChain` is an extension of access control that allows cross-chain operation. ([#3183](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3183))
+ * `AccessControl`: add a virtual `_checkRole(bytes32)` function that can be overridden to alter the `onlyRole` modifier behavior. ([#3137](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3137))
+ * `EnumerableMap`: add new `AddressToUintMap` map type. ([#3150](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3150))
+ * `EnumerableMap`: add new `Bytes32ToBytes32Map` map type. ([#3192](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3192))
+ * `ERC20FlashMint`: support infinite allowance when paying back a flash loan. ([#3226](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3226))
+ * `ERC20Wrapper`: the `decimals()` function now tries to fetch the value from the underlying token instance. If that calls revert, then the default value is used. ([#3259](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3259))
+ * `draft-ERC20Permit`: replace `immutable` with `constant` for `_PERMIT_TYPEHASH` since the `keccak256` of string literals is treated specially and the hash is evaluated at compile time. ([#3196](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3196))
+ * `ERC1155`: Add a `_afterTokenTransfer` hook for improved extensibility. ([#3166](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3166))
+ * `ERC1155URIStorage`: add a new extension that implements a `_setURI` behavior similar to ERC721's `_setTokenURI`. ([#3210](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3210))
+ * `DoubleEndedQueue`: a new data structure that supports efficient push and pop to both front and back, useful for FIFO and LIFO queues. ([#3153](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3153))
+ * `Governor`: improved security of `onlyGovernance` modifier when using an external executor contract (e.g. a timelock) that can operate without necessarily going through the governance protocol. ([#3147](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3147))
+ * `Governor`: Add a way to parameterize votes. This can be used to implement voting systems such as fractionalized voting, ERC721 based voting, or any number of other systems. The `params` argument added to `_countVote` method, and included in the newly added `_getVotes` method, can be used by counting and voting modules respectively for such purposes. ([#3043](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3043))
+ * `Governor`: rewording of revert reason for consistency. ([#3275](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3275))
+ * `Governor`: fix an inconsistency in data locations that could lead to invalid bytecode being produced. ([#3295](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3295))
+ * `Governor`: Implement `IERC721Receiver` and `IERC1155Receiver` to improve token custody by governors. ([#3230](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3230))
+ * `TimelockController`: Implement `IERC721Receiver` and `IERC1155Receiver` to improve token custody by timelocks. ([#3230](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3230))
+ * `TimelockController`: Add a separate canceller role for the ability to cancel. ([#3165](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3165))
+ * `Initializable`: add a reinitializer modifier that enables the initialization of new modules, added to already initialized contracts through upgradeability. ([#3232](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3232))
+ * `Initializable`: add an Initialized event that tracks initialized version numbers. ([#3294](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3294))
+ * `ERC2981`: make `royaltiInfo` public to allow super call in overrides. ([#3305](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3305))
+
+### 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`: 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.
+
 ## 4.5.0 (2022-02-09)
 
  * `ERC2981`: add implementation of the royalty standard, and the respective extensions for `ERC721` and `ERC1155`. ([#3012](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3012))
@@ -437,7 +467,7 @@ Refer to the table below to adjust your inheritance list.
  * `SignedSafeMath`: added overflow-safe operations for signed integers (`int256`). ([#1559](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1559), [#1588](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1588))
 
 ### Improvements
- * The compiler version required by `Array` was behind the rest of the libray so it was updated to `v0.4.24`. ([#1553](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1553))
+ * The compiler version required by `Array` was behind the rest of the library so it was updated to `v0.4.24`. ([#1553](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1553))
  * 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))

+ 1 - 1
CONTRIBUTING.md

@@ -51,7 +51,7 @@ refer to some very important conditions that your PR must meet in order to be ac
 
 6) Maintainers will review your code and possibly ask for changes before your code is pulled in to the main repository. We'll check that all tests pass, review the coding style, and check for general code correctness. If everything is OK, we'll merge your pull request and your code will be part of OpenZeppelin Contracts.
 
-*IMPORTANT* Please pay attention to the maintainer's feedback, since its a necessary step to keep up with the standards OpenZeppelin Contracts attains to.
+*IMPORTANT* Please pay attention to the maintainer's feedback, since it's a necessary step to keep up with the standards OpenZeppelin Contracts attains to.
 
 ## All set!
 

+ 1 - 1
LICENSE

@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2016-2020 zOS Global Limited
+Copyright (c) 2016-2022 zOS Global Limited and contributors
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the

+ 4 - 0
README.md

@@ -12,6 +12,8 @@
 
 :mage: **Not sure how to get started?** Check out [Contracts Wizard](https://wizard.openzeppelin.com/) — an interactive smart contract generator.
 
+:building_construction: **Want to scale your decentralized application?** Check out [OpenZeppelin Defender](https://openzeppelin.com/defender) — a secure platform for automating and monitoring your operations.
+
 ## Overview
 
 ### Installation
@@ -22,6 +24,8 @@ $ 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.
 
+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
 
 Once installed, you can use the contracts in the library by importing them:

+ 1 - 1
audit/2017-03.md

@@ -133,7 +133,7 @@ I presume that the goal of this contract is to allow and annotate a migration to
 
 We like these pauses! Note that these allow significant griefing potential by owners, and that this might not be obvious to participants in smart contracts using the OpenZeppelin framework. We would recommend that additional sample logic be added to for instance the TokenContract showing safer use of the pause and resume functions. In particular, we would recommend a timelock after which anyone could unpause the contract.
 
-The modifers use the pattern `if(bool){_;}`. This is fine for functions that return false upon failure, but could be problematic for functions expected to throw upon failure. See our comments above on standardizing on `throw` or `return(false)`.
+The modifiers use the pattern `if(bool){_;}`. This is fine for functions that return false upon failure, but could be problematic for functions expected to throw upon failure. See our comments above on standardizing on `throw` or `return(false)`.
 
 ## Ownership
 

+ 1 - 1
certora/applyHarness.patch

@@ -71,7 +71,7 @@ diff -ruN governance/Governor.sol governance/Governor.sol
 + 
      /**
       * @dev Restrict access to governor executing address. Some module might override the _executor function to make
-      * sure this modifier is consistant with the execution model.
+      * sure this modifier is consistent with the execution model.
 @@ -167,12 +167,12 @@
      /**
       * @dev Amount of votes already cast passes the threshold limit.

+ 3 - 3
certora/specs/GovernorBase.spec

@@ -173,11 +173,11 @@ rule executionOnlyIfQuoromReachedAndVoteSucceeded(uint256 pId, env e, method f){
 /*
  * A user cannot vote twice
  */
- // Checked for castVote only. all 3 castVote functions call _castVote, so the completness of the verification is counted on
- // the fact that the 3 functions themselves makes no chages, but rather call an internal function to execute.
+ // Checked for castVote only. all 3 castVote functions call _castVote, so the completeness of the verification is counted on
+ // 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 seperately 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;

+ 5 - 5
certora/specs/GovernorCountingSimple.spec

@@ -128,11 +128,11 @@ invariant OneIsNotMoreThanAll(uint256 pId)
 /*
  * Only sender's voting status can be changed by execution of any cast vote function
  */
-// Checked for castVote only. all 3 castVote functions call _castVote, so the completness of the verification is counted on
- // the fact that the 3 functions themselves makes no chages, but rather call an internal function to execute.
+// Checked for castVote only. all 3 castVote functions call _castVote, so the completeness of the verification is counted on
+ // 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 seperately 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 noVoteForSomeoneElse(uint256 pId, uint8 sup, method f) {
     env e; calldataarg args;
@@ -205,7 +205,7 @@ rule privilegedOnlyNumerator(method f, uint256 newQuorumNumerator){
     uint256 quorumNumAfter = quorumNumerator(e);
     address executorCheck = getExecutor(e);
 
-    assert quorumNumBefore != quorumNumAfter => e.msg.sender == executorCheck, "non priveleged user changed quorum numerator";
+    assert quorumNumBefore != quorumNumAfter => e.msg.sender == executorCheck, "non privileged user changed quorum numerator";
 }
 
 rule privilegedOnlyTimelock(method f, uint256 newQuorumNumerator){
@@ -217,5 +217,5 @@ rule privilegedOnlyTimelock(method f, uint256 newQuorumNumerator){
 
     uint256 timelockAfter = timelock(e);
 
-    assert timelockBefore != timelockAfter => e.msg.sender == timelockBefore, "non priveleged user changed timelock";
+    assert timelockBefore != timelockAfter => e.msg.sender == timelockBefore, "non privileged user changed timelock";
 }

+ 14 - 2
contracts/access/AccessControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (access/AccessControl.sol)
 
 pragma solidity ^0.8.0;
 
@@ -67,7 +67,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
      * _Available since v4.1._
      */
     modifier onlyRole(bytes32 role) {
-        _checkRole(role, _msgSender());
+        _checkRole(role);
         _;
     }
 
@@ -85,6 +85,18 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
         return _roles[role].members[account];
     }
 
+    /**
+     * @dev Revert with a standard message if `_msgSender()` is missing `role`.
+     * Overriding this function changes the behavior of the {onlyRole} modifier.
+     *
+     * Format of the revert message is described in {_checkRole}.
+     *
+     * _Available since v4.6._
+     */
+    function _checkRole(bytes32 role) internal view virtual {
+        _checkRole(role, _msgSender());
+    }
+
     /**
      * @dev Revert with a standard message if `account` is missing `role`.
      *

+ 45 - 0
contracts/access/AccessControlCrossChain.sol

@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (access/AccessControlCrossChain.sol)
+
+pragma solidity ^0.8.4;
+
+import "./AccessControl.sol";
+import "../crosschain/CrossChainEnabled.sol";
+
+/**
+ * @dev An extension to {AccessControl} with support for cross-chain access management.
+ * For each role, is extension implements an equivalent "aliased" role that is used for
+ * restricting calls originating from other chains.
+ *
+ * For example, if a function `myFunction` is protected by `onlyRole(SOME_ROLE)`, and
+ * if an address `x` has role `SOME_ROLE`, it would be able to call `myFunction` directly.
+ * A wallet or contract at the same address on another chain would however not be able
+ * to call this function. In order to do so, it would require to have the role
+ * `_crossChainRoleAlias(SOME_ROLE)`.
+ *
+ * This aliasing is required to protect against multiple contracts living at the same
+ * address on different chains but controlled by conflicting entities.
+ *
+ * _Available since v4.6._
+ */
+abstract contract AccessControlCrossChain is AccessControl, CrossChainEnabled {
+    bytes32 public constant CROSSCHAIN_ALIAS = keccak256("CROSSCHAIN_ALIAS");
+
+    /**
+     * @dev See {AccessControl-_checkRole}.
+     */
+    function _checkRole(bytes32 role) internal view virtual override {
+        if (_isCrossChain()) {
+            _checkRole(_crossChainRoleAlias(role), _crossChainSender());
+        } else {
+            super._checkRole(role);
+        }
+    }
+
+    /**
+     * @dev Returns the aliased role corresponding to `role`.
+     */
+    function _crossChainRoleAlias(bytes32 role) internal pure virtual returns (bytes32) {
+        return role ^ CROSSCHAIN_ALIAS;
+    }
+}

+ 2 - 0
contracts/access/README.adoc

@@ -16,6 +16,8 @@ This directory provides ways to restrict who can access the functions of a contr
 
 {{AccessControl}}
 
+{{AccessControlCrossChain}}
+
 {{IAccessControlEnumerable}}
 
 {{AccessControlEnumerable}}

+ 54 - 0
contracts/crosschain/CrossChainEnabled.sol

@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/CrossChainEnabled.sol)
+
+pragma solidity ^0.8.4;
+
+import "./errors.sol";
+
+/**
+ * @dev Provides information for building cross-chain aware contracts. This
+ * abstract contract provides accessors and modifiers to control the execution
+ * flow when receiving cross-chain messages.
+ *
+ * Actual implementations of cross-chain aware contracts, which are based on
+ * this abstraction, will  have to inherit from a bridge-specific
+ * specialization. Such specializations are provided under
+ * `crosschain/<chain>/CrossChainEnabled<chain>.sol`.
+ *
+ * _Available since v4.6._
+ */
+abstract contract CrossChainEnabled {
+    /**
+     * @dev Throws if the current function call is not the result of a
+     * cross-chain execution.
+     */
+    modifier onlyCrossChain() {
+        if (!_isCrossChain()) revert NotCrossChainCall();
+        _;
+    }
+
+    /**
+     * @dev Throws if the current function call is not the result of a
+     * cross-chain execution initiated by `account`.
+     */
+    modifier onlyCrossChainSender(address expected) {
+        address actual = _crossChainSender();
+        if (expected != actual) revert InvalidCrossChainSender(actual, expected);
+        _;
+    }
+
+    /**
+     * @dev Returns whether the current function call is the result of a
+     * cross-chain message.
+     */
+    function _isCrossChain() internal view virtual returns (bool);
+
+    /**
+     * @dev Returns the address of the sender of the cross-chain message that
+     * triggered the current function call.
+     *
+     * IMPORTANT: Should revert with `NotCrossChainCall` if the current function
+     * call is not the result of a cross-chain message.
+     */
+    function _crossChainSender() internal view virtual returns (address);
+}

+ 34 - 0
contracts/crosschain/README.adoc

@@ -0,0 +1,34 @@
+= Cross Chain Awareness
+
+[.readme-notice]
+NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/crosschain
+
+This directory provides building blocks to improve cross-chain awareness of smart contracts.
+
+- {CrossChainEnabled} is an abstraction that contains accessors and modifiers to control the execution flow when receiving cross-chain messages.
+
+== CrossChainEnabled specializations
+
+The following specializations of {CrossChainEnabled} provide implementations of the {CrossChainEnabled} abstraction for specific bridges. This can be used to complexe cross-chain aware components such as {AccessControlCrossChain}.
+
+{{CrossChainEnabledAMB}}
+
+{{CrossChainEnabledArbitrumL1}}
+
+{{CrossChainEnabledArbitrumL2}}
+
+{{CrossChainEnabledOptimism}}
+
+{{CrossChainEnabledPolygonChild}}
+
+== Libraries for cross-chain
+
+In addition to the {CrossChainEnable} abstraction, cross-chain awareness is also available through libraries. These libraries can be used to build complex designs such as contracts with the ability to interact with multiple bridges.
+
+{{LibAMB}}
+
+{{LibArbitrumL1}}
+
+{{LibArbitrumL2}}
+
+{{LibOptimism}}

+ 48 - 0
contracts/crosschain/amb/CrossChainEnabledAMB.sol

@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/amb/CrossChainEnabledAMB.sol)
+
+pragma solidity ^0.8.4;
+
+import "../CrossChainEnabled.sol";
+import "./LibAMB.sol";
+
+/**
+ * @dev [AMB](https://docs.tokenbridge.net/amb-bridge/about-amb-bridge)
+ * specialization or the {CrossChainEnabled} abstraction.
+ *
+ * As of february 2020, AMB bridges are available between the following chains:
+ * - [ETH <> xDai](https://docs.tokenbridge.net/eth-xdai-amb-bridge/about-the-eth-xdai-amb)
+ * - [ETH <> qDai](https://docs.tokenbridge.net/eth-qdai-bridge/about-the-eth-qdai-amb)
+ * - [ETH <> ETC](https://docs.tokenbridge.net/eth-etc-amb-bridge/about-the-eth-etc-amb)
+ * - [ETH <> BSC](https://docs.tokenbridge.net/eth-bsc-amb/about-the-eth-bsc-amb)
+ * - [ETH <> POA](https://docs.tokenbridge.net/eth-poa-amb-bridge/about-the-eth-poa-amb)
+ * - [BSC <> xDai](https://docs.tokenbridge.net/bsc-xdai-amb/about-the-bsc-xdai-amb)
+ * - [POA <> xDai](https://docs.tokenbridge.net/poa-xdai-amb/about-the-poa-xdai-amb)
+ * - [Rinkeby <> xDai](https://docs.tokenbridge.net/rinkeby-xdai-amb-bridge/about-the-rinkeby-xdai-amb)
+ * - [Kovan <> Sokol](https://docs.tokenbridge.net/kovan-sokol-amb-bridge/about-the-kovan-sokol-amb)
+ *
+ * _Available since v4.6._
+ */
+contract CrossChainEnabledAMB is CrossChainEnabled {
+    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
+    address private immutable _bridge;
+
+    /// @custom:oz-upgrades-unsafe-allow constructor
+    constructor(address bridge) {
+        _bridge = bridge;
+    }
+
+    /**
+     * @dev see {CrossChainEnabled-_isCrossChain}
+     */
+    function _isCrossChain() internal view virtual override returns (bool) {
+        return LibAMB.isCrossChain(_bridge);
+    }
+
+    /**
+     * @dev see {CrossChainEnabled-_crossChainSender}
+     */
+    function _crossChainSender() internal view virtual override onlyCrossChain returns (address) {
+        return LibAMB.crossChainSender(_bridge);
+    }
+}

+ 35 - 0
contracts/crosschain/amb/LibAMB.sol

@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/amb/LibAMB.sol)
+
+pragma solidity ^0.8.4;
+
+import {IAMB as AMB_Bridge} from "../../vendor/amb/IAMB.sol";
+import "../errors.sol";
+
+/**
+ * @dev Primitives for cross-chain aware contracts using the
+ * [AMB](https://docs.tokenbridge.net/amb-bridge/about-amb-bridge)
+ * family of bridges.
+ */
+library LibAMB {
+    /**
+     * @dev Returns whether the current function call is the result of a
+     * cross-chain message relayed by `bridge`.
+     */
+    function isCrossChain(address bridge) internal view returns (bool) {
+        return msg.sender == bridge;
+    }
+
+    /**
+     * @dev Returns the address of the sender that triggered the current
+     * cross-chain message through `bridge`.
+     *
+     * NOTE: {isCrossChain} should be checked before trying to recover the
+     * sender, as it will revert with `NotCrossChainCall` if the current
+     * function call is not the result of a cross-chain message.
+     */
+    function crossChainSender(address bridge) internal view returns (address) {
+        if (!isCrossChain(bridge)) revert NotCrossChainCall();
+        return AMB_Bridge(bridge).messageSender();
+    }
+}

+ 44 - 0
contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL1.sol

@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/arbitrum/CrossChainEnabledArbitrumL1.sol)
+
+pragma solidity ^0.8.4;
+
+import "../CrossChainEnabled.sol";
+import "./LibArbitrumL1.sol";
+
+/**
+ * @dev [Arbitrum](https://arbitrum.io/) specialization or the
+ * {CrossChainEnabled} abstraction the L1 side (mainnet).
+ *
+ * This version should only be deployed on L1 to process cross-chain messages
+ * originating from L2. For the other side, use {CrossChainEnabledArbitrumL2}.
+ *
+ * The bridge contract is provided and maintained by the arbitrum team. You can
+ * find the address of this contract on the rinkeby testnet in
+ * [Arbitrum's developer documentation](https://developer.offchainlabs.com/docs/useful_addresses).
+ *
+ * _Available since v4.6._
+ */
+abstract contract CrossChainEnabledArbitrumL1 is CrossChainEnabled {
+    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
+    address private immutable _bridge;
+
+    /// @custom:oz-upgrades-unsafe-allow constructor
+    constructor(address bridge) {
+        _bridge = bridge;
+    }
+
+    /**
+     * @dev see {CrossChainEnabled-_isCrossChain}
+     */
+    function _isCrossChain() internal view virtual override returns (bool) {
+        return LibArbitrumL1.isCrossChain(_bridge);
+    }
+
+    /**
+     * @dev see {CrossChainEnabled-_crossChainSender}
+     */
+    function _crossChainSender() internal view virtual override onlyCrossChain returns (address) {
+        return LibArbitrumL1.crossChainSender(_bridge);
+    }
+}

+ 35 - 0
contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol

@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol)
+
+pragma solidity ^0.8.4;
+
+import "../CrossChainEnabled.sol";
+import "./LibArbitrumL2.sol";
+
+/**
+ * @dev [Arbitrum](https://arbitrum.io/) specialization or the
+ * {CrossChainEnabled} abstraction the L2 side (arbitrum).
+ *
+ * This version should only be deployed on L2 to process cross-chain messages
+ * originating from L1. For the other side, use {CrossChainEnabledArbitrumL1}.
+ *
+ * Arbitrum L2 includes the `ArbSys` contract at a fixed address. Therefore,
+ * this specialization of {CrossChainEnabled} does not include a constructor.
+ *
+ * _Available since v4.6._
+ */
+abstract contract CrossChainEnabledArbitrumL2 is CrossChainEnabled {
+    /**
+     * @dev see {CrossChainEnabled-_isCrossChain}
+     */
+    function _isCrossChain() internal view virtual override returns (bool) {
+        return LibArbitrumL2.isCrossChain(LibArbitrumL2.ARBSYS);
+    }
+
+    /**
+     * @dev see {CrossChainEnabled-_crossChainSender}
+     */
+    function _crossChainSender() internal view virtual override onlyCrossChain returns (address) {
+        return LibArbitrumL2.crossChainSender(LibArbitrumL2.ARBSYS);
+    }
+}

+ 43 - 0
contracts/crosschain/arbitrum/LibArbitrumL1.sol

@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.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";
+
+/**
+ * @dev Primitives for cross-chain aware contracts for
+ * [Arbitrum](https://arbitrum.io/).
+ *
+ * This version should only be used on L1 to process cross-chain messages
+ * originating from L2. For the other side, use {LibArbitrumL2}.
+ */
+library LibArbitrumL1 {
+    /**
+     * @dev Returns whether the current function call is the result of a
+     * cross-chain message relayed by the `bridge`.
+     */
+    function isCrossChain(address bridge) internal view returns (bool) {
+        return msg.sender == bridge;
+    }
+
+    /**
+     * @dev Returns the address of the sender that triggered the current
+     * cross-chain message through the `bridge`.
+     *
+     * NOTE: {isCrossChain} should be checked before trying to recover the
+     * sender, as it will revert with `NotCrossChainCall` if the current
+     * function call is not the result of a cross-chain message.
+     */
+    function crossChainSender(address bridge) internal view returns (address) {
+        if (!isCrossChain(bridge)) revert NotCrossChainCall();
+
+        address sender = ArbitrumL1_Outbox(ArbitrumL1_Bridge(bridge).activeOutbox()).l2ToL1Sender();
+        require(sender != address(0), "LibArbitrumL1: system messages without sender");
+
+        return sender;
+    }
+}

+ 43 - 0
contracts/crosschain/arbitrum/LibArbitrumL2.sol

@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/arbitrum/LibArbitrumL2.sol)
+
+pragma solidity ^0.8.4;
+
+import {IArbSys as ArbitrumL2_Bridge} from "../../vendor/arbitrum/IArbSys.sol";
+import "../errors.sol";
+
+/**
+ * @dev Primitives for cross-chain aware contracts for
+ * [Arbitrum](https://arbitrum.io/).
+ *
+ * This version should only be used on L2 to process cross-chain messages
+ * originating from L1. For the other side, use {LibArbitrumL1}.
+ */
+library LibArbitrumL2 {
+    /**
+     * @dev Returns whether the current function call is the result of a
+     * cross-chain message relayed by `arbsys`.
+     */
+    address public constant ARBSYS = 0x0000000000000000000000000000000000000064;
+
+    function isCrossChain(address arbsys) internal view returns (bool) {
+        return ArbitrumL2_Bridge(arbsys).isTopLevelCall();
+    }
+
+    /**
+     * @dev Returns the address of the sender that triggered the current
+     * cross-chain message through `arbsys`.
+     *
+     * NOTE: {isCrossChain} should be checked before trying to recover the
+     * sender, as it will revert with `NotCrossChainCall` if the current
+     * function call is not the result of a cross-chain message.
+     */
+    function crossChainSender(address arbsys) internal view returns (address) {
+        if (!isCrossChain(arbsys)) revert NotCrossChainCall();
+
+        return
+            ArbitrumL2_Bridge(arbsys).wasMyCallersAddressAliased()
+                ? ArbitrumL2_Bridge(arbsys).myCallersAddressWithoutAliasing()
+                : msg.sender;
+    }
+}

+ 7 - 0
contracts/crosschain/errors.sol

@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/errors.sol)
+
+pragma solidity ^0.8.4;
+
+error NotCrossChainCall();
+error InvalidCrossChainSender(address actual, address expected);

+ 41 - 0
contracts/crosschain/optimism/CrossChainEnabledOptimism.sol

@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/optimism/CrossChainEnabledOptimism.sol)
+
+pragma solidity ^0.8.4;
+
+import "../CrossChainEnabled.sol";
+import "./LibOptimism.sol";
+
+/**
+ * @dev [Optimism](https://www.optimism.io/) specialization or the
+ * {CrossChainEnabled} abstraction.
+ *
+ * The messenger (`CrossDomainMessenger`) contract is provided and maintained by
+ * the optimism team. You can find the address of this contract on mainnet and
+ * kovan in the [deployments section of Optimism monorepo](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts/deployments).
+ *
+ * _Available since v4.6._
+ */
+abstract contract CrossChainEnabledOptimism is CrossChainEnabled {
+    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
+    address private immutable _messenger;
+
+    /// @custom:oz-upgrades-unsafe-allow constructor
+    constructor(address messenger) {
+        _messenger = messenger;
+    }
+
+    /**
+     * @dev see {CrossChainEnabled-_isCrossChain}
+     */
+    function _isCrossChain() internal view virtual override returns (bool) {
+        return LibOptimism.isCrossChain(_messenger);
+    }
+
+    /**
+     * @dev see {CrossChainEnabled-_crossChainSender}
+     */
+    function _crossChainSender() internal view virtual override onlyCrossChain returns (address) {
+        return LibOptimism.crossChainSender(_messenger);
+    }
+}

+ 36 - 0
contracts/crosschain/optimism/LibOptimism.sol

@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/optimism/LibOptimism.sol)
+
+pragma solidity ^0.8.4;
+
+import {ICrossDomainMessenger as Optimism_Bridge} from "../../vendor/optimism/ICrossDomainMessenger.sol";
+import "../errors.sol";
+
+/**
+ * @dev Primitives for cross-chain aware contracts for [Optimism](https://www.optimism.io/).
+ * See the [documentation](https://community.optimism.io/docs/developers/bridge/messaging/#accessing-msg-sender)
+ * for the functionality used here.
+ */
+library LibOptimism {
+    /**
+     * @dev Returns whether the current function call is the result of a
+     * cross-chain message relayed by `messenger`.
+     */
+    function isCrossChain(address messenger) internal view returns (bool) {
+        return msg.sender == messenger;
+    }
+
+    /**
+     * @dev Returns the address of the sender that triggered the current
+     * cross-chain message through `messenger`.
+     *
+     * NOTE: {isCrossChain} should be checked before trying to recover the
+     * sender, as it will revert with `NotCrossChainCall` if the current
+     * function call is not the result of a cross-chain message.
+     */
+    function crossChainSender(address messenger) internal view returns (address) {
+        if (!isCrossChain(messenger)) revert NotCrossChainCall();
+
+        return Optimism_Bridge(messenger).xDomainMessageSender();
+    }
+}

+ 72 - 0
contracts/crosschain/polygon/CrossChainEnabledPolygonChild.sol

@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/polygon/CrossChainEnabledPolygonChild.sol)
+
+pragma solidity ^0.8.4;
+
+import "../CrossChainEnabled.sol";
+import "../../security/ReentrancyGuard.sol";
+import "../../utils/Address.sol";
+import "../../vendor/polygon/IFxMessageProcessor.sol";
+
+address constant DEFAULT_SENDER = 0x000000000000000000000000000000000000dEaD;
+
+/**
+ * @dev [Polygon](https://polygon.technology/) specialization or the
+ * {CrossChainEnabled} abstraction the child side (polygon/mumbai).
+ *
+ * This version should only be deployed on child chain to process cross-chain
+ * messages originating from the parent chain.
+ *
+ * The fxChild contract is provided and maintained by the polygon team. You can
+ * find the address of this contract polygon and mumbai in
+ * [Polygon's Fx-Portal documentation](https://docs.polygon.technology/docs/develop/l1-l2-communication/fx-portal/#contract-addresses).
+ *
+ * _Available since v4.6._
+ */
+abstract contract CrossChainEnabledPolygonChild is IFxMessageProcessor, CrossChainEnabled, ReentrancyGuard {
+    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
+    address private immutable _fxChild;
+    address private _sender = DEFAULT_SENDER;
+
+    /// @custom:oz-upgrades-unsafe-allow constructor
+    constructor(address fxChild) {
+        _fxChild = fxChild;
+    }
+
+    /**
+     * @dev see {CrossChainEnabled-_isCrossChain}
+     */
+    function _isCrossChain() internal view virtual override returns (bool) {
+        return msg.sender == _fxChild;
+    }
+
+    /**
+     * @dev see {CrossChainEnabled-_crossChainSender}
+     */
+    function _crossChainSender() internal view virtual override onlyCrossChain returns (address) {
+        return _sender;
+    }
+
+    /**
+     * @dev External entry point to receive and relay messages originating
+     * from the fxChild.
+     *
+     * Non-reentrancy is crucial to avoid a cross-chain call being able
+     * to impersonate anyone by just looping through this with user-defined
+     * arguments.
+     *
+     * Note: if _fxChild calls any other function that does a delegate-call,
+     * then security could be compromised.
+     */
+    function processMessageFromRoot(
+        uint256, /* stateId */
+        address rootMessageSender,
+        bytes calldata data
+    ) external override nonReentrant {
+        require(msg.sender == _fxChild, "unauthorized cross-chain relay");
+
+        _sender = rootMessageSender;
+        Address.functionDelegateCall(address(this), data, "crosschain execution failled");
+        _sender = DEFAULT_SENDER;
+    }
+}

+ 2 - 2
contracts/finance/VestingWallet.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (finance/VestingWallet.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (finance/VestingWallet.sol)
 pragma solidity ^0.8.0;
 
 import "../token/ERC20/utils/SafeERC20.sol";
@@ -120,7 +120,7 @@ contract VestingWallet is Context {
     }
 
     /**
-     * @dev Virtual implementation of the vesting formula. This returns the amout vested, as a function of time, for
+     * @dev Virtual implementation of the vesting formula. This returns the amount vested, as a function of time, for
      * an asset given its total historical allocation.
      */
     function _vestingSchedule(uint256 totalAllocation, uint64 timestamp) internal view virtual returns (uint256) {

+ 227 - 16
contracts/governance/Governor.sol

@@ -1,12 +1,15 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (governance/Governor.sol)
+// OpenZeppelin Contracts (last updated v4.6.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/introspection/ERC165.sol";
 import "../utils/math/SafeCast.sol";
+import "../utils/structs/DoubleEndedQueue.sol";
 import "../utils/Address.sol";
 import "../utils/Context.sol";
 import "../utils/Timers.sol";
@@ -18,16 +21,19 @@ import "./IGovernor.sol";
  * This contract is abstract and requires several function to be implemented in various modules:
  *
  * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}
- * - A voting module must implement {getVotes}
+ * - A voting module must implement {_getVotes}
  * - Additionanly, the {votingPeriod} must also be implemented
  *
  * _Available since v4.3._
  */
-abstract contract Governor is Context, ERC165, EIP712, IGovernor {
+abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver {
+    using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
     using SafeCast for uint256;
     using Timers for Timers.BlockNumber;
 
     bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");
+    bytes32 public constant EXTENDED_BALLOT_TYPEHASH =
+        keccak256("ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)");
 
     struct ProposalCore {
         Timers.BlockNumber voteStart;
@@ -40,13 +46,29 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
 
     mapping(uint256 => ProposalCore) private _proposals;
 
+    // This queue keeps track of the governor operating on itself. Calls to functions protected by the
+    // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute},
+    // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the
+    // execution of {onlyGovernance} protected calls can only be achieved through successful proposals.
+    DoubleEndedQueue.Bytes32Deque private _governanceCall;
+
     /**
-     * @dev Restrict access of functions to the governance executor, which may be the Governor itself or a timelock
-     * contract, as specified by {_executor}. This generally means that function with this modifier must be voted on and
-     * executed through the governance protocol.
+     * @dev Restricts a function so it can only be executed through governance proposals. For example, governance
+     * parameter setters in {GovernorSettings} are protected using this modifier.
+     *
+     * The governance executing address may be different from the Governor's own address, for example it could be a
+     * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these
+     * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus,
+     * for example, additional timelock proposers are not able to change governance parameters without going through the
+     * governance protocol (since v4.6).
      */
     modifier onlyGovernance() {
         require(_msgSender() == _executor(), "Governor: onlyGovernance");
+        if (_executor() != address(this)) {
+            bytes32 msgDataHash = keccak256(_msgData());
+            // loop until popping the expected operation - throw if deque is empty (operation not authorized)
+            while (_governanceCall.popFront() != msgDataHash) {}
+        }
         _;
     }
 
@@ -68,7 +90,17 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
      * @dev See {IERC165-supportsInterface}.
      */
     function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
-        return interfaceId == type(IGovernor).interfaceId || super.supportsInterface(interfaceId);
+        // In addition to the current interfaceId, also support previous version of the interfaceId that did not
+        // include the castVoteWithReasonAndParams() function as standard
+        return
+            interfaceId ==
+            (type(IGovernor).interfaceId ^
+                this.castVoteWithReasonAndParams.selector ^
+                this.castVoteWithReasonAndParamsBySig.selector ^
+                this.getVotesWithParams.selector) ||
+            interfaceId == type(IGovernor).interfaceId ||
+            interfaceId == type(IERC1155Receiver).interfaceId ||
+            super.supportsInterface(interfaceId);
     }
 
     /**
@@ -95,7 +127,7 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
      *
      * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the
      * same proposal (with same operation and same description) will have the same id if submitted on multiple governors
-     * accross multiple networks. This also means that in order to execute the same operation twice (on the same
+     * across multiple networks. This also means that in order to execute the same operation twice (on the same
      * governor) the proposer will have to change the description in order to avoid proposal id conflicts.
      */
     function hashProposal(
@@ -175,6 +207,15 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
      */
     function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);
 
+    /**
+     * @dev Get the voting weight of `account` at a specific `blockNumber`, for a vote as described by `params`.
+     */
+    function _getVotes(
+        address account,
+        uint256 blockNumber,
+        bytes memory params
+    ) internal view virtual returns (uint256);
+
     /**
      * @dev Register a vote with a given support and voting weight.
      *
@@ -184,9 +225,20 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         uint256 proposalId,
         address account,
         uint8 support,
-        uint256 weight
+        uint256 weight,
+        bytes memory params
     ) internal virtual;
 
+    /**
+     * @dev Default additional encoded parameters used by castVote methods that don't include them
+     *
+     * Note: Should be overridden by specific implementations to use an appropriate value, the
+     * meaning of the additional params, in the context of that implementation
+     */
+    function _defaultParams() internal view virtual returns (bytes memory) {
+        return "";
+    }
+
     /**
      * @dev See {IGovernor-propose}.
      */
@@ -197,8 +249,8 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         string memory description
     ) public virtual override returns (uint256) {
         require(
-            getVotes(msg.sender, block.number - 1) >= proposalThreshold(),
-            "GovernorCompatibilityBravo: proposer votes below proposal threshold"
+            getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),
+            "Governor: proposer votes below proposal threshold"
         );
 
         uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));
@@ -251,13 +303,15 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
 
         emit ProposalExecuted(proposalId);
 
+        _beforeExecute(proposalId, targets, values, calldatas, descriptionHash);
         _execute(proposalId, targets, values, calldatas, descriptionHash);
+        _afterExecute(proposalId, targets, values, calldatas, descriptionHash);
 
         return proposalId;
     }
 
     /**
-     * @dev Internal execution mechanism. Can be overriden to implement different execution mechanism
+     * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism
      */
     function _execute(
         uint256, /* proposalId */
@@ -273,6 +327,42 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         }
     }
 
+    /**
+     * @dev Hook before execution is triggered.
+     */
+    function _beforeExecute(
+        uint256, /* proposalId */
+        address[] memory targets,
+        uint256[] memory, /* values */
+        bytes[] memory calldatas,
+        bytes32 /*descriptionHash*/
+    ) internal virtual {
+        if (_executor() != address(this)) {
+            for (uint256 i = 0; i < targets.length; ++i) {
+                if (targets[i] == address(this)) {
+                    _governanceCall.pushBack(keccak256(calldatas[i]));
+                }
+            }
+        }
+    }
+
+    /**
+     * @dev Hook after execution is triggered.
+     */
+    function _afterExecute(
+        uint256, /* proposalId */
+        address[] memory, /* targets */
+        uint256[] memory, /* values */
+        bytes[] memory, /* calldatas */
+        bytes32 /*descriptionHash*/
+    ) internal virtual {
+        if (_executor() != address(this)) {
+            if (!_governanceCall.empty()) {
+                _governanceCall.clear();
+            }
+        }
+    }
+
     /**
      * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as
      * canceled to allow distinguishing it from executed proposals.
@@ -299,6 +389,24 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         return proposalId;
     }
 
+    /**
+     * @dev See {IGovernor-getVotes}.
+     */
+    function getVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
+        return _getVotes(account, blockNumber, _defaultParams());
+    }
+
+    /**
+     * @dev See {IGovernor-getVotesWithParams}.
+     */
+    function getVotesWithParams(
+        address account,
+        uint256 blockNumber,
+        bytes memory params
+    ) public view virtual override returns (uint256) {
+        return _getVotes(account, blockNumber, params);
+    }
+
     /**
      * @dev See {IGovernor-castVote}.
      */
@@ -319,6 +427,19 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         return _castVote(proposalId, voter, support, reason);
     }
 
+    /**
+     * @dev See {IGovernor-castVoteWithReasonAndParams}.
+     */
+    function castVoteWithReasonAndParams(
+        uint256 proposalId,
+        uint8 support,
+        string calldata reason,
+        bytes memory params
+    ) public virtual override returns (uint256) {
+        address voter = _msgSender();
+        return _castVote(proposalId, voter, support, reason, params);
+    }
+
     /**
      * @dev See {IGovernor-castVoteBySig}.
      */
@@ -338,9 +459,41 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         return _castVote(proposalId, voter, support, "");
     }
 
+    /**
+     * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.
+     */
+    function castVoteWithReasonAndParamsBySig(
+        uint256 proposalId,
+        uint8 support,
+        string calldata reason,
+        bytes memory params,
+        uint8 v,
+        bytes32 r,
+        bytes32 s
+    ) public virtual override returns (uint256) {
+        address voter = ECDSA.recover(
+            _hashTypedDataV4(
+                keccak256(
+                    abi.encode(
+                        EXTENDED_BALLOT_TYPEHASH,
+                        proposalId,
+                        support,
+                        keccak256(bytes(reason)),
+                        keccak256(params)
+                    )
+                )
+            ),
+            v,
+            r,
+            s
+        );
+
+        return _castVote(proposalId, voter, support, reason, params);
+    }
+
     /**
      * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
-     * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.
+     * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().
      *
      * Emits a {IGovernor-VoteCast} event.
      */
@@ -349,14 +502,34 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         address account,
         uint8 support,
         string memory reason
+    ) internal virtual returns (uint256) {
+        return _castVote(proposalId, account, support, reason, _defaultParams());
+    }
+
+    /**
+     * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
+     * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.
+     *
+     * Emits a {IGovernor-VoteCast} event.
+     */
+    function _castVote(
+        uint256 proposalId,
+        address account,
+        uint8 support,
+        string memory reason,
+        bytes memory params
     ) internal virtual returns (uint256) {
         ProposalCore storage proposal = _proposals[proposalId];
         require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active");
 
-        uint256 weight = getVotes(account, proposal.voteStart.getDeadline());
-        _countVote(proposalId, account, support, weight);
+        uint256 weight = _getVotes(account, proposal.voteStart.getDeadline(), params);
+        _countVote(proposalId, account, support, weight, params);
 
-        emit VoteCast(account, proposalId, support, weight, reason);
+        if (params.length == 0) {
+            emit VoteCast(account, proposalId, support, weight, reason);
+        } else {
+            emit VoteCastWithParams(account, proposalId, support, weight, reason, params);
+        }
 
         return weight;
     }
@@ -382,4 +555,42 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
     function _executor() internal view virtual returns (address) {
         return address(this);
     }
+
+    /**
+     * @dev See {IERC721Receiver-onERC721Received}.
+     */
+    function onERC721Received(
+        address,
+        address,
+        uint256,
+        bytes memory
+    ) public virtual override returns (bytes4) {
+        return this.onERC721Received.selector;
+    }
+
+    /**
+     * @dev See {IERC1155Receiver-onERC1155Received}.
+     */
+    function onERC1155Received(
+        address,
+        address,
+        uint256,
+        uint256,
+        bytes memory
+    ) public virtual override returns (bytes4) {
+        return this.onERC1155Received.selector;
+    }
+
+    /**
+     * @dev See {IERC1155Receiver-onERC1155BatchReceived}.
+     */
+    function onERC1155BatchReceived(
+        address,
+        address,
+        uint256[] memory,
+        uint256[] memory,
+        bytes memory
+    ) public virtual override returns (bytes4) {
+        return this.onERC1155BatchReceived.selector;
+    }
 }

+ 67 - 9
contracts/governance/IGovernor.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (governance/IGovernor.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (governance/IGovernor.sol)
 
 pragma solidity ^0.8.0;
 
@@ -48,12 +48,27 @@ abstract contract IGovernor is IERC165 {
     event ProposalExecuted(uint256 proposalId);
 
     /**
-     * @dev Emitted when a vote is cast.
+     * @dev Emitted when a vote is cast without params.
      *
-     * Note: `support` values should be seen as buckets. There interpretation depends on the voting module used.
+     * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
      */
     event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);
 
+    /**
+     * @dev Emitted when a vote is cast with params.
+     *
+     * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
+     * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.
+     */
+    event VoteCastWithParams(
+        address indexed voter,
+        uint256 proposalId,
+        uint8 support,
+        uint256 weight,
+        string reason,
+        bytes params
+    );
+
     /**
      * @notice module:core
      * @dev Name of the governor instance (used in building the ERC712 domain separator).
@@ -78,6 +93,12 @@ abstract contract IGovernor is IERC165 {
      * - `quorum=bravo` means that only For votes are counted towards quorum.
      * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.
      *
+     * If a counting module makes use of encoded `params`, it should  include this under a `params` key with a unique
+     * name that describes the behavior. For example:
+     *
+     * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.
+     * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.
+     *
      * NOTE: The string can be decoded by the standard
      * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]
      * JavaScript class.
@@ -90,9 +111,9 @@ abstract contract IGovernor is IERC165 {
      * @dev Hashing function used to (re)build the proposal id from the proposal details..
      */
     function hashProposal(
-        address[] calldata targets,
-        uint256[] calldata values,
-        bytes[] calldata calldatas,
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
         bytes32 descriptionHash
     ) public pure virtual returns (uint256);
 
@@ -137,8 +158,8 @@ abstract contract IGovernor is IERC165 {
      * @notice module:user-config
      * @dev Minimum number of cast voted required for a proposal to be successful.
      *
-     * Note: The `blockNumber` parameter corresponds to the snaphot used for counting vote. This allows to scale the
-     * quroum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).
+     * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the
+     * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).
      */
     function quorum(uint256 blockNumber) public view virtual returns (uint256);
 
@@ -151,6 +172,16 @@ abstract contract IGovernor is IERC165 {
      */
     function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);
 
+    /**
+     * @notice module:reputation
+     * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.
+     */
+    function getVotesWithParams(
+        address account,
+        uint256 blockNumber,
+        bytes memory params
+    ) public view virtual returns (uint256);
+
     /**
      * @notice module:voting
      * @dev Returns weither `account` has cast a vote on `proposalId`.
@@ -204,7 +235,19 @@ abstract contract IGovernor is IERC165 {
     ) public virtual returns (uint256 balance);
 
     /**
-     * @dev Cast a vote using the user cryptographic signature.
+     * @dev Cast a vote with a reason and additional encoded parameters
+     *
+     * Emits a {VoteCast} event.
+     */
+    function castVoteWithReasonAndParams(
+        uint256 proposalId,
+        uint8 support,
+        string calldata reason,
+        bytes memory params
+    ) public virtual returns (uint256 balance);
+
+    /**
+     * @dev Cast a vote using the user's cryptographic signature.
      *
      * Emits a {VoteCast} event.
      */
@@ -215,4 +258,19 @@ abstract contract IGovernor is IERC165 {
         bytes32 r,
         bytes32 s
     ) public virtual returns (uint256 balance);
+
+    /**
+     * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.
+     *
+     * Emits a {VoteCast} event.
+     */
+    function castVoteWithReasonAndParamsBySig(
+        uint256 proposalId,
+        uint8 support,
+        string calldata reason,
+        bytes memory params,
+        uint8 v,
+        bytes32 r,
+        bytes32 s
+    ) public virtual returns (uint256 balance);
 }

+ 1 - 1
contracts/governance/README.adoc

@@ -40,7 +40,7 @@ Other extensions can customize the behavior or interface in multiple ways.
 
 * {GovernorCompatibilityBravo}: Extends the interface to be fully `GovernorBravo`-compatible. Note that events are compatible regardless of whether this extension is included or not.
 
-* {GovernorSettings}: Manages some of the settings (voting delay, voting period duration, and proposal threshold) in a way that can be updated through a governance proposal, without requiering an upgrade.
+* {GovernorSettings}: Manages some of the settings (voting delay, voting period duration, and proposal threshold) in a way that can be updated through a governance proposal, without requiring an upgrade.
 
 * {GovernorPreventLateQuorum}: Ensures there is a minimum voting period after quorum is reached as a security protection against large voters.
 

+ 78 - 16
contracts/governance/TimelockController.sol

@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (governance/TimelockController.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (governance/TimelockController.sol)
 
 pragma solidity ^0.8.0;
 
 import "../access/AccessControl.sol";
+import "../token/ERC721/IERC721Receiver.sol";
+import "../token/ERC1155/IERC1155Receiver.sol";
 
 /**
  * @dev Contract module which acts as a timelocked controller. When set as the
@@ -20,10 +22,11 @@ import "../access/AccessControl.sol";
  *
  * _Available since v3.3._
  */
-contract TimelockController is AccessControl {
+contract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver {
     bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE");
     bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
     bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
+    bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE");
     uint256 internal constant _DONE_TIMESTAMP = uint256(1);
 
     mapping(bytes32 => uint256) private _timestamps;
@@ -58,7 +61,16 @@ contract TimelockController is AccessControl {
     event MinDelayChange(uint256 oldDuration, uint256 newDuration);
 
     /**
-     * @dev Initializes the contract with a given `minDelay`.
+     * @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.
+     *
+     * 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.
      */
     constructor(
         uint256 minDelay,
@@ -68,14 +80,16 @@ contract TimelockController is AccessControl {
         _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());
         _setupRole(TIMELOCK_ADMIN_ROLE, address(this));
 
-        // register proposers
+        // register proposers and cancellers
         for (uint256 i = 0; i < proposers.length; ++i) {
             _setupRole(PROPOSER_ROLE, proposers[i]);
+            _setupRole(CANCELLER_ROLE, proposers[i]);
         }
 
         // register executors
@@ -105,6 +119,13 @@ contract TimelockController is AccessControl {
      */
     receive() external payable {}
 
+    /**
+     * @dev See {IERC165-supportsInterface}.
+     */
+    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AccessControl) returns (bool) {
+        return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
+    }
+
     /**
      * @dev Returns whether an id correspond to a registered operation. This
      * includes both Pending, Ready and Done operations.
@@ -173,11 +194,11 @@ contract TimelockController is AccessControl {
     function hashOperationBatch(
         address[] calldata targets,
         uint256[] calldata values,
-        bytes[] calldata datas,
+        bytes[] calldata payloads,
         bytes32 predecessor,
         bytes32 salt
     ) public pure virtual returns (bytes32 hash) {
-        return keccak256(abi.encode(targets, values, datas, predecessor, salt));
+        return keccak256(abi.encode(targets, values, payloads, predecessor, salt));
     }
 
     /**
@@ -214,18 +235,18 @@ contract TimelockController is AccessControl {
     function scheduleBatch(
         address[] calldata targets,
         uint256[] calldata values,
-        bytes[] calldata datas,
+        bytes[] calldata payloads,
         bytes32 predecessor,
         bytes32 salt,
         uint256 delay
     ) public virtual onlyRole(PROPOSER_ROLE) {
         require(targets.length == values.length, "TimelockController: length mismatch");
-        require(targets.length == datas.length, "TimelockController: length mismatch");
+        require(targets.length == payloads.length, "TimelockController: length mismatch");
 
-        bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
+        bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
         _schedule(id, delay);
         for (uint256 i = 0; i < targets.length; ++i) {
-            emit CallScheduled(id, i, targets[i], values[i], datas[i], predecessor, delay);
+            emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);
         }
     }
 
@@ -243,9 +264,9 @@ contract TimelockController is AccessControl {
      *
      * Requirements:
      *
-     * - the caller must have the 'proposer' role.
+     * - the caller must have the 'canceller' role.
      */
-    function cancel(bytes32 id) public virtual onlyRole(PROPOSER_ROLE) {
+    function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {
         require(isOperationPending(id), "TimelockController: operation cannot be cancelled");
         delete _timestamps[id];
 
@@ -261,6 +282,9 @@ contract TimelockController is AccessControl {
      *
      * - the caller must have the 'executor' role.
      */
+    // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
+    // thus any modifications to the operation during reentrancy should be caught.
+    // slither-disable-next-line reentrancy-eth
     function execute(
         address target,
         uint256 value,
@@ -286,17 +310,17 @@ contract TimelockController is AccessControl {
     function executeBatch(
         address[] calldata targets,
         uint256[] calldata values,
-        bytes[] calldata datas,
+        bytes[] calldata payloads,
         bytes32 predecessor,
         bytes32 salt
     ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
         require(targets.length == values.length, "TimelockController: length mismatch");
-        require(targets.length == datas.length, "TimelockController: length mismatch");
+        require(targets.length == payloads.length, "TimelockController: length mismatch");
 
-        bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
+        bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
         _beforeCall(id, predecessor);
         for (uint256 i = 0; i < targets.length; ++i) {
-            _call(id, i, targets[i], values[i], datas[i]);
+            _call(id, i, targets[i], values[i], payloads[i]);
         }
         _afterCall(id);
     }
@@ -350,4 +374,42 @@ contract TimelockController is AccessControl {
         emit MinDelayChange(_minDelay, newDelay);
         _minDelay = newDelay;
     }
+
+    /**
+     * @dev See {IERC721Receiver-onERC721Received}.
+     */
+    function onERC721Received(
+        address,
+        address,
+        uint256,
+        bytes memory
+    ) public virtual override returns (bytes4) {
+        return this.onERC721Received.selector;
+    }
+
+    /**
+     * @dev See {IERC1155Receiver-onERC1155Received}.
+     */
+    function onERC1155Received(
+        address,
+        address,
+        uint256,
+        uint256,
+        bytes memory
+    ) public virtual override returns (bytes4) {
+        return this.onERC1155Received.selector;
+    }
+
+    /**
+     * @dev See {IERC1155Receiver-onERC1155BatchReceived}.
+     */
+    function onERC1155BatchReceived(
+        address,
+        address,
+        uint256[] memory,
+        uint256[] memory,
+        bytes memory
+    ) public virtual override returns (bytes4) {
+        return this.onERC1155BatchReceived.selector;
+    }
 }

+ 3 - 2
contracts/governance/compatibility/GovernorCompatibilityBravo.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (governance/compatibility/GovernorCompatibilityBravo.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (governance/compatibility/GovernorCompatibilityBravo.sol)
 
 pragma solidity ^0.8.0;
 
@@ -265,7 +265,8 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
         uint256 proposalId,
         address account,
         uint8 support,
-        uint256 weight
+        uint256 weight,
+        bytes memory // params
     ) internal virtual override {
         ProposalDetails storage details = _proposalDetails[proposalId];
         Receipt storage receipt = details.receipts[account];

+ 3 - 2
contracts/governance/extensions/GovernorCountingSimple.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorCountingSimple.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorCountingSimple.sol)
 
 pragma solidity ^0.8.0;
 
@@ -86,7 +86,8 @@ abstract contract GovernorCountingSimple is Governor {
         uint256 proposalId,
         address account,
         uint8 support,
-        uint256 weight
+        uint256 weight,
+        bytes memory // params
     ) internal virtual override {
         ProposalVote storage proposalvote = _proposalVotes[proposalId];
 

+ 4 - 3
contracts/governance/extensions/GovernorPreventLateQuorum.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorPreventLateQuorum.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorPreventLateQuorum.sol)
 
 pragma solidity ^0.8.0;
 
@@ -57,9 +57,10 @@ abstract contract GovernorPreventLateQuorum is Governor {
         uint256 proposalId,
         address account,
         uint8 support,
-        string memory reason
+        string memory reason,
+        bytes memory params
     ) internal virtual override returns (uint256) {
-        uint256 result = super._castVote(proposalId, account, support, reason);
+        uint256 result = super._castVote(proposalId, account, support, reason, params);
 
         Timers.BlockNumber storage extendedDeadline = _extendedDeadlines[proposalId];
 

+ 5 - 58
contracts/governance/extensions/GovernorTimelockCompound.sol

@@ -1,65 +1,12 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorTimelockCompound.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorTimelockCompound.sol)
 
 pragma solidity ^0.8.0;
 
 import "./IGovernorTimelock.sol";
 import "../Governor.sol";
 import "../../utils/math/SafeCast.sol";
-
-/**
- * https://github.com/compound-finance/compound-protocol/blob/master/contracts/Timelock.sol[Compound's timelock] interface
- */
-interface ICompoundTimelock {
-    receive() external payable;
-
-    // solhint-disable-next-line func-name-mixedcase
-    function GRACE_PERIOD() external view returns (uint256);
-
-    // solhint-disable-next-line func-name-mixedcase
-    function MINIMUM_DELAY() external view returns (uint256);
-
-    // solhint-disable-next-line func-name-mixedcase
-    function MAXIMUM_DELAY() external view returns (uint256);
-
-    function admin() external view returns (address);
-
-    function pendingAdmin() external view returns (address);
-
-    function delay() external view returns (uint256);
-
-    function queuedTransactions(bytes32) external view returns (bool);
-
-    function setDelay(uint256) external;
-
-    function acceptAdmin() external;
-
-    function setPendingAdmin(address) external;
-
-    function queueTransaction(
-        address target,
-        uint256 value,
-        string memory signature,
-        bytes memory data,
-        uint256 eta
-    ) external returns (bytes32);
-
-    function cancelTransaction(
-        address target,
-        uint256 value,
-        string memory signature,
-        bytes memory data,
-        uint256 eta
-    ) external;
-
-    function executeTransaction(
-        address target,
-        uint256 value,
-        string memory signature,
-        bytes memory data,
-        uint256 eta
-    ) external payable returns (bytes memory);
-}
+import "../../vendor/compound/ICompoundTimelock.sol";
 
 /**
  * @dev Extension of {Governor} that binds the execution process to a Compound Timelock. This adds a delay, enforced by
@@ -105,7 +52,7 @@ abstract contract GovernorTimelockCompound is IGovernorTimelock, Governor {
     }
 
     /**
-     * @dev Overriden version of the {Governor-state} function with added support for the `Queued` and `Expired` status.
+     * @dev Overridden version of the {Governor-state} function with added support for the `Queued` and `Expired` status.
      */
     function state(uint256 proposalId) public view virtual override(IGovernor, Governor) returns (ProposalState) {
         ProposalState status = super.state(proposalId);
@@ -167,7 +114,7 @@ abstract contract GovernorTimelockCompound is IGovernorTimelock, Governor {
     }
 
     /**
-     * @dev Overriden execute function that run the already queued proposal through the timelock.
+     * @dev Overridden execute function that run the already queued proposal through the timelock.
      */
     function _execute(
         uint256 proposalId,
@@ -185,7 +132,7 @@ abstract contract GovernorTimelockCompound is IGovernorTimelock, Governor {
     }
 
     /**
-     * @dev Overriden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
+     * @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
      * been queued.
      */
     function _cancel(

+ 7 - 4
contracts/governance/extensions/GovernorTimelockControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorTimelockControl.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorTimelockControl.sol)
 
 pragma solidity ^0.8.0;
 
@@ -47,7 +47,7 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
     }
 
     /**
-     * @dev Overriden version of the {Governor-state} function with added support for the `Queued` status.
+     * @dev Overridden version of the {Governor-state} function with added support for the `Queued` status.
      */
     function state(uint256 proposalId) public view virtual override(IGovernor, Governor) returns (ProposalState) {
         ProposalState status = super.state(proposalId);
@@ -107,7 +107,7 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
     }
 
     /**
-     * @dev Overriden execute function that run the already queued proposal through the timelock.
+     * @dev Overridden execute function that run the already queued proposal through the timelock.
      */
     function _execute(
         uint256, /* proposalId */
@@ -120,9 +120,12 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
     }
 
     /**
-     * @dev Overriden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
+     * @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
      * been queued.
      */
+    // This function can reenter through the external call to the timelock, but we assume the timelock is trusted and
+    // well behaved (according to TimelockController) and this will not happen.
+    // slither-disable-next-line reentrancy-no-eth
     function _cancel(
         address[] memory targets,
         uint256[] memory values,

+ 7 - 3
contracts/governance/extensions/GovernorVotes.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotes.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotes.sol)
 
 pragma solidity ^0.8.0;
 
@@ -19,9 +19,13 @@ abstract contract GovernorVotes is Governor {
     }
 
     /**
-     * Read the voting weight from the token's built in snapshot mechanism (see {IGovernor-getVotes}).
+     * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).
      */
-    function getVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
+    function _getVotes(
+        address account,
+        uint256 blockNumber,
+        bytes memory /*params*/
+    ) internal view virtual override returns (uint256) {
         return token.getPastVotes(account, blockNumber);
     }
 }

+ 7 - 3
contracts/governance/extensions/GovernorVotesComp.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorVotesComp.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (governance/extensions/GovernorVotesComp.sol)
 
 pragma solidity ^0.8.0;
 
@@ -19,9 +19,13 @@ abstract contract GovernorVotesComp is Governor {
     }
 
     /**
-     * Read the voting weight from the token's built in snapshot mechanism (see {IGovernor-getVotes}).
+     * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}).
      */
-    function getVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
+    function _getVotes(
+        address account,
+        uint256 blockNumber,
+        bytes memory /*params*/
+    ) internal view virtual override returns (uint256) {
         return token.getPriorVotes(account, blockNumber);
     }
 }

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/Votes.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (governance/utils/Votes.sol)
 pragma solidity ^0.8.0;
 
 import "../../utils/Context.sol";
@@ -207,5 +207,5 @@ abstract contract Votes is IVotes, Context, EIP712 {
     /**
      * @dev Must return the voting units held by an account.
      */
-    function _getVotingUnits(address) internal virtual returns (uint256);
+    function _getVotingUnits(address) internal view virtual returns (uint256);
 }

+ 2 - 2
contracts/interfaces/IERC2981.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/IERC2981.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)
 
 pragma solidity ^0.8.0;
 
@@ -16,7 +16,7 @@ import "../utils/introspection/IERC165.sol";
 interface IERC2981 is IERC165 {
     /**
      * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
-     * exchange. The royalty amount is denominated and should be payed in that same unit of exchange.
+     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
      */
     function royaltyInfo(uint256 tokenId, uint256 salePrice)
         external

+ 22 - 0
contracts/mocks/AccessControlCrossChainMock.sol

@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.4;
+
+import "../access/AccessControlCrossChain.sol";
+import "../crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol";
+
+contract AccessControlCrossChainMock is AccessControlCrossChain, CrossChainEnabledArbitrumL2 {
+    constructor() {
+        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
+    }
+
+    function setRoleAdmin(bytes32 roleId, bytes32 adminRoleId) public {
+        _setRoleAdmin(roleId, adminRoleId);
+    }
+
+    function senderProtected(bytes32 roleId) public onlyRole(roleId) {}
+
+    function crossChainRoleAlias(bytes32 role) public pure virtual returns (bytes32) {
+        return _crossChainRoleAlias(role);
+    }
+}

+ 58 - 0
contracts/mocks/DoubleEndedQueueMock.sol

@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../utils/structs/DoubleEndedQueue.sol";
+
+// Bytes32Deque
+contract Bytes32DequeMock {
+    using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
+
+    event OperationResult(bytes32 value);
+
+    DoubleEndedQueue.Bytes32Deque private _vector;
+
+    function pushBack(bytes32 value) public {
+        _vector.pushBack(value);
+    }
+
+    function pushFront(bytes32 value) public {
+        _vector.pushFront(value);
+    }
+
+    function popFront() public returns (bytes32) {
+        bytes32 value = _vector.popFront();
+        emit OperationResult(value);
+        return value;
+    }
+
+    function popBack() public returns (bytes32) {
+        bytes32 value = _vector.popBack();
+        emit OperationResult(value);
+        return value;
+    }
+
+    function front() public view returns (bytes32) {
+        return _vector.front();
+    }
+
+    function back() public view returns (bytes32) {
+        return _vector.back();
+    }
+
+    function at(uint256 i) public view returns (bytes32) {
+        return _vector.at(i);
+    }
+
+    function clear() public {
+        _vector.clear();
+    }
+
+    function length() public view returns (uint256) {
+        return _vector.length();
+    }
+
+    function empty() public view returns (bool) {
+        return _vector.empty();
+    }
+}

+ 22 - 0
contracts/mocks/ERC1155URIStorageMock.sol

@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "./ERC1155Mock.sol";
+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) {
+        return ERC1155URIStorage.uri(tokenId);
+    }
+
+    function setURI(uint256 tokenId, string memory _tokenURI) public {
+        _setURI(tokenId, _tokenURI);
+    }
+
+    function setBaseURI(string memory baseURI) public {
+        _setBaseURI(baseURI);
+    }
+}

+ 8 - 0
contracts/mocks/ERC20DecimalsMock.sol

@@ -18,4 +18,12 @@ contract ERC20DecimalsMock is ERC20 {
     function decimals() public view virtual override returns (uint8) {
         return _decimals;
     }
+
+    function mint(address account, uint256 amount) public {
+        _mint(account, amount);
+    }
+
+    function burn(address account, uint256 amount) public {
+        _burn(account, amount);
+    }
 }

+ 87 - 1
contracts/mocks/EnumerableMapMock.sol

@@ -4,7 +4,8 @@ pragma solidity ^0.8.0;
 
 import "../utils/structs/EnumerableMap.sol";
 
-contract EnumerableMapMock {
+// UintToAddressMap
+contract UintToAddressMapMock {
     using EnumerableMap for EnumerableMap.UintToAddressMap;
 
     event OperationResult(bool result);
@@ -45,3 +46,88 @@ contract EnumerableMapMock {
         return _map.get(key, errorMessage);
     }
 }
+
+// AddressToUintMap
+contract AddressToUintMapMock {
+    using EnumerableMap for EnumerableMap.AddressToUintMap;
+
+    event OperationResult(bool result);
+
+    EnumerableMap.AddressToUintMap private _map;
+
+    function contains(address key) public view returns (bool) {
+        return _map.contains(key);
+    }
+
+    function set(address key, uint256 value) public {
+        bool result = _map.set(key, value);
+        emit OperationResult(result);
+    }
+
+    function remove(address key) public {
+        bool result = _map.remove(key);
+        emit OperationResult(result);
+    }
+
+    function length() public view returns (uint256) {
+        return _map.length();
+    }
+
+    function at(uint256 index) public view returns (address key, uint256 value) {
+        return _map.at(index);
+    }
+
+    function tryGet(address key) public view returns (bool, uint256) {
+        return _map.tryGet(key);
+    }
+
+    function get(address key) public view returns (uint256) {
+        return _map.get(key);
+    }
+
+    function getWithMessage(address key, string calldata errorMessage) public view returns (uint256) {
+        return _map.get(key, errorMessage);
+    }
+}
+
+contract Bytes32ToBytes32MapMock {
+    using EnumerableMap for EnumerableMap.Bytes32ToBytes32Map;
+
+    event OperationResult(bool result);
+
+    EnumerableMap.Bytes32ToBytes32Map private _map;
+
+    function contains(bytes32 key) public view returns (bool) {
+        return _map.contains(key);
+    }
+
+    function set(bytes32 key, bytes32 value) public {
+        bool result = _map.set(key, value);
+        emit OperationResult(result);
+    }
+
+    function remove(bytes32 key) public {
+        bool result = _map.remove(key);
+        emit OperationResult(result);
+    }
+
+    function length() public view returns (uint256) {
+        return _map.length();
+    }
+
+    function at(uint256 index) public view returns (bytes32 key, bytes32 value) {
+        return _map.at(index);
+    }
+
+    function tryGet(bytes32 key) public view returns (bool, bytes32) {
+        return _map.tryGet(key);
+    }
+
+    function get(bytes32 key) public view returns (bytes32) {
+        return _map.get(key);
+    }
+
+    function getWithMessage(bytes32 key, string calldata errorMessage) public view returns (bytes32) {
+        return _map.get(key, errorMessage);
+    }
+}

+ 0 - 10
contracts/mocks/GovernorCompMock.sol

@@ -28,14 +28,4 @@ contract GovernorCompMock is GovernorVotesComp, GovernorCountingSimple {
     ) public returns (uint256 proposalId) {
         return _cancel(targets, values, calldatas, salt);
     }
-
-    function getVotes(address account, uint256 blockNumber)
-        public
-        view
-        virtual
-        override(IGovernor, GovernorVotesComp)
-        returns (uint256)
-    {
-        return super.getVotes(account, blockNumber);
-    }
 }

+ 0 - 10
contracts/mocks/GovernorCompatibilityBravoMock.sol

@@ -124,16 +124,6 @@ contract GovernorCompatibilityBravoMock is
         return super._cancel(targets, values, calldatas, salt);
     }
 
-    function getVotes(address account, uint256 blockNumber)
-        public
-        view
-        virtual
-        override(IGovernor, GovernorVotesComp)
-        returns (uint256)
-    {
-        return super.getVotes(account, blockNumber);
-    }
-
     function _executor() internal view virtual override(Governor, GovernorTimelockCompound) returns (address) {
         return super._executor();
     }

+ 0 - 10
contracts/mocks/GovernorMock.sol

@@ -35,16 +35,6 @@ contract GovernorMock is
         return _cancel(targets, values, calldatas, salt);
     }
 
-    function getVotes(address account, uint256 blockNumber)
-        public
-        view
-        virtual
-        override(IGovernor, GovernorVotes)
-        returns (uint256)
-    {
-        return super.getVotes(account, blockNumber);
-    }
-
     function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
         return super.proposalThreshold();
     }

+ 3 - 2
contracts/mocks/GovernorPreventLateQuorumMock.sol

@@ -53,8 +53,9 @@ contract GovernorPreventLateQuorumMock is
         uint256 proposalId,
         address account,
         uint8 support,
-        string memory reason
+        string memory reason,
+        bytes memory params
     ) internal virtual override(Governor, GovernorPreventLateQuorum) returns (uint256) {
-        return super._castVote(proposalId, account, support, reason);
+        return super._castVote(proposalId, account, support, reason, params);
     }
 }

+ 0 - 10
contracts/mocks/GovernorTimelockCompoundMock.sol

@@ -92,16 +92,6 @@ contract GovernorTimelockCompoundMock is
         return super._cancel(targets, values, calldatas, salt);
     }
 
-    function getVotes(address account, uint256 blockNumber)
-        public
-        view
-        virtual
-        override(IGovernor, GovernorVotes)
-        returns (uint256)
-    {
-        return super.getVotes(account, blockNumber);
-    }
-
     function _executor() internal view virtual override(Governor, GovernorTimelockCompound) returns (address) {
         return super._executor();
     }

+ 2 - 10
contracts/mocks/GovernorTimelockControlMock.sol

@@ -92,17 +92,9 @@ contract GovernorTimelockControlMock is
         return super._cancel(targets, values, calldatas, descriptionHash);
     }
 
-    function getVotes(address account, uint256 blockNumber)
-        public
-        view
-        virtual
-        override(IGovernor, GovernorVotes)
-        returns (uint256)
-    {
-        return super.getVotes(account, blockNumber);
-    }
-
     function _executor() internal view virtual override(Governor, GovernorTimelockControl) returns (address) {
         return super._executor();
     }
+
+    function nonGovernanceFunction() external {}
 }

+ 0 - 10
contracts/mocks/GovernorVoteMock.sol

@@ -28,14 +28,4 @@ contract GovernorVoteMocks is GovernorVotes, GovernorCountingSimple {
     ) public returns (uint256 proposalId) {
         return _cancel(targets, values, calldatas, salt);
     }
-
-    function getVotes(address account, uint256 blockNumber)
-        public
-        view
-        virtual
-        override(IGovernor, GovernorVotes)
-        returns (uint256)
-    {
-        return super.getVotes(account, blockNumber);
-    }
 }

+ 61 - 0
contracts/mocks/GovernorWithParamsMock.sol

@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../governance/extensions/GovernorCountingSimple.sol";
+import "../governance/extensions/GovernorVotes.sol";
+
+contract GovernorWithParamsMock is GovernorVotes, GovernorCountingSimple {
+    event CountParams(uint256 uintParam, string strParam);
+
+    constructor(string memory name_, IVotes token_) Governor(name_) GovernorVotes(token_) {}
+
+    function quorum(uint256) public pure override returns (uint256) {
+        return 0;
+    }
+
+    function votingDelay() public pure override returns (uint256) {
+        return 4;
+    }
+
+    function votingPeriod() public pure override returns (uint256) {
+        return 16;
+    }
+
+    function _getVotes(
+        address account,
+        uint256 blockNumber,
+        bytes memory params
+    ) internal view virtual 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) {
+            (reduction, ) = abi.decode(params, (uint256, string));
+        }
+        // reverts on overflow
+        return super._getVotes(account, blockNumber, params) - reduction;
+    }
+
+    function _countVote(
+        uint256 proposalId,
+        address account,
+        uint8 support,
+        uint256 weight,
+        bytes memory params
+    ) internal virtual override(Governor, GovernorCountingSimple) {
+        if (params.length > 0) {
+            (uint256 _uintParam, string memory _strParam) = abi.decode(params, (uint256, string));
+            emit CountParams(_uintParam, _strParam);
+        }
+        return super._countVote(proposalId, account, support, weight, params);
+    }
+
+    function cancel(
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        bytes32 salt
+    ) public returns (uint256 proposalId) {
+        return _cancel(targets, values, calldatas, salt);
+    }
+}

+ 29 - 0
contracts/mocks/InitializableMock.sol

@@ -59,3 +59,32 @@ contract ConstructorInitializableMock is Initializable {
         onlyInitializingRan = true;
     }
 }
+
+contract ReinitializerMock is Initializable {
+    uint256 public counter;
+
+    function initialize() public initializer {
+        doStuff();
+    }
+
+    function reinitialize(uint8 i) public reinitializer(i) {
+        doStuff();
+    }
+
+    function nestedReinitialize(uint8 i, uint8 j) public reinitializer(i) {
+        reinitialize(j);
+    }
+
+    function chainReinitialize(uint8 i, uint8 j) public {
+        reinitialize(i);
+        reinitialize(j);
+    }
+
+    function disableInitializers() public {
+        _disableInitializers();
+    }
+
+    function doStuff() public onlyInitializing {
+        counter++;
+    }
+}

+ 1 - 1
contracts/mocks/VotesMock.sol

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

+ 106 - 0
contracts/mocks/crosschain/bridges.sol

@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../../utils/Address.sol";
+import "../../vendor/polygon/IFxMessageProcessor.sol";
+
+abstract contract BaseRelayMock {
+    // needed to parse custom errors
+    error NotCrossChainCall();
+    error InvalidCrossChainSender(address sender, address expected);
+
+    address internal _currentSender;
+
+    function relayAs(
+        address target,
+        bytes calldata data,
+        address sender
+    ) external virtual {
+        address previousSender = _currentSender;
+
+        _currentSender = sender;
+
+        (bool success, bytes memory returndata) = target.call(data);
+        Address.verifyCallResult(success, returndata, "low-level call reverted");
+
+        _currentSender = previousSender;
+    }
+}
+
+/**
+ * AMB
+ */
+contract BridgeAMBMock is BaseRelayMock {
+    function messageSender() public view returns (address) {
+        return _currentSender;
+    }
+}
+
+/**
+ * Arbitrum
+ */
+contract BridgeArbitrumL1Mock is BaseRelayMock {
+    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
+    address public immutable inbox = address(new BridgeArbitrumL1Inbox());
+    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
+    address public immutable outbox = address(new BridgeArbitrumL1Outbox());
+
+    function activeOutbox() public view returns (address) {
+        return outbox;
+    }
+
+    function currentSender() public view returns (address) {
+        return _currentSender;
+    }
+}
+
+contract BridgeArbitrumL1Inbox {
+    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
+    address public immutable bridge = msg.sender;
+}
+
+contract BridgeArbitrumL1Outbox {
+    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
+    address public immutable bridge = msg.sender;
+
+    function l2ToL1Sender() public view returns (address) {
+        return BridgeArbitrumL1Mock(bridge).currentSender();
+    }
+}
+
+contract BridgeArbitrumL2Mock is BaseRelayMock {
+    function isTopLevelCall() public view returns (bool) {
+        return _currentSender != address(0);
+    }
+
+    function wasMyCallersAddressAliased() public pure returns (bool) {
+        return true;
+    }
+
+    function myCallersAddressWithoutAliasing() public view returns (address) {
+        return _currentSender;
+    }
+}
+
+/**
+ * Optimism
+ */
+contract BridgeOptimismMock is BaseRelayMock {
+    function xDomainMessageSender() public view returns (address) {
+        return _currentSender;
+    }
+}
+
+/**
+ * Polygon
+ */
+contract BridgePolygonChildMock is BaseRelayMock {
+    function relayAs(
+        address target,
+        bytes calldata data,
+        address sender
+    ) external override {
+        IFxMessageProcessor(target).processMessageFromRoot(0, sender, data);
+    }
+}

+ 54 - 0
contracts/mocks/crosschain/receivers.sol

@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.4;
+
+import "../../access/Ownable.sol";
+import "../../crosschain/amb/CrossChainEnabledAMB.sol";
+import "../../crosschain/arbitrum/CrossChainEnabledArbitrumL1.sol";
+import "../../crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol";
+import "../../crosschain/optimism/CrossChainEnabledOptimism.sol";
+import "../../crosschain/polygon/CrossChainEnabledPolygonChild.sol";
+
+abstract contract Receiver is CrossChainEnabled {
+    // we don't use Ownable because it messes up testing for the upgradeable contracts
+    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
+    address public immutable owner = msg.sender;
+
+    function crossChainRestricted() external onlyCrossChain {}
+
+    function crossChainOwnerRestricted() external onlyCrossChainSender(owner) {}
+}
+
+/**
+ * AMB
+ */
+contract CrossChainEnabledAMBMock is Receiver, CrossChainEnabledAMB {
+    /// @custom:oz-upgrades-unsafe-allow constructor
+    constructor(address bridge) CrossChainEnabledAMB(bridge) {}
+}
+
+/**
+ * Arbitrum
+ */
+contract CrossChainEnabledArbitrumL1Mock is Receiver, CrossChainEnabledArbitrumL1 {
+    /// @custom:oz-upgrades-unsafe-allow constructor
+    constructor(address bridge) CrossChainEnabledArbitrumL1(bridge) {}
+}
+
+contract CrossChainEnabledArbitrumL2Mock is Receiver, CrossChainEnabledArbitrumL2 {}
+
+/**
+ * Optimism
+ */
+contract CrossChainEnabledOptimismMock is Receiver, CrossChainEnabledOptimism {
+    /// @custom:oz-upgrades-unsafe-allow constructor
+    constructor(address bridge) CrossChainEnabledOptimism(bridge) {}
+}
+
+/**
+ * Polygon
+ */
+contract CrossChainEnabledPolygonChildMock is Receiver, CrossChainEnabledPolygonChild {
+    /// @custom:oz-upgrades-unsafe-allow constructor
+    constructor(address bridge) CrossChainEnabledPolygonChild(bridge) {}
+}

+ 0 - 9
contracts/mocks/wizard/MyGovernor1.sol

@@ -40,15 +40,6 @@ contract MyGovernor1 is
         return super.quorum(blockNumber);
     }
 
-    function getVotes(address account, uint256 blockNumber)
-        public
-        view
-        override(IGovernor, GovernorVotes)
-        returns (uint256)
-    {
-        return super.getVotes(account, blockNumber);
-    }
-
     function state(uint256 proposalId) public view override(Governor, GovernorTimelockControl) returns (ProposalState) {
         return super.state(proposalId);
     }

+ 0 - 9
contracts/mocks/wizard/MyGovernor2.sol

@@ -46,15 +46,6 @@ contract MyGovernor2 is
         return super.quorum(blockNumber);
     }
 
-    function getVotes(address account, uint256 blockNumber)
-        public
-        view
-        override(IGovernor, GovernorVotes)
-        returns (uint256)
-    {
-        return super.getVotes(account, blockNumber);
-    }
-
     function state(uint256 proposalId) public view override(Governor, GovernorTimelockControl) returns (ProposalState) {
         return super.state(proposalId);
     }

+ 0 - 9
contracts/mocks/wizard/MyGovernor3.sol

@@ -44,15 +44,6 @@ contract MyGovernor is
         return super.quorum(blockNumber);
     }
 
-    function getVotes(address account, uint256 blockNumber)
-        public
-        view
-        override(IGovernor, GovernorVotes)
-        returns (uint256)
-    {
-        return super.getVotes(account, blockNumber);
-    }
-
     function state(uint256 proposalId)
         public
         view

+ 1 - 1
contracts/package.json

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

+ 4 - 4
contracts/proxy/Proxy.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
 
 pragma solidity ^0.8.0;
 
@@ -45,7 +45,7 @@ abstract contract Proxy {
     }
 
     /**
-     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
+     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
      * and {_fallback} should delegate.
      */
     function _implementation() internal view virtual returns (address);
@@ -53,7 +53,7 @@ abstract contract Proxy {
     /**
      * @dev Delegates the current call to the address returned by `_implementation()`.
      *
-     * This function does not return to its internall call site, it will return directly to the external caller.
+     * This function does not return to its internal call site, it will return directly to the external caller.
      */
     function _fallback() internal virtual {
         _beforeFallback();
@@ -80,7 +80,7 @@ abstract contract Proxy {
      * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
      * call, or as part of the Solidity `fallback` or `receive` functions.
      *
-     * If overriden should call `super._beforeFallback()`.
+     * If overridden should call `super._beforeFallback()`.
      */
     function _beforeFallback() internal virtual {}
 }

+ 1 - 1
contracts/proxy/README.adoc

@@ -23,7 +23,7 @@ CAUTION: Using upgradeable proxies correctly and securely is a difficult task th
 
 A different family of proxies are beacon proxies. This pattern, popularized by Dharma, allows multiple proxies to be upgraded to a different implementation in a single transaction.
 
-- {BeaconProxy}: A proxy that retreives its implementation from a beacon contract.
+- {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.

+ 87 - 18
contracts/proxy/utils/Initializable.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)
 
-pragma solidity ^0.8.0;
+pragma solidity ^0.8.2;
 
 import "../../utils/Address.sol";
 
@@ -11,6 +11,26 @@ import "../../utils/Address.sol";
  * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
  * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
  *
+ * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
+ * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
+ * case an upgrade adds a module that needs to be initialized.
+ *
+ * For example:
+ *
+ * [.hljs-theme-light.nopadding]
+ * ```
+ * contract MyToken is ERC20Upgradeable {
+ *     function initialize() initializer public {
+ *         __ERC20_init("MyToken", "MTK");
+ *     }
+ * }
+ * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
+ *     function initializeV2() reinitializer(2) public {
+ *         __ERC20Permit_init("MyToken");
+ *     }
+ * }
+ * ```
+ *
  * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
  * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
  *
@@ -22,21 +42,24 @@ import "../../utils/Address.sol";
  * Avoid leaving a contract uninitialized.
  *
  * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
- * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
- * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
+ * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
+ * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
  *
  * [.hljs-theme-light.nopadding]
  * ```
  * /// @custom:oz-upgrades-unsafe-allow constructor
- * constructor() initializer {}
+ * constructor() {
+ *     _disableInitializers();
+ * }
  * ```
  * ====
  */
 abstract contract Initializable {
     /**
      * @dev Indicates that the contract has been initialized.
+     * @custom:oz-retyped-from bool
      */
-    bool private _initialized;
+    uint8 private _initialized;
 
     /**
      * @dev Indicates that the contract is in the process of being initialized.
@@ -44,37 +67,83 @@ abstract contract Initializable {
     bool private _initializing;
 
     /**
-     * @dev Modifier to protect an initializer function from being invoked twice.
+     * @dev Triggered when the contract has been initialized or reinitialized.
      */
-    modifier initializer() {
-        // If the contract is initializing we ignore whether _initialized is set in order to support multiple
-        // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
-        // contract may have been reentered.
-        require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");
+    event Initialized(uint8 version);
 
-        bool isTopLevelCall = !_initializing;
+    /**
+     * @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)`.
+     */
+    modifier initializer() {
+        bool isTopLevelCall = _setInitializedVersion(1);
         if (isTopLevelCall) {
             _initializing = true;
-            _initialized = true;
         }
-
         _;
+        if (isTopLevelCall) {
+            _initializing = false;
+            emit Initialized(1);
+        }
+    }
 
+    /**
+     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
+     * 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.
+     *
+     * 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.
+     */
+    modifier reinitializer(uint8 version) {
+        bool isTopLevelCall = _setInitializedVersion(version);
+        if (isTopLevelCall) {
+            _initializing = true;
+        }
+        _;
         if (isTopLevelCall) {
             _initializing = false;
+            emit Initialized(version);
         }
     }
 
     /**
      * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
-     * {initializer} modifier, directly or indirectly.
+     * {initializer} and {reinitializer} modifiers, directly or indirectly.
      */
     modifier onlyInitializing() {
         require(_initializing, "Initializable: contract is not initializing");
         _;
     }
 
-    function _isConstructor() private view returns (bool) {
-        return !Address.isContract(address(this));
+    /**
+     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
+     * 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.
+     */
+    function _disableInitializers() internal virtual {
+        _setInitializedVersion(type(uint8).max);
+    }
+
+    function _setInitializedVersion(uint8 version) private returns (bool) {
+        // If the contract is initializing we ignore whether _initialized is set in order to support multiple
+        // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level
+        // of initializers, because in other contexts the contract may have been reentered.
+        if (_initializing) {
+            require(
+                version == 1 && !Address.isContract(address(this)),
+                "Initializable: contract is already initialized"
+            );
+            return false;
+        } else {
+            require(_initialized < version, "Initializable: contract is already initialized");
+            _initialized = version;
+            return true;
+        }
     }
 }

+ 51 - 4
contracts/token/ERC1155/ERC1155.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC1155/ERC1155.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/ERC1155.sol)
 
 pragma solidity ^0.8.0;
 
@@ -167,8 +167,10 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
         require(to != address(0), "ERC1155: transfer to the zero address");
 
         address operator = _msgSender();
+        uint256[] memory ids = _asSingletonArray(id);
+        uint256[] memory amounts = _asSingletonArray(amount);
 
-        _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);
+        _beforeTokenTransfer(operator, from, to, ids, amounts, data);
 
         uint256 fromBalance = _balances[id][from];
         require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
@@ -179,6 +181,8 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
 
         emit TransferSingle(operator, from, to, id, amount);
 
+        _afterTokenTransfer(operator, from, to, ids, amounts, data);
+
         _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
     }
 
@@ -220,6 +224,8 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
 
         emit TransferBatch(operator, from, to, ids, amounts);
 
+        _afterTokenTransfer(operator, from, to, ids, amounts, data);
+
         _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
     }
 
@@ -266,12 +272,16 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
         require(to != address(0), "ERC1155: mint to the zero address");
 
         address operator = _msgSender();
+        uint256[] memory ids = _asSingletonArray(id);
+        uint256[] memory amounts = _asSingletonArray(amount);
 
-        _beforeTokenTransfer(operator, address(0), to, _asSingletonArray(id), _asSingletonArray(amount), data);
+        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
 
         _balances[id][to] += amount;
         emit TransferSingle(operator, address(0), to, id, amount);
 
+        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);
+
         _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);
     }
 
@@ -303,6 +313,8 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
 
         emit TransferBatch(operator, address(0), to, ids, amounts);
 
+        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);
+
         _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
     }
 
@@ -322,8 +334,10 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
         require(from != address(0), "ERC1155: burn from the zero address");
 
         address operator = _msgSender();
+        uint256[] memory ids = _asSingletonArray(id);
+        uint256[] memory amounts = _asSingletonArray(amount);
 
-        _beforeTokenTransfer(operator, from, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");
+        _beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
 
         uint256 fromBalance = _balances[id][from];
         require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
@@ -332,6 +346,8 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
         }
 
         emit TransferSingle(operator, from, address(0), id, amount);
+
+        _afterTokenTransfer(operator, from, address(0), ids, amounts, "");
     }
 
     /**
@@ -365,6 +381,8 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
         }
 
         emit TransferBatch(operator, from, address(0), ids, amounts);
+
+        _afterTokenTransfer(operator, from, address(0), ids, amounts, "");
     }
 
     /**
@@ -411,6 +429,35 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
         bytes memory data
     ) internal virtual {}
 
+    /**
+     * @dev Hook that is called after any token transfer. This includes minting
+     * and burning, as well as batched variants.
+     *
+     * The same hook is called on both single and batched variants. For single
+     * transfers, the length of the `id` and `amount` arrays will be 1.
+     *
+     * Calling conditions (for each `id` and `amount` pair):
+     *
+     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
+     * of token type `id` will be  transferred to `to`.
+     * - When `from` is zero, `amount` tokens of token type `id` will be minted
+     * for `to`.
+     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
+     * will be burned.
+     * - `from` and `to` are never both zero.
+     * - `ids` and `amounts` have the same, non-zero length.
+     *
+     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
+     */
+    function _afterTokenTransfer(
+        address operator,
+        address from,
+        address to,
+        uint256[] memory ids,
+        uint256[] memory amounts,
+        bytes memory data
+    ) internal virtual {}
+
     function _doSafeTransferAcceptanceCheck(
         address operator,
         address from,

+ 2 - 0
contracts/token/ERC1155/README.adoc

@@ -36,6 +36,8 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel
 
 {{ERC1155Supply}}
 
+{{ERC1155URIStorage}}
+
 == Presets
 
 These contracts are preconfigured combinations of the above features. They can be used through inheritance or as models to copy and paste their source code.

+ 8 - 2
contracts/token/ERC1155/extensions/ERC1155Supply.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/ERC1155Supply.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol)
 
 pragma solidity ^0.8.0;
 
@@ -51,7 +51,13 @@ abstract contract ERC1155Supply is ERC1155 {
 
         if (to == address(0)) {
             for (uint256 i = 0; i < ids.length; ++i) {
-                _totalSupply[ids[i]] -= amounts[i];
+                uint256 id = ids[i];
+                uint256 amount = amounts[i];
+                uint256 supply = _totalSupply[id];
+                require(supply >= amount, "ERC1155: burn amount exceeds totalSupply");
+                unchecked {
+                    _totalSupply[id] = supply - amount;
+                }
             }
         }
     }

+ 63 - 0
contracts/token/ERC1155/extensions/ERC1155URIStorage.sol

@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155URIStorage.sol)
+
+pragma solidity ^0.8.0;
+
+import "../../../utils/Strings.sol";
+import "../ERC1155.sol";
+
+/**
+ * @dev ERC1155 token with storage based token URI management.
+ * Inspired by the ERC721URIStorage extension
+ *
+ * _Available since v4.6._
+ */
+abstract contract ERC1155URIStorage is ERC1155 {
+    using Strings for uint256;
+
+    // Optional base URI
+    string private _baseURI = "";
+
+    // Optional mapping for token URIs
+    mapping(uint256 => string) private _tokenURIs;
+
+    /**
+     * @dev See {IERC1155MetadataURI-uri}.
+     *
+     * This implementation returns the concatenation of the `_baseURI`
+     * and the token-specific uri if the latter is set
+     *
+     * This enables the following behaviors:
+     *
+     * - if `_tokenURIs[tokenId]` is set, then the result is the concatenation
+     *   of `_baseURI` and `_tokenURIs[tokenId]` (keep in mind that `_baseURI`
+     *   is empty per default);
+     *
+     * - if `_tokenURIs[tokenId]` is NOT set then we fallback to `super.uri()`
+     *   which in most cases will contain `ERC1155._uri`;
+     *
+     * - if `_tokenURIs[tokenId]` is NOT set, and if the parents do not have a
+     *   uri value set, then the result is empty.
+     */
+    function uri(uint256 tokenId) public view virtual override returns (string memory) {
+        string memory tokenURI = _tokenURIs[tokenId];
+
+        // If token URI is set, concatenate base URI and tokenURI (via abi.encodePacked).
+        return bytes(tokenURI).length > 0 ? string(abi.encodePacked(_baseURI, tokenURI)) : super.uri(tokenId);
+    }
+
+    /**
+     * @dev Sets `tokenURI` as the tokenURI of `tokenId`.
+     */
+    function _setURI(uint256 tokenId, string memory tokenURI) internal virtual {
+        _tokenURIs[tokenId] = tokenURI;
+        emit URI(uri(tokenId), tokenId);
+    }
+
+    /**
+     * @dev Sets `baseURI` as the `_baseURI` for all tokens
+     */
+    function _setBaseURI(string memory baseURI) internal virtual {
+        _baseURI = baseURI;
+    }
+}

+ 4 - 4
contracts/token/ERC20/ERC20.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)
 
 pragma solidity ^0.8.0;
 
@@ -180,7 +180,7 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
      */
     function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
         address owner = _msgSender();
-        _approve(owner, spender, _allowances[owner][spender] + addedValue);
+        _approve(owner, spender, allowance(owner, spender) + addedValue);
         return true;
     }
 
@@ -200,7 +200,7 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
      */
     function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
         address owner = _msgSender();
-        uint256 currentAllowance = _allowances[owner][spender];
+        uint256 currentAllowance = allowance(owner, spender);
         require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
         unchecked {
             _approve(owner, spender, currentAllowance - subtractedValue);
@@ -320,7 +320,7 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
     }
 
     /**
-     * @dev Spend `amount` form the allowance of `owner` toward `spender`.
+     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
      *
      * Does not update the allowance amount in case of infinite allowance.
      * Revert if not enough allowance is available.

+ 15 - 15
contracts/token/ERC20/IERC20.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
 
 pragma solidity ^0.8.0;
 
@@ -7,6 +7,20 @@ pragma solidity ^0.8.0;
  * @dev Interface of the ERC20 standard as defined in the EIP.
  */
 interface IERC20 {
+    /**
+     * @dev Emitted when `value` tokens are moved from one account (`from`) to
+     * another (`to`).
+     *
+     * Note that `value` may be zero.
+     */
+    event Transfer(address indexed from, address indexed to, uint256 value);
+
+    /**
+     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
+     * a call to {approve}. `value` is the new allowance.
+     */
+    event Approval(address indexed owner, address indexed spender, uint256 value);
+
     /**
      * @dev Returns the amount of tokens in existence.
      */
@@ -65,18 +79,4 @@ interface IERC20 {
         address to,
         uint256 amount
     ) external returns (bool);
-
-    /**
-     * @dev Emitted when `value` tokens are moved from one account (`from`) to
-     * another (`to`).
-     *
-     * Note that `value` may be zero.
-     */
-    event Transfer(address indexed from, address indexed to, uint256 value);
-
-    /**
-     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
-     * a call to {approve}. `value` is the new allowance.
-     */
-    event Approval(address indexed owner, address indexed spender, uint256 value);
 }

+ 1 - 1
contracts/token/ERC20/README.adoc

@@ -7,7 +7,7 @@ This set of interfaces, contracts, and utilities are all related to the https://
 
 TIP: For an overview of ERC20 tokens and a walk through on how to create a token contract read our xref:ROOT:erc20.adoc[ERC20 guide].
 
-There a few core contracts that implement the behavior specified in the EIP:
+There are a few core contracts that implement the behavior specified in the EIP:
 
 * {IERC20}: the interface all ERC20 implementations should conform to.
 * {IERC20Metadata}: the extended ERC20 interface including the <<ERC20-name,`name`>>, <<ERC20-symbol,`symbol`>> and <<ERC20-decimals,`decimals`>> functions.

+ 7 - 6
contracts/token/ERC20/extensions/ERC20FlashMint.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20FlashMint.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/ERC20FlashMint.sol)
 
 pragma solidity ^0.8.0;
 
@@ -22,7 +22,7 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
     /**
      * @dev Returns the maximum amount of tokens available for loan.
      * @param token The address of the token that is requested.
-     * @return The amont of token that can be loaned.
+     * @return The amount of token that can be loaned.
      */
     function maxFlashLoan(address token) public view virtual override returns (uint256) {
         return token == address(this) ? type(uint256).max - ERC20.totalSupply() : 0;
@@ -55,8 +55,11 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
      * supported.
      * @param amount The amount of tokens to be loaned.
      * @param data An arbitrary datafield that is passed to the receiver.
-     * @return `true` is the flash loan was successful.
+     * @return `true` if the flash loan was successful.
      */
+    // This function can reenter, but it doesn't pose a risk because it always preserves the property that the amount
+    // minted at the beginning is always recovered and burned at the end, or else the entire function will revert.
+    // slither-disable-next-line reentrancy-no-eth
     function flashLoan(
         IERC3156FlashBorrower receiver,
         address token,
@@ -70,9 +73,7 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
             receiver.onFlashLoan(msg.sender, token, amount, fee, data) == _RETURN_VALUE,
             "ERC20FlashMint: invalid return value"
         );
-        uint256 currentAllowance = allowance(address(receiver), address(this));
-        require(currentAllowance >= amount + fee, "ERC20FlashMint: allowance does not allow refund");
-        _approve(address(receiver), address(this), currentAllowance - amount - fee);
+        _spendAllowance(address(receiver), address(this), amount + fee);
         _burn(address(receiver), amount + fee);
         return true;
     }

+ 2 - 2
contracts/token/ERC20/extensions/ERC20Snapshot.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Snapshot.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/ERC20Snapshot.sol)
 
 pragma solidity ^0.8.0;
 
@@ -22,7 +22,7 @@ import "../../../utils/Counters.sol";
  * and the account address.
  *
  * NOTE: Snapshot policy can be customized by overriding the {_getCurrentSnapshotId} method. For example, having it
- * return `block.number` will trigger the creation of snapshot at the begining of each new block. When overridding this
+ * return `block.number` will trigger the creation of snapshot at the beginning of each new block. When overriding this
  * function, be careful about the monotonicity of its result. Non-monotonic snapshot ids will break the contract.
  *
  * Implementing snapshots for every block using this method will incur significant gas costs. For a gas-efficient

+ 13 - 2
contracts/token/ERC20/extensions/ERC20Wrapper.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Wrapper.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/ERC20Wrapper.sol)
 
 pragma solidity ^0.8.0;
 
@@ -22,6 +22,17 @@ abstract contract ERC20Wrapper is ERC20 {
         underlying = underlyingToken;
     }
 
+    /**
+     * @dev See {ERC20-decimals}.
+     */
+    function decimals() public view virtual override returns (uint8) {
+        try IERC20Metadata(address(underlying)).decimals() returns (uint8 value) {
+            return value;
+        } catch {
+            return super.decimals();
+        }
+    }
+
     /**
      * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.
      */
@@ -41,7 +52,7 @@ abstract contract ERC20Wrapper is ERC20 {
     }
 
     /**
-     * @dev Mint wrapped token to cover any underlyingTokens that would have been transfered by mistake. Internal
+     * @dev Mint wrapped token to cover any underlyingTokens that would have been transferred by mistake. Internal
      * function that can be exposed with access control if desired.
      */
     function _recover(address account) internal virtual returns (uint256) {

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-ERC20Permit.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/draft-ERC20Permit.sol)
 
 pragma solidity ^0.8.0;
 
@@ -25,8 +25,16 @@ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
     mapping(address => Counters.Counter) private _nonces;
 
     // solhint-disable-next-line var-name-mixedcase
-    bytes32 private immutable _PERMIT_TYPEHASH =
+    bytes32 private constant _PERMIT_TYPEHASH =
         keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
+    /**
+     * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
+     * However, to ensure consistency with the upgradeable transpiler, we will continue
+     * to reserve a slot.
+     * @custom:oz-renamed-from _PERMIT_TYPEHASH
+     */
+    // solhint-disable-next-line var-name-mixedcase
+    bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;
 
     /**
      * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/ERC721.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)
 
 pragma solidity ^0.8.0;
 
@@ -100,7 +100,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
     /**
      * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
      * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
-     * by default, can be overriden in child contracts.
+     * by default, can be overridden in child contracts.
      */
     function _baseURI() internal view virtual returns (string memory) {
         return "";
@@ -232,7 +232,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
     function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
         require(_exists(tokenId), "ERC721: operator query for nonexistent token");
         address owner = ERC721.ownerOf(tokenId);
-        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
+        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
     }
 
     /**

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)
 
 pragma solidity ^0.8.0;
 
@@ -38,6 +38,26 @@ interface IERC721 is IERC165 {
      */
     function ownerOf(uint256 tokenId) external view returns (address owner);
 
+    /**
+     * @dev Safely transfers `tokenId` token from `from` to `to`.
+     *
+     * Requirements:
+     *
+     * - `from` cannot be the zero address.
+     * - `to` cannot be the zero address.
+     * - `tokenId` token must exist and be owned by `from`.
+     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
+     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
+     *
+     * Emits a {Transfer} event.
+     */
+    function safeTransferFrom(
+        address from,
+        address to,
+        uint256 tokenId,
+        bytes calldata data
+    ) external;
+
     /**
      * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
      * are aware of the ERC721 protocol to prevent tokens from being forever locked.
@@ -93,15 +113,6 @@ interface IERC721 is IERC165 {
      */
     function approve(address to, uint256 tokenId) external;
 
-    /**
-     * @dev Returns the account approved for `tokenId` token.
-     *
-     * Requirements:
-     *
-     * - `tokenId` must exist.
-     */
-    function getApproved(uint256 tokenId) external view returns (address operator);
-
     /**
      * @dev Approve or remove `operator` as an operator for the caller.
      * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
@@ -115,29 +126,18 @@ interface IERC721 is IERC165 {
     function setApprovalForAll(address operator, bool _approved) external;
 
     /**
-     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
+     * @dev Returns the account approved for `tokenId` token.
      *
-     * See {setApprovalForAll}
+     * Requirements:
+     *
+     * - `tokenId` must exist.
      */
-    function isApprovedForAll(address owner, address operator) external view returns (bool);
+    function getApproved(uint256 tokenId) external view returns (address operator);
 
     /**
-     * @dev Safely transfers `tokenId` token from `from` to `to`.
-     *
-     * Requirements:
-     *
-     * - `from` cannot be the zero address.
-     * - `to` cannot be the zero address.
-     * - `tokenId` token must exist and be owned by `from`.
-     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
-     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
+     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
      *
-     * Emits a {Transfer} event.
+     * See {setApprovalForAll}
      */
-    function safeTransferFrom(
-        address from,
-        address to,
-        uint256 tokenId,
-        bytes calldata data
-    ) external;
+    function isApprovedForAll(address owner, address operator) external view returns (bool);
 }

+ 2 - 2
contracts/token/ERC721/IERC721Receiver.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
 
 pragma solidity ^0.8.0;
 
@@ -16,7 +16,7 @@ interface IERC721Receiver {
      * It must return its Solidity selector to confirm the token transfer.
      * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
      *
-     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
+     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
      */
     function onERC721Received(
         address operator,

+ 2 - 2
contracts/token/ERC721/extensions/draft-ERC721Votes.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/draft-ERC721Votes.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/extensions/draft-ERC721Votes.sol)
 
 pragma solidity ^0.8.0;
 
@@ -34,7 +34,7 @@ abstract contract ERC721Votes is ERC721, Votes {
     /**
      * @dev Returns the balance of `account`.
      */
-    function _getVotingUnits(address account) internal virtual override returns (uint256) {
+    function _getVotingUnits(address account) internal view virtual override returns (uint256) {
         return balanceOf(account);
     }
 }

+ 6 - 25
contracts/token/ERC777/ERC777.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC777/ERC777.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC777/ERC777.sol)
 
 pragma solidity ^0.8.0;
 
@@ -144,16 +144,7 @@ contract ERC777 is Context, IERC777, IERC20 {
      * Also emits a {Sent} event.
      */
     function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
-        require(recipient != address(0), "ERC777: transfer to the zero address");
-
-        address from = _msgSender();
-
-        _callTokensToSend(from, from, recipient, amount, "", "");
-
-        _move(from, from, recipient, amount, "", "");
-
-        _callTokensReceived(from, from, recipient, amount, "", "", false);
-
+        _send(_msgSender(), recipient, amount, "", "", false);
         return true;
     }
 
@@ -286,19 +277,9 @@ contract ERC777 is Context, IERC777, IERC20 {
         address recipient,
         uint256 amount
     ) public virtual override returns (bool) {
-        require(recipient != address(0), "ERC777: transfer to the zero address");
-        require(holder != address(0), "ERC777: transfer from the zero address");
-
         address spender = _msgSender();
-
-        _callTokensToSend(spender, holder, recipient, amount, "", "");
-
         _spendAllowance(holder, spender, amount);
-
-        _move(spender, holder, recipient, amount, "", "");
-
-        _callTokensReceived(spender, holder, recipient, amount, "", "", false);
-
+        _send(holder, recipient, amount, "", "", false);
         return true;
     }
 
@@ -386,8 +367,8 @@ contract ERC777 is Context, IERC777, IERC20 {
         bytes memory operatorData,
         bool requireReceptionAck
     ) internal virtual {
-        require(from != address(0), "ERC777: send from the zero address");
-        require(to != address(0), "ERC777: send to the zero address");
+        require(from != address(0), "ERC777: transfer from the zero address");
+        require(to != address(0), "ERC777: transfer to the zero address");
 
         address operator = _msgSender();
 
@@ -521,7 +502,7 @@ contract ERC777 is Context, IERC777, IERC20 {
     }
 
     /**
-     * @dev Spend `amount` form the allowance of `owner` toward `spender`.
+     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
      *
      * Does not update the allowance amount in case of infinite allowance.
      * Revert if not enough allowance is available.

+ 25 - 9
contracts/token/ERC777/IERC777.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC777/IERC777.sol)
 
 pragma solidity ^0.8.0;
 
@@ -13,6 +13,30 @@ pragma solidity ^0.8.0;
  * {ERC1820Implementer}.
  */
 interface IERC777 {
+    /**
+     * @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`.
+     *
+     * Note that some additional user `data` and `operatorData` can be logged in the event.
+     */
+    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
+
+    /**
+     * @dev Emitted when `operator` destroys `amount` tokens from `account`.
+     *
+     * Note that some additional user `data` and `operatorData` can be logged in the event.
+     */
+    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
+
+    /**
+     * @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`
+     */
+    event RevokedOperator(address indexed operator, address indexed tokenHolder);
+
     /**
      * @dev Returns the name of the token.
      */
@@ -182,12 +206,4 @@ interface IERC777 {
         bytes data,
         bytes operatorData
     );
-
-    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
-
-    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
-
-    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
-
-    event RevokedOperator(address indexed operator, address indexed tokenHolder);
 }

+ 2 - 8
contracts/token/common/ERC2981.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (token/common/ERC2981.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (token/common/ERC2981.sol)
 
 pragma solidity ^0.8.0;
 
@@ -40,13 +40,7 @@ abstract contract ERC2981 is IERC2981, ERC165 {
     /**
      * @inheritdoc IERC2981
      */
-    function royaltyInfo(uint256 _tokenId, uint256 _salePrice)
-        external
-        view
-        virtual
-        override
-        returns (address, uint256)
-    {
+    function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {
         RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];
 
         if (royalty.receiver == address(0)) {

+ 2 - 0
contracts/utils/README.adoc

@@ -88,6 +88,8 @@ Note that, in all cases, accounts simply _declare_ their interfaces, but they ar
 
 {{EnumerableSet}}
 
+{{DoubleEndedQueue}}
+
 {{Checkpoints}}
 
 == Libraries

+ 7 - 2
contracts/utils/cryptography/MerkleProof.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)
 
 pragma solidity ^0.8.0;
 
@@ -11,6 +11,11 @@ pragma solidity ^0.8.0;
  * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
  *
  * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
+ *
+ * WARNING: You should avoid using leaf values that are 64 bytes long prior to
+ * hashing, or use a hash function other than keccak256 for hashing leaves.
+ * This is because the concatenation of a sorted pair of internal nodes in
+ * the merkle tree could be reinterpreted as a leaf value.
  */
 library MerkleProof {
     /**
@@ -28,7 +33,7 @@ library MerkleProof {
     }
 
     /**
-     * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up
+     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
      * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
      * hash matches the root of the tree. When processing the proof, the pairs
      * of leafs & pre-images are assumed to be sorted.

+ 5 - 5
contracts/utils/introspection/IERC1820Registry.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC1820Registry.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (utils/introspection/IERC1820Registry.sol)
 
 pragma solidity ^0.8.0;
 
@@ -18,6 +18,10 @@ pragma solidity ^0.8.0;
  * For an in-depth explanation and source code analysis, see the EIP text.
  */
 interface IERC1820Registry {
+    event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);
+
+    event ManagerChanged(address indexed account, address indexed newManager);
+
     /**
      * @dev Sets `newManager` as the manager for `account`. A manager of an
      * account is able to set interface implementers for it.
@@ -109,8 +113,4 @@ interface IERC1820Registry {
      * @return True if `account` implements `interfaceId`, false otherwise.
      */
     function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);
-
-    event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);
-
-    event ManagerChanged(address indexed account, address indexed newManager);
 }

+ 2 - 2
contracts/utils/math/SafeMath.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)
 
 pragma solidity ^0.8.0;
 
@@ -28,7 +28,7 @@ library SafeMath {
     }
 
     /**
-     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
+     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
      *
      * _Available since v3.4._
      */

+ 170 - 0
contracts/utils/structs/DoubleEndedQueue.sol

@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)
+pragma solidity ^0.8.4;
+
+import "../math/SafeCast.sol";
+
+/**
+ * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of
+ * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and
+ * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that
+ * the existing queue contents are left in storage.
+ *
+ * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be
+ * used in storage, and not in memory.
+ * ```
+ * DoubleEndedQueue.Bytes32Deque queue;
+ * ```
+ *
+ * _Available since v4.6._
+ */
+library DoubleEndedQueue {
+    /**
+     * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.
+     */
+    error Empty();
+
+    /**
+     * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.
+     */
+    error OutOfBounds();
+
+    /**
+     * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end
+     * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely
+     * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.
+     *
+     * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to
+     * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and
+     * lead to unexpected behavior.
+     *
+     * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at
+     * data[end - 1].
+     */
+    struct Bytes32Deque {
+        int128 _begin;
+        int128 _end;
+        mapping(int128 => bytes32) _data;
+    }
+
+    /**
+     * @dev Inserts an item at the end of the queue.
+     */
+    function pushBack(Bytes32Deque storage deque, bytes32 value) internal {
+        int128 backIndex = deque._end;
+        deque._data[backIndex] = value;
+        unchecked {
+            deque._end = backIndex + 1;
+        }
+    }
+
+    /**
+     * @dev Removes the item at the end of the queue and returns it.
+     *
+     * Reverts with `Empty` if the queue is empty.
+     */
+    function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {
+        if (empty(deque)) revert Empty();
+        int128 backIndex;
+        unchecked {
+            backIndex = deque._end - 1;
+        }
+        value = deque._data[backIndex];
+        delete deque._data[backIndex];
+        deque._end = backIndex;
+    }
+
+    /**
+     * @dev Inserts an item at the beginning of the queue.
+     */
+    function pushFront(Bytes32Deque storage deque, bytes32 value) internal {
+        int128 frontIndex;
+        unchecked {
+            frontIndex = deque._begin - 1;
+        }
+        deque._data[frontIndex] = value;
+        deque._begin = frontIndex;
+    }
+
+    /**
+     * @dev Removes the item at the beginning of the queue and returns it.
+     *
+     * Reverts with `Empty` if the queue is empty.
+     */
+    function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {
+        if (empty(deque)) revert Empty();
+        int128 frontIndex = deque._begin;
+        value = deque._data[frontIndex];
+        delete deque._data[frontIndex];
+        unchecked {
+            deque._begin = frontIndex + 1;
+        }
+    }
+
+    /**
+     * @dev Returns the item at the beginning of the queue.
+     *
+     * Reverts with `Empty` if the queue is empty.
+     */
+    function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {
+        if (empty(deque)) revert Empty();
+        int128 frontIndex = deque._begin;
+        return deque._data[frontIndex];
+    }
+
+    /**
+     * @dev Returns the item at the end of the queue.
+     *
+     * Reverts with `Empty` if the queue is empty.
+     */
+    function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {
+        if (empty(deque)) revert Empty();
+        int128 backIndex;
+        unchecked {
+            backIndex = deque._end - 1;
+        }
+        return deque._data[backIndex];
+    }
+
+    /**
+     * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at
+     * `length(deque) - 1`.
+     *
+     * Reverts with `OutOfBounds` if the index is out of bounds.
+     */
+    function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {
+        // int256(deque._begin) is a safe upcast
+        int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));
+        if (idx >= deque._end) revert OutOfBounds();
+        return deque._data[idx];
+    }
+
+    /**
+     * @dev Resets the queue back to being empty.
+     *
+     * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses
+     * out on potential gas refunds.
+     */
+    function clear(Bytes32Deque storage deque) internal {
+        deque._begin = 0;
+        deque._end = 0;
+    }
+
+    /**
+     * @dev Returns the number of items in the queue.
+     */
+    function length(Bytes32Deque storage deque) internal view returns (uint256) {
+        // The interface preserves the invariant that begin <= end so we assume this will not overflow.
+        // We also assume there are at most int256.max items in the queue.
+        unchecked {
+            return uint256(int256(deque._end) - int256(deque._begin));
+        }
+    }
+
+    /**
+     * @dev Returns true if the queue is empty.
+     */
+    function empty(Bytes32Deque storage deque) internal view returns (bool) {
+        return deque._end <= deque._begin;
+    }
+}

+ 125 - 28
contracts/utils/structs/EnumerableMap.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableMap.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/EnumerableMap.sol)
 
 pragma solidity ^0.8.0;
 
@@ -26,8 +26,11 @@ import "./EnumerableSet.sol";
  * }
  * ```
  *
- * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are
- * supported.
+ * The following map types are supported:
+ *
+ * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0
+ * - `address -> uint256` (`AddressToUintMap`) since v4.6.0
+ * - `bytes32 -> bytes32` (`Bytes32ToBytes32`) since v4.6.0
  */
 library EnumerableMap {
     using EnumerableSet for EnumerableSet.Bytes32Set;
@@ -41,7 +44,7 @@ library EnumerableMap {
     // This means that we can only create new EnumerableMaps for types that fit
     // in bytes32.
 
-    struct Map {
+    struct Bytes32ToBytes32Map {
         // Storage of keys
         EnumerableSet.Bytes32Set _keys;
         mapping(bytes32 => bytes32) _values;
@@ -54,11 +57,11 @@ library EnumerableMap {
      * Returns true if the key was added to the map, that is if it was not
      * already present.
      */
-    function _set(
-        Map storage map,
+    function set(
+        Bytes32ToBytes32Map storage map,
         bytes32 key,
         bytes32 value
-    ) private returns (bool) {
+    ) internal returns (bool) {
         map._values[key] = value;
         return map._keys.add(key);
     }
@@ -68,7 +71,7 @@ library EnumerableMap {
      *
      * Returns true if the key was removed from the map, that is if it was present.
      */
-    function _remove(Map storage map, bytes32 key) private returns (bool) {
+    function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
         delete map._values[key];
         return map._keys.remove(key);
     }
@@ -76,14 +79,14 @@ library EnumerableMap {
     /**
      * @dev Returns true if the key is in the map. O(1).
      */
-    function _contains(Map storage map, bytes32 key) private view returns (bool) {
+    function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
         return map._keys.contains(key);
     }
 
     /**
      * @dev Returns the number of key-value pairs in the map. O(1).
      */
-    function _length(Map storage map) private view returns (uint256) {
+    function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
         return map._keys.length();
     }
 
@@ -97,7 +100,7 @@ library EnumerableMap {
      *
      * - `index` must be strictly less than {length}.
      */
-    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
+    function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) {
         bytes32 key = map._keys.at(index);
         return (key, map._values[key]);
     }
@@ -106,10 +109,10 @@ library EnumerableMap {
      * @dev Tries to returns the value associated with `key`.  O(1).
      * Does not revert if `key` is not in the map.
      */
-    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
+    function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {
         bytes32 value = map._values[key];
         if (value == bytes32(0)) {
-            return (_contains(map, key), bytes32(0));
+            return (contains(map, key), bytes32(0));
         } else {
             return (true, value);
         }
@@ -122,9 +125,9 @@ library EnumerableMap {
      *
      * - `key` must be in the map.
      */
-    function _get(Map storage map, bytes32 key) private view returns (bytes32) {
+    function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
         bytes32 value = map._values[key];
-        require(value != 0 || _contains(map, key), "EnumerableMap: nonexistent key");
+        require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key");
         return value;
     }
 
@@ -134,20 +137,20 @@ library EnumerableMap {
      * CAUTION: This function is deprecated because it requires allocating memory for the error
      * message unnecessarily. For custom revert reasons use {_tryGet}.
      */
-    function _get(
-        Map storage map,
+    function get(
+        Bytes32ToBytes32Map storage map,
         bytes32 key,
         string memory errorMessage
-    ) private view returns (bytes32) {
+    ) internal view returns (bytes32) {
         bytes32 value = map._values[key];
-        require(value != 0 || _contains(map, key), errorMessage);
+        require(value != 0 || contains(map, key), errorMessage);
         return value;
     }
 
     // UintToAddressMap
 
     struct UintToAddressMap {
-        Map _inner;
+        Bytes32ToBytes32Map _inner;
     }
 
     /**
@@ -162,7 +165,7 @@ library EnumerableMap {
         uint256 key,
         address value
     ) internal returns (bool) {
-        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
+        return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
     }
 
     /**
@@ -171,21 +174,21 @@ library EnumerableMap {
      * Returns true if the key was removed from the map, that is if it was present.
      */
     function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
-        return _remove(map._inner, bytes32(key));
+        return remove(map._inner, bytes32(key));
     }
 
     /**
      * @dev Returns true if the key is in the map. O(1).
      */
     function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
-        return _contains(map._inner, bytes32(key));
+        return contains(map._inner, bytes32(key));
     }
 
     /**
      * @dev Returns the number of elements in the map. O(1).
      */
     function length(UintToAddressMap storage map) internal view returns (uint256) {
-        return _length(map._inner);
+        return length(map._inner);
     }
 
     /**
@@ -198,7 +201,7 @@ library EnumerableMap {
      * - `index` must be strictly less than {length}.
      */
     function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
-        (bytes32 key, bytes32 value) = _at(map._inner, index);
+        (bytes32 key, bytes32 value) = at(map._inner, index);
         return (uint256(key), address(uint160(uint256(value))));
     }
 
@@ -209,7 +212,7 @@ library EnumerableMap {
      * _Available since v3.4._
      */
     function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
-        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
+        (bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
         return (success, address(uint160(uint256(value))));
     }
 
@@ -221,7 +224,7 @@ library EnumerableMap {
      * - `key` must be in the map.
      */
     function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
-        return address(uint160(uint256(_get(map._inner, bytes32(key)))));
+        return address(uint160(uint256(get(map._inner, bytes32(key)))));
     }
 
     /**
@@ -235,6 +238,100 @@ library EnumerableMap {
         uint256 key,
         string memory errorMessage
     ) internal view returns (address) {
-        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
+        return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));
+    }
+
+    // AddressToUintMap
+
+    struct AddressToUintMap {
+        Bytes32ToBytes32Map _inner;
+    }
+
+    /**
+     * @dev Adds a key-value pair to a map, or updates the value for an existing
+     * key. O(1).
+     *
+     * Returns true if the key was added to the map, that is if it was not
+     * already present.
+     */
+    function set(
+        AddressToUintMap storage map,
+        address key,
+        uint256 value
+    ) internal returns (bool) {
+        return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));
+    }
+
+    /**
+     * @dev Removes a value from a set. O(1).
+     *
+     * Returns true if the key was removed from the map, that is if it was present.
+     */
+    function remove(AddressToUintMap storage map, address key) internal returns (bool) {
+        return remove(map._inner, bytes32(uint256(uint160(key))));
+    }
+
+    /**
+     * @dev Returns true if the key is in the map. O(1).
+     */
+    function contains(AddressToUintMap storage map, address key) internal view returns (bool) {
+        return contains(map._inner, bytes32(uint256(uint160(key))));
+    }
+
+    /**
+     * @dev Returns the number of elements in the map. O(1).
+     */
+    function length(AddressToUintMap storage map) internal view returns (uint256) {
+        return length(map._inner);
+    }
+
+    /**
+     * @dev Returns the element stored at position `index` in the set. O(1).
+     * Note that there are no guarantees on the ordering of values inside the
+     * array, and it may change when more values are added or removed.
+     *
+     * Requirements:
+     *
+     * - `index` must be strictly less than {length}.
+     */
+    function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) {
+        (bytes32 key, bytes32 value) = at(map._inner, index);
+        return (address(uint160(uint256(key))), uint256(value));
+    }
+
+    /**
+     * @dev Tries to returns the value associated with `key`.  O(1).
+     * Does not revert if `key` is not in the map.
+     *
+     * _Available since v3.4._
+     */
+    function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {
+        (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
+        return (success, uint256(value));
+    }
+
+    /**
+     * @dev Returns the value associated with `key`.  O(1).
+     *
+     * Requirements:
+     *
+     * - `key` must be in the map.
+     */
+    function get(AddressToUintMap storage map, address key) internal view returns (uint256) {
+        return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
+    }
+
+    /**
+     * @dev Same as {get}, with a custom error message when `key` is not in the map.
+     *
+     * CAUTION: This function is deprecated because it requires allocating memory for the error
+     * message unnecessarily. For custom revert reasons use {tryGet}.
+     */
+    function get(
+        AddressToUintMap storage map,
+        address key,
+        string memory errorMessage
+    ) internal view returns (uint256) {
+        return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));
     }
 }

+ 4 - 4
contracts/utils/structs/EnumerableSet.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)
+// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/EnumerableSet.sol)
 
 pragma solidity ^0.8.0;
 
@@ -83,12 +83,12 @@ library EnumerableSet {
             uint256 lastIndex = set._values.length - 1;
 
             if (lastIndex != toDeleteIndex) {
-                bytes32 lastvalue = set._values[lastIndex];
+                bytes32 lastValue = set._values[lastIndex];
 
                 // Move the last value to the index where the value to delete is
-                set._values[toDeleteIndex] = lastvalue;
+                set._values[toDeleteIndex] = lastValue;
                 // Update the index for the moved value
-                set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
+                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
             }
 
             // Delete the slot where the moved value was stored

+ 49 - 0
contracts/vendor/amb/IAMB.sol

@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (vendor/amb/IAMB.sol)
+pragma solidity ^0.8.0;
+
+interface IAMB {
+    event UserRequestForAffirmation(bytes32 indexed messageId, bytes encodedData);
+    event UserRequestForSignature(bytes32 indexed messageId, bytes encodedData);
+    event AffirmationCompleted(
+        address indexed sender,
+        address indexed executor,
+        bytes32 indexed messageId,
+        bool status
+    );
+    event RelayedMessage(address indexed sender, address indexed executor, bytes32 indexed messageId, bool status);
+
+    function messageSender() external view returns (address);
+
+    function maxGasPerTx() external view returns (uint256);
+
+    function transactionHash() external view returns (bytes32);
+
+    function messageId() external view returns (bytes32);
+
+    function messageSourceChainId() external view returns (bytes32);
+
+    function messageCallStatus(bytes32 _messageId) external view returns (bool);
+
+    function failedMessageDataHash(bytes32 _messageId) external view returns (bytes32);
+
+    function failedMessageReceiver(bytes32 _messageId) external view returns (address);
+
+    function failedMessageSender(bytes32 _messageId) external view returns (address);
+
+    function requireToPassMessage(
+        address _contract,
+        bytes calldata _data,
+        uint256 _gas
+    ) external returns (bytes32);
+
+    function requireToConfirmMessage(
+        address _contract,
+        bytes calldata _data,
+        uint256 _gas
+    ) external returns (bytes32);
+
+    function sourceChainId() external view returns (uint256);
+
+    function destinationChainId() external view returns (uint256);
+}

+ 99 - 0
contracts/vendor/arbitrum/IArbSys.sol

@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IArbSys.sol)
+pragma solidity >=0.4.21 <0.9.0;
+
+/**
+ * @title Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. Exposes a variety of system-level functionality.
+ */
+interface IArbSys {
+    /**
+     * @notice Get internal version number identifying an ArbOS build
+     * @return version number as int
+     */
+    function arbOSVersion() external pure returns (uint256);
+
+    function arbChainID() external view returns (uint256);
+
+    /**
+     * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)
+     * @return block number as int
+     */
+    function arbBlockNumber() external view returns (uint256);
+
+    /**
+     * @notice Send given amount of Eth to dest from sender.
+     * This is a convenience function, which is equivalent to calling sendTxToL1 with empty calldataForL1.
+     * @param destination recipient address on L1
+     * @return unique identifier for this L2-to-L1 transaction.
+     */
+    function withdrawEth(address destination) external payable returns (uint256);
+
+    /**
+     * @notice Send a transaction to L1
+     * @param destination recipient address on L1
+     * @param calldataForL1 (optional) calldata for L1 contract call
+     * @return a unique identifier for this L2-to-L1 transaction.
+     */
+    function sendTxToL1(address destination, bytes calldata calldataForL1) external payable returns (uint256);
+
+    /**
+     * @notice get the number of transactions issued by the given external account or the account sequence number of the given contract
+     * @param account target account
+     * @return the number of transactions issued by the given external account or the account sequence number of the given contract
+     */
+    function getTransactionCount(address account) external view returns (uint256);
+
+    /**
+     * @notice get the value of target L2 storage slot
+     * This function is only callable from address 0 to prevent contracts from being able to call it
+     * @param account target account
+     * @param index target index of storage slot
+     * @return stotage value for the given account at the given index
+     */
+    function getStorageAt(address account, uint256 index) external view returns (uint256);
+
+    /**
+     * @notice check if current call is coming from l1
+     * @return true if the caller of this was called directly from L1
+     */
+    function isTopLevelCall() external view returns (bool);
+
+    /**
+     * @notice check if the caller (of this caller of this) is an aliased L1 contract address
+     * @return true iff the caller's address is an alias for an L1 contract address
+     */
+    function wasMyCallersAddressAliased() external view returns (bool);
+
+    /**
+     * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing
+     * @return address of the caller's caller, without applying L1 contract address aliasing
+     */
+    function myCallersAddressWithoutAliasing() external view returns (address);
+
+    /**
+     * @notice map L1 sender contract address to its L2 alias
+     * @param sender sender address
+     * @param dest destination address
+     * @return aliased sender address
+     */
+    function mapL1SenderContractAddressToL2Alias(address sender, address dest) external pure returns (address);
+
+    /**
+     * @notice get the caller's amount of available storage gas
+     * @return amount of storage gas available to the caller
+     */
+    function getStorageGasAvailable() external view returns (uint256);
+
+    event L2ToL1Transaction(
+        address caller,
+        address indexed destination,
+        uint256 indexed uniqueId,
+        uint256 indexed batchNumber,
+        uint256 indexInBatch,
+        uint256 arbBlockNum,
+        uint256 ethBlockNum,
+        uint256 timestamp,
+        uint256 callvalue,
+        bytes data
+    );
+}

+ 66 - 0
contracts/vendor/arbitrum/IBridge.sol

@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: Apache-2.0
+// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IBridge.sol)
+
+/*
+ * Copyright 2021, Offchain Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+pragma solidity ^0.8.0;
+
+interface IBridge {
+    event MessageDelivered(
+        uint256 indexed messageIndex,
+        bytes32 indexed beforeInboxAcc,
+        address inbox,
+        uint8 kind,
+        address sender,
+        bytes32 messageDataHash
+    );
+
+    event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data);
+
+    event InboxToggle(address indexed inbox, bool enabled);
+
+    event OutboxToggle(address indexed outbox, bool enabled);
+
+    function deliverMessageToInbox(
+        uint8 kind,
+        address sender,
+        bytes32 messageDataHash
+    ) external payable returns (uint256);
+
+    function executeCall(
+        address destAddr,
+        uint256 amount,
+        bytes calldata data
+    ) external returns (bool success, bytes memory returnData);
+
+    // These are only callable by the admin
+    function setInbox(address inbox, bool enabled) external;
+
+    function setOutbox(address inbox, bool enabled) external;
+
+    // View functions
+
+    function activeOutbox() external view returns (address);
+
+    function allowedInboxes(address inbox) external view returns (bool);
+
+    function allowedOutboxes(address outbox) external view returns (bool);
+
+    function inboxAccs(uint256 index) external view returns (bytes32);
+
+    function messageCount() external view returns (uint256);
+}

+ 92 - 0
contracts/vendor/arbitrum/IInbox.sol

@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: Apache-2.0
+// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IInbox.sol)
+
+/*
+ * Copyright 2021, Offchain Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+pragma solidity ^0.8.0;
+
+import "./IMessageProvider.sol";
+
+interface IInbox is IMessageProvider {
+    function sendL2Message(bytes calldata messageData) external returns (uint256);
+
+    function sendUnsignedTransaction(
+        uint256 maxGas,
+        uint256 gasPriceBid,
+        uint256 nonce,
+        address destAddr,
+        uint256 amount,
+        bytes calldata data
+    ) external returns (uint256);
+
+    function sendContractTransaction(
+        uint256 maxGas,
+        uint256 gasPriceBid,
+        address destAddr,
+        uint256 amount,
+        bytes calldata data
+    ) external returns (uint256);
+
+    function sendL1FundedUnsignedTransaction(
+        uint256 maxGas,
+        uint256 gasPriceBid,
+        uint256 nonce,
+        address destAddr,
+        bytes calldata data
+    ) external payable returns (uint256);
+
+    function sendL1FundedContractTransaction(
+        uint256 maxGas,
+        uint256 gasPriceBid,
+        address destAddr,
+        bytes calldata data
+    ) external payable returns (uint256);
+
+    function createRetryableTicket(
+        address destAddr,
+        uint256 arbTxCallValue,
+        uint256 maxSubmissionCost,
+        address submissionRefundAddress,
+        address valueRefundAddress,
+        uint256 maxGas,
+        uint256 gasPriceBid,
+        bytes calldata data
+    ) external payable returns (uint256);
+
+    function createRetryableTicketNoRefundAliasRewrite(
+        address destAddr,
+        uint256 arbTxCallValue,
+        uint256 maxSubmissionCost,
+        address submissionRefundAddress,
+        address valueRefundAddress,
+        uint256 maxGas,
+        uint256 gasPriceBid,
+        bytes calldata data
+    ) external payable returns (uint256);
+
+    function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);
+
+    function bridge() external view returns (address);
+
+    function pauseCreateRetryables() external;
+
+    function unpauseCreateRetryables() external;
+
+    function startRewriteAddress() external;
+
+    function stopRewriteAddress() external;
+}

+ 26 - 0
contracts/vendor/arbitrum/IMessageProvider.sol

@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: Apache-2.0
+// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IMessageProvider.sol)
+
+/*
+ * Copyright 2021, Offchain Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+pragma solidity ^0.8.0;
+
+interface IMessageProvider {
+    event InboxMessageDelivered(uint256 indexed messageNum, bytes data);
+
+    event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);
+}

+ 51 - 0
contracts/vendor/arbitrum/IOutbox.sol

@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: Apache-2.0
+// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IOutbox.sol)
+
+/*
+ * Copyright 2021, Offchain Labs, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+pragma solidity ^0.8.0;
+
+interface IOutbox {
+    event OutboxEntryCreated(
+        uint256 indexed batchNum,
+        uint256 outboxEntryIndex,
+        bytes32 outputRoot,
+        uint256 numInBatch
+    );
+    event OutBoxTransactionExecuted(
+        address indexed destAddr,
+        address indexed l2Sender,
+        uint256 indexed outboxEntryIndex,
+        uint256 transactionIndex
+    );
+
+    function l2ToL1Sender() external view returns (address);
+
+    function l2ToL1Block() external view returns (uint256);
+
+    function l2ToL1EthBlock() external view returns (uint256);
+
+    function l2ToL1Timestamp() external view returns (uint256);
+
+    function l2ToL1BatchNum() external view returns (uint256);
+
+    function l2ToL1OutputId() external view returns (bytes32);
+
+    function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths) external;
+
+    function outboxEntryExists(uint256 batchNum) external view returns (bool);
+}

+ 86 - 0
contracts/vendor/compound/ICompoundTimelock.sol

@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (vendor/compound/ICompoundTimelock.sol)
+
+pragma solidity ^0.8.0;
+
+/**
+ * https://github.com/compound-finance/compound-protocol/blob/master/contracts/Timelock.sol[Compound's timelock] interface
+ */
+interface ICompoundTimelock {
+    event NewAdmin(address indexed newAdmin);
+    event NewPendingAdmin(address indexed newPendingAdmin);
+    event NewDelay(uint256 indexed newDelay);
+    event CancelTransaction(
+        bytes32 indexed txHash,
+        address indexed target,
+        uint256 value,
+        string signature,
+        bytes data,
+        uint256 eta
+    );
+    event ExecuteTransaction(
+        bytes32 indexed txHash,
+        address indexed target,
+        uint256 value,
+        string signature,
+        bytes data,
+        uint256 eta
+    );
+    event QueueTransaction(
+        bytes32 indexed txHash,
+        address indexed target,
+        uint256 value,
+        string signature,
+        bytes data,
+        uint256 eta
+    );
+
+    receive() external payable;
+
+    // solhint-disable-next-line func-name-mixedcase
+    function GRACE_PERIOD() external view returns (uint256);
+
+    // solhint-disable-next-line func-name-mixedcase
+    function MINIMUM_DELAY() external view returns (uint256);
+
+    // solhint-disable-next-line func-name-mixedcase
+    function MAXIMUM_DELAY() external view returns (uint256);
+
+    function admin() external view returns (address);
+
+    function pendingAdmin() external view returns (address);
+
+    function delay() external view returns (uint256);
+
+    function queuedTransactions(bytes32) external view returns (bool);
+
+    function setDelay(uint256) external;
+
+    function acceptAdmin() external;
+
+    function setPendingAdmin(address) external;
+
+    function queueTransaction(
+        address target,
+        uint256 value,
+        string memory signature,
+        bytes memory data,
+        uint256 eta
+    ) external returns (bytes32);
+
+    function cancelTransaction(
+        address target,
+        uint256 value,
+        string memory signature,
+        bytes memory data,
+        uint256 eta
+    ) external;
+
+    function executeTransaction(
+        address target,
+        uint256 value,
+        string memory signature,
+        bytes memory data,
+        uint256 eta
+    ) external payable returns (bytes memory);
+}

+ 11 - 0
contracts/vendor/compound/LICENSE

@@ -0,0 +1,11 @@
+Copyright 2020 Compound Labs, Inc.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 38 - 0
contracts/vendor/optimism/ICrossDomainMessenger.sol

@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.6.0) (vendor/optimism/ICrossDomainMessenger.sol)
+pragma solidity >0.5.0 <0.9.0;
+
+/**
+ * @title ICrossDomainMessenger
+ */
+interface ICrossDomainMessenger {
+    /**********
+     * Events *
+     **********/
+
+    event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit);
+    event RelayedMessage(bytes32 indexed msgHash);
+    event FailedRelayedMessage(bytes32 indexed msgHash);
+
+    /*************
+     * Variables *
+     *************/
+
+    function xDomainMessageSender() external view returns (address);
+
+    /********************
+     * Public Functions *
+     ********************/
+
+    /**
+     * Sends a cross domain message to the target messenger.
+     * @param _target Target contract address.
+     * @param _message Message to send to the target.
+     * @param _gasLimit Gas limit for the provided message.
+     */
+    function sendMessage(
+        address _target,
+        bytes calldata _message,
+        uint32 _gasLimit
+    ) external;
+}

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно