Compare commits
209 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa64a1ced0 | |||
| 0f553e7f9e | |||
| a0e2bca79a | |||
| ff300b10e1 | |||
| 18c7efe800 | |||
| 0931062a3f | |||
| 3b4c951838 | |||
| c2c08af16d | |||
| 9e49be41b6 | |||
| dd86c97e18 | |||
| 5a8e6bda51 | |||
| c34211417c | |||
| 5a58fd2de0 | |||
| faec973e09 | |||
| 65b7e515a2 | |||
| 318c4b44ea | |||
| b6e5187973 | |||
| 1e8cb4b4a4 | |||
| 9daa0d4d2f | |||
| ceb7324657 | |||
| da00d28cb7 | |||
| c23d5e0143 | |||
| d8658dbc47 | |||
| a6a4c042f5 | |||
| 6be0b410dc | |||
| 051d340171 | |||
| 0a4233f0f6 | |||
| ecc66719bd | |||
| 03d51c5677 | |||
| 268c6ab36c | |||
| 0786f31f22 | |||
| 883116e4af | |||
| 5748034cd3 | |||
| 061e7f0da7 | |||
| a138dc3970 | |||
| fa2b204535 | |||
| 73c7af102b | |||
| 18a8ae5a8a | |||
| fa65bf89be | |||
| 60c8b0e02f | |||
| acac4a7fca | |||
| 6be5ffe54f | |||
| ba843f0ad9 | |||
| 4297be6ac1 | |||
| 7d02933da3 | |||
| d2003a6fff | |||
| ef0483b4be | |||
| 9e51b2e5df | |||
| 951e946e71 | |||
| 1fccf6fa53 | |||
| 7f8fc584de | |||
| 1d1d2ba661 | |||
| 520bf7ac61 | |||
| 85f50d3e06 | |||
| e12cb97e16 | |||
| a3a7e6fa34 | |||
| 3881175d72 | |||
| ef32c04795 | |||
| 42da4d6867 | |||
| f7bb84ce4c | |||
| 5bd1c0d063 | |||
| 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 |
@ -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
|
||||
|
||||
10
.codecov.yml
10
.codecov.yml
@ -1,3 +1,11 @@
|
||||
comment: off
|
||||
github_checks:
|
||||
annotations: false
|
||||
coverage:
|
||||
range: "100...100"
|
||||
status:
|
||||
patch:
|
||||
default:
|
||||
target: 95%
|
||||
project:
|
||||
default:
|
||||
threshold: 1%
|
||||
|
||||
@ -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": {
|
||||
|
||||
|
||||
32
.github/PULL_REQUEST_TEMPLATE.md
vendored
32
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,22 +1,20 @@
|
||||
<!-- 0. 🎉 Thank you for submitting a PR! -->
|
||||
<!-- Thank you for your interest in contributing to OpenZeppelin! -->
|
||||
|
||||
<!-- 1. Does this close any open issues? Please list them below. -->
|
||||
<!-- Consider opening an issue for discussion prior to submitting a PR. -->
|
||||
<!-- New features will be merged faster if they were first discussed and designed with the team. -->
|
||||
|
||||
<!-- Keep in mind that new features have a better chance of being merged fast if
|
||||
they were first discussed and designed with the maintainers. If there is no
|
||||
corresponding issue, please consider opening one for discussion first! -->
|
||||
Fixes #???? <!-- Fill in with issue number -->
|
||||
|
||||
Fixes #
|
||||
<!-- Describe the changes introduced in this pull request. -->
|
||||
<!-- Include any context necessary for understanding the PR's purpose. -->
|
||||
|
||||
<!-- 2. Describe the changes introduced in this pull request. -->
|
||||
<!-- Include any context necessary for understanding the PR's purpose. -->
|
||||
|
||||
<!-- 3. Before submitting, please make sure that you have:
|
||||
- reviewed the OpenZeppelin Contributor Guidelines
|
||||
(https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CONTRIBUTING.md),
|
||||
- added tests where applicable to test new functionality,
|
||||
- made sure that your contracts are well-documented,
|
||||
- run the Solidity linter (`npm run lint:sol`) and fixed any issues,
|
||||
- run the JS linter and fixed any issues (`npm run lint:fix`), and
|
||||
- updated the changelog, if applicable.
|
||||
-->
|
||||
#### PR Checklist
|
||||
|
||||
<!-- Before merging the pull request all of the following must be complete. -->
|
||||
<!-- Feel free to submit a PR or Draft PR even if some items are pending. -->
|
||||
<!-- Some of the items may not apply. -->
|
||||
|
||||
- [ ] Tests
|
||||
- [ ] Documentation
|
||||
- [ ] Changelog entry
|
||||
|
||||
67
.github/stale.yml
vendored
67
.github/stale.yml
vendored
@ -1,67 +0,0 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 15
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 15
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- on hold
|
||||
- meta
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Set to true to ignore issues with an assignee (defaults to false)
|
||||
exemptAssignees: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: stale
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
Hi all!
|
||||
|
||||
This Pull Request has not had any recent activity, is it still relevant? If so, what is blocking it?
|
||||
Is there anything we can do to help move it forward?
|
||||
|
||||
Thanks!
|
||||
|
||||
|
||||
# Comment to post when removing the stale label.
|
||||
# unmarkComment: >
|
||||
# Your comment here.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
closeComment: >
|
||||
Hi folks!
|
||||
|
||||
This Pull Request is being closed as there was no response to the previous prompt.
|
||||
However, please leave a comment whenever you're ready to resume, so it can be reopened.
|
||||
|
||||
Thanks again!
|
||||
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 30
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
only: pulls
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
# pulls:
|
||||
# daysUntilStale: 30
|
||||
# markComment: >
|
||||
# This pull request has been automatically marked as stale because it has not had
|
||||
# recent activity. It will be closed if no further activity occurs. Thank you
|
||||
# for your contributions.
|
||||
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - confirmed
|
||||
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@v2
|
||||
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@v2
|
||||
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,12 @@ module.exports = {
|
||||
compileCommand: 'npm run compile',
|
||||
skipFiles: [
|
||||
'mocks',
|
||||
]
|
||||
],
|
||||
providerOptions: {
|
||||
default_balance_ether: '10000000000000000000000000',
|
||||
},
|
||||
mocha: {
|
||||
fgrep: '[skip-on-coverage]',
|
||||
invert: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -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 }]
|
||||
}
|
||||
}
|
||||
|
||||
73
CHANGELOG.md
73
CHANGELOG.md
@ -1,5 +1,78 @@
|
||||
# Changelog
|
||||
|
||||
## 3.4.0 (2021-02-02)
|
||||
|
||||
* `BeaconProxy`: added new kind of proxy that allows simultaneous atomic upgrades. ([#2411](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2411))
|
||||
* `EIP712`: added helpers to verify EIP712 typed data signatures on chain. ([#2418](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2418))
|
||||
* `ERC20Permit`: added an implementation of the ERC20 permit extension for gasless token approvals. ([#2237](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237))
|
||||
* Presets: added token presets with preminted fixed supply `ERC20PresetFixedSupply` and `ERC777PresetFixedSupply`. ([#2399](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2399))
|
||||
* `Address`: added `functionDelegateCall`, similar to the existing `functionCall`. ([#2333](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2333))
|
||||
* `Clones`: added a library for deploying EIP 1167 minimal proxies. ([#2449](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2449))
|
||||
* `Context`: moved from `contracts/GSN` to `contracts/utils`. ([#2453](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2453))
|
||||
* `PaymentSplitter`: replace usage of `.transfer()` with `Address.sendValue` for improved compatibility with smart wallets. ([#2455](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2455))
|
||||
* `UpgradeableProxy`: bubble revert reasons from initialization calls. ([#2454](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2454))
|
||||
* `SafeMath`: fix a memory allocation issue by adding new `SafeMath.tryOp(uint,uint)→(bool,uint)` functions. `SafeMath.op(uint,uint,string)→uint` are now deprecated. ([#2462](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2462))
|
||||
* `EnumerableMap`: fix a memory allocation issue by adding new `EnumerableMap.tryGet(uint)→(bool,address)` functions. `EnumerableMap.get(uint)→string` is now deprecated. ([#2462](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2462))
|
||||
* `ERC165Checker`: added batch `getSupportedInterfaces`. ([#2469](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2469))
|
||||
* `RefundEscrow`: `beneficiaryWithdraw` will forward all available gas to the beneficiary. ([#2480](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2480))
|
||||
* Many view and pure functions have been made virtual to customize them via overrides. In many cases this will not imply that other functions in the contract will automatically adapt to the overridden definitions. People who wish to override should consult the source code to understand the impact and if they need to override any additional functions to achieve the desired behavior.
|
||||
|
||||
### Security Fixes
|
||||
|
||||
* `ERC777`: fix potential reentrancy issues for custom extensions to `ERC777`. ([#2483](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2483))
|
||||
|
||||
If you're using our implementation of ERC777 from version 3.3.0 or earlier, and you define a custom `_beforeTokenTransfer` function that writes to a storage variable, you may be vulnerable to a reentrancy attack. If you're affected and would like assistance please write to security@openzeppelin.com. [Read more in the pull request.](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2483)
|
||||
|
||||
## 3.3.0 (2020-11-26)
|
||||
|
||||
* 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
|
||||
|
||||
@ -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
|
||||
|
||||
16
README.md
16
README.md
@ -1,8 +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.
|
||||
@ -11,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 (_last full audit on v2.0.0_).
|
||||
* [Audited](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/audit) by leading security firms (_last full audit on v2.0.0_).
|
||||
|
||||
## Overview
|
||||
|
||||
@ -28,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 {
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -45,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,26 +1,5 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
* @dev Provides information about the current execution context, including the
|
||||
* sender of the transaction and its data. While these are generally available
|
||||
* via msg.sender and msg.data, they should not be accessed in such a direct
|
||||
* manner, since when dealing with GSN meta-transactions the account sending and
|
||||
* paying for execution may not be the actual sender (as far as an application
|
||||
* is concerned).
|
||||
*
|
||||
* 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 { }
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
function _msgSender() internal view virtual returns (address payable) {
|
||||
return msg.sender;
|
||||
}
|
||||
|
||||
function _msgData() internal view virtual returns (bytes memory) {
|
||||
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
|
||||
return msg.data;
|
||||
}
|
||||
}
|
||||
import "../utils/Context.sol";
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Context.sol";
|
||||
import "./IRelayRecipient.sol";
|
||||
import "./IRelayHub.sol";
|
||||
import "./Context.sol";
|
||||
|
||||
/**
|
||||
* @dev Base GSN recipient contract: includes the {IRelayRecipient} interface
|
||||
@ -33,7 +35,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
/**
|
||||
* @dev Returns the address of the {IRelayHub} contract for this recipient.
|
||||
*/
|
||||
function getHubAddr() public view override returns (address) {
|
||||
function getHubAddr() public view virtual override returns (address) {
|
||||
return _relayHub;
|
||||
}
|
||||
|
||||
@ -60,7 +62,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
*/
|
||||
// This function is view for future-proofing, it may require reading from
|
||||
// storage in the future.
|
||||
function relayHubVersion() public view returns (string memory) {
|
||||
function relayHubVersion() public view virtual returns (string memory) {
|
||||
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
|
||||
return "1.0.0";
|
||||
}
|
||||
@ -71,7 +73,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
* Derived contracts should expose this in an external interface with proper access control.
|
||||
*/
|
||||
function _withdrawDeposits(uint256 amount, address payable payee) internal virtual {
|
||||
IRelayHub(_relayHub).withdraw(amount, payee);
|
||||
IRelayHub(getHubAddr()).withdraw(amount, payee);
|
||||
}
|
||||
|
||||
// Overrides for Context's functions: when called from RelayHub, sender and
|
||||
@ -86,7 +88,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
* IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.sender`, and use {_msgSender} instead.
|
||||
*/
|
||||
function _msgSender() internal view virtual override returns (address payable) {
|
||||
if (msg.sender != _relayHub) {
|
||||
if (msg.sender != getHubAddr()) {
|
||||
return msg.sender;
|
||||
} else {
|
||||
return _getRelayedCallSender();
|
||||
@ -100,7 +102,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
* IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.data`, and use {_msgData} instead.
|
||||
*/
|
||||
function _msgData() internal view virtual override returns (bytes memory) {
|
||||
if (msg.sender != _relayHub) {
|
||||
if (msg.sender != getHubAddr()) {
|
||||
return msg.data;
|
||||
} else {
|
||||
return _getRelayedCallData();
|
||||
@ -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:
|
||||
*
|
||||
@ -160,7 +162,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
* @dev Return this in acceptRelayedCall to proceed with the execution of a relayed call. Note that this contract
|
||||
* will be charged a fee by RelayHub
|
||||
*/
|
||||
function _approveRelayedCall() internal pure returns (uint256, bytes memory) {
|
||||
function _approveRelayedCall() internal pure virtual returns (uint256, bytes memory) {
|
||||
return _approveRelayedCall("");
|
||||
}
|
||||
|
||||
@ -169,14 +171,14 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
*
|
||||
* This overload forwards `context` to _preRelayedCall and _postRelayedCall.
|
||||
*/
|
||||
function _approveRelayedCall(bytes memory context) internal pure returns (uint256, bytes memory) {
|
||||
function _approveRelayedCall(bytes memory context) internal pure virtual returns (uint256, bytes memory) {
|
||||
return (_RELAYED_CALL_ACCEPTED, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return this in acceptRelayedCall to impede execution of a relayed call. No fees will be charged.
|
||||
*/
|
||||
function _rejectRelayedCall(uint256 errorCode) internal pure returns (uint256, bytes memory) {
|
||||
function _rejectRelayedCall(uint256 errorCode) internal pure virtual returns (uint256, bytes memory) {
|
||||
return (_RELAYED_CALL_REJECTED + errorCode, "");
|
||||
}
|
||||
|
||||
@ -184,7 +186,7 @@ abstract contract GSNRecipient is IRelayRecipient, Context {
|
||||
* @dev Calculates how much RelayHub will charge a recipient for using `gas` at a `gasPrice`, given a relayer's
|
||||
* `serviceFee`.
|
||||
*/
|
||||
function _computeCharge(uint256 gas, uint256 gasPrice, uint256 serviceFee) internal pure returns (uint256) {
|
||||
function _computeCharge(uint256 gas, uint256 gasPrice, uint256 serviceFee) internal pure virtual returns (uint256) {
|
||||
// The fee is expressed as a percentage. E.g. a value of 40 stands for a 40% fee, so the recipient will be
|
||||
// charged for 1.4 times the spent amount.
|
||||
return (gas * gasPrice * (100 + serviceFee)) / 100;
|
||||
|
||||
@ -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";
|
||||
@ -35,15 +37,15 @@ contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
/**
|
||||
* @dev Returns the gas payment token.
|
||||
*/
|
||||
function token() public view returns (IERC20) {
|
||||
return IERC20(_token);
|
||||
function token() public view virtual returns (__unstable__ERC20Owned) {
|
||||
return _token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Internal function that mints the gas payment token. Derived contracts should expose this function in their public API, with proper access control mechanisms.
|
||||
*/
|
||||
function _mint(address account, uint256 amount) internal virtual {
|
||||
_token.mint(account, amount);
|
||||
token().mint(account, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,7 +68,7 @@ contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
override
|
||||
returns (uint256, bytes memory)
|
||||
{
|
||||
if (_token.balanceOf(from) < maxPossibleCharge) {
|
||||
if (token().balanceOf(from) < maxPossibleCharge) {
|
||||
return _rejectRelayedCall(uint256(GSNRecipientERC20FeeErrorCodes.INSUFFICIENT_BALANCE));
|
||||
}
|
||||
|
||||
@ -83,7 +85,9 @@ contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
(address from, uint256 maxPossibleCharge) = abi.decode(context, (address, uint256));
|
||||
|
||||
// The maximum token charge is pre-charged from the user
|
||||
_token.safeTransferFrom(from, address(this), maxPossibleCharge);
|
||||
token().safeTransferFrom(from, address(this), maxPossibleCharge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,7 +104,7 @@ contract GSNRecipientERC20Fee is GSNRecipient {
|
||||
actualCharge = actualCharge.sub(overestimation);
|
||||
|
||||
// After the relayed call has been executed and the actual charge estimated, the excess pre-charge is returned
|
||||
_token.safeTransfer(from, maxPossibleCharge.sub(actualCharge));
|
||||
token().safeTransfer(from, maxPossibleCharge.sub(actualCharge));
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,12 +121,12 @@ contract __unstable__ERC20Owned is ERC20, Ownable {
|
||||
constructor(string memory name, string memory symbol) public ERC20(name, symbol) { }
|
||||
|
||||
// The owner (GSNRecipientERC20Fee) can mint tokens
|
||||
function mint(address account, uint256 amount) public onlyOwner {
|
||||
function mint(address account, uint256 amount) public virtual onlyOwner {
|
||||
_mint(account, amount);
|
||||
}
|
||||
|
||||
// The owner has 'infinite' allowance for all token holders
|
||||
function allowance(address tokenOwner, address spender) public view override returns (uint256) {
|
||||
function allowance(address tokenOwner, address spender) public view virtual override returns (uint256) {
|
||||
if (spender == owner()) {
|
||||
return _UINT256_MAX;
|
||||
} else {
|
||||
@ -131,7 +135,7 @@ contract __unstable__ERC20Owned is ERC20, Ownable {
|
||||
}
|
||||
|
||||
// Allowance for the owner cannot be changed (it is always 'infinite')
|
||||
function _approve(address tokenOwner, address spender, uint256 value) internal override {
|
||||
function _approve(address tokenOwner, address spender, uint256 value) internal virtual override {
|
||||
if (spender == owner()) {
|
||||
return;
|
||||
} else {
|
||||
@ -139,7 +143,7 @@ contract __unstable__ERC20Owned is ERC20, Ownable {
|
||||
}
|
||||
}
|
||||
|
||||
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
|
||||
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
|
||||
if (recipient == owner()) {
|
||||
_transfer(sender, recipient, amount);
|
||||
return true;
|
||||
|
||||
@ -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,8 +1,10 @@
|
||||
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";
|
||||
import "../GSN/Context.sol";
|
||||
import "../utils/Context.sol";
|
||||
|
||||
/**
|
||||
* @dev Contract module that allows children to implement role-based access
|
||||
@ -52,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`.
|
||||
*
|
||||
@ -183,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,6 +1,8 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Context.sol";
|
||||
/**
|
||||
* @dev Contract module which provides a basic access control mechanism, where
|
||||
* there is an account (an owner) that can be granted exclusive access to
|
||||
@ -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);
|
||||
@ -30,7 +32,7 @@ contract Ownable is Context {
|
||||
/**
|
||||
* @dev Returns the address of the current owner.
|
||||
*/
|
||||
function owner() public view returns (address) {
|
||||
function owner() public view virtual returns (address) {
|
||||
return _owner;
|
||||
}
|
||||
|
||||
@ -38,7 +40,7 @@ contract Ownable is Context {
|
||||
* @dev Throws if called by any account other than the owner.
|
||||
*/
|
||||
modifier onlyOwner() {
|
||||
require(_owner == _msgSender(), "Ownable: caller is not the owner");
|
||||
require(owner() == _msgSender(), "Ownable: caller is not the owner");
|
||||
_;
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,101 @@
|
||||
= 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}}
|
||||
|
||||
[[timelock-terminology]]
|
||||
==== 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.
|
||||
|
||||
[[timelock-operation]]
|
||||
==== Operation structure
|
||||
|
||||
Operation executed by the xref:api:access.adoc#TimelockController[`TimelockControler`] can contain one or multiple subsequent calls. Depending on whether you need to multiple calls to be executed atomically, you can either use simple or batched operations.
|
||||
|
||||
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.
|
||||
|
||||
[[timelock-operation-lifecycle]]
|
||||
==== 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)`]
|
||||
|
||||
[[timelock-roles]]
|
||||
==== Roles
|
||||
|
||||
[[timelock-admin]]
|
||||
===== 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`
|
||||
|
||||
[[timelock-proposer]]
|
||||
===== 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`
|
||||
|
||||
[[timelock-executor]]
|
||||
===== Executor
|
||||
|
||||
The executors are in charge of executing the operations scheduled by the proposers once the timelock expires. Logic dictates that multisig or DAO that are proposers should also be executors in order to guarantee operations that have been scheduled will eventually be executed. However, having additional executor can reduce the cost (the executing transaction does not require validation by the multisig or DAO that proposed it), while ensuring whoever is in charge of execution cannot trigger actions that have not been scheduled by the proposers.
|
||||
|
||||
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.
|
||||
|
||||
299
contracts/access/TimelockController.sol
Normal file
299
contracts/access/TimelockController.sol
Normal file
@ -0,0 +1,299 @@
|
||||
// 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.
|
||||
*
|
||||
* _Available since v3.3._
|
||||
*/
|
||||
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 id correspond to a registered operation. This
|
||||
* includes both Pending, Ready and Done operations.
|
||||
*/
|
||||
function isOperation(bytes32 id) public view virtual returns (bool pending) {
|
||||
return getTimestamp(id) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns whether an operation is pending or not.
|
||||
*/
|
||||
function isOperationPending(bytes32 id) public view virtual returns (bool pending) {
|
||||
return getTimestamp(id) > _DONE_TIMESTAMP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns whether an operation is ready or not.
|
||||
*/
|
||||
function isOperationReady(bytes32 id) public view virtual returns (bool ready) {
|
||||
uint256 timestamp = getTimestamp(id);
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns whether an operation is done or not.
|
||||
*/
|
||||
function isOperationDone(bytes32 id) public view virtual returns (bool done) {
|
||||
return getTimestamp(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 virtual returns (uint256 timestamp) {
|
||||
return _timestamps[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the minimum delay for an operation to become valid.
|
||||
*
|
||||
* This value can be changed by executing an operation that calls `updateDelay`.
|
||||
*/
|
||||
function getMinDelay() public view virtual 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 virtual 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 virtual 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(!isOperation(id), "TimelockController: operation already scheduled");
|
||||
require(delay >= getMinDelay(), "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 minimum timelock duration for future operations.
|
||||
*
|
||||
* Emits a {MinDelayChange} event.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
|
||||
* an operation where the timelock is the target and the data is the ABI-encoded call to this function.
|
||||
*/
|
||||
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.
|
||||
@ -41,6 +43,14 @@ library ECDSA {
|
||||
v := byte(0, mload(add(signature, 0x60)))
|
||||
}
|
||||
|
||||
return recover(hash, v, r, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`,
|
||||
* `r` and `s` signature fields separately.
|
||||
*/
|
||||
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
|
||||
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
|
||||
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
|
||||
// the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
|
||||
@ -50,13 +60,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,7 +1,14 @@
|
||||
= 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.
|
||||
|
||||
The following related EIPs are in draft status and can be found in the drafts directory.
|
||||
|
||||
- {EIP712}
|
||||
|
||||
== Libraries
|
||||
|
||||
{{ECDSA}}
|
||||
|
||||
108
contracts/drafts/EIP712.sol
Normal file
108
contracts/drafts/EIP712.sol
Normal file
@ -0,0 +1,108 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
|
||||
*
|
||||
* The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
|
||||
* thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
|
||||
* they need in their contracts using a combination of `abi.encode` and `keccak256`.
|
||||
*
|
||||
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
|
||||
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
|
||||
* ({_hashTypedDataV4}).
|
||||
*
|
||||
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
|
||||
* the chain id to protect against replay attacks on an eventual fork of the chain.
|
||||
*
|
||||
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
|
||||
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
abstract contract EIP712 {
|
||||
/* solhint-disable var-name-mixedcase */
|
||||
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
|
||||
// invalidate the cached domain separator if the chain id changes.
|
||||
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
|
||||
uint256 private immutable _CACHED_CHAIN_ID;
|
||||
|
||||
bytes32 private immutable _HASHED_NAME;
|
||||
bytes32 private immutable _HASHED_VERSION;
|
||||
bytes32 private immutable _TYPE_HASH;
|
||||
/* solhint-enable var-name-mixedcase */
|
||||
|
||||
/**
|
||||
* @dev Initializes the domain separator and parameter caches.
|
||||
*
|
||||
* The meaning of `name` and `version` is specified in
|
||||
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
|
||||
*
|
||||
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
|
||||
* - `version`: the current major version of the signing domain.
|
||||
*
|
||||
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
|
||||
* contract upgrade].
|
||||
*/
|
||||
constructor(string memory name, string memory version) internal {
|
||||
bytes32 hashedName = keccak256(bytes(name));
|
||||
bytes32 hashedVersion = keccak256(bytes(version));
|
||||
bytes32 typeHash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
|
||||
_HASHED_NAME = hashedName;
|
||||
_HASHED_VERSION = hashedVersion;
|
||||
_CACHED_CHAIN_ID = _getChainId();
|
||||
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
|
||||
_TYPE_HASH = typeHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the domain separator for the current chain.
|
||||
*/
|
||||
function _domainSeparatorV4() internal view virtual returns (bytes32) {
|
||||
if (_getChainId() == _CACHED_CHAIN_ID) {
|
||||
return _CACHED_DOMAIN_SEPARATOR;
|
||||
} else {
|
||||
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) {
|
||||
return keccak256(
|
||||
abi.encode(
|
||||
typeHash,
|
||||
name,
|
||||
version,
|
||||
_getChainId(),
|
||||
address(this)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
|
||||
* function returns the hash of the fully encoded EIP712 message for this domain.
|
||||
*
|
||||
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
|
||||
*
|
||||
* ```solidity
|
||||
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
|
||||
* keccak256("Mail(address to,string contents)"),
|
||||
* mailTo,
|
||||
* keccak256(bytes(mailContents))
|
||||
* )));
|
||||
* address signer = ECDSA.recover(digest, signature);
|
||||
* ```
|
||||
*/
|
||||
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
|
||||
return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), structHash));
|
||||
}
|
||||
|
||||
function _getChainId() private view returns (uint256 chainId) {
|
||||
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
chainId := chainid()
|
||||
}
|
||||
}
|
||||
}
|
||||
78
contracts/drafts/ERC20Permit.sol
Normal file
78
contracts/drafts/ERC20Permit.sol
Normal file
@ -0,0 +1,78 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.5 <0.8.0;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "./IERC20Permit.sol";
|
||||
import "../cryptography/ECDSA.sol";
|
||||
import "../utils/Counters.sol";
|
||||
import "./EIP712.sol";
|
||||
|
||||
/**
|
||||
* @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
|
||||
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
|
||||
*
|
||||
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
|
||||
* presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
|
||||
* need to send a transaction, and thus is not required to hold Ether at all.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
|
||||
using Counters for Counters.Counter;
|
||||
|
||||
mapping (address => Counters.Counter) private _nonces;
|
||||
|
||||
// solhint-disable-next-line var-name-mixedcase
|
||||
bytes32 private immutable _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
|
||||
|
||||
/**
|
||||
* @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
|
||||
*
|
||||
* It's a good idea to use the same `name` that is defined as the ERC20 token name.
|
||||
*/
|
||||
constructor(string memory name) internal EIP712(name, "1") {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See {IERC20Permit-permit}.
|
||||
*/
|
||||
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override {
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
|
||||
|
||||
bytes32 structHash = keccak256(
|
||||
abi.encode(
|
||||
_PERMIT_TYPEHASH,
|
||||
owner,
|
||||
spender,
|
||||
value,
|
||||
_nonces[owner].current(),
|
||||
deadline
|
||||
)
|
||||
);
|
||||
|
||||
bytes32 hash = _hashTypedDataV4(structHash);
|
||||
|
||||
address signer = ECDSA.recover(hash, v, r, s);
|
||||
require(signer == owner, "ERC20Permit: invalid signature");
|
||||
|
||||
_nonces[owner].increment();
|
||||
_approve(owner, spender, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See {IERC20Permit-nonces}.
|
||||
*/
|
||||
function nonces(address owner) public view override returns (uint256) {
|
||||
return _nonces[owner].current();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
|
||||
*/
|
||||
// solhint-disable-next-line func-name-mixedcase
|
||||
function DOMAIN_SEPARATOR() external view override returns (bytes32) {
|
||||
return _domainSeparatorV4();
|
||||
}
|
||||
}
|
||||
51
contracts/drafts/IERC20Permit.sol
Normal file
51
contracts/drafts/IERC20Permit.sol
Normal file
@ -0,0 +1,51 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
|
||||
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
|
||||
*
|
||||
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
|
||||
* presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
|
||||
* need to send a transaction, and thus is not required to hold Ether at all.
|
||||
*/
|
||||
interface IERC20Permit {
|
||||
/**
|
||||
* @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,
|
||||
* given `owner`'s signed approval.
|
||||
*
|
||||
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
|
||||
* ordering also apply here.
|
||||
*
|
||||
* Emits an {Approval} event.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - `spender` cannot be the zero address.
|
||||
* - `deadline` must be a timestamp in the future.
|
||||
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
|
||||
* over the EIP712-formatted function arguments.
|
||||
* - the signature must use ``owner``'s current nonce (see {nonces}).
|
||||
*
|
||||
* For more information on the signature format, see the
|
||||
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
|
||||
* section].
|
||||
*/
|
||||
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
|
||||
|
||||
/**
|
||||
* @dev Returns the current nonce for `owner`. This value must be
|
||||
* included whenever a signature is generated for {permit}.
|
||||
*
|
||||
* Every successful call to {permit} increases ``owner``'s nonce by one. This
|
||||
* prevents a signature from being used multiple times.
|
||||
*/
|
||||
function nonces(address owner) external view returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.
|
||||
*/
|
||||
// solhint-disable-next-line func-name-mixedcase
|
||||
function DOMAIN_SEPARATOR() external view returns (bytes32);
|
||||
}
|
||||
15
contracts/drafts/README.adoc
Normal file
15
contracts/drafts/README.adoc
Normal file
@ -0,0 +1,15 @@
|
||||
= Draft EIPs
|
||||
|
||||
This directory contains implementations of EIPs that are still in Draft status.
|
||||
|
||||
Due to their nature as drafts, the details of these contracts may change and we cannot guarantee their xref:ROOT:releases-stability.adoc[stability]. Minor releases of OpenZeppelin Contracts may contain breaking changes for the contracts in this directory, which will be duly announced in the https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md[changelog]. The EIPs included here are used by projects in production and this may make them less likely to change significantly.
|
||||
|
||||
== Cryptography
|
||||
|
||||
{{EIP712}}
|
||||
|
||||
== ERC 20
|
||||
|
||||
{{IERC20Permit}}
|
||||
|
||||
{{ERC20Permit}}
|
||||
@ -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
|
||||
*/
|
||||
@ -30,7 +32,7 @@ contract ERC165 is IERC165 {
|
||||
*
|
||||
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
|
||||
*/
|
||||
function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
|
||||
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
|
||||
return _supportedInterfaces[interfaceId];
|
||||
}
|
||||
|
||||
|
||||
@ -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}.
|
||||
@ -38,6 +40,31 @@ library ERC165Checker {
|
||||
_supportsERC165Interface(account, interfaceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns a boolean array where each value corresponds to the
|
||||
* interfaces passed in and whether they're supported or not. This allows
|
||||
* you to batch check interfaces for a contract where your expectation
|
||||
* is that some interfaces may not be supported.
|
||||
*
|
||||
* See {IERC165-supportsInterface}.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function getSupportedInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool[] memory) {
|
||||
// an array of booleans corresponding to interfaceIds and whether they're supported or not
|
||||
bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
|
||||
|
||||
// query support of ERC165 itself
|
||||
if (supportsERC165(account)) {
|
||||
// query support of each interface in interfaceIds
|
||||
for (uint256 i = 0; i < interfaceIds.length; i++) {
|
||||
interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return interfaceIdsSupported;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns true if `account` supports all the interfaces defined in
|
||||
* `interfaceIds`. Support for {IERC165} itself is queried automatically.
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "./IERC1820Implementer.sol";
|
||||
|
||||
@ -18,7 +20,7 @@ contract ERC1820Implementer is IERC1820Implementer {
|
||||
/**
|
||||
* See {IERC1820Implementer-canImplementInterfaceForAddress}.
|
||||
*/
|
||||
function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) public view override returns (bytes32) {
|
||||
function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) public view virtual override returns (bytes32) {
|
||||
return _supportedInterfaces[interfaceHash][account] ? _ERC1820_ACCEPT_MAGIC : bytes32(0x00);
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
@ -14,6 +16,62 @@ pragma solidity ^0.6.0;
|
||||
* class of bugs, so it's recommended to use it always.
|
||||
*/
|
||||
library SafeMath {
|
||||
/**
|
||||
* @dev Returns the addition of two unsigned integers, with an overflow flag.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
|
||||
uint256 c = a + b;
|
||||
if (c < a) return (false, 0);
|
||||
return (true, c);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
|
||||
if (b > a) return (false, 0);
|
||||
return (true, a - b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
|
||||
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
|
||||
// benefit is lost if 'b' is also tested.
|
||||
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
|
||||
if (a == 0) return (true, 0);
|
||||
uint256 c = a * b;
|
||||
if (c / a != b) return (false, 0);
|
||||
return (true, c);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the division of two unsigned integers, with a division by zero flag.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
|
||||
if (b == 0) return (false, 0);
|
||||
return (true, a / b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
|
||||
if (b == 0) return (false, 0);
|
||||
return (true, a % b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the addition of two unsigned integers, reverting on
|
||||
* overflow.
|
||||
@ -21,12 +79,12 @@ library SafeMath {
|
||||
* Counterpart to Solidity's `+` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Addition cannot overflow.
|
||||
*/
|
||||
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
uint256 c = a + b;
|
||||
require(c >= a, "SafeMath: addition overflow");
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -37,26 +95,12 @@ library SafeMath {
|
||||
* Counterpart to Solidity's `-` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Subtraction cannot overflow.
|
||||
*/
|
||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
return sub(a, b, "SafeMath: subtraction overflow");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
|
||||
* overflow (when the result is negative).
|
||||
*
|
||||
* Counterpart to Solidity's `-` operator.
|
||||
*
|
||||
* Requirements:
|
||||
* - Subtraction cannot overflow.
|
||||
*/
|
||||
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
|
||||
require(b <= a, errorMessage);
|
||||
uint256 c = a - b;
|
||||
|
||||
return c;
|
||||
require(b <= a, "SafeMath: subtraction overflow");
|
||||
return a - b;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,24 +110,18 @@ library SafeMath {
|
||||
* Counterpart to Solidity's `*` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Multiplication cannot overflow.
|
||||
*/
|
||||
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
|
||||
// benefit is lost if 'b' is also tested.
|
||||
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a == 0) return 0;
|
||||
uint256 c = a * b;
|
||||
require(c / a == b, "SafeMath: multiplication overflow");
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the integer division of two unsigned integers. Reverts on
|
||||
* @dev Returns the integer division of two unsigned integers, reverting on
|
||||
* division by zero. The result is rounded towards zero.
|
||||
*
|
||||
* Counterpart to Solidity's `/` operator. Note: this function uses a
|
||||
@ -91,60 +129,86 @@ 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) {
|
||||
return div(a, b, "SafeMath: division by zero");
|
||||
require(b > 0, "SafeMath: division by zero");
|
||||
return a / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
|
||||
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
|
||||
* reverting when dividing by zero.
|
||||
*
|
||||
* Counterpart to Solidity's `%` operator. 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 mod(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b > 0, "SafeMath: modulo by zero");
|
||||
return a % b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
|
||||
* overflow (when the result is negative).
|
||||
*
|
||||
* CAUTION: This function is deprecated because it requires allocating memory for the error
|
||||
* message unnecessarily. For custom revert reasons use {trySub}.
|
||||
*
|
||||
* Counterpart to Solidity's `-` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Subtraction cannot overflow.
|
||||
*/
|
||||
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
|
||||
require(b <= a, errorMessage);
|
||||
return a - b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
|
||||
* division by zero. The result is rounded towards zero.
|
||||
*
|
||||
* CAUTION: This function is deprecated because it requires allocating memory for the error
|
||||
* message unnecessarily. For custom revert reasons use {tryDiv}.
|
||||
*
|
||||
* 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(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
|
||||
|
||||
return c;
|
||||
return a / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
|
||||
* Reverts when dividing by zero.
|
||||
* reverting with custom message when dividing by zero.
|
||||
*
|
||||
* CAUTION: This function is deprecated because it requires allocating memory for the error
|
||||
* message unnecessarily. For custom revert reasons use {tryMod}.
|
||||
*
|
||||
* Counterpart to Solidity's `%` operator. 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 mod(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
return mod(a, b, "SafeMath: modulo by zero");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
|
||||
* Reverts with custom message when dividing by zero.
|
||||
*
|
||||
* Counterpart to Solidity's `%` operator. 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 mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
|
||||
require(b != 0, errorMessage);
|
||||
require(b > 0, errorMessage);
|
||||
return a % b;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,26 @@ 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)));
|
||||
}
|
||||
|
||||
function functionDelegateCall(address target, bytes calldata data) external {
|
||||
bytes memory returnData = Address.functionDelegateCall(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";
|
||||
|
||||
|
||||
12
contracts/mocks/BadBeacon.sol
Normal file
12
contracts/mocks/BadBeacon.sol
Normal file
@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
contract BadBeaconNoImpl {
|
||||
}
|
||||
|
||||
contract BadBeaconNotContract {
|
||||
function implementation() external pure returns (address) {
|
||||
return address(0x1);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
32
contracts/mocks/ClonesMock.sol
Normal file
32
contracts/mocks/ClonesMock.sol
Normal file
@ -0,0 +1,32 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../proxy/Clones.sol";
|
||||
import "../utils/Address.sol";
|
||||
|
||||
contract ClonesMock {
|
||||
using Address for address;
|
||||
using Clones for address;
|
||||
|
||||
event NewInstance(address instance);
|
||||
|
||||
function clone(address master, bytes calldata initdata) public payable {
|
||||
_initAndEmit(master.clone(), initdata);
|
||||
}
|
||||
|
||||
function cloneDeterministic(address master, bytes32 salt, bytes calldata initdata) public payable {
|
||||
_initAndEmit(master.cloneDeterministic(salt), initdata);
|
||||
}
|
||||
|
||||
function predictDeterministicAddress(address master, bytes32 salt) public view returns (address predicted) {
|
||||
return master.predictDeterministicAddress(salt);
|
||||
}
|
||||
|
||||
function _initAndEmit(address instance, bytes memory initdata) private {
|
||||
if (initdata.length > 0) {
|
||||
instance.functionCallWithValue(initdata, msg.value);
|
||||
}
|
||||
emit NewInstance(instance);
|
||||
}
|
||||
}
|
||||
@ -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,6 +1,8 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Context.sol";
|
||||
|
||||
contract ContextMock is Context {
|
||||
event Sender(address sender);
|
||||
|
||||
@ -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 initializeNonPayableWithValue(uint256 _value) public {
|
||||
value = _value;
|
||||
}
|
||||
|
||||
function initializePayableWithValue(uint256 _value) public payable {
|
||||
value = _value;
|
||||
}
|
||||
|
||||
function initialize(uint256 _value, string memory _text, uint256[] memory _values) public {
|
||||
value = _value;
|
||||
text = _text;
|
||||
values = _values;
|
||||
}
|
||||
|
||||
function get() public pure returns (bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function version() public pure virtual returns (string memory) {
|
||||
return "V1";
|
||||
}
|
||||
|
||||
function reverts() public pure {
|
||||
require(false, "DummyImplementation reverted");
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
|
||||
32
contracts/mocks/EIP712External.sol
Normal file
32
contracts/mocks/EIP712External.sol
Normal file
@ -0,0 +1,32 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../drafts/EIP712.sol";
|
||||
import "../cryptography/ECDSA.sol";
|
||||
|
||||
contract EIP712External is EIP712 {
|
||||
constructor(string memory name, string memory version) public EIP712(name, version) {}
|
||||
|
||||
function domainSeparator() external view returns (bytes32) {
|
||||
return _domainSeparatorV4();
|
||||
}
|
||||
|
||||
function verify(bytes memory signature, address signer, address mailTo, string memory mailContents) external view {
|
||||
bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
|
||||
keccak256("Mail(address to,string contents)"),
|
||||
mailTo,
|
||||
keccak256(bytes(mailContents))
|
||||
)));
|
||||
address recoveredSigner = ECDSA.recover(digest, signature);
|
||||
require(recoveredSigner == signer);
|
||||
}
|
||||
|
||||
function getChainId() external view returns (uint256 chainId) {
|
||||
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
chainId := chainid()
|
||||
}
|
||||
}
|
||||
}
|
||||
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";
|
||||
|
||||
@ -16,4 +18,8 @@ contract ERC165CheckerMock {
|
||||
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) public view returns (bool) {
|
||||
return account.supportsAllInterfaces(interfaceIds);
|
||||
}
|
||||
|
||||
function getSupportedInterfaces(address account, bytes4[] memory interfaceIds) public view returns (bool[] memory) {
|
||||
return account.getSupportedInterfaces(interfaceIds);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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";
|
||||
|
||||
|
||||
24
contracts/mocks/ERC20PermitMock.sol
Normal file
24
contracts/mocks/ERC20PermitMock.sol
Normal file
@ -0,0 +1,24 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../drafts/ERC20Permit.sol";
|
||||
|
||||
contract ERC20PermitMock is ERC20Permit {
|
||||
constructor (
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
address initialAccount,
|
||||
uint256 initialBalance
|
||||
) public payable ERC20(name, symbol) ERC20Permit(name) {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
|
||||
function getChainId() external view returns (uint256 chainId) {
|
||||
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
chainId := chainid()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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,9 +1,13 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Context.sol";
|
||||
import "../token/ERC777/ERC777.sol";
|
||||
|
||||
contract ERC777Mock is Context, ERC777 {
|
||||
event BeforeTokenTransfer();
|
||||
|
||||
constructor(
|
||||
address initialHolder,
|
||||
uint256 initialBalance,
|
||||
@ -26,4 +30,8 @@ contract ERC777Mock is Context, ERC777 {
|
||||
function approveInternal(address holder, address spender, uint256 value) public {
|
||||
_approve(holder, spender, value);
|
||||
}
|
||||
|
||||
function _beforeTokenTransfer(address, address, address, uint256) internal override {
|
||||
emit BeforeTokenTransfer();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
pragma solidity ^0.6.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
pragma solidity >=0.6.0 <0.8.0;
|
||||
|
||||
import "../utils/Context.sol";
|
||||
import "../token/ERC777/IERC777.sol";
|
||||
import "../token/ERC777/IERC777Sender.sol";
|
||||
import "../token/ERC777/IERC777Recipient.sol";
|
||||
@ -32,6 +34,9 @@ contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient,
|
||||
uint256 toBalance
|
||||
);
|
||||
|
||||
// Emitted in ERC777Mock. Here for easier decoding
|
||||
event BeforeTokenTransfer();
|
||||
|
||||
bool private _shouldRevertSend;
|
||||
bool private _shouldRevertReceive;
|
||||
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -32,7 +34,15 @@ contract EnumerableMapMock {
|
||||
}
|
||||
|
||||
|
||||
function tryGet(uint256 key) public view returns (bool, address) {
|
||||
return _map.tryGet(key);
|
||||
}
|
||||
|
||||
function get(uint256 key) public view returns (address) {
|
||||
return _map.get(key);
|
||||
}
|
||||
|
||||
function getWithMessage(uint256 key, string calldata errorMessage) public view returns (address) {
|
||||
return _map.get(key, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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";
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user