Compare commits
425 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4070719ff5 | |||
| 169cac718a | |||
| 9c4840a479 | |||
| 516c120104 | |||
| fd9f404f96 | |||
| 5b43fccc34 | |||
| 1320dfb088 | |||
| 94d65429b7 | |||
| 58bf37d506 | |||
| 7ac0502c50 | |||
| dee9a2b897 | |||
| 64cf73d646 | |||
| c4ccdc182f | |||
| e592627578 | |||
| 24416fc208 | |||
| 09dee513ed | |||
| 906b18f144 | |||
| eb6b5b6631 | |||
| 7d0c6280f3 | |||
| 56b7d0713b | |||
| a7d5c72fdc | |||
| 7050b73a89 | |||
| 2b9dc9ae87 | |||
| 9ed1b44865 | |||
| 7aaf15be59 | |||
| 1e5295d304 | |||
| 61c4318c33 | |||
| 79dd498b16 | |||
| 547a5f242a | |||
| 352ec94579 | |||
| 3772233cf5 | |||
| 7f54542172 | |||
| 3ff2e24518 | |||
| 0c617b755e | |||
| 8cc3349d1f | |||
| 41aa39afbc | |||
| 0dded493a0 | |||
| a1f168be96 | |||
| 5b93137c26 | |||
| f5ba7e7f0d | |||
| 5a64eb2e14 | |||
| 2648206394 | |||
| 77d569d8fa | |||
| 634883ce8e | |||
| de90f4458a | |||
| a39bea230e | |||
| 8d0937c54c | |||
| d6c47c4b7c | |||
| 3111291b4a | |||
| 14ec984cc4 | |||
| b14c9f4b68 | |||
| fc17a1d9f5 | |||
| c44e40c293 | |||
| 2fc0aaabb3 | |||
| ae41195863 | |||
| 99a07493f2 | |||
| 328d03a7f4 | |||
| 530c90d438 | |||
| 3654150d0c | |||
| 9cf68279c1 | |||
| 039e5b9602 | |||
| cab777b820 | |||
| 7ed22bbded | |||
| 889af764e2 | |||
| f18fd17355 | |||
| 3dbf651b8e | |||
| 6bf2ae8229 | |||
| 644b121677 | |||
| 40d15146c4 | |||
| 453e3dd454 | |||
| e8e6dd52a5 | |||
| 105b927b62 | |||
| 2c34cfbe0e | |||
| 0b1e1810b1 | |||
| 2eb0de4cd2 | |||
| 3fd5195573 | |||
| 491fb5acd9 | |||
| 05c7d8c861 | |||
| d032ca62e2 | |||
| b306c41525 | |||
| 8dd92fd6ca | |||
| 1fd993bc01 | |||
| b39f3c2055 | |||
| 4e026cd4c7 | |||
| c08d63c118 | |||
| e357592208 | |||
| f3635e1517 | |||
| a09cf147ea | |||
| 04186e2cf6 | |||
| cff2509c63 | |||
| dd433c41bb | |||
| 4952240620 | |||
| 00f7c19d02 | |||
| 5eafd1dec2 | |||
| f80c65ff67 | |||
| 07603d5875 | |||
| 3a5da75876 | |||
| f84278433d | |||
| 73a34f96a7 | |||
| 877f07f0a9 | |||
| e808a64649 | |||
| e1f40e7e23 | |||
| 8617c4b4c8 | |||
| 96432bf28e | |||
| a221c17fb2 | |||
| 1a9cb0786d | |||
| fd808b3ff8 | |||
| 6a658f2ac8 | |||
| d9a8cd2bef | |||
| bce2d68e7f | |||
| b7d60f2f9a | |||
| 7fb90a1566 | |||
| e5b94c1481 | |||
| 79145fa53a | |||
| 3e82db2f6f | |||
| 089f14aa06 | |||
| ae02103e47 | |||
| ba83239dd8 | |||
| 14a59b2903 | |||
| 4f5715bbd7 | |||
| 312a2584e8 | |||
| c23b7ffbad | |||
| 6aa88e2b7d | |||
| 76abd1a41e | |||
| 35d70397b6 | |||
| a5b14f262e | |||
| 350aae09d2 | |||
| 63ce358f30 | |||
| 40f08a8c0b | |||
| 8c20d53789 | |||
| 576b020384 | |||
| 13eff70112 | |||
| daa301fef0 | |||
| 4b8fcbcee1 | |||
| 7361ffd26b | |||
| be5ed7364b | |||
| 73cbad2f78 | |||
| 02f9727dd8 | |||
| 503674167d | |||
| 54ceedbb1f | |||
| d17ae0b806 | |||
| fad30c3d2c | |||
| 8056433c44 | |||
| 12533bcb2b | |||
| 2da19eebd3 | |||
| a99b9da3d4 | |||
| 7142e25e78 | |||
| dd2e947976 | |||
| 357fded2b5 | |||
| 70e616db7c | |||
| 70fd243e3b | |||
| 5caecf548c | |||
| b7d56d5471 | |||
| 41c540fb1e | |||
| e7d6e86395 | |||
| c0bda4db88 | |||
| 88e8c7c94b | |||
| 9faebb5365 | |||
| 714ab21a6e | |||
| 8dae261d20 | |||
| 6fd0010325 | |||
| 7ef2730506 | |||
| 6407d7818d | |||
| c2de8ffd14 | |||
| f0e12d5301 | |||
| 21ed6bee25 | |||
| b9793abec6 | |||
| 5471fc808a | |||
| 281338409b | |||
| a833c4b4ee | |||
| bb6a24e6aa | |||
| 83bc045a56 | |||
| 6363a776f7 | |||
| f72c79d54a | |||
| 32bc7a6fe5 | |||
| 1186520617 | |||
| b5892a2b5e | |||
| 4f356e35a9 | |||
| 79eb94d3cd | |||
| 18552a8d5f | |||
| b047d28476 | |||
| 80458ebc72 | |||
| 6d415c508b | |||
| a936cbf5fb | |||
| 1ac1ac984e | |||
| 54268bfeed | |||
| 8204f6a71f | |||
| bbe804a14b | |||
| 28cf567e41 | |||
| 5bb865218f | |||
| 94692acb14 | |||
| 384dff9abe | |||
| 5bf3907862 | |||
| c8220aeea8 | |||
| 9155bfe27f | |||
| 1c5f16ae26 | |||
| d9fdffe88e | |||
| 0c05ce0eb1 | |||
| f28a4427a2 | |||
| e5ba8666de | |||
| 2fa3176399 | |||
| d1f2b19e6e | |||
| a8a3e0be05 | |||
| f38ff1bdbd | |||
| 34fdb0fe23 | |||
| 793de306cf | |||
| 0720923115 | |||
| 95666637b6 | |||
| 315f426f5c | |||
| 67dac7ae99 | |||
| a07499796a | |||
| fcab9c89f2 | |||
| cbe414864f | |||
| 0231fac514 | |||
| ff0c048ad9 | |||
| 96d6103e0b | |||
| 0ae92d78eb | |||
| 5e69036bbc | |||
| 6395ddac2c | |||
| df3c113711 | |||
| f3df2dab3d | |||
| cfef58361f | |||
| d8ab8a00f2 | |||
| 2733cb4a41 | |||
| a2a28b02e8 | |||
| 03765e08b9 | |||
| 9be0f100c4 | |||
| a3e312d133 | |||
| 3341dd8899 | |||
| 3bd30f7382 | |||
| 844a96d0b9 | |||
| 84a37e1460 | |||
| 36043ecc3e | |||
| d75ba16223 | |||
| 03dfb2965c | |||
| 9f822906b8 | |||
| eb92fd1f48 | |||
| 076cb7decd | |||
| 1961032592 | |||
| da67e435b1 | |||
| fffa406aa4 | |||
| 488c3de389 | |||
| 45747144ff | |||
| bc7ba69f9b | |||
| 423c6523ba | |||
| ecd6c57faa | |||
| 19de09afe1 | |||
| b0da0fded0 | |||
| 58a42443df | |||
| af42c39e6c | |||
| 3acc2b4216 | |||
| 932a39f5fd | |||
| 6956b935b3 | |||
| 7bdefbeb9a | |||
| 6fe9b340b4 | |||
| b25e8b91a5 | |||
| f7e53d90fa | |||
| 41f84f8b40 | |||
| b17de011dc | |||
| 14dd3f6610 | |||
| 716efc4b51 | |||
| 143ccf7a74 | |||
| dd750bc094 | |||
| ef83f895b9 | |||
| cd3be5fb02 | |||
| f29e98f772 | |||
| 308e5e9cc0 | |||
| 744f567f40 | |||
| b41b125c15 | |||
| 3df0a786e4 | |||
| fd4de77651 | |||
| ace14d3ad7 | |||
| 5c228805ad | |||
| 3c4528b8f4 | |||
| c87433e0c2 | |||
| f3888bb0b0 | |||
| 43ebb4fc43 | |||
| 94a7abcebc | |||
| f4d6f40442 | |||
| 269981ee6a | |||
| 34bc709bc2 | |||
| 32d0f6770c | |||
| caa0db9fa9 | |||
| 6ae041bca6 | |||
| fa1dfbd113 | |||
| a6889776f4 | |||
| 621d4b30da | |||
| 693907d3c8 | |||
| 2108641a37 | |||
| 418b6f7cb3 | |||
| 1a4e5346ed | |||
| ed200a0219 | |||
| c4487ba836 | |||
| 2c2d80d9a0 | |||
| 6247a7bf7c | |||
| 22f8660c8e | |||
| 175e2c7254 | |||
| 536262f2ec | |||
| a0a3187b30 | |||
| f3b5f9e8f0 | |||
| e6d5379e39 | |||
| 8bf7356f38 | |||
| d7b7644e68 | |||
| 8dd0739072 | |||
| 838509c0a4 | |||
| e6252d511c | |||
| e2e05294b0 | |||
| 3130a3f3de | |||
| 884d5e0132 | |||
| 8d28bd445a | |||
| 75c0a59bb4 | |||
| d643caf8fe | |||
| a010d88def | |||
| d3116fcea8 | |||
| 947de54cee | |||
| cda2866e7c | |||
| ae109f69cc | |||
| 5fdeaa81d5 | |||
| db2e1d2c74 | |||
| 396680b856 | |||
| 21198bf1c1 | |||
| aa6a44bb20 | |||
| 10642d14ea | |||
| 6ac45333fe | |||
| 0962b9e5e6 | |||
| c630cb4016 | |||
| 21e016378c | |||
| 7cee6df3f7 | |||
| 57325f51ff | |||
| 20a2aa4274 | |||
| 5c1c43d2e1 | |||
| f3a0a6a463 | |||
| 416c4ced2c | |||
| 3f51d342d1 | |||
| 1f54c72d1d | |||
| f90fd5330e | |||
| 653b154b0e | |||
| 6e0ace1914 | |||
| 5b8d5eb5e9 | |||
| 3a3d2b154f | |||
| f3606e3e21 | |||
| 9c16ffcaf4 | |||
| 4c319a1072 | |||
| 9b37104655 | |||
| 3e55408cb5 | |||
| 4b21fcf5af | |||
| d062352de7 | |||
| b4f87bb8fc | |||
| 225b492109 | |||
| 7825caa1fd | |||
| b79196f911 | |||
| d8cbd5554f | |||
| 5f7e43f170 | |||
| b644c72eb0 | |||
| 0b8296e525 | |||
| 651f6d8b57 | |||
| 13b19612d6 | |||
| c12a1c6898 | |||
| a23d42fc04 | |||
| 2a2519414b | |||
| c46f0353d1 | |||
| 8f4610e007 | |||
| 63ca200016 | |||
| d87e833310 | |||
| 198dbf348c | |||
| 094677f179 | |||
| e6167f1c0b | |||
| 23ddc9db2a | |||
| 8443df3826 | |||
| 6e5596e80c | |||
| f00d13125b | |||
| 3af2f8ad7c | |||
| 59afaca753 | |||
| f35eeed0eb | |||
| 8b19e3c215 | |||
| dca62efba9 | |||
| 923bbb44a8 | |||
| d4c455c180 | |||
| 5ac618681a | |||
| d191247505 | |||
| 9b55e96fa0 | |||
| 8868c0b6d3 | |||
| 534ff92ba5 | |||
| 31ec824aef | |||
| b732b6417e | |||
| 998b5f43fb | |||
| ff31995104 | |||
| 48a7cd4e60 | |||
| acd34a9372 | |||
| 2ce67a25ef | |||
| 700b811813 | |||
| 16f04b13d7 | |||
| e3ad4a5e14 | |||
| 579446d5d9 | |||
| fc07f7a0ff | |||
| dd6054efeb | |||
| 27a6a15d66 | |||
| 32e93579fa | |||
| c8719ce418 | |||
| 39fe05dfad | |||
| be101154fa | |||
| c329fc0a5f | |||
| e55dbc9681 | |||
| 6f1c67af0d | |||
| 5284a6df88 | |||
| 8bce0a4f2e | |||
| 11d2bbc092 | |||
| ff69c54497 | |||
| 6669f3fcee | |||
| 18e16a5db0 | |||
| 95fdc7bd8a | |||
| 27d696aa7d | |||
| ff6a565452 | |||
| 5f079c8605 | |||
| ea335ebc64 | |||
| b1a801566c | |||
| 2eac2a79b7 | |||
| f9fc8d2e96 | |||
| 89c32f5dd7 | |||
| eff3d7ca8e | |||
| 85225ef6ae | |||
| 2010c6b464 | |||
| 03891b00a7 | |||
| d0ec491b1f | |||
| 38536f42f4 |
82
.circleci/config.yml
Normal file
82
.circleci/config.yml
Normal file
@ -0,0 +1,82 @@
|
||||
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:8
|
||||
|
||||
- &npm_install_if_necessary
|
||||
run:
|
||||
name: Install npm dependencies
|
||||
command: |
|
||||
if [ ! -d node_modules ]; then
|
||||
npm ci
|
||||
fi
|
||||
|
||||
- &cache_key_node_modules
|
||||
key: v1-node_modules-{{ checksum "package-lock.json" }}
|
||||
|
||||
jobs:
|
||||
dependencies:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
<<: *cache_key_node_modules
|
||||
- *npm_install_if_necessary
|
||||
- save_cache:
|
||||
paths:
|
||||
- node_modules
|
||||
<<: *cache_key_node_modules
|
||||
|
||||
lint:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
<<: *cache_key_node_modules
|
||||
- *npm_install_if_necessary
|
||||
- run:
|
||||
name: Linter
|
||||
command: npm run lint
|
||||
test:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
<<: *cache_key_node_modules
|
||||
- *npm_install_if_necessary
|
||||
- run:
|
||||
name: Unit tests
|
||||
command: npm run test
|
||||
coverage:
|
||||
docker:
|
||||
- image: circleci/node:8
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
<<: *cache_key_node_modules
|
||||
- *npm_install_if_necessary
|
||||
- run:
|
||||
name: Unit tests with coverage report
|
||||
command: npm run coverage
|
||||
|
||||
# TODO(xinbenlv, #1839): run SOLC_NIGHTLY to be run but allow it to fail.
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
everything:
|
||||
jobs:
|
||||
- dependencies
|
||||
- lint:
|
||||
requires:
|
||||
- dependencies
|
||||
- test:
|
||||
requires:
|
||||
- dependencies
|
||||
- coverage:
|
||||
requires:
|
||||
- dependencies
|
||||
@ -1,5 +0,0 @@
|
||||
# configure your infura api key (not technically required)
|
||||
INFURA_API_KEY=
|
||||
|
||||
# change the mnemonic that your hd wallet is seeded with
|
||||
MNEMONIC=
|
||||
11
.eslintrc
11
.eslintrc
@ -1,22 +1,23 @@
|
||||
{
|
||||
"extends" : [
|
||||
"standard",
|
||||
"plugin:promise/recommended"
|
||||
"plugin:promise/recommended",
|
||||
],
|
||||
"plugins": [
|
||||
"promise"
|
||||
"mocha-no-only",
|
||||
"promise",
|
||||
],
|
||||
"env": {
|
||||
"browser" : true,
|
||||
"node" : true,
|
||||
"mocha" : true,
|
||||
"jest" : true
|
||||
"jest" : true,
|
||||
},
|
||||
"globals" : {
|
||||
"artifacts": false,
|
||||
"contract": false,
|
||||
"assert": false,
|
||||
"web3": false
|
||||
"web3": false,
|
||||
},
|
||||
"rules": {
|
||||
|
||||
@ -49,6 +50,8 @@
|
||||
"semi": ["error", "always"],
|
||||
"space-before-function-paren": ["error", "always"],
|
||||
|
||||
"mocha-no-only/mocha-no-only": ["error"],
|
||||
|
||||
"promise/always-return": "off",
|
||||
"promise/avoid-new": "off",
|
||||
}
|
||||
|
||||
34
.github/ISSUE_TEMPLATE.md
vendored
34
.github/ISSUE_TEMPLATE.md
vendored
@ -1,34 +0,0 @@
|
||||
## 🎉 Description
|
||||
|
||||
<!-- Briefly describe the issue you are experiencing (or the feature you want to see added to OpenZeppelin). Tell us what you were trying to do and what happened instead. **Remember, this is _not_ a place to ask for help debugging code; for that, we welcome you in the [OpenZeppelin Slack Channel](https://slack.openzeppelin.org/).** -->
|
||||
|
||||
- [ ] 🐛 This is a bug report.
|
||||
- [ ] 📈 This is a feature request.
|
||||
|
||||
<!-- Please check one of the above by placing an x in the box. -->
|
||||
|
||||
## 💻 Environment
|
||||
|
||||
Next, we need to know what your environment looks like.
|
||||
|
||||
- Which version of OpenZeppelin are you using?
|
||||
- What network are you deploying to? Ganache? Ropsten?
|
||||
- How are you deploying your OpenZeppelin-backed contracts? truffle? Remix? Let us know!
|
||||
|
||||
## 📝 Details
|
||||
|
||||
Describe the problem you have been experiencing in more detail. Include as much information as you think is relevant. Keep in mind that transactions can fail for many reasons; context is key here.
|
||||
|
||||
## 🔢 Code To Reproduce Issue [ Good To Have ]
|
||||
|
||||
Please remember that with sample code it's easier to reproduce the bug and it's much faster to fix it.
|
||||
|
||||
```
|
||||
insert short code snippets here
|
||||
```
|
||||
|
||||
<!-- If your code is larger, consider linking us to a repo illustrating your issue. -->
|
||||
|
||||
## 👍 Other Information
|
||||
|
||||
<!-- List any other information that is relevant to your issue. Error logs, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc. -->
|
||||
21
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
21
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report a bug in OpenZeppelin
|
||||
|
||||
---
|
||||
|
||||
<!-- Briefly describe the issue you're experiencing. Tell us what you were trying to do and what happened instead. -->
|
||||
|
||||
<!-- Remember, this is not a place to ask for help debugging code. For that, we welcome you in the OpenZeppelin Slack channel: https://slack.openzeppelin.org/. -->
|
||||
|
||||
**💻 Environment**
|
||||
|
||||
<!-- Tell us what version of OpenZeppelin you're using, and how you're using it: Truffle, Remix, etc. -->
|
||||
|
||||
**📝 Details**
|
||||
|
||||
<!-- Describe the problem you have been experiencing in more detail. Include as much information as you think is relevant. Keep in mind that transactions can fail for many reasons; context is key here. -->
|
||||
|
||||
**🔢 Code to reproduce bug**
|
||||
|
||||
<!-- We will be able to better help if you provide a minimal example that triggers the bug. -->
|
||||
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for OpenZeppelin
|
||||
|
||||
---
|
||||
|
||||
**🧐 Motivation**
|
||||
<!-- Is your feature request related to a specific problem? Is it just a crazy idea? Tell us about it! -->
|
||||
|
||||
**📝 Details**
|
||||
<!-- Please describe your feature request in detail. -->
|
||||
|
||||
<!-- Make sure that you have reviewed the OpenZeppelin Contributor Guidelines. -->
|
||||
<!-- https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/CONTRIBUTING.md -->
|
||||
25
.github/PULL_REQUEST_TEMPLATE.md
vendored
25
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,17 +1,22 @@
|
||||
<!-- 0. 🎉 Thank you for submitting a PR! -->
|
||||
|
||||
<!-- 1. **Does this close any open issues?** If so, list them here. If not, remove the `Fixes #` line. -->
|
||||
<!-- 1. Does this close any open issues? Please list them below. -->
|
||||
|
||||
<!-- 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 #
|
||||
|
||||
# 🚀 Description
|
||||
|
||||
<!-- 2. Describe the changes introduced in this pull request -->
|
||||
<!-- 2. Describe the changes introduced in this pull request. -->
|
||||
<!-- Include any context necessary for understanding the PR's purpose. -->
|
||||
|
||||
<!-- 3. Before submitting, please review the following checklist: -->
|
||||
|
||||
- [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](../blob/master/CONTRIBUTING.md)
|
||||
- [ ] ✅ I've added tests where applicable to test my new functionality.
|
||||
- [ ] 📖 I've made sure that my contracts are well-documented.
|
||||
- [ ] 🎨 I've run the JS/Solidity linters and fixed any issues (`npm run lint:fix`).
|
||||
<!-- 3. Before submitting, please make sure that you have:
|
||||
- reviewed the OpenZeppelin Contributor Guidelines
|
||||
(https://github.com/OpenZeppelin/openzeppelin-solidity/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.
|
||||
-->
|
||||
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@ -32,8 +32,13 @@ npm-debug.log
|
||||
# truffle build directory
|
||||
build/
|
||||
|
||||
# lol macs
|
||||
.DS_Store/
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# truffle
|
||||
.node-xmlhttprequest-*
|
||||
|
||||
.openzeppelin/.session
|
||||
|
||||
# IntelliJ IDE
|
||||
.idea
|
||||
|
||||
@ -1 +0,0 @@
|
||||
v8.9.1
|
||||
923
.openzeppelin/kovan.json
Normal file
923
.openzeppelin/kovan.json
Normal file
@ -0,0 +1,923 @@
|
||||
{
|
||||
"contracts": {
|
||||
"PaymentSplitter": {
|
||||
"address": "0x6CE7dEca802e0c5c133f7cbbE719B1da305A6Ae5",
|
||||
"constructorCode": "608060405234801561001057600080fd5b50610be3806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "6f1453b45140bc5e426ffccfcae058daa1fc53439580e3c9e6b7f73aac54c5d8",
|
||||
"localBytecodeHash": "1b0f3688284b1c14c41ce636762c4504188969cb0e5a052159b61b87cbd4e8a8",
|
||||
"deployedBytecodeHash": "1b0f3688284b1c14c41ce636762c4504188969cb0e5a052159b61b87cbd4e8a8",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_array:dyn<t_address>": {
|
||||
"id": "t_array:dyn<t_address>",
|
||||
"valueType": "t_address",
|
||||
"length": "dyn",
|
||||
"kind": "array",
|
||||
"label": "address[]"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_totalShares",
|
||||
"astId": 9541,
|
||||
"type": "t_uint256",
|
||||
"src": "555:28:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_totalReleased",
|
||||
"astId": 9543,
|
||||
"type": "t_uint256",
|
||||
"src": "589:30:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_shares",
|
||||
"astId": 9547,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "626:43:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_released",
|
||||
"astId": 9551,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "675:45:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_payees",
|
||||
"astId": 9554,
|
||||
"type": "t_array:dyn<t_address>",
|
||||
"src": "726:25:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "______gap",
|
||||
"astId": 9800,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "3251:29:120"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [],
|
||||
"storageDiff": []
|
||||
}
|
||||
},
|
||||
"StandaloneERC20": {
|
||||
"address": "0x65e22dDa13EFa3A7fadd3EF62afC815110748308",
|
||||
"constructorCode": "608060405234801561001057600080fd5b5061290d806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "fffcccf2a7439f83b3eb59e01f5217ea14764c782fde08c6edd511f0c7d1e742",
|
||||
"localBytecodeHash": "be0848d29ef0345b76e9810a67328a1deb1a7b07dd050c9212d3099430cf4222",
|
||||
"deployedBytecodeHash": "be0848d29ef0345b76e9810a67328a1deb1a7b07dd050c9212d3099430cf4222",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_string": {
|
||||
"id": "t_string",
|
||||
"kind": "elementary",
|
||||
"label": "string"
|
||||
},
|
||||
"t_uint8": {
|
||||
"id": "t_uint8",
|
||||
"kind": "elementary",
|
||||
"label": "uint8"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Roles.Role>": {
|
||||
"id": "t_struct<Roles.Role>",
|
||||
"kind": "struct",
|
||||
"label": "Roles.Role",
|
||||
"members": [
|
||||
{
|
||||
"label": "bearer",
|
||||
"astId": 1222,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "150:32:8"
|
||||
}
|
||||
]
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_name",
|
||||
"astId": 10735,
|
||||
"type": "t_string",
|
||||
"src": "397:20:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_symbol",
|
||||
"astId": 10737,
|
||||
"type": "t_string",
|
||||
"src": "423:22:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_decimals",
|
||||
"astId": 10739,
|
||||
"type": "t_uint8",
|
||||
"src": "451:23:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10791,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1112:29:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_balances",
|
||||
"astId": 10239,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "767:46:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_allowed",
|
||||
"astId": 10245,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "820:66:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_totalSupply",
|
||||
"astId": 10247,
|
||||
"type": "t_uint256",
|
||||
"src": "893:28:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10612,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "7729:29:125"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1547,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:10"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Mintable",
|
||||
"path": "contracts/token/ERC20/ERC20Mintable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10840,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "760:29:129"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1666,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:11"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "_paused",
|
||||
"astId": 5401,
|
||||
"type": "t_bool",
|
||||
"src": "367:20:42"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5482,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1444:29:42"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Pausable",
|
||||
"path": "contracts/token/ERC20/ERC20Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10963,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1209:29:130"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
}
|
||||
],
|
||||
"storageDiff": [
|
||||
{
|
||||
"action": "rename",
|
||||
"updated": {
|
||||
"index": 8,
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_allowed",
|
||||
"astId": 10245,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "820:66:125"
|
||||
},
|
||||
"original": {
|
||||
"index": 8,
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_allowances",
|
||||
"astId": 9135,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "1410:69:115"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"TokenVesting": {
|
||||
"address": "0x94CeBcF32a18eA573C85293883f7D3352b360ec1",
|
||||
"constructorCode": "608060405234801561001057600080fd5b506114d8806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "7a623cf584a99e031f19436c354675c6b43934b0d3705ffc3353558b1fb39496",
|
||||
"localBytecodeHash": "e1b9a489ba9fe411cb345548cfbdfb8ef0a9a528c48a9bd07a08f5728a432ea3",
|
||||
"deployedBytecodeHash": "e1b9a489ba9fe411cb345548cfbdfb8ef0a9a528c48a9bd07a08f5728a432ea3",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "Ownable",
|
||||
"path": "contracts/ownership/Ownable.sol",
|
||||
"label": "_owner",
|
||||
"astId": 9325,
|
||||
"type": "t_address",
|
||||
"src": "317:22:118"
|
||||
},
|
||||
{
|
||||
"contract": "Ownable",
|
||||
"path": "contracts/ownership/Ownable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 9436,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "2277:29:118"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_beneficiary",
|
||||
"astId": 4658,
|
||||
"type": "t_address",
|
||||
"src": "1148:28:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_cliff",
|
||||
"astId": 4660,
|
||||
"type": "t_uint256",
|
||||
"src": "1278:22:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_start",
|
||||
"astId": 4662,
|
||||
"type": "t_uint256",
|
||||
"src": "1306:22:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_duration",
|
||||
"astId": 4664,
|
||||
"type": "t_uint256",
|
||||
"src": "1334:25:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_revocable",
|
||||
"astId": 4666,
|
||||
"type": "t_bool",
|
||||
"src": "1366:23:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_released",
|
||||
"astId": 4670,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "1396:46:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_revoked",
|
||||
"astId": 4674,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "1448:42:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5016,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "5852:29:36"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [],
|
||||
"storageDiff": []
|
||||
}
|
||||
},
|
||||
"StandaloneERC721": {
|
||||
"address": "0xB1a160cD691cF3754AA4AE91ba6e2E18798CcE36",
|
||||
"constructorCode": "608060405234801561001057600080fd5b506135c8806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "b71f19d62583c08240fd85bec42565407f679b1873d7f6e97295a894c7864e2d",
|
||||
"localBytecodeHash": "2e71874460f43d0696496418b1abf57ed58ce1dc524044860260dda9d7de7fab",
|
||||
"deployedBytecodeHash": "2e71874460f43d0696496418b1abf57ed58ce1dc524044860260dda9d7de7fab",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_mapping<t_address>": {
|
||||
"id": "t_mapping<t_address>",
|
||||
"valueType": "t_address",
|
||||
"label": "mapping(key => address)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Counters.Counter>": {
|
||||
"id": "t_struct<Counters.Counter>",
|
||||
"kind": "struct",
|
||||
"label": "Counters.Counter",
|
||||
"members": [
|
||||
{
|
||||
"label": "_value",
|
||||
"astId": 3632,
|
||||
"type": "t_uint256",
|
||||
"src": "1021:14:30"
|
||||
}
|
||||
]
|
||||
},
|
||||
"t_mapping<t_struct<Counters.Counter>>": {
|
||||
"id": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"valueType": "t_struct<Counters.Counter>",
|
||||
"label": "mapping(key => Counters.Counter)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_array:dyn<t_uint256>": {
|
||||
"id": "t_array:dyn<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "dyn",
|
||||
"kind": "array",
|
||||
"label": "uint256[]"
|
||||
},
|
||||
"t_mapping<t_array:dyn<t_uint256>>": {
|
||||
"id": "t_mapping<t_array:dyn<t_uint256>>",
|
||||
"valueType": "t_array:dyn<t_uint256>",
|
||||
"label": "mapping(key => uint256[])",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_string": {
|
||||
"id": "t_string",
|
||||
"kind": "elementary",
|
||||
"label": "string"
|
||||
},
|
||||
"t_mapping<t_string>": {
|
||||
"id": "t_mapping<t_string>",
|
||||
"valueType": "t_string",
|
||||
"label": "mapping(key => string)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Roles.Role>": {
|
||||
"id": "t_struct<Roles.Role>",
|
||||
"kind": "struct",
|
||||
"label": "Roles.Role",
|
||||
"members": [
|
||||
{
|
||||
"label": "bearer",
|
||||
"astId": 1222,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "150:32:8"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "ERC165",
|
||||
"path": "contracts/introspection/ERC165.sol",
|
||||
"label": "_supportedInterfaces",
|
||||
"astId": 5191,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "511:52:39"
|
||||
},
|
||||
{
|
||||
"contract": "ERC165",
|
||||
"path": "contracts/introspection/ERC165.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5235,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1244:29:39"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_tokenOwner",
|
||||
"astId": 11595,
|
||||
"type": "t_mapping<t_address>",
|
||||
"src": "844:48:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_tokenApprovals",
|
||||
"astId": 11599,
|
||||
"type": "t_mapping<t_address>",
|
||||
"src": "948:52:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_ownedTokensCount",
|
||||
"astId": 11603,
|
||||
"type": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"src": "1058:63:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_operatorApprovals",
|
||||
"astId": 11609,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "1176:73:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12132,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "11673:29:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_ownedTokens",
|
||||
"astId": 12183,
|
||||
"type": "t_mapping<t_array:dyn<t_uint256>>",
|
||||
"src": "460:50:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_ownedTokensIndex",
|
||||
"astId": 12187,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "580:53:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_allTokens",
|
||||
"astId": 12190,
|
||||
"type": "t_array:dyn<t_uint256>",
|
||||
"src": "694:28:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_allTokensIndex",
|
||||
"astId": 12194,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "793:51:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12523,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "8816:29:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_name",
|
||||
"astId": 12590,
|
||||
"type": "t_string",
|
||||
"src": "281:20:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_symbol",
|
||||
"astId": 12592,
|
||||
"type": "t_string",
|
||||
"src": "328:22:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_tokenURIs",
|
||||
"astId": 12596,
|
||||
"type": "t_mapping<t_string>",
|
||||
"src": "396:45:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12725,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "2849:29:140"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1547,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:10"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721MetadataMintable",
|
||||
"path": "contracts/token/ERC721/ERC721MetadataMintable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12795,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1055:29:141"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1666,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:11"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "_paused",
|
||||
"astId": 5401,
|
||||
"type": "t_bool",
|
||||
"src": "367:20:42"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5482,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1444:29:42"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Pausable",
|
||||
"path": "contracts/token/ERC721/ERC721Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12940,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "865:29:143"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_ownedTokensCount",
|
||||
"astId": 11603,
|
||||
"type": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"src": "1058:63:135"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
}
|
||||
],
|
||||
"storageDiff": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"solidityLibs": {},
|
||||
"proxies": {},
|
||||
"manifestVersion": "2.2",
|
||||
"frozen": true,
|
||||
"app": {
|
||||
"address": "0xf5829D56998ccC1405B7eAbCCAC78164AF270D39"
|
||||
},
|
||||
"package": {
|
||||
"address": "0xB6F8F11b166D526932ee04ffe4D25B810f619E34"
|
||||
},
|
||||
"provider": {
|
||||
"address": "0x6290189B262fe198A51e3a3ac06A09c4782D3bD3"
|
||||
},
|
||||
"version": "2.2.2"
|
||||
}
|
||||
882
.openzeppelin/mainnet.json
Normal file
882
.openzeppelin/mainnet.json
Normal file
@ -0,0 +1,882 @@
|
||||
{
|
||||
"contracts": {
|
||||
"PaymentSplitter": {
|
||||
"address": "0xc6FBEe275DC5a4e7c6bc94bEd156fe10ee09eAba",
|
||||
"constructorCode": "608060405234801561001057600080fd5b50610be3806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "6f1453b45140bc5e426ffccfcae058daa1fc53439580e3c9e6b7f73aac54c5d8",
|
||||
"localBytecodeHash": "1b0f3688284b1c14c41ce636762c4504188969cb0e5a052159b61b87cbd4e8a8",
|
||||
"deployedBytecodeHash": "1b0f3688284b1c14c41ce636762c4504188969cb0e5a052159b61b87cbd4e8a8",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_array:dyn<t_address>": {
|
||||
"id": "t_array:dyn<t_address>",
|
||||
"valueType": "t_address",
|
||||
"length": "dyn",
|
||||
"kind": "array",
|
||||
"label": "address[]"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_totalShares",
|
||||
"astId": 9541,
|
||||
"type": "t_uint256",
|
||||
"src": "555:28:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_totalReleased",
|
||||
"astId": 9543,
|
||||
"type": "t_uint256",
|
||||
"src": "589:30:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_shares",
|
||||
"astId": 9547,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "626:43:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_released",
|
||||
"astId": 9551,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "675:45:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_payees",
|
||||
"astId": 9554,
|
||||
"type": "t_array:dyn<t_address>",
|
||||
"src": "726:25:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "______gap",
|
||||
"astId": 9800,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "3251:29:120"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [],
|
||||
"storageDiff": []
|
||||
}
|
||||
},
|
||||
"TokenVesting": {
|
||||
"address": "0x0E0C247759F066cCbd299dFADe853EdA8D2F3205",
|
||||
"constructorCode": "608060405234801561001057600080fd5b506114d8806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "7a623cf584a99e031f19436c354675c6b43934b0d3705ffc3353558b1fb39496",
|
||||
"localBytecodeHash": "e1b9a489ba9fe411cb345548cfbdfb8ef0a9a528c48a9bd07a08f5728a432ea3",
|
||||
"deployedBytecodeHash": "e1b9a489ba9fe411cb345548cfbdfb8ef0a9a528c48a9bd07a08f5728a432ea3",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "Ownable",
|
||||
"path": "contracts/ownership/Ownable.sol",
|
||||
"label": "_owner",
|
||||
"astId": 9325,
|
||||
"type": "t_address",
|
||||
"src": "317:22:118"
|
||||
},
|
||||
{
|
||||
"contract": "Ownable",
|
||||
"path": "contracts/ownership/Ownable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 9436,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "2277:29:118"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_beneficiary",
|
||||
"astId": 4658,
|
||||
"type": "t_address",
|
||||
"src": "1148:28:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_cliff",
|
||||
"astId": 4660,
|
||||
"type": "t_uint256",
|
||||
"src": "1278:22:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_start",
|
||||
"astId": 4662,
|
||||
"type": "t_uint256",
|
||||
"src": "1306:22:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_duration",
|
||||
"astId": 4664,
|
||||
"type": "t_uint256",
|
||||
"src": "1334:25:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_revocable",
|
||||
"astId": 4666,
|
||||
"type": "t_bool",
|
||||
"src": "1366:23:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_released",
|
||||
"astId": 4670,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "1396:46:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_revoked",
|
||||
"astId": 4674,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "1448:42:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5016,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "5852:29:36"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [],
|
||||
"storageDiff": []
|
||||
}
|
||||
},
|
||||
"StandaloneERC721": {
|
||||
"address": "0xf9D147d5ECfd57EF817EF75B4a329f4fFbb4f100",
|
||||
"constructorCode": "608060405234801561001057600080fd5b506135c8806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "b71f19d62583c08240fd85bec42565407f679b1873d7f6e97295a894c7864e2d",
|
||||
"localBytecodeHash": "2e71874460f43d0696496418b1abf57ed58ce1dc524044860260dda9d7de7fab",
|
||||
"deployedBytecodeHash": "2e71874460f43d0696496418b1abf57ed58ce1dc524044860260dda9d7de7fab",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_mapping<t_address>": {
|
||||
"id": "t_mapping<t_address>",
|
||||
"valueType": "t_address",
|
||||
"label": "mapping(key => address)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Counters.Counter>": {
|
||||
"id": "t_struct<Counters.Counter>",
|
||||
"kind": "struct",
|
||||
"label": "Counters.Counter",
|
||||
"members": [
|
||||
{
|
||||
"label": "_value",
|
||||
"astId": 3632,
|
||||
"type": "t_uint256",
|
||||
"src": "1021:14:30"
|
||||
}
|
||||
]
|
||||
},
|
||||
"t_mapping<t_struct<Counters.Counter>>": {
|
||||
"id": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"valueType": "t_struct<Counters.Counter>",
|
||||
"label": "mapping(key => Counters.Counter)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_array:dyn<t_uint256>": {
|
||||
"id": "t_array:dyn<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "dyn",
|
||||
"kind": "array",
|
||||
"label": "uint256[]"
|
||||
},
|
||||
"t_mapping<t_array:dyn<t_uint256>>": {
|
||||
"id": "t_mapping<t_array:dyn<t_uint256>>",
|
||||
"valueType": "t_array:dyn<t_uint256>",
|
||||
"label": "mapping(key => uint256[])",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_string": {
|
||||
"id": "t_string",
|
||||
"kind": "elementary",
|
||||
"label": "string"
|
||||
},
|
||||
"t_mapping<t_string>": {
|
||||
"id": "t_mapping<t_string>",
|
||||
"valueType": "t_string",
|
||||
"label": "mapping(key => string)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Roles.Role>": {
|
||||
"id": "t_struct<Roles.Role>",
|
||||
"kind": "struct",
|
||||
"label": "Roles.Role",
|
||||
"members": [
|
||||
{
|
||||
"label": "bearer",
|
||||
"astId": 1222,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "150:32:8"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "ERC165",
|
||||
"path": "contracts/introspection/ERC165.sol",
|
||||
"label": "_supportedInterfaces",
|
||||
"astId": 5191,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "511:52:39"
|
||||
},
|
||||
{
|
||||
"contract": "ERC165",
|
||||
"path": "contracts/introspection/ERC165.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5235,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1244:29:39"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_tokenOwner",
|
||||
"astId": 11595,
|
||||
"type": "t_mapping<t_address>",
|
||||
"src": "844:48:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_tokenApprovals",
|
||||
"astId": 11599,
|
||||
"type": "t_mapping<t_address>",
|
||||
"src": "948:52:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_ownedTokensCount",
|
||||
"astId": 11603,
|
||||
"type": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"src": "1058:63:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_operatorApprovals",
|
||||
"astId": 11609,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "1176:73:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12132,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "11673:29:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_ownedTokens",
|
||||
"astId": 12183,
|
||||
"type": "t_mapping<t_array:dyn<t_uint256>>",
|
||||
"src": "460:50:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_ownedTokensIndex",
|
||||
"astId": 12187,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "580:53:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_allTokens",
|
||||
"astId": 12190,
|
||||
"type": "t_array:dyn<t_uint256>",
|
||||
"src": "694:28:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_allTokensIndex",
|
||||
"astId": 12194,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "793:51:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12523,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "8816:29:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_name",
|
||||
"astId": 12590,
|
||||
"type": "t_string",
|
||||
"src": "281:20:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_symbol",
|
||||
"astId": 12592,
|
||||
"type": "t_string",
|
||||
"src": "328:22:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_tokenURIs",
|
||||
"astId": 12596,
|
||||
"type": "t_mapping<t_string>",
|
||||
"src": "396:45:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12725,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "2849:29:140"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1547,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:10"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721MetadataMintable",
|
||||
"path": "contracts/token/ERC721/ERC721MetadataMintable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12795,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1055:29:141"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1666,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:11"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "_paused",
|
||||
"astId": 5401,
|
||||
"type": "t_bool",
|
||||
"src": "367:20:42"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5482,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1444:29:42"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Pausable",
|
||||
"path": "contracts/token/ERC721/ERC721Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12940,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "865:29:143"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_ownedTokensCount",
|
||||
"astId": 11603,
|
||||
"type": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"src": "1058:63:135"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
}
|
||||
],
|
||||
"storageDiff": []
|
||||
}
|
||||
},
|
||||
"StandaloneERC20": {
|
||||
"address": "0x2dD5AD2ab73E0cD7E7A05c63aD7D40deD284B69A",
|
||||
"constructorCode": "608060405234801561001057600080fd5b5061290d806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "fffcccf2a7439f83b3eb59e01f5217ea14764c782fde08c6edd511f0c7d1e742",
|
||||
"localBytecodeHash": "be0848d29ef0345b76e9810a67328a1deb1a7b07dd050c9212d3099430cf4222",
|
||||
"deployedBytecodeHash": "be0848d29ef0345b76e9810a67328a1deb1a7b07dd050c9212d3099430cf4222",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_string": {
|
||||
"id": "t_string",
|
||||
"kind": "elementary",
|
||||
"label": "string"
|
||||
},
|
||||
"t_uint8": {
|
||||
"id": "t_uint8",
|
||||
"kind": "elementary",
|
||||
"label": "uint8"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Roles.Role>": {
|
||||
"id": "t_struct<Roles.Role>",
|
||||
"kind": "struct",
|
||||
"label": "Roles.Role",
|
||||
"members": [
|
||||
{
|
||||
"label": "bearer",
|
||||
"astId": 1222,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "150:32:8"
|
||||
}
|
||||
]
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_name",
|
||||
"astId": 10735,
|
||||
"type": "t_string",
|
||||
"src": "397:20:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_symbol",
|
||||
"astId": 10737,
|
||||
"type": "t_string",
|
||||
"src": "423:22:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_decimals",
|
||||
"astId": 10739,
|
||||
"type": "t_uint8",
|
||||
"src": "451:23:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10791,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1112:29:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_balances",
|
||||
"astId": 10239,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "767:46:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_allowed",
|
||||
"astId": 10245,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "820:66:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_totalSupply",
|
||||
"astId": 10247,
|
||||
"type": "t_uint256",
|
||||
"src": "893:28:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10612,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "7729:29:125"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1547,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:10"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Mintable",
|
||||
"path": "contracts/token/ERC20/ERC20Mintable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10840,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "760:29:129"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1666,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:11"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "_paused",
|
||||
"astId": 5401,
|
||||
"type": "t_bool",
|
||||
"src": "367:20:42"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5482,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1444:29:42"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Pausable",
|
||||
"path": "contracts/token/ERC20/ERC20Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10963,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1209:29:130"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"solidityLibs": {},
|
||||
"proxies": {},
|
||||
"manifestVersion": "2.2",
|
||||
"frozen": true,
|
||||
"app": {
|
||||
"address": "0x2Ba1a8C7352a5B5Ea3ea3408F89e1bA7920d36CE"
|
||||
},
|
||||
"package": {
|
||||
"address": "0x778dddF23Ec1B5Cb18394c6C110480CaaDB3B0f6"
|
||||
},
|
||||
"provider": {
|
||||
"address": "0xd49C0d11A4a7E49c64d954261570FD2d1589f5d2"
|
||||
},
|
||||
"version": "2.2.2"
|
||||
}
|
||||
19
.openzeppelin/project.json
Normal file
19
.openzeppelin/project.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"manifestVersion": "2.2",
|
||||
"name": "@openzeppelin/contracts-ethereum-package",
|
||||
"publish": true,
|
||||
"version": "2.2.2",
|
||||
"contracts": {
|
||||
"StandaloneERC20": "StandaloneERC20",
|
||||
"StandaloneERC721": "StandaloneERC721",
|
||||
"TokenVesting": "TokenVesting",
|
||||
"PaymentSplitter": "PaymentSplitter"
|
||||
},
|
||||
"dependencies": {},
|
||||
"compiler": {
|
||||
"manager": "truffle",
|
||||
"compilerSettings": {
|
||||
"optimizer": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
923
.openzeppelin/rinkeby.json
Normal file
923
.openzeppelin/rinkeby.json
Normal file
@ -0,0 +1,923 @@
|
||||
{
|
||||
"contracts": {
|
||||
"PaymentSplitter": {
|
||||
"address": "0x83aa4099354E7A315939f4c2E06927175e7C649c",
|
||||
"constructorCode": "608060405234801561001057600080fd5b50610be3806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "6f1453b45140bc5e426ffccfcae058daa1fc53439580e3c9e6b7f73aac54c5d8",
|
||||
"localBytecodeHash": "1b0f3688284b1c14c41ce636762c4504188969cb0e5a052159b61b87cbd4e8a8",
|
||||
"deployedBytecodeHash": "1b0f3688284b1c14c41ce636762c4504188969cb0e5a052159b61b87cbd4e8a8",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_array:dyn<t_address>": {
|
||||
"id": "t_array:dyn<t_address>",
|
||||
"valueType": "t_address",
|
||||
"length": "dyn",
|
||||
"kind": "array",
|
||||
"label": "address[]"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_totalShares",
|
||||
"astId": 9541,
|
||||
"type": "t_uint256",
|
||||
"src": "555:28:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_totalReleased",
|
||||
"astId": 9543,
|
||||
"type": "t_uint256",
|
||||
"src": "589:30:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_shares",
|
||||
"astId": 9547,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "626:43:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_released",
|
||||
"astId": 9551,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "675:45:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_payees",
|
||||
"astId": 9554,
|
||||
"type": "t_array:dyn<t_address>",
|
||||
"src": "726:25:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "______gap",
|
||||
"astId": 9800,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "3251:29:120"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [],
|
||||
"storageDiff": []
|
||||
}
|
||||
},
|
||||
"StandaloneERC20": {
|
||||
"address": "0x55855896e5c5407562b3FE1c1Bb7Bf332aFfDa94",
|
||||
"constructorCode": "608060405234801561001057600080fd5b5061290d806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "fffcccf2a7439f83b3eb59e01f5217ea14764c782fde08c6edd511f0c7d1e742",
|
||||
"localBytecodeHash": "be0848d29ef0345b76e9810a67328a1deb1a7b07dd050c9212d3099430cf4222",
|
||||
"deployedBytecodeHash": "be0848d29ef0345b76e9810a67328a1deb1a7b07dd050c9212d3099430cf4222",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_string": {
|
||||
"id": "t_string",
|
||||
"kind": "elementary",
|
||||
"label": "string"
|
||||
},
|
||||
"t_uint8": {
|
||||
"id": "t_uint8",
|
||||
"kind": "elementary",
|
||||
"label": "uint8"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Roles.Role>": {
|
||||
"id": "t_struct<Roles.Role>",
|
||||
"kind": "struct",
|
||||
"label": "Roles.Role",
|
||||
"members": [
|
||||
{
|
||||
"label": "bearer",
|
||||
"astId": 1222,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "150:32:8"
|
||||
}
|
||||
]
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_name",
|
||||
"astId": 10735,
|
||||
"type": "t_string",
|
||||
"src": "397:20:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_symbol",
|
||||
"astId": 10737,
|
||||
"type": "t_string",
|
||||
"src": "423:22:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_decimals",
|
||||
"astId": 10739,
|
||||
"type": "t_uint8",
|
||||
"src": "451:23:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10791,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1112:29:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_balances",
|
||||
"astId": 10239,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "767:46:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_allowed",
|
||||
"astId": 10245,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "820:66:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_totalSupply",
|
||||
"astId": 10247,
|
||||
"type": "t_uint256",
|
||||
"src": "893:28:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10612,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "7729:29:125"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1547,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:10"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Mintable",
|
||||
"path": "contracts/token/ERC20/ERC20Mintable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10840,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "760:29:129"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1666,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:11"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "_paused",
|
||||
"astId": 5401,
|
||||
"type": "t_bool",
|
||||
"src": "367:20:42"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5482,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1444:29:42"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Pausable",
|
||||
"path": "contracts/token/ERC20/ERC20Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10963,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1209:29:130"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
}
|
||||
],
|
||||
"storageDiff": [
|
||||
{
|
||||
"action": "rename",
|
||||
"updated": {
|
||||
"index": 8,
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_allowed",
|
||||
"astId": 10245,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "820:66:125"
|
||||
},
|
||||
"original": {
|
||||
"index": 8,
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_allowances",
|
||||
"astId": 9135,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "1410:69:115"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"TokenVesting": {
|
||||
"address": "0x5B22A5512831ce01269BAbCA8174318f59408435",
|
||||
"constructorCode": "608060405234801561001057600080fd5b506114d8806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "7a623cf584a99e031f19436c354675c6b43934b0d3705ffc3353558b1fb39496",
|
||||
"localBytecodeHash": "e1b9a489ba9fe411cb345548cfbdfb8ef0a9a528c48a9bd07a08f5728a432ea3",
|
||||
"deployedBytecodeHash": "e1b9a489ba9fe411cb345548cfbdfb8ef0a9a528c48a9bd07a08f5728a432ea3",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "Ownable",
|
||||
"path": "contracts/ownership/Ownable.sol",
|
||||
"label": "_owner",
|
||||
"astId": 9325,
|
||||
"type": "t_address",
|
||||
"src": "317:22:118"
|
||||
},
|
||||
{
|
||||
"contract": "Ownable",
|
||||
"path": "contracts/ownership/Ownable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 9436,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "2277:29:118"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_beneficiary",
|
||||
"astId": 4658,
|
||||
"type": "t_address",
|
||||
"src": "1148:28:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_cliff",
|
||||
"astId": 4660,
|
||||
"type": "t_uint256",
|
||||
"src": "1278:22:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_start",
|
||||
"astId": 4662,
|
||||
"type": "t_uint256",
|
||||
"src": "1306:22:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_duration",
|
||||
"astId": 4664,
|
||||
"type": "t_uint256",
|
||||
"src": "1334:25:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_revocable",
|
||||
"astId": 4666,
|
||||
"type": "t_bool",
|
||||
"src": "1366:23:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_released",
|
||||
"astId": 4670,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "1396:46:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_revoked",
|
||||
"astId": 4674,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "1448:42:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5016,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "5852:29:36"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [],
|
||||
"storageDiff": []
|
||||
}
|
||||
},
|
||||
"StandaloneERC721": {
|
||||
"address": "0xfcdA0Ae8c7181521c632550de92B1FB3937D166C",
|
||||
"constructorCode": "608060405234801561001057600080fd5b506135c8806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "b71f19d62583c08240fd85bec42565407f679b1873d7f6e97295a894c7864e2d",
|
||||
"localBytecodeHash": "2e71874460f43d0696496418b1abf57ed58ce1dc524044860260dda9d7de7fab",
|
||||
"deployedBytecodeHash": "2e71874460f43d0696496418b1abf57ed58ce1dc524044860260dda9d7de7fab",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_mapping<t_address>": {
|
||||
"id": "t_mapping<t_address>",
|
||||
"valueType": "t_address",
|
||||
"label": "mapping(key => address)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Counters.Counter>": {
|
||||
"id": "t_struct<Counters.Counter>",
|
||||
"kind": "struct",
|
||||
"label": "Counters.Counter",
|
||||
"members": [
|
||||
{
|
||||
"label": "_value",
|
||||
"astId": 3632,
|
||||
"type": "t_uint256",
|
||||
"src": "1021:14:30"
|
||||
}
|
||||
]
|
||||
},
|
||||
"t_mapping<t_struct<Counters.Counter>>": {
|
||||
"id": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"valueType": "t_struct<Counters.Counter>",
|
||||
"label": "mapping(key => Counters.Counter)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_array:dyn<t_uint256>": {
|
||||
"id": "t_array:dyn<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "dyn",
|
||||
"kind": "array",
|
||||
"label": "uint256[]"
|
||||
},
|
||||
"t_mapping<t_array:dyn<t_uint256>>": {
|
||||
"id": "t_mapping<t_array:dyn<t_uint256>>",
|
||||
"valueType": "t_array:dyn<t_uint256>",
|
||||
"label": "mapping(key => uint256[])",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_string": {
|
||||
"id": "t_string",
|
||||
"kind": "elementary",
|
||||
"label": "string"
|
||||
},
|
||||
"t_mapping<t_string>": {
|
||||
"id": "t_mapping<t_string>",
|
||||
"valueType": "t_string",
|
||||
"label": "mapping(key => string)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Roles.Role>": {
|
||||
"id": "t_struct<Roles.Role>",
|
||||
"kind": "struct",
|
||||
"label": "Roles.Role",
|
||||
"members": [
|
||||
{
|
||||
"label": "bearer",
|
||||
"astId": 1222,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "150:32:8"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "ERC165",
|
||||
"path": "contracts/introspection/ERC165.sol",
|
||||
"label": "_supportedInterfaces",
|
||||
"astId": 5191,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "511:52:39"
|
||||
},
|
||||
{
|
||||
"contract": "ERC165",
|
||||
"path": "contracts/introspection/ERC165.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5235,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1244:29:39"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_tokenOwner",
|
||||
"astId": 11595,
|
||||
"type": "t_mapping<t_address>",
|
||||
"src": "844:48:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_tokenApprovals",
|
||||
"astId": 11599,
|
||||
"type": "t_mapping<t_address>",
|
||||
"src": "948:52:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_ownedTokensCount",
|
||||
"astId": 11603,
|
||||
"type": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"src": "1058:63:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_operatorApprovals",
|
||||
"astId": 11609,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "1176:73:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12132,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "11673:29:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_ownedTokens",
|
||||
"astId": 12183,
|
||||
"type": "t_mapping<t_array:dyn<t_uint256>>",
|
||||
"src": "460:50:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_ownedTokensIndex",
|
||||
"astId": 12187,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "580:53:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_allTokens",
|
||||
"astId": 12190,
|
||||
"type": "t_array:dyn<t_uint256>",
|
||||
"src": "694:28:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_allTokensIndex",
|
||||
"astId": 12194,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "793:51:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12523,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "8816:29:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_name",
|
||||
"astId": 12590,
|
||||
"type": "t_string",
|
||||
"src": "281:20:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_symbol",
|
||||
"astId": 12592,
|
||||
"type": "t_string",
|
||||
"src": "328:22:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_tokenURIs",
|
||||
"astId": 12596,
|
||||
"type": "t_mapping<t_string>",
|
||||
"src": "396:45:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12725,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "2849:29:140"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1547,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:10"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721MetadataMintable",
|
||||
"path": "contracts/token/ERC721/ERC721MetadataMintable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12795,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1055:29:141"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1666,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:11"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "_paused",
|
||||
"astId": 5401,
|
||||
"type": "t_bool",
|
||||
"src": "367:20:42"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5482,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1444:29:42"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Pausable",
|
||||
"path": "contracts/token/ERC721/ERC721Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12940,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "865:29:143"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_ownedTokensCount",
|
||||
"astId": 11603,
|
||||
"type": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"src": "1058:63:135"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
}
|
||||
],
|
||||
"storageDiff": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"solidityLibs": {},
|
||||
"proxies": {},
|
||||
"manifestVersion": "2.2",
|
||||
"frozen": true,
|
||||
"app": {
|
||||
"address": "0x291439E6444dAEc9e47Ae359Aa79FD1811A42679"
|
||||
},
|
||||
"package": {
|
||||
"address": "0xa44bb80b290dE8a465d17B14269dF53CF0B9Bf4f"
|
||||
},
|
||||
"provider": {
|
||||
"address": "0x3629bdF19982A06a7a2Fdfac75aC2dA7F5BC3359"
|
||||
},
|
||||
"version": "2.2.2"
|
||||
}
|
||||
923
.openzeppelin/ropsten.json
Normal file
923
.openzeppelin/ropsten.json
Normal file
@ -0,0 +1,923 @@
|
||||
{
|
||||
"contracts": {
|
||||
"StandaloneERC721": {
|
||||
"address": "0x55C0f7e0B33d414B5541147CFe04E4F6d0dF3616",
|
||||
"constructorCode": "608060405234801561001057600080fd5b506135c8806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "b71f19d62583c08240fd85bec42565407f679b1873d7f6e97295a894c7864e2d",
|
||||
"localBytecodeHash": "2e71874460f43d0696496418b1abf57ed58ce1dc524044860260dda9d7de7fab",
|
||||
"deployedBytecodeHash": "2e71874460f43d0696496418b1abf57ed58ce1dc524044860260dda9d7de7fab",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_mapping<t_address>": {
|
||||
"id": "t_mapping<t_address>",
|
||||
"valueType": "t_address",
|
||||
"label": "mapping(key => address)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Counters.Counter>": {
|
||||
"id": "t_struct<Counters.Counter>",
|
||||
"kind": "struct",
|
||||
"label": "Counters.Counter",
|
||||
"members": [
|
||||
{
|
||||
"label": "_value",
|
||||
"astId": 3632,
|
||||
"type": "t_uint256",
|
||||
"src": "1021:14:30"
|
||||
}
|
||||
]
|
||||
},
|
||||
"t_mapping<t_struct<Counters.Counter>>": {
|
||||
"id": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"valueType": "t_struct<Counters.Counter>",
|
||||
"label": "mapping(key => Counters.Counter)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_array:dyn<t_uint256>": {
|
||||
"id": "t_array:dyn<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "dyn",
|
||||
"kind": "array",
|
||||
"label": "uint256[]"
|
||||
},
|
||||
"t_mapping<t_array:dyn<t_uint256>>": {
|
||||
"id": "t_mapping<t_array:dyn<t_uint256>>",
|
||||
"valueType": "t_array:dyn<t_uint256>",
|
||||
"label": "mapping(key => uint256[])",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_string": {
|
||||
"id": "t_string",
|
||||
"kind": "elementary",
|
||||
"label": "string"
|
||||
},
|
||||
"t_mapping<t_string>": {
|
||||
"id": "t_mapping<t_string>",
|
||||
"valueType": "t_string",
|
||||
"label": "mapping(key => string)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Roles.Role>": {
|
||||
"id": "t_struct<Roles.Role>",
|
||||
"kind": "struct",
|
||||
"label": "Roles.Role",
|
||||
"members": [
|
||||
{
|
||||
"label": "bearer",
|
||||
"astId": 1222,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "150:32:8"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "ERC165",
|
||||
"path": "contracts/introspection/ERC165.sol",
|
||||
"label": "_supportedInterfaces",
|
||||
"astId": 5191,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "511:52:39"
|
||||
},
|
||||
{
|
||||
"contract": "ERC165",
|
||||
"path": "contracts/introspection/ERC165.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5235,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1244:29:39"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_tokenOwner",
|
||||
"astId": 11595,
|
||||
"type": "t_mapping<t_address>",
|
||||
"src": "844:48:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_tokenApprovals",
|
||||
"astId": 11599,
|
||||
"type": "t_mapping<t_address>",
|
||||
"src": "948:52:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_ownedTokensCount",
|
||||
"astId": 11603,
|
||||
"type": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"src": "1058:63:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_operatorApprovals",
|
||||
"astId": 11609,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "1176:73:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12132,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "11673:29:135"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_ownedTokens",
|
||||
"astId": 12183,
|
||||
"type": "t_mapping<t_array:dyn<t_uint256>>",
|
||||
"src": "460:50:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_ownedTokensIndex",
|
||||
"astId": 12187,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "580:53:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_allTokens",
|
||||
"astId": 12190,
|
||||
"type": "t_array:dyn<t_uint256>",
|
||||
"src": "694:28:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "_allTokensIndex",
|
||||
"astId": 12194,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "793:51:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Enumerable",
|
||||
"path": "contracts/token/ERC721/ERC721Enumerable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12523,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "8816:29:137"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_name",
|
||||
"astId": 12590,
|
||||
"type": "t_string",
|
||||
"src": "281:20:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_symbol",
|
||||
"astId": 12592,
|
||||
"type": "t_string",
|
||||
"src": "328:22:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "_tokenURIs",
|
||||
"astId": 12596,
|
||||
"type": "t_mapping<t_string>",
|
||||
"src": "396:45:140"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Metadata",
|
||||
"path": "contracts/token/ERC721/ERC721Metadata.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12725,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "2849:29:140"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1547,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:10"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721MetadataMintable",
|
||||
"path": "contracts/token/ERC721/ERC721MetadataMintable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12795,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1055:29:141"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1666,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:11"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "_paused",
|
||||
"astId": 5401,
|
||||
"type": "t_bool",
|
||||
"src": "367:20:42"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5482,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1444:29:42"
|
||||
},
|
||||
{
|
||||
"contract": "ERC721Pausable",
|
||||
"path": "contracts/token/ERC721/ERC721Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 12940,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "865:29:143"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [
|
||||
{
|
||||
"contract": "ERC721",
|
||||
"path": "contracts/token/ERC721/ERC721.sol",
|
||||
"label": "_ownedTokensCount",
|
||||
"astId": 11603,
|
||||
"type": "t_mapping<t_struct<Counters.Counter>>",
|
||||
"src": "1058:63:135"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
}
|
||||
],
|
||||
"storageDiff": []
|
||||
}
|
||||
},
|
||||
"StandaloneERC20": {
|
||||
"address": "0x5224DbE42faAB502612f871FB8f45A26bB0B0C13",
|
||||
"constructorCode": "608060405234801561001057600080fd5b5061290d806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "fffcccf2a7439f83b3eb59e01f5217ea14764c782fde08c6edd511f0c7d1e742",
|
||||
"localBytecodeHash": "be0848d29ef0345b76e9810a67328a1deb1a7b07dd050c9212d3099430cf4222",
|
||||
"deployedBytecodeHash": "be0848d29ef0345b76e9810a67328a1deb1a7b07dd050c9212d3099430cf4222",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_string": {
|
||||
"id": "t_string",
|
||||
"kind": "elementary",
|
||||
"label": "string"
|
||||
},
|
||||
"t_uint8": {
|
||||
"id": "t_uint8",
|
||||
"kind": "elementary",
|
||||
"label": "uint8"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_struct<Roles.Role>": {
|
||||
"id": "t_struct<Roles.Role>",
|
||||
"kind": "struct",
|
||||
"label": "Roles.Role",
|
||||
"members": [
|
||||
{
|
||||
"label": "bearer",
|
||||
"astId": 1222,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "150:32:8"
|
||||
}
|
||||
]
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_name",
|
||||
"astId": 10735,
|
||||
"type": "t_string",
|
||||
"src": "397:20:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_symbol",
|
||||
"astId": 10737,
|
||||
"type": "t_string",
|
||||
"src": "423:22:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "_decimals",
|
||||
"astId": 10739,
|
||||
"type": "t_uint8",
|
||||
"src": "451:23:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Detailed",
|
||||
"path": "contracts/token/ERC20/ERC20Detailed.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10791,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1112:29:128"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_balances",
|
||||
"astId": 10239,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "767:46:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_allowed",
|
||||
"astId": 10245,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "820:66:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_totalSupply",
|
||||
"astId": 10247,
|
||||
"type": "t_uint256",
|
||||
"src": "893:28:125"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10612,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "7729:29:125"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1547,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:10"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Mintable",
|
||||
"path": "contracts/token/ERC20/ERC20Mintable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10840,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "760:29:129"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "______gap",
|
||||
"astId": 1666,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1096:29:11"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "_paused",
|
||||
"astId": 5401,
|
||||
"type": "t_bool",
|
||||
"src": "367:20:42"
|
||||
},
|
||||
{
|
||||
"contract": "Pausable",
|
||||
"path": "contracts/lifecycle/Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5482,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1444:29:42"
|
||||
},
|
||||
{
|
||||
"contract": "ERC20Pausable",
|
||||
"path": "contracts/token/ERC20/ERC20Pausable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 10963,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1209:29:130"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [
|
||||
{
|
||||
"contract": "MinterRole",
|
||||
"path": "contracts/access/roles/MinterRole.sol",
|
||||
"label": "_minters",
|
||||
"astId": 1448,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:10"
|
||||
},
|
||||
{
|
||||
"contract": "PauserRole",
|
||||
"path": "contracts/access/roles/PauserRole.sol",
|
||||
"label": "_pausers",
|
||||
"astId": 1567,
|
||||
"type": "t_struct<Roles.Role>",
|
||||
"src": "286:27:11"
|
||||
}
|
||||
],
|
||||
"storageDiff": [
|
||||
{
|
||||
"action": "rename",
|
||||
"updated": {
|
||||
"index": 8,
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_allowed",
|
||||
"astId": 10245,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "820:66:125"
|
||||
},
|
||||
"original": {
|
||||
"index": 8,
|
||||
"contract": "ERC20",
|
||||
"path": "contracts/token/ERC20/ERC20.sol",
|
||||
"label": "_allowances",
|
||||
"astId": 9135,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "1410:69:115"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"TokenVesting": {
|
||||
"address": "0x2c0Ba048b8dd92c8f8c437F584bA0E8C5745C11e",
|
||||
"constructorCode": "608060405234801561001057600080fd5b506114d8806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "7a623cf584a99e031f19436c354675c6b43934b0d3705ffc3353558b1fb39496",
|
||||
"localBytecodeHash": "e1b9a489ba9fe411cb345548cfbdfb8ef0a9a528c48a9bd07a08f5728a432ea3",
|
||||
"deployedBytecodeHash": "e1b9a489ba9fe411cb345548cfbdfb8ef0a9a528c48a9bd07a08f5728a432ea3",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_mapping<t_bool>": {
|
||||
"id": "t_mapping<t_bool>",
|
||||
"valueType": "t_bool",
|
||||
"label": "mapping(key => bool)",
|
||||
"kind": "mapping"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "Ownable",
|
||||
"path": "contracts/ownership/Ownable.sol",
|
||||
"label": "_owner",
|
||||
"astId": 9325,
|
||||
"type": "t_address",
|
||||
"src": "317:22:118"
|
||||
},
|
||||
{
|
||||
"contract": "Ownable",
|
||||
"path": "contracts/ownership/Ownable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 9436,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "2277:29:118"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_beneficiary",
|
||||
"astId": 4658,
|
||||
"type": "t_address",
|
||||
"src": "1148:28:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_cliff",
|
||||
"astId": 4660,
|
||||
"type": "t_uint256",
|
||||
"src": "1278:22:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_start",
|
||||
"astId": 4662,
|
||||
"type": "t_uint256",
|
||||
"src": "1306:22:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_duration",
|
||||
"astId": 4664,
|
||||
"type": "t_uint256",
|
||||
"src": "1334:25:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_revocable",
|
||||
"astId": 4666,
|
||||
"type": "t_bool",
|
||||
"src": "1366:23:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_released",
|
||||
"astId": 4670,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "1396:46:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "_revoked",
|
||||
"astId": 4674,
|
||||
"type": "t_mapping<t_bool>",
|
||||
"src": "1448:42:36"
|
||||
},
|
||||
{
|
||||
"contract": "TokenVesting",
|
||||
"path": "contracts/drafts/TokenVesting.sol",
|
||||
"label": "______gap",
|
||||
"astId": 5016,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "5852:29:36"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [],
|
||||
"storageDiff": []
|
||||
}
|
||||
},
|
||||
"PaymentSplitter": {
|
||||
"address": "0xa4988102Dd242B1cF0f50bD6f0D702C08B943Cba",
|
||||
"constructorCode": "608060405234801561001057600080fd5b50610be3806100206000396000f3fe",
|
||||
"bodyBytecodeHash": "6f1453b45140bc5e426ffccfcae058daa1fc53439580e3c9e6b7f73aac54c5d8",
|
||||
"localBytecodeHash": "1b0f3688284b1c14c41ce636762c4504188969cb0e5a052159b61b87cbd4e8a8",
|
||||
"deployedBytecodeHash": "1b0f3688284b1c14c41ce636762c4504188969cb0e5a052159b61b87cbd4e8a8",
|
||||
"types": {
|
||||
"t_bool": {
|
||||
"id": "t_bool",
|
||||
"kind": "elementary",
|
||||
"label": "bool"
|
||||
},
|
||||
"t_uint256": {
|
||||
"id": "t_uint256",
|
||||
"kind": "elementary",
|
||||
"label": "uint256"
|
||||
},
|
||||
"t_array:50<t_uint256>": {
|
||||
"id": "t_array:50<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"length": "50",
|
||||
"kind": "array",
|
||||
"label": "uint256[50]"
|
||||
},
|
||||
"t_mapping<t_uint256>": {
|
||||
"id": "t_mapping<t_uint256>",
|
||||
"valueType": "t_uint256",
|
||||
"label": "mapping(key => uint256)",
|
||||
"kind": "mapping"
|
||||
},
|
||||
"t_address": {
|
||||
"id": "t_address",
|
||||
"kind": "elementary",
|
||||
"label": "address"
|
||||
},
|
||||
"t_array:dyn<t_address>": {
|
||||
"id": "t_array:dyn<t_address>",
|
||||
"valueType": "t_address",
|
||||
"length": "dyn",
|
||||
"kind": "array",
|
||||
"label": "address[]"
|
||||
}
|
||||
},
|
||||
"storage": [
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initialized",
|
||||
"astId": 13400,
|
||||
"type": "t_bool",
|
||||
"src": "757:24:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "initializing",
|
||||
"astId": 13402,
|
||||
"type": "t_bool",
|
||||
"src": "876:25:153"
|
||||
},
|
||||
{
|
||||
"contract": "Initializable",
|
||||
"path": "@openzeppelin/upgrades/contracts/Initializable.sol",
|
||||
"label": "______gap",
|
||||
"astId": 13458,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "1951:29:153"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_totalShares",
|
||||
"astId": 9541,
|
||||
"type": "t_uint256",
|
||||
"src": "555:28:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_totalReleased",
|
||||
"astId": 9543,
|
||||
"type": "t_uint256",
|
||||
"src": "589:30:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_shares",
|
||||
"astId": 9547,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "626:43:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_released",
|
||||
"astId": 9551,
|
||||
"type": "t_mapping<t_uint256>",
|
||||
"src": "675:45:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "_payees",
|
||||
"astId": 9554,
|
||||
"type": "t_array:dyn<t_address>",
|
||||
"src": "726:25:120"
|
||||
},
|
||||
{
|
||||
"contract": "PaymentSplitter",
|
||||
"path": "contracts/payment/PaymentSplitter.sol",
|
||||
"label": "______gap",
|
||||
"astId": 9800,
|
||||
"type": "t_array:50<t_uint256>",
|
||||
"src": "3251:29:120"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"hasConstructor": false,
|
||||
"hasSelfDestruct": false,
|
||||
"hasDelegateCall": false,
|
||||
"hasInitialValuesInDeclarations": false,
|
||||
"uninitializedBaseContracts": [],
|
||||
"storageUncheckedVars": [],
|
||||
"storageDiff": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"solidityLibs": {},
|
||||
"proxies": {},
|
||||
"manifestVersion": "2.2",
|
||||
"frozen": true,
|
||||
"app": {
|
||||
"address": "0x27a09abCA2c4d9F914dbC7BeA164b0e6b74Ce7a9"
|
||||
},
|
||||
"package": {
|
||||
"address": "0x2a9e7B63514438906A83a1e320dBBD814D417002"
|
||||
},
|
||||
"provider": {
|
||||
"address": "0xdE16eC017431009ebE329E54D399CB4d5e161B8d"
|
||||
},
|
||||
"version": "2.2.2"
|
||||
}
|
||||
11
.solhint.json
Normal file
11
.solhint.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "default",
|
||||
"rules": {
|
||||
"indent": ["error", 4],
|
||||
|
||||
"bracket-align": false,
|
||||
"compiler-fixed": false,
|
||||
"no-simple-event-func-name": false,
|
||||
"two-lines-top-level-separator": false
|
||||
}
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
node_modules
|
||||
@ -1,21 +0,0 @@
|
||||
{
|
||||
"extends": "solium:all",
|
||||
"plugins": ["security"],
|
||||
"rules": {
|
||||
"blank-lines": "off",
|
||||
"error-reason": "off",
|
||||
"indentation": ["error", 2],
|
||||
"lbrace": "off",
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"max-len": ["error", 79],
|
||||
"no-constant": ["error"],
|
||||
"no-empty-blocks": "off",
|
||||
"quotes": ["error", "double"],
|
||||
"uppercase": "off",
|
||||
"visibility-first": "error",
|
||||
|
||||
"security/enforce-explicit-visibility": ["error"],
|
||||
"security/no-block-members": ["warning"],
|
||||
"security/no-inline-assembly": ["warning"]
|
||||
}
|
||||
}
|
||||
56
.travis.yml
56
.travis.yml
@ -1,56 +0,0 @@
|
||||
dist: trusty
|
||||
sudo: false
|
||||
group: beta
|
||||
language: node_js
|
||||
node_js:
|
||||
- "8"
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
jobs:
|
||||
# XXX fast_finish doesn't work with stages yet. See
|
||||
# https://github.com/travis-ci/travis-ci/issues/8425
|
||||
# --elopio - 20180531
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- env: SOLIDITY_COVERAGE=true
|
||||
- env: SOLC_NIGHTLY=true
|
||||
include:
|
||||
# Run the unit test suite three times in parallel.
|
||||
# The first one gets results faster and is the only one required to pass.
|
||||
# The second one generates the coverage report.
|
||||
# The third one is to keep us informed about possible issues with the
|
||||
# upcoming solidity release.
|
||||
- stage: tests
|
||||
name: "unit tests"
|
||||
script: npm run test
|
||||
- stage: tests
|
||||
name: "unit tests with coverage"
|
||||
script: npm run test
|
||||
env: SOLIDITY_COVERAGE=true
|
||||
- stage: tests
|
||||
name: "unit tests with solc nightly"
|
||||
script: npm run test
|
||||
env: SOLC_NIGHTLY=true
|
||||
# solidity and javascript style tests.
|
||||
- stage: tests
|
||||
name: "static tests"
|
||||
script: npm run lint
|
||||
- stage: update docs
|
||||
if: tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- curl
|
||||
script:
|
||||
- ./scripts/ci/trigger_docs_update "${TRAVIS_TAG}"
|
||||
|
||||
notifications:
|
||||
slack:
|
||||
rooms:
|
||||
- secure: uEhwUkuwJp5pBNh+VTEytPHz3FDKsnPrKO+8MTAKv5hKi4PCRoVhLv6pklr82HUpL6pvSvJbUPA0HVebOXA+MMSxdny/BHZTh2mtw5Y78l2Ad0svDTWuV2Lus2pmhYigRhT0Wo00/SRX9+pxm0kg4EIFJSTS+uR9G76x0l9NljpEGXrqxlDxjxoHBgk8Ciru2LHaLzX/utE3jlABts4Sb1F3wc2BwFkjd6BDCRTGAPhVJwwFk41ZfnmLVbgSNUyk46Cb38oG5oXHb0FI3d3jV/k1OUhRyFfmA2fLXRk0wavibW8TG1gGJJWZ7xTCKzw/Cvup6mpehSAeQef8eekMdjpWEhF9hYRq1BvOs0384UU8NQ0O+BtdXU+X3Nyr84TMJN/iIfgN7gYX7AsvXH3jC0JfNUcIkWlJvyXdE6l2GV1hMmhL09GFEBbSpuSXRIWlOXTcYBlp5NbvE8xO8PUW+T6N5RG2XXjv1g8wCpr6Wwk1+LmRkX5trv8MFBZ2pM8p4H5da5++Ov8egLonNGK2jbx6aBLBX3tPf+g70LZEkiQ4eBfZw8VIgXIvKreisicppNuCD27gNmSEPNt0NkwiEBcTCJ9GSVAO0CU2g4ggvHDX2A+RW5XPET9bGkBXKLfFyV7Qe+MSQjXkCnW3bIRh7Wo1V31XiUiYOLuZPIiH3EQ=
|
||||
on_success: change
|
||||
on_failure: always
|
||||
on_pull_requests: false
|
||||
70
CHANGELOG.md
Normal file
70
CHANGELOG.md
Normal file
@ -0,0 +1,70 @@
|
||||
# Changelog
|
||||
|
||||
## 2.2.2 (2019-08-12)
|
||||
|
||||
### New features:
|
||||
* Facilities to make metatransaction-enabled contracts through the Gas Station Network. Backported from [#1844](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1844).
|
||||
|
||||
## 2.2.1 (2019-07-22)
|
||||
|
||||
### Changes:
|
||||
* Renamed package to `@openzeppelin/contracts-ethereum-package`. ([#54](https://github.com/OpenZeppelin/openzeppelin-contracts-ethereum-package/pull/54))
|
||||
|
||||
## 2.2.0 (2019-03-14)
|
||||
|
||||
### New features:
|
||||
* `ERC20Snapshot`: create snapshots on demand of the token balances and total supply, to later retrieve and e.g. calculate dividends at a past time. ([#1617](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1617))
|
||||
* `SafeERC20`: `ERC20` contracts with no return value (i.e. that revert on failure) are now supported. ([#1655](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/))
|
||||
* `ERC20`: added internal `_approve(address owner, address spender, uint256 value)`, allowing derived contracts to set the allowance of arbitrary accounts. ([#1609](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1609))
|
||||
* `ERC20Metadata`: added internal `_setTokenURI(string memory tokenURI)`. ([#1618](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1618))
|
||||
* `TimedCrowdsale`: added internal `_extendTime(uint256 newClosingTime)` as well as `TimedCrowdsaleExtended(uint256 prevClosingTime, uint256 newClosingTime)` event allowing to extend the crowdsale, as long as it hasn't already closed.
|
||||
|
||||
### Improvements:
|
||||
* Upgraded the minimum compiler version to v0.5.2: this removes many Solidity warnings that were false positives. ([#1606](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1606))
|
||||
* `ECDSA`: `recover` no longer accepts malleable signatures (those using upper-range values for `s`, or 0/1 for `v`). ([#1622](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1622))
|
||||
* `ERC721`'s transfers are now more gas efficient due to removal of unnecessary `SafeMath` calls. ([#1610](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1610))
|
||||
* `Counter`'s API has been improved, and is now used by `ERC721` (though it is still in `drafts`). ([#1610](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1610))
|
||||
* Fixed variable shadowing issues. ([#1606](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1606))
|
||||
|
||||
### Bugfixes:
|
||||
* (minor) `SafeERC20`: `safeApprove` wasn't properly checking for a zero allowance when attempting to set a non-zero allowance. ([#1647](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1647))
|
||||
|
||||
### Breaking changes:
|
||||
* `TokenMetadata` (in drafts) has been renamed to `ERC20Metadata`. ([#1618](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1618))
|
||||
|
||||
## 2.1.3 (2019-02-26)
|
||||
* Backported `SafeERC20.safeApprove` bugfix. ([#1647](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1647))
|
||||
|
||||
## 2.1.2 (2019-01-17)
|
||||
* Removed most of the test suite from the npm package, except `PublicRole.behavior.js`, which may be useful to users testing their own `Roles`.
|
||||
|
||||
## 2.1.1 (2019-01-04)
|
||||
* Version bump to avoid conflict in the npm registry.
|
||||
|
||||
## 2.1.0 (2019-01-04)
|
||||
|
||||
### New features:
|
||||
* Now targeting the 0.5.x line of Solidity compilers. For 0.4.24 support, use version 2.0 of OpenZeppelin.
|
||||
* `WhitelistCrowdsale`: a crowdsale where only whitelisted accounts (`WhitelistedRole`) can purchase tokens. Adding or removing accounts from the whitelist is done by whitelist admins (`WhitelistAdminRole`). Similar to the pre-2.0 `WhitelistedCrowdsale`. ([#1525](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1525), [#1589](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1589))
|
||||
* `RefundablePostDeliveryCrowdsale`: replacement for `RefundableCrowdsale` (deprecated, see below) where tokens are only granted once the crowdsale ends (if it meets its goal). ([#1543](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1543))
|
||||
* `PausableCrowdsale`: allows for pausers (`PauserRole`) to pause token purchases. Other crowdsale operations (e.g. withdrawals and refunds, if applicable) are not affected. ([#832](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/832))
|
||||
* `ERC20`: `transferFrom` and `_burnFrom ` now emit `Approval` events, to represent the token's state comprehensively through events. ([#1524](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1524))
|
||||
* `ERC721`: added `_burn(uint256 tokenId)`, replacing the similar deprecated function (see below). ([#1550](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1550))
|
||||
* `ERC721`: added `_tokensOfOwner(address owner)`, allowing to internally retrieve the array of an account's owned tokens. ([#1522](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1522))
|
||||
* Crowdsales: all constructors are now `public`, meaning it is not necessary to extend these contracts in order to deploy them. The exception is `FinalizableCrowdsale`, since it is meaningless unless extended. ([#1564](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1564))
|
||||
* `SignedSafeMath`: added overflow-safe operations for signed integers (`int256`). ([#1559](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1559), [#1588](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1588))
|
||||
|
||||
### Improvements:
|
||||
* The compiler version required by `Array` was behind the rest of the libray so it was updated to `v0.4.24`. ([#1553](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1553))
|
||||
* Now conforming to a 4-space indentation code style. ([1508](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1508))
|
||||
* `ERC20`: more gas efficient due to removed redundant `require`s. ([#1409](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1409))
|
||||
* `ERC721`: fixed a bug that prevented internal data structures from being properly cleaned, missing potential gas refunds. ([#1539](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1539) and [#1549](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1549))
|
||||
* `ERC721`: general gas savings on `transferFrom`, `_mint` and `_burn`, due to redudant `require`s and `SSTORE`s. ([#1549](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1549))
|
||||
|
||||
### Bugfixes:
|
||||
|
||||
### Breaking changes:
|
||||
|
||||
### Deprecations:
|
||||
* `ERC721._burn(address owner, uint256 tokenId)`: due to the `owner` parameter being unnecessary. ([#1550](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1550))
|
||||
* `RefundableCrowdsale`: due to trading abuse potential on crowdsales that miss their goal. ([#1543](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1543))
|
||||
104
README.md
104
README.md
@ -1,42 +1,100 @@
|
||||
# <img src="logo.png" alt="OpenZeppelin" width="400px">
|
||||
# <img src="logo.png" alt="OpenZeppelin" height="40px">
|
||||
|
||||
[](https://www.npmjs.org/package/openzeppelin-solidity)
|
||||
[](https://travis-ci.org/OpenZeppelin/openzeppelin-solidity)
|
||||
[](https://coveralls.io/github/OpenZeppelin/openzeppelin-solidity?branch=master)
|
||||
## OpenZeppelin Contracts Ethereum Package
|
||||
|
||||
**OpenZeppelin is a library for secure smart contract development.** It provides implementations of standards like ERC20 and ERC721 which you can deploy as-is or extend to suit your needs, as well as Solidity components to build custom contracts and more complex decentralized systems.
|
||||
[](https://www.npmjs.org/package/@openzeppelin/contracts-ethereum-package)
|
||||
[](https://circleci.com/gh/OpenZeppelin/openzeppelin-contracts-ethereum-package)
|
||||
|
||||
**OpenZeppelin Contracts is a library for secure smart contract development.** It provides implementations of standards like ERC20 and ERC721 which you can deploy as-is or extend to suit your needs, as well as Solidity components to build custom contracts and more complex decentralized systems.
|
||||
|
||||
This fork of OpenZeppelin is set up as a **reusable Ethereum Package**. It is deployed to the kovan, rinkeby, and ropsten test networks, as well as to the main Ethereum network. You can reuse any of the pre-deployed on-chain contracts by simply linking to them using the [OpenZeppelin SDK](https://github.com/openzeppelin/openzeppelin-sdk), or reuse their Solidity source code as with the [vanilla version of OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts).
|
||||
|
||||
## Differences with openzeppelin-contracts
|
||||
|
||||
This package contains the same contracts as the vanilla [openzeppelin-contracts](https://github.com/openZeppelin/openzeppelin-contracts). The main difference is that _all contracts in this package are potentially upgradeable_: you will notice that no contracts have constructors defined, but use [initializer functions](https://docs.zeppelinos.org/docs/writing_contracts.html#initializers) instead. Also, this package is set up as an Ethereum package, and provides a small set of pre-deployed logic contracts that can be used directly via the OpenZeppelin SDK, without needing to deploy them again.
|
||||
|
||||
All in all, **you should use this package instead of openzeppelin-solidity if you are managing your project via the OpenZeppelin CLI**.
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
npm install openzeppelin-solidity
|
||||
npm install @openzeppelin/contracts-ethereum-package
|
||||
```
|
||||
|
||||
## Usage
|
||||
## Deployed logic contracts
|
||||
|
||||
To write your custom contracts, import ours and extend them through inheritance.
|
||||
- [StandaloneERC20](contracts/token/ERC20/StandaloneERC20.sol): ERC20 token implementation, optionally mintable and pausable.
|
||||
- [StandaloneERC721](contracts/token/ERC721/StandaloneERC721.sol): ERC721 non-fungible token implementation with metadata and enumerable extensions, optionally mintable and pausable.
|
||||
- [TokenVesting](contracts/drafts/TokenVesting.sol): tToken holder contract that can release its token balance gradually like a typical vesting scheme, with a cliff and vesting period, optionally revocable.
|
||||
- [PaymentSplitter](contracts/payment/PaymentSplitter.sol): Splits payments among a group of addresses proportionately to some number of shares they own.
|
||||
|
||||
## Using via the OpenZeppelin CLI
|
||||
|
||||
You can easily create upgradeable instances of any of the logic contracts listed above using the OpenZeppelin CLI. This will rely on the pre-deployed instances in mainnet, kovan, ropsten, or rinkeby, greatly reducing your gas deployment costs. To do this, just [create a new OpenZeppelin SDK project](https://docs.zeppelinos.org/docs/deploying.html) and [link to this package](https://docs.zeppelinos.org/docs/linking.html).
|
||||
|
||||
```bash
|
||||
$ npm install -g @openzeppelin/cli
|
||||
$ openzeppelin init
|
||||
$ openzeppelin link @openzeppelin/contracts-ethereum-package
|
||||
> Installing...
|
||||
$ openzeppelin create @openzeppelin/contracts-ethereum-package/StandaloneERC20
|
||||
> Creating...
|
||||
```
|
||||
|
||||
To create an instance of a contract, use the `openzeppelin create` command. As an example, you can run the following to create an upgradeable ERC20 named MyToken, with symbol TKN and 8 decimals, and an initial supply of 100 tokens assigned to the address HOLDER, with a MINTER and a PAUSER. Remember to replace $HOLDER, $MINTER, and $PAUSER with actual addresses when you run this command; you can specify more than one (or none at all) minters and pausers.
|
||||
|
||||
```
|
||||
$ openzeppelin create
|
||||
? Pick a contract to instantiate: @openzeppelin/contracts-ethereum-package/StandaloneERC20
|
||||
? Pick a network: development
|
||||
✓ Deploying @openzeppelin/contracts-ethereum-package dependency to network
|
||||
? Do you want to call a function on the instance after creating it?: Yes
|
||||
? Select which function: * initialize(name: string, symbol: string, decimals: uint8, initialSupply: uint256, initialHolder: address, minters: address[], pausers: address[])
|
||||
? name (string): MyToken
|
||||
? symbol (string): MYT
|
||||
? decimals (uint8): 18
|
||||
? initialSupply (uint256): 100e18
|
||||
? initialHolder (address): 0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1
|
||||
? minters (address[]):
|
||||
? pausers (address[]):
|
||||
✓ Setting everything up to create contract instances
|
||||
✓ Instance created at 0x2612Af3A521c2df9EAF28422Ca335b04AdF3ac66
|
||||
```
|
||||
|
||||
OpenZeppelin will create an upgradeable ERC20 instance and keep track of its address in the `.openzeppelin/rinkeby.json` file. Should you update your version of the openzeppelin contracts ethereum package later down the road, you can simply run `openzeppelin update` to upgrade all your ERC20 instances to the latest version.
|
||||
|
||||
You can also deploy a ERC721 token by choosing the `StandaloneERC721` contract when running `openzeppelin create`. Refer to the `initialize` function of each of the predeployed logic contracts to see which parameters are required for initialization.
|
||||
|
||||
## Extending contracts
|
||||
|
||||
If you prefer to write your custom contracts, import the ones from this package and extend them through inheritance. Note that **you must use this package and not `@openzeppelin/contracts` if you are [writing upgradeable contracts](https://docs.zeppelinos.org/docs/writing_contracts.html)**.
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol';
|
||||
import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol';
|
||||
import '@openzeppelin/upgrades/contracts/Initializable.sol';
|
||||
import '@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/ERC721Full.sol';
|
||||
import '@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/ERC721Mintable.sol';
|
||||
|
||||
contract MyNFT is ERC721Full, ERC721Mintable {
|
||||
constructor() ERC721Full("MyNFT", "MNFT") public {
|
||||
contract MyNFT is Initializable, ERC721Full, ERC721Mintable {
|
||||
function initialize() public initializer {
|
||||
ERC721.initialize();
|
||||
ERC721Enumerable.initialize();
|
||||
ERC721Metadata.initialize("MyNFT", "MNFT");
|
||||
ERC721Mintable.initialize(msg.sender);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> You need an ethereum development framework for the above import statements to work! Check out these guides for [Truffle] or [Embark].
|
||||
|
||||
On our site you will find a few [guides] to learn about the diferent parts of OpenZeppelin, as well as [documentation for the API][API docs]. Keep in mind that the API docs are work in progress, and don’t hesitate to ask questions in [our Slack][Slack].
|
||||
On our site you will find a few [guides] to learn about the different parts of OpenZeppelin, as well as [documentation for the API][API docs]. Keep in mind that the API docs are work in progress, and don’t hesitate to ask questions in [our forum][forum].
|
||||
|
||||
## Security
|
||||
|
||||
OpenZeppelin the project is maintained by [Zeppelin] the company, and developed following our high standards for code quality and security. OpenZeppelin is meant to provide tested and community-audited code, but please use common sense when doing anything that deals with real money! We take no responsibility for your implementation decisions and any security problems you might experience.
|
||||
OpenZeppelin Contracts is maintained by [OpenZeppelin](https://openzeppelin.com) the company, and developed following our high standards for code quality and security. OpenZeppelin Contracts is meant to provide tested and community-audited code, but please use common sense when doing anything that deals with real money! We take no responsibility for your implementation decisions and any security problems you might experience.
|
||||
|
||||
The core development principles and strategies that OpenZeppelin is based on include: security in depth, simple and modular code, clarity-driven naming conventions, comprehensive unit testing, pre-and-post-condition sanity checks, code consistency, and regular audits.
|
||||
The core development principles and strategies that OpenZeppelin Contracts is based on include: security in depth, simple and modular code, clarity-driven naming conventions, comprehensive unit testing, pre-and-post-condition sanity checks, code consistency, and regular audits.
|
||||
|
||||
The latest audit was done on October 2018 on version 2.0.0.
|
||||
|
||||
Please report any security issues you find to security@openzeppelin.org.
|
||||
|
||||
@ -48,11 +106,7 @@ OpenZeppelin exists thanks to its contributors. There are many ways you can part
|
||||
|
||||
OpenZeppelin is released under the [MIT License](LICENSE).
|
||||
|
||||
|
||||
[API docs]: https://openzeppelin.org/api/docs/token_ERC721_ERC721BasicToken.html
|
||||
[guides]: https://openzeppelin.org/api/docs/get-started.html
|
||||
[Slack]: https://slack.openzeppelin.org
|
||||
[Zeppelin]: https://zeppelin.solutions
|
||||
[API docs]: https://docs.openzeppelin.org/v2.3.0/api/token/erc20
|
||||
[guides]: https://docs.openzeppelin.org/v2.3.0/get-started
|
||||
[forum]: https://forum.zeppelin.solutions
|
||||
[contribution guide]: CONTRIBUTING.md
|
||||
[Truffle]: https://truffleframework.com/docs/truffle/quickstart
|
||||
[Embark]: https://embark.status.im/docs/quick_start.html
|
||||
|
||||
@ -34,7 +34,7 @@ git push upstream vX.Y.Z-rc.R
|
||||
|
||||
Draft the release notes in our [GitHub releases](https://github.com/OpenZeppelin/openzeppelin-solidity/releases). Make sure to mark it as a pre-release! Try to be consistent with our previous release notes in the title and format of the text. Release candidates don't need a detailed changelog, but make sure to include a link to GitHub's compare page.
|
||||
|
||||
Once the CI run for the new tag is green, publish on npm under the `next` tag.
|
||||
Once the CI run for the new tag is green, publish on npm under the `next` tag. You should see the contracts compile automatically.
|
||||
|
||||
```
|
||||
npm publish --tag next
|
||||
@ -51,18 +51,21 @@ git checkout release-vX.Y.Z
|
||||
git pull upstream
|
||||
```
|
||||
|
||||
Before starting the release process, make one final commit to CHANGELOG.md, including the date of the release.
|
||||
|
||||
Change the version string in `package.json`, `package-lock.json` and `ethpm.json` removing the "-rc.R" suffix. Commit these changes and tag the commit as `vX.Y.Z`.
|
||||
|
||||
```
|
||||
git add package.json package-lock.json ethpm.json
|
||||
git commit -m "Release vX.Y.Z"
|
||||
git tag -a vX.Y.Z
|
||||
git push upstream release-vX.Y.Z
|
||||
git push upstream vX.Y.Z
|
||||
```
|
||||
|
||||
Draft the release notes in GitHub releases. Try to be consistent with our previous release notes in the title and format of the text. Make sure to include a detailed changelog.
|
||||
|
||||
Once the CI run for the new tag is green, publish on npm.
|
||||
Once the CI run for the new tag is green, publish on npm. You should see the contracts compile automatically.
|
||||
|
||||
```
|
||||
npm publish
|
||||
|
||||
BIN
audit/2018-10.pdf
Normal file
BIN
audit/2018-10.pdf
Normal file
Binary file not shown.
27
contracts/GSN/Context.sol
Normal file
27
contracts/GSN/Context.sol
Normal file
@ -0,0 +1,27 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
/*
|
||||
* @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 not 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, with should be used via inheritance.
|
||||
constructor () internal { }
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
|
||||
function _msgSender() internal view returns (address) {
|
||||
return msg.sender;
|
||||
}
|
||||
|
||||
function _msgData() internal view returns (bytes memory) {
|
||||
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
|
||||
return msg.data;
|
||||
}
|
||||
}
|
||||
103
contracts/GSN/GSNContext.sol
Normal file
103
contracts/GSN/GSNContext.sol
Normal file
@ -0,0 +1,103 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "./Context.sol";
|
||||
|
||||
/*
|
||||
* @dev Enables GSN support on `Context` contracts by recognizing calls from
|
||||
* RelayHub and extracting the actual sender and call data from the received
|
||||
* calldata.
|
||||
*
|
||||
* > This contract does not perform all required tasks to implement a GSN
|
||||
* recipient contract: end users should use `GSNRecipient` instead.
|
||||
*/
|
||||
contract GSNContext is Initializable, Context {
|
||||
// We use a random storage slot to allow proxy contracts to enable GSN support in an upgrade without changing their
|
||||
// storage layout. This value is calculated as: keccak256('gsn.relayhub.address'), minus 1.
|
||||
bytes32 private constant RELAY_HUB_ADDRESS_STORAGE_SLOT = 0x06b7792c761dcc05af1761f0315ce8b01ac39c16cc934eb0b2f7a8e71414f262;
|
||||
|
||||
event RelayHubChanged(address indexed oldRelayHub, address indexed newRelayHub);
|
||||
|
||||
function initialize() public initializer {
|
||||
_upgradeRelayHub(0xD216153c06E857cD7f72665E0aF1d7D82172F494);
|
||||
}
|
||||
|
||||
function _getRelayHub() internal view returns (address relayHub) {
|
||||
bytes32 slot = RELAY_HUB_ADDRESS_STORAGE_SLOT;
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
relayHub := sload(slot)
|
||||
}
|
||||
}
|
||||
|
||||
function _upgradeRelayHub(address newRelayHub) internal {
|
||||
address currentRelayHub = _getRelayHub();
|
||||
require(newRelayHub != address(0), "GSNContext: new RelayHub is the zero address");
|
||||
require(newRelayHub != currentRelayHub, "GSNContext: new RelayHub is the current one");
|
||||
|
||||
emit RelayHubChanged(currentRelayHub, newRelayHub);
|
||||
|
||||
bytes32 slot = RELAY_HUB_ADDRESS_STORAGE_SLOT;
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
sstore(slot, newRelayHub)
|
||||
}
|
||||
}
|
||||
|
||||
// Overrides for Context's functions: when called from RelayHub, sender and
|
||||
// data require some pre-processing: the actual sender is stored at the end
|
||||
// of the call data, which in turns means it needs to be removed from it
|
||||
// when handling said data.
|
||||
|
||||
function _msgSender() internal view returns (address) {
|
||||
if (msg.sender != _getRelayHub()) {
|
||||
return msg.sender;
|
||||
} else {
|
||||
return _getRelayedCallSender();
|
||||
}
|
||||
}
|
||||
|
||||
function _msgData() internal view returns (bytes memory) {
|
||||
if (msg.sender != _getRelayHub()) {
|
||||
return msg.data;
|
||||
} else {
|
||||
return _getRelayedCallData();
|
||||
}
|
||||
}
|
||||
|
||||
function _getRelayedCallSender() private pure returns (address result) {
|
||||
// We need to read 20 bytes (an address) located at array index msg.data.length - 20. In memory, the array
|
||||
// is prefixed with a 32-byte length value, so we first add 32 to get the memory read index. However, doing
|
||||
// so would leave the address in the upper 20 bytes of the 32-byte word, which is inconvenient and would
|
||||
// require bit shifting. We therefore subtract 12 from the read index so the address lands on the lower 20
|
||||
// bytes. This can always be done due to the 32-byte prefix.
|
||||
|
||||
// The final memory read index is msg.data.length - 20 + 32 - 12 = msg.data.length. Using inline assembly is the
|
||||
// easiest/most-efficient way to perform this operation.
|
||||
|
||||
// These fields are not accessible from assembly
|
||||
bytes memory array = msg.data;
|
||||
uint256 index = msg.data.length;
|
||||
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
|
||||
result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function _getRelayedCallData() private pure returns (bytes memory) {
|
||||
// RelayHub appends the sender address at the end of the calldata, so in order to retrieve the actual msg.data,
|
||||
// we must strip the last 20 bytes (length of an address type) from it.
|
||||
|
||||
uint256 actualDataLength = msg.data.length - 20;
|
||||
bytes memory actualData = new bytes(actualDataLength);
|
||||
|
||||
for (uint256 i = 0; i < actualDataLength; ++i) {
|
||||
actualData[i] = msg.data[i];
|
||||
}
|
||||
|
||||
return actualData;
|
||||
}
|
||||
}
|
||||
33
contracts/GSN/GSNRecipient.sol
Normal file
33
contracts/GSN/GSNRecipient.sol
Normal file
@ -0,0 +1,33 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "./IRelayRecipient.sol";
|
||||
import "./GSNContext.sol";
|
||||
import "./bouncers/GSNBouncerBase.sol";
|
||||
import "./IRelayHub.sol";
|
||||
|
||||
/*
|
||||
* @dev Base GSN recipient contract, adding the recipient interface and enabling
|
||||
* GSN support. Not all interface methods are implemented, derived contracts
|
||||
* must do so themselves.
|
||||
*/
|
||||
contract GSNRecipient is Initializable, IRelayRecipient, GSNContext, GSNBouncerBase {
|
||||
function initialize() public initializer {
|
||||
GSNContext.initialize();
|
||||
}
|
||||
|
||||
function getHubAddr() public view returns (address) {
|
||||
return _getRelayHub();
|
||||
}
|
||||
|
||||
// This function is view for future-proofing, it may require reading from
|
||||
// storage in the future.
|
||||
function relayHubVersion() public view returns (string memory) {
|
||||
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
|
||||
return "1.0.0";
|
||||
}
|
||||
|
||||
function _withdrawDeposits(uint256 amount, address payable payee) internal {
|
||||
IRelayHub(_getRelayHub()).withdraw(amount, payee);
|
||||
}
|
||||
}
|
||||
188
contracts/GSN/IRelayHub.sol
Normal file
188
contracts/GSN/IRelayHub.sol
Normal file
@ -0,0 +1,188 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
contract IRelayHub {
|
||||
// Relay management
|
||||
|
||||
// Add stake to a relay and sets its unstakeDelay.
|
||||
// If the relay does not exist, it is created, and the caller
|
||||
// of this function becomes its owner. If the relay already exists, only the owner can call this function. A relay
|
||||
// cannot be its own owner.
|
||||
// All Ether in this function call will be added to the relay's stake.
|
||||
// Its unstake delay will be assigned to unstakeDelay, but the new value must be greater or equal to the current one.
|
||||
// Emits a Staked event.
|
||||
function stake(address relayaddr, uint256 unstakeDelay) external payable;
|
||||
|
||||
// Emited when a relay's stake or unstakeDelay are increased
|
||||
event Staked(address indexed relay, uint256 stake, uint256 unstakeDelay);
|
||||
|
||||
// Registers the caller as a relay.
|
||||
// The relay must be staked for, and not be a contract (i.e. this function must be called directly from an EOA).
|
||||
// Emits a RelayAdded event.
|
||||
// This function can be called multiple times, emitting new RelayAdded events. Note that the received transactionFee
|
||||
// is not enforced by relayCall.
|
||||
function registerRelay(uint256 transactionFee, string memory url) public;
|
||||
|
||||
// Emitted when a relay is registered or re-registerd. 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);
|
||||
|
||||
// Removes (deregisters) a relay. Unregistered (but staked for) relays can also be removed. Can only be called by
|
||||
// the owner of the relay. After the relay's unstakeDelay has elapsed, unstake will be callable.
|
||||
// Emits a RelayRemoved event.
|
||||
function removeRelayByOwner(address relay) public;
|
||||
|
||||
// Emitted when a relay is removed (deregistered). unstakeTime is the time when unstake will be callable.
|
||||
event RelayRemoved(address indexed relay, uint256 unstakeTime);
|
||||
|
||||
// Deletes the relay from the system, and gives back its stake to the owner. Can only be called by the relay owner,
|
||||
// after unstakeDelay has elapsed since removeRelayByOwner was called.
|
||||
// Emits an Unstaked event.
|
||||
function unstake(address relay) public;
|
||||
|
||||
// Emitted when a relay is unstaked for, including the returned stake.
|
||||
event Unstaked(address indexed relay, uint256 stake);
|
||||
|
||||
// States a relay can be in
|
||||
enum RelayState {
|
||||
Unknown, // The relay is unknown to the system: it has never been staked for
|
||||
Staked, // The relay has been staked for, but it is not yet active
|
||||
Registered, // The relay has registered itself, and is active (can relay calls)
|
||||
Removed // The relay has been removed by its owner and can no longer relay calls. It must wait for its unstakeDelay to elapse before it can unstake
|
||||
}
|
||||
|
||||
// Returns a relay's status. Note that relays can be deleted when unstaked or penalized.
|
||||
function getRelay(address relay) external view returns (uint256 totalStake, uint256 unstakeDelay, uint256 unstakeTime, address payable owner, RelayState state);
|
||||
|
||||
// Balance management
|
||||
|
||||
// Deposits ether for a contract, so that it can receive (and pay for) relayed transactions. Unused balance can only
|
||||
// be withdrawn by the contract itself, by callingn withdraw.
|
||||
// Emits a Deposited event.
|
||||
function depositFor(address target) public payable;
|
||||
|
||||
// Emitted when depositFor is called, including the amount and account that was funded.
|
||||
event Deposited(address indexed recipient, address indexed from, uint256 amount);
|
||||
|
||||
// Returns an account's deposits. These can be either a contnract's funds, or a relay owner's revenue.
|
||||
function balanceOf(address target) external view returns (uint256);
|
||||
|
||||
// Withdraws from an account's balance, sending it back to it. Relay owners call this to retrieve their revenue, and
|
||||
// contracts can also use it to reduce their funding.
|
||||
// Emits a Withdrawn event.
|
||||
function withdraw(uint256 amount, address payable dest) public;
|
||||
|
||||
// Emitted when an account withdraws funds from RelayHub.
|
||||
event Withdrawn(address indexed account, address indexed dest, uint256 amount);
|
||||
|
||||
// Relaying
|
||||
|
||||
// Check if the RelayHub will accept a relayed operation. Multiple things must be true for this to happen:
|
||||
// - all arguments must be signed for by the sender (from)
|
||||
// - the sender's nonce must be the current one
|
||||
// - the recipient must accept this transaction (via acceptRelayedCall)
|
||||
// Returns a PreconditionCheck value (OK when the transaction can be relayed), or a recipient-specific error code if
|
||||
// it returns one in acceptRelayedCall.
|
||||
function canRelay(
|
||||
address relay,
|
||||
address from,
|
||||
address to,
|
||||
bytes memory encodedFunction,
|
||||
uint256 transactionFee,
|
||||
uint256 gasPrice,
|
||||
uint256 gasLimit,
|
||||
uint256 nonce,
|
||||
bytes memory signature,
|
||||
bytes memory approvalData
|
||||
) public view returns (uint256 status, bytes memory recipientContext);
|
||||
|
||||
// Preconditions for relaying, checked by canRelay and returned as the corresponding numeric values.
|
||||
enum PreconditionCheck {
|
||||
OK, // All checks passed, the call can be relayed
|
||||
WrongSignature, // The transaction to relay is not signed by requested sender
|
||||
WrongNonce, // The provided nonce has already been used by the sender
|
||||
AcceptRelayedCallReverted, // The recipient rejected this call via acceptRelayedCall
|
||||
InvalidRecipientStatusCode // The recipient returned an invalid (reserved) status code
|
||||
}
|
||||
|
||||
// Relays a transaction. For this to suceed, multiple conditions must be met:
|
||||
// - canRelay must return PreconditionCheck.OK
|
||||
// - the sender must be a registered relay
|
||||
// - the transaction's gas price must be larger or equal to the one that was requested by the sender
|
||||
// - the transaction must have enough gas to not run out of gas if all internal transactions (calls to the
|
||||
// recipient) use all gas available to them
|
||||
// - the recipient must have enough balance to pay the relay for the worst-case scenario (i.e. when all gas is
|
||||
// spent)
|
||||
//
|
||||
// If all conditions are met, the call will be relayed and the recipient charged. preRelayedCall, the encoded
|
||||
// function and postRelayedCall will be called in order.
|
||||
//
|
||||
// Arguments:
|
||||
// - from: the client originating the request
|
||||
// - recipient: the target IRelayRecipient contract
|
||||
// - encodedFunction: the function call to relay, including data
|
||||
// - transactionFee: fee (%) the relay takes over actual gas cost
|
||||
// - gasPrice: gas price the client is willing to pay
|
||||
// - 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 Hub, but
|
||||
// it still can be used for e.g. a signature.
|
||||
//
|
||||
// Emits a TransactionRelayed event.
|
||||
function relayCall(
|
||||
address from,
|
||||
address to,
|
||||
bytes memory encodedFunction,
|
||||
uint256 transactionFee,
|
||||
uint256 gasPrice,
|
||||
uint256 gasLimit,
|
||||
uint256 nonce,
|
||||
bytes memory signature,
|
||||
bytes memory approvalData
|
||||
) public;
|
||||
|
||||
// Emitted when an attempt to relay a call failed. This can happen due to incorrect relayCall arguments, or the
|
||||
// recipient not accepting the relayed call. The actual relayed call was not executed, and the recipient not charged.
|
||||
// The reason field contains an error code: values 1-10 correspond to PreconditionCheck entries, and values over 10
|
||||
// are custom recipient error codes returned from acceptRelayedCall.
|
||||
event CanRelayFailed(address indexed relay, address indexed from, address indexed to, bytes4 selector, uint256 reason);
|
||||
|
||||
// Emitted when a transaction is relayed. Note that the actual encoded function might be reverted: this will be
|
||||
// indicated in the status field.
|
||||
// Useful when monitoring a relay's operation and relayed calls to a contract.
|
||||
// Charge is the ether value deducted from the recipient's balance, paid to the relay's owner.
|
||||
event TransactionRelayed(address indexed relay, address indexed from, address indexed to, bytes4 selector, RelayCallStatus status, uint256 charge);
|
||||
|
||||
// Reason error codes for the TransactionRelayed event
|
||||
enum RelayCallStatus {
|
||||
OK, // The transaction was successfully relayed and execution successful - never included in the event
|
||||
RelayedCallFailed, // The transaction was relayed, but the relayed call failed
|
||||
PreRelayedFailed, // The transaction was not relayed due to preRelatedCall reverting
|
||||
PostRelayedFailed, // The transaction was relayed and reverted due to postRelatedCall reverting
|
||||
RecipientBalanceChanged // The transaction was relayed and reverted due to the recipient's balance changing
|
||||
}
|
||||
|
||||
// Returns how much gas should be forwarded to a call to relayCall, in order to relay a transaction that will spend
|
||||
// up to relayedCallStipend gas.
|
||||
function requiredGas(uint256 relayedCallStipend) public view returns (uint256);
|
||||
|
||||
// Returns the maximum recipient charge, given the amount of gas forwarded, gas price and relay fee.
|
||||
function maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee) public view returns (uint256);
|
||||
|
||||
// Relay penalization. Any account can penalize relays, removing them from the system immediately, and rewarding the
|
||||
// reporter with half of the relay's stake. The other half is burned so that, even if the relay penalizes itself, it
|
||||
// still loses half of its stake.
|
||||
|
||||
// Penalize a relay that signed two transactions using the same nonce (making only the first one valid) and
|
||||
// different data (gas price, gas limit, etc. may be different). The (unsigned) transaction data and signature for
|
||||
// both transactions must be provided.
|
||||
function penalizeRepeatedNonce(bytes memory unsignedTx1, bytes memory signature1, bytes memory unsignedTx2, bytes memory signature2) public;
|
||||
|
||||
// Penalize a relay that sent a transaction that didn't target RelayHub's registerRelay or relayCall.
|
||||
function penalizeIllegalTransaction(bytes memory unsignedTx, bytes memory signature) public;
|
||||
|
||||
event Penalized(address indexed relay, address sender, uint256 amount);
|
||||
|
||||
function getNonce(address from) external view returns (uint256);
|
||||
}
|
||||
|
||||
30
contracts/GSN/IRelayRecipient.sol
Normal file
30
contracts/GSN/IRelayRecipient.sol
Normal file
@ -0,0 +1,30 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
/*
|
||||
* @dev Interface for a contract that will be called via the GSN from RelayHub.
|
||||
*/
|
||||
contract IRelayRecipient {
|
||||
/**
|
||||
* @dev Returns the address of the RelayHub instance this recipient interacts with.
|
||||
*/
|
||||
function getHubAddr() public view returns (address);
|
||||
|
||||
function acceptRelayedCall(
|
||||
address relay,
|
||||
address from,
|
||||
bytes calldata encodedFunction,
|
||||
uint256 transactionFee,
|
||||
uint256 gasPrice,
|
||||
uint256 gasLimit,
|
||||
uint256 nonce,
|
||||
bytes calldata approvalData,
|
||||
uint256 maxPossibleCharge
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (uint256, bytes memory);
|
||||
|
||||
function preRelayedCall(bytes calldata context) external returns (bytes32);
|
||||
|
||||
function postRelayedCall(bytes calldata context, bool success, uint actualCharge, bytes32 preRetVal) external;
|
||||
}
|
||||
92
contracts/GSN/bouncers/GSNBouncerBase.sol
Normal file
92
contracts/GSN/bouncers/GSNBouncerBase.sol
Normal file
@ -0,0 +1,92 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../IRelayRecipient.sol";
|
||||
|
||||
/*
|
||||
* @dev Base contract used to implement GSNBouncers.
|
||||
*
|
||||
* > This contract does not perform all required tasks to implement a GSN
|
||||
* recipient contract: end users should use `GSNRecipient` instead.
|
||||
*/
|
||||
contract GSNBouncerBase is IRelayRecipient {
|
||||
uint256 constant private RELAYED_CALL_ACCEPTED = 0;
|
||||
uint256 constant private RELAYED_CALL_REJECTED = 11;
|
||||
|
||||
// How much gas is forwarded to postRelayedCall
|
||||
uint256 constant internal POST_RELAYED_CALL_MAX_GAS = 100000;
|
||||
|
||||
// Base implementations for pre and post relayedCall: only RelayHub can invoke them, and data is forwarded to the
|
||||
// internal hook.
|
||||
|
||||
/**
|
||||
* @dev See `IRelayRecipient.preRelayedCall`.
|
||||
*
|
||||
* This function should not be overriden directly, use `_preRelayedCall` instead.
|
||||
*
|
||||
* * Requirements:
|
||||
*
|
||||
* - the caller must be the `RelayHub` contract.
|
||||
*/
|
||||
function preRelayedCall(bytes calldata context) external returns (bytes32) {
|
||||
require(msg.sender == getHubAddr(), "GSNBouncerBase: caller is not RelayHub");
|
||||
return _preRelayedCall(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See `IRelayRecipient.postRelayedCall`.
|
||||
*
|
||||
* This function should not be overriden directly, use `_postRelayedCall` instead.
|
||||
*
|
||||
* * Requirements:
|
||||
*
|
||||
* - the caller must be the `RelayHub` contract.
|
||||
*/
|
||||
function postRelayedCall(bytes calldata context, bool success, uint256 actualCharge, bytes32 preRetVal) external {
|
||||
require(msg.sender == getHubAddr(), "GSNBouncerBase: caller is not RelayHub");
|
||||
_postRelayedCall(context, success, actualCharge, preRetVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
return _approveRelayedCall("");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See `GSNBouncerBase._approveRelayedCall`.
|
||||
*
|
||||
* This overload forwards `context` to _preRelayedCall and _postRelayedCall.
|
||||
*/
|
||||
function _approveRelayedCall(bytes memory context) internal pure 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) {
|
||||
return (RELAYED_CALL_REJECTED + errorCode, "");
|
||||
}
|
||||
|
||||
// Empty hooks for pre and post relayed call: users only have to define these if they actually use them.
|
||||
|
||||
function _preRelayedCall(bytes memory) internal returns (bytes32) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
function _postRelayedCall(bytes memory, bool, uint256, bytes32) internal {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
/*
|
||||
* @dev Calculates how much RelaHub 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) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
143
contracts/GSN/bouncers/GSNBouncerERC20Fee.sol
Normal file
143
contracts/GSN/bouncers/GSNBouncerERC20Fee.sol
Normal file
@ -0,0 +1,143 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "./GSNBouncerBase.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../../ownership/Secondary.sol";
|
||||
import "../../token/ERC20/SafeERC20.sol";
|
||||
import "../../token/ERC20/ERC20.sol";
|
||||
import "../../token/ERC20/ERC20Detailed.sol";
|
||||
|
||||
contract GSNBouncerERC20Fee is Initializable, GSNBouncerBase {
|
||||
using SafeERC20 for __unstable__ERC20PrimaryAdmin;
|
||||
using SafeMath for uint256;
|
||||
|
||||
enum GSNBouncerERC20FeeErrorCodes {
|
||||
INSUFFICIENT_BALANCE
|
||||
}
|
||||
|
||||
// We use a random storage slot to allow proxy contracts to enable GSN support in an upgrade without changing their
|
||||
// storage layout. This value is calculated as: keccak256('gsn.bouncer.signature.token'), minus 1.
|
||||
bytes32 constant private TOKEN_STORAGE_SLOT = 0xd918b70a5a5c95a8c0cac8acbdd59e1b4acd0645f53c0461d64b41f8825c8828;
|
||||
|
||||
function initialize(string memory name, string memory symbol, uint8 decimals) initializer public {
|
||||
// TODO: Should we inject this token, instead of creating it, in order to make it upgradeable?
|
||||
// However, that would mean removing it from unstable and making in an official contract
|
||||
_setToken(new __unstable__ERC20PrimaryAdmin(name, symbol, decimals));
|
||||
}
|
||||
|
||||
function token() public view returns (IERC20) {
|
||||
return IERC20(_getToken());
|
||||
}
|
||||
|
||||
function _mint(address account, uint256 amount) internal {
|
||||
_getToken().mint(account, amount);
|
||||
}
|
||||
|
||||
function acceptRelayedCall(
|
||||
address,
|
||||
address from,
|
||||
bytes calldata,
|
||||
uint256 transactionFee,
|
||||
uint256 gasPrice,
|
||||
uint256,
|
||||
uint256,
|
||||
bytes calldata,
|
||||
uint256 maxPossibleCharge
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (uint256, bytes memory)
|
||||
{
|
||||
if (_getToken().balanceOf(from) < maxPossibleCharge) {
|
||||
return _rejectRelayedCall(uint256(GSNBouncerERC20FeeErrorCodes.INSUFFICIENT_BALANCE));
|
||||
}
|
||||
|
||||
return _approveRelayedCall(abi.encode(from, maxPossibleCharge, transactionFee, gasPrice));
|
||||
}
|
||||
|
||||
function _preRelayedCall(bytes memory context) internal returns (bytes32) {
|
||||
(address from, uint256 maxPossibleCharge) = abi.decode(context, (address, uint256));
|
||||
|
||||
// The maximum token charge is pre-charged from the user
|
||||
_getToken().safeTransferFrom(from, address(this), maxPossibleCharge);
|
||||
}
|
||||
|
||||
function _postRelayedCall(bytes memory context, bool, uint256 actualCharge, bytes32) internal {
|
||||
(address from, uint256 maxPossibleCharge, uint256 transactionFee, uint256 gasPrice) =
|
||||
abi.decode(context, (address, uint256, uint256, uint256));
|
||||
|
||||
// actualCharge is an _estimated_ charge, which assumes postRelayedCall will use all available gas.
|
||||
// This implementation's gas cost can be roughly estimated as 10k gas, for the two SSTORE operations in an
|
||||
// ERC20 transfer.
|
||||
uint256 overestimation = _computeCharge(POST_RELAYED_CALL_MAX_GAS.sub(10000), gasPrice, transactionFee);
|
||||
actualCharge = actualCharge.sub(overestimation);
|
||||
|
||||
// After the relayed call has been executed and the actual charge estimated, the excess pre-charge is returned
|
||||
_getToken().safeTransfer(from, maxPossibleCharge.sub(actualCharge));
|
||||
}
|
||||
|
||||
function _getToken() private view returns (__unstable__ERC20PrimaryAdmin token) {
|
||||
bytes32 slot = TOKEN_STORAGE_SLOT;
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
token := sload(slot)
|
||||
}
|
||||
}
|
||||
|
||||
function _setToken(__unstable__ERC20PrimaryAdmin token) private {
|
||||
bytes32 slot = TOKEN_STORAGE_SLOT;
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
sstore(slot, token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @title __unstable__ERC20PrimaryAdmin
|
||||
* @dev An ERC20 token owned by another contract, which has minting permissions and can use transferFrom to receive
|
||||
* anyone's tokens. This contract is an internal helper for GSNRecipientERC20Fee, and should not be used
|
||||
* outside of this context.
|
||||
*/
|
||||
// solhint-disable-next-line contract-name-camelcase
|
||||
contract __unstable__ERC20PrimaryAdmin is ERC20, ERC20Detailed, Secondary {
|
||||
uint256 private constant UINT256_MAX = 2**256 - 1;
|
||||
|
||||
constructor(string memory name, string memory symbol, uint8 decimals) public {
|
||||
Secondary.initialize(msg.sender);
|
||||
ERC20Detailed.initialize(name, symbol, decimals);
|
||||
}
|
||||
|
||||
// The primary account (GSNRecipientERC20Fee) can mint tokens
|
||||
function mint(address account, uint256 amount) public onlyPrimary {
|
||||
_mint(account, amount);
|
||||
}
|
||||
|
||||
// The primary account has 'infinite' allowance for all token holders
|
||||
function allowance(address owner, address spender) public view returns (uint256) {
|
||||
if (spender == primary()) {
|
||||
return UINT256_MAX;
|
||||
} else {
|
||||
return super.allowance(owner, spender);
|
||||
}
|
||||
}
|
||||
|
||||
// Allowance for the primary account cannot be changed (it is always 'infinite')
|
||||
function _approve(address owner, address spender, uint256 value) internal {
|
||||
if (spender == primary()) {
|
||||
return;
|
||||
} else {
|
||||
super._approve(owner, spender, value);
|
||||
}
|
||||
}
|
||||
|
||||
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
|
||||
if (recipient == primary()) {
|
||||
_transfer(sender, recipient, amount);
|
||||
return true;
|
||||
} else {
|
||||
return super.transferFrom(sender, recipient, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
70
contracts/GSN/bouncers/GSNBouncerSignature.sol
Normal file
70
contracts/GSN/bouncers/GSNBouncerSignature.sol
Normal file
@ -0,0 +1,70 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "./GSNBouncerBase.sol";
|
||||
import "../../cryptography/ECDSA.sol";
|
||||
|
||||
contract GSNBouncerSignature is Initializable, GSNBouncerBase {
|
||||
using ECDSA for bytes32;
|
||||
|
||||
// We use a random storage slot to allow proxy contracts to enable GSN support in an upgrade without changing their
|
||||
// storage layout. This value is calculated as: keccak256('gsn.bouncer.signature.trustedSigner'), minus 1.
|
||||
bytes32 constant private TRUSTED_SIGNER_STORAGE_SLOT = 0xe7b237a4017a399d277819456dce32c2356236bbc518a6d84a9a8d1cfdf1e9c5;
|
||||
|
||||
enum GSNBouncerSignatureErrorCodes {
|
||||
INVALID_SIGNER
|
||||
}
|
||||
|
||||
function initialize(address trustedSigner) public initializer {
|
||||
_setTrustedSigner(trustedSigner);
|
||||
}
|
||||
|
||||
function acceptRelayedCall(
|
||||
address relay,
|
||||
address from,
|
||||
bytes calldata encodedFunction,
|
||||
uint256 transactionFee,
|
||||
uint256 gasPrice,
|
||||
uint256 gasLimit,
|
||||
uint256 nonce,
|
||||
bytes calldata approvalData,
|
||||
uint256
|
||||
)
|
||||
external
|
||||
view
|
||||
returns (uint256, bytes memory)
|
||||
{
|
||||
bytes memory blob = abi.encodePacked(
|
||||
relay,
|
||||
from,
|
||||
encodedFunction,
|
||||
transactionFee,
|
||||
gasPrice,
|
||||
gasLimit,
|
||||
nonce, // Prevents replays on RelayHub
|
||||
getHubAddr(), // Prevents replays in multiple RelayHubs
|
||||
address(this) // Prevents replays in multiple recipients
|
||||
);
|
||||
if (keccak256(blob).toEthSignedMessageHash().recover(approvalData) == _getTrustedSigner()) {
|
||||
return _approveRelayedCall();
|
||||
} else {
|
||||
return _rejectRelayedCall(uint256(GSNBouncerSignatureErrorCodes.INVALID_SIGNER));
|
||||
}
|
||||
}
|
||||
|
||||
function _getTrustedSigner() private view returns (address trustedSigner) {
|
||||
bytes32 slot = TRUSTED_SIGNER_STORAGE_SLOT;
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
trustedSigner := sload(slot)
|
||||
}
|
||||
}
|
||||
|
||||
function _setTrustedSigner(address trustedSigner) private {
|
||||
bytes32 slot = TRUSTED_SIGNER_STORAGE_SLOT;
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
sstore(slot, trustedSigner)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,44 +1,40 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
* @title Roles
|
||||
* @dev Library for managing addresses assigned to a Role.
|
||||
*/
|
||||
library Roles {
|
||||
struct Role {
|
||||
mapping (address => bool) bearer;
|
||||
}
|
||||
struct Role {
|
||||
mapping (address => bool) bearer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev give an account access to this role
|
||||
*/
|
||||
function add(Role storage role, address account) internal {
|
||||
require(account != address(0));
|
||||
require(!has(role, account));
|
||||
/**
|
||||
* @dev give an account access to this role
|
||||
*/
|
||||
function add(Role storage role, address account) internal {
|
||||
require(account != address(0));
|
||||
require(!has(role, account));
|
||||
|
||||
role.bearer[account] = true;
|
||||
}
|
||||
role.bearer[account] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove an account's access to this role
|
||||
*/
|
||||
function remove(Role storage role, address account) internal {
|
||||
require(account != address(0));
|
||||
require(has(role, account));
|
||||
/**
|
||||
* @dev remove an account's access to this role
|
||||
*/
|
||||
function remove(Role storage role, address account) internal {
|
||||
require(account != address(0));
|
||||
require(has(role, account));
|
||||
|
||||
role.bearer[account] = false;
|
||||
}
|
||||
role.bearer[account] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev check if an account has this role
|
||||
* @return bool
|
||||
*/
|
||||
function has(Role storage role, address account)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
require(account != address(0));
|
||||
return role.bearer[account];
|
||||
}
|
||||
/**
|
||||
* @dev check if an account has this role
|
||||
* @return bool
|
||||
*/
|
||||
function has(Role storage role, address account) internal view returns (bool) {
|
||||
require(account != address(0));
|
||||
return role.bearer[account];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,43 +1,49 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../Roles.sol";
|
||||
|
||||
contract CapperRole {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event CapperAdded(address indexed account);
|
||||
event CapperRemoved(address indexed account);
|
||||
contract CapperRole is Initializable {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
Roles.Role private cappers;
|
||||
event CapperAdded(address indexed account);
|
||||
event CapperRemoved(address indexed account);
|
||||
|
||||
constructor() internal {
|
||||
_addCapper(msg.sender);
|
||||
}
|
||||
Roles.Role private _cappers;
|
||||
|
||||
modifier onlyCapper() {
|
||||
require(isCapper(msg.sender));
|
||||
_;
|
||||
}
|
||||
function initialize(address sender) public initializer {
|
||||
if (!isCapper(sender)) {
|
||||
_addCapper(sender);
|
||||
}
|
||||
}
|
||||
|
||||
function isCapper(address account) public view returns (bool) {
|
||||
return cappers.has(account);
|
||||
}
|
||||
modifier onlyCapper() {
|
||||
require(isCapper(msg.sender));
|
||||
_;
|
||||
}
|
||||
|
||||
function addCapper(address account) public onlyCapper {
|
||||
_addCapper(account);
|
||||
}
|
||||
function isCapper(address account) public view returns (bool) {
|
||||
return _cappers.has(account);
|
||||
}
|
||||
|
||||
function renounceCapper() public {
|
||||
_removeCapper(msg.sender);
|
||||
}
|
||||
function addCapper(address account) public onlyCapper {
|
||||
_addCapper(account);
|
||||
}
|
||||
|
||||
function _addCapper(address account) internal {
|
||||
cappers.add(account);
|
||||
emit CapperAdded(account);
|
||||
}
|
||||
function renounceCapper() public {
|
||||
_removeCapper(msg.sender);
|
||||
}
|
||||
|
||||
function _removeCapper(address account) internal {
|
||||
cappers.remove(account);
|
||||
emit CapperRemoved(account);
|
||||
}
|
||||
function _addCapper(address account) internal {
|
||||
_cappers.add(account);
|
||||
emit CapperAdded(account);
|
||||
}
|
||||
|
||||
function _removeCapper(address account) internal {
|
||||
_cappers.remove(account);
|
||||
emit CapperRemoved(account);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,43 +1,49 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../Roles.sol";
|
||||
|
||||
contract MinterRole {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event MinterAdded(address indexed account);
|
||||
event MinterRemoved(address indexed account);
|
||||
contract MinterRole is Initializable {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
Roles.Role private minters;
|
||||
event MinterAdded(address indexed account);
|
||||
event MinterRemoved(address indexed account);
|
||||
|
||||
constructor() internal {
|
||||
_addMinter(msg.sender);
|
||||
}
|
||||
Roles.Role private _minters;
|
||||
|
||||
modifier onlyMinter() {
|
||||
require(isMinter(msg.sender));
|
||||
_;
|
||||
}
|
||||
function initialize(address sender) public initializer {
|
||||
if (!isMinter(sender)) {
|
||||
_addMinter(sender);
|
||||
}
|
||||
}
|
||||
|
||||
function isMinter(address account) public view returns (bool) {
|
||||
return minters.has(account);
|
||||
}
|
||||
modifier onlyMinter() {
|
||||
require(isMinter(msg.sender));
|
||||
_;
|
||||
}
|
||||
|
||||
function addMinter(address account) public onlyMinter {
|
||||
_addMinter(account);
|
||||
}
|
||||
function isMinter(address account) public view returns (bool) {
|
||||
return _minters.has(account);
|
||||
}
|
||||
|
||||
function renounceMinter() public {
|
||||
_removeMinter(msg.sender);
|
||||
}
|
||||
function addMinter(address account) public onlyMinter {
|
||||
_addMinter(account);
|
||||
}
|
||||
|
||||
function _addMinter(address account) internal {
|
||||
minters.add(account);
|
||||
emit MinterAdded(account);
|
||||
}
|
||||
function renounceMinter() public {
|
||||
_removeMinter(msg.sender);
|
||||
}
|
||||
|
||||
function _removeMinter(address account) internal {
|
||||
minters.remove(account);
|
||||
emit MinterRemoved(account);
|
||||
}
|
||||
function _addMinter(address account) internal {
|
||||
_minters.add(account);
|
||||
emit MinterAdded(account);
|
||||
}
|
||||
|
||||
function _removeMinter(address account) internal {
|
||||
_minters.remove(account);
|
||||
emit MinterRemoved(account);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,43 +1,49 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../Roles.sol";
|
||||
|
||||
contract PauserRole {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event PauserAdded(address indexed account);
|
||||
event PauserRemoved(address indexed account);
|
||||
contract PauserRole is Initializable {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
Roles.Role private pausers;
|
||||
event PauserAdded(address indexed account);
|
||||
event PauserRemoved(address indexed account);
|
||||
|
||||
constructor() internal {
|
||||
_addPauser(msg.sender);
|
||||
}
|
||||
Roles.Role private _pausers;
|
||||
|
||||
modifier onlyPauser() {
|
||||
require(isPauser(msg.sender));
|
||||
_;
|
||||
}
|
||||
function initialize(address sender) public initializer {
|
||||
if (!isPauser(sender)) {
|
||||
_addPauser(sender);
|
||||
}
|
||||
}
|
||||
|
||||
function isPauser(address account) public view returns (bool) {
|
||||
return pausers.has(account);
|
||||
}
|
||||
modifier onlyPauser() {
|
||||
require(isPauser(msg.sender));
|
||||
_;
|
||||
}
|
||||
|
||||
function addPauser(address account) public onlyPauser {
|
||||
_addPauser(account);
|
||||
}
|
||||
function isPauser(address account) public view returns (bool) {
|
||||
return _pausers.has(account);
|
||||
}
|
||||
|
||||
function renouncePauser() public {
|
||||
_removePauser(msg.sender);
|
||||
}
|
||||
function addPauser(address account) public onlyPauser {
|
||||
_addPauser(account);
|
||||
}
|
||||
|
||||
function _addPauser(address account) internal {
|
||||
pausers.add(account);
|
||||
emit PauserAdded(account);
|
||||
}
|
||||
function renouncePauser() public {
|
||||
_removePauser(msg.sender);
|
||||
}
|
||||
|
||||
function _removePauser(address account) internal {
|
||||
pausers.remove(account);
|
||||
emit PauserRemoved(account);
|
||||
}
|
||||
function _addPauser(address account) internal {
|
||||
_pausers.add(account);
|
||||
emit PauserAdded(account);
|
||||
}
|
||||
|
||||
function _removePauser(address account) internal {
|
||||
_pausers.remove(account);
|
||||
emit PauserRemoved(account);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,43 +1,49 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../Roles.sol";
|
||||
|
||||
contract SignerRole {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event SignerAdded(address indexed account);
|
||||
event SignerRemoved(address indexed account);
|
||||
contract SignerRole is Initializable {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
Roles.Role private signers;
|
||||
event SignerAdded(address indexed account);
|
||||
event SignerRemoved(address indexed account);
|
||||
|
||||
constructor() internal {
|
||||
_addSigner(msg.sender);
|
||||
}
|
||||
Roles.Role private _signers;
|
||||
|
||||
modifier onlySigner() {
|
||||
require(isSigner(msg.sender));
|
||||
_;
|
||||
}
|
||||
function initialize(address sender) public initializer {
|
||||
if (!isSigner(sender)) {
|
||||
_addSigner(sender);
|
||||
}
|
||||
}
|
||||
|
||||
function isSigner(address account) public view returns (bool) {
|
||||
return signers.has(account);
|
||||
}
|
||||
modifier onlySigner() {
|
||||
require(isSigner(msg.sender));
|
||||
_;
|
||||
}
|
||||
|
||||
function addSigner(address account) public onlySigner {
|
||||
_addSigner(account);
|
||||
}
|
||||
function isSigner(address account) public view returns (bool) {
|
||||
return _signers.has(account);
|
||||
}
|
||||
|
||||
function renounceSigner() public {
|
||||
_removeSigner(msg.sender);
|
||||
}
|
||||
function addSigner(address account) public onlySigner {
|
||||
_addSigner(account);
|
||||
}
|
||||
|
||||
function _addSigner(address account) internal {
|
||||
signers.add(account);
|
||||
emit SignerAdded(account);
|
||||
}
|
||||
function renounceSigner() public {
|
||||
_removeSigner(msg.sender);
|
||||
}
|
||||
|
||||
function _removeSigner(address account) internal {
|
||||
signers.remove(account);
|
||||
emit SignerRemoved(account);
|
||||
}
|
||||
function _addSigner(address account) internal {
|
||||
_signers.add(account);
|
||||
emit SignerAdded(account);
|
||||
}
|
||||
|
||||
function _removeSigner(address account) internal {
|
||||
_signers.remove(account);
|
||||
emit SignerRemoved(account);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
53
contracts/access/roles/WhitelistAdminRole.sol
Normal file
53
contracts/access/roles/WhitelistAdminRole.sol
Normal file
@ -0,0 +1,53 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
|
||||
import "../Roles.sol";
|
||||
|
||||
/**
|
||||
* @title WhitelistAdminRole
|
||||
* @dev WhitelistAdmins are responsible for assigning and removing Whitelisted accounts.
|
||||
*/
|
||||
contract WhitelistAdminRole is Initializable {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event WhitelistAdminAdded(address indexed account);
|
||||
event WhitelistAdminRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _whitelistAdmins;
|
||||
|
||||
function initialize(address sender) public initializer {
|
||||
if (!isWhitelistAdmin(sender)) {
|
||||
_addWhitelistAdmin(sender);
|
||||
}
|
||||
}
|
||||
|
||||
modifier onlyWhitelistAdmin() {
|
||||
require(isWhitelistAdmin(msg.sender));
|
||||
_;
|
||||
}
|
||||
|
||||
function isWhitelistAdmin(address account) public view returns (bool) {
|
||||
return _whitelistAdmins.has(account);
|
||||
}
|
||||
|
||||
function addWhitelistAdmin(address account) public onlyWhitelistAdmin {
|
||||
_addWhitelistAdmin(account);
|
||||
}
|
||||
|
||||
function renounceWhitelistAdmin() public {
|
||||
_removeWhitelistAdmin(msg.sender);
|
||||
}
|
||||
|
||||
function _addWhitelistAdmin(address account) internal {
|
||||
_whitelistAdmins.add(account);
|
||||
emit WhitelistAdminAdded(account);
|
||||
}
|
||||
|
||||
function _removeWhitelistAdmin(address account) internal {
|
||||
_whitelistAdmins.remove(account);
|
||||
emit WhitelistAdminRemoved(account);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
58
contracts/access/roles/WhitelistedRole.sol
Normal file
58
contracts/access/roles/WhitelistedRole.sol
Normal file
@ -0,0 +1,58 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
|
||||
import "../Roles.sol";
|
||||
import "./WhitelistAdminRole.sol";
|
||||
|
||||
/**
|
||||
* @title WhitelistedRole
|
||||
* @dev Whitelisted accounts have been approved by a WhitelistAdmin to perform certain actions (e.g. participate in a
|
||||
* crowdsale). This role is special in that the only accounts that can add it are WhitelistAdmins (who can also remove
|
||||
* it), and not Whitelisteds themselves.
|
||||
*/
|
||||
contract WhitelistedRole is Initializable, WhitelistAdminRole {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
event WhitelistedAdded(address indexed account);
|
||||
event WhitelistedRemoved(address indexed account);
|
||||
|
||||
Roles.Role private _whitelisteds;
|
||||
|
||||
modifier onlyWhitelisted() {
|
||||
require(isWhitelisted(msg.sender));
|
||||
_;
|
||||
}
|
||||
|
||||
function initialize(address sender) public initializer {
|
||||
WhitelistAdminRole.initialize(sender);
|
||||
}
|
||||
|
||||
function isWhitelisted(address account) public view returns (bool) {
|
||||
return _whitelisteds.has(account);
|
||||
}
|
||||
|
||||
function addWhitelisted(address account) public onlyWhitelistAdmin {
|
||||
_addWhitelisted(account);
|
||||
}
|
||||
|
||||
function removeWhitelisted(address account) public onlyWhitelistAdmin {
|
||||
_removeWhitelisted(account);
|
||||
}
|
||||
|
||||
function renounceWhitelisted() public {
|
||||
_removeWhitelisted(msg.sender);
|
||||
}
|
||||
|
||||
function _addWhitelisted(address account) internal {
|
||||
_whitelisteds.add(account);
|
||||
emit WhitelistedAdded(account);
|
||||
}
|
||||
|
||||
function _removeWhitelisted(address account) internal {
|
||||
_whitelisteds.remove(account);
|
||||
emit WhitelistedRemoved(account);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
@ -11,231 +12,194 @@ import "../utils/ReentrancyGuard.sol";
|
||||
* allowing investors to purchase tokens with ether. This contract implements
|
||||
* such functionality in its most fundamental form and can be extended to provide additional
|
||||
* functionality and/or custom behavior.
|
||||
* The external interface represents the basic interface for purchasing tokens, and conform
|
||||
* the base architecture for crowdsales. They are *not* intended to be modified / overridden.
|
||||
* The external interface represents the basic interface for purchasing tokens, and conforms
|
||||
* the base architecture for crowdsales. It is *not* intended to be modified / overridden.
|
||||
* The internal interface conforms the extensible and modifiable surface of crowdsales. Override
|
||||
* the methods to add functionality. Consider using 'super' where appropriate to concatenate
|
||||
* behavior.
|
||||
*/
|
||||
contract Crowdsale is ReentrancyGuard {
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
contract Crowdsale is Initializable, ReentrancyGuard {
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
// The token being sold
|
||||
IERC20 private _token;
|
||||
// The token being sold
|
||||
IERC20 private _token;
|
||||
|
||||
// Address where funds are collected
|
||||
address private _wallet;
|
||||
// Address where funds are collected
|
||||
address payable private _wallet;
|
||||
|
||||
// How many token units a buyer gets per wei.
|
||||
// The rate is the conversion between wei and the smallest and indivisible token unit.
|
||||
// So, if you are using a rate of 1 with a ERC20Detailed token with 3 decimals called TOK
|
||||
// 1 wei will give you 1 unit, or 0.001 TOK.
|
||||
uint256 private _rate;
|
||||
// How many token units a buyer gets per wei.
|
||||
// The rate is the conversion between wei and the smallest and indivisible token unit.
|
||||
// So, if you are using a rate of 1 with a ERC20Detailed token with 3 decimals called TOK
|
||||
// 1 wei will give you 1 unit, or 0.001 TOK.
|
||||
uint256 private _rate;
|
||||
|
||||
// Amount of wei raised
|
||||
uint256 private _weiRaised;
|
||||
// Amount of wei raised
|
||||
uint256 private _weiRaised;
|
||||
|
||||
/**
|
||||
* Event for token purchase logging
|
||||
* @param purchaser who paid for the tokens
|
||||
* @param beneficiary who got the tokens
|
||||
* @param value weis paid for purchase
|
||||
* @param amount amount of tokens purchased
|
||||
*/
|
||||
event TokensPurchased(
|
||||
address indexed purchaser,
|
||||
address indexed beneficiary,
|
||||
uint256 value,
|
||||
uint256 amount
|
||||
);
|
||||
/**
|
||||
* Event for token purchase logging
|
||||
* @param purchaser who paid for the tokens
|
||||
* @param beneficiary who got the tokens
|
||||
* @param value weis paid for purchase
|
||||
* @param amount amount of tokens purchased
|
||||
*/
|
||||
event TokensPurchased(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
|
||||
|
||||
/**
|
||||
* @param rate Number of token units a buyer gets per wei
|
||||
* @dev The rate is the conversion between wei and the smallest and indivisible
|
||||
* token unit. So, if you are using a rate of 1 with a ERC20Detailed token
|
||||
* with 3 decimals called TOK, 1 wei will give you 1 unit, or 0.001 TOK.
|
||||
* @param wallet Address where collected funds will be forwarded to
|
||||
* @param token Address of the token being sold
|
||||
*/
|
||||
constructor(uint256 rate, address wallet, IERC20 token) internal {
|
||||
require(rate > 0);
|
||||
require(wallet != address(0));
|
||||
require(token != address(0));
|
||||
/**
|
||||
* @param rate Number of token units a buyer gets per wei
|
||||
* @dev The rate is the conversion between wei and the smallest and indivisible
|
||||
* token unit. So, if you are using a rate of 1 with a ERC20Detailed token
|
||||
* with 3 decimals called TOK, 1 wei will give you 1 unit, or 0.001 TOK.
|
||||
* @param wallet Address where collected funds will be forwarded to
|
||||
* @param token Address of the token being sold
|
||||
*/
|
||||
function initialize(uint256 rate, address payable wallet, IERC20 token) public initializer {
|
||||
require(rate > 0);
|
||||
require(wallet != address(0));
|
||||
require(address(token) != address(0));
|
||||
|
||||
_rate = rate;
|
||||
_wallet = wallet;
|
||||
_token = token;
|
||||
}
|
||||
_rate = rate;
|
||||
_wallet = wallet;
|
||||
_token = token;
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// Crowdsale external interface
|
||||
// -----------------------------------------
|
||||
/**
|
||||
* @dev fallback function ***DO NOT OVERRIDE***
|
||||
* Note that other contracts will transfer funds with a base gas stipend
|
||||
* of 2300, which is not enough to call buyTokens. Consider calling
|
||||
* buyTokens directly when purchasing tokens from a contract.
|
||||
*/
|
||||
function () external payable {
|
||||
buyTokens(msg.sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev fallback function ***DO NOT OVERRIDE***
|
||||
* Note that other contracts will transfer fund with a base gas stipend
|
||||
* of 2300, which is not enough to call buyTokens. Consider calling
|
||||
* buyTokens directly when purchasing tokens from a contract.
|
||||
*/
|
||||
function () external payable {
|
||||
buyTokens(msg.sender);
|
||||
}
|
||||
/**
|
||||
* @return the token being sold.
|
||||
*/
|
||||
function token() public view returns (IERC20) {
|
||||
return _token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the token being sold.
|
||||
*/
|
||||
function token() public view returns(IERC20) {
|
||||
return _token;
|
||||
}
|
||||
/**
|
||||
* @return the address where funds are collected.
|
||||
*/
|
||||
function wallet() public view returns (address payable) {
|
||||
return _wallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the address where funds are collected.
|
||||
*/
|
||||
function wallet() public view returns(address) {
|
||||
return _wallet;
|
||||
}
|
||||
/**
|
||||
* @return the number of token units a buyer gets per wei.
|
||||
*/
|
||||
function rate() public view returns (uint256) {
|
||||
return _rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of token units a buyer gets per wei.
|
||||
*/
|
||||
function rate() public view returns(uint256) {
|
||||
return _rate;
|
||||
}
|
||||
/**
|
||||
* @return the amount of wei raised.
|
||||
*/
|
||||
function weiRaised() public view returns (uint256) {
|
||||
return _weiRaised;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the amount of wei raised.
|
||||
*/
|
||||
function weiRaised() public view returns (uint256) {
|
||||
return _weiRaised;
|
||||
}
|
||||
/**
|
||||
* @dev low level token purchase ***DO NOT OVERRIDE***
|
||||
* This function has a non-reentrancy guard, so it shouldn't be called by
|
||||
* another `nonReentrant` function.
|
||||
* @param beneficiary Recipient of the token purchase
|
||||
*/
|
||||
function buyTokens(address beneficiary) public nonReentrant payable {
|
||||
uint256 weiAmount = msg.value;
|
||||
_preValidatePurchase(beneficiary, weiAmount);
|
||||
|
||||
/**
|
||||
* @dev low level token purchase ***DO NOT OVERRIDE***
|
||||
* This function has a non-reentrancy guard, so it shouldn't be called by
|
||||
* another `nonReentrant` function.
|
||||
* @param beneficiary Recipient of the token purchase
|
||||
*/
|
||||
function buyTokens(address beneficiary) public nonReentrant payable {
|
||||
// calculate token amount to be created
|
||||
uint256 tokens = _getTokenAmount(weiAmount);
|
||||
|
||||
uint256 weiAmount = msg.value;
|
||||
_preValidatePurchase(beneficiary, weiAmount);
|
||||
// update state
|
||||
_weiRaised = _weiRaised.add(weiAmount);
|
||||
|
||||
// calculate token amount to be created
|
||||
uint256 tokens = _getTokenAmount(weiAmount);
|
||||
_processPurchase(beneficiary, tokens);
|
||||
emit TokensPurchased(msg.sender, beneficiary, weiAmount, tokens);
|
||||
|
||||
// update state
|
||||
_weiRaised = _weiRaised.add(weiAmount);
|
||||
_updatePurchasingState(beneficiary, weiAmount);
|
||||
|
||||
_processPurchase(beneficiary, tokens);
|
||||
emit TokensPurchased(
|
||||
msg.sender,
|
||||
beneficiary,
|
||||
weiAmount,
|
||||
tokens
|
||||
);
|
||||
_forwardFunds();
|
||||
_postValidatePurchase(beneficiary, weiAmount);
|
||||
}
|
||||
|
||||
_updatePurchasingState(beneficiary, weiAmount);
|
||||
function _hasBeenInitialized() internal view returns (bool) {
|
||||
return ((_rate > 0) && (_wallet != address(0)) && (address(_token) != address(0)));
|
||||
}
|
||||
|
||||
_forwardFunds();
|
||||
_postValidatePurchase(beneficiary, weiAmount);
|
||||
}
|
||||
/**
|
||||
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met.
|
||||
* Use `super` in contracts that inherit from Crowdsale to extend their validations.
|
||||
* Example from CappedCrowdsale.sol's _preValidatePurchase method:
|
||||
* super._preValidatePurchase(beneficiary, weiAmount);
|
||||
* require(weiRaised().add(weiAmount) <= cap);
|
||||
* @param beneficiary Address performing the token purchase
|
||||
* @param weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
require(beneficiary != address(0));
|
||||
require(weiAmount != 0);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// Internal interface (extensible)
|
||||
// -----------------------------------------
|
||||
/**
|
||||
* @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid
|
||||
* conditions are not met.
|
||||
* @param beneficiary Address performing the token purchase
|
||||
* @param weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _postValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use `super` in contracts that inherit from Crowdsale to extend their validations.
|
||||
* Example from CappedCrowdsale.sol's _preValidatePurchase method:
|
||||
* super._preValidatePurchase(beneficiary, weiAmount);
|
||||
* require(weiRaised().add(weiAmount) <= cap);
|
||||
* @param beneficiary Address performing the token purchase
|
||||
* @param weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _preValidatePurchase(
|
||||
address beneficiary,
|
||||
uint256 weiAmount
|
||||
)
|
||||
internal
|
||||
view
|
||||
{
|
||||
require(beneficiary != address(0));
|
||||
require(weiAmount != 0);
|
||||
}
|
||||
/**
|
||||
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends
|
||||
* its tokens.
|
||||
* @param beneficiary Address performing the token purchase
|
||||
* @param tokenAmount Number of tokens to be emitted
|
||||
*/
|
||||
function _deliverTokens(address beneficiary, uint256 tokenAmount) internal {
|
||||
_token.safeTransfer(beneficiary, tokenAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met.
|
||||
* @param beneficiary Address performing the token purchase
|
||||
* @param weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _postValidatePurchase(
|
||||
address beneficiary,
|
||||
uint256 weiAmount
|
||||
)
|
||||
internal
|
||||
view
|
||||
{
|
||||
// optional override
|
||||
}
|
||||
/**
|
||||
* @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send
|
||||
* tokens.
|
||||
* @param beneficiary Address receiving the tokens
|
||||
* @param tokenAmount Number of tokens to be purchased
|
||||
*/
|
||||
function _processPurchase(address beneficiary, uint256 tokenAmount) internal {
|
||||
_deliverTokens(beneficiary, tokenAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
|
||||
* @param beneficiary Address performing the token purchase
|
||||
* @param tokenAmount Number of tokens to be emitted
|
||||
*/
|
||||
function _deliverTokens(
|
||||
address beneficiary,
|
||||
uint256 tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
_token.safeTransfer(beneficiary, tokenAmount);
|
||||
}
|
||||
/**
|
||||
* @dev Override for extensions that require an internal state to check for validity (current user contributions,
|
||||
* etc.)
|
||||
* @param beneficiary Address receiving the tokens
|
||||
* @param weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _updatePurchasingState(address beneficiary, uint256 weiAmount) internal {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send tokens.
|
||||
* @param beneficiary Address receiving the tokens
|
||||
* @param tokenAmount Number of tokens to be purchased
|
||||
*/
|
||||
function _processPurchase(
|
||||
address beneficiary,
|
||||
uint256 tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
_deliverTokens(beneficiary, tokenAmount);
|
||||
}
|
||||
/**
|
||||
* @dev Override to extend the way in which ether is converted to tokens.
|
||||
* @param weiAmount Value in wei to be converted into tokens
|
||||
* @return Number of tokens that can be purchased with the specified _weiAmount
|
||||
*/
|
||||
function _getTokenAmount(uint256 weiAmount) internal view returns (uint256) {
|
||||
return weiAmount.mul(_rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.)
|
||||
* @param beneficiary Address receiving the tokens
|
||||
* @param weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _updatePurchasingState(
|
||||
address beneficiary,
|
||||
uint256 weiAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
// optional override
|
||||
}
|
||||
/**
|
||||
* @dev Determines how ETH is stored/forwarded on purchases.
|
||||
*/
|
||||
function _forwardFunds() internal {
|
||||
_wallet.transfer(msg.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Override to extend the way in which ether is converted to tokens.
|
||||
* @param weiAmount Value in wei to be converted into tokens
|
||||
* @return Number of tokens that can be purchased with the specified _weiAmount
|
||||
*/
|
||||
function _getTokenAmount(uint256 weiAmount)
|
||||
internal view returns (uint256)
|
||||
{
|
||||
return weiAmount.mul(_rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Determines how ETH is stored/forwarded on purchases.
|
||||
*/
|
||||
function _forwardFunds() internal {
|
||||
_wallet.transfer(msg.value);
|
||||
}
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,50 +1,50 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
|
||||
/**
|
||||
* @title FinalizableCrowdsale
|
||||
* @dev Extension of Crowdsale with a one-off finalization action, where one
|
||||
* @dev Extension of TimedCrowdsale with a one-off finalization action, where one
|
||||
* can do extra work after finishing.
|
||||
*/
|
||||
contract FinalizableCrowdsale is TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
contract FinalizableCrowdsale is Initializable, TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
bool private _finalized;
|
||||
bool private _finalized;
|
||||
|
||||
event CrowdsaleFinalized();
|
||||
event CrowdsaleFinalized();
|
||||
|
||||
constructor() internal {
|
||||
_finalized = false;
|
||||
}
|
||||
/**
|
||||
* @return true if the crowdsale is finalized, false otherwise.
|
||||
*/
|
||||
function finalized() public view returns (bool) {
|
||||
return _finalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the crowdsale is finalized, false otherwise.
|
||||
*/
|
||||
function finalized() public view returns (bool) {
|
||||
return _finalized;
|
||||
}
|
||||
/**
|
||||
* @dev Must be called after crowdsale ends, to do some extra finalization
|
||||
* work. Calls the contract's finalization function.
|
||||
*/
|
||||
function finalize() public {
|
||||
require(!_finalized);
|
||||
require(hasClosed());
|
||||
|
||||
/**
|
||||
* @dev Must be called after crowdsale ends, to do some extra finalization
|
||||
* work. Calls the contract's finalization function.
|
||||
*/
|
||||
function finalize() public {
|
||||
require(!_finalized);
|
||||
require(hasClosed());
|
||||
_finalized = true;
|
||||
|
||||
_finalized = true;
|
||||
_finalization();
|
||||
emit CrowdsaleFinalized();
|
||||
}
|
||||
|
||||
_finalization();
|
||||
emit CrowdsaleFinalized();
|
||||
}
|
||||
/**
|
||||
* @dev Can be overridden to add finalization logic. The overriding function
|
||||
* should call super._finalization() to ensure the chain of finalization is
|
||||
* executed entirely.
|
||||
*/
|
||||
function _finalization() internal {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Can be overridden to add finalization logic. The overriding function
|
||||
* should call super._finalization() to ensure the chain of finalization is
|
||||
* executed entirely.
|
||||
*/
|
||||
function _finalization() internal {
|
||||
}
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
@ -7,44 +8,38 @@ import "../../math/SafeMath.sol";
|
||||
* @title PostDeliveryCrowdsale
|
||||
* @dev Crowdsale that locks tokens from withdrawal until it ends.
|
||||
*/
|
||||
contract PostDeliveryCrowdsale is TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
contract PostDeliveryCrowdsale is Initializable, TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping(address => uint256) private _balances;
|
||||
mapping(address => uint256) private _balances;
|
||||
|
||||
constructor() internal {}
|
||||
/**
|
||||
* @dev Withdraw tokens only after crowdsale ends.
|
||||
* @param beneficiary Whose tokens will be withdrawn.
|
||||
*/
|
||||
function withdrawTokens(address beneficiary) public {
|
||||
require(hasClosed());
|
||||
uint256 amount = _balances[beneficiary];
|
||||
require(amount > 0);
|
||||
_balances[beneficiary] = 0;
|
||||
_deliverTokens(beneficiary, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw tokens only after crowdsale ends.
|
||||
* @param beneficiary Whose tokens will be withdrawn.
|
||||
*/
|
||||
function withdrawTokens(address beneficiary) public {
|
||||
require(hasClosed());
|
||||
uint256 amount = _balances[beneficiary];
|
||||
require(amount > 0);
|
||||
_balances[beneficiary] = 0;
|
||||
_deliverTokens(beneficiary, amount);
|
||||
}
|
||||
/**
|
||||
* @return the balance of an account.
|
||||
*/
|
||||
function balanceOf(address account) public view returns (uint256) {
|
||||
return _balances[account];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the balance of an account.
|
||||
*/
|
||||
function balanceOf(address account) public view returns(uint256) {
|
||||
return _balances[account];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent by storing balances instead of issuing tokens right away.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param tokenAmount Amount of tokens purchased
|
||||
*/
|
||||
function _processPurchase(
|
||||
address beneficiary,
|
||||
uint256 tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
_balances[beneficiary] = _balances[beneficiary].add(tokenAmount);
|
||||
}
|
||||
/**
|
||||
* @dev Overrides parent by storing balances instead of issuing tokens right away.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param tokenAmount Amount of tokens purchased
|
||||
*/
|
||||
function _processPurchase(address beneficiary, uint256 tokenAmount) internal {
|
||||
_balances[beneficiary] = _balances[beneficiary].add(tokenAmount);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,91 +1,92 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "./FinalizableCrowdsale.sol";
|
||||
import "../../payment/escrow/RefundEscrow.sol";
|
||||
|
||||
/**
|
||||
* @title RefundableCrowdsale
|
||||
* @dev Extension of Crowdsale contract that adds a funding goal, and
|
||||
* the possibility of users getting a refund if goal is not met.
|
||||
* WARNING: note that if you allow tokens to be traded before the goal
|
||||
* is met, then an attack is possible in which the attacker purchases
|
||||
* tokens from the crowdsale and when they sees that the goal is
|
||||
* unlikely to be met, they sell their tokens (possibly at a discount).
|
||||
* The attacker will be refunded when the crowdsale is finalized, and
|
||||
* the users that purchased from them will be left with worthless
|
||||
* tokens. There are many possible ways to avoid this, like making the
|
||||
* the crowdsale inherit from PostDeliveryCrowdsale, or imposing
|
||||
* restrictions on token trading until the crowdsale is finalized.
|
||||
* This is being discussed in
|
||||
* https://github.com/OpenZeppelin/openzeppelin-solidity/issues/877
|
||||
* This contract will be updated when we agree on a general solution
|
||||
* for this problem.
|
||||
* @dev Extension of FinalizableCrowdsale contract that adds a funding goal, and the possibility of users
|
||||
* getting a refund if goal is not met.
|
||||
*
|
||||
* Deprecated, use RefundablePostDeliveryCrowdsale instead. Note that if you allow tokens to be traded before the goal
|
||||
* is met, then an attack is possible in which the attacker purchases tokens from the crowdsale and when they sees that
|
||||
* the goal is unlikely to be met, they sell their tokens (possibly at a discount). The attacker will be refunded when
|
||||
* the crowdsale is finalized, and the users that purchased from them will be left with worthless tokens.
|
||||
*/
|
||||
contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
contract RefundableCrowdsale is Initializable, FinalizableCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
// minimum amount of funds to be raised in weis
|
||||
uint256 private _goal;
|
||||
// minimum amount of funds to be raised in weis
|
||||
uint256 private _goal;
|
||||
|
||||
// refund escrow used to hold funds while crowdsale is running
|
||||
RefundEscrow private _escrow;
|
||||
// refund escrow used to hold funds while crowdsale is running
|
||||
RefundEscrow private _escrow;
|
||||
|
||||
/**
|
||||
* @dev Constructor, creates RefundEscrow.
|
||||
* @param goal Funding goal
|
||||
*/
|
||||
constructor(uint256 goal) internal {
|
||||
require(goal > 0);
|
||||
_escrow = new RefundEscrow(wallet());
|
||||
_goal = goal;
|
||||
}
|
||||
/**
|
||||
* @dev Constructor, creates RefundEscrow.
|
||||
* @param goal Funding goal
|
||||
*/
|
||||
function initialize(uint256 goal) public initializer {
|
||||
// FinalizableCrowdsale depends on TimedCrowdsale
|
||||
assert(TimedCrowdsale._hasBeenInitialized());
|
||||
|
||||
/**
|
||||
* @return minimum amount of funds to be raised in wei.
|
||||
*/
|
||||
function goal() public view returns(uint256) {
|
||||
return _goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Investors can claim refunds here if crowdsale is unsuccessful
|
||||
* @param beneficiary Whose refund will be claimed.
|
||||
*/
|
||||
function claimRefund(address beneficiary) public {
|
||||
require(finalized());
|
||||
require(!goalReached());
|
||||
|
||||
_escrow.withdraw(beneficiary);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether funding goal was reached.
|
||||
* @return Whether funding goal was reached
|
||||
*/
|
||||
function goalReached() public view returns (bool) {
|
||||
return weiRaised() >= _goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev escrow finalization task, called when finalize() is called
|
||||
*/
|
||||
function _finalization() internal {
|
||||
if (goalReached()) {
|
||||
_escrow.close();
|
||||
_escrow.beneficiaryWithdraw();
|
||||
} else {
|
||||
_escrow.enableRefunds();
|
||||
require(goal > 0);
|
||||
// conditional added to make initializer idempotent in case of diamond inheritance
|
||||
if (address(_escrow) == address(0)) {
|
||||
_escrow = new RefundEscrow();
|
||||
_escrow.initialize(wallet(), address(this));
|
||||
}
|
||||
_goal = goal;
|
||||
}
|
||||
|
||||
super._finalization();
|
||||
}
|
||||
/**
|
||||
* @return minimum amount of funds to be raised in wei.
|
||||
*/
|
||||
function goal() public view returns (uint256) {
|
||||
return _goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides Crowdsale fund forwarding, sending funds to escrow.
|
||||
*/
|
||||
function _forwardFunds() internal {
|
||||
_escrow.deposit.value(msg.value)(msg.sender);
|
||||
}
|
||||
/**
|
||||
* @dev Investors can claim refunds here if crowdsale is unsuccessful
|
||||
* @param refundee Whose refund will be claimed.
|
||||
*/
|
||||
function claimRefund(address payable refundee) public {
|
||||
require(finalized());
|
||||
require(!goalReached());
|
||||
|
||||
_escrow.withdraw(refundee);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether funding goal was reached.
|
||||
* @return Whether funding goal was reached
|
||||
*/
|
||||
function goalReached() public view returns (bool) {
|
||||
return weiRaised() >= _goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev escrow finalization task, called when finalize() is called
|
||||
*/
|
||||
function _finalization() internal {
|
||||
if (goalReached()) {
|
||||
_escrow.close();
|
||||
_escrow.beneficiaryWithdraw();
|
||||
} else {
|
||||
_escrow.enableRefunds();
|
||||
}
|
||||
|
||||
super._finalization();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides Crowdsale fund forwarding, sending funds to escrow.
|
||||
*/
|
||||
function _forwardFunds() internal {
|
||||
_escrow.deposit.value(msg.value)(msg.sender);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
|
||||
import "./RefundableCrowdsale.sol";
|
||||
import "./PostDeliveryCrowdsale.sol";
|
||||
|
||||
/**
|
||||
* @title RefundablePostDeliveryCrowdsale
|
||||
* @dev Extension of RefundableCrowdsale contract that only delivers the tokens
|
||||
* once the crowdsale has closed and the goal met, preventing refunds to be issued
|
||||
* to token holders.
|
||||
*/
|
||||
contract RefundablePostDeliveryCrowdsale is Initializable, RefundableCrowdsale, PostDeliveryCrowdsale {
|
||||
function withdrawTokens(address beneficiary) public {
|
||||
require(finalized());
|
||||
require(goalReached());
|
||||
|
||||
super.withdrawTokens(beneficiary);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/IERC20.sol";
|
||||
import "../../token/ERC20/SafeERC20.sol";
|
||||
@ -10,50 +11,46 @@ import "../../math/Math.sol";
|
||||
* @title AllowanceCrowdsale
|
||||
* @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale.
|
||||
*/
|
||||
contract AllowanceCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
contract AllowanceCrowdsale is Initializable, Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
address private _tokenWallet;
|
||||
address private _tokenWallet;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes token wallet address.
|
||||
* @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale
|
||||
*/
|
||||
constructor(address tokenWallet) internal {
|
||||
require(tokenWallet != address(0));
|
||||
_tokenWallet = tokenWallet;
|
||||
}
|
||||
/**
|
||||
* @dev Constructor, takes token wallet address.
|
||||
* @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale
|
||||
*/
|
||||
function initialize(address tokenWallet) public initializer {
|
||||
assert(Crowdsale._hasBeenInitialized());
|
||||
|
||||
/**
|
||||
* @return the address of the wallet that will hold the tokens.
|
||||
*/
|
||||
function tokenWallet() public view returns(address) {
|
||||
return _tokenWallet;
|
||||
}
|
||||
require(tokenWallet != address(0));
|
||||
_tokenWallet = tokenWallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks the amount of tokens left in the allowance.
|
||||
* @return Amount of tokens left in the allowance
|
||||
*/
|
||||
function remainingTokens() public view returns (uint256) {
|
||||
return Math.min(
|
||||
token().balanceOf(_tokenWallet),
|
||||
token().allowance(_tokenWallet, this)
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @return the address of the wallet that will hold the tokens.
|
||||
*/
|
||||
function tokenWallet() public view returns (address) {
|
||||
return _tokenWallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent behavior by transferring tokens from wallet.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param tokenAmount Amount of tokens purchased
|
||||
*/
|
||||
function _deliverTokens(
|
||||
address beneficiary,
|
||||
uint256 tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
token().safeTransferFrom(_tokenWallet, beneficiary, tokenAmount);
|
||||
}
|
||||
/**
|
||||
* @dev Checks the amount of tokens left in the allowance.
|
||||
* @return Amount of tokens left in the allowance
|
||||
*/
|
||||
function remainingTokens() public view returns (uint256) {
|
||||
return Math.min(token().balanceOf(_tokenWallet), token().allowance(_tokenWallet, address(this)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent behavior by transferring tokens from wallet.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param tokenAmount Amount of tokens purchased
|
||||
*/
|
||||
function _deliverTokens(address beneficiary, uint256 tokenAmount) internal {
|
||||
token().safeTransferFrom(_tokenWallet, beneficiary, tokenAmount);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/ERC20Mintable.sol";
|
||||
|
||||
@ -8,22 +9,16 @@ import "../../token/ERC20/ERC20Mintable.sol";
|
||||
* @dev Extension of Crowdsale contract whose tokens are minted in each purchase.
|
||||
* Token ownership should be transferred to MintedCrowdsale for minting.
|
||||
*/
|
||||
contract MintedCrowdsale is Crowdsale {
|
||||
constructor() internal {}
|
||||
contract MintedCrowdsale is Initializable, Crowdsale {
|
||||
/**
|
||||
* @dev Overrides delivery by minting tokens upon purchase.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param tokenAmount Number of tokens to be minted
|
||||
*/
|
||||
function _deliverTokens(address beneficiary, uint256 tokenAmount) internal {
|
||||
// Potentially dangerous assumption about the type of the token.
|
||||
require(ERC20Mintable(address(token())).mint(beneficiary, tokenAmount));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides delivery by minting tokens upon purchase.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param tokenAmount Number of tokens to be minted
|
||||
*/
|
||||
function _deliverTokens(
|
||||
address beneficiary,
|
||||
uint256 tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
// Potentially dangerous assumption about the type of the token.
|
||||
require(
|
||||
ERC20Mintable(address(token())).mint(beneficiary, tokenAmount));
|
||||
}
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
@ -9,73 +10,74 @@ import "../../math/SafeMath.sol";
|
||||
* Note that what should be provided to the constructor is the initial and final _rates_, that is,
|
||||
* the amount of tokens per wei contributed. Thus, the initial rate must be greater than the final rate.
|
||||
*/
|
||||
contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
contract IncreasingPriceCrowdsale is Initializable, TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 private _initialRate;
|
||||
uint256 private _finalRate;
|
||||
uint256 private _initialRate;
|
||||
uint256 private _finalRate;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes initial and final rates of tokens received per wei contributed.
|
||||
* @param initialRate Number of tokens a buyer gets per wei at the start of the crowdsale
|
||||
* @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale
|
||||
*/
|
||||
constructor(uint256 initialRate, uint256 finalRate) internal {
|
||||
require(finalRate > 0);
|
||||
require(initialRate > finalRate);
|
||||
_initialRate = initialRate;
|
||||
_finalRate = finalRate;
|
||||
}
|
||||
/**
|
||||
* @dev Constructor, takes initial and final rates of tokens received per wei contributed.
|
||||
* @param initialRate Number of tokens a buyer gets per wei at the start of the crowdsale
|
||||
* @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale
|
||||
*/
|
||||
function initialize(uint256 initialRate, uint256 finalRate) public initializer {
|
||||
assert(TimedCrowdsale._hasBeenInitialized());
|
||||
|
||||
/**
|
||||
* The base rate function is overridden to revert, since this crowdsale doens't use it, and
|
||||
* all calls to it are a mistake.
|
||||
*/
|
||||
function rate() public view returns(uint256) {
|
||||
revert();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the initial rate of the crowdsale.
|
||||
*/
|
||||
function initialRate() public view returns(uint256) {
|
||||
return _initialRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the final rate of the crowdsale.
|
||||
*/
|
||||
function finalRate() public view returns (uint256) {
|
||||
return _finalRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the rate of tokens per wei at the present time.
|
||||
* Note that, as price _increases_ with time, the rate _decreases_.
|
||||
* @return The number of tokens a buyer gets per wei at a given time
|
||||
*/
|
||||
function getCurrentRate() public view returns (uint256) {
|
||||
if (!isOpen()) {
|
||||
return 0;
|
||||
require(finalRate > 0);
|
||||
require(initialRate > finalRate);
|
||||
_initialRate = initialRate;
|
||||
_finalRate = finalRate;
|
||||
}
|
||||
|
||||
// solium-disable-next-line security/no-block-members
|
||||
uint256 elapsedTime = block.timestamp.sub(openingTime());
|
||||
uint256 timeRange = closingTime().sub(openingTime());
|
||||
uint256 rateRange = _initialRate.sub(_finalRate);
|
||||
return _initialRate.sub(elapsedTime.mul(rateRange).div(timeRange));
|
||||
}
|
||||
/**
|
||||
* The base rate function is overridden to revert, since this crowdsale doesn't use it, and
|
||||
* all calls to it are a mistake.
|
||||
*/
|
||||
function rate() public view returns (uint256) {
|
||||
revert();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent method taking into account variable rate.
|
||||
* @param weiAmount The value in wei to be converted into tokens
|
||||
* @return The number of tokens _weiAmount wei will buy at present time
|
||||
*/
|
||||
function _getTokenAmount(uint256 weiAmount)
|
||||
internal view returns (uint256)
|
||||
{
|
||||
uint256 currentRate = getCurrentRate();
|
||||
return currentRate.mul(weiAmount);
|
||||
}
|
||||
/**
|
||||
* @return the initial rate of the crowdsale.
|
||||
*/
|
||||
function initialRate() public view returns (uint256) {
|
||||
return _initialRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the final rate of the crowdsale.
|
||||
*/
|
||||
function finalRate() public view returns (uint256) {
|
||||
return _finalRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the rate of tokens per wei at the present time.
|
||||
* Note that, as price _increases_ with time, the rate _decreases_.
|
||||
* @return The number of tokens a buyer gets per wei at a given time
|
||||
*/
|
||||
function getCurrentRate() public view returns (uint256) {
|
||||
if (!isOpen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
uint256 elapsedTime = block.timestamp.sub(openingTime());
|
||||
uint256 timeRange = closingTime().sub(openingTime());
|
||||
uint256 rateRange = _initialRate.sub(_finalRate);
|
||||
return _initialRate.sub(elapsedTime.mul(rateRange).div(timeRange));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent method taking into account variable rate.
|
||||
* @param weiAmount The value in wei to be converted into tokens
|
||||
* @return The number of tokens _weiAmount wei will buy at present time
|
||||
*/
|
||||
function _getTokenAmount(uint256 weiAmount) internal view returns (uint256) {
|
||||
uint256 currentRate = getCurrentRate();
|
||||
return currentRate.mul(weiAmount);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
|
||||
@ -7,49 +8,46 @@ import "../Crowdsale.sol";
|
||||
* @title CappedCrowdsale
|
||||
* @dev Crowdsale with a limit for total contributions.
|
||||
*/
|
||||
contract CappedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
contract CappedCrowdsale is Initializable, Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 private _cap;
|
||||
uint256 private _cap;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes maximum amount of wei accepted in the crowdsale.
|
||||
* @param cap Max amount of wei to be contributed
|
||||
*/
|
||||
constructor(uint256 cap) internal {
|
||||
require(cap > 0);
|
||||
_cap = cap;
|
||||
}
|
||||
/**
|
||||
* @dev Constructor, takes maximum amount of wei accepted in the crowdsale.
|
||||
* @param cap Max amount of wei to be contributed
|
||||
*/
|
||||
function initialize(uint256 cap) public initializer {
|
||||
assert(Crowdsale._hasBeenInitialized());
|
||||
|
||||
/**
|
||||
* @return the cap of the crowdsale.
|
||||
*/
|
||||
function cap() public view returns(uint256) {
|
||||
return _cap;
|
||||
}
|
||||
require(cap > 0);
|
||||
_cap = cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether the cap has been reached.
|
||||
* @return Whether the cap was reached
|
||||
*/
|
||||
function capReached() public view returns (bool) {
|
||||
return weiRaised() >= _cap;
|
||||
}
|
||||
/**
|
||||
* @return the cap of the crowdsale.
|
||||
*/
|
||||
function cap() public view returns (uint256) {
|
||||
return _cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring purchase to respect the funding cap.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(
|
||||
address beneficiary,
|
||||
uint256 weiAmount
|
||||
)
|
||||
internal
|
||||
view
|
||||
{
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
require(weiRaised().add(weiAmount) <= _cap);
|
||||
}
|
||||
/**
|
||||
* @dev Checks whether the cap has been reached.
|
||||
* @return Whether the cap was reached
|
||||
*/
|
||||
function capReached() public view returns (bool) {
|
||||
return weiRaised() >= _cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring purchase to respect the funding cap.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
require(weiRaised().add(weiAmount) <= _cap);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
import "../../access/roles/CapperRole.sol";
|
||||
@ -8,74 +9,64 @@ import "../../access/roles/CapperRole.sol";
|
||||
* @title IndividuallyCappedCrowdsale
|
||||
* @dev Crowdsale with per-beneficiary caps.
|
||||
*/
|
||||
contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole {
|
||||
using SafeMath for uint256;
|
||||
contract IndividuallyCappedCrowdsale is Initializable, Crowdsale, CapperRole {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping(address => uint256) private _contributions;
|
||||
mapping(address => uint256) private _caps;
|
||||
mapping(address => uint256) private _contributions;
|
||||
mapping(address => uint256) private _caps;
|
||||
|
||||
constructor() internal {}
|
||||
function initialize(address sender) public initializer {
|
||||
assert(Crowdsale._hasBeenInitialized());
|
||||
|
||||
/**
|
||||
* @dev Sets a specific beneficiary's maximum contribution.
|
||||
* @param beneficiary Address to be capped
|
||||
* @param cap Wei limit for individual contribution
|
||||
*/
|
||||
function setCap(address beneficiary, uint256 cap) external onlyCapper {
|
||||
_caps[beneficiary] = cap;
|
||||
}
|
||||
CapperRole.initialize(sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the cap of a specific beneficiary.
|
||||
* @param beneficiary Address whose cap is to be checked
|
||||
* @return Current cap for individual beneficiary
|
||||
*/
|
||||
function getCap(address beneficiary) public view returns (uint256) {
|
||||
return _caps[beneficiary];
|
||||
}
|
||||
/**
|
||||
* @dev Sets a specific beneficiary's maximum contribution.
|
||||
* @param beneficiary Address to be capped
|
||||
* @param cap Wei limit for individual contribution
|
||||
*/
|
||||
function setCap(address beneficiary, uint256 cap) external onlyCapper {
|
||||
_caps[beneficiary] = cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the amount contributed so far by a specific beneficiary.
|
||||
* @param beneficiary Address of contributor
|
||||
* @return Beneficiary contribution so far
|
||||
*/
|
||||
function getContribution(address beneficiary)
|
||||
public view returns (uint256)
|
||||
{
|
||||
return _contributions[beneficiary];
|
||||
}
|
||||
/**
|
||||
* @dev Returns the cap of a specific beneficiary.
|
||||
* @param beneficiary Address whose cap is to be checked
|
||||
* @return Current cap for individual beneficiary
|
||||
*/
|
||||
function getCap(address beneficiary) public view returns (uint256) {
|
||||
return _caps[beneficiary];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring purchase to respect the beneficiary's funding cap.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(
|
||||
address beneficiary,
|
||||
uint256 weiAmount
|
||||
)
|
||||
internal
|
||||
view
|
||||
{
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
require(
|
||||
_contributions[beneficiary].add(weiAmount) <= _caps[beneficiary]);
|
||||
}
|
||||
/**
|
||||
* @dev Returns the amount contributed so far by a specific beneficiary.
|
||||
* @param beneficiary Address of contributor
|
||||
* @return Beneficiary contribution so far
|
||||
*/
|
||||
function getContribution(address beneficiary) public view returns (uint256) {
|
||||
return _contributions[beneficiary];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior to update beneficiary contributions
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _updatePurchasingState(
|
||||
address beneficiary,
|
||||
uint256 weiAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
super._updatePurchasingState(beneficiary, weiAmount);
|
||||
_contributions[beneficiary] = _contributions[beneficiary].add(
|
||||
weiAmount);
|
||||
}
|
||||
/**
|
||||
* @dev Extend parent behavior requiring purchase to respect the beneficiary's funding cap.
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
require(_contributions[beneficiary].add(weiAmount) <= _caps[beneficiary]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior to update beneficiary contributions
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _updatePurchasingState(address beneficiary, uint256 weiAmount) internal {
|
||||
super._updatePurchasingState(beneficiary, weiAmount);
|
||||
_contributions[beneficiary] = _contributions[beneficiary].add(weiAmount);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
31
contracts/crowdsale/validation/PausableCrowdsale.sol
Normal file
31
contracts/crowdsale/validation/PausableCrowdsale.sol
Normal file
@ -0,0 +1,31 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../lifecycle/Pausable.sol";
|
||||
|
||||
/**
|
||||
* @title PausableCrowdsale
|
||||
* @dev Extension of Crowdsale contract where purchases can be paused and unpaused by the pauser role.
|
||||
*/
|
||||
contract PausableCrowdsale is Initializable, Crowdsale, Pausable {
|
||||
function initialize(address sender) public initializer {
|
||||
assert(Crowdsale._hasBeenInitialized());
|
||||
|
||||
Pausable.initialize(sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met.
|
||||
* Use super to concatenate validations.
|
||||
* Adds the validation that the crowdsale must not be paused.
|
||||
* @param _beneficiary Address performing the token purchase
|
||||
* @param _weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal view whenNotPaused {
|
||||
return super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
|
||||
@ -7,79 +8,98 @@ import "../Crowdsale.sol";
|
||||
* @title TimedCrowdsale
|
||||
* @dev Crowdsale accepting contributions only within a time frame.
|
||||
*/
|
||||
contract TimedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
contract TimedCrowdsale is Initializable, Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 private _openingTime;
|
||||
uint256 private _closingTime;
|
||||
uint256 private _openingTime;
|
||||
uint256 private _closingTime;
|
||||
|
||||
/**
|
||||
* @dev Reverts if not in crowdsale time range.
|
||||
*/
|
||||
modifier onlyWhileOpen {
|
||||
require(isOpen());
|
||||
_;
|
||||
}
|
||||
/**
|
||||
* Event for crowdsale extending
|
||||
* @param newClosingTime new closing time
|
||||
* @param prevClosingTime old closing time
|
||||
*/
|
||||
event TimedCrowdsaleExtended(uint256 prevClosingTime, uint256 newClosingTime);
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes crowdsale opening and closing times.
|
||||
* @param openingTime Crowdsale opening time
|
||||
* @param closingTime Crowdsale closing time
|
||||
*/
|
||||
constructor(uint256 openingTime, uint256 closingTime) internal {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
require(openingTime >= block.timestamp);
|
||||
require(closingTime > openingTime);
|
||||
/**
|
||||
* @dev Reverts if not in crowdsale time range.
|
||||
*/
|
||||
modifier onlyWhileOpen {
|
||||
require(isOpen());
|
||||
_;
|
||||
}
|
||||
|
||||
_openingTime = openingTime;
|
||||
_closingTime = closingTime;
|
||||
}
|
||||
/**
|
||||
* @dev Constructor, takes crowdsale opening and closing times.
|
||||
* @param openingTime Crowdsale opening time
|
||||
* @param closingTime Crowdsale closing time
|
||||
*/
|
||||
function initialize(uint256 openingTime, uint256 closingTime) public initializer {
|
||||
assert(Crowdsale._hasBeenInitialized());
|
||||
|
||||
/**
|
||||
* @return the crowdsale opening time.
|
||||
*/
|
||||
function openingTime() public view returns(uint256) {
|
||||
return _openingTime;
|
||||
}
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
require(openingTime >= block.timestamp);
|
||||
require(closingTime > openingTime);
|
||||
|
||||
/**
|
||||
* @return the crowdsale closing time.
|
||||
*/
|
||||
function closingTime() public view returns(uint256) {
|
||||
return _closingTime;
|
||||
}
|
||||
_openingTime = openingTime;
|
||||
_closingTime = closingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the crowdsale is open, false otherwise.
|
||||
*/
|
||||
function isOpen() public view returns (bool) {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
return block.timestamp >= _openingTime && block.timestamp <= _closingTime;
|
||||
}
|
||||
/**
|
||||
* @return the crowdsale opening time.
|
||||
*/
|
||||
function openingTime() public view returns (uint256) {
|
||||
return _openingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether the period in which the crowdsale is open has already elapsed.
|
||||
* @return Whether crowdsale period has elapsed
|
||||
*/
|
||||
function hasClosed() public view returns (bool) {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
return block.timestamp > _closingTime;
|
||||
}
|
||||
/**
|
||||
* @return the crowdsale closing time.
|
||||
*/
|
||||
function closingTime() public view returns (uint256) {
|
||||
return _closingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring to be within contributing period
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(
|
||||
address beneficiary,
|
||||
uint256 weiAmount
|
||||
)
|
||||
internal
|
||||
onlyWhileOpen
|
||||
view
|
||||
{
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
}
|
||||
/**
|
||||
* @return true if the crowdsale is open, false otherwise.
|
||||
*/
|
||||
function isOpen() public view returns (bool) {
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
return block.timestamp >= _openingTime && block.timestamp <= _closingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether the period in which the crowdsale is open has already elapsed.
|
||||
* @return Whether crowdsale period has elapsed
|
||||
*/
|
||||
function hasClosed() public view returns (bool) {
|
||||
// solhint-disable-next-line not-rely-on-time
|
||||
return block.timestamp > _closingTime;
|
||||
}
|
||||
|
||||
function _hasBeenInitialized() internal view returns (bool) {
|
||||
return ((_openingTime > 0) && (_closingTime > 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring to be within contributing period
|
||||
* @param beneficiary Token purchaser
|
||||
* @param weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal onlyWhileOpen view {
|
||||
super._preValidatePurchase(beneficiary, weiAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend crowdsale
|
||||
* @param newClosingTime Crowdsale closing time
|
||||
*/
|
||||
function _extendTime(uint256 newClosingTime) internal {
|
||||
require(!hasClosed());
|
||||
require(newClosingTime > _closingTime);
|
||||
|
||||
emit TimedCrowdsaleExtended(_closingTime, newClosingTime);
|
||||
_closingTime = newClosingTime;
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
29
contracts/crowdsale/validation/WhitelistCrowdsale.sol
Normal file
29
contracts/crowdsale/validation/WhitelistCrowdsale.sol
Normal file
@ -0,0 +1,29 @@
|
||||
pragma solidity ^0.5.2;
|
||||
import "../Crowdsale.sol";
|
||||
import "../../access/roles/WhitelistedRole.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title WhitelistCrowdsale
|
||||
* @dev Crowdsale in which only whitelisted users can contribute.
|
||||
*/
|
||||
contract WhitelistCrowdsale is Initializable, WhitelistedRole, Crowdsale {
|
||||
function initialize(address sender) public initializer {
|
||||
WhitelistedRole.initialize(sender);
|
||||
|
||||
assert(Crowdsale._hasBeenInitialized());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring beneficiary to be whitelisted. Note that no
|
||||
* restriction is imposed on the account sending the transaction.
|
||||
* @param _beneficiary Token beneficiary
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal view {
|
||||
require(isWhitelisted(_beneficiary));
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
* @title Elliptic curve signature operations
|
||||
@ -8,64 +8,60 @@ pragma solidity ^0.4.24;
|
||||
*/
|
||||
|
||||
library ECDSA {
|
||||
/**
|
||||
* @dev Recover signer address from a message by using their signature
|
||||
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
|
||||
* @param signature bytes signature, the signature is generated using web3.eth.sign()
|
||||
*/
|
||||
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
|
||||
// Check the signature length
|
||||
if (signature.length != 65) {
|
||||
return (address(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Recover signer address from a message by using their signature
|
||||
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
|
||||
* @param signature bytes signature, the signature is generated using web3.eth.sign()
|
||||
*/
|
||||
function recover(bytes32 hash, bytes signature)
|
||||
internal
|
||||
pure
|
||||
returns (address)
|
||||
{
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
uint8 v;
|
||||
// Divide the signature in r, s and v variables
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
uint8 v;
|
||||
|
||||
// Check the signature length
|
||||
if (signature.length != 65) {
|
||||
return (address(0));
|
||||
// ecrecover takes the signature parameters, and the only way to get them
|
||||
// currently is to use assembly.
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
r := mload(add(signature, 0x20))
|
||||
s := mload(add(signature, 0x40))
|
||||
v := byte(0, mload(add(signature, 0x60)))
|
||||
}
|
||||
|
||||
// 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
|
||||
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
|
||||
//
|
||||
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
|
||||
// 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) {
|
||||
return address(0);
|
||||
}
|
||||
|
||||
if (v != 27 && v != 28) {
|
||||
return address(0);
|
||||
}
|
||||
|
||||
// If the signature is valid (and not malleable), return the signer address
|
||||
return ecrecover(hash, v, r, s);
|
||||
}
|
||||
|
||||
// Divide the signature in r, s and v variables
|
||||
// ecrecover takes the signature parameters, and the only way to get them
|
||||
// currently is to use assembly.
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
r := mload(add(signature, 0x20))
|
||||
s := mload(add(signature, 0x40))
|
||||
v := byte(0, mload(add(signature, 0x60)))
|
||||
/**
|
||||
* toEthSignedMessageHash
|
||||
* @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
|
||||
* and hash the result
|
||||
*/
|
||||
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
|
||||
// 32 is the length in bytes of hash,
|
||||
// enforced by the type signature above
|
||||
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
|
||||
}
|
||||
|
||||
// Version of signature should be 27 or 28, but 0 and 1 are also possible versions
|
||||
if (v < 27) {
|
||||
v += 27;
|
||||
}
|
||||
|
||||
// If the version is correct return the signer address
|
||||
if (v != 27 && v != 28) {
|
||||
return (address(0));
|
||||
} else {
|
||||
// solium-disable-next-line arg-overflow
|
||||
return ecrecover(hash, v, r, s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* toEthSignedMessageHash
|
||||
* @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
|
||||
* and hash the result
|
||||
*/
|
||||
function toEthSignedMessageHash(bytes32 hash)
|
||||
internal
|
||||
pure
|
||||
returns (bytes32)
|
||||
{
|
||||
// 32 is the length in bytes of hash,
|
||||
// enforced by the type signature above
|
||||
return keccak256(
|
||||
abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
* @title MerkleProof
|
||||
@ -6,37 +6,29 @@ pragma solidity ^0.4.24;
|
||||
* https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
|
||||
*/
|
||||
library MerkleProof {
|
||||
/**
|
||||
* @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
|
||||
* and each pair of pre-images are sorted.
|
||||
* @param proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree
|
||||
* @param root Merkle root
|
||||
* @param leaf Leaf of Merkle tree
|
||||
*/
|
||||
function verify(
|
||||
bytes32[] proof,
|
||||
bytes32 root,
|
||||
bytes32 leaf
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool)
|
||||
{
|
||||
bytes32 computedHash = leaf;
|
||||
/**
|
||||
* @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
|
||||
* and each pair of pre-images are sorted.
|
||||
* @param proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree
|
||||
* @param root Merkle root
|
||||
* @param leaf Leaf of Merkle tree
|
||||
*/
|
||||
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
|
||||
bytes32 computedHash = leaf;
|
||||
|
||||
for (uint256 i = 0; i < proof.length; i++) {
|
||||
bytes32 proofElement = proof[i];
|
||||
for (uint256 i = 0; i < proof.length; i++) {
|
||||
bytes32 proofElement = proof[i];
|
||||
|
||||
if (computedHash < proofElement) {
|
||||
// Hash(current computed hash + current element of the proof)
|
||||
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
|
||||
} else {
|
||||
// Hash(current element of the proof + current computed hash)
|
||||
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
|
||||
}
|
||||
if (computedHash < proofElement) {
|
||||
// Hash(current computed hash + current element of the proof)
|
||||
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
|
||||
} else {
|
||||
// Hash(current element of the proof + current computed hash)
|
||||
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the computed hash (root) is equal to the provided root
|
||||
return computedHash == root;
|
||||
}
|
||||
|
||||
// Check if the computed hash (root) is equal to the provided root
|
||||
return computedHash == root;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
/**
|
||||
* @title Counter
|
||||
* @author Matt Condon (@shrugs)
|
||||
* @dev Provides an incrementing uint256 id acquired by the `Counter#next` getter.
|
||||
* Use this for issuing ERC721 ids or keeping track of request ids, anything you want, really.
|
||||
*
|
||||
* Include with `using Counter for Counter.Counter;`
|
||||
* @notice Does not allow an Id of 0, which is popularly used to signify a null state in solidity.
|
||||
* Does not protect from overflows, but if you have 2^256 ids, you have other problems.
|
||||
* (But actually, it's generally impossible to increment a counter this many times, energy wise
|
||||
* so it's not something you have to worry about.)
|
||||
*/
|
||||
library Counter {
|
||||
|
||||
struct Counter {
|
||||
uint256 current; // default: 0
|
||||
}
|
||||
|
||||
function next(Counter storage index)
|
||||
internal
|
||||
returns (uint256)
|
||||
{
|
||||
index.current += 1;
|
||||
return index.current;
|
||||
}
|
||||
}
|
||||
37
contracts/drafts/Counters.sol
Normal file
37
contracts/drafts/Counters.sol
Normal file
@ -0,0 +1,37 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
/**
|
||||
* @title Counters
|
||||
* @author Matt Condon (@shrugs)
|
||||
* @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
|
||||
* of elements in a mapping, issuing ERC721 ids, or counting request ids
|
||||
*
|
||||
* Include with `using Counters for Counters.Counter;`
|
||||
* Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the SafeMath
|
||||
* overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
|
||||
* directly accessed.
|
||||
*/
|
||||
library Counters {
|
||||
using SafeMath for uint256;
|
||||
|
||||
struct Counter {
|
||||
// This variable should never be directly accessed by users of the library: interactions must be restricted to
|
||||
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
|
||||
// this feature: see https://github.com/ethereum/solidity/issues/4637
|
||||
uint256 _value; // default: 0
|
||||
}
|
||||
|
||||
function current(Counter storage counter) internal view returns (uint256) {
|
||||
return counter._value;
|
||||
}
|
||||
|
||||
function increment(Counter storage counter) internal {
|
||||
counter._value += 1;
|
||||
}
|
||||
|
||||
function decrement(Counter storage counter) internal {
|
||||
counter._value = counter._value.sub(1);
|
||||
}
|
||||
}
|
||||
27
contracts/drafts/ERC1046/ERC20Metadata.sol
Normal file
27
contracts/drafts/ERC1046/ERC20Metadata.sol
Normal file
@ -0,0 +1,27 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../../token/ERC20/IERC20.sol";
|
||||
|
||||
/**
|
||||
* @title ERC-1047 Token Metadata
|
||||
* @dev See https://eips.ethereum.org/EIPS/eip-1046
|
||||
* @dev tokenURI must respond with a URI that implements https://eips.ethereum.org/EIPS/eip-1047
|
||||
*/
|
||||
contract ERC20Metadata is Initializable {
|
||||
string private _tokenURI;
|
||||
|
||||
function initialize(string memory tokenURI_) public {
|
||||
_setTokenURI(tokenURI_);
|
||||
}
|
||||
|
||||
function tokenURI() external view returns (string memory) {
|
||||
return _tokenURI;
|
||||
}
|
||||
|
||||
function _setTokenURI(string memory tokenURI_) internal {
|
||||
_tokenURI = tokenURI_;
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../token/ERC20/IERC20.sol";
|
||||
|
||||
/**
|
||||
* @title ERC-1047 Token Metadata
|
||||
* @dev See https://eips.ethereum.org/EIPS/eip-1046
|
||||
* @dev tokenURI must respond with a URI that implements https://eips.ethereum.org/EIPS/eip-1047
|
||||
* @dev TODO - update https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/IERC721.sol#L17 when 1046 is finalized
|
||||
*/
|
||||
contract ERC20TokenMetadata is IERC20 {
|
||||
function tokenURI() external view returns (string);
|
||||
}
|
||||
|
||||
contract ERC20WithMetadata is ERC20TokenMetadata {
|
||||
string private _tokenURI;
|
||||
|
||||
constructor(string tokenURI)
|
||||
public
|
||||
{
|
||||
_tokenURI = tokenURI;
|
||||
}
|
||||
|
||||
function tokenURI() external view returns (string) {
|
||||
return _tokenURI;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../token/ERC20/ERC20Mintable.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
@ -17,13 +18,13 @@ import "../math/Math.sol";
|
||||
* OpenZeppelin's ERC20Mintable, but the only functions that are needed are
|
||||
* `isMinter(address)` and `mint(address, amount)`. The migrator will check
|
||||
* that it is a minter for the token.
|
||||
* The balance from the legacy token will be transfered to the migrator, as it
|
||||
* The balance from the legacy token will be transferred to the migrator, as it
|
||||
* is migrated, and remain there forever.
|
||||
* Although this contract can be used in many different scenarios, the main
|
||||
* motivation was to provide a way to migrate ERC20 tokens into an upgradeable
|
||||
* version of it using ZeppelinOS. To read more about how this can be done
|
||||
* version of it using the OpenZeppelin SDK. To read more about how this can be done
|
||||
* using this implementation, please follow the official documentation site of
|
||||
* ZeppelinOS: https://docs.zeppelinos.org/docs/erc20_onboarding.html
|
||||
* the OpenZeppelinSDK: https://docs.zeppelinos.org/docs/erc20_onboarding.html
|
||||
* Example of usage:
|
||||
* ```
|
||||
* const migrator = await ERC20Migrator.new(legacyToken.address);
|
||||
@ -31,70 +32,73 @@ import "../math/Math.sol";
|
||||
* await migrator.beginMigration(newToken.address);
|
||||
* ```
|
||||
*/
|
||||
contract ERC20Migrator {
|
||||
using SafeERC20 for IERC20;
|
||||
contract ERC20Migrator is Initializable {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
/// Address of the old token contract
|
||||
IERC20 private _legacyToken;
|
||||
/// Address of the old token contract
|
||||
IERC20 private _legacyToken;
|
||||
|
||||
/// Address of the new token contract
|
||||
ERC20Mintable private _newToken;
|
||||
/// Address of the new token contract
|
||||
ERC20Mintable private _newToken;
|
||||
|
||||
/**
|
||||
* @param legacyToken address of the old token contract
|
||||
*/
|
||||
constructor(IERC20 legacyToken) public {
|
||||
require(legacyToken != address(0));
|
||||
_legacyToken = legacyToken;
|
||||
}
|
||||
/**
|
||||
* @param legacyToken address of the old token contract
|
||||
*/
|
||||
function initialize(IERC20 legacyToken) public initializer {
|
||||
require(address(legacyToken) != address(0));
|
||||
_legacyToken = legacyToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the legacy token that is being migrated.
|
||||
*/
|
||||
function legacyToken() public view returns (IERC20) {
|
||||
return _legacyToken;
|
||||
}
|
||||
/**
|
||||
* @dev Returns the legacy token that is being migrated.
|
||||
*/
|
||||
function legacyToken() public view returns (IERC20) {
|
||||
return _legacyToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the new token to which we are migrating.
|
||||
*/
|
||||
function newToken() public view returns (IERC20) {
|
||||
return _newToken;
|
||||
}
|
||||
/**
|
||||
* @dev Returns the new token to which we are migrating.
|
||||
*/
|
||||
function newToken() public view returns (IERC20) {
|
||||
return _newToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Begins the migration by setting which is the new token that will be
|
||||
* minted. This contract must be a minter for the new token.
|
||||
* @param newToken the token that will be minted
|
||||
*/
|
||||
function beginMigration(ERC20Mintable newToken) public {
|
||||
require(_newToken == address(0));
|
||||
require(newToken != address(0));
|
||||
require(newToken.isMinter(this));
|
||||
/**
|
||||
* @dev Begins the migration by setting which is the new token that will be
|
||||
* minted. This contract must be a minter for the new token.
|
||||
* @param newToken_ the token that will be minted
|
||||
*/
|
||||
function beginMigration(ERC20Mintable newToken_) public {
|
||||
require(address(_newToken) == address(0));
|
||||
require(address(newToken_) != address(0));
|
||||
require(newToken_.isMinter(address(this)));
|
||||
|
||||
_newToken = newToken;
|
||||
}
|
||||
_newToken = newToken_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers part of an account's balance in the old token to this
|
||||
* contract, and mints the same amount of new tokens for that account.
|
||||
* @param account whose tokens will be migrated
|
||||
* @param amount amount of tokens to be migrated
|
||||
*/
|
||||
function migrate(address account, uint256 amount) public {
|
||||
_legacyToken.safeTransferFrom(account, this, amount);
|
||||
_newToken.mint(account, amount);
|
||||
}
|
||||
/**
|
||||
* @dev Transfers part of an account's balance in the old token to this
|
||||
* contract, and mints the same amount of new tokens for that account.
|
||||
* @param account whose tokens will be migrated
|
||||
* @param amount amount of tokens to be migrated
|
||||
*/
|
||||
function migrate(address account, uint256 amount) public {
|
||||
require(address(_newToken) != address(0));
|
||||
_legacyToken.safeTransferFrom(account, address(this), amount);
|
||||
_newToken.mint(account, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers all of an account's allowed balance in the old token to
|
||||
* this contract, and mints the same amount of new tokens for that account.
|
||||
* @param account whose tokens will be migrated
|
||||
*/
|
||||
function migrateAll(address account) public {
|
||||
uint256 balance = _legacyToken.balanceOf(account);
|
||||
uint256 allowance = _legacyToken.allowance(account, this);
|
||||
uint256 amount = Math.min(balance, allowance);
|
||||
migrate(account, amount);
|
||||
}
|
||||
/**
|
||||
* @dev Transfers all of an account's allowed balance in the old token to
|
||||
* this contract, and mints the same amount of new tokens for that account.
|
||||
* @param account whose tokens will be migrated
|
||||
*/
|
||||
function migrateAll(address account) public {
|
||||
uint256 balance = _legacyToken.balanceOf(account);
|
||||
uint256 allowance = _legacyToken.allowance(account, address(this));
|
||||
uint256 amount = Math.min(balance, allowance);
|
||||
migrate(account, amount);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
142
contracts/drafts/ERC20Snapshot.sol
Normal file
142
contracts/drafts/ERC20Snapshot.sol
Normal file
@ -0,0 +1,142 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
import "../utils/Arrays.sol";
|
||||
import "../drafts/Counters.sol";
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
|
||||
/**
|
||||
* @title ERC20 token with snapshots.
|
||||
* @dev Inspired by Jordi Baylina's MiniMeToken to record historical balances:
|
||||
* https://github.com/Giveth/minime/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol
|
||||
* When a snapshot is made, the balances and totalSupply at the time of the snapshot are recorded for later
|
||||
* access.
|
||||
*
|
||||
* To make a snapshot, call the `snapshot` function, which will emit the `Snapshot` event and return a snapshot id.
|
||||
* To get the total supply from a snapshot, call the function `totalSupplyAt` with the snapshot id.
|
||||
* To get the balance of an account from a snapshot, call the `balanceOfAt` function with the snapshot id and the
|
||||
* account address.
|
||||
* @author Validity Labs AG <info@validitylabs.org>
|
||||
*/
|
||||
contract ERC20Snapshot is Initializable, ERC20 {
|
||||
using SafeMath for uint256;
|
||||
using Arrays for uint256[];
|
||||
using Counters for Counters.Counter;
|
||||
|
||||
// Snapshotted values have arrays of ids and the value corresponding to that id. These could be an array of a
|
||||
// Snapshot struct, but that would impede usage of functions that work on an array.
|
||||
struct Snapshots {
|
||||
uint256[] ids;
|
||||
uint256[] values;
|
||||
}
|
||||
|
||||
mapping (address => Snapshots) private _accountBalanceSnapshots;
|
||||
Snapshots private _totalSupplySnaphots;
|
||||
|
||||
// Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid.
|
||||
Counters.Counter private _currentSnapshotId;
|
||||
|
||||
event Snapshot(uint256 id);
|
||||
|
||||
// Creates a new snapshot id. Balances are only stored in snapshots on demand: unless a snapshot was taken, a
|
||||
// balance change will not be recorded. This means the extra added cost of storing snapshotted balances is only paid
|
||||
// when required, but is also flexible enough that it allows for e.g. daily snapshots.
|
||||
function snapshot() public returns (uint256) {
|
||||
_currentSnapshotId.increment();
|
||||
|
||||
uint256 currentId = _currentSnapshotId.current();
|
||||
emit Snapshot(currentId);
|
||||
return currentId;
|
||||
}
|
||||
|
||||
function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) {
|
||||
(bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);
|
||||
|
||||
return snapshotted ? value : balanceOf(account);
|
||||
}
|
||||
|
||||
function totalSupplyAt(uint256 snapshotId) public view returns(uint256) {
|
||||
(bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnaphots);
|
||||
|
||||
return snapshotted ? value : totalSupply();
|
||||
}
|
||||
|
||||
// _transfer, _mint and _burn are the only functions where the balances are modified, so it is there that the
|
||||
// snapshots are updated. Note that the update happens _before_ the balance change, with the pre-modified value.
|
||||
// The same is true for the total supply and _mint and _burn.
|
||||
function _transfer(address from, address to, uint256 value) internal {
|
||||
_updateAccountSnapshot(from);
|
||||
_updateAccountSnapshot(to);
|
||||
|
||||
super._transfer(from, to, value);
|
||||
}
|
||||
|
||||
function _mint(address account, uint256 value) internal {
|
||||
_updateAccountSnapshot(account);
|
||||
_updateTotalSupplySnapshot();
|
||||
|
||||
super._mint(account, value);
|
||||
}
|
||||
|
||||
function _burn(address account, uint256 value) internal {
|
||||
_updateAccountSnapshot(account);
|
||||
_updateTotalSupplySnapshot();
|
||||
|
||||
super._burn(account, value);
|
||||
}
|
||||
|
||||
// When a valid snapshot is queried, there are three possibilities:
|
||||
// a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never
|
||||
// created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds
|
||||
// to this id is the current one.
|
||||
// b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the
|
||||
// requested id, and its value is the one to return.
|
||||
// c) More snapshots were created after the requested one, and the queried value was later modified. There will be
|
||||
// no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is
|
||||
// larger than the requested one.
|
||||
//
|
||||
// In summary, we need to find an element in an array, returning the index of the smallest value that is larger if
|
||||
// it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does
|
||||
// exactly this.
|
||||
function _valueAt(uint256 snapshotId, Snapshots storage snapshots)
|
||||
private view returns (bool, uint256)
|
||||
{
|
||||
require(snapshotId > 0);
|
||||
require(snapshotId <= _currentSnapshotId.current());
|
||||
|
||||
uint256 index = snapshots.ids.findUpperBound(snapshotId);
|
||||
|
||||
if (index == snapshots.ids.length) {
|
||||
return (false, 0);
|
||||
} else {
|
||||
return (true, snapshots.values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
function _updateAccountSnapshot(address account) private {
|
||||
_updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account));
|
||||
}
|
||||
|
||||
function _updateTotalSupplySnapshot() private {
|
||||
_updateSnapshot(_totalSupplySnaphots, totalSupply());
|
||||
}
|
||||
|
||||
function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private {
|
||||
uint256 currentId = _currentSnapshotId.current();
|
||||
if (_lastSnapshotId(snapshots.ids) < currentId) {
|
||||
snapshots.ids.push(currentId);
|
||||
snapshots.values.push(currentValue);
|
||||
}
|
||||
}
|
||||
|
||||
function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) {
|
||||
if (ids.length == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return ids[ids.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../access/roles/SignerRole.sol";
|
||||
import "../cryptography/ECDSA.sol";
|
||||
|
||||
@ -29,118 +30,94 @@ import "../cryptography/ECDSA.sol";
|
||||
* @notice A method that uses the `onlyValidSignatureAndData` modifier must make
|
||||
* the _signature parameter the "last" parameter. You cannot sign a message that
|
||||
* has its own signature in it so the last 128 bytes of msg.data (which
|
||||
* represents the length of the _signature data and the _signaature data itself)
|
||||
* represents the length of the _signature data and the _signature data itself)
|
||||
* is ignored when validating. Also non fixed sized parameters make constructing
|
||||
* the data in the signature much more complex.
|
||||
* See https://ethereum.stackexchange.com/a/50616 for more details.
|
||||
*/
|
||||
contract SignatureBouncer is SignerRole {
|
||||
using ECDSA for bytes32;
|
||||
contract SignatureBouncer is Initializable, SignerRole {
|
||||
using ECDSA for bytes32;
|
||||
|
||||
// Function selectors are 4 bytes long, as documented in
|
||||
// https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector
|
||||
uint256 private constant _METHOD_ID_SIZE = 4;
|
||||
// Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes
|
||||
uint256 private constant _SIGNATURE_SIZE = 96;
|
||||
// Function selectors are 4 bytes long, as documented in
|
||||
// https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector
|
||||
uint256 private constant _METHOD_ID_SIZE = 4;
|
||||
// Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes
|
||||
uint256 private constant _SIGNATURE_SIZE = 96;
|
||||
|
||||
constructor() internal {}
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature of a signer was provided
|
||||
*/
|
||||
modifier onlyValidSignature(bytes signature)
|
||||
{
|
||||
require(_isValidSignature(msg.sender, signature));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature with a specifed method of a signer was provided
|
||||
*/
|
||||
modifier onlyValidSignatureAndMethod(bytes signature)
|
||||
{
|
||||
require(_isValidSignatureAndMethod(msg.sender, signature));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature with a specifed method and params of a signer was provided
|
||||
*/
|
||||
modifier onlyValidSignatureAndData(bytes signature)
|
||||
{
|
||||
require(_isValidSignatureAndData(msg.sender, signature));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + sender` from a signer?
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidSignature(address account, bytes signature)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return _isValidDataHash(
|
||||
keccak256(abi.encodePacked(address(this), account)),
|
||||
signature
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + sender + methodId` from a signer?
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidSignatureAndMethod(address account, bytes signature)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
bytes memory data = new bytes(_METHOD_ID_SIZE);
|
||||
for (uint i = 0; i < data.length; i++) {
|
||||
data[i] = msg.data[i];
|
||||
function initialize(address sender) public initializer {
|
||||
SignerRole.initialize(sender);
|
||||
}
|
||||
return _isValidDataHash(
|
||||
keccak256(abi.encodePacked(address(this), account, data)),
|
||||
signature
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + sender + methodId + params(s)` from a signer?
|
||||
* @notice the signature parameter of the method being validated must be the "last" parameter
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidSignatureAndData(address account, bytes signature)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
require(msg.data.length > _SIGNATURE_SIZE);
|
||||
bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE);
|
||||
for (uint i = 0; i < data.length; i++) {
|
||||
data[i] = msg.data[i];
|
||||
/**
|
||||
* @dev requires that a valid signature of a signer was provided
|
||||
*/
|
||||
modifier onlyValidSignature(bytes memory signature) {
|
||||
require(_isValidSignature(msg.sender, signature));
|
||||
_;
|
||||
}
|
||||
return _isValidDataHash(
|
||||
keccak256(abi.encodePacked(address(this), account, data)),
|
||||
signature
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev internal function to convert a hash to an eth signed message
|
||||
* and then recover the signature and check it against the signer role
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidDataHash(bytes32 hash, bytes signature)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
address signer = hash
|
||||
.toEthSignedMessageHash()
|
||||
.recover(signature);
|
||||
/**
|
||||
* @dev requires that a valid signature with a specified method of a signer was provided
|
||||
*/
|
||||
modifier onlyValidSignatureAndMethod(bytes memory signature) {
|
||||
require(_isValidSignatureAndMethod(msg.sender, signature));
|
||||
_;
|
||||
}
|
||||
|
||||
return signer != address(0) && isSigner(signer);
|
||||
}
|
||||
/**
|
||||
* @dev requires that a valid signature with a specified method and params of a signer was provided
|
||||
*/
|
||||
modifier onlyValidSignatureAndData(bytes memory signature) {
|
||||
require(_isValidSignatureAndData(msg.sender, signature));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + account` from a signer?
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidSignature(address account, bytes memory signature) internal view returns (bool) {
|
||||
return _isValidDataHash(keccak256(abi.encodePacked(address(this), account)), signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + account + methodId` from a signer?
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidSignatureAndMethod(address account, bytes memory signature) internal view returns (bool) {
|
||||
bytes memory data = new bytes(_METHOD_ID_SIZE);
|
||||
for (uint i = 0; i < data.length; i++) {
|
||||
data[i] = msg.data[i];
|
||||
}
|
||||
return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + account + methodId + params(s)` from a signer?
|
||||
* @notice the signature parameter of the method being validated must be the "last" parameter
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) {
|
||||
require(msg.data.length > _SIGNATURE_SIZE);
|
||||
|
||||
bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE);
|
||||
for (uint i = 0; i < data.length; i++) {
|
||||
data[i] = msg.data[i];
|
||||
}
|
||||
|
||||
return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev internal function to convert a hash to an eth signed message
|
||||
* and then recover the signature and check it against the signer role
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidDataHash(bytes32 hash, bytes memory signature) internal view returns (bool) {
|
||||
address signer = hash.toEthSignedMessageHash().recover(signature);
|
||||
|
||||
return signer != address(0) && isSigner(signer);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
60
contracts/drafts/SignedSafeMath.sol
Normal file
60
contracts/drafts/SignedSafeMath.sol
Normal file
@ -0,0 +1,60 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
* @title SignedSafeMath
|
||||
* @dev Signed math operations with safety checks that revert on error
|
||||
*/
|
||||
library SignedSafeMath {
|
||||
int256 constant private INT256_MIN = -2**255;
|
||||
|
||||
/**
|
||||
* @dev Multiplies two signed integers, reverts on overflow.
|
||||
*/
|
||||
function mul(int256 a, int256 b) internal pure returns (int256) {
|
||||
// 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-solidity/pull/522
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
require(!(a == -1 && b == INT256_MIN)); // This is the only case of overflow not detected by the check below
|
||||
|
||||
int256 c = a * b;
|
||||
require(c / a == b);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
|
||||
*/
|
||||
function div(int256 a, int256 b) internal pure returns (int256) {
|
||||
require(b != 0); // Solidity only automatically asserts when dividing by 0
|
||||
require(!(b == -1 && a == INT256_MIN)); // This is the only case of overflow
|
||||
|
||||
int256 c = a / b;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Subtracts two signed integers, reverts on overflow.
|
||||
*/
|
||||
function sub(int256 a, int256 b) internal pure returns (int256) {
|
||||
int256 c = a - b;
|
||||
require((b >= 0 && c <= a) || (b < 0 && c > a));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Adds two signed integers, reverts on overflow.
|
||||
*/
|
||||
function add(int256 a, int256 b) internal pure returns (int256) {
|
||||
int256 c = a + b;
|
||||
require((b >= 0 && c >= a) || (b < 0 && c < a));
|
||||
|
||||
return c;
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
/* solium-disable security/no-block-members */
|
||||
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
@ -12,164 +11,167 @@ import "../math/SafeMath.sol";
|
||||
* typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
|
||||
* owner.
|
||||
*/
|
||||
contract TokenVesting is Ownable {
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
contract TokenVesting is Initializable, 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
|
||||
|
||||
event TokensReleased(address token, uint256 amount);
|
||||
event TokenVestingRevoked(address token);
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
// beneficiary of tokens after they are released
|
||||
address private _beneficiary;
|
||||
event TokensReleased(address token, uint256 amount);
|
||||
event TokenVestingRevoked(address token);
|
||||
|
||||
uint256 private _cliff;
|
||||
uint256 private _start;
|
||||
uint256 private _duration;
|
||||
// beneficiary of tokens after they are released
|
||||
address private _beneficiary;
|
||||
|
||||
bool private _revocable;
|
||||
// Durations and timestamps are expressed in UNIX time, the same units as block.timestamp.
|
||||
uint256 private _cliff;
|
||||
uint256 private _start;
|
||||
uint256 private _duration;
|
||||
|
||||
mapping (address => uint256) private _released;
|
||||
mapping (address => bool) private _revoked;
|
||||
bool private _revocable;
|
||||
|
||||
/**
|
||||
* @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));
|
||||
require(cliffDuration <= duration);
|
||||
require(duration > 0);
|
||||
require(start.add(duration) > block.timestamp);
|
||||
mapping (address => uint256) private _released;
|
||||
mapping (address => bool) private _revoked;
|
||||
|
||||
_beneficiary = beneficiary;
|
||||
_revocable = revocable;
|
||||
_duration = duration;
|
||||
_cliff = start.add(cliffDuration);
|
||||
_start = start;
|
||||
}
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
function initialize(address beneficiary, uint256 start, uint256 cliffDuration, uint256 duration, bool revocable, address sender) public initializer {
|
||||
Ownable.initialize(sender);
|
||||
|
||||
/**
|
||||
* @return the beneficiary of the tokens.
|
||||
*/
|
||||
function beneficiary() public view returns(address) {
|
||||
return _beneficiary;
|
||||
}
|
||||
require(beneficiary != address(0));
|
||||
require(cliffDuration <= duration);
|
||||
require(duration > 0);
|
||||
require(start.add(duration) > block.timestamp);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
_released[token] = _released[token].add(unreleased);
|
||||
|
||||
token.safeTransfer(_beneficiary, unreleased);
|
||||
|
||||
emit TokensReleased(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);
|
||||
require(!_revoked[token]);
|
||||
|
||||
uint256 balance = token.balanceOf(address(this));
|
||||
|
||||
uint256 unreleased = _releasableAmount(token);
|
||||
uint256 refund = balance.sub(unreleased);
|
||||
|
||||
_revoked[token] = true;
|
||||
|
||||
token.safeTransfer(owner(), refund);
|
||||
|
||||
emit TokenVestingRevoked(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[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(this);
|
||||
uint256 totalBalance = currentBalance.add(_released[token]);
|
||||
|
||||
if (block.timestamp < _cliff) {
|
||||
return 0;
|
||||
} else if (block.timestamp >= _start.add(_duration) || _revoked[token]) {
|
||||
return totalBalance;
|
||||
} else {
|
||||
return totalBalance.mul(block.timestamp.sub(_start)).div(_duration);
|
||||
_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);
|
||||
|
||||
_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);
|
||||
require(!_revoked[address(token)]);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||
import "../crowdsale/emission/MintedCrowdsale.sol";
|
||||
@ -11,8 +12,13 @@ import "../token/ERC20/ERC20Detailed.sol";
|
||||
* @dev Very simple ERC20 Token that can be minted.
|
||||
* It is meant to be used in a crowdsale contract.
|
||||
*/
|
||||
contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed {
|
||||
constructor() public ERC20Detailed("Sample Crowdsale Token", "SCT", 18) {}
|
||||
contract SampleCrowdsaleToken is Initializable, ERC20Mintable, ERC20Detailed {
|
||||
function initialize(address sender) public initializer {
|
||||
ERC20Mintable.initialize(sender);
|
||||
ERC20Detailed.initialize("Sample Crowdsale Token", "SCT", 18);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -28,30 +34,29 @@ contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed {
|
||||
* After adding multiple features it's good practice to run integration tests
|
||||
* to ensure that subcontracts works together as intended.
|
||||
*/
|
||||
// XXX There doesn't seem to be a way to split this line that keeps solium
|
||||
// happy. See:
|
||||
// https://github.com/duaraghav8/Solium/issues/205
|
||||
// --elopio - 2018-05-10
|
||||
// solium-disable-next-line max-len
|
||||
contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale, MintedCrowdsale {
|
||||
contract SampleCrowdsale is Initializable, Crowdsale, CappedCrowdsale, RefundableCrowdsale, MintedCrowdsale {
|
||||
|
||||
constructor(
|
||||
uint256 openingTime,
|
||||
uint256 closingTime,
|
||||
uint256 rate,
|
||||
address wallet,
|
||||
uint256 cap,
|
||||
ERC20Mintable token,
|
||||
uint256 goal
|
||||
)
|
||||
public
|
||||
Crowdsale(rate, wallet, token)
|
||||
CappedCrowdsale(cap)
|
||||
TimedCrowdsale(openingTime, closingTime)
|
||||
RefundableCrowdsale(goal)
|
||||
{
|
||||
//As goal needs to be met for a successful crowdsale
|
||||
//the value needs to less or equal than a cap which is limit for accepted funds
|
||||
require(goal <= cap);
|
||||
}
|
||||
function initialize(
|
||||
uint256 openingTime,
|
||||
uint256 closingTime,
|
||||
uint256 rate,
|
||||
address payable wallet,
|
||||
uint256 cap,
|
||||
ERC20Mintable token,
|
||||
uint256 goal
|
||||
)
|
||||
public
|
||||
initializer
|
||||
{
|
||||
Crowdsale.initialize(rate, wallet, token);
|
||||
CappedCrowdsale.initialize(cap);
|
||||
TimedCrowdsale.initialize(openingTime, closingTime);
|
||||
RefundableCrowdsale.initialize(goal);
|
||||
|
||||
//As goal needs to be met for a successful crowdsale
|
||||
//the value needs to less or equal than a cap which is limit for accepted funds
|
||||
require(goal <= cap);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
|
||||
/**
|
||||
* @title SimpleToken
|
||||
@ -8,19 +10,17 @@ import "../token/ERC20/ERC20.sol";
|
||||
* Note they can later distribute these tokens as they wish using `transfer` and other
|
||||
* `ERC20` functions.
|
||||
*/
|
||||
contract SimpleToken is ERC20 {
|
||||
contract SimpleToken is Initializable, ERC20, ERC20Detailed {
|
||||
uint8 public constant DECIMALS = 18;
|
||||
uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(DECIMALS));
|
||||
|
||||
string public constant name = "SimpleToken";
|
||||
string public constant symbol = "SIM";
|
||||
uint8 public constant decimals = 18;
|
||||
|
||||
uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals));
|
||||
|
||||
/**
|
||||
* @dev Constructor that gives msg.sender all of existing tokens.
|
||||
*/
|
||||
constructor() public {
|
||||
_mint(msg.sender, INITIAL_SUPPLY);
|
||||
}
|
||||
/**
|
||||
* @dev Constructor that gives msg.sender all of existing tokens.
|
||||
*/
|
||||
function initialize(address sender) public initializer {
|
||||
ERC20Detailed.initialize("SimpleToken", "SIM", DECIMALS);
|
||||
_mint(sender, INITIAL_SUPPLY);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "./IERC165.sol";
|
||||
|
||||
/**
|
||||
@ -7,47 +8,40 @@ import "./IERC165.sol";
|
||||
* @author Matt Condon (@shrugs)
|
||||
* @dev Implements ERC165 using a lookup table.
|
||||
*/
|
||||
contract ERC165 is IERC165 {
|
||||
contract ERC165 is Initializable, IERC165 {
|
||||
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
/*
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
*/
|
||||
|
||||
bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7;
|
||||
/**
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
*/
|
||||
/**
|
||||
* @dev a mapping of interface id to whether or not it's supported
|
||||
*/
|
||||
mapping(bytes4 => bool) private _supportedInterfaces;
|
||||
|
||||
/**
|
||||
* @dev a mapping of interface id to whether or not it's supported
|
||||
*/
|
||||
mapping(bytes4 => bool) private _supportedInterfaces;
|
||||
/**
|
||||
* @dev A contract implementing SupportsInterfaceWithLookup
|
||||
* implement ERC165 itself
|
||||
*/
|
||||
function initialize() public initializer {
|
||||
_registerInterface(_INTERFACE_ID_ERC165);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev A contract implementing SupportsInterfaceWithLookup
|
||||
* implement ERC165 itself
|
||||
*/
|
||||
constructor()
|
||||
internal
|
||||
{
|
||||
_registerInterface(_InterfaceId_ERC165);
|
||||
}
|
||||
/**
|
||||
* @dev implement supportsInterface(bytes4) using a lookup table
|
||||
*/
|
||||
function supportsInterface(bytes4 interfaceId) public view returns (bool) {
|
||||
return _supportedInterfaces[interfaceId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev implement supportsInterface(bytes4) using a lookup table
|
||||
*/
|
||||
function supportsInterface(bytes4 interfaceId)
|
||||
external
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return _supportedInterfaces[interfaceId];
|
||||
}
|
||||
/**
|
||||
* @dev internal method for registering an interface
|
||||
*/
|
||||
function _registerInterface(bytes4 interfaceId) internal {
|
||||
require(interfaceId != 0xffffffff);
|
||||
_supportedInterfaces[interfaceId] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev internal method for registering an interface
|
||||
*/
|
||||
function _registerInterface(bytes4 interfaceId)
|
||||
internal
|
||||
{
|
||||
require(interfaceId != 0xffffffff);
|
||||
_supportedInterfaces[interfaceId] = true;
|
||||
}
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,146 +1,123 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
* @title ERC165Checker
|
||||
* @dev Use `using ERC165Checker for address`; to include this library
|
||||
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
|
||||
* https://eips.ethereum.org/EIPS/eip-165
|
||||
*/
|
||||
library ERC165Checker {
|
||||
// As per the EIP-165 spec, no interface should ever match 0xffffffff
|
||||
bytes4 private constant _InterfaceId_Invalid = 0xffffffff;
|
||||
// As per the EIP-165 spec, no interface should ever match 0xffffffff
|
||||
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
|
||||
|
||||
bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7;
|
||||
/**
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
*/
|
||||
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
/*
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
*/
|
||||
|
||||
/**
|
||||
* @notice Query if a contract supports ERC165
|
||||
* @param account The address of the contract to query for support of ERC165
|
||||
* @return true if the contract at account implements ERC165
|
||||
*/
|
||||
function _supportsERC165(address account)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
// Any contract that implements ERC165 must explicitly indicate support of
|
||||
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
|
||||
return _supportsERC165Interface(account, _InterfaceId_ERC165) &&
|
||||
!_supportsERC165Interface(account, _InterfaceId_Invalid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Query if a contract implements an interface, also checks support of ERC165
|
||||
* @param account The address of the contract to query for support of an interface
|
||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||
* @return true if the contract at account indicates support of the interface with
|
||||
* identifier interfaceId, false otherwise
|
||||
* @dev Interface identification is specified in ERC-165.
|
||||
*/
|
||||
function _supportsInterface(address account, bytes4 interfaceId)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
// query support of both ERC165 as per the spec and support of _interfaceId
|
||||
return _supportsERC165(account) &&
|
||||
_supportsERC165Interface(account, interfaceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Query if a contract implements interfaces, also checks support of ERC165
|
||||
* @param account The address of the contract to query for support of an interface
|
||||
* @param interfaceIds A list of interface identifiers, as specified in ERC-165
|
||||
* @return true if the contract at account indicates support all interfaces in the
|
||||
* interfaceIds list, false otherwise
|
||||
* @dev Interface identification is specified in ERC-165.
|
||||
*/
|
||||
function _supportsAllInterfaces(address account, bytes4[] interfaceIds)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
// query support of ERC165 itself
|
||||
if (!_supportsERC165(account)) {
|
||||
return false;
|
||||
/**
|
||||
* @notice Query if a contract supports ERC165
|
||||
* @param account The address of the contract to query for support of ERC165
|
||||
* @return true if the contract at account implements ERC165
|
||||
*/
|
||||
function _supportsERC165(address account) internal view returns (bool) {
|
||||
// Any contract that implements ERC165 must explicitly indicate support of
|
||||
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
|
||||
return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) &&
|
||||
!_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
|
||||
}
|
||||
|
||||
// query support of each interface in _interfaceIds
|
||||
for (uint256 i = 0; i < interfaceIds.length; i++) {
|
||||
if (!_supportsERC165Interface(account, interfaceIds[i])) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @notice Query if a contract implements an interface, also checks support of ERC165
|
||||
* @param account The address of the contract to query for support of an interface
|
||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||
* @return true if the contract at account indicates support of the interface with
|
||||
* identifier interfaceId, false otherwise
|
||||
* @dev Interface identification is specified in ERC-165.
|
||||
*/
|
||||
function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
|
||||
// query support of both ERC165 as per the spec and support of _interfaceId
|
||||
return _supportsERC165(account) &&
|
||||
_supportsERC165Interface(account, interfaceId);
|
||||
}
|
||||
|
||||
// all interfaces supported
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @notice Query if a contract implements interfaces, also checks support of ERC165
|
||||
* @param account The address of the contract to query for support of an interface
|
||||
* @param interfaceIds A list of interface identifiers, as specified in ERC-165
|
||||
* @return true if the contract at account indicates support all interfaces in the
|
||||
* interfaceIds list, false otherwise
|
||||
* @dev Interface identification is specified in ERC-165.
|
||||
*/
|
||||
function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
|
||||
// query support of ERC165 itself
|
||||
if (!_supportsERC165(account)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Query if a contract implements an interface, does not check ERC165 support
|
||||
* @param account The address of the contract to query for support of an interface
|
||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||
* @return true if the contract at account indicates support of the interface with
|
||||
* identifier interfaceId, false otherwise
|
||||
* @dev Assumes that account contains a contract that supports ERC165, otherwise
|
||||
* the behavior of this method is undefined. This precondition can be checked
|
||||
* with the `supportsERC165` method in this library.
|
||||
* Interface identification is specified in ERC-165.
|
||||
*/
|
||||
function _supportsERC165Interface(address account, bytes4 interfaceId)
|
||||
private
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
// success determines whether the staticcall succeeded and result determines
|
||||
// whether the contract at account indicates support of _interfaceId
|
||||
(bool success, bool result) = _callERC165SupportsInterface(
|
||||
account, interfaceId);
|
||||
// query support of each interface in _interfaceIds
|
||||
for (uint256 i = 0; i < interfaceIds.length; i++) {
|
||||
if (!_supportsERC165Interface(account, interfaceIds[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (success && result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw
|
||||
* @param account The address of the contract to query for support of an interface
|
||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||
* @return success true if the STATICCALL succeeded, false otherwise
|
||||
* @return result true if the STATICCALL succeeded and the contract at account
|
||||
* indicates support of the interface with identifier interfaceId, false otherwise
|
||||
*/
|
||||
function _callERC165SupportsInterface(
|
||||
address account,
|
||||
bytes4 interfaceId
|
||||
)
|
||||
private
|
||||
view
|
||||
returns (bool success, bool result)
|
||||
{
|
||||
bytes memory encodedParams = abi.encodeWithSelector(
|
||||
_InterfaceId_ERC165,
|
||||
interfaceId
|
||||
);
|
||||
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
let encodedParams_data := add(0x20, encodedParams)
|
||||
let encodedParams_size := mload(encodedParams)
|
||||
|
||||
let output := mload(0x40) // Find empty storage location using "free memory pointer"
|
||||
mstore(output, 0x0)
|
||||
|
||||
success := staticcall(
|
||||
30000, // 30k gas
|
||||
account, // To addr
|
||||
encodedParams_data,
|
||||
encodedParams_size,
|
||||
output,
|
||||
0x20 // Outputs are 32 bytes long
|
||||
)
|
||||
|
||||
result := mload(output) // Load the result
|
||||
// all interfaces supported
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Query if a contract implements an interface, does not check ERC165 support
|
||||
* @param account The address of the contract to query for support of an interface
|
||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||
* @return true if the contract at account indicates support of the interface with
|
||||
* identifier interfaceId, false otherwise
|
||||
* @dev Assumes that account contains a contract that supports ERC165, otherwise
|
||||
* the behavior of this method is undefined. This precondition can be checked
|
||||
* with the `supportsERC165` method in this library.
|
||||
* Interface identification is specified in ERC-165.
|
||||
*/
|
||||
function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
|
||||
// success determines whether the staticcall succeeded and result determines
|
||||
// whether the contract at account indicates support of _interfaceId
|
||||
(bool success, bool result) = _callERC165SupportsInterface(account, interfaceId);
|
||||
|
||||
return (success && result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw
|
||||
* @param account The address of the contract to query for support of an interface
|
||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||
* @return success true if the STATICCALL succeeded, false otherwise
|
||||
* @return result true if the STATICCALL succeeded and the contract at account
|
||||
* indicates support of the interface with identifier interfaceId, false otherwise
|
||||
*/
|
||||
function _callERC165SupportsInterface(address account, bytes4 interfaceId)
|
||||
private
|
||||
view
|
||||
returns (bool success, bool result)
|
||||
{
|
||||
bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId);
|
||||
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly {
|
||||
let encodedParams_data := add(0x20, encodedParams)
|
||||
let encodedParams_size := mload(encodedParams)
|
||||
|
||||
let output := mload(0x40) // Find empty storage location using "free memory pointer"
|
||||
mstore(output, 0x0)
|
||||
|
||||
success := staticcall(
|
||||
30000, // 30k gas
|
||||
account, // To addr
|
||||
encodedParams_data,
|
||||
encodedParams_size,
|
||||
output,
|
||||
0x20 // Outputs are 32 bytes long
|
||||
)
|
||||
|
||||
result := mload(output) // Load the result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,19 +1,15 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
* @title IERC165
|
||||
* @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
|
||||
* @dev https://eips.ethereum.org/EIPS/eip-165
|
||||
*/
|
||||
interface IERC165 {
|
||||
|
||||
/**
|
||||
* @notice Query if a contract implements an interface
|
||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||
* @dev Interface identification is specified in ERC-165. This function
|
||||
* uses less than 30,000 gas.
|
||||
*/
|
||||
function supportsInterface(bytes4 interfaceId)
|
||||
external
|
||||
view
|
||||
returns (bool);
|
||||
/**
|
||||
* @notice Query if a contract implements an interface
|
||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||
* @dev Interface identification is specified in ERC-165. This function
|
||||
* uses less than 30,000 gas.
|
||||
*/
|
||||
function supportsInterface(bytes4 interfaceId) external view returns (bool);
|
||||
}
|
||||
|
||||
@ -1,57 +1,62 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "@openzeppelin/upgrades/contracts/Initializable.sol";
|
||||
import "../access/roles/PauserRole.sol";
|
||||
|
||||
/**
|
||||
* @title Pausable
|
||||
* @dev Base contract which allows children to implement an emergency stop mechanism.
|
||||
*/
|
||||
contract Pausable is PauserRole {
|
||||
event Paused(address account);
|
||||
event Unpaused(address account);
|
||||
contract Pausable is Initializable, PauserRole {
|
||||
event Paused(address account);
|
||||
event Unpaused(address account);
|
||||
|
||||
bool private _paused;
|
||||
bool private _paused;
|
||||
|
||||
constructor() internal {
|
||||
_paused = false;
|
||||
}
|
||||
function initialize(address sender) public initializer {
|
||||
PauserRole.initialize(sender);
|
||||
|
||||
/**
|
||||
* @return true if the contract is paused, false otherwise.
|
||||
*/
|
||||
function paused() public view returns(bool) {
|
||||
return _paused;
|
||||
}
|
||||
_paused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Modifier to make a function callable only when the contract is not paused.
|
||||
*/
|
||||
modifier whenNotPaused() {
|
||||
require(!_paused);
|
||||
_;
|
||||
}
|
||||
/**
|
||||
* @return true if the contract is paused, false otherwise.
|
||||
*/
|
||||
function paused() public view returns (bool) {
|
||||
return _paused;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Modifier to make a function callable only when the contract is paused.
|
||||
*/
|
||||
modifier whenPaused() {
|
||||
require(_paused);
|
||||
_;
|
||||
}
|
||||
/**
|
||||
* @dev Modifier to make a function callable only when the contract is not paused.
|
||||
*/
|
||||
modifier whenNotPaused() {
|
||||
require(!_paused);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev called by the owner to pause, triggers stopped state
|
||||
*/
|
||||
function pause() public onlyPauser whenNotPaused {
|
||||
_paused = true;
|
||||
emit Paused(msg.sender);
|
||||
}
|
||||
/**
|
||||
* @dev Modifier to make a function callable only when the contract is paused.
|
||||
*/
|
||||
modifier whenPaused() {
|
||||
require(_paused);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev called by the owner to unpause, returns to normal state
|
||||
*/
|
||||
function unpause() public onlyPauser whenPaused {
|
||||
_paused = false;
|
||||
emit Unpaused(msg.sender);
|
||||
}
|
||||
/**
|
||||
* @dev called by the owner to pause, triggers stopped state
|
||||
*/
|
||||
function pause() public onlyPauser whenNotPaused {
|
||||
_paused = true;
|
||||
emit Paused(msg.sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev called by the owner to unpause, returns to normal state
|
||||
*/
|
||||
function unpause() public onlyPauser whenPaused {
|
||||
_paused = false;
|
||||
emit Unpaused(msg.sender);
|
||||
}
|
||||
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
||||
@ -1,31 +1,31 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
* @title Math
|
||||
* @dev Assorted math operations
|
||||
*/
|
||||
library Math {
|
||||
/**
|
||||
* @dev Returns the largest of two numbers.
|
||||
*/
|
||||
function max(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
return a >= b ? a : b;
|
||||
}
|
||||
/**
|
||||
* @dev Returns the largest of two numbers.
|
||||
*/
|
||||
function max(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
return a >= b ? a : b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the smallest of two numbers.
|
||||
*/
|
||||
function min(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
/**
|
||||
* @dev Returns the smallest of two numbers.
|
||||
*/
|
||||
function min(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates the average of two numbers. Since these are integers,
|
||||
* averages of an even and odd number cannot be represented, and will be
|
||||
* rounded down.
|
||||
*/
|
||||
function average(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// (a + b) / 2 can overflow, so we distribute
|
||||
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
|
||||
}
|
||||
/**
|
||||
* @dev Calculates the average of two numbers. Since these are integers,
|
||||
* averages of an even and odd number cannot be represented, and will be
|
||||
* rounded down.
|
||||
*/
|
||||
function average(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// (a + b) / 2 can overflow, so we distribute
|
||||
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,65 +1,65 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
/**
|
||||
* @title SafeMath
|
||||
* @dev Math operations with safety checks that revert on error
|
||||
* @dev Unsigned math operations with safety checks that revert on error
|
||||
*/
|
||||
library SafeMath {
|
||||
/**
|
||||
* @dev Multiplies two unsigned integers, reverts on 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-solidity/pull/522
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Multiplies two numbers, reverts on 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-solidity/pull/522
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
uint256 c = a * b;
|
||||
require(c / a == b);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint256 c = a * b;
|
||||
require(c / a == b);
|
||||
/**
|
||||
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
|
||||
*/
|
||||
function div(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// Solidity only automatically asserts when dividing by 0
|
||||
require(b > 0);
|
||||
uint256 c = a / b;
|
||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
||||
|
||||
return c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
|
||||
*/
|
||||
function div(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b > 0); // Solidity only automatically asserts when dividing by 0
|
||||
uint256 c = a / b;
|
||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
||||
/**
|
||||
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
|
||||
*/
|
||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b <= a);
|
||||
uint256 c = a - b;
|
||||
|
||||
return c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
|
||||
*/
|
||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b <= a);
|
||||
uint256 c = a - b;
|
||||
/**
|
||||
* @dev Adds two unsigned integers, reverts on overflow.
|
||||
*/
|
||||
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
uint256 c = a + b;
|
||||
require(c >= a);
|
||||
|
||||
return c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Adds two numbers, reverts on overflow.
|
||||
*/
|
||||
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
uint256 c = a + b;
|
||||
require(c >= a);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Divides two numbers and returns the remainder (unsigned integer modulo),
|
||||
* reverts when dividing by zero.
|
||||
*/
|
||||
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b != 0);
|
||||
return a % b;
|
||||
}
|
||||
/**
|
||||
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
|
||||
* reverts when dividing by zero.
|
||||
*/
|
||||
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b != 0);
|
||||
return a % b;
|
||||
}
|
||||
}
|
||||
|
||||
19
contracts/mocks/Acknowledger.sol
Normal file
19
contracts/mocks/Acknowledger.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
contract Acknowledger {
|
||||
event AcknowledgeFoo(uint256 a);
|
||||
event AcknowledgeBarSingle(uint256 a);
|
||||
event AcknowledgeBarDouble(uint256 a, uint256 b);
|
||||
|
||||
function foo(uint256 a) public {
|
||||
emit AcknowledgeFoo(a);
|
||||
}
|
||||
|
||||
function bar(uint256 a) public {
|
||||
emit AcknowledgeBarSingle(a);
|
||||
}
|
||||
|
||||
function bar(uint256 a, uint256 b) public {
|
||||
emit AcknowledgeBarDouble(a, b);
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,9 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../utils/Address.sol";
|
||||
|
||||
contract AddressImpl {
|
||||
function isContract(address account)
|
||||
external
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return Address.isContract(account);
|
||||
}
|
||||
|
||||
function isContract(address account) external view returns (bool) {
|
||||
return Address.isContract(account);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,20 +1,13 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../crowdsale/emission/AllowanceCrowdsale.sol";
|
||||
|
||||
contract AllowanceCrowdsaleImpl is AllowanceCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 rate,
|
||||
address wallet,
|
||||
IERC20 token,
|
||||
address tokenWallet
|
||||
)
|
||||
public
|
||||
Crowdsale(rate, wallet, token)
|
||||
AllowanceCrowdsale(tokenWallet)
|
||||
{
|
||||
}
|
||||
|
||||
constructor (uint256 rate, address payable wallet, IERC20 token, address tokenWallet)
|
||||
public
|
||||
{
|
||||
Crowdsale.initialize(rate, wallet, token);
|
||||
AllowanceCrowdsale.initialize(tokenWallet);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../utils/Arrays.sol";
|
||||
|
||||
contract ArraysImpl {
|
||||
using Arrays for uint256[];
|
||||
|
||||
using Arrays for uint256[];
|
||||
uint256[] private array;
|
||||
|
||||
uint256[] private array;
|
||||
constructor (uint256[] memory _array) public {
|
||||
array = _array;
|
||||
}
|
||||
|
||||
constructor(uint256[] _array) public {
|
||||
array = _array;
|
||||
}
|
||||
|
||||
function findUpperBound(uint256 _element) external view returns (uint256) {
|
||||
return array.findUpperBound(_element);
|
||||
}
|
||||
function findUpperBound(uint256 _element) external view returns (uint256) {
|
||||
return array.findUpperBound(_element);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,20 +1,13 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../token/ERC20/IERC20.sol";
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
|
||||
contract CappedCrowdsaleImpl is CappedCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 rate,
|
||||
address wallet,
|
||||
IERC20 token,
|
||||
uint256 cap
|
||||
)
|
||||
public
|
||||
Crowdsale(rate, wallet, token)
|
||||
CappedCrowdsale(cap)
|
||||
{
|
||||
}
|
||||
|
||||
constructor (uint256 rate, address payable wallet, IERC20 token, uint256 cap)
|
||||
public
|
||||
{
|
||||
Crowdsale.initialize(rate, wallet, token);
|
||||
CappedCrowdsale.initialize(cap);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,17 +1,22 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../access/roles/CapperRole.sol";
|
||||
|
||||
contract CapperRoleMock is CapperRole {
|
||||
function removeCapper(address account) public {
|
||||
_removeCapper(account);
|
||||
}
|
||||
constructor() public {
|
||||
CapperRole.initialize(msg.sender);
|
||||
}
|
||||
|
||||
function onlyCapperMock() public view onlyCapper {
|
||||
}
|
||||
function removeCapper(address account) public {
|
||||
_removeCapper(account);
|
||||
}
|
||||
|
||||
// Causes a compilation error if super._removeCapper is not internal
|
||||
function _removeCapper(address account) internal {
|
||||
super._removeCapper(account);
|
||||
}
|
||||
function onlyCapperMock() public view onlyCapper {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
// Causes a compilation error if super._removeCapper is not internal
|
||||
function _removeCapper(address account) internal {
|
||||
super._removeCapper(account);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../payment/escrow/ConditionalEscrow.sol";
|
||||
|
||||
// mock class using ConditionalEscrow
|
||||
contract ConditionalEscrowMock is ConditionalEscrow {
|
||||
mapping(address => bool) private _allowed;
|
||||
mapping(address => bool) private _allowed;
|
||||
|
||||
function setAllowed(address payee, bool allowed) public {
|
||||
_allowed[payee] = allowed;
|
||||
}
|
||||
constructor() public {
|
||||
ConditionalEscrow.initialize(msg.sender);
|
||||
}
|
||||
|
||||
function withdrawalAllowed(address payee) public view returns (bool) {
|
||||
return _allowed[payee];
|
||||
}
|
||||
function setAllowed(address payee, bool allowed) public {
|
||||
_allowed[payee] = allowed;
|
||||
}
|
||||
|
||||
function withdrawalAllowed(address payee) public view returns (bool) {
|
||||
return _allowed[payee];
|
||||
}
|
||||
}
|
||||
|
||||
27
contracts/mocks/ContextMock.sol
Normal file
27
contracts/mocks/ContextMock.sol
Normal file
@ -0,0 +1,27 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../GSN/Context.sol";
|
||||
|
||||
contract ContextMock is Context {
|
||||
event Sender(address sender);
|
||||
|
||||
function msgSender() public {
|
||||
emit Sender(_msgSender());
|
||||
}
|
||||
|
||||
event Data(bytes data, uint256 integerValue, string stringValue);
|
||||
|
||||
function msgData(uint256 integerValue, string memory stringValue) public {
|
||||
emit Data(_msgData(), integerValue, stringValue);
|
||||
}
|
||||
}
|
||||
|
||||
contract ContextMockCaller {
|
||||
function callSender(ContextMock context) public {
|
||||
context.msgSender();
|
||||
}
|
||||
|
||||
function callData(ContextMock context, uint256 integerValue, string memory stringValue) public {
|
||||
context.msgData(integerValue, stringValue);
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../drafts/Counter.sol";
|
||||
|
||||
contract CounterImpl {
|
||||
using Counter for Counter.Counter;
|
||||
|
||||
uint256 public theId;
|
||||
|
||||
// use whatever key you want to track your counters
|
||||
mapping(string => Counter.Counter) private _counters;
|
||||
|
||||
function doThing(string key)
|
||||
public
|
||||
returns (uint256)
|
||||
{
|
||||
theId = _counters[key].next();
|
||||
return theId;
|
||||
}
|
||||
}
|
||||
21
contracts/mocks/CountersImpl.sol
Normal file
21
contracts/mocks/CountersImpl.sol
Normal file
@ -0,0 +1,21 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../drafts/Counters.sol";
|
||||
|
||||
contract CountersImpl {
|
||||
using Counters for Counters.Counter;
|
||||
|
||||
Counters.Counter private _counter;
|
||||
|
||||
function current() public view returns (uint256) {
|
||||
return _counter.current();
|
||||
}
|
||||
|
||||
function increment() public {
|
||||
_counter.increment();
|
||||
}
|
||||
|
||||
function decrement() public {
|
||||
_counter.decrement();
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../crowdsale/Crowdsale.sol";
|
||||
|
||||
contract CrowdsaleMock is Crowdsale {
|
||||
constructor(uint256 rate, address wallet, IERC20 token) public
|
||||
Crowdsale(rate, wallet, token) {
|
||||
}
|
||||
constructor (uint256 rate, address payable wallet, IERC20 token) public {
|
||||
Crowdsale.initialize(rate, wallet, token);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
|
||||
contract ERC20DetailedMock is ERC20, ERC20Detailed {
|
||||
constructor(
|
||||
string name,
|
||||
string symbol,
|
||||
uint8 decimals
|
||||
)
|
||||
ERC20Detailed(name, symbol, decimals)
|
||||
public
|
||||
{}
|
||||
}
|
||||
@ -1,23 +1,15 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../cryptography/ECDSA.sol";
|
||||
|
||||
contract ECDSAMock {
|
||||
using ECDSA for bytes32;
|
||||
using ECDSA for bytes32;
|
||||
|
||||
function recover(bytes32 hash, bytes signature)
|
||||
public
|
||||
pure
|
||||
returns (address)
|
||||
{
|
||||
return hash.recover(signature);
|
||||
}
|
||||
function recover(bytes32 hash, bytes memory signature) public pure returns (address) {
|
||||
return hash.recover(signature);
|
||||
}
|
||||
|
||||
function toEthSignedMessageHash(bytes32 hash)
|
||||
public
|
||||
pure
|
||||
returns (bytes32)
|
||||
{
|
||||
return hash.toEthSignedMessageHash();
|
||||
}
|
||||
function toEthSignedMessageHash(bytes32 hash) public pure returns (bytes32) {
|
||||
return hash.toEthSignedMessageHash();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,66 +1,57 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../../introspection/IERC165.sol";
|
||||
|
||||
/**
|
||||
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-214.md#specification
|
||||
* > Any attempts to make state-changing operations inside an execution instance with STATIC set to true will instead throw an exception.
|
||||
* https://eips.ethereum.org/EIPS/eip-214#specification
|
||||
* From the specification:
|
||||
* > Any attempts to make state-changing operations inside an execution instance with STATIC set to true will instead
|
||||
* throw an exception.
|
||||
* > These operations include [...], LOG0, LOG1, LOG2, [...]
|
||||
*
|
||||
* therefore, because this contract is staticcall'd we need to not emit events (which is how solidity-coverage works)
|
||||
* solidity-coverage ignores the /mocks folder, so we duplicate its implementation here to avoid instrumenting it
|
||||
*/
|
||||
contract SupportsInterfaceWithLookupMock is IERC165 {
|
||||
bytes4 public constant INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||
/*
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
*/
|
||||
|
||||
bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7;
|
||||
/**
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
*/
|
||||
/**
|
||||
* @dev a mapping of interface id to whether or not it's supported
|
||||
*/
|
||||
mapping(bytes4 => bool) private _supportedInterfaces;
|
||||
|
||||
/**
|
||||
* @dev a mapping of interface id to whether or not it's supported
|
||||
*/
|
||||
mapping(bytes4 => bool) private _supportedInterfaces;
|
||||
/**
|
||||
* @dev A contract implementing SupportsInterfaceWithLookup
|
||||
* implement ERC165 itself
|
||||
*/
|
||||
constructor () public {
|
||||
_registerInterface(INTERFACE_ID_ERC165);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev A contract implementing SupportsInterfaceWithLookup
|
||||
* implement ERC165 itself
|
||||
*/
|
||||
constructor()
|
||||
public
|
||||
{
|
||||
_registerInterface(InterfaceId_ERC165);
|
||||
}
|
||||
/**
|
||||
* @dev implement supportsInterface(bytes4) using a lookup table
|
||||
*/
|
||||
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
|
||||
return _supportedInterfaces[interfaceId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev implement supportsInterface(bytes4) using a lookup table
|
||||
*/
|
||||
function supportsInterface(bytes4 interfaceId)
|
||||
external
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return _supportedInterfaces[interfaceId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev private method for registering an interface
|
||||
*/
|
||||
function _registerInterface(bytes4 interfaceId)
|
||||
internal
|
||||
{
|
||||
require(interfaceId != 0xffffffff);
|
||||
_supportedInterfaces[interfaceId] = true;
|
||||
}
|
||||
/**
|
||||
* @dev private method for registering an interface
|
||||
*/
|
||||
function _registerInterface(bytes4 interfaceId) internal {
|
||||
require(interfaceId != 0xffffffff);
|
||||
_supportedInterfaces[interfaceId] = true;
|
||||
}
|
||||
}
|
||||
|
||||
contract ERC165InterfacesSupported is SupportsInterfaceWithLookupMock {
|
||||
constructor (bytes4[] interfaceIds)
|
||||
public
|
||||
{
|
||||
for (uint256 i = 0; i < interfaceIds.length; i++) {
|
||||
_registerInterface(interfaceIds[i]);
|
||||
constructor (bytes4[] memory interfaceIds) public {
|
||||
for (uint256 i = 0; i < interfaceIds.length; i++) {
|
||||
_registerInterface(interfaceIds[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
contract ERC165NotSupported {
|
||||
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
@ -1,31 +1,19 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../introspection/ERC165Checker.sol";
|
||||
|
||||
contract ERC165CheckerMock {
|
||||
using ERC165Checker for address;
|
||||
using ERC165Checker for address;
|
||||
|
||||
function supportsERC165(address account)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return account._supportsERC165();
|
||||
}
|
||||
function supportsERC165(address account) public view returns (bool) {
|
||||
return account._supportsERC165();
|
||||
}
|
||||
|
||||
function supportsInterface(address account, bytes4 interfaceId)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return account._supportsInterface(interfaceId);
|
||||
}
|
||||
function supportsInterface(address account, bytes4 interfaceId) public view returns (bool) {
|
||||
return account._supportsInterface(interfaceId);
|
||||
}
|
||||
|
||||
function supportsAllInterfaces(address account, bytes4[] interfaceIds)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return account._supportsAllInterfaces(interfaceIds);
|
||||
}
|
||||
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) public view returns (bool) {
|
||||
return account._supportsAllInterfaces(interfaceIds);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../introspection/ERC165.sol";
|
||||
|
||||
contract ERC165Mock is ERC165 {
|
||||
function registerInterface(bytes4 interfaceId)
|
||||
public
|
||||
{
|
||||
_registerInterface(interfaceId);
|
||||
}
|
||||
constructor() public {
|
||||
ERC165.initialize();
|
||||
}
|
||||
|
||||
function registerInterface(bytes4 interfaceId) public {
|
||||
_registerInterface(interfaceId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../token/ERC20/ERC20Burnable.sol";
|
||||
|
||||
contract ERC20BurnableMock is ERC20Burnable {
|
||||
|
||||
constructor(address initialAccount, uint256 initialBalance) public {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
|
||||
constructor(address initialAccount, uint256 initialBalance) public {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
}
|
||||
|
||||
13
contracts/mocks/ERC20CappedMock.sol
Normal file
13
contracts/mocks/ERC20CappedMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC20/ERC20Capped.sol";
|
||||
import "./MinterRoleMock.sol";
|
||||
|
||||
|
||||
contract ERC20CappedMock is ERC20Capped, MinterRoleMock {
|
||||
|
||||
constructor(uint256 cap) public {
|
||||
ERC20Capped.initialize(cap, msg.sender);
|
||||
}
|
||||
|
||||
}
|
||||
12
contracts/mocks/ERC20DetailedMock.sol
Normal file
12
contracts/mocks/ERC20DetailedMock.sol
Normal file
@ -0,0 +1,12 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
|
||||
contract ERC20DetailedMock is ERC20, ERC20Detailed {
|
||||
constructor (string memory name, string memory symbol, uint8 decimals)
|
||||
public
|
||||
{
|
||||
ERC20Detailed.initialize(name, symbol, decimals);
|
||||
}
|
||||
}
|
||||
14
contracts/mocks/ERC20MetadataMock.sol
Normal file
14
contracts/mocks/ERC20MetadataMock.sol
Normal file
@ -0,0 +1,14 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../drafts/ERC1046/ERC20Metadata.sol";
|
||||
|
||||
contract ERC20MetadataMock is ERC20, ERC20Metadata {
|
||||
constructor (string memory tokenURI) public {
|
||||
ERC20Metadata.initialize(tokenURI);
|
||||
}
|
||||
|
||||
function setTokenURI(string memory tokenURI) public {
|
||||
_setTokenURI(tokenURI);
|
||||
}
|
||||
}
|
||||
12
contracts/mocks/ERC20MigratorMock.sol
Normal file
12
contracts/mocks/ERC20MigratorMock.sol
Normal file
@ -0,0 +1,12 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../drafts/ERC20Migrator.sol";
|
||||
|
||||
|
||||
contract ERC20MigratorMock is ERC20Migrator {
|
||||
|
||||
constructor(IERC20 legacyToken) public {
|
||||
ERC20Migrator.initialize(legacyToken);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,10 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../token/ERC20/ERC20Mintable.sol";
|
||||
import "./MinterRoleMock.sol";
|
||||
|
||||
contract ERC20MintableMock is ERC20Mintable, MinterRoleMock {
|
||||
constructor() public {
|
||||
ERC20Mintable.initialize(msg.sender);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,24 +1,26 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
|
||||
// mock class using ERC20
|
||||
contract ERC20Mock is ERC20 {
|
||||
constructor (address initialAccount, uint256 initialBalance) public {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
|
||||
constructor(address initialAccount, uint256 initialBalance) public {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
function mint(address account, uint256 amount) public {
|
||||
_mint(account, amount);
|
||||
}
|
||||
|
||||
function mint(address account, uint256 amount) public {
|
||||
_mint(account, amount);
|
||||
}
|
||||
function burn(address account, uint256 amount) public {
|
||||
_burn(account, amount);
|
||||
}
|
||||
|
||||
function burn(address account, uint256 amount) public {
|
||||
_burn(account, amount);
|
||||
}
|
||||
|
||||
function burnFrom(address account, uint256 amount) public {
|
||||
_burnFrom(account, amount);
|
||||
}
|
||||
function burnFrom(address account, uint256 amount) public {
|
||||
_burnFrom(account, amount);
|
||||
}
|
||||
|
||||
function approveInternal(address owner, address spender, uint256 value) public {
|
||||
_approve(owner, spender, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../token/ERC20/ERC20Pausable.sol";
|
||||
import "./PauserRoleMock.sol";
|
||||
|
||||
// mock class using ERC20Pausable
|
||||
contract ERC20PausableMock is ERC20Pausable, PauserRoleMock {
|
||||
|
||||
constructor(address initialAccount, uint initialBalance) public {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
|
||||
constructor (address initialAccount, uint initialBalance) public {
|
||||
ERC20Pausable.initialize(msg.sender);
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
}
|
||||
|
||||
18
contracts/mocks/ERC20SnapshotMock.sol
Normal file
18
contracts/mocks/ERC20SnapshotMock.sol
Normal file
@ -0,0 +1,18 @@
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../drafts/ERC20Snapshot.sol";
|
||||
|
||||
|
||||
contract ERC20SnapshotMock is ERC20Snapshot {
|
||||
constructor(address initialAccount, uint256 initialBalance) public {
|
||||
_mint(initialAccount, initialBalance);
|
||||
}
|
||||
|
||||
function mint(address account, uint256 amount) public {
|
||||
_mint(account, amount);
|
||||
}
|
||||
|
||||
function burn(address account, uint256 amount) public {
|
||||
_burn(account, amount);
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../drafts/ERC1046/TokenMetadata.sol";
|
||||
|
||||
contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata {
|
||||
constructor(string tokenURI) public
|
||||
ERC20WithMetadata(tokenURI)
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../token/ERC721/ERC721Full.sol";
|
||||
import "../token/ERC721/ERC721Mintable.sol";
|
||||
@ -7,26 +7,27 @@ import "../token/ERC721/ERC721Burnable.sol";
|
||||
|
||||
/**
|
||||
* @title ERC721FullMock
|
||||
* This mock just provides a public mint and burn functions for testing purposes,
|
||||
* and a public setter for metadata URI
|
||||
* This mock just provides public functions for setting metadata URI, getting all tokens of an owner,
|
||||
* checking token existence, removal of a token from an address
|
||||
*/
|
||||
contract ERC721FullMock
|
||||
is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable {
|
||||
contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable {
|
||||
constructor (string memory name, string memory symbol) public {
|
||||
ERC721.initialize();
|
||||
ERC721Metadata.initialize(name, symbol);
|
||||
ERC721Enumerable.initialize();
|
||||
ERC721Mintable.initialize(msg.sender);
|
||||
ERC721MetadataMintable.initialize(msg.sender);
|
||||
}
|
||||
|
||||
constructor(string name, string symbol) public
|
||||
ERC721Mintable()
|
||||
ERC721Full(name, symbol)
|
||||
{}
|
||||
function exists(uint256 tokenId) public view returns (bool) {
|
||||
return _exists(tokenId);
|
||||
}
|
||||
|
||||
function exists(uint256 tokenId) public view returns (bool) {
|
||||
return _exists(tokenId);
|
||||
}
|
||||
function tokensOfOwner(address owner) public view returns (uint256[] memory) {
|
||||
return _tokensOfOwner(owner);
|
||||
}
|
||||
|
||||
function setTokenURI(uint256 tokenId, string uri) public {
|
||||
_setTokenURI(tokenId, uri);
|
||||
}
|
||||
|
||||
function removeTokenFrom(address from, uint256 tokenId) public {
|
||||
_removeTokenFrom(from, tokenId);
|
||||
}
|
||||
function setTokenURI(uint256 tokenId, string memory uri) public {
|
||||
_setTokenURI(tokenId, uri);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../token/ERC721/ERC721Full.sol";
|
||||
import "../token/ERC721/ERC721Mintable.sol";
|
||||
@ -8,13 +8,12 @@ import "../token/ERC721/ERC721Burnable.sol";
|
||||
/**
|
||||
* @title ERC721MintableBurnableImpl
|
||||
*/
|
||||
contract ERC721MintableBurnableImpl
|
||||
is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable {
|
||||
|
||||
constructor()
|
||||
ERC721Mintable()
|
||||
ERC721Full("Test", "TEST")
|
||||
public
|
||||
{
|
||||
}
|
||||
contract ERC721MintableBurnableImpl is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable {
|
||||
constructor () public {
|
||||
ERC721.initialize();
|
||||
ERC721Metadata.initialize("Test", "TEST");
|
||||
ERC721Enumerable.initialize();
|
||||
ERC721Mintable.initialize(msg.sender);
|
||||
ERC721MetadataMintable.initialize(msg.sender);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.24;
|
||||
pragma solidity ^0.5.2;
|
||||
|
||||
import "../token/ERC721/ERC721.sol";
|
||||
|
||||
@ -7,11 +7,19 @@ import "../token/ERC721/ERC721.sol";
|
||||
* This mock just provides a public mint and burn functions for testing purposes
|
||||
*/
|
||||
contract ERC721Mock is ERC721 {
|
||||
function mint(address to, uint256 tokenId) public {
|
||||
_mint(to, tokenId);
|
||||
}
|
||||
constructor() public {
|
||||
ERC721.initialize();
|
||||
}
|
||||
|
||||
function burn(uint256 tokenId) public {
|
||||
_burn(ownerOf(tokenId), tokenId);
|
||||
}
|
||||
function mint(address to, uint256 tokenId) public {
|
||||
_mint(to, tokenId);
|
||||
}
|
||||
|
||||
function burn(address owner, uint256 tokenId) public {
|
||||
_burn(owner, tokenId);
|
||||
}
|
||||
|
||||
function burn(uint256 tokenId) public {
|
||||
_burn(tokenId);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user