Compare commits

...

290 Commits

Author SHA1 Message Date
b53c43242f 4.4.2 2022-01-11 16:52:22 -03:00
9cae52c591 Use abi.encodePacked instead of bytes.concat
(cherry picked from commit 1051db3802)
2022-01-11 16:52:22 -03:00
93d2d1508a Make script executable
(cherry picked from commit a8f35b6c25)
2022-01-11 16:42:24 -03:00
eff4ad7c1d Fix encoding of signature+calldata in GovernorCompatibilityBravo (#3100)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
(cherry picked from commit c366de3626)
2022-01-11 16:26:21 -03:00
66436cbb4e Change release script to only update version comment for changed files (#3033)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
(cherry picked from commit 1ffcb10bd2)
2022-01-11 16:22:37 -03:00
6bd6b76d11 4.4.1 2021-12-14 13:14:39 -03:00
13a6ec753a Remove bad date from changelog 2021-12-14 13:14:21 -03:00
553c8fdec7 Update initializer modifier to prevent reentrancy during initialization (#3006)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
(cherry picked from commit 08840b9f8c)
2021-12-10 13:10:17 -03:00
4961a51cc7 4.4.0 2021-11-25 16:35:37 -03:00
94a0b8f573 Make VestingWallet token event argument indexed (#2988)
(cherry picked from commit 0859c70936)
2021-11-25 16:03:00 -03:00
0413d58860 add bug bounty info
(cherry picked from commit 86bd4d7389)
2021-11-22 15:06:10 +01:00
a4cee9ed37 make setters in GovernorSettings virtual
(cherry picked from commit 6e5bf05211)
2021-11-18 10:17:31 +01:00
65ef662a2b 4.4.0-rc.1 2021-11-16 10:23:53 -03:00
8b8ee57a1a Make quorum behavior match GovernorBravo (#2974)
* Make quorum inclusive minimum in GovernorCompatibilityBravo

* add PR link

(cherry picked from commit a94cf0509f)
2021-11-16 10:08:08 -03:00
cf6e32fc54 Fix Timelock Controller description typo (#2960)
(cherry picked from commit e63b09c9ad)
2021-11-15 18:08:07 -03:00
3a3e643eb9 Fix typo and reframed a sentence (#2951)
Corrected spelling for a word on line number 3 and sentence reframed on line number 309

(cherry picked from commit 2b4e023180)
2021-11-15 18:08:07 -03:00
462d6fa2b2 Grammar correction in utilities doc (#2952)
Fix grammar in a sentence

(cherry picked from commit b5daea6d5f)
2021-11-15 18:08:07 -03:00
70138680cf Fix ERC1155 supply tracking (#2956)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
(cherry picked from commit 4088540aef)
2021-11-15 18:07:21 -03:00
3db4393b58 Fix link to #2849 in changelog
(cherry picked from commit 57630d2a64)
2021-11-09 15:40:19 -03:00
09e5888ca8 fix typos in GovernorSettings (#2957)
(cherry picked from commit ce51655c81)
Signed-off-by: Hadrien Croubois <hadrien.croubois@gmail.com>
2021-11-08 17:26:05 +01:00
6dab43c3a9 AccessControlEnumerable: Hook into the internal function (#2946)
* AccessControlEnumerable: Hook into the internal function

* add changelog entry

(cherry picked from commit 7579828180)
2021-11-08 12:23:37 -03:00
db58acead1 Fix changelog links
(cherry picked from commit 2b046d79e1)
2021-10-27 18:19:35 -03:00
0a87a4e75b 4.4.0-rc.0 2021-10-20 17:21:04 -03:00
7dcc7b372f Fix update-comment.js 2021-10-20 17:20:49 -03:00
9e13852135 Fix typo (#2919) 2021-10-20 08:33:08 +02:00
c9bdb1f0ae Add a comment documenting the package version being used (#2918) 2021-10-19 19:18:19 -03:00
7fe5326c2d Add changelog entries for #2849 2021-10-19 15:37:11 -03:00
b12af48a7d Add Governor module for governance-settable parameters (#2904)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-10-19 15:33:02 -03:00
0db97c9681 updated docs for governor votes, 0 is against not for (#2915)
* updated docs for governor votes, 0 is against not for

* Revert unecessary changelog entry

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
2021-10-18 18:41:02 +02:00
88e4b69bfb Add a VestingWallet (#2748)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-10-18 12:47:37 -03:00
e6f26b46fc Fix code sample in utilities.adoc 2021-10-14 23:31:24 -03:00
7006e4e3e6 Remove invalid parameters in MerkleProof tests (#2912) 2021-10-14 22:02:49 -03:00
d244b81972 Add a MerkleProof.processProof utility function (#2841)
* Add a MerkleProof.processProof utility function

* Add changelog entry

* fix lint

* return index when processingProof

* fix lint

* fix test

* Apply suggestions from code review

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>

* improve documentation

* Apply suggestions from code review

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>

* remove index - see discussion in the PR

* update changelog

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-10-14 11:50:35 +02:00
5b28259dac #890: Add ECDSA.toEthSignedMessageHash(bytes) for abritrary length message hashing (#2865)
* #890: Add ECDSA#toEthSignedMessage for bytes type

* refactor

* add test, refactor

* select overloaded function explicitly

* use short test message string

* add changelog entry

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
2021-10-11 14:59:30 +02:00
efb5b0a28f Extend PaymentSplitter to support ERC20 tokens (#2858)
* Add MultiPaymentSplitter

with ERC20 support on top of the existing PaymentSplitter

* consistency and linting

* Add MultiPaymentSplitter tests

* fix lint

* add changelog entry

* add MultiPaymentSplitter to documentation

* rework PaymentSplitter to include ERC20 support by default

* remove test file for MultiPaymentSplitter

* fix lint

* completelly split erc20 and token tracking

* address some PR comments

* add notice about rebasing tokens

* fix minor error in tests

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-10-07 16:17:10 +02:00
abeb0fbf5c Delay the Pending state until strictly after proposal.voteStart (#2892)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-10-06 19:29:57 -03:00
caba6b93ef Add an internal _setApprovalForAll function (721 & 1155) (#2834)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-10-06 13:48:18 +00:00
e2fa301bfb Improve parameters naming and remove unecessary returns (#2891) 2021-10-06 10:34:27 -03:00
29eeb2828e Fix EIP712 for delegatecalls (#2852)
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-10-06 10:24:46 -03:00
75d422feca Update lockfile (#2842)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-05 22:36:25 -03:00
6f23efa970 Review wording of SafeMath need in Solidity 0.8 (#2898) 2021-10-05 16:12:51 +02:00
1b27c13096 Fix typo in doc of SignatureChecker (#2881) 2021-09-24 13:27:53 +00:00
f77fd4667e fix typo in GovernorCountingSimple (#2879)
Co-authored-by: Joey Santoro <joseph.santoro@duke.edu>
2021-09-23 08:37:02 +00:00
6af4ed6169 revokeRole spec mismatch (#2872)
revokeRole emits {RoleRevoked} event if `account` has been revoked `role`

Greetings from ChainSecurity!
2021-09-21 10:16:14 +02:00
01f2ff1ba1 Allow Governor + CompoundTimelock to manage native tokens (eth) in and out of the timelock contract. (#2849)
* Change GovernorTimelockCompound to support ETH in Timelock

* refactor compound timelock module

* Allow governor to receive ETH is executor == address(this)
2021-09-17 16:57:00 +02:00
296223f876 Merge branch 'release-v4.3' 2021-09-15 10:41:50 -03:00
0c4de6721d 4.3.2 2021-09-14 18:06:39 -03:00
024cc50df4 Restrict upgrade to proxy context in UUPSUpgradeable
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
(cherry picked from commit 6241995ad3)
2021-09-14 18:06:00 -03:00
6241995ad3 Restrict upgrade to proxy context in UUPSUpgradeable
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-09-14 17:33:17 -03:00
d02cc020e8 Remove deprecated prepublish script 2021-09-14 17:29:19 -03:00
bc5c8e2c9c Improve wording of recommendation in Initializable 2021-09-14 16:57:26 -03:00
7237b1672e Make some private functions internal to allow the developpement of "withSignature" functions (like permit) (#2568)
* add internal _setOwner in Ownable

* address issues raised in #2567

* updte changelog entry

* improve changelog and documentation

* rephrasing doc

* add cahngelog improvement lost in merge

* notify deprecation of _setupRole in changelog

* Demote caution to note

* Update CHANGELOG.md

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-09-14 09:03:47 +02:00
5e34a84d4a Fix ERC721URIStorage description in docs 2021-09-13 18:32:43 -03:00
38448c104a Add recommendation to initialize all contracts that use Initializable 2021-09-13 18:08:50 -03:00
8a5b67fb79 Add notice about location of funds in Governor+Timelock setup (#2855) 2021-09-13 17:43:49 -03:00
aefcb3e8aa Bump tar from 4.4.17 to 4.4.19 (#2843)
Bumps [tar](https://github.com/npm/node-tar) from 4.4.17 to 4.4.19.
- [Release notes](https://github.com/npm/node-tar/releases)
- [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-tar/compare/v4.4.17...v4.4.19)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-01 14:28:28 +02:00
fb36326a58 Support london with coverage using initialBaseFee = 0 (#2838) 2021-08-30 16:42:22 -03:00
9b4326d91e Fixed a typo (#2835) 2021-08-30 15:20:35 +02:00
6edb6dd1ca 4.3.1 2021-08-26 17:59:03 -03:00
0ec7f4c25d Add additional isOperationReady check in TimelockController
(cherry picked from commit cec4f2ef57)
2021-08-24 16:23:37 -03:00
cec4f2ef57 Add additional isOperationReady check in TimelockController 2021-08-24 16:23:12 -03:00
52188a2127 Add changelog entry for 3.4.1 2021-08-24 16:09:25 -03:00
83644fdb6a Remove unused SafeMath.sol import (#2823) 2021-08-20 21:26:41 +00:00
56d4063e92 Add comment about optimizer in GovernorCompatibilityBravo 2021-08-20 12:38:44 -03:00
1baa009266 Merge branch 'release-v4.3' 2021-08-17 22:39:45 -03:00
1d2e15fbd7 4.3.0 2021-08-17 12:35:02 -03:00
e3cbfcd44b Improve Governor documentation
(cherry picked from commit 4ac1070cd3)
2021-08-17 11:20:50 -03:00
4ac1070cd3 Improve Governor documentation 2021-08-17 11:20:10 -03:00
bb2b687b46 Remove duplicate lines from changelog
(cherry picked from commit 38c1dd098c)
2021-08-16 16:55:23 -03:00
38c1dd098c Remove duplicate lines from changelog 2021-08-16 16:54:41 -03:00
494cc6d3a5 Fix typo casted -> cast
(cherry picked from commit b174f067df)
2021-08-13 18:45:15 -03:00
b174f067df Fix typo casted -> cast 2021-08-13 18:44:44 -03:00
7072b623af Fix typo casted -> cast
(cherry picked from commit 9253c614d2)
2021-08-13 18:17:22 -03:00
4a6d82acb9 add workflow to trigger transpilation to upgradeable contracts
(cherry picked from commit 049ff9a3c7)
2021-08-13 18:17:21 -03:00
9253c614d2 Fix typo casted -> cast 2021-08-13 18:16:38 -03:00
049ff9a3c7 add workflow to trigger transpilation to upgradeable contracts 2021-08-13 18:15:37 -03:00
73425c22d8 Update lockfile (#2787)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-12 14:35:20 +00:00
832ff3b9f9 Fix docs function for ECDSA (#2819) 2021-08-10 17:37:50 -03:00
635e36ff08 4.3.0-rc.0 2021-08-06 16:08:58 +02:00
6618f9f184 Fix documentation of functions in interfaces directory 2021-08-06 11:06:30 -03:00
7fcacb549b Fix name of interfaces directory in changelog 2021-08-06 11:04:40 -03:00
541e82144f Optimize EOA signature verification (#2661)
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-08-06 10:47:52 -03:00
18668870fd Add an interface folder that lists common interfaces (#2517)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-08-06 10:36:34 -03:00
694f169832 Remove changelog entry for test changes 2021-08-06 10:14:00 -03:00
7279273ebb Fix inconsistencies in contract/test hierachy (#2814)
* Fix inconsistencies in contract/test hierachy

* changelog entry
2021-08-06 13:43:23 +02:00
d89f2a4ac6 Update ERC721.behavior.js (#2801) 2021-08-05 19:44:13 +02:00
48375aa908 Read optional compiler version from args/envvars (#2810) 2021-08-05 16:03:50 +02:00
29957d4a47 Add Governor guide (#2811) 2021-08-04 19:08:44 -03:00
4b152bd8ce Improve Governor (#2794)
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
2021-08-04 18:29:13 -03:00
f782943099 Move variable declaration to top of test file (#2806)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-08-03 14:19:21 +00:00
3da0cf698f Uncomment assertion in ERC2771Context.test.js (#2796) 2021-08-03 11:06:24 -03:00
e1c0f3eaef Update tests for RFC 2606 (#2802) 2021-08-02 23:41:13 +00:00
8bcf0ad7ab Use Hardhat recommended Mocha configuration (#2805) 2021-08-02 20:35:12 -03:00
56b3b7a487 Remove mention of 2.0.0 audit in docs 2021-08-02 20:06:30 -03:00
bbd68b721d Update security policy regarding past major releases 2021-08-02 19:57:04 -03:00
2d1e82c901 remove duplicated 'private-vars-leading-underscore' solhint rule (#2800) 2021-08-02 18:02:40 +02:00
9a385dcb45 fix typo 2021-08-02 12:14:20 +02:00
3dadd40034 Avoid safe math in BitMap (#2797) 2021-07-30 09:48:45 +02:00
566a774222 Update lockfile (#2774)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-20 10:49:34 -03:00
865dc9365c Update codecov/codecov-action action to v2 (#2779)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-20 13:48:26 +00:00
0500c9e53e Use "OpenZeppelin Contracts" where appropriate (#2778) 2021-07-20 10:35:58 -03:00
d3c5bdf4de Fix yellowpaper reference (#2775) 2021-07-19 09:45:04 -03:00
7e41bf2259 Remove ERC20FlashMint from drafts section in docs 2021-07-16 19:44:40 -03:00
6c1a634053 Add Governor contracts (#2672)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-07-16 12:44:01 -03:00
f88e555234 Add values() functions to EnumerableSets (#2768)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-07-16 12:06:47 -03:00
87826f807a Update lockfile 2021-07-16 11:58:22 -03:00
b8fdc620aa Downgrade yargs to v16 2021-07-16 11:49:12 -03:00
466cf05912 Deprecate openzeppelin-solidity on every release 2021-07-16 11:22:47 -03:00
8467143f2a Update lockfile (#2763)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-14 16:14:51 -03:00
c346c09b01 Clarify zero address usage in proposer and executor roles in Timelock (#2765)
* Clarify zero address usage in proposer and executor roles in access control

* Address zero only applies to executor

* Fix incorrect role
2021-07-14 16:39:08 +02:00
3935b907d4 Fix NatSpec comment syntax 2021-07-13 17:10:54 -03:00
4e2641a915 Simplify selector access (#2766) 2021-07-13 01:23:14 +02:00
973b0f883a fix typo in erc20 docs (#2764) 2021-07-12 16:45:39 +02:00
6d97f09195 Gas optimization on average function of Math.sol (#2757)
* change implementation to save gas

* add average test with two max uni256 number
2021-07-10 21:28:12 +02:00
1c1ebd765d Remove defer tag for Wizard embed script 2021-07-09 16:38:44 -03:00
9eba3ef29a fix two minor typos (#2755) 2021-07-08 17:23:13 +02:00
e4696f7315 Update lockfile (#2752)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-06 19:23:06 -03:00
23b3807ea7 Use private instead of immutable in ERC2771Context (#2754) 2021-07-06 14:41:03 -03:00
15b92e4097 Add missing "await" in tests (#2749)
* add missing await in tests

* fix test description
2021-07-06 17:20:08 +02:00
922058dbc8 Change comma to decimal point in comment (#2742) 2021-07-05 12:20:27 -03:00
b9e2c7896d Merge branch 'release-v4.2' 2021-06-30 14:31:57 -03:00
9fbc1d71c0 4.2.0 2021-06-30 14:29:37 -03:00
3ae911b442 Update lockfile (#2732)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-29 17:46:11 -03:00
eea376911b Reorder AccessControl event to emit after assignment (#2738) 2021-06-24 10:38:02 -03:00
1db3037808 Fix misleading comments (#2737)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-06-24 10:37:20 -03:00
556e366ce5 4.2.0-rc.0 2021-06-23 09:54:29 -03:00
6842518b1b Wrapper extension for ERC20 token (#2633)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-06-22 19:27:33 -03:00
8a775cd8d4 Emit DelegateVotesChanged events after Transfer (#2733) 2021-06-22 19:14:40 -03:00
4d0f8c1da8 Check inheritance tree consistency (#2727)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-06-18 15:08:13 +00:00
27e09007cc Reorder state changes and event emission for consistency (#2719)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-06-18 14:58:50 +00:00
00128bd260 Fix function ordering in ERC1967Upgrades (#2722) 2021-06-14 18:54:19 -03:00
f710bafae8 Fix typos (#2723) 2021-06-14 18:51:56 -03:00
788d338c9b Improve naming of internal variables (#2721) 2021-06-14 18:51:37 -03:00
6f50f6e1ef Remove repeated code from ERC1967Upgrade (#2720) 2021-06-14 18:50:51 -03:00
fd111df16d Remove unecessary code from Context (#2718) 2021-06-14 18:44:00 -03:00
17958adaca Uninstall unused mocha dependency 2021-06-14 17:41:34 -03:00
0a05f6fa45 Add a recover(bytes32,bytes32,bytes32) that follows EIP2098 (#2713) 2021-06-14 15:12:08 -03:00
78103f3137 Update lockfile (#2717)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-14 18:55:46 +02:00
f7da53cebd Add a BitMap struct (#2710)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-06-11 15:24:00 -03:00
75f6dbb86c Add import statements and GitHub link in API docs (#2714) 2021-06-11 15:09:32 -03:00
9d5f77db9d Update lockfile (#2702)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-07 19:45:26 +02:00
b0cf6fbb7a Add Prettier for linting and fix Solhint config (#2697)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-06-07 12:33:03 -03:00
e3661abe84 Split ERC20Votes and ERC20VotesComp (#2706)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-06-04 12:52:19 -03:00
1488d4f678 Improve ECDSA tests and docs (#2619) 2021-06-01 17:59:24 -03:00
adc50d465c Tweak ERC20Votes revert reasons and documentation (#2696)
* adapt revert reason convention

* add whitespace

* tweak documentation

* fix tests
2021-05-27 18:16:37 +02:00
f6efd8aced Add totalSupply checkpoints to ER20Votes (#2695)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-05-27 15:13:18 +00:00
ad3c18eb5f Fix the ERC721 link in the ERC1155 doc (#2694) 2021-05-26 19:11:08 +00:00
eabec630b9 Update lockfile (#2690)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-26 15:27:55 -03:00
406c83649b Introduce ERC1155 totalSupply() and exists() functions (#2593)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-05-20 21:46:21 +00:00
5f50b9f6e0 Update lockfile (#2675)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-20 11:45:43 -03:00
1b37c21da5 reserve unchecked for when guarded by explicit require (#2685) 2021-05-20 16:40:18 +02:00
7144ec8db4 Fix whitespace in ERC777 (#2667) 2021-05-20 11:01:20 -03:00
f31bb101ad Move ERC20Votes and ERC20FlashMint out of draft (#2673)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-05-20 11:00:22 -03:00
7c754d0665 Add ceiling division operation to the Math.sol library (#2681)
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-05-20 13:53:31 +00:00
5f7eda1f98 Tokens: wrap safe substractions in uchecked block (#2669)
* Tokens: wrap definitely safe subs in unchecked

* Add change in changelog

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
2021-05-20 10:33:28 +02:00
f8f6d56c58 Update README intro with link to Wizard 2021-05-19 20:58:29 -03:00
8ad458e955 Explain how baseURI is used for building the tokenURI (#2679) 2021-05-19 16:07:56 -03:00
8ea06b75aa Add a Counter.reset function (#2678) 2021-05-19 15:52:43 -03:00
c3ae4790c7 Fix Changelog structure 2021-05-14 15:42:18 +02:00
5cd86f740d Update lockfile (#2666)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-12 16:14:31 +00:00
aa06c9fbc1 Use Node 12 in CI 2021-05-12 13:06:07 -03:00
100ca0b8a2 ERC20 extension for governance tokens (vote delegation and snapshots) (#2632)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-05-12 10:13:59 -03:00
8669481309 Fix typo in comment (#2660) 2021-05-05 10:41:46 -03:00
1dc4a319ab Use shorter syntax for Escrow addition (#2646) 2021-05-04 20:04:51 +00:00
08ba72afa2 Fix ERC721._beforeTokenTransfer docs (#2653) 2021-05-04 11:10:24 -03:00
0a905d674b Fix typo in tokens.adoc (#2654) 2021-05-03 16:56:50 -03:00
319afebdc0 Fix typo in ERC20._mint docs (#2648) 2021-05-03 16:54:23 -03:00
f1e92dd184 Fix code comments (#2658) 2021-05-03 16:50:07 -03:00
9048e565d7 Update dependency yargs to v17 (#2655)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-03 16:43:57 -03:00
95dec684ad Update lockfile (#2656)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-03 16:42:54 -03:00
0d40f705a7 Add link to full list of upgrades resources 2021-04-29 22:58:59 -03:00
df8a0fe8dc Complete documentation of UUPSUpgradeable 2021-04-29 22:43:39 -03:00
50a9b4d1e7 Fix package-lock.json 2021-04-29 18:14:13 -03:00
2e30b9f382 Merge branch 'release-v4.1' 2021-04-29 18:06:52 -03:00
23869e5b2a 4.1.0 2021-04-29 18:04:21 -03:00
3ba2a1354f Update solidity-docgen 2021-04-27 09:40:20 -03:00
903df56837 Review structure of Proxies API docs (#2645)
(cherry picked from commit 4a53ee5a13)
2021-04-27 09:29:52 -03:00
4a53ee5a13 Review structure of Proxies API docs (#2645) 2021-04-27 09:29:13 -03:00
cfd6e7eab9 Fix documentation typos
(cherry picked from commit a98814b930)
2021-04-26 15:41:36 -03:00
a98814b930 Fix documentation typos 2021-04-26 15:41:17 -03:00
10c763da6f Fix whitespace in doc comments
(cherry picked from commit a020a55f9d)
2021-04-26 15:37:22 -03:00
a020a55f9d Fix whitespace in doc comments 2021-04-26 15:37:04 -03:00
6552adafb2 Merge ERC1967Storage into ERC1967Upgrade (#2644)
(cherry picked from commit 5756e31999)
2021-04-26 15:16:44 -03:00
5756e31999 Merge ERC1967Storage into ERC1967Upgrade (#2644) 2021-04-26 15:16:19 -03:00
8ae9f0914b Update lockfile (#2643)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-26 10:56:01 -03:00
3c4a18f0df Update Stability document with current practices 2021-04-22 11:51:17 -03:00
165e6f1948 EnumerableSet: Remove Boundary Check in _at (#2606)
* remove boundary check

* fix tests for EnumerableSet "index out of bound"

* Changelog

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
2021-04-20 19:51:26 +00:00
750a17653d Optimize removal in EnumerableSet (#2605)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-04-20 18:08:34 +00:00
07b48484ff Fix ERC721 guide for 4.x 2021-04-20 12:37:15 -03:00
a664fb1e45 Improve code comments in ERC1967._upgradeToAndCallSecure
(cherry picked from commit 2e6ef74593)
2021-04-19 19:37:19 -03:00
2e6ef74593 Improve code comments in ERC1967._upgradeToAndCallSecure 2021-04-19 19:36:14 -03:00
440b65bf77 Refactor ERC1155 transfers to use internal functions (#2636)
* Refactor ERC1155 transfers to use internal functions #2622

* apply length check to all internal calls

Co-authored-by: Robert Kaiser <kairo@kairo.at>
2021-04-19 22:13:15 +02:00
df7996b671 add Available since 4.1 comments
(cherry picked from commit 9a698e6b7b)
2021-04-19 20:55:39 +02:00
9a698e6b7b add Available since 4.1 comments 2021-04-19 20:55:16 +02:00
915109b2c4 Move UUPSUpgradeable to proxy/utils
(cherry picked from commit b9125001f0)
2021-04-19 20:46:58 +02:00
2fa86736dd typo: remove duplicate word (#2631)
(cherry picked from commit f17624194b)
2021-04-19 20:46:55 +02:00
b9125001f0 Move UUPSUpgradeable to proxy/utils 2021-04-19 20:44:10 +02:00
f17624194b typo: remove duplicate word (#2631) 2021-04-16 20:07:09 -03:00
7360a2532d Add missing changelog entry
(cherry picked from commit 72eb905c58)
2021-04-16 20:38:45 +02:00
72eb905c58 Add missing changelog entry 2021-04-16 20:37:54 +02:00
ad90dbdaff 4.1.0-rc.0 2021-04-16 18:14:24 +02:00
e0a2b195e4 Add modifier & internal function with standard revert message in AccessControl (#2609)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-04-16 12:15:09 -03:00
1c676ac0ec Implement UUPS proxy (ERC1822) (#2542)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-04-16 11:41:47 -03:00
538b6d21b1 Update ERC721 guide for 4.0 (#2630) 2021-04-15 23:49:53 -03:00
3157aff844 Update docs for setting ERC20 decimals (#2629) 2021-04-14 16:00:22 +00:00
f4898a2e3a Update lockfile (#2627)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-12 19:17:28 -03:00
555be63c90 Add support for EIP2098 "short signatures" in the ECDSA library (#2582)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-04-09 22:58:03 +00:00
057efbfe95 Update lockfile (#2604)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-09 17:33:14 -03:00
585db1f667 Improve Hardhat config (#2612)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-04-09 11:09:16 -03:00
7f6a1666fa Add Multicall module (#2608) 2021-04-07 17:26:40 +00:00
0c621246d3 Add tooling to verify signatures with support for ERC1271 (#2532)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-04-07 13:09:17 +00:00
5bd798c6e1 Add ERC3156 extension of ERC20 (flash minting and lending) (#2543)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-04-06 03:13:10 +00:00
5ecd2b850c Add Contracts Wizard docs page (#2624) 2021-04-05 17:46:57 -03:00
243adff49c fix typo in ERC20's documentation 2021-03-26 14:06:58 +01:00
378531b709 Fix merge issue in CHANGELOG.md 2021-03-23 16:28:01 +01:00
9584c23594 Update package-lock.json 2021-03-23 12:19:17 -03:00
64f20ec624 Fix release.sh for npm 7 2021-03-23 12:15:21 -03:00
783e928ae8 Merge branch 'release-v4.0' 2021-03-23 12:13:57 -03:00
a673994de5 4.0.0 2021-03-23 12:06:54 -03:00
9b0e27c98c add missing rewrite rule in scripts/migrate-imports.js
(cherry picked from commit a3712a3288)
2021-03-22 18:08:36 +01:00
a3712a3288 add missing rewrite rule in scripts/migrate-imports.js 2021-03-22 18:07:02 +01:00
74e03de760 removes unused dependency (#2603) 2021-03-21 19:22:45 +01:00
09e302384a Update lockfile (#2592)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-16 16:07:24 -03:00
3dc374ddcf Make overide of ERC721.isApprovedForAll affect the ERC721 logic (#2597) 2021-03-16 15:32:22 -03:00
90a72f9acd Fix ERC721URIStorage in documentation
(cherry picked from commit 7c1625b0e0)
2021-03-15 16:48:43 -03:00
7c1625b0e0 Fix ERC721URIStorage in documentation 2021-03-15 16:47:39 -03:00
cd443f0d5b Add tests to extend code coverage (#2586) 2021-03-15 13:01:47 -03:00
d5194725b7 Add optimization for EnumerableSet (#2588)
Co-authored-by: Reason <Reason@Lee.com>
2021-03-13 10:19:29 +01:00
82e3ec3afe Fix MerkleProof generation in tests and add some documentation (#2585) 2021-03-12 21:41:54 +00:00
682def9f89 Typo in ERC20 constructor docstring (#2581) 2021-03-11 17:28:26 +01:00
96aece07f3 Fix docs formatting in IERC20Permit (#2579)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-03-10 19:48:22 -03:00
508a879ef0 Remove merkleTree.js in favor of merkletreejs dependency (#2578) 2021-03-10 18:30:16 +01:00
5171e46c47 Add an internal _useNonce(address) function in ERC20Permit (#2565) 2021-03-10 12:24:12 -03:00
1ee939e7c4 4.0.0-rc.0 2021-03-09 15:38:49 +01:00
59f33c1cc1 remove extra changelog entry 2021-03-09 15:32:54 +01:00
fb95a8b34b move changelog entry to the appropriate section 2021-03-09 15:31:34 +01:00
d104ced953 fix changelog format
(cherry picked from commit 2658e01baa)
2021-03-09 15:25:22 +01:00
1fd54698ff Update lockfile (#2573)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
(cherry picked from commit 9612b891c9)
2021-03-09 15:23:05 +01:00
2658e01baa fix changelog format 2021-03-09 15:21:58 +01:00
9612b891c9 Update lockfile (#2573)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-08 22:11:26 -03:00
27fc833550 Make ERC1155.uri public (#2576)
(cherry picked from commit 5dbbda5435)
2021-03-08 17:37:25 -03:00
0b3e0d74b0 Further reorganisation of the repo (#2575)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
(cherry picked from commit f076ff5dbd)
2021-03-08 17:37:03 -03:00
d75b4cf613 Update changelog to list beta bugfix separately
(cherry picked from commit 5aab6ff81b)
2021-03-08 17:37:00 -03:00
5aab6ff81b Update changelog to list beta bugfix separately 2021-03-08 17:33:04 -03:00
f076ff5dbd Further reorganisation of the repo (#2575)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-03-08 17:06:54 -03:00
b8ab763581 Add IERC20Metadata with name, symbol and decimals (#2561)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-03-08 19:53:01 +00:00
78a9821129 Mint ERC777 without reception ack (#2552) 2021-03-08 19:44:31 +00:00
5dbbda5435 Make ERC1155.uri public (#2576) 2021-03-08 15:42:34 -03:00
b1e0aa487d Fix AccessControlEnumerable not tracking renounceRole (#2572)
* Fix AccessControlEnumerable not tracking renounceRole

* Updated changelog

(cherry picked from commit 7adf0d88a0)
2021-03-08 14:32:21 +01:00
6505e28c40 removes invalid character in comments (#2571)
(cherry picked from commit fc004c0ad2)
2021-03-08 14:32:09 +01:00
7adf0d88a0 Fix AccessControlEnumerable not tracking renounceRole (#2572)
* Fix AccessControlEnumerable not tracking renounceRole

* Updated changelog
2021-03-08 13:44:20 +01:00
fc004c0ad2 removes invalid character in comments (#2571) 2021-03-08 13:42:35 +01:00
f07c39be8a Add ERC165 interface detection to AccessControl (#2562)
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
(cherry picked from commit 29ffe6f426)
2021-03-04 18:50:49 -03:00
29ffe6f426 Add ERC165 interface detection to AccessControl (#2562)
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
2021-03-04 18:50:12 -03:00
ec63c604ab Fix prepack script 2021-03-03 17:06:05 +01:00
69ca2ad676 Fix name of ERC721URIStorage contract in changelog
(cherry picked from commit 3d587f3043)
2021-03-03 12:50:05 -03:00
3d587f3043 Fix name of ERC721URIStorage contract in changelog 2021-03-03 12:49:22 -03:00
ae1e384a9a Fix prepack script
(cherry picked from commit 10c52439dd5118d4b671e12d691bfde42c987fb9)
2021-03-03 16:32:22 +01:00
954f6110d6 4.0.0-beta.1 2021-03-03 16:23:38 +01:00
4390b8df12 Add ERC721URIStorage extension (#2555)
(cherry picked from commit 1705067e65)
2021-03-03 16:15:51 +01:00
cb88e15b33 Enable optimizations when publishing package (#2557)
(cherry picked from commit 618a735816)
2021-03-03 16:15:26 +01:00
1705067e65 Add ERC721URIStorage extension (#2555) 2021-03-03 12:13:09 -03:00
618a735816 Enable optimizations when publishing package (#2557) 2021-03-03 12:01:54 -03:00
136de91049 Rename variable master to implementation #2 (#2553)
(cherry picked from commit 103ff8e23d)
2021-03-03 12:33:03 +01:00
103ff8e23d Rename variable master to implementation #2 (#2553) 2021-03-03 12:31:33 +01:00
e2bf45f262 Rename variable master to implementation
(cherry picked from commit cdb929aada)
2021-03-02 21:30:26 -03:00
cdb929aada Rename variable master to implementation 2021-03-02 21:25:56 -03:00
93d990c653 Optimize constructor of ERC777 (#2551)
(cherry picked from commit 62af16b9f2)
2021-03-02 21:31:07 +01:00
62af16b9f2 Optimize constructor of ERC777 (#2551) 2021-03-02 21:29:05 +01:00
3dfd02b4b4 Fix link to TimelockController
(cherry picked from commit ba1d773176)
2021-03-02 21:14:33 +01:00
7a7bd8f6d7 Fix typo Controler -> Controller
(cherry picked from commit 583146f9d6)
2021-03-02 21:14:26 +01:00
16312fcfb9 Rename UpgradeableProxy to ERC1967Proxy (#2547)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
(cherry picked from commit c789941d76)
2021-03-02 21:14:08 +01:00
a81a88cca0 Fix mentions of buidler (#2548)
(cherry picked from commit 232c355b3a)
2021-03-02 21:14:00 +01:00
5acedf5027 Change title of meta transactions page in docs sidebar
(cherry picked from commit 773c7265e8)
2021-03-02 21:13:51 +01:00
566c601d41 Update lockfile (#2546)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
(cherry picked from commit 742c436d28)
2021-03-02 21:13:39 +01:00
ba1d773176 Fix link to TimelockController 2021-03-02 15:53:03 -03:00
583146f9d6 Fix typo Controler -> Controller 2021-03-02 15:32:10 -03:00
c789941d76 Rename UpgradeableProxy to ERC1967Proxy (#2547)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
2021-03-02 11:20:59 -03:00
232c355b3a Fix mentions of buidler (#2548) 2021-03-02 09:24:37 +01:00
773c7265e8 Change title of meta transactions page in docs sidebar 2021-03-01 14:38:12 -03:00
742c436d28 Update lockfile (#2546)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-01 14:02:18 -03:00
15214a53ce Optimize implementation of ERC20Capped (#2524)
(cherry picked from commit 36b855972b)
2021-03-01 12:09:21 -03:00
36b855972b Optimize implementation of ERC20Capped (#2524) 2021-02-24 22:07:03 +00:00
d5f4862405 Fix package.json files field
(cherry picked from commit 735c03fcf3)
2021-02-24 00:36:08 -03:00
735c03fcf3 Fix package.json files field 2021-02-24 00:35:47 -03:00
4a1985f870 Fix migrate-imports.js test for upgradeable paths
(cherry picked from commit 4519c237c5)
2021-02-24 00:20:07 -03:00
4519c237c5 Fix migrate-imports.js test for upgradeable paths 2021-02-23 23:50:40 -03:00
ac8279a0a5 Update Antora component version 2021-02-23 23:31:48 -03:00
7cab19a2e4 Check upgradeable paths in migrate-imports test
(cherry picked from commit 4ee9fd77fd)
2021-02-23 23:31:34 -03:00
4ee9fd77fd Check upgradeable paths in migrate-imports test 2021-02-23 23:29:43 -03:00
323 changed files with 31151 additions and 10545 deletions

View File

@ -10,5 +10,5 @@ about: Suggest an idea for OpenZeppelin Contracts
**📝 Details**
<!-- Please describe your feature request in detail. -->
<!-- Make sure that you have reviewed the OpenZeppelin Contributor Guidelines. -->
<!-- Make sure that you have reviewed the OpenZeppelin Contracts Contributor Guidelines. -->
<!-- https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CONTRIBUTING.md -->

View File

@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 10.x
node-version: 12.x
- uses: actions/cache@v2
id: cache
with:
@ -28,7 +28,8 @@ jobs:
- run: npm run test
env:
FORCE_COLOR: 1
ENABLE_GAS_REPORT: 1
ENABLE_GAS_REPORT: true
- run: npm run test:inheritance
- name: Print gas report
run: cat gas-report.txt
@ -40,7 +41,7 @@ jobs:
fetch-depth: 2
- uses: actions/setup-node@v2
with:
node-version: 10.x
node-version: 12.x
- uses: actions/cache@v2
id: cache
with:
@ -52,4 +53,4 @@ jobs:
- run: npm run coverage
env:
NODE_OPTIONS: --max_old_space_size=4096
- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v2

23
.github/workflows/upgradeable.yml vendored Normal file
View File

@ -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 }}" } }'

2
.gitignore vendored
View File

@ -54,6 +54,6 @@ allFiredEvents
.coverage_cache
.coverage_contracts
# buidler
# hardhat
cache
artifacts

View File

@ -1,3 +1,4 @@
module.exports = {
require: 'hardhat/register',
timeout: 4000,
};

11
.prettierrc Normal file
View File

@ -0,0 +1,11 @@
{
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 120,
"explicitTypes": "always"
}
}
]
}

View File

@ -1,12 +1,14 @@
{
"extends": "solhint:recommended",
"rules": {
"func-order": "off",
"mark-callable-contracts": "off",
"no-empty-blocks": "off",
"compiler-version": "off",
"no-unused-vars": "error",
"const-name-snakecase": "error",
"contract-name-camelcase": "error",
"event-name-camelcase": "error",
"func-name-mixedcase": "error",
"func-param-name-mixedcase": "error",
"modifier-name-mixedcase": "error",
"private-vars-leading-underscore": "error",
"reason-string": "off",
"func-visibility": ["error", { "ignoreConstructors": true }]
"var-name-mixedcase": "error",
"imports-on-top": "error"
}
}

View File

@ -1,19 +1,140 @@
# Changelog
## 4.0.0
## 4.4.2 (2022-01-11)
### Bugfixes
* `GovernorCompatibilityBravo`: Fix error in the encoding of calldata for proposals submitted through the compatibility interface with explicit signatures. ([#3100](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/#3100))
## 4.4.1 (2021-12-14)
* `Initializable`: change the existing `initializer` modifier and add a new `onlyInitializing` modifier to prevent reentrancy risk. ([#3006](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3006))
### Breaking change
It is no longer possible to call an `initializer`-protected function from within another `initializer` function outside the context of a constructor. Projects using OpenZeppelin upgradeable proxies should continue to work as is, since in the common case the initializer is invoked in the constructor directly. If this is not the case for you, the suggested change is to use the new `onlyInitializing` modifier in the following way:
```diff
contract A {
- function initialize() public initializer { ... }
+ function initialize() internal onlyInitializing { ... }
}
contract B is A {
function initialize() public initializer {
A.initialize();
}
}
```
## 4.4.0 (2021-11-25)
* `Ownable`: add an internal `_transferOwnership(address)`. ([#2568](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2568))
* `AccessControl`: add internal `_grantRole(bytes32,address)` and `_revokeRole(bytes32,address)`. ([#2568](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2568))
* `AccessControl`: mark `_setupRole(bytes32,address)` as deprecated in favor of `_grantRole(bytes32,address)`. ([#2568](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2568))
* `AccessControlEnumerable`: hook into `_grantRole(bytes32,address)` and `_revokeRole(bytes32,address)`. ([#2946](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2946))
* `EIP712`: cache `address(this)` to immutable storage to avoid potential issues if a vanilla contract is used in a delegatecall context. ([#2852](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2852))
* Add internal `_setApprovalForAll` to `ERC721` and `ERC1155`. ([#2834](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2834))
* `Governor`: shift vote start and end by one block to better match Compound's GovernorBravo and prevent voting at the Governor level if the voting snapshot is not ready. ([#2892](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2892))
* `GovernorCompatibilityBravo`: consider quorum an inclusive rather than exclusive minimum to match Compound's GovernorBravo. ([#2974](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2974))
* `GovernorSettings`: a new governor module that manages voting settings updatable through governance actions. ([#2904](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2904))
* `PaymentSplitter`: now supports ERC20 assets in addition to Ether. ([#2858](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2858))
* `ECDSA`: add a variant of `toEthSignedMessageHash` for arbitrary length message hashing. ([#2865](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2865))
* `MerkleProof`: add a `processProof` function that returns the rebuilt root hash given a leaf and a proof. ([#2841](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2841))
* `VestingWallet`: new contract that handles the vesting of Ether and ERC20 tokens following a customizable vesting schedule. ([#2748](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2748))
* `Governor`: enable receiving Ether when a Timelock contract is not used. ([#2748](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2849))
* `GovernorTimelockCompound`: fix ability to use Ether stored in the Timelock contract. ([#2748](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2849))
## 4.3.3
* `ERC1155Supply`: Handle `totalSupply` changes by hooking into `_beforeTokenTransfer` to ensure consistency of balances and supply during `IERC1155Receiver.onERC1155Received` calls.
## 4.3.2 (2021-09-14)
* `UUPSUpgradeable`: Add modifiers to prevent `upgradeTo` and `upgradeToAndCall` being executed on any contract that is not the active ERC1967 proxy. This prevents these functions being called on implementation contracts or minimal ERC1167 clones, in particular.
## 4.3.1 (2021-08-26)
* `TimelockController`: Add additional isOperationReady check.
## 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))
* `Governor`: added a modular system of `Governor` contracts based on `GovernorAlpha` and `GovernorBravo`. ([#2672](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2672))
* 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))
## 4.2.0 (2021-06-30)
* `ERC20Votes`: add a new extension of the `ERC20` token with support for voting snapshots and delegation. ([#2632](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2632))
* `ERC20VotesComp`: Variant of `ERC20Votes` that is compatible with Compound's `Comp` token interface but restricts supply to `uint96`. ([#2706](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2706))
* `ERC20Wrapper`: add a new extension of the `ERC20` token which wraps an underlying token. Deposit and withdraw guarantee that the total supply is backed by a corresponding amount of underlying token. ([#2633](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2633))
* Enumerables: Improve gas cost of removal in `EnumerableSet` and `EnumerableMap`.
* Enumerables: Improve gas cost of lookup in `EnumerableSet` and `EnumerableMap`.
* `Counter`: add a reset method. ([#2678](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2678))
* Tokens: Wrap definitely safe subtractions in `unchecked` blocks.
* `Math`: Add a `ceilDiv` method for performing ceiling division.
* `ERC1155Supply`: add a new `ERC1155` extension that keeps track of the totalSupply of each tokenId. ([#2593](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2593))
* `BitMaps`: add a new `BitMaps` library that provides a storage efficient datastructure for `uint256` to `bool` mapping with contiguous keys. ([#2710](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2710))
### Breaking Changes
* `ERC20FlashMint` is no longer a Draft ERC. ([#2673](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2673)))
**How to update:** Change your import paths by removing the `draft-` prefix from `@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20FlashMint.sol`.
> See [Releases and Stability: Drafts](https://docs.openzeppelin.com/contracts/4.x/releases-stability#drafts).
## 4.1.0 (2021-04-29)
* `IERC20Metadata`: add a new extended interface that includes the optional `name()`, `symbol()` and `decimals()` functions. ([#2561](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2561))
* `ERC777`: make reception acquirement optional in `_mint`. ([#2552](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2552))
* `ERC20Permit`: add a `_useNonce` to enable further usage of ERC712 signatures. ([#2565](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2565))
* `ERC20FlashMint`: add an implementation of the ERC3156 extension for flash-minting ERC20 tokens. ([#2543](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2543))
* `SignatureChecker`: add a signature verification library that supports both EOA and ERC1271 compliant contracts as signers. ([#2532](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2532))
* `Multicall`: add abstract contract with `multicall(bytes[] calldata data)` function to bundle multiple calls together ([#2608](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2608))
* `ECDSA`: add support for ERC2098 short-signatures. ([#2582](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2582))
* `AccessControl`: add a `onlyRole` modifier to restrict specific function to callers bearing a specific role. ([#2609](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2609))
* `StorageSlot`: add a library for reading and writing primitive types to specific storage slots. ([#2542](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2542))
* UUPS Proxies: add `UUPSUpgradeable` to implement the UUPS proxy pattern together with `EIP1967Proxy`. ([#2542](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2542))
### Breaking changes
This release includes two small breaking changes in `TimelockController`.
1. The `onlyRole` modifier in this contract was designed to let anyone through if the role was granted to `address(0)`,
allowing the possibility to to make a role "open", which can be used for `EXECUTOR_ROLE`. This modifier is now
replaced by `AccessControl.onlyRole`, which does not have this ability. The previous behavior was moved to the
modifier `TimelockController.onlyRoleOrOpenRole`.
2. It was possible to make `PROPOSER_ROLE` an open role (as described in the previous item) if it was granted to
`address(0)`. This would affect the `schedule`, `scheduleBatch`, and `cancel` operations in `TimelockController`.
This ability was removed as it does not make sense to open up the `PROPOSER_ROLE` in the same way that it does for
`EXECUTOR_ROLE`.
## 4.0.0 (2021-03-23)
* Now targeting the 0.8.x line of Solidity compilers. For 0.6.x (resp 0.7.x) support, use version 3.4.0 (resp 3.4.0-solc-0.7) of OpenZeppelin.
* `Context`: making `_msgData` return `bytes calldata` instead of `bytes memory` ([#2492](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2492))
* `ERC20`: Removed the `_setDecimals` function and the storage slot associated to decimals. ([#2502](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2502))
* `ERC20`: removed the `_setDecimals` function and the storage slot associated to decimals. ([#2502](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2502))
* `Strings`: addition of a `toHexString` function. ([#2504](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2504))
* `EnumerableMap`: change implementation to optimize for `key → value` lookups instead of enumeration. ([#2518](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2518))
* `GSN`: Deprecate GSNv1 support in favor of upcomming support for GSNv2. ([#2521](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2521))
* `ERC165`: Remove uses of storage in the base ERC165 implementation. ERC165 based contracts now use storage-less virtual functions. Old behaviour remains available in the `ERC165Storage` extension. ([#2505](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2505))
* `Initializable`: Make initializer check stricter during construction. ([#2531](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2531))
* `GSN`: deprecate GSNv1 support in favor of upcoming support for GSNv2. ([#2521](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2521))
* `ERC165`: remove uses of storage in the base ERC165 implementation. ERC165 based contracts now use storage-less virtual functions. Old behavior remains available in the `ERC165Storage` extension. ([#2505](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2505))
* `Initializable`: make initializer check stricter during construction. ([#2531](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2531))
* `ERC721`: remove enumerability of tokens from the base implementation. This feature is now provided separately through the `ERC721Enumerable` extension. ([#2511](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2511))
* `AccessControl`: removed enumerability by default for a more lightweight contract. It is now opt-in through `AccessControlEnumerable`. ([#2512](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2512))
* Meta Transactions: add `ERC2771Context` and a `MinimalForwarder` for meta-transactions. ([#2508](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2508))
* Overall reorganisation of the contract folder to improve clarity and discoverability. ([#2503](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2503))
* Overall reorganization of the contract folder to improve clarity and discoverability. ([#2503](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2503))
* `ERC20Capped`: optimize gas usage by enforcing the check directly in `_mint`. ([#2524](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2524))
* Rename `UpgradeableProxy` to `ERC1967Proxy`. ([#2547](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2547))
* `ERC777`: optimize the gas costs of the constructor. ([#2551](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2551))
* `ERC721URIStorage`: add a new extension that implements the `_setTokenURI` behavior as it was available in 3.4.0. ([#2555](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2555))
* `AccessControl`: added ERC165 interface detection. ([#2562](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2562))
* `ERC1155`: make `uri` public so overloading function can call it using super. ([#2576](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2576))
### Bug fixes for beta releases
* `AccessControlEnumerable`: Fixed `renounceRole` not updating enumerable set of addresses for a role. ([#2572](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2572))
### How to upgrade from 3.x
@ -25,6 +146,18 @@ npx openzeppelin-contracts-migrate-imports
Make sure you're using git or another version control system to be able to recover from any potential error in our script.
### How to upgrade from 4.0-beta.x
Some further changes have been done between the different beta iterations. Transitions made during this period are configured in the `migrate-imports` script. Consequently, you can upgrade from any previous 4.0-beta.x version using the same script as described in the *How to upgrade from 3.x* section.
## 3.4.2
* `TimelockController`: Add additional isOperationReady check.
## 3.4.1 (2021-03-03)
* `ERC721`: made `_approve` an internal function (was private).
## 3.4.0 (2021-02-02)
* `BeaconProxy`: added new kind of proxy that allows simultaneous atomic upgrades. ([#2411](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2411))

View File

@ -49,9 +49,9 @@ npm run lint
*IMPORTANT* Read the PR template very carefully and make sure to follow all the instructions. These instructions
refer to some very important conditions that your PR must meet in order to be accepted, such as making sure that all tests pass, JS linting tests pass, Solidity linting tests pass, etc.
6) Maintainers will review your code and possibly ask for changes before your code is pulled in to the main repository. We'll check that all tests pass, review the coding style, and check for general code correctness. If everything is OK, we'll merge your pull request and your code will be part of OpenZeppelin.
6) Maintainers will review your code and possibly ask for changes before your code is pulled in to the main repository. We'll check that all tests pass, review the coding style, and check for general code correctness. If everything is OK, we'll merge your pull request and your code will be part of OpenZeppelin Contracts.
*IMPORTANT* Please pay attention to the maintainer's feedback, since its a necessary step to keep up with the standards OpenZeppelin attains to.
*IMPORTANT* Please pay attention to the maintainer's feedback, since its a necessary step to keep up with the standards OpenZeppelin Contracts attains to.
## All set!

View File

@ -1,7 +1,7 @@
Design Guidelines
=======
These are some global design goals in OpenZeppelin.
These are some global design goals in OpenZeppelin Contracts.
#### D0 - Security in Depth
We strive to provide secure, tested, audited code. To achieve this, we need to match intention with function. Thus, documentation, code clarity, community review and security discussions are fundamental.

View File

@ -9,8 +9,8 @@
* Implementations of standards like [ERC20](https://docs.openzeppelin.com/contracts/erc20) and [ERC721](https://docs.openzeppelin.com/contracts/erc721).
* Flexible [role-based permissioning](https://docs.openzeppelin.com/contracts/access-control) scheme.
* Reusable [Solidity components](https://docs.openzeppelin.com/contracts/utilities) to build custom contracts and complex decentralized systems.
* First-class integration with the [Gas Station Network](https://docs.openzeppelin.com/contracts/gsn) for systems with no gas fees!
* [Audited](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/audit) by leading security firms (_last full audit on v2.0.0_).
:mage: **Not sure how to get started?** Check out [Contracts Wizard](https://wizard.openzeppelin.com/) — an interactive smart contract generator.
## Overview
@ -60,18 +60,20 @@ Finally, you may want to take a look at the [guides on our blog](https://blog.op
## Security
This project is maintained by [OpenZeppelin](https://openzeppelin.com), and developed following our high standards for code quality and security. OpenZeppelin is meant to provide tested and community-audited code, but please use common sense when doing anything that deals with real money! We take no responsibility for your implementation decisions and any security problems you might experience.
This project is maintained by [OpenZeppelin](https://openzeppelin.com), and developed following our high standards for code quality and security. OpenZeppelin Contracts is meant to provide tested and community-audited code, but please use common sense when doing anything that deals with real money! We take no responsibility for your implementation decisions and any security problems you might experience.
The core development principles and strategies that OpenZeppelin is based on include: security in depth, simple and modular code, clarity-driven naming conventions, comprehensive unit testing, pre-and-post-condition sanity checks, code consistency, and regular audits.
The core development principles and strategies that OpenZeppelin Contracts is based on include: security in depth, simple and modular code, clarity-driven naming conventions, comprehensive unit testing, pre-and-post-condition sanity checks, code consistency, and regular audits.
The latest audit was done on October 2018 on version 2.0.0.
Please report any security issues you find to security@openzeppelin.org.
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.
Critical bug fixes will be backported to past major releases.
## Contribute
OpenZeppelin exists thanks to its contributors. There are many ways you can participate and help build high quality software. Check out the [contribution guide](CONTRIBUTING.md)!
OpenZeppelin Contracts exists thanks to its contributors. There are many ways you can participate and help build high quality software. Check out the [contribution guide](CONTRIBUTING.md)!
## License
OpenZeppelin is released under the [MIT License](LICENSE).
OpenZeppelin Contracts is released under the [MIT License](LICENSE).

View File

@ -10,10 +10,10 @@ Publish a release candidate with `npm run release rc`.
Publish the final release with `npm run release final`.
Follow the general [OpenZeppelin release checklist].
Follow the general [OpenZeppelin Contracts release checklist].
[details about release schedule]: https://docs.openzeppelin.com/contracts/releases-stability
[OpenZeppelin release checklist]: https://github.com/OpenZeppelin/code-style/blob/master/RELEASE_CHECKLIST.md
[OpenZeppelin Contracts release checklist]: https://github.com/OpenZeppelin/code-style/blob/master/RELEASE_CHECKLIST.md
## Merging the release branch

18
SECURITY.md Normal file
View File

@ -0,0 +1,18 @@
# Security Policy
## Supported Versions
The recommendation is to use the latest version available.
| Version | Supported |
| ------- | ------------------------------------ |
| 4.x | :white_check_mark::white_check_mark: |
| 3.4 | :white_check_mark: |
| 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.

View File

@ -1,5 +1,7 @@
# OpenZeppelin Audit
NOTE ON 2021-07-19: This report makes reference to Zeppelin, OpenZeppelin, OpenZeppelin [C]ontracts, the OpenZeppelin team, and OpenZeppelin library. Many of these things have since been renamed and know that this audit applies to what is currently called the OpenZeppelin Contracts which are maintained by the OpenZeppelin Conracts Community.
March, 2017
Authored by Dennis Peterson and Peter Vessenes

View File

@ -1,8 +1,12 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
@ -42,57 +46,74 @@ import "../utils/Context.sol";
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context {
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping (address => bool) members;
mapping(address => bool) members;
bytes32 adminRole;
}
mapping (bytes32 => RoleData) private _roles;
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
* The format of the revert reason is given by the following regular expression:
*
* _Available since v3.1._
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {_setupRole}.
* @dev See {IERC165-supportsInterface}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view returns (bool) {
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view returns (bytes32) {
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
@ -106,9 +127,7 @@ abstract contract AccessControl is Context {
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) public virtual {
require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to grant");
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
@ -121,9 +140,7 @@ abstract contract AccessControl is Context {
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) public virtual {
require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to revoke");
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
@ -134,14 +151,14 @@ abstract contract AccessControl is Context {
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) public virtual {
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
@ -162,6 +179,8 @@ abstract contract AccessControl is Context {
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
@ -173,18 +192,29 @@ abstract contract AccessControl is Context {
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) private {
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) private {
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());

View File

@ -1,17 +1,26 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/AccessControlEnumerable.sol)
pragma solidity ^0.8.0;
import "./IAccessControlEnumerable.sol";
import "./AccessControl.sol";
import "../utils/structs/EnumerableSet.sol";
/**
* @dev Extension of {AccessControl} that allows enumerating the members of each role.
*/
abstract contract AccessControlEnumerable is AccessControl {
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
using EnumerableSet for EnumerableSet.AddressSet;
mapping (bytes32 => EnumerableSet.AddressSet) private _roleMembers;
mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
@ -25,7 +34,7 @@ abstract contract AccessControlEnumerable is AccessControl {
* 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 returns (address) {
function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {
return _roleMembers[role].at(index);
}
@ -33,31 +42,23 @@ abstract contract AccessControlEnumerable is AccessControl {
* @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 returns (uint256) {
function getRoleMemberCount(bytes32 role) public view override returns (uint256) {
return _roleMembers[role].length();
}
/**
* @dev Overload {grantRole} to track enumerable memberships
* @dev Overload {_grantRole} to track enumerable memberships
*/
function grantRole(bytes32 role, address account) public virtual override {
super.grantRole(role, account);
function _grantRole(bytes32 role, address account) internal virtual override {
super._grantRole(role, account);
_roleMembers[role].add(account);
}
/**
* @dev Overload {revokeRole} to track enumerable memberships
* @dev Overload {_revokeRole} to track enumerable memberships
*/
function revokeRole(bytes32 role, address account) public virtual override {
super.revokeRole(role, account);
function _revokeRole(bytes32 role, address account) internal virtual override {
super._revokeRole(role, account);
_roleMembers[role].remove(account);
}
/**
* @dev Overload {_setupRole} to track enumerable memberships
*/
function _setupRole(bytes32 role, address account) internal virtual override {
super._setupRole(role, account);
_roleMembers[role].add(account);
}
}

View File

@ -0,0 +1,88 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}

View File

@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
/**
* @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
*/
interface IAccessControlEnumerable is IAccessControl {
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* 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) external view returns (address);
/**
* @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) external view returns (uint256);
}

View File

@ -1,8 +1,10 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
@ -23,10 +25,8 @@ abstract contract Ownable is Context {
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
constructor() {
_transferOwnership(_msgSender());
}
/**
@ -52,8 +52,7 @@ abstract contract Ownable is Context {
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
_transferOwnership(address(0));
}
/**
@ -62,7 +61,16 @@ abstract contract Ownable is Context {
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}

View File

@ -1,4 +1,4 @@
= Access
= Access Control
[.readme-notice]
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/access
@ -12,6 +12,10 @@ This directory provides ways to restrict who can access the functions of a contr
{{Ownable}}
{{IAccessControl}}
{{AccessControl}}
{{IAccessControlEnumerable}}
{{AccessControlEnumerable}}

View File

@ -1,10 +1,11 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (finance/PaymentSplitter.sol)
pragma solidity ^0.8.0;
import "./Address.sol";
import "./Context.sol";
import "./math/SafeMath.sol";
import "../token/ERC20/utils/SafeERC20.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";
/**
* @title PaymentSplitter
@ -18,10 +19,15 @@ import "./math/SafeMath.sol";
* `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
* accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
* function.
*
* NOTE: This contract assumes that ERC20 tokens will behave similarly to native tokens (Ether). Rebasing tokens, and
* tokens that apply fees during transfers, are likely to not be supported as expected. If in doubt, we encourage you
* to run tests before sending real value to this contract.
*/
contract PaymentSplitter is Context {
event PayeeAdded(address account, uint256 shares);
event PaymentReleased(address to, uint256 amount);
event ERC20PaymentReleased(IERC20 indexed token, address to, uint256 amount);
event PaymentReceived(address from, uint256 amount);
uint256 private _totalShares;
@ -31,6 +37,9 @@ contract PaymentSplitter is Context {
mapping(address => uint256) private _released;
address[] private _payees;
mapping(IERC20 => uint256) private _erc20TotalReleased;
mapping(IERC20 => mapping(address => uint256)) private _erc20Released;
/**
* @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
* the matching position in the `shares` array.
@ -38,8 +47,7 @@ contract PaymentSplitter is Context {
* All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
* duplicates in `payees`.
*/
constructor (address[] memory payees, uint256[] memory shares_) payable {
// solhint-disable-next-line max-line-length
constructor(address[] memory payees, uint256[] memory shares_) payable {
require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch");
require(payees.length > 0, "PaymentSplitter: no payees");
@ -57,7 +65,7 @@ contract PaymentSplitter is Context {
* https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
* functions].
*/
receive () external payable virtual {
receive() external payable virtual {
emit PaymentReceived(_msgSender(), msg.value);
}
@ -75,6 +83,14 @@ contract PaymentSplitter is Context {
return _totalReleased;
}
/**
* @dev Getter for the total amount of `token` already released. `token` should be the address of an IERC20
* contract.
*/
function totalReleased(IERC20 token) public view returns (uint256) {
return _erc20TotalReleased[token];
}
/**
* @dev Getter for the amount of shares held by an account.
*/
@ -89,6 +105,14 @@ contract PaymentSplitter is Context {
return _released[account];
}
/**
* @dev Getter for the amount of `token` tokens already released to a payee. `token` should be the address of an
* IERC20 contract.
*/
function released(IERC20 token, address account) public view returns (uint256) {
return _erc20Released[token][account];
}
/**
* @dev Getter for the address of the payee number `index`.
*/
@ -103,18 +127,50 @@ contract PaymentSplitter is Context {
function release(address payable account) public virtual {
require(_shares[account] > 0, "PaymentSplitter: account has no shares");
uint256 totalReceived = address(this).balance + _totalReleased;
uint256 payment = totalReceived * _shares[account] / _totalShares - _released[account];
uint256 totalReceived = address(this).balance + totalReleased();
uint256 payment = _pendingPayment(account, totalReceived, released(account));
require(payment != 0, "PaymentSplitter: account is not due payment");
_released[account] = _released[account] + payment;
_totalReleased = _totalReleased + payment;
_released[account] += payment;
_totalReleased += payment;
Address.sendValue(account, payment);
emit PaymentReleased(account, payment);
}
/**
* @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their
* percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20
* contract.
*/
function release(IERC20 token, address account) public virtual {
require(_shares[account] > 0, "PaymentSplitter: account has no shares");
uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token);
uint256 payment = _pendingPayment(account, totalReceived, released(token, account));
require(payment != 0, "PaymentSplitter: account is not due payment");
_erc20Released[token][account] += payment;
_erc20TotalReleased[token] += payment;
SafeERC20.safeTransfer(token, account, payment);
emit ERC20PaymentReleased(token, account, payment);
}
/**
* @dev internal logic for computing the pending payment of an `account` given the token historical balances and
* already released amounts.
*/
function _pendingPayment(
address account,
uint256 totalReceived,
uint256 alreadyReleased
) private view returns (uint256) {
return (totalReceived * _shares[account]) / _totalShares - alreadyReleased;
}
/**
* @dev Add a new payee to the contract.
* @param account The address of the payee to add.

View File

@ -0,0 +1,20 @@
= Finance
[.readme-notice]
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/finance
This directory includes primitives for financial systems:
- {PaymentSplitter} allows to split Ether and ERC20 payments among a group of accounts. The sender does not need to be
aware that the assets will be split in this way, since it is handled transparently by the contract. The split can be
in equal parts or in any other arbitrary proportion.
- {VestingWallet} handles the vesting of Ether and ERC20 tokens for a given beneficiary. Custody of multiple tokens can
be given to this contract, which will release the token to the beneficiary following a given, customizable, vesting
schedule.
== Contracts
{{PaymentSplitter}}
{{VestingWallet}}

View File

@ -0,0 +1,135 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (finance/VestingWallet.sol)
pragma solidity ^0.8.0;
import "../token/ERC20/utils/SafeERC20.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";
import "../utils/math/Math.sol";
/**
* @title VestingWallet
* @dev This contract handles the vesting of Eth and ERC20 tokens for a given beneficiary. Custody of multiple tokens
* can be given to this contract, which will release the token to the beneficiary following a given vesting schedule.
* The vesting schedule is customizable through the {vestedAmount} function.
*
* Any token transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
* Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly)
* be immediately releasable.
*/
contract VestingWallet is Context {
event EtherReleased(uint256 amount);
event ERC20Released(address indexed token, uint256 amount);
uint256 private _released;
mapping(address => uint256) private _erc20Released;
address private immutable _beneficiary;
uint64 private immutable _start;
uint64 private immutable _duration;
/**
* @dev Set the beneficiary, start timestamp and vesting duration of the vesting wallet.
*/
constructor(
address beneficiaryAddress,
uint64 startTimestamp,
uint64 durationSeconds
) {
require(beneficiaryAddress != address(0), "VestingWallet: beneficiary is zero address");
_beneficiary = beneficiaryAddress;
_start = startTimestamp;
_duration = durationSeconds;
}
/**
* @dev The contract should be able to receive Eth.
*/
receive() external payable virtual {}
/**
* @dev Getter for the beneficiary address.
*/
function beneficiary() public view virtual returns (address) {
return _beneficiary;
}
/**
* @dev Getter for the start timestamp.
*/
function start() public view virtual returns (uint256) {
return _start;
}
/**
* @dev Getter for the vesting duration.
*/
function duration() public view virtual returns (uint256) {
return _duration;
}
/**
* @dev Amount of eth already released
*/
function released() public view virtual returns (uint256) {
return _released;
}
/**
* @dev Amount of token already released
*/
function released(address token) public view virtual returns (uint256) {
return _erc20Released[token];
}
/**
* @dev Release the native token (ether) that have already vested.
*
* Emits a {TokensReleased} event.
*/
function release() public virtual {
uint256 releasable = vestedAmount(uint64(block.timestamp)) - released();
_released += releasable;
emit EtherReleased(releasable);
Address.sendValue(payable(beneficiary()), releasable);
}
/**
* @dev Release the tokens that have already vested.
*
* Emits a {TokensReleased} event.
*/
function release(address token) public virtual {
uint256 releasable = vestedAmount(token, uint64(block.timestamp)) - released(token);
_erc20Released[token] += releasable;
emit ERC20Released(token, releasable);
SafeERC20.safeTransfer(IERC20(token), beneficiary(), releasable);
}
/**
* @dev Calculates the amount of ether that has already vested. Default implementation is a linear vesting curve.
*/
function vestedAmount(uint64 timestamp) public view virtual returns (uint256) {
return _vestingSchedule(address(this).balance + released(), timestamp);
}
/**
* @dev Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve.
*/
function vestedAmount(address token, uint64 timestamp) public view virtual returns (uint256) {
return _vestingSchedule(IERC20(token).balanceOf(address(this)) + released(token), timestamp);
}
/**
* @dev Virtual implementation of the vesting formula. This returns the amout vested, as a function of time, for
* an asset given its total historical allocation.
*/
function _vestingSchedule(uint256 totalAllocation, uint64 timestamp) internal view virtual returns (uint256) {
if (timestamp < start()) {
return 0;
} else if (timestamp > start() + duration()) {
return totalAllocation;
} else {
return (totalAllocation * (timestamp - start())) / duration();
}
}
}

View File

@ -0,0 +1,357 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/Governor.sol)
pragma solidity ^0.8.0;
import "../utils/cryptography/ECDSA.sol";
import "../utils/cryptography/draft-EIP712.sol";
import "../utils/introspection/ERC165.sol";
import "../utils/math/SafeCast.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";
import "../utils/Timers.sol";
import "./IGovernor.sol";
/**
* @dev Core of the governance system, designed to be extended though 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}
* - Additionanly, the {votingPeriod} must also be implemented
*
* _Available since v4.3._
*/
abstract contract Governor is Context, ERC165, EIP712, IGovernor {
using SafeCast for uint256;
using Timers for Timers.BlockNumber;
bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)");
struct ProposalCore {
Timers.BlockNumber voteStart;
Timers.BlockNumber voteEnd;
bool executed;
bool canceled;
}
string private _name;
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.
*/
modifier onlyGovernance() {
require(_msgSender() == _executor(), "Governor: onlyGovernance");
_;
}
/**
* @dev Sets the value for {name} and {version}
*/
constructor(string memory name_) EIP712(name_, version()) {
_name = name_;
}
/**
* @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)
*/
receive() external payable virtual {
require(_executor() == address(this));
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IGovernor).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IGovernor-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IGovernor-version}.
*/
function version() public view virtual override returns (string memory) {
return "1";
}
/**
* @dev See {IGovernor-hashProposal}.
*
* The proposal id is produced by hashing the RLC encoded `targets` array, the `values` array, the `calldatas` array
* and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id
* can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in
* advance, before the proposal is submitted.
*
* Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the
* same proposal (with same operation and same description) will have the same id if submitted on multiple governors
* accross multiple networks. This also means that in order to execute the same operation twice (on the same
* governor) the proposer will have to change the description in order to avoid proposal id conflicts.
*/
function hashProposal(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public pure virtual override returns (uint256) {
return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));
}
/**
* @dev See {IGovernor-state}.
*/
function state(uint256 proposalId) public view virtual override returns (ProposalState) {
ProposalCore memory proposal = _proposals[proposalId];
if (proposal.executed) {
return ProposalState.Executed;
} else if (proposal.canceled) {
return ProposalState.Canceled;
} else if (proposal.voteStart.getDeadline() >= block.number) {
return ProposalState.Pending;
} else if (proposal.voteEnd.getDeadline() >= block.number) {
return ProposalState.Active;
} else if (proposal.voteEnd.isExpired()) {
return
_quorumReached(proposalId) && _voteSucceeded(proposalId)
? ProposalState.Succeeded
: ProposalState.Defeated;
} else {
revert("Governor: unknown proposal id");
}
}
/**
* @dev See {IGovernor-proposalSnapshot}.
*/
function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].voteStart.getDeadline();
}
/**
* @dev See {IGovernor-proposalDeadline}.
*/
function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
return _proposals[proposalId].voteEnd.getDeadline();
}
/**
* @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_.
*/
function proposalThreshold() public view virtual returns (uint256) {
return 0;
}
/**
* @dev Amount of votes already cast passes the threshold limit.
*/
function _quorumReached(uint256 proposalId) internal view virtual returns (bool);
/**
* @dev Is the proposal successful or not.
*/
function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);
/**
* @dev Register a vote with a given support and voting weight.
*
* Note: Support is generic and can represent various things depending on the voting system used.
*/
function _countVote(
uint256 proposalId,
address account,
uint8 support,
uint256 weight
) internal virtual;
/**
* @dev See {IGovernor-propose}.
*/
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public virtual override returns (uint256) {
require(
getVotes(msg.sender, block.number - 1) >= proposalThreshold(),
"GovernorCompatibilityBravo: proposer votes below proposal threshold"
);
uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));
require(targets.length == values.length, "Governor: invalid proposal length");
require(targets.length == calldatas.length, "Governor: invalid proposal length");
require(targets.length > 0, "Governor: empty proposal");
ProposalCore storage proposal = _proposals[proposalId];
require(proposal.voteStart.isUnset(), "Governor: proposal already exists");
uint64 snapshot = block.number.toUint64() + votingDelay().toUint64();
uint64 deadline = snapshot + votingPeriod().toUint64();
proposal.voteStart.setDeadline(snapshot);
proposal.voteEnd.setDeadline(deadline);
emit ProposalCreated(
proposalId,
_msgSender(),
targets,
values,
new string[](targets.length),
calldatas,
snapshot,
deadline,
description
);
return proposalId;
}
/**
* @dev See {IGovernor-execute}.
*/
function execute(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public payable virtual override returns (uint256) {
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
ProposalState status = state(proposalId);
require(
status == ProposalState.Succeeded || status == ProposalState.Queued,
"Governor: proposal not successful"
);
_proposals[proposalId].executed = true;
emit ProposalExecuted(proposalId);
_execute(proposalId, targets, values, calldatas, descriptionHash);
return proposalId;
}
/**
* @dev Internal execution mechanism. Can be overriden to implement different execution mechanism
*/
function _execute(
uint256, /* proposalId */
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 /*descriptionHash*/
) internal virtual {
string memory errorMessage = "Governor: call reverted without message";
for (uint256 i = 0; i < targets.length; ++i) {
(bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]);
Address.verifyCallResult(success, returndata, errorMessage);
}
}
/**
* @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as
* canceled to allow distinguishing it from executed proposals.
*
* Emits a {IGovernor-ProposalCanceled} event.
*/
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual returns (uint256) {
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
ProposalState status = state(proposalId);
require(
status != ProposalState.Canceled && status != ProposalState.Expired && status != ProposalState.Executed,
"Governor: proposal not active"
);
_proposals[proposalId].canceled = true;
emit ProposalCanceled(proposalId);
return proposalId;
}
/**
* @dev See {IGovernor-castVote}.
*/
function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) {
address voter = _msgSender();
return _castVote(proposalId, voter, support, "");
}
/**
* @dev See {IGovernor-castVoteWithReason}.
*/
function castVoteWithReason(
uint256 proposalId,
uint8 support,
string calldata reason
) public virtual override returns (uint256) {
address voter = _msgSender();
return _castVote(proposalId, voter, support, reason);
}
/**
* @dev See {IGovernor-castVoteBySig}.
*/
function castVoteBySig(
uint256 proposalId,
uint8 support,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override returns (uint256) {
address voter = ECDSA.recover(
_hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))),
v,
r,
s
);
return _castVote(proposalId, voter, support, "");
}
/**
* @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
* voting weight using {IGovernor-getVotes} and call the {_countVote} internal function.
*
* Emits a {IGovernor-VoteCast} event.
*/
function _castVote(
uint256 proposalId,
address account,
uint8 support,
string memory reason
) internal virtual returns (uint256) {
ProposalCore storage proposal = _proposals[proposalId];
require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active");
uint256 weight = getVotes(account, proposal.voteStart.getDeadline());
_countVote(proposalId, account, support, weight);
emit VoteCast(account, proposalId, support, weight, reason);
return weight;
}
/**
* @dev Address through which the governor executes action. Will be overloaded by module that execute actions
* through another contract such as a timelock.
*/
function _executor() internal view virtual returns (address) {
return address(this);
}
}

View File

@ -0,0 +1,218 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/IGovernor.sol)
pragma solidity ^0.8.0;
import "../utils/introspection/ERC165.sol";
/**
* @dev Interface of the {Governor} core.
*
* _Available since v4.3._
*/
abstract contract IGovernor is IERC165 {
enum ProposalState {
Pending,
Active,
Canceled,
Defeated,
Succeeded,
Queued,
Expired,
Executed
}
/**
* @dev Emitted when a proposal is created.
*/
event ProposalCreated(
uint256 proposalId,
address proposer,
address[] targets,
uint256[] values,
string[] signatures,
bytes[] calldatas,
uint256 startBlock,
uint256 endBlock,
string description
);
/**
* @dev Emitted when a proposal is canceled.
*/
event ProposalCanceled(uint256 proposalId);
/**
* @dev Emitted when a proposal is executed.
*/
event ProposalExecuted(uint256 proposalId);
/**
* @dev Emitted when a vote is cast.
*
* Note: `support` values should be seen as buckets. There interpretation depends on the voting module used.
*/
event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);
/**
* @notice module:core
* @dev Name of the governor instance (used in building the ERC712 domain separator).
*/
function name() public view virtual returns (string memory);
/**
* @notice module:core
* @dev Version of the governor instance (used in building the ERC712 domain separator). Default: "1"
*/
function version() public view virtual returns (string memory);
/**
* @notice module:voting
* @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to
* be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of
* key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.
*
* There are 2 standard keys: `support` and `quorum`.
*
* - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.
* - `quorum=bravo` means that only For votes are counted towards quorum.
* - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.
*
* NOTE: The string can be decoded by the standard
* https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]
* JavaScript class.
*/
// solhint-disable-next-line func-name-mixedcase
function COUNTING_MODE() public pure virtual returns (string memory);
/**
* @notice module:core
* @dev Hashing function used to (re)build the proposal id from the proposal details..
*/
function hashProposal(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata calldatas,
bytes32 descriptionHash
) public pure virtual returns (uint256);
/**
* @notice module:core
* @dev Current state of a proposal, following Compound's convention
*/
function state(uint256 proposalId) public view virtual returns (ProposalState);
/**
* @notice module:core
* @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's
* ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the
* beginning of the following block.
*/
function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);
/**
* @notice module:core
* @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote
* during this block.
*/
function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);
/**
* @notice module:user-config
* @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to
* leave time for users to buy voting power, of delegate it, before the voting of a proposal starts.
*/
function votingDelay() public view virtual returns (uint256);
/**
* @notice module:user-config
* @dev Delay, in number of blocks, between the vote start and vote ends.
*
* NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting
* duration compared to the voting delay.
*/
function votingPeriod() public view virtual returns (uint256);
/**
* @notice module:user-config
* @dev Minimum number of cast voted required for a proposal to be successful.
*
* Note: The `blockNumber` parameter corresponds to the snaphot used for counting vote. This allows to scale the
* quroum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).
*/
function quorum(uint256 blockNumber) public view virtual returns (uint256);
/**
* @notice module:reputation
* @dev Voting power of an `account` at a specific `blockNumber`.
*
* Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or
* multiple), {ERC20Votes} tokens.
*/
function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);
/**
* @notice module:voting
* @dev Returns weither `account` has cast a vote on `proposalId`.
*/
function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);
/**
* @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends
* {IGovernor-votingPeriod} blocks after the voting starts.
*
* Emits a {ProposalCreated} event.
*/
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public virtual returns (uint256 proposalId);
/**
* @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 requirements for execution, for example by adding an additional timelock.
*/
function execute(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public payable virtual returns (uint256 proposalId);
/**
* @dev Cast a vote
*
* Emits a {VoteCast} event.
*/
function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);
/**
* @dev Cast a with a reason
*
* Emits a {VoteCast} event.
*/
function castVoteWithReason(
uint256 proposalId,
uint8 support,
string calldata reason
) public virtual returns (uint256 balance);
/**
* @dev Cast a vote using the user cryptographic signature.
*
* Emits a {VoteCast} event.
*/
function castVoteBySig(
uint256 proposalId,
uint8 support,
uint8 v,
bytes32 r,
bytes32 s
) public virtual returns (uint256 balance);
}

View File

@ -1,12 +1,89 @@
= Governance
[.readme-notice]
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/access
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/governance
This directory includes primitives for on-chain governance. We currently only offer the {TimelockController} contract, that can be used as a component in a governance systems to introduce a delay between a proposal and its execution.
This directory includes primitives for on-chain governance.
== Governor
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.
[TIP]
====
For a guided experience, set up your Governor contract using https://wizard.openzeppelin.com/#governor[Contracts Wizard].
For a written walkthrough, check out our guide on xref:ROOT:governance.adoc[How to set up on-chain governance].
====
* {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.
Votes modules determine the source of voting power, and sometimes quorum number.
* {GovernorVotes}: Extracts voting weight from an {ERC20Votes} token.
* {GovernorVotesComp}: Extracts voting weight from a COMP-like or {ERC20VotesComp} token.
* {GovernorVotesQuorumFraction}: Combines with `GovernorVotes` to set the quorum as a fraction of the total token supply.
Counting modules determine valid voting options.
* {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.
* {GovernorCompatibilityBravo}: Extends the interface to be fully `GovernorBravo`-compatible. Note that events are compatible regardless of whether this extension is included or not.
* {GovernorSettings}: Manages some of the settings (voting delay, voting period duration, and proposal threshold) in a way that can be updated through a governance proposal, without requiering an upgrade.
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.
=== Core
{{IGovernor}}
{{Governor}}
=== Modules
{{GovernorCountingSimple}}
{{GovernorVotes}}
{{GovernorVotesQuorumFraction}}
{{GovernorVotesComp}}
=== Extensions
{{GovernorTimelockControl}}
{{GovernorTimelockCompound}}
{{GovernorSettings}}
{{GovernorCompatibilityBravo}}
=== Deprecated
{{GovernorProposalThreshold}}
== 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}.
{{TimelockController}}
[[timelock-terminology]]
@ -20,13 +97,14 @@ This directory includes primitives for on-chain governance. We currently only of
** *Done:* An operation that has been executed.
* *Predecessor*: An (optional) dependency between operations. An operation can depend on another operation (its predecessor), forcing the execution order of these two operations.
* *Role*:
** *Admin:* An address (smart contract or EOA) that is in charge of granting the roles of Proposer and Executor.
** *Proposer:* An address (smart contract or EOA) that is in charge of scheduling (and cancelling) operations.
** *Executor:* An address (smart contract or EOA) that is in charge of executing operations.
** *Executor:* An address (smart contract or EOA) that is in charge of executing operations once the timelock has expired. This role can be given to the zero address to allow anyone to execute operations.
[[timelock-operation]]
==== Operation structure
Operation executed by the xref:api:access.adoc#TimelockController[`TimelockControler`] can contain one or multiple subsequent calls. Depending on whether you need to multiple calls to be executed atomically, you can either use simple or batched operations.
Operation executed by the xref:api:governance.adoc#TimelockController[`TimelockController`] can contain one or multiple subsequent calls. Depending on whether you need to multiple calls to be executed atomically, you can either use simple or batched operations.
Both operations contain:
@ -50,16 +128,16 @@ Timelocked operations are identified by a unique id (their hash) and follow a sp
`Unset` -> `Pending` -> `Pending` + `Ready` -> `Done`
* By calling xref:api:access.adoc#TimelockController-schedule-address-uint256-bytes-bytes32-bytes32-uint256-[`schedule`] (or xref:api:access.adoc#TimelockController-scheduleBatch-address---uint256---bytes---bytes32-bytes32-uint256-[`scheduleBatch`]), a proposer moves the operation from the `Unset` to the `Pending` state. This starts a timer that must be longer than the minimum delay. The timer expires at a timestamp accessible through the xref:api:access.adoc#TimelockController-getTimestamp-bytes32-[`getTimestamp`] method.
* By calling xref:api:governance.adoc#TimelockController-schedule-address-uint256-bytes-bytes32-bytes32-uint256-[`schedule`] (or xref:api:governance.adoc#TimelockController-scheduleBatch-address---uint256---bytes---bytes32-bytes32-uint256-[`scheduleBatch`]), a proposer moves the operation from the `Unset` to the `Pending` state. This starts a timer that must be longer than the minimum delay. The timer expires at a timestamp accessible through the xref:api:governance.adoc#TimelockController-getTimestamp-bytes32-[`getTimestamp`] method.
* Once the timer expires, the operation automatically gets the `Ready` state. At this point, it can be executed.
* By calling xref:api:access.adoc#TimelockController-TimelockController-execute-address-uint256-bytes-bytes32-bytes32-[`execute`] (or xref:api:access.adoc#TimelockController-executeBatch-address---uint256---bytes---bytes32-bytes32-[`executeBatch`]), an executor triggers the operation's underlying transactions and moves it to the `Done` state. If the operation has a predecessor, it has to be in the `Done` state for this transition to succeed.
* xref:api:access.adoc#TimelockController-TimelockController-cancel-bytes32-[`cancel`] allows proposers to cancel any `Pending` operation. This resets the operation to the `Unset` state. It is thus possible for a proposer to re-schedule an operation that has been cancelled. In this case, the timer restarts when the operation is re-scheduled.
* By calling xref:api:governance.adoc#TimelockController-TimelockController-execute-address-uint256-bytes-bytes32-bytes32-[`execute`] (or xref:api:governance.adoc#TimelockController-executeBatch-address---uint256---bytes---bytes32-bytes32-[`executeBatch`]), an executor triggers the operation's underlying transactions and moves it to the `Done` state. If the operation has a predecessor, it has to be in the `Done` state for this transition to succeed.
* xref:api:governance.adoc#TimelockController-TimelockController-cancel-bytes32-[`cancel`] allows proposers to cancel any `Pending` operation. This resets the operation to the `Unset` state. It is thus possible for a proposer to re-schedule an operation that has been cancelled. In this case, the timer restarts when the operation is re-scheduled.
Operations status can be queried using the functions:
* xref:api:access.adoc#TimelockController-isOperationPending-bytes32-[`isOperationPending(bytes32)`]
* xref:api:access.adoc#TimelockController-isOperationReady-bytes32-[`isOperationReady(bytes32)`]
* xref:api:access.adoc#TimelockController-isOperationDone-bytes32-[`isOperationDone(bytes32)`]
* xref:api:governance.adoc#TimelockController-isOperationPending-bytes32-[`isOperationPending(bytes32)`]
* xref:api:governance.adoc#TimelockController-isOperationReady-bytes32-[`isOperationReady(bytes32)`]
* xref:api:governance.adoc#TimelockController-isOperationDone-bytes32-[`isOperationDone(bytes32)`]
[[timelock-roles]]
==== Roles
@ -83,9 +161,8 @@ This role is identified by the *PROPOSER_ROLE* value: `0xb09aa5aeb3702cfd50b6b62
[[timelock-executor]]
===== Executor
The executors are in charge of executing the operations scheduled by the proposers once the timelock expires. Logic dictates that multisig or DAO that are proposers should also be executors in order to guarantee operations that have been scheduled will eventually be executed. However, having additional executor can reduce the cost (the executing transaction does not require validation by the multisig or DAO that proposed it), while ensuring whoever is in charge of execution cannot trigger actions that have not been scheduled by the proposers.
The executors are in charge of executing the operations scheduled by the proposers once the timelock expires. Logic dictates that multisig or DAO that are proposers should also be executors in order to guarantee operations that have been scheduled will eventually be executed. However, having additional executors can reduce the cost (the executing transaction does not require validation by the multisig or DAO that proposed it), while ensuring whoever is in charge of execution cannot trigger actions that have not been scheduled by the proposers. Alternatively, it is possible to allow _any_ address to execute a proposal once the timelock has expired by granting the executor role to the zero address.
This role is identified by the *EXECUTOR_ROLE* value: `0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63`
WARNING: A live contract without at least one proposer and one executor is locked. Make sure these roles are filled by reliable entities before the deployer renounces its administrative rights in favour of the timelock contract itself. See the {AccessControl} documentation to learn more about role management.

View File

@ -1,4 +1,5 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/TimelockController.sol)
pragma solidity ^0.8.0;
@ -31,7 +32,15 @@ contract TimelockController is AccessControl {
/**
* @dev Emitted when a call is scheduled as part of operation `id`.
*/
event CallScheduled(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data, bytes32 predecessor, uint256 delay);
event CallScheduled(
bytes32 indexed id,
uint256 indexed index,
address target,
uint256 value,
bytes data,
bytes32 predecessor,
uint256 delay
);
/**
* @dev Emitted when a call is performed as part of operation `id`.
@ -51,7 +60,11 @@ contract TimelockController is AccessControl {
/**
* @dev Initializes the contract with a given `minDelay`.
*/
constructor(uint256 minDelay, address[] memory proposers, address[] memory executors) {
constructor(
uint256 minDelay,
address[] memory proposers,
address[] memory executors
) {
_setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);
_setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);
_setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);
@ -80,8 +93,10 @@ contract TimelockController is AccessControl {
* considered. Granting a role to `address(0)` is equivalent to enabling
* this role for everyone.
*/
modifier onlyRole(bytes32 role) {
require(hasRole(role, _msgSender()) || hasRole(role, address(0)), "TimelockController: sender requires permission");
modifier onlyRoleOrOpenRole(bytes32 role) {
if (!hasRole(role, address(0))) {
_checkRole(role, _msgSender());
}
_;
}
@ -110,7 +125,6 @@ contract TimelockController is AccessControl {
*/
function isOperationReady(bytes32 id) public view virtual returns (bool ready) {
uint256 timestamp = getTimestamp(id);
// solhint-disable-next-line not-rely-on-time
return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;
}
@ -142,7 +156,13 @@ contract TimelockController is AccessControl {
* @dev Returns the identifier of an operation containing a single
* transaction.
*/
function hashOperation(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt) public pure virtual returns (bytes32 hash) {
function hashOperation(
address target,
uint256 value,
bytes calldata data,
bytes32 predecessor,
bytes32 salt
) public pure virtual returns (bytes32 hash) {
return keccak256(abi.encode(target, value, data, predecessor, salt));
}
@ -150,7 +170,13 @@ contract TimelockController is AccessControl {
* @dev Returns the identifier of an operation containing a batch of
* transactions.
*/
function hashOperationBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt) public pure virtual returns (bytes32 hash) {
function hashOperationBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata datas,
bytes32 predecessor,
bytes32 salt
) public pure virtual returns (bytes32 hash) {
return keccak256(abi.encode(targets, values, datas, predecessor, salt));
}
@ -163,7 +189,14 @@ contract TimelockController is AccessControl {
*
* - the caller must have the 'proposer' role.
*/
function schedule(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt, uint256 delay) public virtual onlyRole(PROPOSER_ROLE) {
function schedule(
address target,
uint256 value,
bytes calldata data,
bytes32 predecessor,
bytes32 salt,
uint256 delay
) public virtual onlyRole(PROPOSER_ROLE) {
bytes32 id = hashOperation(target, value, data, predecessor, salt);
_schedule(id, delay);
emit CallScheduled(id, 0, target, value, data, predecessor, delay);
@ -178,7 +211,14 @@ contract TimelockController is AccessControl {
*
* - the caller must have the 'proposer' role.
*/
function scheduleBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt, uint256 delay) public virtual onlyRole(PROPOSER_ROLE) {
function scheduleBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata datas,
bytes32 predecessor,
bytes32 salt,
uint256 delay
) public virtual onlyRole(PROPOSER_ROLE) {
require(targets.length == values.length, "TimelockController: length mismatch");
require(targets.length == datas.length, "TimelockController: length mismatch");
@ -195,7 +235,6 @@ contract TimelockController is AccessControl {
function _schedule(bytes32 id, uint256 delay) private {
require(!isOperation(id), "TimelockController: operation already scheduled");
require(delay >= getMinDelay(), "TimelockController: insufficient delay");
// solhint-disable-next-line not-rely-on-time
_timestamps[id] = block.timestamp + delay;
}
@ -222,9 +261,15 @@ contract TimelockController is AccessControl {
*
* - the caller must have the 'executor' role.
*/
function execute(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt) public payable virtual onlyRole(EXECUTOR_ROLE) {
function execute(
address target,
uint256 value,
bytes calldata data,
bytes32 predecessor,
bytes32 salt
) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
bytes32 id = hashOperation(target, value, data, predecessor, salt);
_beforeCall(predecessor);
_beforeCall(id, predecessor);
_call(id, 0, target, value, data);
_afterCall(id);
}
@ -238,12 +283,18 @@ contract TimelockController is AccessControl {
*
* - the caller must have the 'executor' role.
*/
function executeBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt) public payable virtual onlyRole(EXECUTOR_ROLE) {
function executeBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata datas,
bytes32 predecessor,
bytes32 salt
) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
require(targets.length == values.length, "TimelockController: length mismatch");
require(targets.length == datas.length, "TimelockController: length mismatch");
bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
_beforeCall(predecessor);
_beforeCall(id, predecessor);
for (uint256 i = 0; i < targets.length; ++i) {
_call(id, i, targets[i], values[i], datas[i]);
}
@ -253,7 +304,8 @@ contract TimelockController is AccessControl {
/**
* @dev Checks before execution of an operation's calls.
*/
function _beforeCall(bytes32 predecessor) private view {
function _beforeCall(bytes32 id, bytes32 predecessor) private view {
require(isOperationReady(id), "TimelockController: operation is not ready");
require(predecessor == bytes32(0) || isOperationDone(predecessor), "TimelockController: missing dependency");
}
@ -270,9 +322,14 @@ contract TimelockController is AccessControl {
*
* Emits a {CallExecuted} event.
*/
function _call(bytes32 id, uint256 index, address target, uint256 value, bytes calldata data) private {
// solhint-disable-next-line avoid-low-level-calls
(bool success,) = target.call{value: value}(data);
function _call(
bytes32 id,
uint256 index,
address target,
uint256 value,
bytes calldata data
) private {
(bool success, ) = target.call{value: value}(data);
require(success, "TimelockController: underlying transaction reverted");
emit CallExecuted(id, index, target, value, data);

View File

@ -0,0 +1,288 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.4.2) (governance/compatibility/GovernorCompatibilityBravo.sol)
pragma solidity ^0.8.0;
import "../../utils/Counters.sol";
import "../../utils/math/SafeCast.sol";
import "../extensions/IGovernorTimelock.sol";
import "../Governor.sol";
import "./IGovernorCompatibilityBravo.sol";
/**
* @dev Compatibility layer that implements GovernorBravo compatibility on to of {Governor}.
*
* This compatibility layer includes a voting system and requires a {IGovernorTimelock} compatible module to be added
* through inheritance. It does not include token bindings, not does it include any variable upgrade patterns.
*
* NOTE: When using this module, you may need to enable the Solidity optimizer to avoid hitting the contract size limit.
*
* _Available since v4.3._
*/
abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorCompatibilityBravo, Governor {
using Counters for Counters.Counter;
using Timers for Timers.BlockNumber;
enum VoteType {
Against,
For,
Abstain
}
struct ProposalDetails {
address proposer;
address[] targets;
uint256[] values;
string[] signatures;
bytes[] calldatas;
uint256 forVotes;
uint256 againstVotes;
uint256 abstainVotes;
mapping(address => Receipt) receipts;
bytes32 descriptionHash;
}
mapping(uint256 => ProposalDetails) private _proposalDetails;
// solhint-disable-next-line func-name-mixedcase
function COUNTING_MODE() public pure virtual override returns (string memory) {
return "support=bravo&quorum=bravo";
}
// ============================================== Proposal lifecycle ==============================================
/**
* @dev See {IGovernor-propose}.
*/
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public virtual override(IGovernor, Governor) returns (uint256) {
_storeProposal(_msgSender(), targets, values, new string[](calldatas.length), calldatas, description);
return super.propose(targets, values, calldatas, description);
}
/**
* @dev See {IGovernorCompatibilityBravo-propose}.
*/
function propose(
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description
) public virtual override returns (uint256) {
_storeProposal(_msgSender(), targets, values, signatures, calldatas, description);
return propose(targets, values, _encodeCalldata(signatures, calldatas), description);
}
/**
* @dev See {IGovernorCompatibilityBravo-queue}.
*/
function queue(uint256 proposalId) public virtual override {
ProposalDetails storage details = _proposalDetails[proposalId];
queue(
details.targets,
details.values,
_encodeCalldata(details.signatures, details.calldatas),
details.descriptionHash
);
}
/**
* @dev See {IGovernorCompatibilityBravo-execute}.
*/
function execute(uint256 proposalId) public payable virtual override {
ProposalDetails storage details = _proposalDetails[proposalId];
execute(
details.targets,
details.values,
_encodeCalldata(details.signatures, details.calldatas),
details.descriptionHash
);
}
function cancel(uint256 proposalId) public virtual override {
ProposalDetails storage details = _proposalDetails[proposalId];
require(
_msgSender() == details.proposer || getVotes(details.proposer, block.number - 1) < proposalThreshold(),
"GovernorBravo: proposer above threshold"
);
_cancel(
details.targets,
details.values,
_encodeCalldata(details.signatures, details.calldatas),
details.descriptionHash
);
}
/**
* @dev Encodes calldatas with optional function signature.
*/
function _encodeCalldata(string[] memory signatures, bytes[] memory calldatas)
private
pure
returns (bytes[] memory)
{
bytes[] memory fullcalldatas = new bytes[](calldatas.length);
for (uint256 i = 0; i < signatures.length; ++i) {
fullcalldatas[i] = bytes(signatures[i]).length == 0
? calldatas[i]
: abi.encodePacked(bytes4(keccak256(bytes(signatures[i]))), calldatas[i]);
}
return fullcalldatas;
}
/**
* @dev Store proposal metadata for later lookup
*/
function _storeProposal(
address proposer,
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description
) private {
bytes32 descriptionHash = keccak256(bytes(description));
uint256 proposalId = hashProposal(targets, values, _encodeCalldata(signatures, calldatas), descriptionHash);
ProposalDetails storage details = _proposalDetails[proposalId];
if (details.descriptionHash == bytes32(0)) {
details.proposer = proposer;
details.targets = targets;
details.values = values;
details.signatures = signatures;
details.calldatas = calldatas;
details.descriptionHash = descriptionHash;
}
}
// ==================================================== Views =====================================================
/**
* @dev See {IGovernorCompatibilityBravo-proposals}.
*/
function proposals(uint256 proposalId)
public
view
virtual
override
returns (
uint256 id,
address proposer,
uint256 eta,
uint256 startBlock,
uint256 endBlock,
uint256 forVotes,
uint256 againstVotes,
uint256 abstainVotes,
bool canceled,
bool executed
)
{
id = proposalId;
eta = proposalEta(proposalId);
startBlock = proposalSnapshot(proposalId);
endBlock = proposalDeadline(proposalId);
ProposalDetails storage details = _proposalDetails[proposalId];
proposer = details.proposer;
forVotes = details.forVotes;
againstVotes = details.againstVotes;
abstainVotes = details.abstainVotes;
ProposalState status = state(proposalId);
canceled = status == ProposalState.Canceled;
executed = status == ProposalState.Executed;
}
/**
* @dev See {IGovernorCompatibilityBravo-getActions}.
*/
function getActions(uint256 proposalId)
public
view
virtual
override
returns (
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas
)
{
ProposalDetails storage details = _proposalDetails[proposalId];
return (details.targets, details.values, details.signatures, details.calldatas);
}
/**
* @dev See {IGovernorCompatibilityBravo-getReceipt}.
*/
function getReceipt(uint256 proposalId, address voter) public view virtual override returns (Receipt memory) {
return _proposalDetails[proposalId].receipts[voter];
}
/**
* @dev See {IGovernorCompatibilityBravo-quorumVotes}.
*/
function quorumVotes() public view virtual override returns (uint256) {
return quorum(block.number - 1);
}
// ==================================================== Voting ====================================================
/**
* @dev See {IGovernor-hasVoted}.
*/
function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
return _proposalDetails[proposalId].receipts[account].hasVoted;
}
/**
* @dev See {Governor-_quorumReached}. In this module, only forVotes count toward the quorum.
*/
function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
ProposalDetails storage details = _proposalDetails[proposalId];
return quorum(proposalSnapshot(proposalId)) <= details.forVotes;
}
/**
* @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) {
ProposalDetails storage details = _proposalDetails[proposalId];
return details.forVotes > details.againstVotes;
}
/**
* @dev See {Governor-_countVote}. In this module, the support follows Governor Bravo.
*/
function _countVote(
uint256 proposalId,
address account,
uint8 support,
uint256 weight
) internal virtual override {
ProposalDetails storage details = _proposalDetails[proposalId];
Receipt storage receipt = details.receipts[account];
require(!receipt.hasVoted, "GovernorCompatibilityBravo: vote already cast");
receipt.hasVoted = true;
receipt.support = support;
receipt.votes = SafeCast.toUint96(weight);
if (support == uint8(VoteType.Against)) {
details.againstVotes += weight;
} else if (support == uint8(VoteType.For)) {
details.forVotes += weight;
} else if (support == uint8(VoteType.Abstain)) {
details.abstainVotes += weight;
} else {
revert("GovernorCompatibilityBravo: invalid vote type");
}
}
}

View File

@ -0,0 +1,114 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/compatibility/IGovernorCompatibilityBravo.sol)
pragma solidity ^0.8.0;
import "../IGovernor.sol";
/**
* @dev Interface extension that adds missing functions to the {Governor} core to provide `GovernorBravo` compatibility.
*
* _Available since v4.3._
*/
abstract contract IGovernorCompatibilityBravo is IGovernor {
/**
* @dev Proposal structure from Compound Governor Bravo. Not actually used by the compatibility layer, as
* {{proposal}} returns a very different structure.
*/
struct Proposal {
uint256 id;
address proposer;
uint256 eta;
address[] targets;
uint256[] values;
string[] signatures;
bytes[] calldatas;
uint256 startBlock;
uint256 endBlock;
uint256 forVotes;
uint256 againstVotes;
uint256 abstainVotes;
bool canceled;
bool executed;
mapping(address => Receipt) receipts;
}
/**
* @dev Receipt structure from Compound Governor Bravo
*/
struct Receipt {
bool hasVoted;
uint8 support;
uint96 votes;
}
/**
* @dev Part of the Governor Bravo's interface.
*/
function quorumVotes() public view virtual returns (uint256);
/**
* @dev Part of the Governor Bravo's interface: _"The official record of all proposals ever proposed"_.
*/
function proposals(uint256)
public
view
virtual
returns (
uint256 id,
address proposer,
uint256 eta,
uint256 startBlock,
uint256 endBlock,
uint256 forVotes,
uint256 againstVotes,
uint256 abstainVotes,
bool canceled,
bool executed
);
/**
* @dev Part of the Governor Bravo's interface: _"Function used to propose a new proposal"_.
*/
function propose(
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description
) public virtual returns (uint256);
/**
* @dev Part of the Governor Bravo's interface: _"Queues a proposal of state succeeded"_.
*/
function queue(uint256 proposalId) public virtual;
/**
* @dev Part of the Governor Bravo's interface: _"Executes a queued proposal if eta has passed"_.
*/
function execute(uint256 proposalId) public payable virtual;
/**
* @dev Cancels a proposal only if sender is the proposer, or proposer delegates dropped below proposal threshold.
*/
function cancel(uint256 proposalId) public virtual;
/**
* @dev Part of the Governor Bravo's interface: _"Gets actions of a proposal"_.
*/
function getActions(uint256 proposalId)
public
view
virtual
returns (
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas
);
/**
* @dev Part of the Governor Bravo's interface: _"Gets the receipt for a voter on a given proposal"_.
*/
function getReceipt(uint256 proposalId, address voter) public view virtual returns (Receipt memory);
}

View File

@ -0,0 +1,106 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorCountingSimple.sol)
pragma solidity ^0.8.0;
import "../Governor.sol";
/**
* @dev Extension of {Governor} for simple, 3 options, vote counting.
*
* _Available since v4.3._
*/
abstract contract GovernorCountingSimple is Governor {
/**
* @dev Supported vote types. Matches Governor Bravo ordering.
*/
enum VoteType {
Against,
For,
Abstain
}
struct ProposalVote {
uint256 againstVotes;
uint256 forVotes;
uint256 abstainVotes;
mapping(address => bool) hasVoted;
}
mapping(uint256 => ProposalVote) private _proposalVotes;
/**
* @dev See {IGovernor-COUNTING_MODE}.
*/
// solhint-disable-next-line func-name-mixedcase
function COUNTING_MODE() public pure virtual override returns (string memory) {
return "support=bravo&quorum=for,abstain";
}
/**
* @dev See {IGovernor-hasVoted}.
*/
function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
return _proposalVotes[proposalId].hasVoted[account];
}
/**
* @dev Accessor to the internal vote counts.
*/
function proposalVotes(uint256 proposalId)
public
view
virtual
returns (
uint256 againstVotes,
uint256 forVotes,
uint256 abstainVotes
)
{
ProposalVote storage proposalvote = _proposalVotes[proposalId];
return (proposalvote.againstVotes, proposalvote.forVotes, proposalvote.abstainVotes);
}
/**
* @dev See {Governor-_quorumReached}.
*/
function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
ProposalVote storage proposalvote = _proposalVotes[proposalId];
return quorum(proposalSnapshot(proposalId)) <= proposalvote.forVotes + proposalvote.abstainVotes;
}
/**
* @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes.
*/
function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) {
ProposalVote storage proposalvote = _proposalVotes[proposalId];
return proposalvote.forVotes > proposalvote.againstVotes;
}
/**
* @dev See {Governor-_countVote}. In this module, the support follows the `VoteType` enum (from Governor Bravo).
*/
function _countVote(
uint256 proposalId,
address account,
uint8 support,
uint256 weight
) internal virtual override {
ProposalVote storage proposalvote = _proposalVotes[proposalId];
require(!proposalvote.hasVoted[account], "GovernorVotingSimple: vote already cast");
proposalvote.hasVoted[account] = true;
if (support == uint8(VoteType.Against)) {
proposalvote.againstVotes += weight;
} else if (support == uint8(VoteType.For)) {
proposalvote.forVotes += weight;
} else if (support == uint8(VoteType.Abstain)) {
proposalvote.abstainVotes += weight;
} else {
revert("GovernorVotingSimple: invalid value for enum VoteType");
}
}
}

View File

@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorProposalThreshold.sol)
pragma solidity ^0.8.0;
import "../Governor.sol";
/**
* @dev Extension of {Governor} for proposal restriction to token holders with a minimum balance.
*
* _Available since v4.3._
* _Deprecated since v4.4._
*/
abstract contract GovernorProposalThreshold is Governor {
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public virtual override returns (uint256) {
return super.propose(targets, values, calldatas, description);
}
}

View File

@ -0,0 +1,114 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorSettings.sol)
pragma solidity ^0.8.0;
import "../Governor.sol";
/**
* @dev Extension of {Governor} for settings updatable through governance.
*
* _Available since v4.4._
*/
abstract contract GovernorSettings is Governor {
uint256 private _votingDelay;
uint256 private _votingPeriod;
uint256 private _proposalThreshold;
event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);
event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);
event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold);
/**
* @dev Initialize the governance parameters.
*/
constructor(
uint256 initialVotingDelay,
uint256 initialVotingPeriod,
uint256 initialProposalThreshold
) {
_setVotingDelay(initialVotingDelay);
_setVotingPeriod(initialVotingPeriod);
_setProposalThreshold(initialProposalThreshold);
}
/**
* @dev See {IGovernor-votingDelay}.
*/
function votingDelay() public view virtual override returns (uint256) {
return _votingDelay;
}
/**
* @dev See {IGovernor-votingPeriod}.
*/
function votingPeriod() public view virtual override returns (uint256) {
return _votingPeriod;
}
/**
* @dev See {Governor-proposalThreshold}.
*/
function proposalThreshold() public view virtual override returns (uint256) {
return _proposalThreshold;
}
/**
* @dev Update the voting delay. This operation can only be performed through a governance proposal.
*
* Emits a {VotingDelaySet} event.
*/
function setVotingDelay(uint256 newVotingDelay) public virtual onlyGovernance {
_setVotingDelay(newVotingDelay);
}
/**
* @dev Update the voting period. This operation can only be performed through a governance proposal.
*
* Emits a {VotingPeriodSet} event.
*/
function setVotingPeriod(uint256 newVotingPeriod) public virtual onlyGovernance {
_setVotingPeriod(newVotingPeriod);
}
/**
* @dev Update the proposal threshold. This operation can only be performed through a governance proposal.
*
* Emits a {ProposalThresholdSet} event.
*/
function setProposalThreshold(uint256 newProposalThreshold) public virtual onlyGovernance {
_setProposalThreshold(newProposalThreshold);
}
/**
* @dev Internal setter for the voting delay.
*
* Emits a {VotingDelaySet} event.
*/
function _setVotingDelay(uint256 newVotingDelay) internal virtual {
emit VotingDelaySet(_votingDelay, newVotingDelay);
_votingDelay = newVotingDelay;
}
/**
* @dev Internal setter for the voting period.
*
* Emits a {VotingPeriodSet} event.
*/
function _setVotingPeriod(uint256 newVotingPeriod) internal virtual {
// voting period must be at least one block long
require(newVotingPeriod > 0, "GovernorSettings: voting period too low");
emit VotingPeriodSet(_votingPeriod, newVotingPeriod);
_votingPeriod = newVotingPeriod;
}
/**
* @dev Internal setter for the proposal threshold.
*
* Emits a {ProposalThresholdSet} event.
*/
function _setProposalThreshold(uint256 newProposalThreshold) internal virtual {
emit ProposalThresholdSet(_proposalThreshold, newProposalThreshold);
_proposalThreshold = newProposalThreshold;
}
}

View File

@ -0,0 +1,244 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorTimelockCompound.sol)
pragma solidity ^0.8.0;
import "./IGovernorTimelock.sol";
import "../Governor.sol";
import "../../utils/math/SafeCast.sol";
/**
* https://github.com/compound-finance/compound-protocol/blob/master/contracts/Timelock.sol[Compound's timelock] interface
*/
interface ICompoundTimelock {
receive() external payable;
// solhint-disable-next-line func-name-mixedcase
function GRACE_PERIOD() external view returns (uint256);
// solhint-disable-next-line func-name-mixedcase
function MINIMUM_DELAY() external view returns (uint256);
// solhint-disable-next-line func-name-mixedcase
function MAXIMUM_DELAY() external view returns (uint256);
function admin() external view returns (address);
function pendingAdmin() external view returns (address);
function delay() external view returns (uint256);
function queuedTransactions(bytes32) external view returns (bool);
function setDelay(uint256) external;
function acceptAdmin() external;
function setPendingAdmin(address) external;
function queueTransaction(
address target,
uint256 value,
string memory signature,
bytes memory data,
uint256 eta
) external returns (bytes32);
function cancelTransaction(
address target,
uint256 value,
string memory signature,
bytes memory data,
uint256 eta
) external;
function executeTransaction(
address target,
uint256 value,
string memory signature,
bytes memory data,
uint256 eta
) external payable returns (bytes memory);
}
/**
* @dev Extension of {Governor} that binds the execution process to a Compound Timelock. This adds a delay, enforced by
* the external timelock to all successful proposal (in addition to the voting duration). The {Governor} needs to be
* the admin of the timelock for any operation to be performed. A public, unrestricted,
* {GovernorTimelockCompound-__acceptAdmin} is available to accept ownership of the timelock.
*
* 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.
*
* _Available since v4.3._
*/
abstract contract GovernorTimelockCompound is IGovernorTimelock, Governor {
using SafeCast for uint256;
using Timers for Timers.Timestamp;
struct ProposalTimelock {
Timers.Timestamp timer;
}
ICompoundTimelock private _timelock;
mapping(uint256 => ProposalTimelock) private _proposalTimelocks;
/**
* @dev Emitted when the timelock controller used for proposal execution is modified.
*/
event TimelockChange(address oldTimelock, address newTimelock);
/**
* @dev Set the timelock.
*/
constructor(ICompoundTimelock timelockAddress) {
_updateTimelock(timelockAddress);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, Governor) returns (bool) {
return interfaceId == type(IGovernorTimelock).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Overriden version of the {Governor-state} function with added support for the `Queued` and `Expired` status.
*/
function state(uint256 proposalId) public view virtual override(IGovernor, Governor) returns (ProposalState) {
ProposalState status = super.state(proposalId);
if (status != ProposalState.Succeeded) {
return status;
}
uint256 eta = proposalEta(proposalId);
if (eta == 0) {
return status;
} else if (block.timestamp >= eta + _timelock.GRACE_PERIOD()) {
return ProposalState.Expired;
} else {
return ProposalState.Queued;
}
}
/**
* @dev Public accessor to check the address of the timelock
*/
function timelock() public view virtual override returns (address) {
return address(_timelock);
}
/**
* @dev Public accessor to check the eta of a queued proposal
*/
function proposalEta(uint256 proposalId) public view virtual override returns (uint256) {
return _proposalTimelocks[proposalId].timer.getDeadline();
}
/**
* @dev Function to queue a proposal to the timelock.
*/
function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual override returns (uint256) {
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
require(state(proposalId) == ProposalState.Succeeded, "Governor: proposal not successful");
uint256 eta = block.timestamp + _timelock.delay();
_proposalTimelocks[proposalId].timer.setDeadline(eta.toUint64());
for (uint256 i = 0; i < targets.length; ++i) {
require(
!_timelock.queuedTransactions(keccak256(abi.encode(targets[i], values[i], "", calldatas[i], eta))),
"GovernorTimelockCompound: identical proposal action already queued"
);
_timelock.queueTransaction(targets[i], values[i], "", calldatas[i], eta);
}
emit ProposalQueued(proposalId, eta);
return proposalId;
}
/**
* @dev Overriden execute function that run the already queued proposal through the timelock.
*/
function _execute(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 /*descriptionHash*/
) internal virtual override {
uint256 eta = proposalEta(proposalId);
require(eta > 0, "GovernorTimelockCompound: proposal not yet queued");
Address.sendValue(payable(_timelock), msg.value);
for (uint256 i = 0; i < targets.length; ++i) {
_timelock.executeTransaction(targets[i], values[i], "", calldatas[i], eta);
}
}
/**
* @dev Overriden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
* been queued.
*/
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual override returns (uint256) {
uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash);
uint256 eta = proposalEta(proposalId);
if (eta > 0) {
for (uint256 i = 0; i < targets.length; ++i) {
_timelock.cancelTransaction(targets[i], values[i], "", calldatas[i], eta);
}
_proposalTimelocks[proposalId].timer.reset();
}
return proposalId;
}
/**
* @dev Address through which the governor executes action. In this case, the timelock.
*/
function _executor() internal view virtual override returns (address) {
return address(_timelock);
}
/**
* @dev Accept admin right over the timelock.
*/
// solhint-disable-next-line private-vars-leading-underscore
function __acceptAdmin() public {
_timelock.acceptAdmin();
}
/**
* @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.
*
* For security reason, 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.
*/
function updateTimelock(ICompoundTimelock newTimelock) external virtual onlyGovernance {
_updateTimelock(newTimelock);
}
function _updateTimelock(ICompoundTimelock newTimelock) private {
emit TimelockChange(address(_timelock), address(newTimelock));
_timelock = newTimelock;
}
}

View File

@ -0,0 +1,154 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorTimelockControl.sol)
pragma solidity ^0.8.0;
import "./IGovernorTimelock.sol";
import "../Governor.sol";
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.
*
* 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.
*
* _Available since v4.3._
*/
abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
TimelockController private _timelock;
mapping(uint256 => bytes32) private _timelockIds;
/**
* @dev Emitted when the timelock controller used for proposal execution is modified.
*/
event TimelockChange(address oldTimelock, address newTimelock);
/**
* @dev Set the timelock.
*/
constructor(TimelockController timelockAddress) {
_updateTimelock(timelockAddress);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, Governor) returns (bool) {
return interfaceId == type(IGovernorTimelock).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Overriden version of the {Governor-state} function with added support for the `Queued` status.
*/
function state(uint256 proposalId) public view virtual override(IGovernor, Governor) returns (ProposalState) {
ProposalState status = super.state(proposalId);
if (status != ProposalState.Succeeded) {
return status;
}
// core tracks execution, so we just have to check if successful proposal have been queued.
bytes32 queueid = _timelockIds[proposalId];
if (queueid == bytes32(0)) {
return status;
} else if (_timelock.isOperationDone(queueid)) {
return ProposalState.Executed;
} else {
return ProposalState.Queued;
}
}
/**
* @dev Public accessor to check the address of the timelock
*/
function timelock() public view virtual override returns (address) {
return address(_timelock);
}
/**
* @dev Public accessor to check the eta of a queued proposal
*/
function proposalEta(uint256 proposalId) public view virtual override returns (uint256) {
uint256 eta = _timelock.getTimestamp(_timelockIds[proposalId]);
return eta == 1 ? 0 : eta; // _DONE_TIMESTAMP (1) should be replaced with a 0 value
}
/**
* @dev Function to queue a proposal to the timelock.
*/
function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual override returns (uint256) {
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
require(state(proposalId) == ProposalState.Succeeded, "Governor: proposal not successful");
uint256 delay = _timelock.getMinDelay();
_timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, descriptionHash);
_timelock.scheduleBatch(targets, values, calldatas, 0, descriptionHash, delay);
emit ProposalQueued(proposalId, block.timestamp + delay);
return proposalId;
}
/**
* @dev Overriden execute function that run the already queued proposal through the timelock.
*/
function _execute(
uint256, /* proposalId */
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual override {
_timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, descriptionHash);
}
/**
* @dev Overriden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already
* been queued.
*/
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual override returns (uint256) {
uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash);
if (_timelockIds[proposalId] != 0) {
_timelock.cancel(_timelockIds[proposalId]);
delete _timelockIds[proposalId];
}
return proposalId;
}
/**
* @dev Address through which the governor executes action. In this case, the timelock.
*/
function _executor() internal view virtual override returns (address) {
return address(_timelock);
}
/**
* @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.
*/
function updateTimelock(TimelockController newTimelock) external virtual onlyGovernance {
_updateTimelock(newTimelock);
}
function _updateTimelock(TimelockController newTimelock) private {
emit TimelockChange(address(_timelock), address(newTimelock));
_timelock = newTimelock;
}
}

View File

@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorVotes.sol)
pragma solidity ^0.8.0;
import "../Governor.sol";
import "../../token/ERC20/extensions/ERC20Votes.sol";
import "../../utils/math/Math.sol";
/**
* @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token.
*
* _Available since v4.3._
*/
abstract contract GovernorVotes is Governor {
ERC20Votes public immutable token;
constructor(ERC20Votes tokenAddress) {
token = tokenAddress;
}
/**
* Read the voting weight from the token's built in snapshot mechanism (see {IGovernor-getVotes}).
*/
function getVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
return token.getPastVotes(account, blockNumber);
}
}

View File

@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorVotesComp.sol)
pragma solidity ^0.8.0;
import "../Governor.sol";
import "../../token/ERC20/extensions/ERC20VotesComp.sol";
/**
* @dev Extension of {Governor} for voting weight extraction from a Comp token.
*
* _Available since v4.3._
*/
abstract contract GovernorVotesComp is Governor {
ERC20VotesComp public immutable token;
constructor(ERC20VotesComp token_) {
token = token_;
}
/**
* Read the voting weight from the token's built in snapshot mechanism (see {IGovernor-getVotes}).
*/
function getVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {
return token.getPriorVotes(account, blockNumber);
}
}

View File

@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorVotesQuorumFraction.sol)
pragma solidity ^0.8.0;
import "./GovernorVotes.sol";
/**
* @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a
* fraction of the total supply.
*
* _Available since v4.3._
*/
abstract contract GovernorVotesQuorumFraction is GovernorVotes {
uint256 private _quorumNumerator;
event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);
constructor(uint256 quorumNumeratorValue) {
_updateQuorumNumerator(quorumNumeratorValue);
}
function quorumNumerator() public view virtual returns (uint256) {
return _quorumNumerator;
}
function quorumDenominator() public view virtual returns (uint256) {
return 100;
}
function quorum(uint256 blockNumber) public view virtual override returns (uint256) {
return (token.getPastTotalSupply(blockNumber) * quorumNumerator()) / quorumDenominator();
}
function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance {
_updateQuorumNumerator(newQuorumNumerator);
}
function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual {
require(
newQuorumNumerator <= quorumDenominator(),
"GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator"
);
uint256 oldQuorumNumerator = _quorumNumerator;
_quorumNumerator = newQuorumNumerator;
emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);
}
}

View File

@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/IGovernorTimelock.sol)
pragma solidity ^0.8.0;
import "../IGovernor.sol";
/**
* @dev Extension of the {IGovernor} for timelock supporting modules.
*
* _Available since v4.3._
*/
abstract contract IGovernorTimelock is IGovernor {
event ProposalQueued(uint256 proposalId, uint256 eta);
function timelock() public view virtual returns (address);
function proposalEta(uint256 proposalId) public view virtual returns (uint256);
function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual returns (uint256 proposalId);
}

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155.sol)
pragma solidity ^0.8.0;
import "../token/ERC1155/IERC1155.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155MetadataURI.sol)
pragma solidity ^0.8.0;
import "../token/ERC1155/extensions/IERC1155MetadataURI.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../token/ERC1155/IERC1155Receiver.sol";

View File

@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*
* _Available since v4.1._
*/
interface IERC1271 {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

View File

@ -0,0 +1,95 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1363.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./IERC165.sol";
interface IERC1363 is IERC165, IERC20 {
/*
* Note: the ERC-165 identifier for this interface is 0x4bbee2df.
* 0x4bbee2df ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)'))
*/
/*
* Note: the ERC-165 identifier for this interface is 0xfb9ec8ce.
* 0xfb9ec8ce ===
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver
* @param to address The address which you want to transfer to
* @param value uint256 The amount of tokens to be transferred
* @return true unless throwing
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver
* @param to address The address which you want to transfer to
* @param value uint256 The amount of tokens to be transferred
* @param data bytes Additional data with no specified format, sent in call to `to`
* @return true unless throwing
*/
function transferAndCall(
address to,
uint256 value,
bytes memory data
) external returns (bool);
/**
* @dev Transfer tokens from one address to another and then call `onTransferReceived` on receiver
* @param from address The address which you want to send tokens from
* @param to address The address which you want to transfer to
* @param value uint256 The amount of tokens to be transferred
* @return true unless throwing
*/
function transferFromAndCall(
address from,
address to,
uint256 value
) external returns (bool);
/**
* @dev Transfer tokens from one address to another and then call `onTransferReceived` on receiver
* @param from address The address which you want to send tokens from
* @param to address The address which you want to transfer to
* @param value uint256 The amount of tokens to be transferred
* @param data bytes Additional data with no specified format, sent in call to `to`
* @return true unless throwing
*/
function transferFromAndCall(
address from,
address to,
uint256 value,
bytes memory data
) external returns (bool);
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender
* and then call `onApprovalReceived` on spender.
* @param spender address The address which will spend the funds
* @param value uint256 The amount of tokens to be spent
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender
* and then call `onApprovalReceived` on spender.
* @param spender address The address which will spend the funds
* @param value uint256 The amount of tokens to be spent
* @param data bytes Additional data with no specified format, sent in call to `spender`
*/
function approveAndCall(
address spender,
uint256 value,
bytes memory data
) external returns (bool);
}

View File

@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1363Receiver.sol)
pragma solidity ^0.8.0;
interface IERC1363Receiver {
/*
* Note: the ERC-165 identifier for this interface is 0x88a7ca5c.
* 0x88a7ca5c === bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))
*/
/**
* @notice Handle the receipt of ERC1363 tokens
* @dev Any ERC1363 smart contract calls this function on the recipient
* after a `transfer` or a `transferFrom`. This function MAY throw to revert and reject the
* transfer. Return of other than the magic value MUST result in the
* transaction being reverted.
* Note: the token contract address is always the message sender.
* @param operator address The address which called `transferAndCall` or `transferFromAndCall` function
* @param from address The address which are token transferred from
* @param value uint256 The amount of tokens transferred
* @param data bytes Additional data with no specified format
* @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))`
* unless throwing
*/
function onTransferReceived(
address operator,
address from,
uint256 value,
bytes memory data
) external returns (bytes4);
}

View File

@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1363Spender.sol)
pragma solidity ^0.8.0;
interface IERC1363Spender {
/*
* Note: the ERC-165 identifier for this interface is 0x7b04a2d0.
* 0x7b04a2d0 === bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))
*/
/**
* @notice Handle the approval of ERC1363 tokens
* @dev Any ERC1363 smart contract calls this function on the recipient
* after an `approve`. This function MAY throw to revert and reject the
* approval. Return of other than the magic value MUST result in the
* transaction being reverted.
* Note: the token contract address is always the message sender.
* @param owner address The address which called `approveAndCall` function
* @param value uint256 The amount of tokens to be spent
* @param data bytes Additional data with no specified format
* @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))`
* unless throwing
*/
function onApprovalReceived(
address owner,
uint256 value,
bytes memory data
) external returns (bytes4);
}

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)
pragma solidity ^0.8.0;
import "../utils/introspection/IERC165.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1820Implementer.sol)
pragma solidity ^0.8.0;
import "../utils/introspection/IERC1820Implementer.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1820Registry.sol)
pragma solidity ^0.8.0;
import "../utils/introspection/IERC1820Registry.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)
pragma solidity ^0.8.0;
import "../token/ERC20/IERC20.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../token/ERC20/extensions/IERC20Metadata.sol";

View File

@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC2981.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard
*/
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`
*/
function royaltyInfo(uint256 tokenId, uint256 salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
}

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156.sol)
pragma solidity ^0.8.0;
import "./IERC3156FlashBorrower.sol";
import "./IERC3156FlashLender.sol";

View File

@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashBorrower.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC3156 FlashBorrower, as defined in
* https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].
*
* _Available since v4.1._
*/
interface IERC3156FlashBorrower {
/**
* @dev Receive a flash loan.
* @param initiator The initiator of the loan.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @param fee The additional amount of tokens to repay.
* @param data Arbitrary data structure, intended to contain user-defined parameters.
* @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan"
*/
function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32);
}

View File

@ -0,0 +1,43 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashLender.sol)
pragma solidity ^0.8.0;
import "./IERC3156FlashBorrower.sol";
/**
* @dev Interface of the ERC3156 FlashLender, as defined in
* https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].
*
* _Available since v4.1._
*/
interface IERC3156FlashLender {
/**
* @dev The amount of currency available to be lended.
* @param token The loan currency.
* @return The amount of `token` that can be borrowed.
*/
function maxFlashLoan(address token) external view returns (uint256);
/**
* @dev The fee to be charged for a given loan.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @return The amount of `token` to be charged for the loan, on top of the returned principal.
*/
function flashFee(address token, uint256 amount) external view returns (uint256);
/**
* @dev Initiate a flash loan.
* @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @param data Arbitrary data structure, intended to contain user-defined parameters.
*/
function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external returns (bool);
}

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721.sol)
pragma solidity ^0.8.0;
import "../token/ERC721/IERC721.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../token/ERC721/extensions/IERC721Enumerable.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../token/ERC721/extensions/IERC721Metadata.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Receiver.sol)
pragma solidity ^0.8.0;
import "../token/ERC721/IERC721Receiver.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC777.sol)
pragma solidity ^0.8.0;
import "../token/ERC777/IERC777.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC777Recipient.sol)
pragma solidity ^0.8.0;
import "../token/ERC777/IERC777Recipient.sol";

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC777Sender.sol)
pragma solidity ^0.8.0;
import "../token/ERC777/IERC777Sender.sol";

View File

@ -0,0 +1,50 @@
= Interfaces
[.readme-notice]
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
are usefull to interract with third party contracts that implement them.
- {IERC20}
- {IERC20Metadata}
- {IERC165}
- {IERC721}
- {IERC721Receiver}
- {IERC721Enumerable}
- {IERC721Metadata}
- {IERC777}
- {IERC777Recipient}
- {IERC777Sender}
- {IERC1155}
- {IERC1155Receiver}
- {IERC1155MetadataURI}
- {IERC1271}
- {IERC1363}
- {IERC1820Implementer}
- {IERC1820Registry}
- {IERC2612}
- {IERC2981}
- {IERC3156FlashLender}
- {IERC3156FlashBorrower}
== Detailed ABI
{{IERC1271}}
{{IERC1363}}
{{IERC1363Receiver}}
{{IERC1820Implementer}}
{{IERC1820Registry}}
{{IERC2612}}
{{IERC2981}}
{{IERC3156FlashLender}}
{{IERC3156FlashBorrower}}

View File

@ -0,0 +1,8 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/draft-IERC2612.sol)
pragma solidity ^0.8.0;
import "../token/ERC20/extensions/draft-IERC20Permit.sol";
interface IERC2612 is IERC20Permit {}

View File

@ -1,27 +1,30 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (metatx/ERC2771Context.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/*
/**
* @dev Context variant with ERC2771 support.
*/
abstract contract ERC2771Context is Context {
address immutable _trustedForwarder;
address private _trustedForwarder;
constructor(address trustedForwarder) {
_trustedForwarder = trustedForwarder;
}
function isTrustedForwarder(address forwarder) public view virtual returns(bool) {
function isTrustedForwarder(address forwarder) public view virtual returns (bool) {
return forwarder == _trustedForwarder;
}
function _msgSender() internal view virtual override returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
// The assembly code is more direct than the Solidity version using `abi.decode`.
assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) }
assembly {
sender := shr(96, calldataload(sub(calldatasize(), 20)))
}
} else {
return super._msgSender();
}
@ -29,7 +32,7 @@ abstract contract ERC2771Context is Context {
function _msgData() internal view virtual override returns (bytes calldata) {
if (isTrustedForwarder(msg.sender)) {
return msg.data[:msg.data.length-20];
return msg.data[:msg.data.length - 20];
} else {
return super._msgData();
}

View File

@ -1,11 +1,12 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (metatx/MinimalForwarder.sol)
pragma solidity ^0.8.0;
import "../utils/cryptography/ECDSA.sol";
import "../utils/cryptography/draft-EIP712.sol";
/*
/**
* @dev Simple minimal forwarder to be used together with an ERC2771 compatible contract. See {ERC2771Context}.
*/
contract MinimalForwarder is EIP712 {
@ -20,7 +21,8 @@ contract MinimalForwarder is EIP712 {
bytes data;
}
bytes32 private constant TYPEHASH = keccak256("ForwardRequest(address from,address to,uint256 value,uint256 gas,uint256 nonce,bytes data)");
bytes32 private constant _TYPEHASH =
keccak256("ForwardRequest(address from,address to,uint256 value,uint256 gas,uint256 nonce,bytes data)");
mapping(address => uint256) private _nonces;
@ -31,24 +33,23 @@ contract MinimalForwarder is EIP712 {
}
function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool) {
address signer = _hashTypedDataV4(keccak256(abi.encode(
TYPEHASH,
req.from,
req.to,
req.value,
req.gas,
req.nonce,
keccak256(req.data)
))).recover(signature);
address signer = _hashTypedDataV4(
keccak256(abi.encode(_TYPEHASH, req.from, req.to, req.value, req.gas, req.nonce, keccak256(req.data)))
).recover(signature);
return _nonces[req.from] == req.nonce && signer == req.from;
}
function execute(ForwardRequest calldata req, bytes calldata signature) public payable returns (bool, bytes memory) {
function execute(ForwardRequest calldata req, bytes calldata signature)
public
payable
returns (bool, bytes memory)
{
require(verify(req, signature), "MinimalForwarder: signature does not match request");
_nonces[req.from] = req.nonce + 1;
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = req.to.call{gas: req.gas, value: req.value}(abi.encodePacked(req.data, req.from));
(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);

View File

@ -12,4 +12,6 @@ contract AccessControlEnumerableMock is AccessControlEnumerable {
function setRoleAdmin(bytes32 roleId, bytes32 adminRoleId) public {
_setRoleAdmin(roleId, adminRoleId);
}
function senderProtected(bytes32 roleId) public onlyRole(roleId) {}
}

View File

@ -12,4 +12,6 @@ contract AccessControlMock is AccessControl {
function setRoleAdmin(bytes32 roleId, bytes32 adminRoleId) public {
_setRoleAdmin(roleId, adminRoleId);
}
function senderProtected(bytes32 roleId) public onlyRole(roleId) {}
}

View File

@ -22,7 +22,11 @@ contract AddressImpl {
emit CallReturnValue(abi.decode(returnData, (string)));
}
function functionCallWithValue(address target, bytes calldata data, uint256 value) external payable {
function functionCallWithValue(
address target,
bytes calldata data,
uint256 value
) external payable {
bytes memory returnData = Address.functionCallWithValue(target, data, value);
emit CallReturnValue(abi.decode(returnData, (string)));
}
@ -38,5 +42,5 @@ contract AddressImpl {
}
// sendValue's tests require the contract to hold Ether
receive () external payable { }
receive() external payable {}
}

View File

@ -9,7 +9,7 @@ contract ArraysImpl {
uint256[] private _array;
constructor (uint256[] memory array) {
constructor(uint256[] memory array) {
_array = array;
}

View File

@ -2,8 +2,7 @@
pragma solidity ^0.8.0;
contract BadBeaconNoImpl {
}
contract BadBeaconNoImpl {}
contract BadBeaconNotContract {
function implementation() external pure returns (address) {

View File

@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/structs/BitMaps.sol";
contract BitMapMock {
using BitMaps for BitMaps.BitMap;
BitMaps.BitMap private _bitmap;
function get(uint256 index) public view returns (bool) {
return _bitmap.get(index);
}
function setTo(uint256 index, bool value) public {
_bitmap.setTo(index, value);
}
function set(uint256 index) public {
_bitmap.set(index);
}
function unset(uint256 index) public {
_bitmap.unset(index);
}
}

View File

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

View File

@ -2,19 +2,17 @@
pragma solidity ^0.8.0;
/**
* @dev Implementation contract with an admin() function made to clash with
* @dev TransparentUpgradeableProxy's to test correct functioning of the
* @dev Transparent Proxy feature.
*/
contract ClashingImplementation {
function admin() external pure returns (address) {
return 0x0000000000000000000000000000000011111142;
}
function admin() external pure returns (address) {
return 0x0000000000000000000000000000000011111142;
}
function delegatedFunction() external pure returns (bool) {
return true;
}
function delegatedFunction() external pure returns (bool) {
return true;
}
}

View File

@ -11,16 +11,20 @@ contract ClonesMock {
event NewInstance(address instance);
function clone(address master, bytes calldata initdata) public payable {
_initAndEmit(master.clone(), initdata);
function clone(address implementation, bytes calldata initdata) public payable {
_initAndEmit(implementation.clone(), initdata);
}
function cloneDeterministic(address master, bytes32 salt, bytes calldata initdata) public payable {
_initAndEmit(master.cloneDeterministic(salt), initdata);
function cloneDeterministic(
address implementation,
bytes32 salt,
bytes calldata initdata
) public payable {
_initAndEmit(implementation.cloneDeterministic(salt), initdata);
}
function predictDeterministicAddress(address master, bytes32 salt) public view returns (address predicted) {
return master.predictDeterministicAddress(salt);
function predictDeterministicAddress(address implementation, bytes32 salt) public view returns (address predicted) {
return implementation.predictDeterministicAddress(salt);
}
function _initAndEmit(address instance, bytes memory initdata) private {

View File

@ -23,7 +23,11 @@ contract ContextMockCaller {
context.msgSender();
}
function callData(ContextMock context, uint256 integerValue, string memory stringValue) public {
function callData(
ContextMock context,
uint256 integerValue,
string memory stringValue
) public {
context.msgData(integerValue, stringValue);
}
}

View File

@ -20,4 +20,8 @@ contract CountersImpl {
function decrement() public {
_counter.decrement();
}
function reset() public {
_counter.reset();
}
}

View File

@ -6,12 +6,15 @@ import "../utils/Create2.sol";
import "../utils/introspection/ERC1820Implementer.sol";
contract Create2Impl {
function deploy(uint256 value, bytes32 salt, bytes memory code) public {
function deploy(
uint256 value,
bytes32 salt,
bytes memory code
) public {
Create2.deploy(value, salt, code);
}
function deployERC1820Implementer(uint256 value, bytes32 salt) public {
// solhint-disable-next-line indent
Create2.deploy(value, salt, type(ERC1820Implementer).creationCode);
}
@ -19,7 +22,11 @@ contract Create2Impl {
return Create2.computeAddress(salt, codeHash);
}
function computeAddressWithDeployer(bytes32 salt, bytes32 codeHash, address deployer) public pure returns (address) {
function computeAddressWithDeployer(
bytes32 salt,
bytes32 codeHash,
address deployer
) public pure returns (address) {
return Create2.computeAddress(salt, codeHash, deployer);
}

View File

@ -3,55 +3,59 @@
pragma solidity ^0.8.0;
abstract contract Impl {
function version() public pure virtual returns (string memory);
function version() public pure virtual returns (string memory);
}
contract DummyImplementation {
uint256 public value;
string public text;
uint256[] public values;
uint256 public value;
string public text;
uint256[] public values;
function initializeNonPayable() public {
value = 10;
}
function initializeNonPayable() public {
value = 10;
}
function initializePayable() public payable {
value = 100;
}
function initializePayable() public payable {
value = 100;
}
function initializeNonPayableWithValue(uint256 _value) public {
value = _value;
}
function initializeNonPayableWithValue(uint256 _value) public {
value = _value;
}
function initializePayableWithValue(uint256 _value) public payable {
value = _value;
}
function initializePayableWithValue(uint256 _value) public payable {
value = _value;
}
function initialize(uint256 _value, string memory _text, uint256[] memory _values) public {
value = _value;
text = _text;
values = _values;
}
function initialize(
uint256 _value,
string memory _text,
uint256[] memory _values
) public {
value = _value;
text = _text;
values = _values;
}
function get() public pure returns (bool) {
return true;
}
function get() public pure returns (bool) {
return true;
}
function version() public pure virtual returns (string memory) {
return "V1";
}
function version() public pure virtual returns (string memory) {
return "V1";
}
function reverts() public pure {
require(false, "DummyImplementation reverted");
}
function reverts() public pure {
require(false, "DummyImplementation reverted");
}
}
contract DummyImplementationV2 is DummyImplementation {
function migrate(uint256 newVal) public payable {
value = newVal;
}
function migrate(uint256 newVal) public payable {
value = newVal;
}
function version() public pure override returns (string memory) {
return "V2";
}
function version() public pure override returns (string memory) {
return "V2";
}
}

View File

@ -6,12 +6,36 @@ import "../utils/cryptography/ECDSA.sol";
contract ECDSAMock {
using ECDSA for bytes32;
using ECDSA for bytes;
function recover(bytes32 hash, bytes memory signature) public pure returns (address) {
return hash.recover(signature);
}
// solhint-disable-next-line func-name-mixedcase
function recover_v_r_s(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) public pure returns (address) {
return hash.recover(v, r, s);
}
// solhint-disable-next-line func-name-mixedcase
function recover_r_vs(
bytes32 hash,
bytes32 r,
bytes32 vs
) public pure returns (address) {
return hash.recover(r, vs);
}
function toEthSignedMessageHash(bytes32 hash) public pure returns (bytes32) {
return hash.toEthSignedMessageHash();
}
function toEthSignedMessageHash(bytes memory s) public pure returns (bytes32) {
return s.toEthSignedMessageHash();
}
}

View File

@ -12,12 +12,15 @@ contract EIP712External is EIP712 {
return _domainSeparatorV4();
}
function verify(bytes memory signature, address signer, address mailTo, string memory mailContents) external view {
bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
keccak256("Mail(address to,string contents)"),
mailTo,
keccak256(bytes(mailContents))
)));
function verify(
bytes memory signature,
address signer,
address mailTo,
string memory mailContents
) external view {
bytes32 digest = _hashTypedDataV4(
keccak256(abi.encode(keccak256("Mail(address to,string contents)"), mailTo, keccak256(bytes(mailContents))))
);
address recoveredSigner = ECDSA.recover(digest, signature);
require(recoveredSigner == signer);
}

View File

@ -5,9 +5,14 @@ pragma solidity ^0.8.0;
import "../token/ERC1155/extensions/ERC1155Burnable.sol";
contract ERC1155BurnableMock is ERC1155Burnable {
constructor(string memory uri) ERC1155(uri) { }
constructor(string memory uri) ERC1155(uri) {}
function mint(address to, uint256 id, uint256 value, bytes memory data) public {
function mint(
address to,
uint256 id,
uint256 value,
bytes memory data
) public {
_mint(to, id, value, data);
}
}

View File

@ -9,27 +9,43 @@ import "../token/ERC1155/ERC1155.sol";
* This mock just publicizes internal functions for testing purposes
*/
contract ERC1155Mock is ERC1155 {
constructor (string memory uri) ERC1155(uri) {
// solhint-disable-previous-line no-empty-blocks
}
constructor(string memory uri) ERC1155(uri) {}
function setURI(string memory newuri) public {
_setURI(newuri);
}
function mint(address to, uint256 id, uint256 value, bytes memory data) public {
function mint(
address to,
uint256 id,
uint256 value,
bytes memory data
) public {
_mint(to, id, value, data);
}
function mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) public {
function mintBatch(
address to,
uint256[] memory ids,
uint256[] memory values,
bytes memory data
) public {
_mintBatch(to, ids, values, data);
}
function burn(address owner, uint256 id, uint256 value) public {
function burn(
address owner,
uint256 id,
uint256 value
) public {
_burn(owner, id, value);
}
function burnBatch(address owner, uint256[] memory ids, uint256[] memory values) public {
function burnBatch(
address owner,
uint256[] memory ids,
uint256[] memory values
) public {
_burnBatch(owner, ids, values);
}
}

View File

@ -6,7 +6,7 @@ import "./ERC1155Mock.sol";
import "../token/ERC1155/extensions/ERC1155Pausable.sol";
contract ERC1155PausableMock is ERC1155Mock, ERC1155Pausable {
constructor(string memory uri) ERC1155Mock(uri) { }
constructor(string memory uri) ERC1155Mock(uri) {}
function pause() external {
_pause();
@ -23,9 +23,7 @@ contract ERC1155PausableMock is ERC1155Mock, ERC1155Pausable {
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
)
internal virtual override(ERC1155, ERC1155Pausable)
{
) internal virtual override(ERC1155, ERC1155Pausable) {
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
}
}

View File

@ -5,7 +5,7 @@ pragma solidity ^0.8.0;
import "../token/ERC1155/IERC1155Receiver.sol";
import "../utils/introspection/ERC165.sol";
contract ERC1155ReceiverMock is IERC1155Receiver, ERC165 {
contract ERC1155ReceiverMock is ERC165, IERC1155Receiver {
bytes4 private _recRetval;
bool private _recReverts;
bytes4 private _batRetval;
@ -14,13 +14,12 @@ contract ERC1155ReceiverMock is IERC1155Receiver, ERC165 {
event Received(address operator, address from, uint256 id, uint256 value, bytes data, uint256 gas);
event BatchReceived(address operator, address from, uint256[] ids, uint256[] values, bytes data, uint256 gas);
constructor (
constructor(
bytes4 recRetval,
bool recReverts,
bytes4 batRetval,
bool batReverts
)
{
) {
_recRetval = recRetval;
_recReverts = recReverts;
_batRetval = batRetval;
@ -33,11 +32,7 @@ contract ERC1155ReceiverMock is IERC1155Receiver, ERC165 {
uint256 id,
uint256 value,
bytes calldata data
)
external
override
returns(bytes4)
{
) external override returns (bytes4) {
require(!_recReverts, "ERC1155ReceiverMock: reverting on receive");
emit Received(operator, from, id, value, data, gasleft());
return _recRetval;
@ -49,11 +44,7 @@ contract ERC1155ReceiverMock is IERC1155Receiver, ERC165 {
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
)
external
override
returns(bytes4)
{
) external override returns (bytes4) {
require(!_batReverts, "ERC1155ReceiverMock: reverting on batch receive");
emit BatchReceived(operator, from, ids, values, data, gasleft());
return _batRetval;

View File

@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ERC1155Mock.sol";
import "../token/ERC1155/extensions/ERC1155Supply.sol";
contract ERC1155SupplyMock is ERC1155Mock, ERC1155Supply {
constructor(string memory uri) ERC1155Mock(uri) {}
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual override(ERC1155, ERC1155Supply) {
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
}
}

View File

@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../access/Ownable.sol";
import "../interfaces/IERC1271.sol";
import "../utils/cryptography/ECDSA.sol";
contract ERC1271WalletMock is Ownable, IERC1271 {
constructor(address originalOwner) {
transferOwnership(originalOwner);
}
function isValidSignature(bytes32 hash, bytes memory signature) public view override returns (bytes4 magicValue) {
return ECDSA.recover(hash, signature) == owner() ? this.isValidSignature.selector : bytes4(0);
}
}

View File

@ -29,7 +29,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 {
* @dev A contract implementing SupportsInterfaceWithLookup
* implement ERC165 itself.
*/
constructor () {
constructor() {
_registerInterface(INTERFACE_ID_ERC165);
}
@ -50,7 +50,7 @@ contract SupportsInterfaceWithLookupMock is IERC165 {
}
contract ERC165InterfacesSupported is SupportsInterfaceWithLookupMock {
constructor (bytes4[] memory interfaceIds) {
constructor(bytes4[] memory interfaceIds) {
for (uint256 i = 0; i < interfaceIds.length; i++) {
_registerInterface(interfaceIds[i]);
}

View File

@ -2,4 +2,4 @@
pragma solidity ^0.8.0;
contract ERC165NotSupported { }
contract ERC165NotSupported {}

View File

@ -4,5 +4,4 @@ pragma solidity ^0.8.0;
import "../utils/introspection/ERC165.sol";
contract ERC165Mock is ERC165 {
}
contract ERC165Mock is ERC165 {}

View File

@ -5,7 +5,7 @@ pragma solidity ^0.8.0;
import "../token/ERC20/extensions/ERC20Burnable.sol";
contract ERC20BurnableMock is ERC20Burnable {
constructor (
constructor(
string memory name,
string memory symbol,
address initialAccount,

View File

@ -5,9 +5,11 @@ pragma solidity ^0.8.0;
import "../token/ERC20/extensions/ERC20Capped.sol";
contract ERC20CappedMock is ERC20Capped {
constructor (string memory name, string memory symbol, uint256 cap)
ERC20(name, symbol) ERC20Capped(cap)
{ }
constructor(
string memory name,
string memory symbol,
uint256 cap
) ERC20(name, symbol) ERC20Capped(cap) {}
function mint(address to, uint256 tokenId) public {
_mint(to, tokenId);

View File

@ -5,9 +5,13 @@ pragma solidity ^0.8.0;
import "../token/ERC20/ERC20.sol";
contract ERC20DecimalsMock is ERC20 {
uint8 immutable private _decimals;
uint8 private immutable _decimals;
constructor (string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_
) ERC20(name_, symbol_) {
_decimals = decimals_;
}

View File

@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../token/ERC20/extensions/ERC20FlashMint.sol";
contract ERC20FlashMintMock is ERC20FlashMint {
constructor(
string memory name,
string memory symbol,
address initialAccount,
uint256 initialBalance
) ERC20(name, symbol) {
_mint(initialAccount, initialBalance);
}
}

View File

@ -6,7 +6,7 @@ import "../token/ERC20/ERC20.sol";
// mock class using ERC20
contract ERC20Mock is ERC20 {
constructor (
constructor(
string memory name,
string memory symbol,
address initialAccount,
@ -23,11 +23,19 @@ contract ERC20Mock is ERC20 {
_burn(account, amount);
}
function transferInternal(address from, address to, uint256 value) public {
function transferInternal(
address from,
address to,
uint256 value
) public {
_transfer(from, to, value);
}
function approveInternal(address owner, address spender, uint256 value) public {
function approveInternal(
address owner,
address spender,
uint256 value
) public {
_approve(owner, spender, value);
}
}

View File

@ -6,7 +6,7 @@ import "../token/ERC20/extensions/ERC20Pausable.sol";
// mock class using ERC20Pausable
contract ERC20PausableMock is ERC20Pausable {
constructor (
constructor(
string memory name,
string memory symbol,
address initialAccount,

View File

@ -2,11 +2,10 @@
pragma solidity ^0.8.0;
import "../token/ERC20/extensions/draft-ERC20Permit.sol";
contract ERC20PermitMock is ERC20Permit {
constructor (
constructor(
string memory name,
string memory symbol,
address initialAccount,

View File

@ -4,7 +4,6 @@ pragma solidity ^0.8.0;
import "../token/ERC20/extensions/ERC20Snapshot.sol";
contract ERC20SnapshotMock is ERC20Snapshot {
constructor(
string memory name,

View File

@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../token/ERC20/extensions/ERC20VotesComp.sol";
contract ERC20VotesCompMock is ERC20VotesComp {
constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {}
function mint(address account, uint256 amount) public {
_mint(account, amount);
}
function burn(address account, uint256 amount) public {
_burn(account, amount);
}
function getChainId() external view returns (uint256) {
return block.chainid;
}
}

View File

@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../token/ERC20/extensions/ERC20Votes.sol";
contract ERC20VotesMock is ERC20Votes {
constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {}
function mint(address account, uint256 amount) public {
_mint(account, amount);
}
function burn(address account, uint256 amount) public {
_burn(account, amount);
}
function getChainId() external view returns (uint256) {
return block.chainid;
}
}

View File

@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../token/ERC20/extensions/ERC20Wrapper.sol";
contract ERC20WrapperMock is ERC20Wrapper {
constructor(
IERC20 _underlyingToken,
string memory name,
string memory symbol
) ERC20(name, symbol) ERC20Wrapper(_underlyingToken) {}
function recover(address account) public returns (uint256) {
return _recover(account);
}
}

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