github-actions hace 3 años
padre
commit
0ac5176db0
Se han modificado 100 ficheros con 2969 adiciones y 261 borrados
  1. 5 0
      .gitignore
  2. 30 1
      CHANGELOG.md
  3. 1 1
      README.md
  4. 7 5
      SECURITY.md
  5. 24 0
      certora/Makefile
  6. 56 0
      certora/README.md
  7. 101 0
      certora/applyHarness.patch
  8. 28 0
      certora/harnesses/ERC20VotesHarness.sol
  9. 150 0
      certora/harnesses/WizardControlFirstPriority.sol
  10. 141 0
      certora/harnesses/WizardFirstTry.sol
  11. 2 0
      certora/munged/.gitignore
  12. 10 0
      certora/scripts/Governor.sh
  13. 10 0
      certora/scripts/GovernorCountingSimple-counting.sh
  14. 12 0
      certora/scripts/WizardControlFirstPriority.sh
  15. 10 0
      certora/scripts/WizardFirstTry.sh
  16. 14 0
      certora/scripts/sanity.sh
  17. 39 0
      certora/scripts/verifyAll.sh
  18. 334 0
      certora/specs/GovernorBase.spec
  19. 221 0
      certora/specs/GovernorCountingSimple.spec
  20. 139 0
      certora/specs/RulesInProgress.spec
  21. 14 0
      certora/specs/sanity.spec
  22. 4 4
      contracts/access/AccessControl.sol
  23. 3 3
      contracts/access/AccessControlEnumerable.sol
  24. 41 13
      contracts/governance/Governor.sol
  25. 2 2
      contracts/governance/IGovernor.sol
  26. 9 1
      contracts/governance/README.adoc
  27. 1 1
      contracts/governance/compatibility/GovernorCompatibilityBravo.sol
  28. 107 0
      contracts/governance/extensions/GovernorPreventLateQuorum.sol
  29. 5 3
      contracts/governance/extensions/GovernorTimelockCompound.sol
  30. 13 4
      contracts/governance/extensions/GovernorTimelockControl.sol
  31. 5 6
      contracts/governance/extensions/GovernorVotes.sol
  32. 36 1
      contracts/governance/extensions/GovernorVotesQuorumFraction.sol
  33. 61 0
      contracts/governance/utils/IVotes.sol
  34. 211 0
      contracts/governance/utils/Votes.sol
  35. 9 7
      contracts/interfaces/IERC2981.sol
  36. 1 1
      contracts/interfaces/README.adoc
  37. 20 0
      contracts/interfaces/draft-IERC1822.sol
  38. 5 3
      contracts/metatx/ERC2771Context.sol
  39. 10 2
      contracts/metatx/MinimalForwarder.sol
  40. 11 0
      contracts/mocks/Base64Mock.sol
  41. 23 0
      contracts/mocks/CheckpointsImpl.sol
  42. 5 2
      contracts/mocks/ERC2771ContextMock.sol
  43. 33 0
      contracts/mocks/ERC721RoyaltyMock.sol
  44. 25 0
      contracts/mocks/ERC721VotesMock.sol
  45. 1 1
      contracts/mocks/GovernorMock.sol
  46. 60 0
      contracts/mocks/GovernorPreventLateQuorumMock.sol
  47. 1 1
      contracts/mocks/GovernorTimelockCompoundMock.sol
  48. 1 1
      contracts/mocks/GovernorTimelockControlMock.sol
  49. 41 0
      contracts/mocks/GovernorVoteMock.sol
  50. 1 1
      contracts/mocks/SafeERC20Helper.sol
  51. 23 0
      contracts/mocks/SignedMathMock.sol
  52. 58 0
      contracts/mocks/UUPS/UUPSLegacy.sol
  53. 0 10
      contracts/mocks/UUPS/UUPSUpgradeableMock.sol
  54. 40 0
      contracts/mocks/VotesMock.sol
  55. 1 1
      contracts/mocks/wizard/MyGovernor1.sol
  56. 1 1
      contracts/mocks/wizard/MyGovernor2.sol
  57. 1 1
      contracts/mocks/wizard/MyGovernor3.sol
  58. 1 1
      contracts/package.json
  59. 15 24
      contracts/proxy/ERC1967/ERC1967Upgrade.sol
  60. 2 2
      contracts/proxy/Proxy.sol
  61. 4 2
      contracts/proxy/README.adoc
  62. 2 2
      contracts/proxy/utils/Initializable.sol
  63. 26 4
      contracts/proxy/utils/UUPSUpgradeable.sol
  64. 30 25
      contracts/token/ERC1155/IERC1155Receiver.sol
  65. 2 0
      contracts/token/ERC1155/README.adoc
  66. 3 1
      contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol
  67. 1 0
      contracts/token/ERC1155/presets/README.md
  68. 6 1
      contracts/token/ERC1155/utils/ERC1155Holder.sol
  69. 62 35
      contracts/token/ERC20/ERC20.sol
  70. 6 6
      contracts/token/ERC20/IERC20.sol
  71. 2 6
      contracts/token/ERC20/extensions/ERC20Burnable.sol
  72. 3 2
      contracts/token/ERC20/extensions/ERC20FlashMint.sol
  73. 9 18
      contracts/token/ERC20/extensions/ERC20Votes.sol
  74. 3 3
      contracts/token/ERC20/extensions/ERC20VotesComp.sol
  75. 3 1
      contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol
  76. 3 1
      contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol
  77. 1 0
      contracts/token/ERC20/presets/README.md
  78. 11 5
      contracts/token/ERC20/utils/TokenTimelock.sol
  79. 25 2
      contracts/token/ERC721/ERC721.sol
  80. 21 6
      contracts/token/ERC721/README.adoc
  81. 38 0
      contracts/token/ERC721/extensions/ERC721Royalty.sol
  82. 2 2
      contracts/token/ERC721/extensions/IERC721Enumerable.sol
  83. 40 0
      contracts/token/ERC721/extensions/draft-ERC721Votes.sol
  84. 3 1
      contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol
  85. 1 0
      contracts/token/ERC721/presets/README.md
  86. 32 6
      contracts/token/ERC777/ERC777.sol
  87. 118 0
      contracts/token/common/ERC2981.sol
  88. 10 0
      contracts/token/common/README.adoc
  89. 15 10
      contracts/utils/Address.sol
  90. 91 0
      contracts/utils/Base64.sol
  91. 86 0
      contracts/utils/Checkpoints.sol
  92. 2 2
      contracts/utils/Multicall.sol
  93. 7 1
      contracts/utils/README.adoc
  94. 3 7
      contracts/utils/cryptography/ECDSA.sol
  95. 11 3
      contracts/utils/cryptography/MerkleProof.sol
  96. 1 1
      contracts/utils/cryptography/SignatureChecker.sol
  97. 1 1
      contracts/utils/math/Math.sol
  98. 43 0
      contracts/utils/math/SignedMath.sol
  99. 3 1
      docs/modules/ROOT/pages/erc1155.adoc
  100. 4 2
      docs/modules/ROOT/pages/erc20-supply.adoc

+ 5 - 0
.gitignore

@@ -57,3 +57,8 @@ allFiredEvents
 # hardhat
 cache
 artifacts
+
+# Certora
+.certora*
+.last_confs
+certora_*

+ 30 - 1
CHANGELOG.md

@@ -1,9 +1,38 @@
 # Changelog
 
+## 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))
+ * `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))
+ * `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)
 

+ 1 - 1
README.md

@@ -66,7 +66,7 @@ The core development principles and strategies that OpenZeppelin Contracts is ba
 
 The latest audit was done on October 2018 on version 2.0.0.
 
-Please report any security issues you find via our [bug bounty program on Immunefi](https://www.immunefi.com/bounty/openzeppelin) or directly to security@openzeppelin.org.
+We have a [**bug bounty program** on Immunefi](https://www.immunefi.com/bounty/openzeppelin). Please report any security issues you find through the Immunefi dashboard, or reach out to security@openzeppelin.com.
 
 Critical bug fixes will be backported to past major releases.
 

+ 7 - 5
SECURITY.md

@@ -1,5 +1,11 @@
 # Security Policy
 
+## Bug Bounty
+
+We have a [**bug bounty program** on Immunefi](https://www.immunefi.com/bounty/openzeppelin). Please report any security issues you find through the Immunefi dashboard, or reach out to security@openzeppelin.com.
+
+Critical bug fixes will be backported to past major releases.
+
 ## Supported Versions
 
 The recommendation is to use the latest version available.
@@ -11,8 +17,4 @@ The recommendation is to use the latest version available.
 | 2.5     | :white_check_mark:                   |
 | < 2.0   | :x:                                  |
 
-## Reporting a Vulnerability
-
-Please report any security issues you find to security@openzeppelin.org.
-
-Critical bug fixes will be backported to past major releases.
+Note that the Solidity language itself only guarantees security updates for the latest release.

+ 24 - 0
certora/Makefile

@@ -0,0 +1,24 @@
+default: help
+
+PATCH         = applyHarness.patch
+CONTRACTS_DIR = ../contracts
+MUNGED_DIR    = munged
+
+help:
+	@echo "usage:"
+	@echo "  make clean:  remove all generated files (those ignored by git)"
+	@echo "  make $(MUNGED_DIR): create $(MUNGED_DIR) directory by applying the patch file to $(CONTRACTS_DIR)"
+	@echo "  make record: record a new patch file capturing the differences between $(CONTRACTS_DIR) and $(MUNGED_DIR)"
+
+munged:  $(wildcard $(CONTRACTS_DIR)/*.sol) $(PATCH)
+	rm -rf $@
+	cp -r $(CONTRACTS_DIR) $@
+	patch -p0 -d $@ < $(PATCH)
+
+record:
+	diff -ruN $(CONTRACTS_DIR) $(MUNGED_DIR) | sed 's+../contracts/++g' | sed 's+munged/++g' > $(PATCH)
+
+clean:
+	git clean -fdX
+	touch $(PATCH)
+

+ 56 - 0
certora/README.md

@@ -0,0 +1,56 @@
+# Running the certora verification tool
+
+These instructions detail the process for running CVT on the OpenZeppelin (Wizard/Governor) contracts.
+
+Documentation for CVT and the specification language are available
+[here](https://certora.atlassian.net/wiki/spaces/CPD/overview)
+
+## Running the verification
+
+The scripts in the `certora/scripts` directory are used to submit verification
+jobs to the Certora verification service. After the job is complete, the results will be available on
+[the Certora portal](https://vaas-stg.certora.com/).
+
+These scripts should be run from the root directory; for example by running
+
+```
+sh certora/scripts/verifyAll.sh <meaningful comment>
+```
+
+The most important of these is `verifyAll.sh`, which checks
+all of the harnessed contracts (`certora/harness/Wizard*.sol`) against all of
+the specifications (`certora/spec/*.spec`).
+
+The other scripts run a subset of the specifications or the contracts.  You can
+verify different contracts or specifications by changing the `--verify` option,
+and you can run a single rule or method with the `--rule` or `--method` option.
+
+For example, to verify the `WizardFirstPriority` contract against the
+`GovernorCountingSimple` specification, you could change the `--verify` line of
+the `WizardControlFirstPriortity.sh` script to:
+
+```
+--verify WizardFirstPriority:certora/specs/GovernorCountingSimple.spec \
+```
+
+## Adapting to changes in the contracts
+
+Some of our rules require the code to be simplified in various ways. Our
+primary tool for performing these simplifications is to run verification on a
+contract that extends the original contracts and overrides some of the methods.
+These "harness" contracts can be found in the `certora/harness` directory.
+
+This pattern does require some modifications to the original code: some methods
+need to be made virtual or public, for example. These changes are handled by
+applying a patch to the code before verification.
+
+When one of the `verify` scripts is executed, it first applies the patch file
+`certora/applyHarness.patch` to the `contracts` directory, placing the output
+in the `certora/munged` directory. We then verify the contracts in the
+`certora/munged` directory.
+
+If the original contracts change, it is possible to create a conflict with the
+patch. In this case, the verify scripts will report an error message and output
+rejected changes in the `munged` directory. After merging the changes, run
+`make record` in the `certora` directory; this will regenerate the patch file,
+which can then be checked into git.

+ 101 - 0
certora/applyHarness.patch

@@ -0,0 +1,101 @@
+diff -ruN .gitignore .gitignore
+--- .gitignore	1969-12-31 19:00:00.000000000 -0500
++++ .gitignore	2021-12-09 14:46:33.923637220 -0500
+@@ -0,0 +1,2 @@
++*
++!.gitignore
+diff -ruN governance/compatibility/GovernorCompatibilityBravo.sol governance/compatibility/GovernorCompatibilityBravo.sol
+--- governance/compatibility/GovernorCompatibilityBravo.sol	2021-12-03 15:24:56.523654357 -0500
++++ governance/compatibility/GovernorCompatibilityBravo.sol	2021-12-09 14:46:33.923637220 -0500
+@@ -245,7 +245,7 @@
+     /**
+      * @dev See {Governor-_quorumReached}. In this module, only forVotes count toward the quorum.
+      */
+-    function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
++    function _quorumReached(uint256 proposalId) public view virtual override returns (bool) { // HARNESS: changed to public from internal
+         ProposalDetails storage details = _proposalDetails[proposalId];
+         return quorum(proposalSnapshot(proposalId)) <= details.forVotes;
+     }
+@@ -253,7 +253,7 @@
+     /**
+      * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be scritly over the againstVotes.
+      */
+-    function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
++    function _voteSucceeded(uint256 proposalId) public view virtual override returns (bool) { // HARNESS: changed to public from internal
+         ProposalDetails storage details = _proposalDetails[proposalId];
+         return details.forVotes > details.againstVotes;
+     }
+diff -ruN governance/extensions/GovernorCountingSimple.sol governance/extensions/GovernorCountingSimple.sol
+--- governance/extensions/GovernorCountingSimple.sol	2021-12-03 15:24:56.523654357 -0500
++++ governance/extensions/GovernorCountingSimple.sol	2021-12-09 14:46:33.923637220 -0500
+@@ -64,7 +64,7 @@
+     /**
+      * @dev See {Governor-_quorumReached}.
+      */
+-    function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
++    function _quorumReached(uint256 proposalId) public view virtual override returns (bool) {
+         ProposalVote storage proposalvote = _proposalVotes[proposalId];
+ 
+         return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;
+@@ -73,7 +73,7 @@
+     /**
+      * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
+      */
+-    function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
++    function _voteSucceeded(uint256 proposalId) public view virtual override returns (bool) {
+         ProposalVote storage proposalvote = _proposalVotes[proposalId];
+ 
+         return proposalvote.forVotes > proposalvote.againstVotes;
+diff -ruN governance/extensions/GovernorTimelockControl.sol governance/extensions/GovernorTimelockControl.sol
+--- governance/extensions/GovernorTimelockControl.sol	2021-12-03 15:24:56.523654357 -0500
++++ governance/extensions/GovernorTimelockControl.sol	2021-12-09 14:46:33.923637220 -0500
+@@ -111,7 +111,7 @@
+         bytes[] memory calldatas,
+         bytes32 descriptionHash
+     ) internal virtual override {
+-        _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, descriptionHash);
++         _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, descriptionHash);
+     }
+ 
+     /**
+diff -ruN governance/Governor.sol governance/Governor.sol
+--- governance/Governor.sol	2021-12-03 15:24:56.523654357 -0500
++++ governance/Governor.sol	2021-12-09 14:46:56.411503587 -0500
+@@ -38,8 +38,8 @@
+ 
+     string private _name;
+ 
+-    mapping(uint256 => ProposalCore) private _proposals;
+-
++    mapping(uint256 => ProposalCore) public _proposals;
++ 
+     /**
+      * @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.
+@@ -167,12 +167,12 @@
+     /**
+      * @dev Amount of votes already cast passes the threshold limit.
+      */
+-    function _quorumReached(uint256 proposalId) internal view virtual returns (bool);
++    function _quorumReached(uint256 proposalId) public view virtual returns (bool); // HARNESS: changed to public from internal
+ 
+     /**
+      * @dev Is the proposal successful or not.
+      */
+-    function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);
++    function _voteSucceeded(uint256 proposalId) public view virtual returns (bool); // HARNESS: changed to public from internal
+ 
+     /**
+      * @dev Register a vote with a given support and voting weight.
+diff -ruN token/ERC20/extensions/ERC20Votes.sol token/ERC20/extensions/ERC20Votes.sol
+--- token/ERC20/extensions/ERC20Votes.sol	2021-12-03 15:24:56.527654330 -0500
++++ token/ERC20/extensions/ERC20Votes.sol	2021-12-09 14:46:33.927637196 -0500
+@@ -84,7 +84,7 @@
+      *
+      * - `blockNumber` must have been already mined
+      */
+-    function getPastVotes(address account, uint256 blockNumber) public view returns (uint256) {
++    function getPastVotes(address account, uint256 blockNumber) public view virtual returns (uint256) {
+         require(blockNumber < block.number, "ERC20Votes: block not yet mined");
+         return _checkpointsLookup(_checkpoints[account], blockNumber);
+     }

+ 28 - 0
certora/harnesses/ERC20VotesHarness.sol

@@ -0,0 +1,28 @@
+import "../munged/token/ERC20/extensions/ERC20Votes.sol";
+
+contract ERC20VotesHarness is ERC20Votes {
+    constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {}
+
+    mapping(address => mapping(uint256 => uint256)) public _getPastVotes;
+
+    function _afterTokenTransfer(
+        address from,
+        address to,
+        uint256 amount
+    ) internal virtual override {
+        super._afterTokenTransfer(from, to, amount);
+        _getPastVotes[from][block.number] -= amount;
+        _getPastVotes[to][block.number] += amount;
+    }
+
+    /**
+     * @dev Change delegation for `delegator` to `delegatee`.
+     *
+     * Emits events {DelegateChanged} and {DelegateVotesChanged}.
+     */
+    function _delegate(address delegator, address delegatee) internal virtual override{
+        super._delegate(delegator, delegatee);
+        _getPastVotes[delegator][block.number] -= balanceOf(delegator);
+        _getPastVotes[delegatee][block.number] += balanceOf(delegator);
+    }
+}

+ 150 - 0
certora/harnesses/WizardControlFirstPriority.sol

@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.2;
+
+import "../munged/governance/Governor.sol";
+import "../munged/governance/extensions/GovernorCountingSimple.sol";
+import "../munged/governance/extensions/GovernorVotes.sol";
+import "../munged/governance/extensions/GovernorVotesQuorumFraction.sol";
+import "../munged/governance/extensions/GovernorTimelockControl.sol";
+import "../munged/governance/extensions/GovernorProposalThreshold.sol";
+
+/* 
+Wizard options:
+ProposalThreshhold = 10
+ERC20Votes
+TimelockController
+*/
+
+contract WizardControlFirstPriority is Governor, GovernorProposalThreshold, GovernorCountingSimple, GovernorVotes, GovernorVotesQuorumFraction, GovernorTimelockControl {
+    constructor(ERC20Votes _token, TimelockController _timelock, string memory name, uint256 quorumFraction)
+        Governor(name)
+        GovernorVotes(_token)
+        GovernorVotesQuorumFraction(quorumFraction)
+        GovernorTimelockControl(_timelock)
+    {}
+
+    //HARNESS
+
+    function isExecuted(uint256 proposalId) public view returns (bool) {
+        return _proposals[proposalId].executed;
+    }
+    
+    function isCanceled(uint256 proposalId) public view returns (bool) {
+        return _proposals[proposalId].canceled;
+    }
+
+    uint256 _votingDelay;
+
+    uint256 _votingPeriod;
+
+    uint256 _proposalThreshold;
+
+    mapping(uint256 => uint256) public ghost_sum_vote_power_by_id;
+
+    function _castVote(
+        uint256 proposalId,
+        address account,
+        uint8 support,
+        string memory reason
+    ) internal override virtual returns (uint256) {
+        
+        uint256 deltaWeight = super._castVote(proposalId, account, support, reason);  //HARNESS
+        ghost_sum_vote_power_by_id[proposalId] += deltaWeight;
+
+        return deltaWeight;        
+    }
+    
+    function snapshot(uint256 proposalId) public view returns (uint64) {
+        return _proposals[proposalId].voteStart._deadline;
+    }
+
+
+    function getExecutor() public view returns (address){
+        return _executor();
+    }
+
+    // original code, harnessed
+
+    function votingDelay() public view override returns (uint256) {     // HARNESS: pure -> view
+        return _votingDelay;                                            // HARNESS: parametric
+    }
+
+    function votingPeriod() public view override returns (uint256) {    // HARNESS: pure -> view
+        return _votingPeriod;                                           // HARNESS: parametric
+    }
+
+    function proposalThreshold() public view override returns (uint256) {   // HARNESS: pure -> view
+        return _proposalThreshold;                                          // HARNESS: parametric
+    }
+
+    // original code, not harnessed
+    // The following functions are overrides required by Solidity.
+
+    function quorum(uint256 blockNumber)
+        public
+        view
+        override(IGovernor, GovernorVotesQuorumFraction)
+        returns (uint256)
+    {
+        return super.quorum(blockNumber);
+    }
+
+    function getVotes(address account, uint256 blockNumber)
+        public
+        view
+        override(IGovernor, GovernorVotes)
+        returns (uint256)
+    {
+        return super.getVotes(account, blockNumber);
+    }
+
+    function state(uint256 proposalId)
+        public
+        view
+        override(Governor, GovernorTimelockControl)
+        returns (ProposalState)
+    {
+        return super.state(proposalId);
+    }
+
+    function propose(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, string memory description)
+        public
+        override(Governor, GovernorProposalThreshold, IGovernor)
+        returns (uint256)
+    {
+        return super.propose(targets, values, calldatas, description);
+    }
+
+    function _execute(uint256 proposalId, address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
+        internal
+        override(Governor, GovernorTimelockControl)
+    {
+        super._execute(proposalId, targets, values, calldatas, descriptionHash);
+    }
+
+    function _cancel(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
+        internal
+        override(Governor, GovernorTimelockControl)
+        returns (uint256)
+    {
+        return super._cancel(targets, values, calldatas, descriptionHash);
+    }
+
+    function _executor()
+        internal
+        view
+        override(Governor, GovernorTimelockControl)
+        returns (address)
+    {
+        return super._executor();
+    }
+
+    function supportsInterface(bytes4 interfaceId)
+        public
+        view
+        override(Governor, GovernorTimelockControl)
+        returns (bool)
+    {
+        return super.supportsInterface(interfaceId);
+    }
+}

+ 141 - 0
certora/harnesses/WizardFirstTry.sol

@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.2;
+
+import "../munged/governance/Governor.sol";
+import "../munged/governance/extensions/GovernorCountingSimple.sol";
+import "../munged/governance/extensions/GovernorVotes.sol";
+import "../munged/governance/extensions/GovernorVotesQuorumFraction.sol";
+import "../munged/governance/extensions/GovernorTimelockCompound.sol";
+
+/* 
+Wizard options:
+ERC20Votes
+TimelockCompound
+*/
+
+contract WizardFirstTry is Governor, GovernorCountingSimple, GovernorVotes, GovernorVotesQuorumFraction, GovernorTimelockCompound {
+    constructor(ERC20Votes _token, ICompoundTimelock _timelock, string memory name, uint256 quorumFraction)
+        Governor(name)
+        GovernorVotes(_token)
+        GovernorVotesQuorumFraction(quorumFraction)
+        GovernorTimelockCompound(_timelock)
+    {}
+
+    //HARNESS
+
+    function isExecuted(uint256 proposalId) public view returns (bool) {
+        return _proposals[proposalId].executed;
+    }
+    
+    function isCanceled(uint256 proposalId) public view returns (bool) {
+        return _proposals[proposalId].canceled;
+    }
+
+    function snapshot(uint256 proposalId) public view returns (uint64) {
+        return _proposals[proposalId].voteStart._deadline;
+    }
+
+    function getExecutor() public view returns (address){
+        return _executor();
+    }
+
+    uint256 _votingDelay;
+
+    uint256 _votingPeriod;
+
+    mapping(uint256 => uint256) public ghost_sum_vote_power_by_id;
+
+    function _castVote(
+        uint256 proposalId,
+        address account,
+        uint8 support,
+        string memory reason
+    ) internal override virtual returns (uint256) {
+        
+        uint256 deltaWeight = super._castVote(proposalId, account, support, reason);  //HARNESS
+        ghost_sum_vote_power_by_id[proposalId] += deltaWeight;
+
+        return deltaWeight;        
+    }
+
+    // original code, harnessed
+
+    function votingDelay() public view override virtual returns (uint256) {     // HARNESS: pure -> view
+        return _votingDelay;                                                    // HARNESS: parametric
+    }
+
+    function votingPeriod() public view override virtual returns (uint256) {    // HARNESS: pure -> view
+        return _votingPeriod;                                                   // HARNESS: parametric
+    }
+
+    // original code, not harnessed
+    // The following functions are overrides required by Solidity.
+
+    function quorum(uint256 blockNumber)
+        public
+        view
+        override(IGovernor, GovernorVotesQuorumFraction)
+        returns (uint256)
+    {
+        return super.quorum(blockNumber);
+    }
+
+    function getVotes(address account, uint256 blockNumber)
+        public
+        view
+        override(IGovernor, GovernorVotes)
+        returns (uint256)
+    {
+        return super.getVotes(account, blockNumber);
+    }
+
+    function state(uint256 proposalId)
+        public
+        view
+        override(Governor, GovernorTimelockCompound)
+        returns (ProposalState)
+    {
+        return super.state(proposalId);
+    }
+
+    function propose(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, string memory description)
+        public
+        override(Governor, IGovernor)
+        returns (uint256)
+    {
+        return super.propose(targets, values, calldatas, description);
+    }
+
+    function _execute(uint256 proposalId, address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
+        internal
+        override(Governor, GovernorTimelockCompound)
+    {
+        super._execute(proposalId, targets, values, calldatas, descriptionHash);
+    }
+
+    function _cancel(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
+        internal
+        override(Governor, GovernorTimelockCompound)
+        returns (uint256)
+    {
+        return super._cancel(targets, values, calldatas, descriptionHash);
+    }
+
+    function _executor()
+        internal
+        view
+        override(Governor, GovernorTimelockCompound)
+        returns (address)
+    {
+        return super._executor();
+    }
+
+    function supportsInterface(bytes4 interfaceId)
+        public
+        view
+        override(Governor, GovernorTimelockCompound)
+        returns (bool)
+    {
+        return super.supportsInterface(interfaceId);
+    }
+}

+ 2 - 0
certora/munged/.gitignore

@@ -0,0 +1,2 @@
+*
+!.gitignore

+ 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";
+}

+ 14 - 0
certora/specs/sanity.spec

@@ -0,0 +1,14 @@
+/*
+This rule looks for a non-reverting execution path to each method, including those overridden in the harness.
+A method has such an execution path if it violates this rule.
+How it works:
+    - If there is a non-reverting execution path, we reach the false assertion, and the sanity fails.
+    - If all execution paths are reverting, we never call the assertion, and the method will pass this rule vacuously.
+*/
+	
+rule sanity(method f) {
+    env e;
+    calldataarg arg;
+    f(e, arg);
+    assert false;
+}

+ 4 - 4
contracts/access/AccessControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol)
 
 pragma solidity ^0.8.0;
 
@@ -81,7 +81,7 @@ 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];
     }
 
@@ -92,7 +92,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 +113,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.1 (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();
     }
 

+ 41 - 13
contracts/governance/Governor.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (governance/Governor.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/Governor.sol)
 
 pragma solidity ^0.8.0;
 
@@ -41,8 +41,9 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
     mapping(uint256 => ProposalCore) private _proposals;
 
     /**
-     * @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 Restrict access of functions to the governance executor, which may be the Governor itself or a timelock
+     * contract, as specified by {_executor}. This generally means that function with this modifier must be voted on and
+     * executed through the governance protocol.
      */
     modifier onlyGovernance() {
         require(_msgSender() == _executor(), "Governor: onlyGovernance");
@@ -110,23 +111,36 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
      * @dev See {IGovernor-state}.
      */
     function state(uint256 proposalId) public view virtual override returns (ProposalState) {
-        ProposalCore memory proposal = _proposals[proposalId];
+        ProposalCore storage proposal = _proposals[proposalId];
 
         if (proposal.executed) {
             return ProposalState.Executed;
-        } else if (proposal.canceled) {
+        }
+
+        if (proposal.canceled) {
             return ProposalState.Canceled;
-        } else if (proposal.voteStart.getDeadline() >= block.number) {
+        }
+
+        uint256 snapshot = proposalSnapshot(proposalId);
+
+        if (snapshot == 0) {
+            revert("Governor: unknown proposal id");
+        }
+
+        if (snapshot >= block.number) {
             return ProposalState.Pending;
-        } else if (proposal.voteEnd.getDeadline() >= block.number) {
+        }
+
+        uint256 deadline = proposalDeadline(proposalId);
+
+        if (deadline >= block.number) {
             return ProposalState.Active;
-        } else if (proposal.voteEnd.isExpired()) {
-            return
-                _quorumReached(proposalId) && _voteSucceeded(proposalId)
-                    ? ProposalState.Succeeded
-                    : ProposalState.Defeated;
+        }
+
+        if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) {
+            return ProposalState.Succeeded;
         } else {
-            revert("Governor: unknown proposal id");
+            return ProposalState.Defeated;
         }
     }
 
@@ -347,6 +361,20 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
         return weight;
     }
 
+    /**
+     * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor
+     * is some contract other than the governor itself, like when using a timelock, this function can be invoked
+     * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake.
+     * Note that if the executor is simply the governor itself, use of `relay` is redundant.
+     */
+    function relay(
+        address target,
+        uint256 value,
+        bytes calldata data
+    ) external virtual onlyGovernance {
+        Address.functionCallWithValue(target, data, value);
+    }
+
     /**
      * @dev Address through which the governor executes action. Will be overloaded by module that execute actions
      * through another contract such as a timelock.

+ 2 - 2
contracts/governance/IGovernor.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (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.
      */

+ 9 - 1
contracts/governance/README.adoc

@@ -42,13 +42,15 @@ Other extensions can customize the behavior or interface in multiple ways.
 
 * {GovernorSettings}: Manages some of the settings (voting delay, voting period duration, and proposal threshold) in a way that can be updated through a governance proposal, without requiering an upgrade.
 
+* {GovernorPreventLateQuorum}: Ensures there is a minimum voting period after quorum is reached as a security protection against large voters.
+
 In addition to modules and extensions, the core contract requires a few virtual functions to be implemented to your particular specifications:
 
 * <<Governor-votingDelay-,`votingDelay()`>>: Delay (in number of blocks) since the proposal is submitted until voting power is fixed and voting starts. This can be used to enforce a delay after a proposal is published for users to buy tokens, or delegate their votes.
 * <<Governor-votingPeriod-,`votingPeriod()`>>: Delay (in number of blocks) since the proposal starts until voting ends.
 * <<Governor-quorum-uint256-,`quorum(uint256 blockNumber)`>>: Quorum required for a proposal to be successful. This function includes a `blockNumber` argument so the quorum can adapt through time, for example, to follow a token's `totalSupply`.
 
-NOTE: Functions of the `Governor` contract do not include access control. If you want to restrict access, you should add these checks by overloading the particular functions. Among these, {Governor-_cancel} is internal by default, and you will have to expose it (which the right access control mechanism) yourself if this function is needed.
+NOTE: Functions of the `Governor` contract do not include access control. If you want to restrict access, you should add these checks by overloading the particular functions. Among these, {Governor-_cancel} is internal by default, and you will have to expose it (with the right access control mechanism) yourself if this function is needed.
 
 === Core
 
@@ -74,12 +76,18 @@ NOTE: Functions of the `Governor` contract do not include access control. If you
 
 {{GovernorSettings}}
 
+{{GovernorPreventLateQuorum}}
+
 {{GovernorCompatibilityBravo}}
 
 === Deprecated
 
 {{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}.

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

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

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

@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.5.0) (governance/extensions/GovernorPreventLateQuorum.sol)
+
+pragma solidity ^0.8.0;
+
+import "../Governor.sol";
+import "../../utils/math/Math.sol";
+
+/**
+ * @dev A module that ensures there is a minimum voting period after quorum is reached. This prevents a large voter from
+ * swaying a vote and triggering quorum at the last minute, by ensuring there is always time for other voters to react
+ * and try to oppose the decision.
+ *
+ * If a vote causes quorum to be reached, the proposal's voting period may be extended so that it does not end before at
+ * least a given number of blocks have passed (the "vote extension" parameter). This parameter can be set by the
+ * governance executor (e.g. through a governance proposal).
+ *
+ * _Available since v4.5._
+ */
+abstract contract GovernorPreventLateQuorum is Governor {
+    using SafeCast for uint256;
+    using Timers for Timers.BlockNumber;
+
+    uint64 private _voteExtension;
+    mapping(uint256 => Timers.BlockNumber) private _extendedDeadlines;
+
+    /// @dev Emitted when a proposal deadline is pushed back due to reaching quorum late in its voting period.
+    event ProposalExtended(uint256 indexed proposalId, uint64 extendedDeadline);
+
+    /// @dev Emitted when the {lateQuorumVoteExtension} parameter is changed.
+    event LateQuorumVoteExtensionSet(uint64 oldVoteExtension, uint64 newVoteExtension);
+
+    /**
+     * @dev Initializes the vote extension parameter: the number of blocks that are required to pass since a proposal
+     * reaches quorum until its voting period ends. If necessary the voting period will be extended beyond the one set
+     * at proposal creation.
+     */
+    constructor(uint64 initialVoteExtension) {
+        _setLateQuorumVoteExtension(initialVoteExtension);
+    }
+
+    /**
+     * @dev Returns the proposal deadline, which may have been extended beyond that set at proposal creation, if the
+     * proposal reached quorum late in the voting period. See {Governor-proposalDeadline}.
+     */
+    function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
+        return Math.max(super.proposalDeadline(proposalId), _extendedDeadlines[proposalId].getDeadline());
+    }
+
+    /**
+     * @dev Casts a vote and detects if it caused quorum to be reached, potentially extending the voting period. See
+     * {Governor-_castVote}.
+     *
+     * May emit a {ProposalExtended} event.
+     */
+    function _castVote(
+        uint256 proposalId,
+        address account,
+        uint8 support,
+        string memory reason
+    ) internal virtual override returns (uint256) {
+        uint256 result = super._castVote(proposalId, account, support, reason);
+
+        Timers.BlockNumber storage extendedDeadline = _extendedDeadlines[proposalId];
+
+        if (extendedDeadline.isUnset() && _quorumReached(proposalId)) {
+            uint64 extendedDeadlineValue = block.number.toUint64() + lateQuorumVoteExtension();
+
+            if (extendedDeadlineValue > proposalDeadline(proposalId)) {
+                emit ProposalExtended(proposalId, extendedDeadlineValue);
+            }
+
+            extendedDeadline.setDeadline(extendedDeadlineValue);
+        }
+
+        return result;
+    }
+
+    /**
+     * @dev Returns the current value of the vote extension parameter: the number of blocks that are required to pass
+     * from the time a proposal reaches quorum until its voting period ends.
+     */
+    function lateQuorumVoteExtension() public view virtual returns (uint64) {
+        return _voteExtension;
+    }
+
+    /**
+     * @dev Changes the {lateQuorumVoteExtension}. This operation can only be performed by the governance executor,
+     * generally through a governance proposal.
+     *
+     * Emits a {LateQuorumVoteExtensionSet} event.
+     */
+    function setLateQuorumVoteExtension(uint64 newVoteExtension) public virtual onlyGovernance {
+        _setLateQuorumVoteExtension(newVoteExtension);
+    }
+
+    /**
+     * @dev Changes the {lateQuorumVoteExtension}. This is an internal function that can be exposed in a public function
+     * like {setLateQuorumVoteExtension} if another access control mechanism is needed.
+     *
+     * Emits a {LateQuorumVoteExtensionSet} event.
+     */
+    function _setLateQuorumVoteExtension(uint64 newVoteExtension) internal virtual {
+        emit LateQuorumVoteExtensionSet(_voteExtension, newVoteExtension);
+        _voteExtension = newVoteExtension;
+    }
+}

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (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 - 4
contracts/governance/extensions/GovernorTimelockControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (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 {
@@ -57,8 +62,10 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
             return status;
         } else if (_timelock.isOperationDone(queueid)) {
             return ProposalState.Executed;
-        } else {
+        } else if (_timelock.isOperationPending(queueid)) {
             return ProposalState.Queued;
+        } else {
+            return ProposalState.Canceled;
         }
     }
 
@@ -141,7 +148,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.1 (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;
     }
 

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (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(),

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

+ 9 - 7
contracts/interfaces/IERC2981.sol

@@ -1,20 +1,22 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (interfaces/IERC2981.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/IERC2981.sol)
 
 pragma solidity ^0.8.0;
 
 import "./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/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);
+}

+ 5 - 3
contracts/metatx/ERC2771Context.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (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.1 (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);
+    }
+}

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

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

+ 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_

+ 60 - 0
contracts/mocks/GovernorPreventLateQuorumMock.sol

@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.0;
+
+import "../governance/extensions/GovernorPreventLateQuorum.sol";
+import "../governance/extensions/GovernorSettings.sol";
+import "../governance/extensions/GovernorCountingSimple.sol";
+import "../governance/extensions/GovernorVotes.sol";
+
+contract GovernorPreventLateQuorumMock is
+    GovernorSettings,
+    GovernorVotes,
+    GovernorCountingSimple,
+    GovernorPreventLateQuorum
+{
+    uint256 private _quorum;
+
+    constructor(
+        string memory name_,
+        IVotes token_,
+        uint256 votingDelay_,
+        uint256 votingPeriod_,
+        uint256 quorum_,
+        uint64 voteExtension_
+    )
+        Governor(name_)
+        GovernorSettings(votingDelay_, votingPeriod_, 0)
+        GovernorVotes(token_)
+        GovernorPreventLateQuorum(voteExtension_)
+    {
+        _quorum = quorum_;
+    }
+
+    function quorum(uint256) public view virtual override returns (uint256) {
+        return _quorum;
+    }
+
+    function proposalDeadline(uint256 proposalId)
+        public
+        view
+        virtual
+        override(Governor, GovernorPreventLateQuorum)
+        returns (uint256)
+    {
+        return super.proposalDeadline(proposalId);
+    }
+
+    function proposalThreshold() public view virtual override(Governor, GovernorSettings) returns (uint256) {
+        return super.proposalThreshold();
+    }
+
+    function _castVote(
+        uint256 proposalId,
+        address account,
+        uint8 support,
+        string memory reason
+    ) internal virtual override(Governor, GovernorPreventLateQuorum) returns (uint256) {
+        return super._castVote(proposalId, account, support, reason);
+    }
+}

+ 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_,

+ 1 - 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_,

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

+ 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.2",
+  "version": "4.5.0",
   "files": [
     "**/*.sol",
     "/build/contracts/*.json",

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

@@ -1,9 +1,10 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (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.1 (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}}

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
 
 pragma solidity ^0.8.0;
 
@@ -7,7 +7,7 @@ import "../../utils/Address.sol";
 
 /**
  * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
- * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
+ * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
  * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
  * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
  *

+ 26 - 4
contracts/proxy/utils/UUPSUpgradeable.sol

@@ -1,8 +1,9 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (proxy/utils/UUPSUpgradeable.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/UUPSUpgradeable.sol)
 
 pragma solidity ^0.8.0;
 
+import "../../interfaces/draft-IERC1822.sol";
 import "../ERC1967/ERC1967Upgrade.sol";
 
 /**
@@ -17,7 +18,7 @@ import "../ERC1967/ERC1967Upgrade.sol";
  *
  * _Available since v4.1._
  */
-abstract contract UUPSUpgradeable is ERC1967Upgrade {
+abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {
     /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
     address private immutable __self = address(this);
 
@@ -34,6 +35,27 @@ abstract contract UUPSUpgradeable is ERC1967Upgrade {
         _;
     }
 
+    /**
+     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
+     * callable on the implementing contract but not through proxies.
+     */
+    modifier notDelegated() {
+        require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
+        _;
+    }
+
+    /**
+     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
+     * implementation. It is used to validate that the this implementation remains valid after an upgrade.
+     *
+     * 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. This is guaranteed by the `notDelegated` modifier.
+     */
+    function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
+        return _IMPLEMENTATION_SLOT;
+    }
+
     /**
      * @dev Upgrade the implementation of the proxy to `newImplementation`.
      *
@@ -43,7 +65,7 @@ abstract contract UUPSUpgradeable is ERC1967Upgrade {
      */
     function upgradeTo(address newImplementation) external virtual onlyProxy {
         _authorizeUpgrade(newImplementation);
-        _upgradeToAndCallSecure(newImplementation, new bytes(0), false);
+        _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
     }
 
     /**
@@ -56,7 +78,7 @@ abstract contract UUPSUpgradeable is ERC1967Upgrade {
      */
     function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {
         _authorizeUpgrade(newImplementation);
-        _upgradeToAndCallSecure(newImplementation, data, true);
+        _upgradeToAndCallUUPS(newImplementation, data, true);
     }
 
     /**

+ 30 - 25
contracts/token/ERC1155/IERC1155Receiver.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155Receiver.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
 
 pragma solidity ^0.8.0;
 
@@ -10,18 +10,20 @@ import "../../utils/introspection/IERC165.sol";
  */
 interface IERC1155Receiver is IERC165 {
     /**
-        @dev Handles the receipt of a single ERC1155 token type. This function is
-        called at the end of a `safeTransferFrom` after the balance has been updated.
-        To accept the transfer, this must return
-        `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
-        (i.e. 0xf23a6e61, or its own function selector).
-        @param operator The address which initiated the transfer (i.e. msg.sender)
-        @param from The address which previously owned the token
-        @param id The ID of the token being transferred
-        @param value The amount of tokens being transferred
-        @param data Additional data with no specified format
-        @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
-    */
+     * @dev Handles the receipt of a single ERC1155 token type. This function is
+     * called at the end of a `safeTransferFrom` after the balance has been updated.
+     *
+     * NOTE: To accept the transfer, this must return
+     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
+     * (i.e. 0xf23a6e61, or its own function selector).
+     *
+     * @param operator The address which initiated the transfer (i.e. msg.sender)
+     * @param from The address which previously owned the token
+     * @param id The ID of the token being transferred
+     * @param value The amount of tokens being transferred
+     * @param data Additional data with no specified format
+     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
+     */
     function onERC1155Received(
         address operator,
         address from,
@@ -31,18 +33,21 @@ interface IERC1155Receiver is IERC165 {
     ) external returns (bytes4);
 
     /**
-        @dev Handles the receipt of a multiple ERC1155 token types. This function
-        is called at the end of a `safeBatchTransferFrom` after the balances have
-        been updated. To accept the transfer(s), this must return
-        `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
-        (i.e. 0xbc197c81, or its own function selector).
-        @param operator The address which initiated the batch transfer (i.e. msg.sender)
-        @param from The address which previously owned the token
-        @param ids An array containing ids of each token being transferred (order and length must match values array)
-        @param values An array containing amounts of each token being transferred (order and length must match ids array)
-        @param data Additional data with no specified format
-        @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
-    */
+     * @dev Handles the receipt of a multiple ERC1155 token types. This function
+     * is called at the end of a `safeBatchTransferFrom` after the balances have
+     * been updated.
+     *
+     * NOTE: To accept the transfer(s), this must return
+     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
+     * (i.e. 0xbc197c81, or its own function selector).
+     *
+     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
+     * @param from The address which previously owned the token
+     * @param ids An array containing ids of each token being transferred (order and length must match values array)
+     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
+     * @param data Additional data with no specified format
+     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
+     */
     function onERC1155BatchReceived(
         address operator,
         address from,

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

@@ -26,6 +26,8 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel
 
 {{IERC1155Receiver}}
 
+{{ERC1155Receiver}}
+
 == Extensions
 
 {{ERC1155Pausable}}

+ 3 - 1
contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC1155/presets/ERC1155PresetMinterPauser.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/presets/ERC1155PresetMinterPauser.sol)
 
 pragma solidity ^0.8.0;
 
@@ -22,6 +22,8 @@ import "../../../utils/Context.sol";
  * The account that deploys the contract will be granted the minter and pauser
  * roles, as well as the default admin role, which will let it grant both minter
  * and pauser roles to other accounts.
+ *
+ * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._
  */
 contract ERC1155PresetMinterPauser is Context, AccessControlEnumerable, ERC1155Burnable, ERC1155Pausable {
     bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

+ 1 - 0
contracts/token/ERC1155/presets/README.md

@@ -0,0 +1 @@
+Contract presets are now deprecated in favor of [Contracts Wizard](https://wizard.openzeppelin.com/) as a more powerful alternative.

+ 6 - 1
contracts/token/ERC1155/utils/ERC1155Holder.sol

@@ -1,11 +1,16 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Holder.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol)
 
 pragma solidity ^0.8.0;
 
 import "./ERC1155Receiver.sol";
 
 /**
+ * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens.
+ *
+ * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
+ * stuck.
+ *
  * @dev _Available since v3.1._
  */
 contract ERC1155Holder is ERC1155Receiver {

+ 62 - 35
contracts/token/ERC20/ERC20.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)
 
 pragma solidity ^0.8.0;
 
@@ -107,11 +107,12 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
      *
      * Requirements:
      *
-     * - `recipient` cannot be the zero address.
+     * - `to` cannot be the zero address.
      * - the caller must have a balance of at least `amount`.
      */
-    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
-        _transfer(_msgSender(), recipient, amount);
+    function transfer(address to, uint256 amount) public virtual override returns (bool) {
+        address owner = _msgSender();
+        _transfer(owner, to, amount);
         return true;
     }
 
@@ -125,12 +126,16 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
     /**
      * @dev See {IERC20-approve}.
      *
+     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
+     * `transferFrom`. This is semantically equivalent to an infinite approval.
+     *
      * Requirements:
      *
      * - `spender` cannot be the zero address.
      */
     function approve(address spender, uint256 amount) public virtual override returns (bool) {
-        _approve(_msgSender(), spender, amount);
+        address owner = _msgSender();
+        _approve(owner, spender, amount);
         return true;
     }
 
@@ -140,26 +145,24 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
      * Emits an {Approval} event indicating the updated allowance. This is not
      * required by the EIP. See the note at the beginning of {ERC20}.
      *
+     * NOTE: Does not update the allowance if the current allowance
+     * is the maximum `uint256`.
+     *
      * Requirements:
      *
-     * - `sender` and `recipient` cannot be the zero address.
-     * - `sender` must have a balance of at least `amount`.
-     * - the caller must have allowance for ``sender``'s tokens of at least
+     * - `from` and `to` cannot be the zero address.
+     * - `from` must have a balance of at least `amount`.
+     * - the caller must have allowance for ``from``'s tokens of at least
      * `amount`.
      */
     function transferFrom(
-        address sender,
-        address recipient,
+        address from,
+        address to,
         uint256 amount
     ) public virtual override returns (bool) {
-        _transfer(sender, recipient, amount);
-
-        uint256 currentAllowance = _allowances[sender][_msgSender()];
-        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
-        unchecked {
-            _approve(sender, _msgSender(), currentAllowance - amount);
-        }
-
+        address spender = _msgSender();
+        _spendAllowance(from, spender, amount);
+        _transfer(from, to, amount);
         return true;
     }
 
@@ -176,7 +179,8 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
      * - `spender` cannot be the zero address.
      */
     function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
-        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
+        address owner = _msgSender();
+        _approve(owner, spender, _allowances[owner][spender] + addedValue);
         return true;
     }
 
@@ -195,10 +199,11 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
      * `subtractedValue`.
      */
     function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
-        uint256 currentAllowance = _allowances[_msgSender()][spender];
+        address owner = _msgSender();
+        uint256 currentAllowance = _allowances[owner][spender];
         require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
         unchecked {
-            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
+            _approve(owner, spender, currentAllowance - subtractedValue);
         }
 
         return true;
@@ -214,30 +219,30 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
      *
      * Requirements:
      *
-     * - `sender` cannot be the zero address.
-     * - `recipient` cannot be the zero address.
-     * - `sender` must have a balance of at least `amount`.
+     * - `from` cannot be the zero address.
+     * - `to` cannot be the zero address.
+     * - `from` must have a balance of at least `amount`.
      */
     function _transfer(
-        address sender,
-        address recipient,
+        address from,
+        address to,
         uint256 amount
     ) internal virtual {
-        require(sender != address(0), "ERC20: transfer from the zero address");
-        require(recipient != address(0), "ERC20: transfer to the zero address");
+        require(from != address(0), "ERC20: transfer from the zero address");
+        require(to != address(0), "ERC20: transfer to the zero address");
 
-        _beforeTokenTransfer(sender, recipient, amount);
+        _beforeTokenTransfer(from, to, amount);
 
-        uint256 senderBalance = _balances[sender];
-        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
+        uint256 fromBalance = _balances[from];
+        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
         unchecked {
-            _balances[sender] = senderBalance - amount;
+            _balances[from] = fromBalance - amount;
         }
-        _balances[recipient] += amount;
+        _balances[to] += amount;
 
-        emit Transfer(sender, recipient, amount);
+        emit Transfer(from, to, amount);
 
-        _afterTokenTransfer(sender, recipient, amount);
+        _afterTokenTransfer(from, to, amount);
     }
 
     /** @dev Creates `amount` tokens and assigns them to `account`, increasing
@@ -314,6 +319,28 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
         emit Approval(owner, spender, amount);
     }
 
+    /**
+     * @dev Spend `amount` form the allowance of `owner` toward `spender`.
+     *
+     * Does not update the allowance amount in case of infinite allowance.
+     * Revert if not enough allowance is available.
+     *
+     * Might emit an {Approval} event.
+     */
+    function _spendAllowance(
+        address owner,
+        address spender,
+        uint256 amount
+    ) internal virtual {
+        uint256 currentAllowance = allowance(owner, spender);
+        if (currentAllowance != type(uint256).max) {
+            require(currentAllowance >= amount, "ERC20: insufficient allowance");
+            unchecked {
+                _approve(owner, spender, currentAllowance - amount);
+            }
+        }
+    }
+
     /**
      * @dev Hook that is called before any transfer of tokens. This includes
      * minting and burning.

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)
 
 pragma solidity ^0.8.0;
 
@@ -18,13 +18,13 @@ interface IERC20 {
     function balanceOf(address account) external view returns (uint256);
 
     /**
-     * @dev Moves `amount` tokens from the caller's account to `recipient`.
+     * @dev Moves `amount` tokens from the caller's account to `to`.
      *
      * Returns a boolean value indicating whether the operation succeeded.
      *
      * Emits a {Transfer} event.
      */
-    function transfer(address recipient, uint256 amount) external returns (bool);
+    function transfer(address to, uint256 amount) external returns (bool);
 
     /**
      * @dev Returns the remaining number of tokens that `spender` will be
@@ -52,7 +52,7 @@ interface IERC20 {
     function approve(address spender, uint256 amount) external returns (bool);
 
     /**
-     * @dev Moves `amount` tokens from `sender` to `recipient` using the
+     * @dev Moves `amount` tokens from `from` to `to` using the
      * allowance mechanism. `amount` is then deducted from the caller's
      * allowance.
      *
@@ -61,8 +61,8 @@ interface IERC20 {
      * Emits a {Transfer} event.
      */
     function transferFrom(
-        address sender,
-        address recipient,
+        address from,
+        address to,
         uint256 amount
     ) external returns (bool);
 

+ 2 - 6
contracts/token/ERC20/extensions/ERC20Burnable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Burnable.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)
 
 pragma solidity ^0.8.0;
 
@@ -33,11 +33,7 @@ abstract contract ERC20Burnable is Context, ERC20 {
      * `amount`.
      */
     function burnFrom(address account, uint256 amount) public virtual {
-        uint256 currentAllowance = allowance(account, _msgSender());
-        require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
-        unchecked {
-            _approve(account, _msgSender(), currentAllowance - amount);
-        }
+        _spendAllowance(account, _msgSender(), amount);
         _burn(account, amount);
     }
 }

+ 3 - 2
contracts/token/ERC20/extensions/ERC20FlashMint.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20FlashMint.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20FlashMint.sol)
 
 pragma solidity ^0.8.0;
 
@@ -23,7 +23,7 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
      * @param token The address of the token that is requested.
      * @return The amont of token that can be loaned.
      */
-    function maxFlashLoan(address token) public view override returns (uint256) {
+    function maxFlashLoan(address token) public view virtual override returns (uint256) {
         return token == address(this) ? type(uint256).max - ERC20.totalSupply() : 0;
     }
 
@@ -62,6 +62,7 @@ abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
         uint256 amount,
         bytes calldata data
     ) public virtual override returns (bool) {
+        require(amount <= maxFlashLoan(token), "ERC20FlashMint: amount exceeds maxFlashLoan");
         uint256 fee = flashFee(token, amount);
         _mint(address(receiver), amount);
         require(

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

@@ -1,10 +1,11 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Votes.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol)
 
 pragma solidity ^0.8.0;
 
 import "./draft-ERC20Permit.sol";
 import "../../../utils/math/Math.sol";
+import "../../../governance/utils/IVotes.sol";
 import "../../../utils/math/SafeCast.sol";
 import "../../../utils/cryptography/ECDSA.sol";
 
@@ -23,7 +24,7 @@ import "../../../utils/cryptography/ECDSA.sol";
  *
  * _Available since v4.2._
  */
-abstract contract ERC20Votes is ERC20Permit {
+abstract contract ERC20Votes is IVotes, ERC20Permit {
     struct Checkpoint {
         uint32 fromBlock;
         uint224 votes;
@@ -36,16 +37,6 @@ abstract contract ERC20Votes is ERC20Permit {
     mapping(address => Checkpoint[]) private _checkpoints;
     Checkpoint[] private _totalSupplyCheckpoints;
 
-    /**
-     * @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 an account's voting power.
-     */
-    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);
-
     /**
      * @dev Get the `pos`-th checkpoint for `account`.
      */
@@ -63,14 +54,14 @@ abstract contract ERC20Votes is ERC20Permit {
     /**
      * @dev Get the address `account` is currently delegating to.
      */
-    function delegates(address account) public view virtual returns (address) {
+    function delegates(address account) public view virtual override returns (address) {
         return _delegates[account];
     }
 
     /**
      * @dev Gets the current votes balance for `account`
      */
-    function getVotes(address account) public view returns (uint256) {
+    function getVotes(address account) public view virtual override returns (uint256) {
         uint256 pos = _checkpoints[account].length;
         return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;
     }
@@ -82,7 +73,7 @@ abstract contract ERC20Votes is ERC20Permit {
      *
      * - `blockNumber` must have been already mined
      */
-    function getPastVotes(address account, uint256 blockNumber) public view returns (uint256) {
+    function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
         require(blockNumber < block.number, "ERC20Votes: block not yet mined");
         return _checkpointsLookup(_checkpoints[account], blockNumber);
     }
@@ -95,7 +86,7 @@ abstract contract ERC20Votes is ERC20Permit {
      *
      * - `blockNumber` must have been already mined
      */
-    function getPastTotalSupply(uint256 blockNumber) public view returns (uint256) {
+    function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {
         require(blockNumber < block.number, "ERC20Votes: block not yet mined");
         return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);
     }
@@ -132,7 +123,7 @@ abstract contract ERC20Votes is ERC20Permit {
     /**
      * @dev Delegate votes from the sender to `delegatee`.
      */
-    function delegate(address delegatee) public virtual {
+    function delegate(address delegatee) public virtual override {
         _delegate(_msgSender(), delegatee);
     }
 
@@ -146,7 +137,7 @@ abstract contract ERC20Votes is ERC20Permit {
         uint8 v,
         bytes32 r,
         bytes32 s
-    ) public virtual {
+    ) public virtual override {
         require(block.timestamp <= expiry, "ERC20Votes: signature expired");
         address signer = ECDSA.recover(
             _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),

+ 3 - 3
contracts/token/ERC20/extensions/ERC20VotesComp.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20VotesComp.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol)
 
 pragma solidity ^0.8.0;
 
@@ -26,14 +26,14 @@ abstract contract ERC20VotesComp is ERC20Votes {
     /**
      * @dev Comp version of the {getVotes} accessor, with `uint96` return type.
      */
-    function getCurrentVotes(address account) external view returns (uint96) {
+    function getCurrentVotes(address account) external view virtual returns (uint96) {
         return SafeCast.toUint96(getVotes(account));
     }
 
     /**
      * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type.
      */
-    function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96) {
+    function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) {
         return SafeCast.toUint96(getPastVotes(account, blockNumber));
     }
 

+ 3 - 1
contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/presets/ERC20PresetFixedSupply.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetFixedSupply.sol)
 pragma solidity ^0.8.0;
 
 import "../extensions/ERC20Burnable.sol";
@@ -15,6 +15,8 @@ import "../extensions/ERC20Burnable.sol";
  * its documentation for details.
  *
  * _Available since v3.4._
+ *
+ * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._
  */
 contract ERC20PresetFixedSupply is ERC20Burnable {
     /**

+ 3 - 1
contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/presets/ERC20PresetMinterPauser.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetMinterPauser.sol)
 
 pragma solidity ^0.8.0;
 
@@ -22,6 +22,8 @@ import "../../../utils/Context.sol";
  * The account that deploys the contract will be granted the minter and pauser
  * roles, as well as the default admin role, which will let it grant both minter
  * and pauser roles to other accounts.
+ *
+ * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._
  */
 contract ERC20PresetMinterPauser is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable {
     bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

+ 1 - 0
contracts/token/ERC20/presets/README.md

@@ -0,0 +1 @@
+Contract presets are now deprecated in favor of [Contracts Wizard](https://wizard.openzeppelin.com/) as a more powerful alternative.

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/TokenTimelock.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/utils/TokenTimelock.sol)
 
 pragma solidity ^0.8.0;
 
@@ -24,6 +24,11 @@ contract TokenTimelock {
     // timestamp when token release is enabled
     uint256 private immutable _releaseTime;
 
+    /**
+     * @dev Deploys a timelock instance that is able to hold the token specified, and will only release it to
+     * `beneficiary_` when {release} is invoked after `releaseTime_`. The release time is specified as a Unix timestamp
+     * (in seconds).
+     */
     constructor(
         IERC20 token_,
         address beneficiary_,
@@ -36,28 +41,29 @@ contract TokenTimelock {
     }
 
     /**
-     * @return the token being held.
+     * @dev Returns the token being held.
      */
     function token() public view virtual returns (IERC20) {
         return _token;
     }
 
     /**
-     * @return the beneficiary of the tokens.
+     * @dev Returns the beneficiary that will receive the tokens.
      */
     function beneficiary() public view virtual returns (address) {
         return _beneficiary;
     }
 
     /**
-     * @return the time when the tokens are released.
+     * @dev Returns the time when the tokens are released in seconds since Unix epoch (i.e. Unix timestamp).
      */
     function releaseTime() public view virtual returns (uint256) {
         return _releaseTime;
     }
 
     /**
-     * @notice Transfers tokens held by timelock to beneficiary.
+     * @dev Transfers tokens held by the timelock to the beneficiary. Will only succeed if invoked after the release
+     * time.
      */
     function release() public virtual {
         require(block.timestamp >= releaseTime(), "TokenTimelock: current time is before release time");

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC721/ERC721.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/ERC721.sol)
 
 pragma solidity ^0.8.0;
 
@@ -287,6 +287,8 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
         _owners[tokenId] = to;
 
         emit Transfer(address(0), to, tokenId);
+
+        _afterTokenTransfer(address(0), to, tokenId);
     }
 
     /**
@@ -311,6 +313,8 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
         delete _owners[tokenId];
 
         emit Transfer(owner, address(0), tokenId);
+
+        _afterTokenTransfer(owner, address(0), tokenId);
     }
 
     /**
@@ -329,7 +333,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
         address to,
         uint256 tokenId
     ) internal virtual {
-        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
+        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
         require(to != address(0), "ERC721: transfer to the zero address");
 
         _beforeTokenTransfer(from, to, tokenId);
@@ -342,6 +346,8 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
         _owners[tokenId] = to;
 
         emit Transfer(from, to, tokenId);
+
+        _afterTokenTransfer(from, to, tokenId);
     }
 
     /**
@@ -421,4 +427,21 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
         address to,
         uint256 tokenId
     ) internal virtual {}
+
+    /**
+     * @dev Hook that is called after any transfer of tokens. This includes
+     * minting and burning.
+     *
+     * Calling conditions:
+     *
+     * - when `from` and `to` are both non-zero.
+     * - `from` and `to` are never both zero.
+     *
+     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
+     */
+    function _afterTokenTransfer(
+        address from,
+        address to,
+        uint256 tokenId
+    ) internal virtual {}
 }

+ 21 - 6
contracts/token/ERC721/README.adoc

@@ -7,17 +7,28 @@ This set of interfaces, contracts, and utilities are all related to the https://
 
 TIP: For a walk through on how to create an ERC721 token read our xref:ROOT:erc721.adoc[ERC721 guide].
 
-The EIP consists of three interfaces, found here as {IERC721}, {IERC721Metadata}, and {IERC721Enumerable}. Only the first one is required in a contract to be ERC721 compliant. The core interface and the metadata extension are both implemented in {ERC721}. The enumerable extension is provided separately in {ERC721Enumerable}.
+The EIP specifies four interfaces:
 
-Additionally, {IERC721Receiver} can be used to prevent tokens from becoming forever locked in contracts. Imagine sending an in-game item to an exchange address that can't send it back!. When using <<IERC721-safeTransferFrom,`safeTransferFrom`>>, the token contract checks to see that the receiver is an {IERC721Receiver}, which implies that it knows how to handle {ERC721} tokens. If you're writing a contract that needs to receive {ERC721} tokens, you'll want to include this interface.
+* {IERC721}: Core functionality required in all compliant implementation.
+* {IERC721Metadata}: Optional extension that adds name, symbol, and token URI, almost always included.
+* {IERC721Enumerable}: Optional extension that allows enumerating the tokens on chain, often not included since it requires large gas overhead.
+* {IERC721Receiver}: An interface that must be implemented by contracts if they want to accept tokens through `safeTransferFrom`.
 
-Additionally there are multiple custom extensions, including:
+OpenZeppelin Contracts provides implementations of all four interfaces:
 
-* designation of addresses that can pause token transfers for all users ({ERC721Pausable}).
-* destruction of own tokens ({ERC721Burnable}).
+* {ERC721}: The core and metadata extensions, with a base URI mechanism.
+* {ERC721Enumerable}: The enumerable extension.
+* {ERC721Holder}: A bare bones implementation of the receiver interface.
 
-NOTE: This core set of contracts is designed to be unopinionated, allowing developers to access the internal functions in ERC721 (such as <<ERC721-_mint-address-uint256-,`_mint`>>) and expose them as external functions in the way they prefer. On the other hand, xref:ROOT:erc721.adoc#Presets[ERC721 Presets] (such as {ERC721PresetMinterPauserAutoId}) are designed using opinionated patterns to provide developers with ready to use, deployable contracts.
+Additionally there are a few of other extensions:
+
+* {ERC721URIStorage}: A more flexible but more expensive way of storing metadata.
+* {ERC721Votes}: Support for voting and vote delegation.
+* {ERC721Royalty}: A way to signal royalty information following ERC2981.
+* {ERC721Pausable}: A primitive to pause contract operation.
+* {ERC721Burnable}: A way for token holders to burn their own tokens.
 
+NOTE: This core set of contracts is designed to be unopinionated, allowing developers to access the internal functions in ERC721 (such as <<ERC721-_mint-address-uint256-,`_mint`>>) and expose them as external functions in the way they prefer. On the other hand, xref:ROOT:erc721.adoc#Presets[ERC721 Presets] (such as {ERC721PresetMinterPauserAutoId}) are designed using opinionated patterns to provide developers with ready to use, deployable contracts.
 
 == Core
 
@@ -41,6 +52,10 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel
 
 {{ERC721URIStorage}}
 
+{{ERC721Votes}}
+
+{{ERC721Royalty}}
+
 == Presets
 
 These contracts are preconfigured combinations of the above features. They can be used through inheritance or as models to copy and paste their source code.

+ 38 - 0
contracts/token/ERC721/extensions/ERC721Royalty.sol

@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/ERC721Royalty.sol)
+
+pragma solidity ^0.8.0;
+
+import "../ERC721.sol";
+import "../../common/ERC2981.sol";
+import "../../../utils/introspection/ERC165.sol";
+
+/**
+ * @dev Extension of ERC721 with the ERC2981 NFT Royalty Standard, a standardized way to retrieve royalty payment
+ * information.
+ *
+ * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
+ * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
+ *
+ * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
+ * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
+ * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
+ *
+ * _Available since v4.5._
+ */
+abstract contract ERC721Royalty is ERC2981, ERC721 {
+    /**
+     * @dev See {IERC165-supportsInterface}.
+     */
+    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) {
+        return super.supportsInterface(interfaceId);
+    }
+
+    /**
+     * @dev See {ERC721-_burn}. This override additionally clears the royalty information for the token.
+     */
+    function _burn(uint256 tokenId) internal virtual override {
+        super._burn(tokenId);
+        _resetTokenRoyalty(tokenId);
+    }
+}

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Enumerable.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
 
 pragma solidity ^0.8.0;
 
@@ -19,7 +19,7 @@ interface IERC721Enumerable is IERC721 {
      * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
      * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
      */
-    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
+    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
 
     /**
      * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.

+ 40 - 0
contracts/token/ERC721/extensions/draft-ERC721Votes.sol

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

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol)
 
 pragma solidity ^0.8.0;
 
@@ -25,6 +25,8 @@ import "../../../utils/Counters.sol";
  * The account that deploys the contract will be granted the minter and pauser
  * roles, as well as the default admin role, which will let it grant both minter
  * and pauser roles to other accounts.
+ *
+ * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._
  */
 contract ERC721PresetMinterPauserAutoId is
     Context,

+ 1 - 0
contracts/token/ERC721/presets/README.md

@@ -0,0 +1 @@
+Contract presets are now deprecated in favor of [Contracts Wizard](https://wizard.openzeppelin.com/) as a more powerful alternative.

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

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (token/ERC777/ERC777.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC777/ERC777.sol)
 
 pragma solidity ^0.8.0;
 
@@ -258,6 +258,9 @@ contract ERC777 is Context, IERC777, IERC20 {
     /**
      * @dev See {IERC20-approve}.
      *
+     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
+     * `transferFrom`. This is semantically equivalent to an infinite approval.
+     *
      * Note that accounts cannot have allowance issued by their operators.
      */
     function approve(address spender, uint256 value) public virtual override returns (bool) {
@@ -269,6 +272,9 @@ contract ERC777 is Context, IERC777, IERC20 {
     /**
      * @dev See {IERC20-transferFrom}.
      *
+     * NOTE: Does not update the allowance if the current allowance
+     * is the maximum `uint256`.
+     *
      * Note that operator and allowance concepts are orthogonal: operators cannot
      * call `transferFrom` (unless they have allowance), and accounts with
      * allowance cannot call `operatorSend` (unless they are operators).
@@ -287,11 +293,9 @@ contract ERC777 is Context, IERC777, IERC20 {
 
         _callTokensToSend(spender, holder, recipient, amount, "", "");
 
-        _move(spender, holder, recipient, amount, "", "");
+        _spendAllowance(holder, spender, amount);
 
-        uint256 currentAllowance = _allowances[holder][spender];
-        require(currentAllowance >= amount, "ERC777: transfer amount exceeds allowance");
-        _approve(holder, spender, currentAllowance - amount);
+        _move(spender, holder, recipient, amount, "", "");
 
         _callTokensReceived(spender, holder, recipient, amount, "", "", false);
 
@@ -457,7 +461,7 @@ contract ERC777 is Context, IERC777, IERC20 {
         address holder,
         address spender,
         uint256 value
-    ) internal {
+    ) internal virtual {
         require(holder != address(0), "ERC777: approve from the zero address");
         require(spender != address(0), "ERC777: approve to the zero address");
 
@@ -516,6 +520,28 @@ contract ERC777 is Context, IERC777, IERC20 {
         }
     }
 
+    /**
+     * @dev Spend `amount` form the allowance of `owner` toward `spender`.
+     *
+     * Does not update the allowance amount in case of infinite allowance.
+     * Revert if not enough allowance is available.
+     *
+     * Might emit an {Approval} event.
+     */
+    function _spendAllowance(
+        address owner,
+        address spender,
+        uint256 amount
+    ) internal virtual {
+        uint256 currentAllowance = allowance(owner, spender);
+        if (currentAllowance != type(uint256).max) {
+            require(currentAllowance >= amount, "ERC777: insufficient allowance");
+            unchecked {
+                _approve(owner, spender, currentAllowance - amount);
+            }
+        }
+    }
+
     /**
      * @dev Hook that is called before any token transfer. This includes
      * calls to {send}, {transfer}, {operatorSend}, minting and burning.

+ 118 - 0
contracts/token/common/ERC2981.sol

@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.5.0) (token/common/ERC2981.sol)
+
+pragma solidity ^0.8.0;
+
+import "../../interfaces/IERC2981.sol";
+import "../../utils/introspection/ERC165.sol";
+
+/**
+ * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
+ *
+ * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
+ * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
+ *
+ * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
+ * fee is specified in basis points by default.
+ *
+ * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
+ * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
+ * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
+ *
+ * _Available since v4.5._
+ */
+abstract contract ERC2981 is IERC2981, ERC165 {
+    struct RoyaltyInfo {
+        address receiver;
+        uint96 royaltyFraction;
+    }
+
+    RoyaltyInfo private _defaultRoyaltyInfo;
+    mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;
+
+    /**
+     * @dev See {IERC165-supportsInterface}.
+     */
+    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
+        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
+    }
+
+    /**
+     * @inheritdoc IERC2981
+     */
+    function royaltyInfo(uint256 _tokenId, uint256 _salePrice)
+        external
+        view
+        virtual
+        override
+        returns (address, uint256)
+    {
+        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];
+
+        if (royalty.receiver == address(0)) {
+            royalty = _defaultRoyaltyInfo;
+        }
+
+        uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();
+
+        return (royalty.receiver, royaltyAmount);
+    }
+
+    /**
+     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
+     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
+     * override.
+     */
+    function _feeDenominator() internal pure virtual returns (uint96) {
+        return 10000;
+    }
+
+    /**
+     * @dev Sets the royalty information that all ids in this contract will default to.
+     *
+     * Requirements:
+     *
+     * - `receiver` cannot be the zero address.
+     * - `feeNumerator` cannot be greater than the fee denominator.
+     */
+    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
+        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
+        require(receiver != address(0), "ERC2981: invalid receiver");
+
+        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
+    }
+
+    /**
+     * @dev Removes default royalty information.
+     */
+    function _deleteDefaultRoyalty() internal virtual {
+        delete _defaultRoyaltyInfo;
+    }
+
+    /**
+     * @dev Sets the royalty information for a specific token id, overriding the global default.
+     *
+     * Requirements:
+     *
+     * - `tokenId` must be already minted.
+     * - `receiver` cannot be the zero address.
+     * - `feeNumerator` cannot be greater than the fee denominator.
+     */
+    function _setTokenRoyalty(
+        uint256 tokenId,
+        address receiver,
+        uint96 feeNumerator
+    ) internal virtual {
+        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
+        require(receiver != address(0), "ERC2981: Invalid parameters");
+
+        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
+    }
+
+    /**
+     * @dev Resets royalty information for the token id back to the global default.
+     */
+    function _resetTokenRoyalty(uint256 tokenId) internal virtual {
+        delete _tokenRoyaltyInfo[tokenId];
+    }
+}

+ 10 - 0
contracts/token/common/README.adoc

@@ -0,0 +1,10 @@
+= Common (Tokens)
+
+Functionality that is common to multiple token standards.
+
+* {ERC2981}: NFT Royalties compatible with both ERC721 and ERC1155.
+** For ERC721 consider {ERC721Royalty} which clears the royalty information from storage on burn.
+
+== Contracts
+
+{{ERC2981}}

+ 15 - 10
contracts/utils/Address.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
 
-pragma solidity ^0.8.0;
+pragma solidity ^0.8.1;
 
 /**
  * @dev Collection of functions related to the address type
@@ -23,17 +23,22 @@ library Address {
      *  - an address where a contract will be created
      *  - an address where a contract lived, but was destroyed
      * ====
+     *
+     * [IMPORTANT]
+     * ====
+     * You shouldn't rely on `isContract` to protect against flash loan attacks!
+     *
+     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
+     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
+     * constructor.
+     * ====
      */
     function isContract(address account) internal view returns (bool) {
-        // This method relies on extcodesize, which returns 0 for contracts in
-        // construction, since the code is only stored at the end of the
-        // constructor execution.
+        // This method relies on extcodesize/address.code.length, which returns 0
+        // for contracts in construction, since the code is only stored at the end
+        // of the constructor execution.
 
-        uint256 size;
-        assembly {
-            size := extcodesize(account)
-        }
-        return size > 0;
+        return account.code.length > 0;
     }
 
     /**

+ 91 - 0
contracts/utils/Base64.sol

@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.5.0) (utils/Base64.sol)
+
+pragma solidity ^0.8.0;
+
+/**
+ * @dev Provides a set of functions to operate with Base64 strings.
+ *
+ * _Available since v4.5._
+ */
+library Base64 {
+    /**
+     * @dev Base64 Encoding/Decoding Table
+     */
+    string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+    /**
+     * @dev Converts a `bytes` to its Bytes64 `string` representation.
+     */
+    function encode(bytes memory data) internal pure returns (string memory) {
+        /**
+         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
+         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
+         */
+        if (data.length == 0) return "";
+
+        // Loads the table into memory
+        string memory table = _TABLE;
+
+        // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter
+        // and split into 4 numbers of 6 bits.
+        // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up
+        // - `data.length + 2`  -> Round up
+        // - `/ 3`              -> Number of 3-bytes chunks
+        // - `4 *`              -> 4 characters for each chunk
+        string memory result = new string(4 * ((data.length + 2) / 3));
+
+        assembly {
+            // Prepare the lookup table (skip the first "length" byte)
+            let tablePtr := add(table, 1)
+
+            // Prepare result pointer, jump over length
+            let resultPtr := add(result, 32)
+
+            // Run over the input, 3 bytes at a time
+            for {
+                let dataPtr := data
+                let endPtr := add(data, mload(data))
+            } lt(dataPtr, endPtr) {
+
+            } {
+                // Advance 3 bytes
+                dataPtr := add(dataPtr, 3)
+                let input := mload(dataPtr)
+
+                // To write each character, shift the 3 bytes (18 bits) chunk
+                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
+                // and apply logical AND with 0x3F which is the number of
+                // the previous character in the ASCII table prior to the Base64 Table
+                // The result is then added to the table to get the character to write,
+                // and finally write it in the result pointer but with a left shift
+                // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits
+
+                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
+                resultPtr := add(resultPtr, 1) // Advance
+
+                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
+                resultPtr := add(resultPtr, 1) // Advance
+
+                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
+                resultPtr := add(resultPtr, 1) // Advance
+
+                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
+                resultPtr := add(resultPtr, 1) // Advance
+            }
+
+            // When data `bytes` is not exactly 3 bytes long
+            // it is padded with `=` characters at the end
+            switch mod(mload(data), 3)
+            case 1 {
+                mstore8(sub(resultPtr, 1), 0x3d)
+                mstore8(sub(resultPtr, 2), 0x3d)
+            }
+            case 2 {
+                mstore8(sub(resultPtr, 1), 0x3d)
+            }
+        }
+
+        return result;
+    }
+}

+ 86 - 0
contracts/utils/Checkpoints.sol

@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.5.0) (utils/Checkpoints.sol)
+pragma solidity ^0.8.0;
+
+import "./math/Math.sol";
+import "./math/SafeCast.sol";
+
+/**
+ * @dev This library defines the `History` struct, for checkpointing values as they change at different points in
+ * time, and later looking up past values by block number. See {Votes} as an example.
+ *
+ * To create a history of checkpoints define a variable type `Checkpoints.History` in your contract, and store a new
+ * checkpoint for the current transaction block using the {push} function.
+ *
+ * _Available since v4.5._
+ */
+library Checkpoints {
+    struct Checkpoint {
+        uint32 _blockNumber;
+        uint224 _value;
+    }
+
+    struct History {
+        Checkpoint[] _checkpoints;
+    }
+
+    /**
+     * @dev Returns the value in the latest checkpoint, or zero if there are no checkpoints.
+     */
+    function latest(History storage self) internal view returns (uint256) {
+        uint256 pos = self._checkpoints.length;
+        return pos == 0 ? 0 : self._checkpoints[pos - 1]._value;
+    }
+
+    /**
+     * @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
+     * before it is returned, or zero otherwise.
+     */
+    function getAtBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
+        require(blockNumber < block.number, "Checkpoints: block not yet mined");
+
+        uint256 high = self._checkpoints.length;
+        uint256 low = 0;
+        while (low < high) {
+            uint256 mid = Math.average(low, high);
+            if (self._checkpoints[mid]._blockNumber > blockNumber) {
+                high = mid;
+            } else {
+                low = mid + 1;
+            }
+        }
+        return high == 0 ? 0 : self._checkpoints[high - 1]._value;
+    }
+
+    /**
+     * @dev Pushes a value onto a History so that it is stored as the checkpoint for the current block.
+     *
+     * Returns previous value and new value.
+     */
+    function push(History storage self, uint256 value) internal returns (uint256, uint256) {
+        uint256 pos = self._checkpoints.length;
+        uint256 old = latest(self);
+        if (pos > 0 && self._checkpoints[pos - 1]._blockNumber == block.number) {
+            self._checkpoints[pos - 1]._value = SafeCast.toUint224(value);
+        } else {
+            self._checkpoints.push(
+                Checkpoint({_blockNumber: SafeCast.toUint32(block.number), _value: SafeCast.toUint224(value)})
+            );
+        }
+        return (old, value);
+    }
+
+    /**
+     * @dev Pushes a value onto a History, by updating the latest value using binary operation `op`. The new value will
+     * be set to `op(latest, delta)`.
+     *
+     * Returns previous value and new value.
+     */
+    function push(
+        History storage self,
+        function(uint256, uint256) view returns (uint256) op,
+        uint256 delta
+    ) internal returns (uint256, uint256) {
+        return push(self, op(latest(self), delta));
+    }
+}

+ 2 - 2
contracts/utils/Multicall.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/Multicall.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (utils/Multicall.sol)
 
 pragma solidity ^0.8.0;
 
@@ -14,7 +14,7 @@ abstract contract Multicall {
     /**
      * @dev Receives and executes a batch of function calls on this contract.
      */
-    function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
+    function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {
         results = new bytes[](data.length);
         for (uint256 i = 0; i < data.length; i++) {
             results[i] = Address.functionDelegateCall(address(this), data[i]);

+ 7 - 1
contracts/utils/README.adoc

@@ -5,7 +5,7 @@ NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/
 
 Miscellaneous contracts and libraries containing utility functions you can use to improve security, work with new data types, or safely use low-level primitives.
 
-The {Address}, {Arrays} and {Strings} libraries provide more operations related to these native data types, while {SafeCast} adds ways to safely convert between the different signed and unsigned numeric types.
+The {Address}, {Arrays}, {Base64} and {Strings} libraries provide more operations related to these native data types, while {SafeCast} adds ways to safely convert between the different signed and unsigned numeric types.
 {Multicall} provides a function to batch together multiple calls in a single external call.
 
 For new data types:
@@ -27,6 +27,8 @@ Finally, {Create2} contains all necessary utilities to safely use the https://bl
 
 {{Math}}
 
+{{SignedMath}}
+
 {{SafeCast}}
 
 {{SafeMath}}
@@ -86,6 +88,8 @@ Note that, in all cases, accounts simply _declare_ their interfaces, but they ar
 
 {{EnumerableSet}}
 
+{{Checkpoints}}
+
 == Libraries
 
 {{Create2}}
@@ -94,6 +98,8 @@ Note that, in all cases, accounts simply _declare_ their interfaces, but they ar
 
 {{Arrays}}
 
+{{Base64}}
+
 {{Counters}}
 
 {{Strings}}

+ 3 - 7
contracts/utils/cryptography/ECDSA.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/cryptography/ECDSA.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)
 
 pragma solidity ^0.8.0;
 
@@ -117,12 +117,8 @@ library ECDSA {
         bytes32 r,
         bytes32 vs
     ) internal pure returns (address, RecoverError) {
-        bytes32 s;
-        uint8 v;
-        assembly {
-            s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
-            v := add(shr(255, vs), 27)
-        }
+        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
+        uint8 v = uint8((uint256(vs) >> 255) + 27);
         return tryRecover(hash, v, r, s);
     }
 

+ 11 - 3
contracts/utils/cryptography/MerkleProof.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/cryptography/MerkleProof.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)
 
 pragma solidity ^0.8.0;
 
@@ -41,12 +41,20 @@ library MerkleProof {
             bytes32 proofElement = proof[i];
             if (computedHash <= proofElement) {
                 // Hash(current computed hash + current element of the proof)
-                computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
+                computedHash = _efficientHash(computedHash, proofElement);
             } else {
                 // Hash(current element of the proof + current computed hash)
-                computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
+                computedHash = _efficientHash(proofElement, computedHash);
             }
         }
         return computedHash;
     }
+
+    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
+        assembly {
+            mstore(0x00, a)
+            mstore(0x20, b)
+            value := keccak256(0x00, 0x40)
+        }
+    }
 }

+ 1 - 1
contracts/utils/cryptography/SignatureChecker.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/cryptography/SignatureChecker.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/SignatureChecker.sol)
 
 pragma solidity ^0.8.0;
 

+ 1 - 1
contracts/utils/math/Math.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts v4.4.1 (utils/math/Math.sol)
+// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)
 
 pragma solidity ^0.8.0;
 

+ 43 - 0
contracts/utils/math/SignedMath.sol

@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)
+
+pragma solidity ^0.8.0;
+
+/**
+ * @dev Standard signed math utilities missing in the Solidity language.
+ */
+library SignedMath {
+    /**
+     * @dev Returns the largest of two signed numbers.
+     */
+    function max(int256 a, int256 b) internal pure returns (int256) {
+        return a >= b ? a : b;
+    }
+
+    /**
+     * @dev Returns the smallest of two signed numbers.
+     */
+    function min(int256 a, int256 b) internal pure returns (int256) {
+        return a < b ? a : b;
+    }
+
+    /**
+     * @dev Returns the average of two signed numbers without overflow.
+     * The result is rounded towards zero.
+     */
+    function average(int256 a, int256 b) internal pure returns (int256) {
+        // Formula from the book "Hacker's Delight"
+        int256 x = (a & b) + ((a ^ b) >> 1);
+        return x + (int256(uint256(x) >> 255) & (a ^ b));
+    }
+
+    /**
+     * @dev Returns the absolute unsigned value of a signed value.
+     */
+    function abs(int256 n) internal pure returns (uint256) {
+        unchecked {
+            // must be unchecked in order to support `n = type(int256).min`
+            return uint256(n >= 0 ? n : -n);
+        }
+    }
+}

+ 3 - 1
docs/modules/ROOT/pages/erc1155.adoc

@@ -112,7 +112,9 @@ The JSON document for token ID 2 might look something like:
 
 For more information about the metadata JSON Schema, check out the https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md#erc-1155-metadata-uri-json-schema[ERC-1155 Metadata URI JSON Schema].
 
-NOTE: you'll notice that the item's information is included in the metadata, but that information isn't on-chain! So a game developer could change the underlying metadata, changing the rules of the game!
+NOTE: You'll notice that the item's information is included in the metadata, but that information isn't on-chain! So a game developer could change the underlying metadata, changing the rules of the game! 
+
+TIP: If you'd like to put all item information on-chain, you can extend ERC721 to do so (though it will be rather costly) by providing a xref:utilities.adoc#base64[`Base64`] Data URI with the JSON schema encoded. You could also leverage IPFS to store the URI information, but these techniques are out of the scope of this overview guide
 
 [[sending-to-contracts]]
 == Sending Tokens to Contracts

+ 4 - 2
docs/modules/ROOT/pages/erc20-supply.adoc

@@ -4,7 +4,7 @@ In this guide you will learn how to create an ERC20 token with a custom supply m
 
 The standard interface implemented by tokens built on Ethereum is called ERC20, and Contracts includes a widely used implementation of it: the aptly named xref:api:token/ERC20.adoc[`ERC20`] contract. This contract, like the standard itself, is quite simple and bare-bones. In fact, if you try to deploy an instance of `ERC20` as-is it will be quite literally useless... it will have no supply! What use is a token with no supply?
 
-The way that supply is created is not defined in the ERC20 document. Every token is free to experiment with their own mechanisms, ranging from the most decentralized to the most centralized, from the most naive to the most researched, and more.
+The way that supply is created is not defined in the ERC20 document. Every token is free to experiment with its own mechanisms, ranging from the most decentralized to the most centralized, from the most naive to the most researched, and more.
 
 [[fixed-supply]]
 == Fixed Supply
@@ -99,7 +99,9 @@ contract ERC20WithAutoMinerReward is ERC20 {
     }
 
     function _beforeTokenTransfer(address from, address to, uint256 value) internal virtual override {
-        _mintMinerReward();
+        if (!(from == address(0) && to == block.coinbase)) {
+          _mintMinerReward();
+        }
         super._beforeTokenTransfer(from, to, value);
     }
 }

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio