Compare commits
169 Commits
v3.0.0
...
v3.3.0-rc.
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fccf6fa53 | |||
| 7f8fc584de | |||
| 1d1d2ba661 | |||
| 3881175d72 | |||
| f7bb84ce4c | |||
| c67d81bae1 | |||
| a5d1ac7ed0 | |||
| 877f440331 | |||
| 90ed1af972 | |||
| 21344b91ed | |||
| fce2513827 | |||
| 3debb8820e | |||
| d3a4e31fe2 | |||
| 25ac33486c | |||
| 5803e11663 | |||
| b33372cc92 | |||
| bcb2b5d1cd | |||
| 3d2e5c0310 | |||
| f547b6ff27 | |||
| 5272799bdd | |||
| 1a230e3aa5 | |||
| 679b7d147c | |||
| 8effd1e02a | |||
| cb19930b83 | |||
| c6b07b33c5 | |||
| 47e37975c9 | |||
| 5472eedbad | |||
| af95fe7a93 | |||
| 705b0b0001 | |||
| 35c931126b | |||
| 6aada9d356 | |||
| da9161fc91 | |||
| 1e78adc28c | |||
| fcdf8f4618 | |||
| 8533499507 | |||
| fb4659c5d7 | |||
| f06738828b | |||
| 0c27ecc536 | |||
| e5fbbda9ba | |||
| ba125961d6 | |||
| 2bb06b1af4 | |||
| 8108f2f9b9 | |||
| 08dfaab829 | |||
| d1c121b599 | |||
| e98b187e64 | |||
| 87326f7313 | |||
| 7f3eee750a | |||
| ace35fdeda | |||
| bf4c9d700d | |||
| c7d99531a7 | |||
| ca7ee098ca | |||
| 1229c28ce0 | |||
| 09d437c1f9 | |||
| 492d4ac013 | |||
| 1ada3b633e | |||
| 45b81c969f | |||
| cfb7f80003 | |||
| ae4e9845de | |||
| 95dc7525ac | |||
| f1cce7e223 | |||
| f2fb8cf23b | |||
| 9f900f6dba | |||
| 91f16a7e47 | |||
| 6bc2ae3731 | |||
| 885b76f66f | |||
| ded2b0a55c | |||
| 0f08b1d099 | |||
| aaa5ef81cf | |||
| cb791a1b21 | |||
| 0b489f4d79 | |||
| 1f06fd7e66 | |||
| e5da0986bb | |||
| 0fc9578fe6 | |||
| b1ea59e814 | |||
| 7d48d79b53 | |||
| 6d5a73815d | |||
| d1f336d8fd | |||
| 9700e6b4bd | |||
| 722879b32d | |||
| 943a663a31 | |||
| 09014f90f9 | |||
| 0c667ca32a | |||
| 7c4a2a0a29 | |||
| c801c8d2bb | |||
| 98e862e162 | |||
| b9d72d2991 | |||
| c6612871fb | |||
| b991fca341 | |||
| ef3bbbcf40 | |||
| 32f0fe5d08 | |||
| 6d987f1418 | |||
| de99bccbfd | |||
| 0cc882ef9d | |||
| 3f4420527b | |||
| 21d06999f6 | |||
| f3803d3a5d | |||
| c6da044dc5 | |||
| 02a6b05bde | |||
| 242400e9ea | |||
| 8c1daaab57 | |||
| 7f62c8e145 | |||
| e2876b947d | |||
| ed3a513f86 | |||
| b72088a90a | |||
| 8b58fc7191 | |||
| d9fa59f30a | |||
| 13e2132b69 | |||
| 298e1b5fdc | |||
| 5294f3b9b7 | |||
| b191e67552 | |||
| fac773ac99 | |||
| 82769e54c3 | |||
| 022f2bc177 | |||
| ccf79ee483 | |||
| ecf0725dd1 | |||
| d3ef93a9a5 | |||
| 47a7a575e8 | |||
| ff8fe4be7e | |||
| d7a6e7be2e | |||
| a81e948fc9 | |||
| ccfd370b89 | |||
| 91516b2318 | |||
| 52f7b6e03b | |||
| 64ab594ad6 | |||
| 394987f365 | |||
| df4b317fb3 | |||
| 142f6c3f05 | |||
| 414adb94f0 | |||
| 7ee98cf525 | |||
| d418da6b91 | |||
| 2a0f2a8ba8 | |||
| 5513dfd3cf | |||
| c18ffd7c81 | |||
| 424ab2a024 | |||
| e2b97d6712 | |||
| 217a616fde | |||
| 56de324afe | |||
| fa36244bec | |||
| 4fe31f8d4d | |||
| cfa9ad9943 | |||
| fd981ad315 | |||
| 5f9a86a8f2 | |||
| 956d6632d9 | |||
| 0c7b2ec09e | |||
| 4cbcaf35e4 | |||
| 73baf0b635 | |||
| 78dc37739f | |||
| ac0a4327a9 | |||
| c20e620a06 | |||
| 4bc45e35c2 | |||
| b362e886ec | |||
| ca38899ede | |||
| 61973af29f | |||
| 087d314daf | |||
| 6e3de4d48a | |||
| dc3f92210b | |||
| 1ff8a97d11 | |||
| dd226e1987 | |||
| d0f67f99a7 | |||
| e156b617b9 | |||
| 837828967a | |||
| 3843c9beb7 | |||
| c75b016919 | |||
| ad290e7181 | |||
| 364da52a49 | |||
| e50e496f5b | |||
| c4be4d16e8 | |||
| 6f40ed3fbf | |||
| 57551c8516 |
@ -1,84 +0,0 @@
|
||||
version: 2
|
||||
# 2.1 does not yet support local run
|
||||
# unless with workaround. For simplicity just use it.
|
||||
# https://github.com/CircleCI-Public/circleci-cli/issues/79
|
||||
|
||||
aliases:
|
||||
- &defaults
|
||||
docker:
|
||||
- image: circleci/node:10
|
||||
|
||||
- &cache_key_node_modules
|
||||
key: v1-node_modules-{{ checksum "package-lock.json" }}
|
||||
|
||||
jobs:
|
||||
dependencies:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
<<: *cache_key_node_modules
|
||||
- run:
|
||||
name: Install npm dependencies and prepare
|
||||
command: |
|
||||
if [ ! -d node_modules ]; then
|
||||
npm ci
|
||||
else
|
||||
npm run prepare
|
||||
fi
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- node_modules
|
||||
- build
|
||||
- save_cache:
|
||||
paths:
|
||||
- node_modules
|
||||
<<: *cache_key_node_modules
|
||||
|
||||
lint:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Linter
|
||||
command: npm run lint
|
||||
test:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Unit tests
|
||||
command: npm run test
|
||||
|
||||
coverage:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Unit tests with coverage report
|
||||
command: npm run coverage
|
||||
|
||||
# TODO(xinbenlv, #1839): run SOLC_NIGHTLY to be run but allow it to fail.
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
everything:
|
||||
jobs:
|
||||
- dependencies
|
||||
- lint:
|
||||
requires:
|
||||
- dependencies
|
||||
- test:
|
||||
requires:
|
||||
- dependencies
|
||||
- coverage:
|
||||
requires:
|
||||
- dependencies
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
version: 1
|
||||
|
||||
update_configs:
|
||||
- package_manager: "javascript"
|
||||
directory: "/"
|
||||
update_schedule: "weekly"
|
||||
version_requirement_updates: "increase_versions"
|
||||
@ -8,7 +8,7 @@ charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
trim_trailing_whitespace = false
|
||||
max_line_length = 120
|
||||
|
||||
[*.sol]
|
||||
@ -16,3 +16,6 @@ indent_size = 4
|
||||
|
||||
[*.js]
|
||||
indent_size = 2
|
||||
|
||||
[*.adoc]
|
||||
max_line_length = 0
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
"contract": false,
|
||||
"assert": false,
|
||||
"web3": false,
|
||||
"usePlugin": false,
|
||||
"extendEnvironment": false,
|
||||
},
|
||||
"rules": {
|
||||
|
||||
|
||||
45
.github/workflows/test.yml
vendored
Normal file
45
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release-v*
|
||||
pull_request: {}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10.x
|
||||
- uses: actions/cache@v2
|
||||
id: cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: npm-v2-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: npm-v2-
|
||||
- run: npm ci
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- run: npm run lint
|
||||
- run: npm run test
|
||||
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10.x
|
||||
- uses: actions/cache@v2
|
||||
id: cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: npm-v2-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: npm-v2-
|
||||
- run: npm ci
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- run: npm run coverage
|
||||
- uses: codecov/codecov-action@v1
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@ -50,3 +50,10 @@ contracts/README.md
|
||||
|
||||
# temporary artifact from solidity-coverage
|
||||
allFiredEvents
|
||||
.coverage_artifacts
|
||||
.coverage_cache
|
||||
.coverage_contracts
|
||||
|
||||
# buidler
|
||||
cache
|
||||
artifacts
|
||||
|
||||
3
.mocharc.js
Normal file
3
.mocharc.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
timeout: 4000,
|
||||
};
|
||||
@ -4,5 +4,8 @@ module.exports = {
|
||||
compileCommand: 'npm run compile',
|
||||
skipFiles: [
|
||||
'mocks',
|
||||
]
|
||||
],
|
||||
providerOptions: {
|
||||
default_balance_ether: '10000000000000000000000000',
|
||||
},
|
||||
}
|
||||
|
||||
@ -4,7 +4,9 @@
|
||||
"func-order": "off",
|
||||
"mark-callable-contracts": "off",
|
||||
"no-empty-blocks": "off",
|
||||
"compiler-version": ["error", "^0.6.0"],
|
||||
"private-vars-leading-underscore": "error"
|
||||
"compiler-version": "off",
|
||||
"private-vars-leading-underscore": "error",
|
||||
"reason-string": "off",
|
||||
"func-visibility": ["error", { "ignoreConstructors": true }]
|
||||
}
|
||||
}
|
||||
|
||||
60
CHANGELOG.md
60
CHANGELOG.md
@ -1,5 +1,60 @@
|
||||
# Changelog
|
||||
|
||||
## 3.3.0
|
||||
|
||||
* Now supports both Solidity 0.6 and 0.7. Compiling with solc 0.7 will result in warnings. Install the `solc-0.7` tag to compile without warnings.
|
||||
* `Address`: added `functionStaticCall`, similar to the existing `functionCall`. ([#2333](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2333))
|
||||
* `TimelockController`: added a contract to augment access control schemes with a delay. ([#2354](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2354))
|
||||
* `EnumerableSet`: added `Bytes32Set`, for sets of `bytes32`. ([#2395](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2395))
|
||||
|
||||
## 3.2.0 (2020-09-10)
|
||||
|
||||
### New features
|
||||
* Proxies: added the proxy contracts from OpenZeppelin SDK. ([#2335](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2335))
|
||||
|
||||
#### Proxy changes with respect to OpenZeppelin SDK
|
||||
|
||||
Aside from upgrading them from Solidity 0.5 to 0.6, we've changed a few minor things from the proxy contracts as they were found in OpenZeppelin SDK.
|
||||
|
||||
- `UpgradeabilityProxy` was renamed to `UpgradeableProxy`.
|
||||
- `AdminUpgradeabilityProxy` was renamed to `TransparentUpgradeableProxy`.
|
||||
- `Proxy._willFallback` was renamed to `Proxy._beforeFallback`.
|
||||
- `UpgradeabilityProxy._setImplementation` and `AdminUpgradeabilityProxy._setAdmin` were made private.
|
||||
|
||||
### Improvements
|
||||
* `Address.isContract`: switched from `extcodehash` to `extcodesize` for less gas usage. ([#2311](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2311))
|
||||
|
||||
### Breaking changes
|
||||
* `ERC20Snapshot`: switched to using `_beforeTokenTransfer` hook instead of overriding ERC20 operations. ([#2312](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2312))
|
||||
|
||||
This small change in the way we implemented `ERC20Snapshot` may affect users who are combining this contract with
|
||||
other ERC20 flavors, since it no longer overrides `_transfer`, `_mint`, and `_burn`. This can result in having to remove Solidity `override(...)` specifiers in derived contracts for these functions, and to instead have to add it for `_beforeTokenTransfer`. See [Using Hooks](https://docs.openzeppelin.com/contracts/3.x/extending-contracts#using-hooks) in the documentation.
|
||||
|
||||
## 3.1.0 (2020-06-23)
|
||||
|
||||
### New features
|
||||
* `SafeCast`: added functions to downcast signed integers (e.g. `toInt32`), improving usability of `SignedSafeMath`. ([#2243](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2243))
|
||||
* `functionCall`: new helpers that replicate Solidity's function call semantics, reducing the need to rely on `call`. ([#2264](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2264))
|
||||
* `ERC1155`: added support for a base implementation, non-standard extensions and a preset contract. ([#2014](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2014), [#2230](https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2230))
|
||||
|
||||
### Improvements
|
||||
* `ReentrancyGuard`: reduced overhead of using the `nonReentrant` modifier. ([#2171](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2171))
|
||||
* `AccessControl`: added a `RoleAdminChanged` event to `_setAdminRole`. ([#2214](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2214))
|
||||
* Made all `public` functions in the token preset contracts `virtual`. ([#2257](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2257))
|
||||
|
||||
### Deprecations
|
||||
* `SafeERC20`: deprecated `safeApprove`. ([#2268](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2268))
|
||||
|
||||
## 3.0.2 (2020-06-08)
|
||||
|
||||
### Improvements
|
||||
* Added SPX license identifier to all contracts. ([#2235](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2235))
|
||||
|
||||
## 3.0.1 (2020-04-27)
|
||||
|
||||
### Bugfixes
|
||||
* `ERC777`: fixed the `_approve` internal function not validating some of their arguments for non-zero addresses. ([#2213](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2213))
|
||||
|
||||
## 3.0.0 (2020-04-20)
|
||||
|
||||
### New features
|
||||
@ -37,6 +92,11 @@
|
||||
* `ERC20`: added a constructor for `name` and `symbol`. `decimals` now defaults to 18. ([#2161](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2161))
|
||||
* `Strings`: renamed `fromUint256` to `toString` ([#2188](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2188))
|
||||
|
||||
## 2.5.1 (2020-04-24)
|
||||
|
||||
### Bugfixes
|
||||
* `ERC777`: fixed the `_send` and `_approve` internal functions not validating some of their arguments for non-zero addresses. ([#2212](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2212))
|
||||
|
||||
## 2.5.0 (2020-02-04)
|
||||
|
||||
### New features
|
||||
|
||||
@ -1,69 +0,0 @@
|
||||
# Code Style
|
||||
|
||||
We value clean code and consistency, and those are prerequisites for us to
|
||||
include new code in the repository. Before proposing a change, please read this
|
||||
document and take some time to familiarize yourself with the style of the
|
||||
existing codebase.
|
||||
|
||||
## Solidity code
|
||||
|
||||
In order to be consistent with all the other Solidity projects, we follow the
|
||||
[official recommendations documented in the Solidity style guide](http://solidity.readthedocs.io/en/latest/style-guide.html).
|
||||
|
||||
Any exception or additions specific to our project are documented below.
|
||||
|
||||
### Naming
|
||||
|
||||
* Try to avoid acronyms and abbreviations.
|
||||
|
||||
* All state variables should be private.
|
||||
|
||||
* Private state variables should have an underscore prefix.
|
||||
|
||||
```
|
||||
contract TestContract {
|
||||
uint256 private _privateVar;
|
||||
uint256 internal _internalVar;
|
||||
}
|
||||
```
|
||||
|
||||
* Parameters must not be prefixed with an underscore.
|
||||
|
||||
```
|
||||
function test(uint256 testParameter1, uint256 testParameter2) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
* Internal and private functions should have an underscore prefix.
|
||||
|
||||
```
|
||||
function _testInternal() internal {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
function _testPrivate() private {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
* Events should be emitted immediately after the state change that they
|
||||
represent, and consequently they should be named in past tense.
|
||||
|
||||
```
|
||||
function _burn(address _who, uint256 _value) internal {
|
||||
super._burn(_who, _value);
|
||||
emit TokensBurned(_who, _value);
|
||||
}
|
||||
```
|
||||
|
||||
Some standards (e.g. ERC20) use present tense, and in those cases the
|
||||
standard specification prevails.
|
||||
|
||||
* Interface names should have a capital I prefix.
|
||||
|
||||
```
|
||||
interface IERC777 {
|
||||
```
|
||||
@ -44,13 +44,6 @@ npm test
|
||||
npm run lint
|
||||
```
|
||||
|
||||
or you can simply run CircleCI locally
|
||||
```bash
|
||||
circleci local execute --job build
|
||||
circleci local execute --job test
|
||||
```
|
||||
*Note*: requires installing CircleCI and docker locally on your machine.
|
||||
|
||||
5) Go to [github.com/OpenZeppelin/openzeppelin-contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) in your web browser and issue a new pull request.
|
||||
|
||||
*IMPORTANT* Read the PR template very carefully and make sure to follow all the instructions. These instructions
|
||||
|
||||
@ -10,7 +10,7 @@ program that extracts the API Reference from source code.
|
||||
|
||||
The [`docs.openzeppelin.com`](https://github.com/OpenZeppelin/docs.openzeppelin.com)
|
||||
repository hosts the configuration for the entire site, which includes
|
||||
documetation for all of the OpenZeppelin projects.
|
||||
documentation for all of the OpenZeppelin projects.
|
||||
|
||||
To run the docs locally you should run `npm run docs start` on this
|
||||
To run the docs locally you should run `npm run docs:watch` on this
|
||||
repository.
|
||||
|
||||
@ -28,37 +28,78 @@ Consistency on the way classes are used is paramount to an easier understanding
|
||||
#### D6 - Regular Audits
|
||||
Following good programming practices is a way to reduce the risk of vulnerabilities, but professional code audits are still needed. We will perform regular code audits on major releases, and hire security professionals to provide independent review.
|
||||
|
||||
## Style Guidelines
|
||||
# Style Guidelines
|
||||
|
||||
The design guidelines have quite a high abstraction level. These style guidelines are more concrete and easier to apply, and also more opinionated.
|
||||
The design guidelines have quite a high abstraction level. These style guidelines are more concrete and easier to apply, and also more opinionated. We value clean code and consistency, and those are prerequisites for us to include new code in the repository. Before proposing a change, please read these guidelines and take some time to familiarize yourself with the style of the existing codebase.
|
||||
|
||||
### General
|
||||
## Solidity code
|
||||
|
||||
#### G0 - Default to Solidity's official style guide.
|
||||
In order to be consistent with all the other Solidity projects, we follow the
|
||||
[official recommendations documented in the Solidity style guide](http://solidity.readthedocs.io/en/latest/style-guide.html).
|
||||
|
||||
Follow the official Solidity style guide: https://solidity.readthedocs.io/en/latest/style-guide.html
|
||||
Any exception or additions specific to our project are documented below.
|
||||
|
||||
#### G1 - No Magic Constants
|
||||
* Try to avoid acronyms and abbreviations.
|
||||
|
||||
Avoid constants in the code as much as possible. Magic strings are also magic constants.
|
||||
* All state variables should be private.
|
||||
|
||||
#### G2 - Code that Fails Early
|
||||
* Private state variables should have an underscore prefix.
|
||||
|
||||
We ask our code to fail as soon as possible when an unexpected input was provided or unexpected state was found.
|
||||
```
|
||||
contract TestContract {
|
||||
uint256 private _privateVar;
|
||||
uint256 internal _internalVar;
|
||||
}
|
||||
```
|
||||
|
||||
#### G3 - Internal Amounts Must be Signed Integers and Represent the Smallest Units.
|
||||
* Parameters must not be prefixed with an underscore.
|
||||
|
||||
Avoid representation errors by always dealing with weis when handling ether. GUIs can convert to more human-friendly representations. Use Signed Integers (int) to prevent underflow problems.
|
||||
```
|
||||
function test(uint256 testParameter1, uint256 testParameter2) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
* Internal and private functions should have an underscore prefix.
|
||||
|
||||
```
|
||||
function _testInternal() internal {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
function _testPrivate() private {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
* Events should be emitted immediately after the state change that they
|
||||
represent, and consequently they should be named in past tense.
|
||||
|
||||
```
|
||||
function _burn(address who, uint256 value) internal {
|
||||
super._burn(who, value);
|
||||
emit TokensBurned(who, value);
|
||||
}
|
||||
```
|
||||
|
||||
Some standards (e.g. ERC20) use present tense, and in those cases the
|
||||
standard specification prevails.
|
||||
|
||||
* Interface names should have a capital I prefix.
|
||||
|
||||
```
|
||||
interface IERC777 {
|
||||
```
|
||||
|
||||
|
||||
### Testing
|
||||
## Tests
|
||||
|
||||
#### T1 - Tests Must be Written Elegantly
|
||||
* Tests Must be Written Elegantly
|
||||
|
||||
Style guidelines are not relaxed for tests. Tests are a good way to show how to use the library, and maintaining them is extremely necessary.
|
||||
Tests are a good way to show how to use the library, and maintaining them is extremely necessary. Don't write long tests, write helper functions to make them be as short and concise as possible (they should take just a few lines each), and use good variable names.
|
||||
|
||||
Don't write long tests, write helper functions to make them be as short and concise as possible (they should take just a few lines each), and use good variable names.
|
||||
* Tests Must not be Random
|
||||
|
||||
#### T2 - Tests Must not be Random
|
||||
|
||||
Inputs for tests should not be generated randomly. Accounts used to create test contracts are an exception, those can be random. Also, the type and structure of outputs should be checked.
|
||||
Inputs for tests should not be generated randomly. Accounts used to create test contracts are an exception, those can be random. Also, the type and structure of outputs should be checked.
|
||||
|
||||
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016-2019 zOS Global Limited
|
||||
Copyright (c) 2016-2020 zOS Global Limited
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
17
README.md
17
README.md
@ -1,7 +1,7 @@
|
||||
# <img src="logo.png" alt="OpenZeppelin" height="40px">
|
||||
# <img src="logo.svg" alt="OpenZeppelin" height="40px">
|
||||
|
||||
[](https://docs.openzeppelin.com/contracts)
|
||||
[](https://www.npmjs.org/package/@openzeppelin/contracts)
|
||||
[](https://circleci.com/gh/OpenZeppelin/openzeppelin-contracts)
|
||||
[](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts)
|
||||
|
||||
**A library for secure smart contract development.** Build on a solid foundation of community-vetted code.
|
||||
@ -10,7 +10,7 @@
|
||||
* 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 by leading security firms.
|
||||
* [Audited](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/audit) by leading security firms (_last full audit on v2.0.0_).
|
||||
|
||||
## Overview
|
||||
|
||||
@ -27,13 +27,12 @@ OpenZeppelin Contracts features a [stable API](https://docs.openzeppelin.com/con
|
||||
Once installed, you can use the contracts in the library by importing them:
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.5.0;
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC721/ERC721Full.sol";
|
||||
import "@openzeppelin/contracts/token/ERC721/ERC721Mintable.sol";
|
||||
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
||||
|
||||
contract MyNFT is ERC721Full, ERC721Mintable {
|
||||
constructor() ERC721Full("MyNFT", "MNFT") public {
|
||||
contract MyCollectible is ERC721 {
|
||||
constructor() ERC721("MyCollectible", "MCO") public {
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -44,7 +43,7 @@ To keep your system secure, you should **always** use the installed code as-is,
|
||||
|
||||
## Learn More
|
||||
|
||||
The guides in the sidebar will teach about different concepts, and how to use the related contracts that OpenZeppelin Contracts provides:
|
||||
The guides in the [docs site](https://docs.openzeppelin.com/contracts) will teach about different concepts, and how to use the related contracts that OpenZeppelin Contracts provides:
|
||||
|
||||
* [Access Control](https://docs.openzeppelin.com/contracts/access-control): decide who can perform each of the actions on your system.
|
||||
* [Tokens](https://docs.openzeppelin.com/contracts/tokens): create tradeable assets or collectives, and distribute them via [Crowdsales](https://docs.openzeppelin.com/contracts/crowdsales).
|
||||
|
||||
20
buidler.config.js
Normal file
20
buidler.config.js
Normal file
@ -0,0 +1,20 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
usePlugin('solidity-coverage');
|
||||
usePlugin('@nomiclabs/buidler-truffle5');
|
||||
|
||||
for (const f of fs.readdirSync(path.join(__dirname, 'buidler'))) {
|
||||
require(path.join(__dirname, 'buidler', f));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
networks: {
|
||||
buidlerevm: {
|
||||
blockGasLimit: 10000000,
|
||||
},
|
||||
},
|
||||
solc: {
|
||||
version: '0.6.12',
|
||||
},
|
||||
};
|
||||
10
buidler/env-contract.js
Normal file
10
buidler/env-contract.js
Normal file
@ -0,0 +1,10 @@
|
||||
extendEnvironment(env => {
|
||||
const { contract } = env;
|
||||
|
||||
env.contract = function (name, body) {
|
||||
// remove the default account from the accounts list used in tests, in order
|
||||
// to protect tests against accidentally passing due to the contract
|
||||
// deployer being used subsequently as function caller
|
||||
contract(name, accounts => body(accounts.slice(1)));
|
||||
};
|
||||
});
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/*
|
||||
* @dev Provides information about the current execution context, including the
|
||||
@ -10,11 +12,7 @@ pragma solidity ^0.6.0;
|
||||
*
|
||||
* This contract is only required for intermediate, library-like contracts.
|
||||
*/
|
||||
contract Context {
|
||||
// Empty internal constructor, to prevent people from mistakenly deploying
|
||||
// an instance of this contract, which should be used via inheritance.
|
||||
constructor () internal { }
|
||||
|
||||
abstract contract Context {
|
||||
function _msgSender() internal view virtual returns (address payable) {
|
||||
return msg.sender;
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "./IRelayRecipient.sol";
|
||||
import "./IRelayHub.sol";
|
||||
@ -113,7 +115,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
/**
|
||||
* @dev See `IRelayRecipient.preRelayedCall`.
|
||||
*
|
||||
* This function should not be overriden directly, use `_preRelayedCall` instead.
|
||||
* This function should not be overridden directly, use `_preRelayedCall` instead.
|
||||
*
|
||||
* * Requirements:
|
||||
*
|
||||
@ -136,7 +138,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
/**
|
||||
* @dev See `IRelayRecipient.postRelayedCall`.
|
||||
*
|
||||
* This function should not be overriden directly, use `_postRelayedCall` instead.
|
||||
* This function should not be overridden directly, use `_postRelayedCall` instead.
|
||||
*
|
||||
* * Requirements:
|
||||
*
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "./GSNRecipient.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
@ -84,6 +86,8 @@ contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
|
||||
// The maximum token charge is pre-charged from the user
|
||||
_token.safeTransferFrom(from, address(this), maxPossibleCharge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "./GSNRecipient.sol";
|
||||
import "../cryptography/ECDSA.sol";
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Interface for `RelayHub`, the core contract of the GSN. Users should not need to interact with this contract
|
||||
@ -39,7 +41,7 @@ interface IRelayHub {
|
||||
function registerRelay(uint256 transactionFee, string calldata url) external;
|
||||
|
||||
/**
|
||||
* @dev Emitted when a relay is registered or re-registerd. Looking at these events (and filtering out
|
||||
* @dev Emitted when a relay is registered or re-registered. Looking at these events (and filtering out
|
||||
* {RelayRemoved} events) lets a client discover the list of available relays.
|
||||
*/
|
||||
event RelayAdded(address indexed relay, address indexed owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url);
|
||||
@ -103,7 +105,7 @@ interface IRelayHub {
|
||||
event Deposited(address indexed recipient, address indexed from, uint256 amount);
|
||||
|
||||
/**
|
||||
* @dev Returns an account's deposits. These can be either a contracts's funds, or a relay owner's revenue.
|
||||
* @dev Returns an account's deposits. These can be either a contract's funds, or a relay owner's revenue.
|
||||
*/
|
||||
function balanceOf(address target) external view returns (uint256);
|
||||
|
||||
@ -178,7 +180,7 @@ interface IRelayHub {
|
||||
* - `gasLimit`: gas to forward when calling the encoded function
|
||||
* - `nonce`: client's nonce
|
||||
* - `signature`: client's signature over all previous params, plus the relay and RelayHub addresses
|
||||
* - `approvalData`: dapp-specific data forwared to {acceptRelayedCall}. This value is *not* verified by the
|
||||
* - `approvalData`: dapp-specific data forwarded to {acceptRelayedCall}. This value is *not* verified by the
|
||||
* `RelayHub`, but it still can be used for e.g. a signature.
|
||||
*
|
||||
* Emits a {TransactionRelayed} event.
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Base interface for a contract that will be called via the GSN from {IRelayHub}.
|
||||
@ -51,7 +53,7 @@ interface IRelayRecipient {
|
||||
*
|
||||
* Returns a value to be passed to {postRelayedCall}.
|
||||
*
|
||||
* {preRelayedCall} is called with 100k gas: if it runs out during exection or otherwise reverts, the relayed call
|
||||
* {preRelayedCall} is called with 100k gas: if it runs out during execution or otherwise reverts, the relayed call
|
||||
* will not be executed, but the recipient will still be charged for the transaction's cost.
|
||||
*/
|
||||
function preRelayedCall(bytes calldata context) external returns (bytes32);
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
= Gas Station Network (GSN)
|
||||
|
||||
[.readme-notice]
|
||||
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/gsn
|
||||
|
||||
This set of contracts provide all the tools required to make a contract callable via the https://gsn.openzeppelin.com[Gas Station Network].
|
||||
|
||||
TIP: If you're new to the GSN, head over to our xref:learn::sending-gasless-transactions.adoc[overview of the system] and basic guide to xref:ROOT:gsn.adoc[creating a GSN-capable contract].
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/EnumerableSet.sol";
|
||||
import "../utils/Address.sol";
|
||||
@ -21,7 +23,7 @@ import "../GSN/Context.sol";
|
||||
*
|
||||
* ```
|
||||
* function foo() public {
|
||||
* require(hasRole(MY_ROLE, _msgSender()));
|
||||
* require(hasRole(MY_ROLE, msg.sender));
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
@ -34,6 +36,10 @@ import "../GSN/Context.sol";
|
||||
* that only accounts with this role will be able to grant or revoke other
|
||||
* roles. More complex role relationships can be created by using
|
||||
* {_setRoleAdmin}.
|
||||
*
|
||||
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
|
||||
* grant and revoke this role. Extra precautions should be taken to secure
|
||||
* accounts that have been granted it.
|
||||
*/
|
||||
abstract contract AccessControl is Context {
|
||||
using EnumerableSet for EnumerableSet.AddressSet;
|
||||
@ -48,6 +54,16 @@ abstract contract AccessControl is Context {
|
||||
|
||||
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
|
||||
|
||||
/**
|
||||
* @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`.
|
||||
*
|
||||
@ -179,8 +195,11 @@ abstract contract AccessControl is Context {
|
||||
|
||||
/**
|
||||
* @dev Sets `adminRole` as ``role``'s admin role.
|
||||
*
|
||||
* Emits a {RoleAdminChanged} event.
|
||||
*/
|
||||
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
|
||||
emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
|
||||
_roles[role].adminRole = adminRole;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
/**
|
||||
@ -13,7 +15,7 @@ import "../GSN/Context.sol";
|
||||
* `onlyOwner`, which can be applied to your functions to restrict their use to
|
||||
* the owner.
|
||||
*/
|
||||
contract Ownable is Context {
|
||||
abstract contract Ownable is Context {
|
||||
address private _owner;
|
||||
|
||||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
|
||||
|
||||
@ -1,9 +1,94 @@
|
||||
= Access
|
||||
|
||||
Contract modules for authorization and access control mechanisms.
|
||||
[.readme-notice]
|
||||
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/access
|
||||
|
||||
== Contracts
|
||||
This directory provides ways to restrict who can access the functions of a contract or when they can do it.
|
||||
|
||||
- {AccessControl} provides a general role based access control mechanism. Multiple hierarchical roles can be created and assigned each to multiple accounts.
|
||||
- {Ownable} is a simpler mechanism with a single owner "role" that can be assigned to a single account. This simpler mechanism can be useful for quick tests but projects with production concerns are likely to outgrow it.
|
||||
- {TimelockController} is used in combination with one of the above two mechanisms. By assigning a role to an instance of the `TimelockController` contract, the access to the functions controlled by that role will be delayed by some amount of time.
|
||||
|
||||
== Authorization
|
||||
|
||||
{{Ownable}}
|
||||
|
||||
{{AccessControl}}
|
||||
|
||||
== Timelock
|
||||
|
||||
{{TimelockController}}
|
||||
|
||||
==== Terminology
|
||||
|
||||
* *Operation:* A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution (see xref:access-control.adoc#operation_lifecycle[operation lifecycle]). If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content.
|
||||
* *Operation status:*
|
||||
** *Unset:* An operation that is not part of the timelock mechanism.
|
||||
** *Pending:* An operation that has been scheduled, before the timer expires.
|
||||
** *Ready:* An operation that has been scheduled, after the timer expires.
|
||||
** *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*:
|
||||
** *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.
|
||||
|
||||
==== 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.
|
||||
|
||||
Both operations contain:
|
||||
|
||||
* *Target*, the address of the smart contract that the timelock should operate on.
|
||||
* *Value*, in wei, that should be sent with the transaction. Most of the time this will be 0. Ether can be deposited before-end or passed along when executing the transaction.
|
||||
* *Data*, containing the encoded function selector and parameters of the call. This can be produced using a number of tools. For example, a maintenance operation granting role `ROLE` to `ACCOUNT` can be encode using web3js as follows:
|
||||
|
||||
```javascript
|
||||
const data = timelock.contract.methods.grantRole(ROLE, ACCOUNT).encodeABI()
|
||||
```
|
||||
|
||||
* *Predecessor*, that specifies a dependency between operations. This dependency is optional. Use `bytes32(0)` if the operation does not have any dependency.
|
||||
* *Salt*, used to disambiguate two otherwise identical operations. This can be any random value.
|
||||
|
||||
In the case of batched operations, `target`, `value` and `data` are specified as arrays, which must be of the same length.
|
||||
|
||||
==== Operation lifecycle
|
||||
|
||||
Timelocked operations are identified by a unique id (their hash) and follow a specific lifecycle:
|
||||
|
||||
`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.
|
||||
* 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.
|
||||
|
||||
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)`]
|
||||
|
||||
==== Roles
|
||||
|
||||
===== Admin
|
||||
|
||||
The admins are in charge of managing proposers and executors. For the timelock to be self-governed, this role should only be given to the timelock itself. Upon deployment, both the timelock and the deployer have this role. After further configuration and testing, the deployer can renounce this role such that all further maintenance operations have to go through the timelock process.
|
||||
|
||||
This role is identified by the *TIMELOCK_ADMIN_ROLE* value: `0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5`
|
||||
|
||||
===== Proposer
|
||||
|
||||
The proposers are in charge of scheduling (and cancelling) operations. This is a critical role, that should be given to governing entities. This could be an EOA, a multisig, or a DAO.
|
||||
|
||||
WARNING: *Proposer fight:* Having multiple proposers, while providing redundancy in case one becomes unavailable, can be dangerous. As proposer have their say on all operations, they could cancel operations they disagree with, including operations to remove them for the proposers.
|
||||
|
||||
This role is identified by the *PROPOSER_ROLE* value: `0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1`
|
||||
|
||||
===== 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.
|
||||
|
||||
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.
|
||||
|
||||
281
contracts/access/TimelockController.sol
Normal file
281
contracts/access/TimelockController.sol
Normal file
@ -0,0 +1,281 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.9 <0.8.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./../math/SafeMath.sol";
|
||||
import "./AccessControl.sol";
|
||||
|
||||
/**
|
||||
* @dev Contract module which acts as a timelocked controller. When set as the
|
||||
* owner of an `Ownable` smart contract, it enforces a timelock on all
|
||||
* `onlyOwner` maintenance operations. This gives time for users of the
|
||||
* controlled contract to exit before a potentially dangerous maintenance
|
||||
* operation is applied.
|
||||
*
|
||||
* By default, this contract is self administered, meaning administration tasks
|
||||
* have to go through the timelock process. The proposer (resp executor) role
|
||||
* is in charge of proposing (resp executing) operations. A common use case is
|
||||
* to position this {TimelockController} as the owner of a smart contract, with
|
||||
* a multisig or a DAO as the sole proposer.
|
||||
*/
|
||||
contract TimelockController is AccessControl {
|
||||
|
||||
bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE");
|
||||
bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
|
||||
bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
|
||||
uint256 internal constant _DONE_TIMESTAMP = uint256(1);
|
||||
|
||||
mapping(bytes32 => uint256) private _timestamps;
|
||||
uint256 private _minDelay;
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @dev Emitted when a call is performed as part of operation `id`.
|
||||
*/
|
||||
event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);
|
||||
|
||||
/**
|
||||
* @dev Emitted when operation `id` is cancelled.
|
||||
*/
|
||||
event Cancelled(bytes32 indexed id);
|
||||
|
||||
/**
|
||||
* @dev Emitted when the minimum delay for future operations is modified.
|
||||
*/
|
||||
event MinDelayChange(uint256 oldDuration, uint256 newDuration);
|
||||
|
||||
/**
|
||||
* @dev Initializes the contract with a given `minDelay`.
|
||||
*/
|
||||
constructor(uint256 minDelay, address[] memory proposers, address[] memory executors) public {
|
||||
_setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);
|
||||
_setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);
|
||||
_setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);
|
||||
|
||||
// deployer + self administration
|
||||
_setupRole(TIMELOCK_ADMIN_ROLE, _msgSender());
|
||||
_setupRole(TIMELOCK_ADMIN_ROLE, address(this));
|
||||
|
||||
// register proposers
|
||||
for (uint256 i = 0; i < proposers.length; ++i) {
|
||||
_setupRole(PROPOSER_ROLE, proposers[i]);
|
||||
}
|
||||
|
||||
// register executors
|
||||
for (uint256 i = 0; i < executors.length; ++i) {
|
||||
_setupRole(EXECUTOR_ROLE, executors[i]);
|
||||
}
|
||||
|
||||
_minDelay = minDelay;
|
||||
emit MinDelayChange(0, minDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Modifier to make a function callable only by a certain role. In
|
||||
* addition to checking the sender's role, `address(0)` 's role is also
|
||||
* 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");
|
||||
_;
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Contract might receive/hold ETH as part of the maintenance process.
|
||||
*/
|
||||
receive() external payable {}
|
||||
|
||||
/**
|
||||
* @dev Returns whether an operation is pending or not.
|
||||
*/
|
||||
function isOperationPending(bytes32 id) public view returns (bool pending) {
|
||||
return _timestamps[id] > _DONE_TIMESTAMP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns whether an operation is ready or not.
|
||||
*/
|
||||
function isOperationReady(bytes32 id) public view returns (bool ready) {
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
return _timestamps[id] > _DONE_TIMESTAMP && _timestamps[id] <= block.timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns whether an operation is done or not.
|
||||
*/
|
||||
function isOperationDone(bytes32 id) public view returns (bool done) {
|
||||
return _timestamps[id] == _DONE_TIMESTAMP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the timestamp at with an operation becomes ready (0 for
|
||||
* unset operations, 1 for done operations).
|
||||
*/
|
||||
function getTimestamp(bytes32 id) public view returns (uint256 timestamp) {
|
||||
return _timestamps[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the minimum delay for an operation to become valid.
|
||||
*/
|
||||
function getMinDelay() public view returns (uint256 duration) {
|
||||
return _minDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 returns (bytes32 hash) {
|
||||
return keccak256(abi.encode(target, value, data, predecessor, salt));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 returns (bytes32 hash) {
|
||||
return keccak256(abi.encode(targets, values, datas, predecessor, salt));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Schedule an operation containing a single transaction.
|
||||
*
|
||||
* Emits a {CallScheduled} event.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - 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) {
|
||||
bytes32 id = hashOperation(target, value, data, predecessor, salt);
|
||||
_schedule(id, delay);
|
||||
emit CallScheduled(id, 0, target, value, data, predecessor, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Schedule an operation containing a batch of transactions.
|
||||
*
|
||||
* Emits one {CallScheduled} event per transaction in the batch.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - 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) {
|
||||
require(targets.length == values.length, "TimelockController: length mismatch");
|
||||
require(targets.length == datas.length, "TimelockController: length mismatch");
|
||||
|
||||
bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
|
||||
_schedule(id, delay);
|
||||
for (uint256 i = 0; i < targets.length; ++i) {
|
||||
emit CallScheduled(id, i, targets[i], values[i], datas[i], predecessor, delay);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Schedule an operation that is to becomes valid after a given delay.
|
||||
*/
|
||||
function _schedule(bytes32 id, uint256 delay) private {
|
||||
require(_timestamps[id] == 0, "TimelockController: operation already scheduled");
|
||||
require(delay >= _minDelay, "TimelockController: insufficient delay");
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
_timestamps[id] = SafeMath.add(block.timestamp, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Cancel an operation.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must have the 'proposer' role.
|
||||
*/
|
||||
function cancel(bytes32 id) public virtual onlyRole(PROPOSER_ROLE) {
|
||||
require(isOperationPending(id), "TimelockController: operation cannot be cancelled");
|
||||
delete _timestamps[id];
|
||||
|
||||
emit Cancelled(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Execute an (ready) operation containing a single transaction.
|
||||
*
|
||||
* Emits a {CallExecuted} event.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - 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) {
|
||||
bytes32 id = hashOperation(target, value, data, predecessor, salt);
|
||||
_beforeCall(predecessor);
|
||||
_call(id, 0, target, value, data);
|
||||
_afterCall(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Execute an (ready) operation containing a batch of transactions.
|
||||
*
|
||||
* Emits one {CallExecuted} event per transaction in the batch.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - 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) {
|
||||
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);
|
||||
for (uint256 i = 0; i < targets.length; ++i) {
|
||||
_call(id, i, targets[i], values[i], datas[i]);
|
||||
}
|
||||
_afterCall(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks before execution of an operation's calls.
|
||||
*/
|
||||
function _beforeCall(bytes32 predecessor) private view {
|
||||
require(predecessor == bytes32(0) || isOperationDone(predecessor), "TimelockController: missing dependency");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks after execution of an operation's calls.
|
||||
*/
|
||||
function _afterCall(bytes32 id) private {
|
||||
require(isOperationReady(id), "TimelockController: operation is not ready");
|
||||
_timestamps[id] = _DONE_TIMESTAMP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Execute an operation's call.
|
||||
*
|
||||
* 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);
|
||||
require(success, "TimelockController: underlying transaction reverted");
|
||||
|
||||
emit CallExecuted(id, index, target, value, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Changes the timelock duration for future operations.
|
||||
*
|
||||
* Emits a {MinDelayChange} event.
|
||||
*/
|
||||
function updateDelay(uint256 newDelay) external virtual {
|
||||
require(msg.sender == address(this), "TimelockController: caller must be timelock");
|
||||
emit MinDelayChange(_minDelay, newDelay);
|
||||
_minDelay = newDelay;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
|
||||
@ -50,13 +52,8 @@ library ECDSA {
|
||||
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
|
||||
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
|
||||
// these malleable signatures as well.
|
||||
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
|
||||
revert("ECDSA: invalid signature 's' value");
|
||||
}
|
||||
|
||||
if (v != 27 && v != 28) {
|
||||
revert("ECDSA: invalid signature 'v' value");
|
||||
}
|
||||
require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value");
|
||||
require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");
|
||||
|
||||
// If the signature is valid (and not malleable), return the signer address
|
||||
address signer = ecrecover(hash, v, r, s);
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev These functions deal with verification of Merkle trees (hash trees),
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
= Cryptography
|
||||
|
||||
[.readme-notice]
|
||||
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/cryptography
|
||||
|
||||
This collection of libraries provides simple and safe ways to use different cryptographic primitives.
|
||||
|
||||
== Libraries
|
||||
|
||||
@ -1,174 +0,0 @@
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
import "../access/Ownable.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
/**
|
||||
* @title TokenVesting
|
||||
* @dev A token holder contract that can release its token balance gradually like a
|
||||
* typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
|
||||
* owner.
|
||||
*/
|
||||
contract TokenVesting is Ownable {
|
||||
// The vesting schedule is time-based (i.e. using block timestamps as opposed to e.g. block numbers), and is
|
||||
// therefore sensitive to timestamp manipulation (which is something miners can do, to a certain degree). Therefore,
|
||||
// it is recommended to avoid using short time durations (less than a minute). Typical vesting schemes, with a
|
||||
// cliff period of a year and a duration of four years, are safe to use.
|
||||
// solhint-disable not-rely-on-time
|
||||
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
event TokensReleased(address token, uint256 amount);
|
||||
event TokenVestingRevoked(address token);
|
||||
|
||||
// beneficiary of tokens after they are released
|
||||
address private _beneficiary;
|
||||
|
||||
// Durations and timestamps are expressed in UNIX time, the same units as block.timestamp.
|
||||
uint256 private _cliff;
|
||||
uint256 private _start;
|
||||
uint256 private _duration;
|
||||
|
||||
bool private _revocable;
|
||||
|
||||
mapping (address => uint256) private _released;
|
||||
mapping (address => bool) private _revoked;
|
||||
|
||||
/**
|
||||
* @dev Creates a vesting contract that vests its balance of any ERC20 token to the
|
||||
* beneficiary, gradually in a linear fashion until start + duration. By then all
|
||||
* of the balance will have vested.
|
||||
* @param beneficiary address of the beneficiary to whom vested tokens are transferred
|
||||
* @param cliffDuration duration in seconds of the cliff in which tokens will begin to vest
|
||||
* @param start the time (as Unix time) at which point vesting starts
|
||||
* @param duration duration in seconds of the period in which the tokens will vest
|
||||
* @param revocable whether the vesting is revocable or not
|
||||
*/
|
||||
constructor (address beneficiary, uint256 start, uint256 cliffDuration, uint256 duration, bool revocable) public {
|
||||
require(beneficiary != address(0), "TokenVesting: beneficiary is the zero address");
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(cliffDuration <= duration, "TokenVesting: cliff is longer than duration");
|
||||
require(duration > 0, "TokenVesting: duration is 0");
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(start.add(duration) > block.timestamp, "TokenVesting: final time is before current time");
|
||||
|
||||
_beneficiary = beneficiary;
|
||||
_revocable = revocable;
|
||||
_duration = duration;
|
||||
_cliff = start.add(cliffDuration);
|
||||
_start = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the beneficiary of the tokens.
|
||||
*/
|
||||
function beneficiary() public view returns (address) {
|
||||
return _beneficiary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cliff time of the token vesting.
|
||||
*/
|
||||
function cliff() public view returns (uint256) {
|
||||
return _cliff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the start time of the token vesting.
|
||||
*/
|
||||
function start() public view returns (uint256) {
|
||||
return _start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the duration of the token vesting.
|
||||
*/
|
||||
function duration() public view returns (uint256) {
|
||||
return _duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the vesting is revocable.
|
||||
*/
|
||||
function revocable() public view returns (bool) {
|
||||
return _revocable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the amount of the token released.
|
||||
*/
|
||||
function released(address token) public view returns (uint256) {
|
||||
return _released[token];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the token is revoked.
|
||||
*/
|
||||
function revoked(address token) public view returns (bool) {
|
||||
return _revoked[token];
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Transfers vested tokens to beneficiary.
|
||||
* @param token ERC20 token which is being vested
|
||||
*/
|
||||
function release(IERC20 token) public {
|
||||
uint256 unreleased = _releasableAmount(token);
|
||||
|
||||
require(unreleased > 0, "TokenVesting: no tokens are due");
|
||||
|
||||
_released[address(token)] = _released[address(token)].add(unreleased);
|
||||
|
||||
token.safeTransfer(_beneficiary, unreleased);
|
||||
|
||||
emit TokensReleased(address(token), unreleased);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Allows the owner to revoke the vesting. Tokens already vested
|
||||
* remain in the contract, the rest are returned to the owner.
|
||||
* @param token ERC20 token which is being vested
|
||||
*/
|
||||
function revoke(IERC20 token) public onlyOwner {
|
||||
require(_revocable, "TokenVesting: cannot revoke");
|
||||
require(!_revoked[address(token)], "TokenVesting: token already revoked");
|
||||
|
||||
uint256 balance = token.balanceOf(address(this));
|
||||
|
||||
uint256 unreleased = _releasableAmount(token);
|
||||
uint256 refund = balance.sub(unreleased);
|
||||
|
||||
_revoked[address(token)] = true;
|
||||
|
||||
token.safeTransfer(owner(), refund);
|
||||
|
||||
emit TokenVestingRevoked(address(token));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates the amount that has already vested but hasn't been released yet.
|
||||
* @param token ERC20 token which is being vested
|
||||
*/
|
||||
function _releasableAmount(IERC20 token) private view returns (uint256) {
|
||||
return _vestedAmount(token).sub(_released[address(token)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates the amount that has already vested.
|
||||
* @param token ERC20 token which is being vested
|
||||
*/
|
||||
function _vestedAmount(IERC20 token) private view returns (uint256) {
|
||||
uint256 currentBalance = token.balanceOf(address(this));
|
||||
uint256 totalBalance = currentBalance.add(_released[address(token)]);
|
||||
|
||||
if (block.timestamp < _cliff) {
|
||||
return 0;
|
||||
} else if (block.timestamp >= _start.add(_duration) || _revoked[address(token)]) {
|
||||
return totalBalance;
|
||||
} else {
|
||||
return totalBalance.mul(block.timestamp.sub(_start)).div(_duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "./IERC165.sol";
|
||||
|
||||
@ -8,7 +10,7 @@ import "./IERC165.sol";
|
||||
* Contracts may inherit from this and call {_registerInterface} to declare
|
||||
* their support of an interface.
|
||||
*/
|
||||
contract ERC165 is IERC165 {
|
||||
abstract contract ERC165 is IERC165 {
|
||||
/*
|
||||
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
|
||||
*/
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.2;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.2 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Library used to query support of an interface declared via {IERC165}.
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "./IERC1820Implementer.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Interface of the ERC165 standard, as defined in the
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Interface for an ERC1820 implementer, as defined in the
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Interface of the global ERC1820 Registry, as defined in the
|
||||
@ -57,7 +59,7 @@ interface IERC1820Registry {
|
||||
* queried for support, unless `implementer` is the caller. See
|
||||
* {IERC1820Implementer-canImplementInterfaceForAddress}.
|
||||
*/
|
||||
function setInterfaceImplementer(address account, bytes32 interfaceHash, address implementer) external;
|
||||
function setInterfaceImplementer(address account, bytes32 _interfaceHash, address implementer) external;
|
||||
|
||||
/**
|
||||
* @dev Returns the implementer of `interfaceHash` for `account`. If no such
|
||||
@ -68,7 +70,7 @@ interface IERC1820Registry {
|
||||
*
|
||||
* `account` being the zero address is an alias for the caller's address.
|
||||
*/
|
||||
function getInterfaceImplementer(address account, bytes32 interfaceHash) external view returns (address);
|
||||
function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address);
|
||||
|
||||
/**
|
||||
* @dev Returns the interface hash for an `interfaceName`, as defined in the
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
= Introspection
|
||||
|
||||
[.readme-notice]
|
||||
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/introspection
|
||||
|
||||
This set of interfaces and contracts deal with https://en.wikipedia.org/wiki/Type_introspection[type introspection] of contracts, that is, examining which functions can be called on them. This is usually referred to as a contract's _interface_.
|
||||
|
||||
Ethereum contracts have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. `ERC20` tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract _declaring_ its interface can be very helpful in preventing errors.
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Standard math utilities missing in the Solidity language.
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
= Math
|
||||
|
||||
[.readme-notice]
|
||||
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/math
|
||||
|
||||
These are math-related utilities.
|
||||
|
||||
== Libraries
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Wrappers over Solidity's arithmetic operations with added overflow
|
||||
@ -21,6 +23,7 @@ library SafeMath {
|
||||
* Counterpart to Solidity's `+` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Addition cannot overflow.
|
||||
*/
|
||||
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
@ -37,6 +40,7 @@ library SafeMath {
|
||||
* Counterpart to Solidity's `-` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Subtraction cannot overflow.
|
||||
*/
|
||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
@ -50,6 +54,7 @@ library SafeMath {
|
||||
* Counterpart to Solidity's `-` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Subtraction cannot overflow.
|
||||
*/
|
||||
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
|
||||
@ -66,6 +71,7 @@ library SafeMath {
|
||||
* Counterpart to Solidity's `*` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Multiplication cannot overflow.
|
||||
*/
|
||||
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
@ -91,6 +97,7 @@ library SafeMath {
|
||||
* uses an invalid opcode to revert (consuming all remaining gas).
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - The divisor cannot be zero.
|
||||
*/
|
||||
function div(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
@ -106,10 +113,10 @@ library SafeMath {
|
||||
* uses an invalid opcode to revert (consuming all remaining gas).
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - The divisor cannot be zero.
|
||||
*/
|
||||
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
|
||||
// Solidity only automatically asserts when dividing by 0
|
||||
require(b > 0, errorMessage);
|
||||
uint256 c = a / b;
|
||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
||||
@ -126,6 +133,7 @@ library SafeMath {
|
||||
* invalid opcode to revert (consuming all remaining gas).
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - The divisor cannot be zero.
|
||||
*/
|
||||
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
@ -141,6 +149,7 @@ library SafeMath {
|
||||
* invalid opcode to revert (consuming all remaining gas).
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - The divisor cannot be zero.
|
||||
*/
|
||||
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @title SignedSafeMath
|
||||
@ -8,7 +10,14 @@ library SignedSafeMath {
|
||||
int256 constant private _INT256_MIN = -2**255;
|
||||
|
||||
/**
|
||||
* @dev Multiplies two signed integers, reverts on overflow.
|
||||
* @dev Returns the multiplication of two signed integers, reverting on
|
||||
* overflow.
|
||||
*
|
||||
* Counterpart to Solidity's `*` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Multiplication cannot overflow.
|
||||
*/
|
||||
function mul(int256 a, int256 b) internal pure returns (int256) {
|
||||
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
|
||||
@ -27,7 +36,16 @@ library SignedSafeMath {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
|
||||
* @dev Returns the integer division of two signed integers. Reverts on
|
||||
* division by zero. The result is rounded towards zero.
|
||||
*
|
||||
* Counterpart to Solidity's `/` operator. Note: this function uses a
|
||||
* `revert` opcode (which leaves remaining gas untouched) while Solidity
|
||||
* uses an invalid opcode to revert (consuming all remaining gas).
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - The divisor cannot be zero.
|
||||
*/
|
||||
function div(int256 a, int256 b) internal pure returns (int256) {
|
||||
require(b != 0, "SignedSafeMath: division by zero");
|
||||
@ -39,7 +57,14 @@ library SignedSafeMath {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Subtracts two signed integers, reverts on overflow.
|
||||
* @dev Returns the subtraction of two signed integers, reverting on
|
||||
* overflow.
|
||||
*
|
||||
* Counterpart to Solidity's `-` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Subtraction cannot overflow.
|
||||
*/
|
||||
function sub(int256 a, int256 b) internal pure returns (int256) {
|
||||
int256 c = a - b;
|
||||
@ -49,7 +74,14 @@ library SignedSafeMath {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Adds two signed integers, reverts on overflow.
|
||||
* @dev Returns the addition of two signed integers, reverting on
|
||||
* overflow.
|
||||
*
|
||||
* Counterpart to Solidity's `+` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Addition cannot overflow.
|
||||
*/
|
||||
function add(int256 a, int256 b) internal pure returns (int256) {
|
||||
int256 c = a + b;
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../access/AccessControl.sol";
|
||||
|
||||
|
||||
@ -1,8 +1,14 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Address.sol";
|
||||
|
||||
contract AddressImpl {
|
||||
string public sharedAnswer;
|
||||
|
||||
event CallReturnValue(string data);
|
||||
|
||||
function isContract(address account) external view returns (bool) {
|
||||
return Address.isContract(account);
|
||||
}
|
||||
@ -11,6 +17,21 @@ contract AddressImpl {
|
||||
Address.sendValue(receiver, amount);
|
||||
}
|
||||
|
||||
function functionCall(address target, bytes calldata data) external {
|
||||
bytes memory returnData = Address.functionCall(target, data);
|
||||
emit CallReturnValue(abi.decode(returnData, (string)));
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
function functionStaticCall(address target, bytes calldata data) external {
|
||||
bytes memory returnData = Address.functionStaticCall(target, data);
|
||||
emit CallReturnValue(abi.decode(returnData, (string)));
|
||||
}
|
||||
|
||||
// sendValue's tests require the contract to hold Ether
|
||||
receive () external payable { }
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Arrays.sol";
|
||||
|
||||
|
||||
50
contracts/mocks/CallReceiverMock.sol
Normal file
50
contracts/mocks/CallReceiverMock.sol
Normal file
@ -0,0 +1,50 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
contract CallReceiverMock {
|
||||
string public sharedAnswer;
|
||||
|
||||
event MockFunctionCalled();
|
||||
|
||||
uint256[] private _array;
|
||||
|
||||
function mockFunction() public payable returns (string memory) {
|
||||
emit MockFunctionCalled();
|
||||
|
||||
return "0x1234";
|
||||
}
|
||||
|
||||
function mockFunctionNonPayable() public returns (string memory) {
|
||||
emit MockFunctionCalled();
|
||||
|
||||
return "0x1234";
|
||||
}
|
||||
|
||||
function mockStaticFunction() public pure returns (string memory) {
|
||||
return "0x1234";
|
||||
}
|
||||
|
||||
function mockFunctionRevertsNoReason() public payable {
|
||||
revert();
|
||||
}
|
||||
|
||||
function mockFunctionRevertsReason() public payable {
|
||||
revert("CallReceiverMock: reverting");
|
||||
}
|
||||
|
||||
function mockFunctionThrows() public payable {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
function mockFunctionOutOfGas() public payable {
|
||||
for (uint256 i = 0; ; ++i) {
|
||||
_array.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
function mockFunctionWritesStorage() public returns (string memory) {
|
||||
sharedAnswer = "42";
|
||||
return "0x1234";
|
||||
}
|
||||
}
|
||||
20
contracts/mocks/ClashingImplementation.sol
Normal file
20
contracts/mocks/ClashingImplementation.sol
Normal file
@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <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 delegatedFunction() external pure returns (bool) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../payment/escrow/ConditionalEscrow.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Counters.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Create2.sol";
|
||||
import "../introspection/ERC1820Implementer.sol";
|
||||
@ -21,5 +23,5 @@ contract Create2Impl {
|
||||
return Create2.computeAddress(salt, codeHash, deployer);
|
||||
}
|
||||
|
||||
receive() payable external {}
|
||||
receive() external payable {}
|
||||
}
|
||||
|
||||
57
contracts/mocks/DummyImplementation.sol
Normal file
57
contracts/mocks/DummyImplementation.sol
Normal file
@ -0,0 +1,57 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
abstract contract Impl {
|
||||
function version() public pure virtual returns (string memory);
|
||||
}
|
||||
|
||||
contract DummyImplementation {
|
||||
uint256 public value;
|
||||
string public text;
|
||||
uint256[] public values;
|
||||
|
||||
function initializeNonPayable() public {
|
||||
value = 10;
|
||||
}
|
||||
|
||||
function initializePayable() public payable {
|
||||
value = 100;
|
||||
}
|
||||
|
||||
function initializeNonPayable(uint256 _value) public {
|
||||
value = _value;
|
||||
}
|
||||
|
||||
function initializePayable(uint256 _value) public payable {
|
||||
value = _value;
|
||||
}
|
||||
|
||||
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 version() public pure virtual returns (string memory) {
|
||||
return "V1";
|
||||
}
|
||||
|
||||
function reverts() public pure {
|
||||
require(false);
|
||||
}
|
||||
}
|
||||
|
||||
contract DummyImplementationV2 is DummyImplementation {
|
||||
function migrate(uint256 newVal) public payable {
|
||||
value = newVal;
|
||||
}
|
||||
|
||||
function version() public pure override returns (string memory) {
|
||||
return "V2";
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../cryptography/ECDSA.sol";
|
||||
|
||||
|
||||
13
contracts/mocks/ERC1155BurnableMock.sol
Normal file
13
contracts/mocks/ERC1155BurnableMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC1155/ERC1155Burnable.sol";
|
||||
|
||||
contract ERC1155BurnableMock is ERC1155Burnable {
|
||||
constructor(string memory uri) public ERC1155(uri) { }
|
||||
|
||||
function mint(address to, uint256 id, uint256 value, bytes memory data) public {
|
||||
_mint(to, id, value, data);
|
||||
}
|
||||
}
|
||||
35
contracts/mocks/ERC1155Mock.sol
Normal file
35
contracts/mocks/ERC1155Mock.sol
Normal file
@ -0,0 +1,35 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC1155/ERC1155.sol";
|
||||
|
||||
/**
|
||||
* @title ERC1155Mock
|
||||
* This mock just publicizes internal functions for testing purposes
|
||||
*/
|
||||
contract ERC1155Mock is ERC1155 {
|
||||
constructor (string memory uri) public ERC1155(uri) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
function setURI(string memory newuri) public {
|
||||
_setURI(newuri);
|
||||
}
|
||||
|
||||
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 {
|
||||
_mintBatch(to, ids, values, data);
|
||||
}
|
||||
|
||||
function burn(address owner, uint256 id, uint256 value) public {
|
||||
_burn(owner, id, value);
|
||||
}
|
||||
|
||||
function burnBatch(address owner, uint256[] memory ids, uint256[] memory values) public {
|
||||
_burnBatch(owner, ids, values);
|
||||
}
|
||||
}
|
||||
31
contracts/mocks/ERC1155PausableMock.sol
Normal file
31
contracts/mocks/ERC1155PausableMock.sol
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "./ERC1155Mock.sol";
|
||||
import "../token/ERC1155/ERC1155Pausable.sol";
|
||||
|
||||
contract ERC1155PausableMock is ERC1155Mock, ERC1155Pausable {
|
||||
constructor(string memory uri) public ERC1155Mock(uri) { }
|
||||
|
||||
function pause() external {
|
||||
_pause();
|
||||
}
|
||||
|
||||
function unpause() external {
|
||||
_unpause();
|
||||
}
|
||||
|
||||
function _beforeTokenTransfer(
|
||||
address operator,
|
||||
address from,
|
||||
address to,
|
||||
uint256[] memory ids,
|
||||
uint256[] memory amounts,
|
||||
bytes memory data
|
||||
)
|
||||
internal virtual override(ERC1155, ERC1155Pausable)
|
||||
{
|
||||
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
|
||||
}
|
||||
}
|
||||
62
contracts/mocks/ERC1155ReceiverMock.sol
Normal file
62
contracts/mocks/ERC1155ReceiverMock.sol
Normal file
@ -0,0 +1,62 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC1155/IERC1155Receiver.sol";
|
||||
import "./ERC165Mock.sol";
|
||||
|
||||
contract ERC1155ReceiverMock is IERC1155Receiver, ERC165Mock {
|
||||
bytes4 private _recRetval;
|
||||
bool private _recReverts;
|
||||
bytes4 private _batRetval;
|
||||
bool private _batReverts;
|
||||
|
||||
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 (
|
||||
bytes4 recRetval,
|
||||
bool recReverts,
|
||||
bytes4 batRetval,
|
||||
bool batReverts
|
||||
)
|
||||
public
|
||||
{
|
||||
_recRetval = recRetval;
|
||||
_recReverts = recReverts;
|
||||
_batRetval = batRetval;
|
||||
_batReverts = batReverts;
|
||||
}
|
||||
|
||||
function onERC1155Received(
|
||||
address operator,
|
||||
address from,
|
||||
uint256 id,
|
||||
uint256 value,
|
||||
bytes calldata data
|
||||
)
|
||||
external
|
||||
override
|
||||
returns(bytes4)
|
||||
{
|
||||
require(!_recReverts, "ERC1155ReceiverMock: reverting on receive");
|
||||
emit Received(operator, from, id, value, data, gasleft());
|
||||
return _recRetval;
|
||||
}
|
||||
|
||||
function onERC1155BatchReceived(
|
||||
address operator,
|
||||
address from,
|
||||
uint256[] calldata ids,
|
||||
uint256[] calldata values,
|
||||
bytes calldata data
|
||||
)
|
||||
external
|
||||
override
|
||||
returns(bytes4)
|
||||
{
|
||||
require(!_batReverts, "ERC1155ReceiverMock: reverting on batch receive");
|
||||
emit BatchReceived(operator, from, ids, values, data, gasleft());
|
||||
return _batRetval;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../../introspection/IERC165.sol";
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
contract ERC165NotSupported { }
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../introspection/ERC165Checker.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../introspection/ERC165.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../introspection/ERC1820Implementer.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC20/ERC20Burnable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC20/ERC20Capped.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC20/ERC20Pausable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC20/ERC20Snapshot.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC721/ERC721Burnable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC721/ERC721.sol";
|
||||
import "../GSN/GSNRecipient.sol";
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC721/ERC721.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC721/ERC721Pausable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../token/ERC721/IERC721Receiver.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
import "../token/ERC777/ERC777.sol";
|
||||
@ -22,4 +24,8 @@ contract ERC777Mock is Context, ERC777 {
|
||||
) public {
|
||||
_mint(to, amount, userData, operatorData);
|
||||
}
|
||||
|
||||
function approveInternal(address holder, address spender, uint256 value) public {
|
||||
_approve(holder, spender, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
import "../token/ERC777/IERC777.sol";
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/EnumerableMap.sol";
|
||||
|
||||
|
||||
@ -1,8 +1,42 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/EnumerableSet.sol";
|
||||
|
||||
contract EnumerableSetMock {
|
||||
// Bytes32Set
|
||||
contract EnumerableBytes32SetMock {
|
||||
using EnumerableSet for EnumerableSet.Bytes32Set;
|
||||
|
||||
event OperationResult(bool result);
|
||||
|
||||
EnumerableSet.Bytes32Set private _set;
|
||||
|
||||
function contains(bytes32 value) public view returns (bool) {
|
||||
return _set.contains(value);
|
||||
}
|
||||
|
||||
function add(bytes32 value) public {
|
||||
bool result = _set.add(value);
|
||||
emit OperationResult(result);
|
||||
}
|
||||
|
||||
function remove(bytes32 value) public {
|
||||
bool result = _set.remove(value);
|
||||
emit OperationResult(result);
|
||||
}
|
||||
|
||||
function length() public view returns (uint256) {
|
||||
return _set.length();
|
||||
}
|
||||
|
||||
function at(uint256 index) public view returns (bytes32) {
|
||||
return _set.at(index);
|
||||
}
|
||||
}
|
||||
|
||||
// AddressSet
|
||||
contract EnumerableAddressSetMock {
|
||||
using EnumerableSet for EnumerableSet.AddressSet;
|
||||
|
||||
event OperationResult(bool result);
|
||||
@ -31,3 +65,34 @@ contract EnumerableSetMock {
|
||||
return _set.at(index);
|
||||
}
|
||||
}
|
||||
|
||||
// UintSet
|
||||
contract EnumerableUintSetMock {
|
||||
using EnumerableSet for EnumerableSet.UintSet;
|
||||
|
||||
event OperationResult(bool result);
|
||||
|
||||
EnumerableSet.UintSet private _set;
|
||||
|
||||
function contains(uint256 value) public view returns (bool) {
|
||||
return _set.contains(value);
|
||||
}
|
||||
|
||||
function add(uint256 value) public {
|
||||
bool result = _set.add(value);
|
||||
emit OperationResult(result);
|
||||
}
|
||||
|
||||
function remove(uint256 value) public {
|
||||
bool result = _set.remove(value);
|
||||
emit OperationResult(result);
|
||||
}
|
||||
|
||||
function length() public view returns (uint256) {
|
||||
return _set.length();
|
||||
}
|
||||
|
||||
function at(uint256 index) public view returns (uint256) {
|
||||
return _set.at(index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
contract EtherReceiverMock {
|
||||
bool private _acceptEther;
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../GSN/GSNRecipient.sol";
|
||||
import "../GSN/GSNRecipientERC20Fee.sol";
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "./ContextMock.sol";
|
||||
import "../GSN/GSNRecipient.sol";
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../GSN/GSNRecipient.sol";
|
||||
import "../GSN/GSNRecipientSignature.sol";
|
||||
|
||||
36
contracts/mocks/InitializableMock.sol
Normal file
36
contracts/mocks/InitializableMock.sol
Normal file
@ -0,0 +1,36 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../proxy/Initializable.sol";
|
||||
|
||||
/**
|
||||
* @title InitializableMock
|
||||
* @dev This contract is a mock to test initializable functionality
|
||||
*/
|
||||
contract InitializableMock is Initializable {
|
||||
|
||||
bool public initializerRan;
|
||||
uint256 public x;
|
||||
|
||||
function initialize() public initializer {
|
||||
initializerRan = true;
|
||||
}
|
||||
|
||||
function initializeNested() public initializer {
|
||||
initialize();
|
||||
}
|
||||
|
||||
function initializeWithX(uint256 _x) public payable initializer {
|
||||
x = _x;
|
||||
}
|
||||
|
||||
function nonInitializable(uint256 _x) public payable {
|
||||
x = _x;
|
||||
}
|
||||
|
||||
function fail() public pure {
|
||||
require(false, "InitializableMock forced failure");
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../math/Math.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import { MerkleProof } from "../cryptography/MerkleProof.sol";
|
||||
|
||||
|
||||
76
contracts/mocks/MultipleInheritanceInitializableMocks.sol
Normal file
76
contracts/mocks/MultipleInheritanceInitializableMocks.sol
Normal file
@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../proxy/Initializable.sol";
|
||||
|
||||
// Sample contracts showing upgradeability with multiple inheritance.
|
||||
// Child contract inherits from Father and Mother contracts, and Father extends from Gramps.
|
||||
//
|
||||
// Human
|
||||
// / \
|
||||
// | Gramps
|
||||
// | |
|
||||
// Mother Father
|
||||
// | |
|
||||
// -- Child --
|
||||
|
||||
/**
|
||||
* Sample base intializable contract that is a human
|
||||
*/
|
||||
contract SampleHuman is Initializable {
|
||||
bool public isHuman;
|
||||
|
||||
function initialize() public initializer {
|
||||
isHuman = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample base intializable contract that defines a field mother
|
||||
*/
|
||||
contract SampleMother is Initializable, SampleHuman {
|
||||
uint256 public mother;
|
||||
|
||||
function initialize(uint256 value) public initializer virtual {
|
||||
SampleHuman.initialize();
|
||||
mother = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample base intializable contract that defines a field gramps
|
||||
*/
|
||||
contract SampleGramps is Initializable, SampleHuman {
|
||||
string public gramps;
|
||||
|
||||
function initialize(string memory value) public initializer virtual {
|
||||
SampleHuman.initialize();
|
||||
gramps = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample base intializable contract that defines a field father and extends from gramps
|
||||
*/
|
||||
contract SampleFather is Initializable, SampleGramps {
|
||||
uint256 public father;
|
||||
|
||||
function initialize(string memory _gramps, uint256 _father) public initializer {
|
||||
SampleGramps.initialize(_gramps);
|
||||
father = _father;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Child extends from mother, father (gramps)
|
||||
*/
|
||||
contract SampleChild is Initializable, SampleMother, SampleFather {
|
||||
uint256 public child;
|
||||
|
||||
function initialize(uint256 _mother, string memory _gramps, uint256 _father, uint256 _child) public initializer {
|
||||
SampleMother.initialize(_mother);
|
||||
SampleFather.initialize(_gramps, _father);
|
||||
child = _child;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../access/Ownable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Pausable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../payment/PullPayment.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
contract ReentrancyAttack is Context {
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/ReentrancyGuard.sol";
|
||||
import "./ReentrancyAttack.sol";
|
||||
|
||||
66
contracts/mocks/RegressionImplementation.sol
Normal file
66
contracts/mocks/RegressionImplementation.sol
Normal file
@ -0,0 +1,66 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../proxy/Initializable.sol";
|
||||
|
||||
contract Implementation1 is Initializable {
|
||||
uint internal _value;
|
||||
|
||||
function initialize() public initializer {
|
||||
}
|
||||
|
||||
function setValue(uint _number) public {
|
||||
_value = _number;
|
||||
}
|
||||
}
|
||||
|
||||
contract Implementation2 is Initializable {
|
||||
uint internal _value;
|
||||
|
||||
function initialize() public initializer {
|
||||
}
|
||||
|
||||
function setValue(uint _number) public {
|
||||
_value = _number;
|
||||
}
|
||||
|
||||
function getValue() public view returns (uint) {
|
||||
return _value;
|
||||
}
|
||||
}
|
||||
|
||||
contract Implementation3 is Initializable {
|
||||
uint internal _value;
|
||||
|
||||
function initialize() public initializer {
|
||||
}
|
||||
|
||||
function setValue(uint _number) public {
|
||||
_value = _number;
|
||||
}
|
||||
|
||||
function getValue(uint _number) public view returns (uint) {
|
||||
return _value + _number;
|
||||
}
|
||||
}
|
||||
|
||||
contract Implementation4 is Initializable {
|
||||
uint internal _value;
|
||||
|
||||
function initialize() public initializer {
|
||||
}
|
||||
|
||||
function setValue(uint _number) public {
|
||||
_value = _number;
|
||||
}
|
||||
|
||||
function getValue() public view returns (uint) {
|
||||
return _value;
|
||||
}
|
||||
|
||||
// solhint-disable-next-line payable-fallback
|
||||
fallback() external {
|
||||
_value = 1;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/SafeCast.sol";
|
||||
|
||||
@ -33,4 +35,24 @@ contract SafeCastMock {
|
||||
function toUint8(uint a) public pure returns (uint8) {
|
||||
return a.toUint8();
|
||||
}
|
||||
|
||||
function toInt128(int a) public pure returns (int128) {
|
||||
return a.toInt128();
|
||||
}
|
||||
|
||||
function toInt64(int a) public pure returns (int64) {
|
||||
return a.toInt64();
|
||||
}
|
||||
|
||||
function toInt32(int a) public pure returns (int32) {
|
||||
return a.toInt32();
|
||||
}
|
||||
|
||||
function toInt16(int a) public pure returns (int16) {
|
||||
return a.toInt16();
|
||||
}
|
||||
|
||||
function toInt8(int a) public pure returns (int8) {
|
||||
return a.toInt8();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../math/SignedSafeMath.sol";
|
||||
|
||||
|
||||
49
contracts/mocks/SingleInheritanceInitializableMocks.sol
Normal file
49
contracts/mocks/SingleInheritanceInitializableMocks.sol
Normal file
@ -0,0 +1,49 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../proxy/Initializable.sol";
|
||||
|
||||
/**
|
||||
* @title MigratableMockV1
|
||||
* @dev This contract is a mock to test initializable functionality through migrations
|
||||
*/
|
||||
contract MigratableMockV1 is Initializable {
|
||||
uint256 public x;
|
||||
|
||||
function initialize(uint256 value) public payable initializer {
|
||||
x = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @title MigratableMockV2
|
||||
* @dev This contract is a mock to test migratable functionality with params
|
||||
*/
|
||||
contract MigratableMockV2 is MigratableMockV1 {
|
||||
bool internal _migratedV2;
|
||||
uint256 public y;
|
||||
|
||||
function migrate(uint256 value, uint256 anotherValue) public payable {
|
||||
require(!_migratedV2);
|
||||
x = value;
|
||||
y = anotherValue;
|
||||
_migratedV2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @title MigratableMockV3
|
||||
* @dev This contract is a mock to test migratable functionality without params
|
||||
*/
|
||||
contract MigratableMockV3 is MigratableMockV2 {
|
||||
bool internal _migratedV3;
|
||||
|
||||
function migrate() public payable {
|
||||
require(!_migratedV3);
|
||||
uint256 oldX = x;
|
||||
x = y;
|
||||
y = oldX;
|
||||
_migratedV3 = true;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Strings.sol";
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@openzeppelin/contracts",
|
||||
"version": "3.0.0",
|
||||
"description": "Secure Smart Contract library for Solidity",
|
||||
"version": "3.3.0-rc.2",
|
||||
"files": [
|
||||
"**/*.sol",
|
||||
"/build/contracts/*.json",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user