Browse Source

Merge branch 'OpenZeppelin:master' into certora/erc20

Michael D. George 3 years ago
parent
commit
99864fd2da
100 changed files with 1902 additions and 156 deletions
  1. 3 5
      .eslintrc
  2. 2 2
      .github/ISSUE_TEMPLATE/config.yml
  3. 25 0
      .github/workflows/docs.yml
  4. 26 3
      .github/workflows/test.yml
  5. 3 0
      .prettierrc
  6. 58 4
      CHANGELOG.md
  7. 1 1
      LICENSE
  8. 2 0
      README.md
  9. 10 0
      certora/scripts/Governor.sh
  10. 10 0
      certora/scripts/GovernorCountingSimple-counting.sh
  11. 12 0
      certora/scripts/WizardControlFirstPriority.sh
  12. 10 0
      certora/scripts/WizardFirstTry.sh
  13. 14 0
      certora/scripts/sanity.sh
  14. 39 0
      certora/scripts/verifyAll.sh
  15. 334 0
      certora/specs/GovernorBase.spec
  16. 221 0
      certora/specs/GovernorCountingSimple.spec
  17. 139 0
      certora/specs/RulesInProgress.spec
  18. 17 5
      contracts/access/AccessControl.sol
  19. 3 3
      contracts/access/AccessControlEnumerable.sol
  20. 1 1
      contracts/access/IAccessControl.sol
  21. 1 1
      contracts/access/IAccessControlEnumerable.sol
  22. 1 1
      contracts/access/Ownable.sol
  23. 1 1
      contracts/finance/PaymentSplitter.sol
  24. 1 1
      contracts/finance/VestingWallet.sol
  25. 62 5
      contracts/governance/Governor.sol
  26. 2 2
      contracts/governance/IGovernor.sol
  27. 4 0
      contracts/governance/README.adoc
  28. 4 1
      contracts/governance/TimelockController.sol
  29. 2 2
      contracts/governance/compatibility/GovernorCompatibilityBravo.sol
  30. 1 1
      contracts/governance/compatibility/IGovernorCompatibilityBravo.sol
  31. 1 1
      contracts/governance/extensions/GovernorCountingSimple.sol
  32. 1 0
      contracts/governance/extensions/GovernorPreventLateQuorum.sol
  33. 1 1
      contracts/governance/extensions/GovernorProposalThreshold.sol
  34. 1 1
      contracts/governance/extensions/GovernorSettings.sol
  35. 5 3
      contracts/governance/extensions/GovernorTimelockCompound.sol
  36. 13 3
      contracts/governance/extensions/GovernorTimelockControl.sol
  37. 5 6
      contracts/governance/extensions/GovernorVotes.sol
  38. 1 1
      contracts/governance/extensions/GovernorVotesComp.sol
  39. 36 1
      contracts/governance/extensions/GovernorVotesQuorumFraction.sol
  40. 1 1
      contracts/governance/extensions/IGovernorTimelock.sol
  41. 61 0
      contracts/governance/utils/IVotes.sol
  42. 211 0
      contracts/governance/utils/Votes.sol
  43. 1 1
      contracts/interfaces/IERC1155.sol
  44. 1 1
      contracts/interfaces/IERC1155MetadataURI.sol
  45. 1 1
      contracts/interfaces/IERC1155Receiver.sol
  46. 1 1
      contracts/interfaces/IERC1271.sol
  47. 1 1
      contracts/interfaces/IERC1363.sol
  48. 1 1
      contracts/interfaces/IERC1363Receiver.sol
  49. 1 1
      contracts/interfaces/IERC1363Spender.sol
  50. 1 1
      contracts/interfaces/IERC165.sol
  51. 1 1
      contracts/interfaces/IERC1820Implementer.sol
  52. 1 1
      contracts/interfaces/IERC1820Registry.sol
  53. 1 1
      contracts/interfaces/IERC20.sol
  54. 1 1
      contracts/interfaces/IERC20Metadata.sol
  55. 10 8
      contracts/interfaces/IERC2981.sol
  56. 1 1
      contracts/interfaces/IERC3156.sol
  57. 1 1
      contracts/interfaces/IERC3156FlashBorrower.sol
  58. 1 1
      contracts/interfaces/IERC3156FlashLender.sol
  59. 1 1
      contracts/interfaces/IERC721.sol
  60. 1 1
      contracts/interfaces/IERC721Enumerable.sol
  61. 1 1
      contracts/interfaces/IERC721Metadata.sol
  62. 1 1
      contracts/interfaces/IERC721Receiver.sol
  63. 1 1
      contracts/interfaces/IERC777.sol
  64. 1 1
      contracts/interfaces/IERC777Recipient.sol
  65. 1 1
      contracts/interfaces/IERC777Sender.sol
  66. 1 1
      contracts/interfaces/README.adoc
  67. 20 0
      contracts/interfaces/draft-IERC1822.sol
  68. 1 1
      contracts/interfaces/draft-IERC2612.sol
  69. 5 3
      contracts/metatx/ERC2771Context.sol
  70. 10 2
      contracts/metatx/MinimalForwarder.sol
  71. 11 0
      contracts/mocks/Base64Mock.sol
  72. 7 0
      contracts/mocks/CallReceiverMock.sol
  73. 23 0
      contracts/mocks/CheckpointsImpl.sol
  74. 58 0
      contracts/mocks/DoubleEndedQueueMock.sol
  75. 5 2
      contracts/mocks/ERC2771ContextMock.sol
  76. 33 0
      contracts/mocks/ERC721RoyaltyMock.sol
  77. 25 0
      contracts/mocks/ERC721VotesMock.sol
  78. 41 1
      contracts/mocks/EnumerableMapMock.sol
  79. 1 1
      contracts/mocks/GovernorMock.sol
  80. 1 1
      contracts/mocks/GovernorPreventLateQuorumMock.sol
  81. 1 1
      contracts/mocks/GovernorTimelockCompoundMock.sol
  82. 3 1
      contracts/mocks/GovernorTimelockControlMock.sol
  83. 41 0
      contracts/mocks/GovernorVoteMock.sol
  84. 28 1
      contracts/mocks/InitializableMock.sol
  85. 0 4
      contracts/mocks/MathMock.sol
  86. 60 5
      contracts/mocks/MultipleInheritanceInitializableMocks.sol
  87. 1 1
      contracts/mocks/SafeERC20Helper.sol
  88. 23 0
      contracts/mocks/SignedMathMock.sol
  89. 58 0
      contracts/mocks/UUPS/UUPSLegacy.sol
  90. 0 10
      contracts/mocks/UUPS/UUPSUpgradeableMock.sol
  91. 40 0
      contracts/mocks/VotesMock.sol
  92. 1 1
      contracts/mocks/wizard/MyGovernor1.sol
  93. 1 1
      contracts/mocks/wizard/MyGovernor2.sol
  94. 1 1
      contracts/mocks/wizard/MyGovernor3.sol
  95. 1 1
      contracts/package.json
  96. 1 1
      contracts/proxy/Clones.sol
  97. 1 1
      contracts/proxy/ERC1967/ERC1967Proxy.sol
  98. 15 24
      contracts/proxy/ERC1967/ERC1967Upgrade.sol
  99. 2 2
      contracts/proxy/Proxy.sol
  100. 4 2
      contracts/proxy/README.adoc

+ 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

+ 25 - 0
.github/workflows/docs.yml

@@ -0,0 +1,25 @@
+name: Build Docs
+
+on:
+  push:
+    branches: [release-v*]
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions/setup-node@v3
+        with:
+          node-version: 12.x
+      - uses: actions/cache@v2
+        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'
+      - run: bash scripts/git-user-config.sh
+      - run: node scripts/update-docs-branch.js
+      - run: git push --all origin 

+ 26 - 3
.github/workflows/test.yml

@@ -13,7 +13,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
-      - uses: actions/setup-node@v2
+      - uses: actions/setup-node@v3
         with:
           node-version: 12.x
       - uses: actions/cache@v2
@@ -29,7 +29,7 @@ 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
 
@@ -39,7 +39,7 @@ jobs:
       - uses: actions/checkout@v2
         with:
           fetch-depth: 2
-      - uses: actions/setup-node@v2
+      - uses: actions/setup-node@v3
         with:
           node-version: 12.x
       - uses: actions/cache@v2
@@ -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@v2
+      - uses: actions/setup-node@v3
+        with:
+          node-version: 12.x
+      - uses: actions/cache@v2
+        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"
       }

+ 58 - 4
CHANGELOG.md

@@ -2,11 +2,65 @@
 
 ## Unreleased
 
-* `GovernorTimelockControl`: improve the `state()` function to have it reflect cases where a proposal has been canceled directly on the timelock. ([#2977](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2977))
-* `Math`: add a `abs(int256)` method that returns the unsigned absolute value of a signed value. ([#2984](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2984))
-* Preset contracts are now deprecated in favor of [Contracts Wizard](https://wizard.openzeppelin.com). ([#2986](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2986))
+ * `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))
+ * `ERC1155`: Add a `_afterTokenTransfer` hook for improved extensibility. ([#3166](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3166))
+ * `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))
+
+## 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))
+ * `GovernorTimelockControl`: improve the `state()` function to have it reflect cases where a proposal has been canceled directly on the timelock. ([#2977](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2977))
+ * Preset contracts are now deprecated in favor of [Contracts Wizard](https://wizard.openzeppelin.com). ([#2986](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2986))
  * `Governor`: add a relay function to help recover assets sent to a governor that is not its own executor (e.g. when using a timelock). ([#2926](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2926))
- * `GovernorExtendedVoting`: add new module to ensure a minimum voting duration is available after the quorum is reached. ([#2973](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2973))
+ * `GovernorPreventLateQuorum`: add new module to ensure a minimum voting duration is available after the quorum is reached. ([#2973](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2973))
+ * `ERC721`: improved revert reason when transferring from wrong owner. ([#2975](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2975))
+ * `Votes`: Added a base contract for vote tracking with delegation. ([#2944](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2944))
+ * `ERC721Votes`: Added an extension of ERC721 enabled with vote tracking and delegation. ([#2944](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2944))
+ * `ERC2771Context`: use immutable storage to store the forwarder address, no longer an issue since Solidity >=0.8.8 allows reading immutable variables in the constructor. ([#2917](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2917))
+ * `Base64`: add a library to parse bytes into base64 strings using `encode(bytes memory)` function, and provide examples to show how to use to build URL-safe `tokenURIs`. ([#2884](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2884))
+ * `ERC20`: reduce allowance before triggering transfer. ([#3056](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3056))
+ * `ERC20`: do not update allowance on `transferFrom` when allowance is `type(uint256).max`. ([#3085](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3085))
+ * `ERC20`: add a `_spendAllowance` internal function. ([#3170](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3170))
+ * `ERC20Burnable`: do not update allowance on `burnFrom` when allowance is `type(uint256).max`. ([#3170](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3170))
+ * `ERC777`: do not update allowance on `transferFrom` when allowance is `type(uint256).max`. ([#3085](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3085))
+ * `ERC777`: add a `_spendAllowance` internal function. ([#3170](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3170))
+ * `SignedMath`: a new signed version of the Math library with `max`, `min`,  and `average`. ([#2686](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2686))
+ * `SignedMath`: add a `abs(int256)` method that returns the unsigned absolute value of a signed value. ([#2984](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2984))
+ * `ERC1967Upgrade`: Refactor the secure upgrade to use `ERC1822` instead of the previous rollback mechanism. This reduces code complexity and attack surface with similar security guarantees. ([#3021](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3021))
+ * `UUPSUpgradeable`: Add `ERC1822` compliance to support the updated secure upgrade mechanism. ([#3021](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3021))
+ * Some more functions have been made virtual to customize them via overrides. In many cases this will not imply that other functions in the contract will automatically adapt to the overridden definitions. People who wish to override should consult the source code to understand the impact and if they need to override any additional functions to achieve the desired behavior.
+
+### Breaking changes
+
+* `ERC1967Upgrade`: The function `_upgradeToAndCallSecure` was renamed to `_upgradeToAndCallUUPS`, along with the change in security mechanism described above.
+* `Address`: The Solidity pragma is increased from `^0.8.0` to `^0.8.1`. This is required by the `account.code.length` syntax that replaces inline assembly. This may require users to bump their compiler version from `0.8.0` to `0.8.1` or later. Note that other parts of the code already include stricter requirements.
+
+## 4.4.2 (2022-01-11)
+
+### Bugfixes
+ * `GovernorCompatibilityBravo`: Fix error in the encoding of calldata for proposals submitted through the compatibility interface with explicit signatures. ([#3100](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3100))
+
+## 4.4.1 (2021-12-14)
+
+ * `Initializable`: change the existing `initializer` modifier and add a new `onlyInitializing` modifier to prevent reentrancy risk. ([#3006](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3006))
+
+### Breaking change
+
+It is no longer possible to call an `initializer`-protected function from within another `initializer` function outside the context of a constructor. Projects using OpenZeppelin upgradeable proxies should continue to work as is, since in the common case the initializer is invoked in the constructor directly. If this is not the case for you, the suggested change is to use the new `onlyInitializing` modifier in the following way:
+
+```diff
+ contract A {
+-    function initialize() public   initializer { ... }
++    function initialize() internal onlyInitializing { ... }
+ }
+ contract B is A {
+     function initialize() public initializer {
+         A.initialize();
+     }
+ }
+```
 
 ## 4.4.0 (2021-11-25)
 

+ 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

+ 2 - 0
README.md

@@ -22,6 +22,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:

+ 10 - 0
certora/scripts/Governor.sh

@@ -0,0 +1,10 @@
+make -C certora munged
+
+certoraRun certora/harnesses/ERC20VotesHarness.sol certora/harnesses/GovernorHarness.sol \
+    --verify GovernorHarness:certora/specs/GovernorBase.spec \
+    --solc solc8.0 \
+    --staging shelly/forSasha \
+    --optimistic_loop \
+    --settings -copyLoopUnroll=4 \
+    --rule voteStartBeforeVoteEnd \
+    --msg "$1"

+ 10 - 0
certora/scripts/GovernorCountingSimple-counting.sh

@@ -0,0 +1,10 @@
+make -C certora munged
+
+certoraRun  certora/harnesses/ERC20VotesHarness.sol certora/harnesses/GovernorBasicHarness.sol \
+    --verify GovernorBasicHarness:certora/specs/GovernorCountingSimple.spec \
+    --solc solc8.2 \
+    --staging shelly/forSasha \
+    --optimistic_loop \
+    --settings -copyLoopUnroll=4 \
+    --rule hasVotedCorrelation \
+    --msg "$1"

+ 12 - 0
certora/scripts/WizardControlFirstPriority.sh

@@ -0,0 +1,12 @@
+make -C certora munged
+
+certoraRun certora/harnesses/ERC20VotesHarness.sol certora/harnesses/WizardControlFirstPriority.sol \
+    --link WizardControlFirstPriority:token=ERC20VotesHarness \
+    --verify WizardControlFirstPriority:certora/specs/GovernorBase.spec \
+    --solc solc8.2 \
+    --disableLocalTypeChecking \
+    --staging shelly/forSasha \
+    --optimistic_loop \
+    --settings -copyLoopUnroll=4 \
+    --rule canVoteDuringVotingPeriod \
+    --msg "$1"

+ 10 - 0
certora/scripts/WizardFirstTry.sh

@@ -0,0 +1,10 @@
+make -C certora munged
+
+certoraRun certora/harnesses/ERC20VotesHarness.sol certora/harnesses/WizardFirstTry.sol \
+    --verify WizardFirstTry:certora/specs/GovernorBase.spec \
+    --solc solc8.2 \
+    --staging shelly/forSasha \
+    --optimistic_loop \
+    --disableLocalTypeChecking \
+    --settings -copyLoopUnroll=4 \
+    --msg "$1"

+ 14 - 0
certora/scripts/sanity.sh

@@ -0,0 +1,14 @@
+make -C certora munged
+
+for f in certora/harnesses/Wizard*.sol
+do
+    echo "Processing $f"
+    file=$(basename $f)
+    echo ${file%.*}
+    certoraRun certora/harnesses/$file \
+    --verify ${file%.*}:certora/specs/sanity.spec "$@" \
+    --solc solc8.2 --staging shelly/forSasha \
+    --optimistic_loop \
+    --msg "checking sanity on ${file%.*}"
+    --settings -copyLoopUnroll=4
+done

+ 39 - 0
certora/scripts/verifyAll.sh

@@ -0,0 +1,39 @@
+#!/bin/bash
+
+make -C certora munged
+
+for contract in certora/harnesses/Wizard*.sol;
+do
+    for spec in certora/specs/*.spec;
+    do      
+        contractFile=$(basename $contract)
+        specFile=$(basename $spec)
+        if [[ "${specFile%.*}" != "RulesInProgress" ]];
+        then
+            echo "Processing ${contractFile%.*} with $specFile"
+            if [[ "${contractFile%.*}" = *"WizardControl"* ]];
+            then
+                certoraRun certora/harnesses/ERC20VotesHarness.sol certora/harnesses/$contractFile \
+                --link ${contractFile%.*}:token=ERC20VotesHarness \
+                --verify ${contractFile%.*}:certora/specs/$specFile "$@" \
+                --solc solc8.2 \
+                --staging shelly/forSasha \
+                --disableLocalTypeChecking \
+                --optimistic_loop \
+                --settings -copyLoopUnroll=4 \
+                --send_only \
+                --msg "checking $specFile on ${contractFile%.*}"
+            else
+                certoraRun certora/harnesses/ERC20VotesHarness.sol certora/harnesses/$contractFile \
+                --verify ${contractFile%.*}:certora/specs/$specFile "$@" \
+                --solc solc8.2 \
+                --staging shelly/forSasha \
+                --disableLocalTypeChecking \
+                --optimistic_loop \
+                --settings -copyLoopUnroll=4 \
+                --send_only \
+                --msg "checking $specFile on ${contractFile%.*}"
+            fi
+        fi
+    done
+done

+ 334 - 0
certora/specs/GovernorBase.spec

@@ -0,0 +1,334 @@
+//////////////////////////////////////////////////////////////////////////////
+///////////////////// Governor.sol base definitions //////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+using ERC20VotesHarness as erc20votes
+
+methods {
+    proposalSnapshot(uint256) returns uint256 envfree // matches proposalVoteStart
+    proposalDeadline(uint256) returns uint256 envfree // matches proposalVoteEnd
+    hashProposal(address[],uint256[],bytes[],bytes32) returns uint256 envfree
+    isExecuted(uint256) returns bool envfree
+    isCanceled(uint256) returns bool envfree
+    execute(address[], uint256[], bytes[], bytes32) returns uint256
+    hasVoted(uint256, address) returns bool
+    castVote(uint256, uint8) returns uint256
+    updateQuorumNumerator(uint256)
+    queue(address[], uint256[], bytes[], bytes32) returns uint256
+
+    // internal functions made public in harness:
+    _quorumReached(uint256) returns bool
+    _voteSucceeded(uint256) returns bool envfree
+
+    // function summarization
+    proposalThreshold() returns uint256 envfree
+
+    getVotes(address, uint256) returns uint256 => DISPATCHER(true)
+
+    getPastTotalSupply(uint256 t) returns uint256      => PER_CALLEE_CONSTANT
+    getPastVotes(address a, uint256 t) returns uint256 => PER_CALLEE_CONSTANT
+
+    //scheduleBatch(address[],uint256[],bytes[],bytes32,bytes32,uint256) => DISPATCHER(true)
+    //executeBatch(address[], uint256[], bytes[], bytes32, bytes32) => DISPATCHER(true)
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////// Definitions /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+// proposal was created - relation proved in noStartBeforeCreation
+definition proposalCreated(uint256 pId) returns bool = proposalSnapshot(pId) > 0;
+
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////////// Helper Functions ///////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+function helperFunctionsWithRevert(uint256 proposalId, method f, env e) {
+    address[] targets; uint256[] values; bytes[] calldatas; string reason; bytes32 descriptionHash;
+    uint8 support; uint8 v; bytes32 r; bytes32 s;
+	if (f.selector == propose(address[], uint256[], bytes[], string).selector) {
+		uint256 result = propose@withrevert(e, targets, values, calldatas, reason);
+        require(result == proposalId);
+	} else if (f.selector == execute(address[], uint256[], bytes[], bytes32).selector) {
+		uint256 result = execute@withrevert(e, targets, values, calldatas, descriptionHash);
+        require(result == proposalId);
+	} else if (f.selector == castVote(uint256, uint8).selector) {
+		castVote@withrevert(e, proposalId, support);
+	} else if  (f.selector == castVoteWithReason(uint256, uint8, string).selector) {
+        castVoteWithReason@withrevert(e, proposalId, support, reason);
+	} else if (f.selector == castVoteBySig(uint256, uint8,uint8, bytes32, bytes32).selector) {
+		castVoteBySig@withrevert(e, proposalId, support, v, r, s);
+    } else if (f.selector == queue(address[], uint256[], bytes[], bytes32).selector) {
+        queue@withrevert(e, targets, values, calldatas, descriptionHash);
+	} else {
+        calldataarg args;
+        f@withrevert(e, args);
+    }
+}
+
+/*
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////// State Diagram //////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //                                                                                                                          //
+ //                                                                castVote(s)()                                             //
+ //  -------------  propose()  ----------------------  time pass  ---------------       time passes         -----------      //
+ // | No Proposal | --------> | Before Start (Delay) | --------> | Voting Period | ----------------------> | execute() |     //
+ //  -------------             ----------------------             --------------- -> Executed/Canceled      -----------      //
+ //  ------------------------------------------------------------|---------------|-------------------------|-------------->  //
+ // t                                                          start            end                     timelock             //
+ //                                                                                                                          //
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+*/
+
+
+///////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////// Global Valid States /////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
+
+
+/*
+ * Start and end date are either initialized (non zero) or uninitialized (zero) simultaneously
+ * This invariant assumes that the block number cannot be 0 at any stage of the contract cycle
+ * This is very safe assumption as usually the 0 block is genesis block which is uploaded with data
+ * by the developers and will not be valid to raise proposals (at the current way that block chain is functioning)
+ */
+ // To use env with general preserved block disable type checking [--disableLocalTypeChecking]
+invariant startAndEndDatesNonZero(uint256 pId)
+        proposalSnapshot(pId) != 0 <=> proposalDeadline(pId) != 0
+        { preserved with (env e){   
+                require e.block.number > 0;
+        }}
+        
+
+/*
+ * If a proposal is canceled it must have a start and an end date 
+ */
+ // To use env with general preserved block disable type checking [--disableLocalTypeChecking]
+invariant canceledImplyStartAndEndDateNonZero(uint pId)
+        isCanceled(pId) => proposalSnapshot(pId) != 0
+        {preserved with (env e){               
+                require e.block.number > 0;
+        }}
+
+
+/*
+ * If a proposal is executed it must have a start and an end date 
+ */
+ // To use env with general preserved block disable type checking [--disableLocalTypeChecking] 
+invariant executedImplyStartAndEndDateNonZero(uint pId)
+        isExecuted(pId) => proposalSnapshot(pId) != 0
+        { preserved with (env e){
+            requireInvariant startAndEndDatesNonZero(pId);
+            require e.block.number > 0;
+        }}
+
+
+/*
+ * A proposal starting block number must be less or equal than the proposal end date
+ */
+invariant voteStartBeforeVoteEnd(uint256 pId)
+        // from < to <= because snapshot and deadline can be the same block number if delays are set to 0
+        // This is possible before the integration of GovernorSettings.sol to the system.
+        // After integration of GovernorSettings.sol the invariant expression should be changed from <= to <
+        (proposalSnapshot(pId) > 0 =>  proposalSnapshot(pId) <= proposalDeadline(pId))
+        // (proposalSnapshot(pId) > 0 =>  proposalSnapshot(pId) <= proposalDeadline(pId))
+        { preserved {
+            requireInvariant startAndEndDatesNonZero(pId);
+        }}
+
+
+/*
+ * A proposal cannot be both executed and canceled simultaneously.
+ */
+invariant noBothExecutedAndCanceled(uint256 pId) 
+        !isExecuted(pId) || !isCanceled(pId)
+
+
+/*
+ * A proposal could be executed only if quorum was reached and vote succeeded
+ */
+rule executionOnlyIfQuoromReachedAndVoteSucceeded(uint256 pId, env e, method f){
+    bool isExecutedBefore = isExecuted(pId);
+    bool quorumReachedBefore = _quorumReached(e, pId);
+    bool voteSucceededBefore = _voteSucceeded(pId);
+    
+    calldataarg args;
+    f(e, args);
+    
+    bool isExecutedAfter = isExecuted(pId);
+    assert (!isExecutedBefore && isExecutedAfter) => (quorumReachedBefore && voteSucceededBefore), "quorum was changed";
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////// In-State Rules /////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
+
+//==========================================
+//------------- Voting Period --------------
+//==========================================
+
+/*
+ * 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.
+ // 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 
+ // benefit, as it is evident that nothing is happening in the first 2 functions (calling a view function), and we do not desire to check the signature verification.
+rule doubleVoting(uint256 pId, uint8 sup, method f) {
+    env e;
+    address user = e.msg.sender;        
+    bool votedCheck = hasVoted(e, pId, user);
+
+    castVote@withrevert(e, pId, sup);
+
+    assert votedCheck => lastReverted, "double voting accured";
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////// State Transitions Rules //////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
+
+//===========================================
+//-------- Propose() --> End of Time --------
+//===========================================
+
+
+/*
+ * Once a proposal is created, voteStart and voteEnd are immutable
+ */
+rule immutableFieldsAfterProposalCreation(uint256 pId, method f) {
+    uint256 _voteStart = proposalSnapshot(pId);
+    uint256 _voteEnd = proposalDeadline(pId);
+
+    require proposalCreated(pId); // startDate > 0
+    
+    env e; calldataarg arg;
+    f(e, arg);
+
+    uint256 voteStart_ = proposalSnapshot(pId);
+    uint256 voteEnd_ = proposalDeadline(pId);
+    assert _voteStart == voteStart_, "Start date was changed";
+    assert _voteEnd == voteEnd_, "End date was changed";
+}
+
+
+/*
+ * Voting cannot start at a block number prior to proposal’s creation block number
+ */
+rule noStartBeforeCreation(uint256 pId) {
+    uint256 previousStart = proposalSnapshot(pId);
+    // This line makes sure that we see only cases where start date is changed from 0, i.e. creation of proposal
+    // We proved in immutableFieldsAfterProposalCreation that once dates set for proposal, it cannot be changed
+    require !proposalCreated(pId); // previousStart == 0;
+    
+    env e; calldataarg args;
+    propose(e, args);
+
+    uint256 newStart = proposalSnapshot(pId);
+    // if created, start is after current block number (creation block)
+    assert(newStart != previousStart => newStart >= e.block.number);
+}
+
+
+//============================================
+//--- End of Voting Period --> End of Time ---
+//============================================
+
+
+/*
+ * A proposal can neither be executed nor canceled before it ends
+ */
+ // By induction it cannot be executed nor canceled before it starts, due to voteStartBeforeVoteEnd
+rule noExecuteOrCancelBeforeDeadline(uint256 pId, method f){
+    require !isExecuted(pId) && !isCanceled(pId);
+
+    env e; calldataarg args;
+    f(e, args);
+
+    assert e.block.number < proposalDeadline(pId) => (!isExecuted(pId) && !isCanceled(pId)), "executed/cancelled before deadline";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////// Integrity Of Functions (Unit Tests) /////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////// High Level Rules ////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////
+///////////////////////////// Not Categorized Yet //////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+
+/*
+ * All proposal specific (non-view) functions should revert if proposal is executed
+ */
+ // In this rule we show that if a function is executed, i.e. execute() was called on the proposal ID,
+ // non of the proposal specific functions can make changes again. In executedOnlyAfterExecuteFunc 
+ // we connected the executed attribute to the execute() function, showing that only execute() can
+ // change it, and that it will always change it.
+rule allFunctionsRevertIfExecuted(method f) filtered { f ->
+    !f.isView && !f.isFallback
+      && f.selector != updateTimelock(address).selector
+      && f.selector != updateQuorumNumerator(uint256).selector
+      && f.selector != queue(address[],uint256[],bytes[],bytes32).selector
+      && f.selector != relay(address,uint256,bytes).selector
+      && f.selector != 0xb9a61961 // __acceptAdmin()
+} {
+    env e; calldataarg args;
+    uint256 pId;
+    require(isExecuted(pId));
+    requireInvariant noBothExecutedAndCanceled(pId);
+    requireInvariant executedImplyStartAndEndDateNonZero(pId);
+
+    helperFunctionsWithRevert(pId, f, e);
+
+    assert(lastReverted, "Function was not reverted");
+}
+
+/*
+ * All proposal specific (non-view) functions should revert if proposal is canceled
+ */
+rule allFunctionsRevertIfCanceled(method f) filtered {
+    f -> !f.isView && !f.isFallback
+      && f.selector != updateTimelock(address).selector
+      && f.selector != updateQuorumNumerator(uint256).selector
+      && f.selector != queue(address[],uint256[],bytes[],bytes32).selector
+      && f.selector != relay(address,uint256,bytes).selector
+      && f.selector != 0xb9a61961 // __acceptAdmin()
+} {
+    env e; calldataarg args;
+    uint256 pId;
+    require(isCanceled(pId));
+    requireInvariant noBothExecutedAndCanceled(pId);
+    requireInvariant canceledImplyStartAndEndDateNonZero(pId);
+
+    helperFunctionsWithRevert(pId, f, e);
+
+    assert(lastReverted, "Function was not reverted");
+}
+
+/*
+ * Proposal can be switched to executed only via execute() function
+ */
+rule executedOnlyAfterExecuteFunc(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash, method f) {
+    env e; calldataarg args;
+    uint256 pId;
+    bool executedBefore = isExecuted(pId);
+    require(!executedBefore);
+
+    helperFunctionsWithRevert(pId, f, e);
+
+    bool executedAfter = isExecuted(pId);
+    assert(executedAfter != executedBefore => f.selector == execute(address[], uint256[], bytes[], bytes32).selector, "isExecuted only changes in the execute method");
+}
+

+ 221 - 0
certora/specs/GovernorCountingSimple.spec

@@ -0,0 +1,221 @@
+import "GovernorBase.spec"
+
+using ERC20VotesHarness as erc20votes
+
+methods {
+    ghost_sum_vote_power_by_id(uint256) returns uint256 envfree
+
+    quorum(uint256) returns uint256
+    proposalVotes(uint256) returns (uint256, uint256, uint256) envfree
+
+    quorumNumerator() returns uint256
+    _executor() returns address
+
+    erc20votes._getPastVotes(address, uint256) returns uint256
+
+    getExecutor() returns address
+
+    timelock() returns address
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////////////// GHOSTS /////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+//////////// ghosts to keep track of votes counting ////////////
+
+/*
+ * the sum of voting power of those who voted
+ */
+ghost sum_all_votes_power() returns uint256 {
+	init_state axiom sum_all_votes_power() == 0;
+}
+
+hook Sstore ghost_sum_vote_power_by_id [KEY uint256 pId] uint256 current_power(uint256 old_power) STORAGE {
+	havoc sum_all_votes_power assuming sum_all_votes_power@new() == sum_all_votes_power@old() - old_power + current_power;
+}
+
+/*
+ * sum of all votes casted per proposal
+ */
+ghost tracked_weight(uint256) returns uint256 {
+	init_state axiom forall uint256 p. tracked_weight(p) == 0;
+}
+
+/*
+ * sum of all votes casted
+ */
+ghost sum_tracked_weight() returns uint256 {
+	init_state axiom sum_tracked_weight() == 0;
+}
+
+/*
+ * getter for _proposalVotes.againstVotes
+ */
+ghost votesAgainst() returns uint256 {
+    init_state axiom votesAgainst() == 0;
+}
+
+/*
+ * getter for _proposalVotes.forVotes
+ */
+ghost votesFor() returns uint256 {
+    init_state axiom votesFor() == 0;
+}
+
+/*
+ * getter for _proposalVotes.abstainVotes
+ */
+ghost votesAbstain() returns uint256 {
+    init_state axiom votesAbstain() == 0;
+}
+
+hook Sstore _proposalVotes [KEY uint256 pId].againstVotes uint256 votes(uint256 old_votes) STORAGE {
+	havoc tracked_weight assuming forall uint256 p.(p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) &&
+	                                            (p != pId => tracked_weight@new(p) == tracked_weight@old(p));
+	havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes;
+    havoc votesAgainst assuming votesAgainst@new() == votesAgainst@old() - old_votes + votes;
+}
+
+hook Sstore _proposalVotes [KEY uint256 pId].forVotes uint256 votes(uint256 old_votes) STORAGE {
+	havoc tracked_weight assuming forall uint256 p.(p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) &&
+	                                            (p != pId => tracked_weight@new(p) == tracked_weight@old(p));
+	havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes;
+    havoc votesFor assuming votesFor@new() == votesFor@old() - old_votes + votes;
+}
+
+hook Sstore _proposalVotes [KEY uint256 pId].abstainVotes uint256 votes(uint256 old_votes) STORAGE {
+	havoc tracked_weight assuming forall uint256 p.(p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) &&
+	                                            (p != pId => tracked_weight@new(p) == tracked_weight@old(p));
+	havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes;
+    havoc votesAbstain assuming votesAbstain@new() == votesAbstain@old() - old_votes + votes;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+////////////////////////////// INVARIANTS ////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+/*
+ * sum of all votes casted is equal to the sum of voting power of those who voted, per each proposal
+ */
+invariant SumOfVotesCastEqualSumOfPowerOfVotedPerProposal(uint256 pId) 
+	tracked_weight(pId) == ghost_sum_vote_power_by_id(pId)
+
+
+/*
+ * sum of all votes casted is equal to the sum of voting power of those who voted
+ */
+invariant SumOfVotesCastEqualSumOfPowerOfVoted() 
+	sum_tracked_weight() == sum_all_votes_power()
+
+
+/*
+* sum of all votes casted is greater or equal to the sum of voting power of those who voted at a specific proposal
+*/
+invariant OneIsNotMoreThanAll(uint256 pId) 
+	sum_all_votes_power() >= tracked_weight(pId)
+
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////////////// RULES //////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+/*
+ * 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.
+ // 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 
+ // 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;
+
+    address voter = e.msg.sender;
+    address user;
+
+    bool hasVotedBefore_User = hasVoted(e, pId, user);
+
+    castVote@withrevert(e, pId, sup);
+    require(!lastReverted);
+
+    bool hasVotedAfter_User = hasVoted(e, pId, user);
+
+    assert user != voter => hasVotedBefore_User == hasVotedAfter_User;
+}
+
+
+/*
+* Total voting tally is monotonically non-decreasing in every operation 
+*/
+rule votingWeightMonotonicity(method f){
+    uint256 votingWeightBefore = sum_tracked_weight();
+
+    env e; 
+    calldataarg args;
+    f(e, args);
+
+    uint256 votingWeightAfter = sum_tracked_weight();
+
+    assert votingWeightBefore <= votingWeightAfter, "Voting weight was decreased somehow";
+}
+
+
+/*
+* A change in hasVoted must be correlated with an non-decreasing of the vote supports (nondecrease because user can vote with weight 0)
+*/
+rule hasVotedCorrelation(uint256 pId, method f, env e, uint256 bn) {
+    address acc = e.msg.sender;
+    
+    uint256 againstBefore = votesAgainst();
+    uint256 forBefore = votesFor();
+    uint256 abstainBefore = votesAbstain();
+
+    bool hasVotedBefore = hasVoted(e, pId, acc);
+
+    helperFunctionsWithRevert(pId, f, e);
+    require(!lastReverted);
+
+    uint256 againstAfter = votesAgainst();
+    uint256 forAfter = votesFor();
+    uint256 abstainAfter = votesAbstain();
+    
+    bool hasVotedAfter = hasVoted(e, pId, acc);
+
+    assert (!hasVotedBefore && hasVotedAfter) => againstBefore <= againstAfter || forBefore <= forAfter || abstainBefore <= abstainAfter, "no correlation";
+}
+
+
+/*
+* Only privileged users can execute privileged operations, e.g. change _quorumNumerator or _timelock
+*/
+rule privilegedOnlyNumerator(method f, uint256 newQuorumNumerator){
+    env e;
+    calldataarg arg;
+    uint256 quorumNumBefore = quorumNumerator(e);
+
+    f(e, arg);
+
+    uint256 quorumNumAfter = quorumNumerator(e);
+    address executorCheck = getExecutor(e);
+
+    assert quorumNumBefore != quorumNumAfter => e.msg.sender == executorCheck, "non priveleged user changed quorum numerator";
+}
+
+rule privilegedOnlyTimelock(method f, uint256 newQuorumNumerator){
+    env e;
+    calldataarg arg;
+    uint256 timelockBefore = timelock(e);
+
+    f(e, arg);
+
+    uint256 timelockAfter = timelock(e);
+
+    assert timelockBefore != timelockAfter => e.msg.sender == timelockBefore, "non priveleged user changed timelock";
+}

+ 139 - 0
certora/specs/RulesInProgress.spec

@@ -0,0 +1,139 @@
+//////////////////////////////////////////////////////////////////////////////
+////////////// THIS SPEC IS A RESERVE FOR NOT IN PROGRESS //////////////
+//////////////////////////////////////////////////////////////////////////////
+
+import "GovernorBase.spec"
+
+using ERC20VotesHarness as erc20votes
+
+methods {
+    ghost_sum_vote_power_by_id(uint256) returns uint256 envfree
+
+    quorum(uint256) returns uint256
+    proposalVotes(uint256) returns (uint256, uint256, uint256) envfree
+
+    quorumNumerator() returns uint256
+    _executor() returns address
+
+    erc20votes._getPastVotes(address, uint256) returns uint256
+
+    getExecutor() returns address
+
+    timelock() returns address
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////////////// GHOSTS /////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+//////////// ghosts to keep track of votes counting ////////////
+
+/*
+ * the sum of voting power of those who voted
+ */
+ghost sum_all_votes_power() returns uint256 {
+	init_state axiom sum_all_votes_power() == 0;
+}
+
+hook Sstore ghost_sum_vote_power_by_id [KEY uint256 pId] uint256 current_power(uint256 old_power) STORAGE {
+	havoc sum_all_votes_power assuming sum_all_votes_power@new() == sum_all_votes_power@old() - old_power + current_power;
+}
+
+/*
+ * sum of all votes casted per proposal
+ */
+ghost tracked_weight(uint256) returns uint256 {
+	init_state axiom forall uint256 p. tracked_weight(p) == 0;
+}
+
+/*
+ * sum of all votes casted
+ */
+ghost sum_tracked_weight() returns uint256 {
+	init_state axiom sum_tracked_weight() == 0;
+}
+
+/*
+ * getter for _proposalVotes.againstVotes
+ */
+ghost votesAgainst() returns uint256 {
+    init_state axiom votesAgainst() == 0;
+}
+
+/*
+ * getter for _proposalVotes.forVotes
+ */
+ghost votesFor() returns uint256 {
+    init_state axiom votesFor() == 0;
+}
+
+/*
+ * getter for _proposalVotes.abstainVotes
+ */
+ghost votesAbstain() returns uint256 {
+    init_state axiom votesAbstain() == 0;
+}
+
+hook Sstore _proposalVotes [KEY uint256 pId].againstVotes uint256 votes(uint256 old_votes) STORAGE {
+	havoc tracked_weight assuming forall uint256 p.(p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) &&
+	                                            (p != pId => tracked_weight@new(p) == tracked_weight@old(p));
+	havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes;
+    havoc votesAgainst assuming votesAgainst@new() == votesAgainst@old() - old_votes + votes;
+}
+
+hook Sstore _proposalVotes [KEY uint256 pId].forVotes uint256 votes(uint256 old_votes) STORAGE {
+	havoc tracked_weight assuming forall uint256 p.(p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) &&
+	                                            (p != pId => tracked_weight@new(p) == tracked_weight@old(p));
+	havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes;
+    havoc votesFor assuming votesFor@new() == votesFor@old() - old_votes + votes;
+}
+
+hook Sstore _proposalVotes [KEY uint256 pId].abstainVotes uint256 votes(uint256 old_votes) STORAGE {
+	havoc tracked_weight assuming forall uint256 p.(p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) &&
+	                                            (p != pId => tracked_weight@new(p) == tracked_weight@old(p));
+	havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes;
+    havoc votesAbstain assuming votesAbstain@new() == votesAbstain@old() - old_votes + votes;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+////////////////////////////// INVARIANTS ////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////////////// RULES //////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+//NOT FINISHED
+/*
+* the sum of voting power of those who voted is less or equal to the maximum possible votes, per each proposal
+*/
+rule possibleTotalVotes(uint256 pId, uint8 sup, env e, method f) {
+
+    // add requireinvariant  for all i, j. i = i - 1 && i < j => checkpointlookup[i] < checkpointlookup[j];
+    require tracked_weight(pId) <= erc20votes.getPastTotalSupply(e, proposalSnapshot(pId));
+
+    uint256 againstB;
+    uint256 forB;
+    uint256 absatinB;
+    againstB, forB, absatinB = proposalVotes(pId);
+
+    calldataarg args;
+    //f(e, args);
+
+    castVote(e, pId, sup);
+
+    uint256 against;
+    uint256 for;
+    uint256 absatin;
+    against, for, absatin = proposalVotes(pId);
+
+    uint256 ps = proposalSnapshot(pId);
+
+    assert tracked_weight(pId) <= erc20votes.getPastTotalSupply(e, proposalSnapshot(pId)), "bla bla bla";
+}

+ 17 - 5
contracts/access/AccessControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (access/AccessControl.sol)
+// OpenZeppelin Contracts (last updated v4.5.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);
         _;
     }
 
@@ -81,10 +81,22 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
     /**
      * @dev Returns `true` if `account` has been granted `role`.
      */
-    function hasRole(bytes32 role, address account) public view override returns (bool) {
+    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
         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`.
      *
@@ -92,7 +104,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
      *
      *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
      */
-    function _checkRole(bytes32 role, address account) internal view {
+    function _checkRole(bytes32 role, address account) internal view virtual {
         if (!hasRole(role, account)) {
             revert(
                 string(
@@ -113,7 +125,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
      *
      * To change a role's admin, use {_setRoleAdmin}.
      */
-    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
+    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
         return _roles[role].adminRole;
     }
 

+ 3 - 3
contracts/access/AccessControlEnumerable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (access/AccessControlEnumerable.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)
 
 pragma solidity ^0.8.0;
 
@@ -34,7 +34,7 @@ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessCon
      * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
      * for more information.
      */
-    function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {
+    function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {
         return _roleMembers[role].at(index);
     }
 
@@ -42,7 +42,7 @@ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessCon
      * @dev Returns the number of accounts that have `role`. Can be used
      * together with {getRoleMember} to enumerate all bearers of a role.
      */
-    function getRoleMemberCount(bytes32 role) public view override returns (uint256) {
+    function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {
         return _roleMembers[role].length();
     }
 

+ 1 - 1
contracts/access/IAccessControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (access/IAccessControl.sol)
+// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/access/IAccessControlEnumerable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (access/IAccessControlEnumerable.sol)
+// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/access/Ownable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (access/Ownable.sol)
+// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/finance/PaymentSplitter.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (finance/PaymentSplitter.sol)
+// OpenZeppelin Contracts v4.4.1 (finance/PaymentSplitter.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/finance/VestingWallet.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (finance/VestingWallet.sol)
+// OpenZeppelin Contracts v4.4.1 (finance/VestingWallet.sol)
 pragma solidity ^0.8.0;
 
 import "../token/ERC20/utils/SafeERC20.sol";

+ 62 - 5
contracts/governance/Governor.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/Governor.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/Governor.sol)
 
 pragma solidity ^0.8.0;
 
@@ -7,6 +7,7 @@ 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";
@@ -24,6 +25,7 @@ import "./IGovernor.sol";
  * _Available since v4.3._
  */
 abstract contract Governor is Context, ERC165, EIP712, IGovernor {
+    using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
     using SafeCast for uint256;
     using Timers for Timers.BlockNumber;
 
@@ -40,12 +42,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},
+    // consummed 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 to governor executing address. Some module might override the _executor function to make
-     * sure this modifier is consistant with the execution model.
+     * @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 poping the expected operation - throw if deque is empty (operation not authorized)
+            while (_governanceCall.popFront() != msgDataHash) {}
+        }
         _;
     }
 
@@ -196,7 +215,7 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         string memory description
     ) public virtual override returns (uint256) {
         require(
-            getVotes(msg.sender, block.number - 1) >= proposalThreshold(),
+            getVotes(_msgSender(), block.number - 1) >= proposalThreshold(),
             "GovernorCompatibilityBravo: proposer votes below proposal threshold"
         );
 
@@ -250,7 +269,9 @@ 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;
     }
@@ -272,6 +293,42 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         }
     }
 
+    /**
+     * @dev Hook before execution is trigerred.
+     */
+    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 trigerred.
+     */
+    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.
@@ -370,7 +427,7 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         address target,
         uint256 value,
         bytes calldata data
-    ) external onlyGovernance {
+    ) external virtual onlyGovernance {
         Address.functionCallWithValue(target, data, value);
     }
 

+ 2 - 2
contracts/governance/IGovernor.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/IGovernor.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/IGovernor.sol)
 
 pragma solidity ^0.8.0;
 
@@ -193,7 +193,7 @@ abstract contract IGovernor is IERC165 {
     function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);
 
     /**
-     * @dev Cast a with a reason
+     * @dev Cast a vote with a reason
      *
      * Emits a {VoteCast} event.
      */

+ 4 - 0
contracts/governance/README.adoc

@@ -84,6 +84,10 @@ NOTE: Functions of the `Governor` contract do not include access control. If you
 
 {{GovernorProposalThreshold}}
 
+== Utils
+
+{{Votes}}
+
 == Timelock
 
 In a governance system, the {TimelockController} contract is in charge of introducing a delay between a proposal and its execution. It can be used with or without a {Governor}.

+ 4 - 1
contracts/governance/TimelockController.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/TimelockController.sol)
+// OpenZeppelin Contracts v4.4.1 (governance/TimelockController.sol)
 
 pragma solidity ^0.8.0;
 
@@ -261,6 +261,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,

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/compatibility/GovernorCompatibilityBravo.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/compatibility/GovernorCompatibilityBravo.sol)
 
 pragma solidity ^0.8.0;
 
@@ -132,7 +132,7 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
         for (uint256 i = 0; i < signatures.length; ++i) {
             fullcalldatas[i] = bytes(signatures[i]).length == 0
                 ? calldatas[i]
-                : abi.encodeWithSignature(signatures[i], calldatas[i]);
+                : abi.encodePacked(bytes4(keccak256(bytes(signatures[i]))), calldatas[i]);
         }
 
         return fullcalldatas;

+ 1 - 1
contracts/governance/compatibility/IGovernorCompatibilityBravo.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/compatibility/IGovernorCompatibilityBravo.sol)
+// OpenZeppelin Contracts v4.4.1 (governance/compatibility/IGovernorCompatibilityBravo.sol)
 
 pragma solidity ^0.8.0;
 

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/extensions/GovernorCountingSimple.sol)
+// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorCountingSimple.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 0
contracts/governance/extensions/GovernorPreventLateQuorum.sol

@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorPreventLateQuorum.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/governance/extensions/GovernorProposalThreshold.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/extensions/GovernorProposalThreshold.sol)
+// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorProposalThreshold.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/governance/extensions/GovernorSettings.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/extensions/GovernorSettings.sol)
+// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorSettings.sol)
 
 pragma solidity ^0.8.0;
 

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/extensions/GovernorTimelockCompound.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorTimelockCompound.sol)
 
 pragma solidity ^0.8.0;
 
@@ -224,14 +224,16 @@ abstract contract GovernorTimelockCompound is IGovernorTimelock, Governor {
 
     /**
      * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
-     * must be proposed, scheduled and executed using the {Governor} workflow.
+     * must be proposed, scheduled, and executed through governance proposals.
      *
-     * For security reason, the timelock must be handed over to another admin before setting up a new one. The two
+     * For security reasons, the timelock must be handed over to another admin before setting up a new one. The two
      * operations (hand over the timelock) and do the update can be batched in a single proposal.
      *
      * Note that if the timelock admin has been handed over in a previous operation, we refuse updates made through the
      * timelock if admin of the timelock has already been accepted and the operation is executed outside the scope of
      * governance.
+
+     * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
      */
     function updateTimelock(ICompoundTimelock newTimelock) external virtual onlyGovernance {
         _updateTimelock(newTimelock);

+ 13 - 3
contracts/governance/extensions/GovernorTimelockControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/extensions/GovernorTimelockControl.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorTimelockControl.sol)
 
 pragma solidity ^0.8.0;
 
@@ -10,12 +10,17 @@ import "../TimelockController.sol";
 /**
  * @dev Extension of {Governor} that binds the execution process to an instance of {TimelockController}. This adds a
  * delay, enforced by the {TimelockController} to all successful proposal (in addition to the voting duration). The
- * {Governor} needs the proposer (an ideally the executor) roles for the {Governor} to work properly.
+ * {Governor} needs the proposer (and ideally the executor) roles for the {Governor} to work properly.
  *
  * Using this model means the proposal will be operated by the {TimelockController} and not by the {Governor}. Thus,
  * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be
  * inaccessible.
  *
+ * WARNING: Setting up the TimelockController to have additional proposers besides the governor is very risky, as it
+ * grants them powers that they must be trusted or known not to use: 1) {onlyGovernance} functions like {relay} are
+ * available to them through the timelock, and 2) approved governance proposals can be blocked by them, effectively
+ * executing a Denial of Service attack. This risk will be mitigated in a future release.
+ *
  * _Available since v4.3._
  */
 abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
@@ -118,6 +123,9 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
      * @dev Overriden 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,
@@ -143,7 +151,9 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
 
     /**
      * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates
-     * must be proposed, scheduled and executed using the {Governor} workflow.
+     * must be proposed, scheduled, and executed through governance proposals.
+     *
+     * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals.
      */
     function updateTimelock(TimelockController newTimelock) external virtual onlyGovernance {
         _updateTimelock(newTimelock);

+ 5 - 6
contracts/governance/extensions/GovernorVotes.sol

@@ -1,21 +1,20 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/extensions/GovernorVotes.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotes.sol)
 
 pragma solidity ^0.8.0;
 
 import "../Governor.sol";
-import "../../token/ERC20/extensions/ERC20Votes.sol";
-import "../../utils/math/Math.sol";
+import "../utils/IVotes.sol";
 
 /**
- * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token.
+ * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token.
  *
  * _Available since v4.3._
  */
 abstract contract GovernorVotes is Governor {
-    ERC20Votes public immutable token;
+    IVotes public immutable token;
 
-    constructor(ERC20Votes tokenAddress) {
+    constructor(IVotes tokenAddress) {
         token = tokenAddress;
     }
 

+ 1 - 1
contracts/governance/extensions/GovernorVotesComp.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/extensions/GovernorVotesComp.sol)
+// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorVotesComp.sol)
 
 pragma solidity ^0.8.0;
 

+ 36 - 1
contracts/governance/extensions/GovernorVotesQuorumFraction.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/extensions/GovernorVotesQuorumFraction.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorVotesQuorumFraction.sol)
 
 pragma solidity ^0.8.0;
 
@@ -16,26 +16,61 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes {
 
     event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);
 
+    /**
+     * @dev Initialize quorum as a fraction of the token's total supply.
+     *
+     * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is
+     * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be
+     * customized by overriding {quorumDenominator}.
+     */
     constructor(uint256 quorumNumeratorValue) {
         _updateQuorumNumerator(quorumNumeratorValue);
     }
 
+    /**
+     * @dev Returns the current quorum numerator. See {quorumDenominator}.
+     */
     function quorumNumerator() public view virtual returns (uint256) {
         return _quorumNumerator;
     }
 
+    /**
+     * @dev Returns the quorum denominator. Defaults to 100, but may be overridden.
+     */
     function quorumDenominator() public view virtual returns (uint256) {
         return 100;
     }
 
+    /**
+     * @dev Returns the quorum for a block number, in terms of number of votes: `supply * numerator / denominator`.
+     */
     function quorum(uint256 blockNumber) public view virtual override returns (uint256) {
         return (token.getPastTotalSupply(blockNumber) * quorumNumerator()) / quorumDenominator();
     }
 
+    /**
+     * @dev Changes the quorum numerator.
+     *
+     * Emits a {QuorumNumeratorUpdated} event.
+     *
+     * Requirements:
+     *
+     * - Must be called through a governance proposal.
+     * - New numerator must be smaller or equal to the denominator.
+     */
     function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {
         _updateQuorumNumerator(newQuorumNumerator);
     }
 
+    /**
+     * @dev Changes the quorum numerator.
+     *
+     * Emits a {QuorumNumeratorUpdated} event.
+     *
+     * Requirements:
+     *
+     * - New numerator must be smaller or equal to the denominator.
+     */
     function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {
         require(
             newQuorumNumerator <= quorumDenominator(),

+ 1 - 1
contracts/governance/extensions/IGovernorTimelock.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (governance/extensions/IGovernorTimelock.sol)
+// OpenZeppelin Contracts v4.4.1 (governance/extensions/IGovernorTimelock.sol)
 
 pragma solidity ^0.8.0;
 

+ 61 - 0
contracts/governance/utils/IVotes.sol

@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)
+pragma solidity ^0.8.0;
+
+/**
+ * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
+ *
+ * _Available since v4.5._
+ */
+interface IVotes {
+    /**
+     * @dev Emitted when an account changes their delegate.
+     */
+    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
+
+    /**
+     * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
+     */
+    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);
+
+    /**
+     * @dev Returns the current amount of votes that `account` has.
+     */
+    function getVotes(address account) external view returns (uint256);
+
+    /**
+     * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).
+     */
+    function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);
+
+    /**
+     * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).
+     *
+     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
+     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
+     * vote.
+     */
+    function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);
+
+    /**
+     * @dev Returns the delegate that `account` has chosen.
+     */
+    function delegates(address account) external view returns (address);
+
+    /**
+     * @dev Delegates votes from the sender to `delegatee`.
+     */
+    function delegate(address delegatee) external;
+
+    /**
+     * @dev Delegates votes from signer to `delegatee`.
+     */
+    function delegateBySig(
+        address delegatee,
+        uint256 nonce,
+        uint256 expiry,
+        uint8 v,
+        bytes32 r,
+        bytes32 s
+    ) external;
+}

+ 211 - 0
contracts/governance/utils/Votes.sol

@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/Votes.sol)
+pragma solidity ^0.8.0;
+
+import "../../utils/Context.sol";
+import "../../utils/Counters.sol";
+import "../../utils/Checkpoints.sol";
+import "../../utils/cryptography/draft-EIP712.sol";
+import "./IVotes.sol";
+
+/**
+ * @dev This is a base abstract contract that tracks voting units, which are a measure of voting power that can be
+ * transferred, and provides a system of vote delegation, where an account can delegate its voting units to a sort of
+ * "representative" that will pool delegated voting units from different accounts and can then use it to vote in
+ * decisions. In fact, voting units _must_ be delegated in order to count as actual votes, and an account has to
+ * delegate those votes to itself if it wishes to participate in decisions and does not have a trusted representative.
+ *
+ * This contract is often combined with a token contract such that voting units correspond to token units. For an
+ * example, see {ERC721Votes}.
+ *
+ * The full history of delegate votes is tracked on-chain so that governance protocols can consider votes as distributed
+ * at a particular block number to protect against flash loans and double voting. The opt-in delegate system makes the
+ * cost of this history tracking optional.
+ *
+ * When using this module the derived contract must implement {_getVotingUnits} (for example, make it return
+ * {ERC721-balanceOf}), and can use {_transferVotingUnits} to track a change in the distribution of those units (in the
+ * previous example, it would be included in {ERC721-_beforeTokenTransfer}).
+ *
+ * _Available since v4.5._
+ */
+abstract contract Votes is IVotes, Context, EIP712 {
+    using Checkpoints for Checkpoints.History;
+    using Counters for Counters.Counter;
+
+    bytes32 private constant _DELEGATION_TYPEHASH =
+        keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
+
+    mapping(address => address) private _delegation;
+    mapping(address => Checkpoints.History) private _delegateCheckpoints;
+    Checkpoints.History private _totalCheckpoints;
+
+    mapping(address => Counters.Counter) private _nonces;
+
+    /**
+     * @dev Returns the current amount of votes that `account` has.
+     */
+    function getVotes(address account) public view virtual override returns (uint256) {
+        return _delegateCheckpoints[account].latest();
+    }
+
+    /**
+     * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).
+     *
+     * Requirements:
+     *
+     * - `blockNumber` must have been already mined
+     */
+    function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
+        return _delegateCheckpoints[account].getAtBlock(blockNumber);
+    }
+
+    /**
+     * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).
+     *
+     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
+     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
+     * vote.
+     *
+     * Requirements:
+     *
+     * - `blockNumber` must have been already mined
+     */
+    function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {
+        require(blockNumber < block.number, "Votes: block not yet mined");
+        return _totalCheckpoints.getAtBlock(blockNumber);
+    }
+
+    /**
+     * @dev Returns the current total supply of votes.
+     */
+    function _getTotalSupply() internal view virtual returns (uint256) {
+        return _totalCheckpoints.latest();
+    }
+
+    /**
+     * @dev Returns the delegate that `account` has chosen.
+     */
+    function delegates(address account) public view virtual override returns (address) {
+        return _delegation[account];
+    }
+
+    /**
+     * @dev Delegates votes from the sender to `delegatee`.
+     */
+    function delegate(address delegatee) public virtual override {
+        address account = _msgSender();
+        _delegate(account, delegatee);
+    }
+
+    /**
+     * @dev Delegates votes from signer to `delegatee`.
+     */
+    function delegateBySig(
+        address delegatee,
+        uint256 nonce,
+        uint256 expiry,
+        uint8 v,
+        bytes32 r,
+        bytes32 s
+    ) public virtual override {
+        require(block.timestamp <= expiry, "Votes: signature expired");
+        address signer = ECDSA.recover(
+            _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),
+            v,
+            r,
+            s
+        );
+        require(nonce == _useNonce(signer), "Votes: invalid nonce");
+        _delegate(signer, delegatee);
+    }
+
+    /**
+     * @dev Delegate all of `account`'s voting units to `delegatee`.
+     *
+     * Emits events {DelegateChanged} and {DelegateVotesChanged}.
+     */
+    function _delegate(address account, address delegatee) internal virtual {
+        address oldDelegate = delegates(account);
+        _delegation[account] = delegatee;
+
+        emit DelegateChanged(account, oldDelegate, delegatee);
+        _moveDelegateVotes(oldDelegate, delegatee, _getVotingUnits(account));
+    }
+
+    /**
+     * @dev Transfers, mints, or burns voting units. To register a mint, `from` should be zero. To register a burn, `to`
+     * should be zero. Total supply of voting units will be adjusted with mints and burns.
+     */
+    function _transferVotingUnits(
+        address from,
+        address to,
+        uint256 amount
+    ) internal virtual {
+        if (from == address(0)) {
+            _totalCheckpoints.push(_add, amount);
+        }
+        if (to == address(0)) {
+            _totalCheckpoints.push(_subtract, amount);
+        }
+        _moveDelegateVotes(delegates(from), delegates(to), amount);
+    }
+
+    /**
+     * @dev Moves delegated votes from one delegate to another.
+     */
+    function _moveDelegateVotes(
+        address from,
+        address to,
+        uint256 amount
+    ) private {
+        if (from != to && amount > 0) {
+            if (from != address(0)) {
+                (uint256 oldValue, uint256 newValue) = _delegateCheckpoints[from].push(_subtract, amount);
+                emit DelegateVotesChanged(from, oldValue, newValue);
+            }
+            if (to != address(0)) {
+                (uint256 oldValue, uint256 newValue) = _delegateCheckpoints[to].push(_add, amount);
+                emit DelegateVotesChanged(to, oldValue, newValue);
+            }
+        }
+    }
+
+    function _add(uint256 a, uint256 b) private pure returns (uint256) {
+        return a + b;
+    }
+
+    function _subtract(uint256 a, uint256 b) private pure returns (uint256) {
+        return a - b;
+    }
+
+    /**
+     * @dev Consumes a nonce.
+     *
+     * Returns the current value and increments nonce.
+     */
+    function _useNonce(address owner) internal virtual returns (uint256 current) {
+        Counters.Counter storage nonce = _nonces[owner];
+        current = nonce.current();
+        nonce.increment();
+    }
+
+    /**
+     * @dev Returns an address nonce.
+     */
+    function nonces(address owner) public view virtual returns (uint256) {
+        return _nonces[owner].current();
+    }
+
+    /**
+     * @dev Returns the contract's {EIP712} domain separator.
+     */
+    // solhint-disable-next-line func-name-mixedcase
+    function DOMAIN_SEPARATOR() external view returns (bytes32) {
+        return _domainSeparatorV4();
+    }
+
+    /**
+     * @dev Must return the voting units held by an account.
+     */
+    function _getVotingUnits(address) internal virtual returns (uint256);
+}

+ 1 - 1
contracts/interfaces/IERC1155.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC1155.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC1155MetadataURI.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC1155MetadataURI.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155MetadataURI.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC1155Receiver.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC1155Receiver.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155Receiver.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC1271.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC1271.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC1363.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC1363.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1363.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC1363Receiver.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC1363Receiver.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1363Receiver.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC1363Spender.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC1363Spender.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1363Spender.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC165.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC165.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC1820Implementer.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC1820Implementer.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1820Implementer.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC1820Registry.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC1820Registry.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1820Registry.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC20.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC20.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC20Metadata.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC20Metadata.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20Metadata.sol)
 
 pragma solidity ^0.8.0;
 

+ 10 - 8
contracts/interfaces/IERC2981.sol

@@ -1,20 +1,22 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC2981.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/IERC2981.sol)
 
 pragma solidity ^0.8.0;
 
-import "./IERC165.sol";
+import "../utils/introspection/IERC165.sol";
 
 /**
- * @dev Interface for the NFT Royalty Standard
+ * @dev Interface for the NFT Royalty Standard.
+ *
+ * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
+ * support for royalty payments across all NFT marketplaces and ecosystem participants.
+ *
+ * _Available since v4.5._
  */
 interface IERC2981 is IERC165 {
     /**
-     * @dev Called with the sale price to determine how much royalty is owed and to whom.
-     * @param tokenId - the NFT asset queried for royalty information
-     * @param salePrice - the sale price of the NFT asset specified by `tokenId`
-     * @return receiver - address of who should be sent the royalty payment
-     * @return royaltyAmount - the royalty payment amount for `salePrice`
+     * @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.
      */
     function royaltyInfo(uint256 tokenId, uint256 salePrice)
         external

+ 1 - 1
contracts/interfaces/IERC3156.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC3156.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC3156FlashBorrower.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC3156FlashBorrower.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashBorrower.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC3156FlashLender.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC3156FlashLender.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashLender.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC721.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC721.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC721Enumerable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC721Enumerable.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Enumerable.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC721Metadata.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC721Metadata.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Metadata.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC721Receiver.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC721Receiver.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Receiver.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC777.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC777.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC777.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC777Recipient.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC777Recipient.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC777Recipient.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/IERC777Sender.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/IERC777Sender.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/IERC777Sender.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/interfaces/README.adoc

@@ -5,7 +5,7 @@ NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/
 
 == List of standardized interfaces
 These interfaces are available as `.sol` files, and also as compiler `.json` ABI files (through the npm package). These
-are usefull to interract with third party contracts that implement them.
+are useful to interact with third party contracts that implement them.
 
 - {IERC20}
 - {IERC20Metadata}

+ 20 - 0
contracts/interfaces/draft-IERC1822.sol

@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
+
+pragma solidity ^0.8.0;
+
+/**
+ * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
+ * proxy whose upgrades are fully controlled by the current implementation.
+ */
+interface IERC1822Proxiable {
+    /**
+     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
+     * address.
+     *
+     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
+     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
+     * function revert if invoked through a proxy.
+     */
+    function proxiableUUID() external view returns (bytes32);
+}

+ 1 - 1
contracts/interfaces/draft-IERC2612.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (interfaces/draft-IERC2612.sol)
+// OpenZeppelin Contracts v4.4.1 (interfaces/draft-IERC2612.sol)
 
 pragma solidity ^0.8.0;
 

+ 5 - 3
contracts/metatx/ERC2771Context.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (metatx/ERC2771Context.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (metatx/ERC2771Context.sol)
 
-pragma solidity ^0.8.0;
+pragma solidity ^0.8.9;
 
 import "../utils/Context.sol";
 
@@ -9,8 +9,10 @@ import "../utils/Context.sol";
  * @dev Context variant with ERC2771 support.
  */
 abstract contract ERC2771Context is Context {
-    address private _trustedForwarder;
+    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
+    address private immutable _trustedForwarder;
 
+    /// @custom:oz-upgrades-unsafe-allow constructor
     constructor(address trustedForwarder) {
         _trustedForwarder = trustedForwarder;
     }

+ 10 - 2
contracts/metatx/MinimalForwarder.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (metatx/MinimalForwarder.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (metatx/MinimalForwarder.sol)
 
 pragma solidity ^0.8.0;
 
@@ -50,9 +50,17 @@ contract MinimalForwarder is EIP712 {
         (bool success, bytes memory returndata) = req.to.call{gas: req.gas, value: req.value}(
             abi.encodePacked(req.data, req.from)
         );
+
         // Validate that the relayer has sent enough gas for the call.
         // See https://ronan.eth.link/blog/ethereum-gas-dangers/
-        assert(gasleft() > req.gas / 63);
+        if (gasleft() <= req.gas / 63) {
+            // We explicitly trigger invalid opcode to consume all gas and bubble-up the effects, since
+            // neither revert or assert consume all gas since Solidity 0.8.0
+            // https://docs.soliditylang.org/en/v0.8.0/control-structures.html#panic-via-assert-and-error-via-require
+            assembly {
+                invalid()
+            }
+        }
 
         return (success, returndata);
     }

+ 11 - 0
contracts/mocks/Base64Mock.sol

@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../utils/Base64.sol";
+
+contract Base64Mock {
+    function encode(bytes memory value) external pure returns (string memory) {
+        return Base64.encode(value);
+    }
+}

+ 7 - 0
contracts/mocks/CallReceiverMock.sol

@@ -6,6 +6,7 @@ contract CallReceiverMock {
     string public sharedAnswer;
 
     event MockFunctionCalled();
+    event MockFunctionCalledWithArgs(uint256 a, uint256 b);
 
     uint256[] private _array;
 
@@ -15,6 +16,12 @@ contract CallReceiverMock {
         return "0x1234";
     }
 
+    function mockFunctionWithArgs(uint256 a, uint256 b) public payable returns (string memory) {
+        emit MockFunctionCalledWithArgs(a, b);
+
+        return "0x1234";
+    }
+
     function mockFunctionNonPayable() public returns (string memory) {
         emit MockFunctionCalled();
 

+ 23 - 0
contracts/mocks/CheckpointsImpl.sol

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

+ 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();
+    }
+}

+ 5 - 2
contracts/mocks/ERC2771ContextMock.sol

@@ -1,13 +1,16 @@
 // SPDX-License-Identifier: MIT
 
-pragma solidity ^0.8.0;
+pragma solidity ^0.8.9;
 
 import "./ContextMock.sol";
 import "../metatx/ERC2771Context.sol";
 
 // By inheriting from ERC2771Context, Context's internal functions are overridden automatically
 contract ERC2771ContextMock is ContextMock, ERC2771Context {
-    constructor(address trustedForwarder) ERC2771Context(trustedForwarder) {}
+    /// @custom:oz-upgrades-unsafe-allow constructor
+    constructor(address trustedForwarder) ERC2771Context(trustedForwarder) {
+        emit Sender(_msgSender()); // _msgSender() should be accessible during construction
+    }
 
     function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address) {
         return ERC2771Context._msgSender();

+ 33 - 0
contracts/mocks/ERC721RoyaltyMock.sol

@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../token/ERC721/extensions/ERC721Royalty.sol";
+
+contract ERC721RoyaltyMock is ERC721Royalty {
+    constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
+
+    function setTokenRoyalty(
+        uint256 tokenId,
+        address recipient,
+        uint96 fraction
+    ) public {
+        _setTokenRoyalty(tokenId, recipient, fraction);
+    }
+
+    function setDefaultRoyalty(address recipient, uint96 fraction) public {
+        _setDefaultRoyalty(recipient, fraction);
+    }
+
+    function mint(address to, uint256 tokenId) public {
+        _mint(to, tokenId);
+    }
+
+    function burn(uint256 tokenId) public {
+        _burn(tokenId);
+    }
+
+    function deleteDefaultRoyalty() public {
+        _deleteDefaultRoyalty();
+    }
+}

+ 25 - 0
contracts/mocks/ERC721VotesMock.sol

@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../token/ERC721/extensions/draft-ERC721Votes.sol";
+
+contract ERC721VotesMock is ERC721Votes {
+    constructor(string memory name, string memory symbol) ERC721(name, symbol) EIP712(name, "1") {}
+
+    function getTotalSupply() public view returns (uint256) {
+        return _getTotalSupply();
+    }
+
+    function mint(address account, uint256 tokenId) public {
+        _mint(account, tokenId);
+    }
+
+    function burn(uint256 tokenId) public {
+        _burn(tokenId);
+    }
+
+    function getChainId() external view returns (uint256) {
+        return block.chainid;
+    }
+}

+ 41 - 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,42 @@ 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);
+    }
+}

+ 1 - 1
contracts/mocks/GovernorMock.sol

@@ -15,7 +15,7 @@ contract GovernorMock is
 {
     constructor(
         string memory name_,
-        ERC20Votes token_,
+        IVotes token_,
         uint256 votingDelay_,
         uint256 votingPeriod_,
         uint256 quorumNumerator_

+ 1 - 1
contracts/mocks/GovernorPreventLateQuorumMock.sol

@@ -17,7 +17,7 @@ contract GovernorPreventLateQuorumMock is
 
     constructor(
         string memory name_,
-        ERC20Votes token_,
+        IVotes token_,
         uint256 votingDelay_,
         uint256 votingPeriod_,
         uint256 quorum_,

+ 1 - 1
contracts/mocks/GovernorTimelockCompoundMock.sol

@@ -15,7 +15,7 @@ contract GovernorTimelockCompoundMock is
 {
     constructor(
         string memory name_,
-        ERC20Votes token_,
+        IVotes token_,
         uint256 votingDelay_,
         uint256 votingPeriod_,
         ICompoundTimelock timelock_,

+ 3 - 1
contracts/mocks/GovernorTimelockControlMock.sol

@@ -15,7 +15,7 @@ contract GovernorTimelockControlMock is
 {
     constructor(
         string memory name_,
-        ERC20Votes token_,
+        IVotes token_,
         uint256 votingDelay_,
         uint256 votingPeriod_,
         TimelockController timelock_,
@@ -105,4 +105,6 @@ contract GovernorTimelockControlMock is
     function _executor() internal view virtual override(Governor, GovernorTimelockControl) returns (address) {
         return super._executor();
     }
+
+    function nonGovernanceFunction() external {}
 }

+ 41 - 0
contracts/mocks/GovernorVoteMock.sol

@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../governance/extensions/GovernorCountingSimple.sol";
+import "../governance/extensions/GovernorVotes.sol";
+
+contract GovernorVoteMocks is GovernorVotes, GovernorCountingSimple {
+    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 cancel(
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        bytes32 salt
+    ) 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);
+    }
+}

+ 28 - 1
contracts/mocks/InitializableMock.sol

@@ -10,16 +10,25 @@ import "../proxy/utils/Initializable.sol";
  */
 contract InitializableMock is Initializable {
     bool public initializerRan;
+    bool public onlyInitializingRan;
     uint256 public x;
 
     function initialize() public initializer {
         initializerRan = true;
     }
 
-    function initializeNested() public initializer {
+    function initializeOnlyInitializing() public onlyInitializing {
+        onlyInitializingRan = true;
+    }
+
+    function initializerNested() public initializer {
         initialize();
     }
 
+    function onlyInitializingNested() public initializer {
+        initializeOnlyInitializing();
+    }
+
     function initializeWithX(uint256 _x) public payable initializer {
         x = _x;
     }
@@ -32,3 +41,21 @@ contract InitializableMock is Initializable {
         require(false, "InitializableMock forced failure");
     }
 }
+
+contract ConstructorInitializableMock is Initializable {
+    bool public initializerRan;
+    bool public onlyInitializingRan;
+
+    constructor() initializer {
+        initialize();
+        initializeOnlyInitializing();
+    }
+
+    function initialize() public initializer {
+        initializerRan = true;
+    }
+
+    function initializeOnlyInitializing() public onlyInitializing {
+        onlyInitializingRan = true;
+    }
+}

+ 0 - 4
contracts/mocks/MathMock.sol

@@ -20,8 +20,4 @@ contract MathMock {
     function ceilDiv(uint256 a, uint256 b) public pure returns (uint256) {
         return Math.ceilDiv(a, b);
     }
-
-    function abs(int256 n) public pure returns (uint256) {
-        return Math.abs(n);
-    }
 }

+ 60 - 5
contracts/mocks/MultipleInheritanceInitializableMocks.sol

@@ -22,6 +22,16 @@ contract SampleHuman is Initializable {
     bool public isHuman;
 
     function initialize() public initializer {
+        __SampleHuman_init();
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __SampleHuman_init() internal onlyInitializing {
+        __SampleHuman_init_unchained();
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __SampleHuman_init_unchained() internal onlyInitializing {
         isHuman = true;
     }
 }
@@ -33,7 +43,17 @@ contract SampleMother is Initializable, SampleHuman {
     uint256 public mother;
 
     function initialize(uint256 value) public virtual initializer {
-        SampleHuman.initialize();
+        __SampleMother_init(value);
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __SampleMother_init(uint256 value) internal onlyInitializing {
+        __SampleHuman_init();
+        __SampleMother_init_unchained(value);
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __SampleMother_init_unchained(uint256 value) internal onlyInitializing {
         mother = value;
     }
 }
@@ -45,7 +65,17 @@ contract SampleGramps is Initializable, SampleHuman {
     string public gramps;
 
     function initialize(string memory value) public virtual initializer {
-        SampleHuman.initialize();
+        __SampleGramps_init(value);
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __SampleGramps_init(string memory value) internal onlyInitializing {
+        __SampleHuman_init();
+        __SampleGramps_init_unchained(value);
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __SampleGramps_init_unchained(string memory value) internal onlyInitializing {
         gramps = value;
     }
 }
@@ -57,7 +87,17 @@ contract SampleFather is Initializable, SampleGramps {
     uint256 public father;
 
     function initialize(string memory _gramps, uint256 _father) public initializer {
-        SampleGramps.initialize(_gramps);
+        __SampleFather_init(_gramps, _father);
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __SampleFather_init(string memory _gramps, uint256 _father) internal onlyInitializing {
+        __SampleGramps_init(_gramps);
+        __SampleFather_init_unchained(_father);
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __SampleFather_init_unchained(uint256 _father) internal onlyInitializing {
         father = _father;
     }
 }
@@ -74,8 +114,23 @@ contract SampleChild is Initializable, SampleMother, SampleFather {
         uint256 _father,
         uint256 _child
     ) public initializer {
-        SampleMother.initialize(_mother);
-        SampleFather.initialize(_gramps, _father);
+        __SampleChild_init(_mother, _gramps, _father, _child);
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __SampleChild_init(
+        uint256 _mother,
+        string memory _gramps,
+        uint256 _father,
+        uint256 _child
+    ) internal onlyInitializing {
+        __SampleMother_init(_mother);
+        __SampleFather_init(_gramps, _father);
+        __SampleChild_init_unchained(_child);
+    }
+
+    // solhint-disable-next-line func-name-mixedcase
+    function __SampleChild_init_unchained(uint256 _child) internal onlyInitializing {
         child = _child;
     }
 }

+ 1 - 1
contracts/mocks/SafeERC20Helper.sol

@@ -33,7 +33,7 @@ contract ERC20ReturnFalseMock is Context {
     }
 
     function allowance(address, address) public view returns (uint256) {
-        require(_dummy == 0); // Duummy read from a state variable so that the function is view
+        require(_dummy == 0); // Dummy read from a state variable so that the function is view
         return 0;
     }
 }

+ 23 - 0
contracts/mocks/SignedMathMock.sol

@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../utils/math/SignedMath.sol";
+
+contract SignedMathMock {
+    function max(int256 a, int256 b) public pure returns (int256) {
+        return SignedMath.max(a, b);
+    }
+
+    function min(int256 a, int256 b) public pure returns (int256) {
+        return SignedMath.min(a, b);
+    }
+
+    function average(int256 a, int256 b) public pure returns (int256) {
+        return SignedMath.average(a, b);
+    }
+
+    function abs(int256 n) public pure returns (uint256) {
+        return SignedMath.abs(n);
+    }
+}

+ 58 - 0
contracts/mocks/UUPS/UUPSLegacy.sol

@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "./UUPSUpgradeableMock.sol";
+
+// This contract implements the pre-4.5 UUPS upgrade function with a rollback test.
+// It's used to test that newer UUPS contracts are considered valid upgrades by older UUPS contracts.
+contract UUPSUpgradeableLegacyMock is UUPSUpgradeableMock {
+    // Inlined from ERC1967Upgrade
+    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
+
+    // ERC1967Upgrade._setImplementation is private so we reproduce it here.
+    // An extra underscore prevents a name clash error.
+    function __setImplementation(address newImplementation) private {
+        require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
+        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
+    }
+
+    function _upgradeToAndCallSecureLegacyV1(
+        address newImplementation,
+        bytes memory data,
+        bool forceCall
+    ) internal {
+        address oldImplementation = _getImplementation();
+
+        // Initial upgrade and setup call
+        __setImplementation(newImplementation);
+        if (data.length > 0 || forceCall) {
+            Address.functionDelegateCall(newImplementation, data);
+        }
+
+        // Perform rollback test if not already in progress
+        StorageSlot.BooleanSlot storage rollbackTesting = StorageSlot.getBooleanSlot(_ROLLBACK_SLOT);
+        if (!rollbackTesting.value) {
+            // Trigger rollback using upgradeTo from the new implementation
+            rollbackTesting.value = true;
+            Address.functionDelegateCall(
+                newImplementation,
+                abi.encodeWithSignature("upgradeTo(address)", oldImplementation)
+            );
+            rollbackTesting.value = false;
+            // Check rollback was effective
+            require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades");
+            // Finally reset to the new implementation and log the upgrade
+            _upgradeTo(newImplementation);
+        }
+    }
+
+    // hooking into the old mechanism
+    function upgradeTo(address newImplementation) external virtual override {
+        _upgradeToAndCallSecureLegacyV1(newImplementation, bytes(""), false);
+    }
+
+    function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual override {
+        _upgradeToAndCallSecureLegacyV1(newImplementation, data, false);
+    }
+}

+ 0 - 10
contracts/mocks/UUPS/TestInProd.sol → contracts/mocks/UUPS/UUPSUpgradeableMock.sol

@@ -19,13 +19,3 @@ contract UUPSUpgradeableUnsafeMock is UUPSUpgradeableMock {
         ERC1967Upgrade._upgradeToAndCall(newImplementation, data, false);
     }
 }
-
-contract UUPSUpgradeableBrokenMock is UUPSUpgradeableMock {
-    function upgradeTo(address) external virtual override {
-        // pass
-    }
-
-    function upgradeToAndCall(address, bytes memory) external payable virtual override {
-        // pass
-    }
-}

+ 40 - 0
contracts/mocks/VotesMock.sol

@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../governance/utils/Votes.sol";
+
+contract VotesMock is Votes {
+    mapping(address => uint256) private _balances;
+    mapping(uint256 => address) private _owners;
+
+    constructor(string memory name) EIP712(name, "1") {}
+
+    function getTotalSupply() public view returns (uint256) {
+        return _getTotalSupply();
+    }
+
+    function delegate(address account, address newDelegation) public {
+        return _delegate(account, newDelegation);
+    }
+
+    function _getVotingUnits(address account) internal virtual override returns (uint256) {
+        return _balances[account];
+    }
+
+    function mint(address account, uint256 voteId) external {
+        _balances[account] += 1;
+        _owners[voteId] = account;
+        _transferVotingUnits(address(0), account, 1);
+    }
+
+    function burn(uint256 voteId) external {
+        address owner = _owners[voteId];
+        _balances[owner] -= 1;
+        _transferVotingUnits(owner, address(0), 1);
+    }
+
+    function getChainId() external view returns (uint256) {
+        return block.chainid;
+    }
+}

+ 1 - 1
contracts/mocks/wizard/MyGovernor1.sol

@@ -14,7 +14,7 @@ contract MyGovernor1 is
     GovernorVotesQuorumFraction,
     GovernorCountingSimple
 {
-    constructor(ERC20Votes _token, TimelockController _timelock)
+    constructor(IVotes _token, TimelockController _timelock)
         Governor("MyGovernor")
         GovernorVotes(_token)
         GovernorVotesQuorumFraction(4)

+ 1 - 1
contracts/mocks/wizard/MyGovernor2.sol

@@ -16,7 +16,7 @@ contract MyGovernor2 is
     GovernorVotesQuorumFraction,
     GovernorCountingSimple
 {
-    constructor(ERC20Votes _token, TimelockController _timelock)
+    constructor(IVotes _token, TimelockController _timelock)
         Governor("MyGovernor")
         GovernorVotes(_token)
         GovernorVotesQuorumFraction(4)

+ 1 - 1
contracts/mocks/wizard/MyGovernor3.sol

@@ -14,7 +14,7 @@ contract MyGovernor is
     GovernorVotes,
     GovernorVotesQuorumFraction
 {
-    constructor(ERC20Votes _token, TimelockController _timelock)
+    constructor(IVotes _token, TimelockController _timelock)
         Governor("MyGovernor")
         GovernorVotes(_token)
         GovernorVotesQuorumFraction(4)

+ 1 - 1
contracts/package.json

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

+ 1 - 1
contracts/proxy/Clones.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (proxy/Clones.sol)
+// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/proxy/ERC1967/ERC1967Proxy.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (proxy/ERC1967/ERC1967Proxy.sol)
+// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)
 
 pragma solidity ^0.8.0;
 

+ 15 - 24
contracts/proxy/ERC1967/ERC1967Upgrade.sol

@@ -1,9 +1,10 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (proxy/ERC1967/ERC1967Upgrade.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
 
 pragma solidity ^0.8.2;
 
 import "../beacon/IBeacon.sol";
+import "../../interfaces/draft-IERC1822.sol";
 import "../../utils/Address.sol";
 import "../../utils/StorageSlot.sol";
 
@@ -77,33 +78,23 @@ abstract contract ERC1967Upgrade {
      *
      * Emits an {Upgraded} event.
      */
-    function _upgradeToAndCallSecure(
+    function _upgradeToAndCallUUPS(
         address newImplementation,
         bytes memory data,
         bool forceCall
     ) internal {
-        address oldImplementation = _getImplementation();
-
-        // Initial upgrade and setup call
-        _setImplementation(newImplementation);
-        if (data.length > 0 || forceCall) {
-            Address.functionDelegateCall(newImplementation, data);
-        }
-
-        // Perform rollback test if not already in progress
-        StorageSlot.BooleanSlot storage rollbackTesting = StorageSlot.getBooleanSlot(_ROLLBACK_SLOT);
-        if (!rollbackTesting.value) {
-            // Trigger rollback using upgradeTo from the new implementation
-            rollbackTesting.value = true;
-            Address.functionDelegateCall(
-                newImplementation,
-                abi.encodeWithSignature("upgradeTo(address)", oldImplementation)
-            );
-            rollbackTesting.value = false;
-            // Check rollback was effective
-            require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades");
-            // Finally reset to the new implementation and log the upgrade
-            _upgradeTo(newImplementation);
+        // Upgrades from old implementations will perform a rollback test. This test requires the new
+        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
+        // this special case will break upgrade paths from old UUPS implementation to new ones.
+        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
+            _setImplementation(newImplementation);
+        } else {
+            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
+                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
+            } catch {
+                revert("ERC1967Upgrade: new implementation is not UUPS");
+            }
+            _upgradeToAndCall(newImplementation, data, forceCall);
         }
     }
 

+ 2 - 2
contracts/proxy/Proxy.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.0 (proxy/Proxy.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)
 
 pragma solidity ^0.8.0;
 
@@ -17,7 +17,7 @@ abstract contract Proxy {
     /**
      * @dev Delegates the current call to `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 _delegate(address implementation) internal virtual {
         assembly {

+ 4 - 2
contracts/proxy/README.adoc

@@ -17,14 +17,14 @@ In order to avoid clashes with the storage variables of the implementation contr
 There are two alternative ways to add upgradeability to an ERC1967 proxy. Their differences are explained below in <<transparent-vs-uups>>.
 
 - {TransparentUpgradeableProxy}: A proxy with a built in admin and upgrade interface.
-- {UUPSUpgradeable}: An upgradeability mechanism to be included in the implementation for an ERC1967 proxy.
+- {UUPSUpgradeable}: An upgradeability mechanism to be included in the implementation contract.
 
 CAUTION: Using upgradeable proxies correctly and securely is a difficult task that requires deep knowledge of the proxy pattern, Solidity, and the EVM. Unless you want a lot of low level control, we recommend using the xref:upgrades-plugins::index.adoc[OpenZeppelin Upgrades Plugins] for Truffle and Hardhat.
 
 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.
-- {UpgradeableBeacon}: A beacon contract that can be upgraded.
+- {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.
 
@@ -48,6 +48,8 @@ By default, the upgrade functionality included in {UUPSUpgradeable} contains a s
 - Adding a flag mechanism in the implementation that will disable the upgrade function when triggered.
 - Upgrading to an implementation that features an upgrade mechanism without the additional security check, and then upgrading again to another implementation without the upgrade mechanism.
 
+The current implementation of this security mechanism uses https://eips.ethereum.org/EIPS/eip-1822[EIP1822] to detect the storage slot used by the implementation. A previous implementation, now deprecated, relied on a rollback check. It is possible to upgrade from a contract using the old mechanism to a new one. The inverse is however not possible, as old implementations (before version 4.5) did not include the `ERC1822` interface.
+
 == Core
 
 {{Proxy}}

Some files were not shown because too many files changed in this diff