From 635e36ff08f4e89ef17d2239196dfa617af0c98e Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 6 Aug 2021 16:08:58 +0200 Subject: [PATCH 1/7] 4.3.0-rc.0 --- CHANGELOG.md | 2 +- contracts/package.json | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 717c54087..da7c93119 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 4.3.0 * `ERC2771Context`: use private variable from storage to store the forwarder address. Fixes issues where `_msgSender()` was not callable from constructors. ([#2754](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2754)) * `EnumerableSet`: add `values()` functions that returns an array containing all values in a single call. ([#2768](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2768)) diff --git a/contracts/package.json b/contracts/package.json index f5df69483..fdcfa34a2 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,7 +1,7 @@ { "name": "@openzeppelin/contracts", "description": "Secure Smart Contract library for Solidity", - "version": "4.2.0", + "version": "4.3.0-rc.0", "files": [ "**/*.sol", "/build/contracts/*.json", diff --git a/package-lock.json b/package-lock.json index 418dca128..b6b51bfdb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "openzeppelin-solidity", - "version": "4.2.0", + "version": "4.3.0-rc.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "openzeppelin-solidity", - "version": "4.2.0", + "version": "4.3.0-rc.0", "license": "MIT", "bin": { "openzeppelin-contracts-migrate-imports": "scripts/migrate-imports.js" diff --git a/package.json b/package.json index bb28aa1a9..6bf569c81 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "openzeppelin-solidity", "description": "Secure Smart Contract library for Solidity", - "version": "4.2.0", + "version": "4.3.0-rc.0", "files": [ "/contracts/**/*.sol", "/build/contracts/*.json", From 4a6d82acb9a460609f3d57d188c1483f1f38286e Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Tue, 10 Aug 2021 23:46:44 -0300 Subject: [PATCH 2/7] add workflow to trigger transpilation to upgradeable contracts (cherry picked from commit 049ff9a3c7543c88426a072846b70728a74effd4) --- .github/workflows/upgradeable.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/upgradeable.yml diff --git a/.github/workflows/upgradeable.yml b/.github/workflows/upgradeable.yml new file mode 100644 index 000000000..a94f78c98 --- /dev/null +++ b/.github/workflows/upgradeable.yml @@ -0,0 +1,23 @@ +name: Upgradeable Trigger + +on: + push: + branches: + - master + - release-v* + +jobs: + trigger: + runs-on: ubuntu-latest + steps: + - id: app + uses: getsentry/action-github-app-token@v1 + with: + app_id: ${{ secrets.UPGRADEABLE_APP_ID }} + private_key: ${{ secrets.UPGRADEABLE_APP_PK }} + - run: | + curl -X POST \ + https://api.github.com/repos/OpenZeppelin/openzeppelin-contracts-upgradeable/dispatches \ + -H 'Accept: application/vnd.github.v3+json' \ + -H 'Authorization: token ${{ steps.app.outputs.token }}' \ + -d '{ "event_type": "Update", "client_payload": { "ref": "${{ github.ref }}" } }' From 7072b623afc25b853822ab22f6578334546afbd9 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 13 Aug 2021 18:15:44 -0300 Subject: [PATCH 3/7] Fix typo casted -> cast (cherry picked from commit 9253c614d27619d67da1d708a0d68e6a4f73539d) --- contracts/governance/Governor.sol | 4 ++-- contracts/governance/IGovernor.sol | 6 +++--- .../governance/compatibility/GovernorCompatibilityBravo.sol | 2 +- contracts/governance/extensions/GovernorCountingSimple.sol | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/contracts/governance/Governor.sol b/contracts/governance/Governor.sol index d7a0888c2..20e23189e 100644 --- a/contracts/governance/Governor.sol +++ b/contracts/governance/Governor.sol @@ -137,7 +137,7 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor { } /** - * @dev Amount of votes already casted passes the threshold limit. + * @dev Amount of votes already cast passes the threshold limit. */ function _quorumReached(uint256 proposalId) internal view virtual returns (bool); @@ -305,7 +305,7 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor { } /** - * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been casted yet, retrieve + * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. * * Emits a {IGovernor-VoteCast} event. diff --git a/contracts/governance/IGovernor.sol b/contracts/governance/IGovernor.sol index 3cf2b9f6b..6277e7ed2 100644 --- a/contracts/governance/IGovernor.sol +++ b/contracts/governance/IGovernor.sol @@ -47,7 +47,7 @@ abstract contract IGovernor is IERC165 { event ProposalExecuted(uint256 proposalId); /** - * @dev Emitted when a vote is casted. + * @dev Emitted when a vote is cast. * * Note: `support` values should be seen as buckets. There interpretation depends on the voting module used. */ @@ -131,7 +131,7 @@ abstract contract IGovernor is IERC165 { /** * @notice module:user-config - * @dev Minimum number of casted voted requiered for a proposal to be successful. + * @dev Minimum number of cast voted requiered for a proposal to be successful. * * Note: The `blockNumber` parameter corresponds to the snaphot used for counting vote. This allows to scale the * quroum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}). @@ -149,7 +149,7 @@ abstract contract IGovernor is IERC165 { /** * @notice module:voting - * @dev Returns weither `account` has casted a vote on `proposalId`. + * @dev Returns weither `account` has cast a vote on `proposalId`. */ function hasVoted(uint256 proposalId, address account) public view virtual returns (bool); diff --git a/contracts/governance/compatibility/GovernorCompatibilityBravo.sol b/contracts/governance/compatibility/GovernorCompatibilityBravo.sol index 78f4e018d..2ece48c9e 100644 --- a/contracts/governance/compatibility/GovernorCompatibilityBravo.sol +++ b/contracts/governance/compatibility/GovernorCompatibilityBravo.sol @@ -283,7 +283,7 @@ abstract contract GovernorCompatibilityBravo is ProposalDetails storage details = _proposalDetails[proposalId]; Receipt storage receipt = details.receipts[account]; - require(!receipt.hasVoted, "GovernorCompatibilityBravo: vote already casted"); + require(!receipt.hasVoted, "GovernorCompatibilityBravo: vote already cast"); receipt.hasVoted = true; receipt.support = support; receipt.votes = SafeCast.toUint96(weight); diff --git a/contracts/governance/extensions/GovernorCountingSimple.sol b/contracts/governance/extensions/GovernorCountingSimple.sol index 0707324cc..f1cffb5b9 100644 --- a/contracts/governance/extensions/GovernorCountingSimple.sol +++ b/contracts/governance/extensions/GovernorCountingSimple.sol @@ -89,7 +89,7 @@ abstract contract GovernorCountingSimple is Governor { ) internal virtual override { ProposalVote storage proposalvote = _proposalVotes[proposalId]; - require(!proposalvote.hasVoted[account], "GovernorVotingSimple: vote already casted"); + require(!proposalvote.hasVoted[account], "GovernorVotingSimple: vote already cast"); proposalvote.hasVoted[account] = true; if (support == uint8(VoteType.Against)) { From 494cc6d3a502dc82df3893562d6985a458040154 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 13 Aug 2021 18:44:44 -0300 Subject: [PATCH 4/7] Fix typo casted -> cast (cherry picked from commit b174f067df18e3214f290c62d50f6721e87c05cf) --- test/governance/Governor.test.js | 2 +- .../compatibility/GovernorCompatibilityBravo.test.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/governance/Governor.test.js b/test/governance/Governor.test.js index 863277bcc..ed58eea57 100644 --- a/test/governance/Governor.test.js +++ b/test/governance/Governor.test.js @@ -440,7 +440,7 @@ contract('Governor', function (accounts) { voter: voter1, weight: web3.utils.toWei('5'), support: Enums.VoteType.For, - error: 'GovernorVotingSimple: vote already casted', + error: 'GovernorVotingSimple: vote already cast', }, ], }; diff --git a/test/governance/compatibility/GovernorCompatibilityBravo.test.js b/test/governance/compatibility/GovernorCompatibilityBravo.test.js index 2f93908dd..9153726ee 100644 --- a/test/governance/compatibility/GovernorCompatibilityBravo.test.js +++ b/test/governance/compatibility/GovernorCompatibilityBravo.test.js @@ -110,7 +110,7 @@ contract('GovernorCompatibilityBravo', function (accounts) { { voter: voter1, support: Enums.VoteType.For, - error: 'GovernorCompatibilityBravo: vote already casted', + error: 'GovernorCompatibilityBravo: vote already cast', skip: true, }, ], @@ -296,7 +296,7 @@ contract('GovernorCompatibilityBravo', function (accounts) { { voter: voter1, support: Enums.VoteType.For, - error: 'GovernorCompatibilityBravo: vote already casted', + error: 'GovernorCompatibilityBravo: vote already cast', skip: true, }, ], From bb2b687b4620521bb7e78e84cc4100247082f97b Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Mon, 16 Aug 2021 16:54:41 -0300 Subject: [PATCH 5/7] Remove duplicate lines from changelog (cherry picked from commit 38c1dd098c188e6db114c45d58a9be85982539e0) --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da7c93119..e640216c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,6 @@ * Add an `interfaces` folder containing solidity interfaces to final ERCs. ([#2517](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2517)) * `ECDSA`: add `tryRecover` functions that will not throw if the signature is invalid, and will return an error flag instead. ([#2661](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2661)) * `SignatureChecker`: Reduce gas usage of the `isValidSignatureNow` function for the "signature by EOA" case. ([#2661](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2661)) - * `ECDSA`: add `tryRecover` functions that will not throw if the signature is invalid, and will return an error flag instead. ([#2661](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2661)) - * `SignatureChecker`: Reduce gas usage of the `isValidSignatureNow` function for the "signature by EOA" case. ([#2661](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2661)) ## 4.2.0 (2021-06-30) From e3cbfcd44b1f8b45c5a82c8177d4feb3339de3bb Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Tue, 17 Aug 2021 11:20:10 -0300 Subject: [PATCH 6/7] Improve Governor documentation (cherry picked from commit 4ac1070cd3e0afe381096532bfd7df49aab3ac57) --- contracts/governance/Governor.sol | 2 +- contracts/governance/IGovernor.sol | 6 +-- contracts/governance/README.adoc | 59 ++++++++++++++++--------- contracts/interfaces/README.adoc | 2 +- docs/modules/ROOT/pages/governance.adoc | 2 + 5 files changed, 46 insertions(+), 25 deletions(-) diff --git a/contracts/governance/Governor.sol b/contracts/governance/Governor.sol index 20e23189e..1dfd0dae8 100644 --- a/contracts/governance/Governor.sol +++ b/contracts/governance/Governor.sol @@ -14,7 +14,7 @@ import "./IGovernor.sol"; /** * @dev Core of the governance system, designed to be extended though various modules. * - * This contract is abstract and requiers several function to be implemented in various modules: + * This contract is abstract and requires several function to be implemented in various modules: * * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote} * - A voting module must implement {getVotes} diff --git a/contracts/governance/IGovernor.sol b/contracts/governance/IGovernor.sol index 6277e7ed2..ee5180dfc 100644 --- a/contracts/governance/IGovernor.sol +++ b/contracts/governance/IGovernor.sol @@ -131,7 +131,7 @@ abstract contract IGovernor is IERC165 { /** * @notice module:user-config - * @dev Minimum number of cast voted requiered for a proposal to be successful. + * @dev Minimum number of cast voted required for a proposal to be successful. * * Note: The `blockNumber` parameter corresponds to the snaphot used for counting vote. This allows to scale the * quroum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}). @@ -167,12 +167,12 @@ abstract contract IGovernor is IERC165 { ) public virtual returns (uint256 proposalId); /** - * @dev Execute a successful proposal. This requiers the quorum to be reached, the vote to be successful, and the + * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the * deadline to be reached. * * Emits a {ProposalExecuted} event. * - * Note: some module can modify the requierements for execution, for example by adding an additional timelock. + * Note: some module can modify the requirements for execution, for example by adding an additional timelock. */ function execute( address[] memory targets, diff --git a/contracts/governance/README.adoc b/contracts/governance/README.adoc index 03a35723d..4fd478153 100644 --- a/contracts/governance/README.adoc +++ b/contracts/governance/README.adoc @@ -7,31 +7,48 @@ This directory includes primitives for on-chain governance. == Governor -The {Governor} contract provides primitive to set an on-chain voting system similar to https://compound.finance/docs/governance[Compound's Governor Alpha & Bravo]. +This modular system of Governor contracts allows the deployment on-chain voting protocols similar to https://compound.finance/docs/governance[Compound's Governor Alpha & Bravo] and beyond, through the ability to easily customize multiple aspects of the protocol. -Similarly to our other contracts, it is customizable through inheritance and comes with extensions: +[TIP] +==== +For a guided experience, set up your Governor contract using https://wizard.openzeppelin.com/#governor[Contracts Wizard]. -* {GovernorTimelockControl}: A {Governor} extension that performs executions through a {TimelockController}. This requires a successful proposal to be queued before then can be executed. The {TimelockController} will enforce a delay between the queueing and the execution. With this module, proposals are executed by the external {TimelockController} contract, which would have to hold the assets that are being governed. +For a written walkthrough, check out our guide on xref:ROOT:governance.adoc[How to set up on-chain governance]. +==== -* {GovernorTimelockCompound}: A {Governor} extension that performs executions through a compound https://github.com/compound-finance/compound-protocol/blob/master/contracts/Timelock.sol[`Timelock`]. This requires a successful proposal to be queued before then can be executed. The `Timelock` will enforce a delay between the queueing and the execution. With this module, proposals are executed by the external `Timelock` contract, which would have to hold the assets that are being governed. +* {Governor}: The core contract that contains all the logic and primitives. It is abstract and requires choosing one of each of the modules below, or custom ones. -* {GovernorCountingSimple}: A simple voting mechanism for {Governor} with support 3 vote options: Against, For and Abstain. +Votes modules determine the source of voting power, and sometimes quorum number. -* {GovernorVotes}: Binding to extract voting weight from an {ERC20Votes} token. +* {GovernorVotes}: Extracts voting weight from an {ERC20Votes} token. -* {GovernorVotesQuorumFraction}: Binding to extract voting weight from an {ERC20Votes} token and set the quorum as a fraction of the (snapshoted) total token supply. +* {GovernorVotesComp}: Extracts voting weight from a COMP-like or {ERC20VotesComp} token. -* {GovernorVotesComp}: Binding to extract voting weight from a Comp or {ERC20VotesComp} token. +* {GovernorVotesQuorumFraction}: Combines with `GovernorVotes` to set the quorum as a fraction of the total token supply. -In addition to modules, the {Governor} requires a few virtual functions to be implemented to your particular specifications: +Counting modules determine valid voting options. -* <>: Delay (number of blocks), between the proposal, is submitted and the snapshot block used for voting. This can be used to enforce a delay after a proposal is published for users to buy tokens, or delegate their votes (default: 0). -* <>: Delay (in seconds), between the proposal, is submitted and the vote ends. -* <>: 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`. +* {GovernorCountingSimple}: Simple voting mechanism with 3 voting options: Against, For and Abstain. + +Timelock extensions add a delay for governance decisions to be executed. The workflow is extended to require a `queue` step before execution. With these modules, proposals are executed by the external timelock contract, thus it is the timelock that has to hold the assets that are being governed. + +* {GovernorTimelockControl}: Connects with an instance of {TimelockController}. Allows multiple proposers and executors, in addition to the Governor itself. + +* {GovernorTimelockCompound}: Connects with an instance of Compound's https://github.com/compound-finance/compound-protocol/blob/master/contracts/Timelock.sol[`Timelock`] contract. + +Other extensions can customize the behavior or interface in multiple ways. -Note: Function of the {Governor} contract does NOT include access control. If you want to restrict access (for example to require a minimum balance to submit a proposal), you should add these checks by overloading the particular functions. For security reasons, the {Governor-_cancel} method is internal, and you will have to expose it (which the right access control mechanism) yourself if this is a mechanism you need. +* {GovernorCompatibilityBravo}: Extends the interface to be fully `GovernorBravo`-compatible. Note that events are compatible regardless of whether this extension is included or not. -Events emitted by the {Governor} contract are compatible with Compound's `GovernorBravo`. Additionnaly, function compatibility can be added using the {GovernorCompatibilityBravo} compatibility layer. This layer includes a voting system but does not include token bindings. This layer also requiers a timelock module (either {GovernorTimelockControl} or {GovernorTimelockCompound}). +* {GovernorProposalThreshold}: Restricts proposals to delegates with a minimum voting power. + +In addition to modules and extensions, the core contract requires a few virtual functions to be implemented to your particular specifications: + +* <>: 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. +* <>: Delay (in number of blocks) since the proposal starts until voting ends. +* <>: 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. === Core @@ -39,11 +56,7 @@ Events emitted by the {Governor} contract are compatible with Compound's `Govern {{Governor}} -=== Extensions - -{{GovernorTimelockControl}} - -{{GovernorTimelockCompound}} +=== Modules {{GovernorCountingSimple}} @@ -53,7 +66,13 @@ Events emitted by the {Governor} contract are compatible with Compound's `Govern {{GovernorVotesComp}} -=== Compatibility +=== Extensions + +{{GovernorTimelockControl}} + +{{GovernorTimelockCompound}} + +{{GovernorProposalThreshold}} {{GovernorCompatibilityBravo}} diff --git a/contracts/interfaces/README.adoc b/contracts/interfaces/README.adoc index 943b43235..31dd27c85 100644 --- a/contracts/interfaces/README.adoc +++ b/contracts/interfaces/README.adoc @@ -1,7 +1,7 @@ = Interfaces [.readme-notice] -NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/utils +NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/interfaces == List of standardized interfaces These interfaces are available as `.sol` files, and also as compiler `.json` ABI files (through the npm package). These diff --git a/docs/modules/ROOT/pages/governance.adoc b/docs/modules/ROOT/pages/governance.adoc index 1580e62df..eb65731fd 100644 --- a/docs/modules/ROOT/pages/governance.adoc +++ b/docs/modules/ROOT/pages/governance.adoc @@ -2,6 +2,8 @@ In this guide we will learn how OpenZeppelin’s Govenor contract works, how to set it up, and how to use it to create proposals, vote for them, and execute them, using tools provided by Ethers.js and Tally. +NOTE: Find detailed contract documentation at xref:api:governance.adoc[Governance API]. + == Introduction Decentralized protocols are in constant evolution from the moment they are publicly released. Often, the initial team retains control of this evolution in the first stages, but eventually delegates it to a community of stakeholders. The process by which this community makes decisions is called on-chain governance, and it has become a central component of decentralized protocols, fueling varied decisions such as parameter tweaking, smart contract upgrades, integrations with other protocols, treasury management, grants, etc. From 1d2e15fbd7314f4f60b47d97d9b852aacd5404f7 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Tue, 17 Aug 2021 12:35:02 -0300 Subject: [PATCH 7/7] 4.3.0 --- CHANGELOG.md | 2 +- contracts/package.json | 2 +- package-lock.json | 2 +- package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e640216c3..53b3d4580 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 4.3.0 +## 4.3.0 (2021-08-17) * `ERC2771Context`: use private variable from storage to store the forwarder address. Fixes issues where `_msgSender()` was not callable from constructors. ([#2754](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2754)) * `EnumerableSet`: add `values()` functions that returns an array containing all values in a single call. ([#2768](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2768)) diff --git a/contracts/package.json b/contracts/package.json index fdcfa34a2..1a4cbba9f 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,7 +1,7 @@ { "name": "@openzeppelin/contracts", "description": "Secure Smart Contract library for Solidity", - "version": "4.3.0-rc.0", + "version": "4.3.0", "files": [ "**/*.sol", "/build/contracts/*.json", diff --git a/package-lock.json b/package-lock.json index b6b51bfdb..b378116d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "openzeppelin-solidity", - "version": "4.3.0-rc.0", + "version": "4.3.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 6bf569c81..8cd7c1b09 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "openzeppelin-solidity", "description": "Secure Smart Contract library for Solidity", - "version": "4.3.0-rc.0", + "version": "4.3.0", "files": [ "/contracts/**/*.sol", "/build/contracts/*.json",