Compare commits
153 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 77d569d8fa | |||
| 634883ce8e | |||
| de90f4458a | |||
| 8617c4b4c8 | |||
| 96432bf28e | |||
| 1a9cb0786d | |||
| fd808b3ff8 | |||
| 6a658f2ac8 | |||
| d9a8cd2bef | |||
| 79145fa53a | |||
| 3e82db2f6f | |||
| 089f14aa06 | |||
| ae02103e47 | |||
| ba83239dd8 | |||
| 4f5715bbd7 | |||
| 312a2584e8 | |||
| 6aa88e2b7d | |||
| 76abd1a41e | |||
| 35d70397b6 | |||
| a5b14f262e | |||
| 40f08a8c0b | |||
| 8c20d53789 | |||
| 576b020384 | |||
| 13eff70112 | |||
| daa301fef0 | |||
| 4b8fcbcee1 | |||
| be5ed7364b | |||
| 02f9727dd8 | |||
| 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 | |||
| 80458ebc72 | |||
| 6d415c508b | |||
| a936cbf5fb | |||
| 1ac1ac984e | |||
| 8204f6a71f | |||
| bbe804a14b | |||
| 28cf567e41 | |||
| 5bb865218f | |||
| 94692acb14 | |||
| 384dff9abe | |||
| 5bf3907862 | |||
| c8220aeea8 | |||
| 9155bfe27f | |||
| 1c5f16ae26 | |||
| d9fdffe88e | |||
| 315f426f5c | |||
| 67dac7ae99 | |||
| a07499796a | |||
| fcab9c89f2 | |||
| cbe414864f | |||
| 0231fac514 | |||
| ff0c048ad9 | |||
| 96d6103e0b | |||
| df3c113711 | |||
| f3df2dab3d | |||
| cfef58361f | |||
| d8ab8a00f2 | |||
| 2733cb4a41 | |||
| 03765e08b9 | |||
| 9be0f100c4 | |||
| a3e312d133 | |||
| 3341dd8899 | |||
| 3bd30f7382 | |||
| 844a96d0b9 | |||
| 03dfb2965c | |||
| 9f822906b8 | |||
| eb92fd1f48 | |||
| 076cb7decd | |||
| da67e435b1 | |||
| b0da0fded0 | |||
| 58a42443df | |||
| af42c39e6c | |||
| 3acc2b4216 | |||
| f7e53d90fa | |||
| 41f84f8b40 | |||
| b17de011dc | |||
| 308e5e9cc0 | |||
| 744f567f40 | |||
| b41b125c15 | |||
| fd4de77651 | |||
| ace14d3ad7 | |||
| 5c228805ad | |||
| c87433e0c2 | |||
| f3888bb0b0 | |||
| 43ebb4fc43 | |||
| f4d6f40442 | |||
| 269981ee6a | |||
| 34bc709bc2 | |||
| 6ae041bca6 | |||
| fa1dfbd113 | |||
| a6889776f4 | |||
| 1a4e5346ed | |||
| 536262f2ec | |||
| 75c0a59bb4 | |||
| 947de54cee | |||
| ae109f69cc | |||
| 5fdeaa81d5 | |||
| db2e1d2c74 | |||
| 396680b856 | |||
| 21198bf1c1 | |||
| 9b37104655 | |||
| 3e55408cb5 | |||
| 4b21fcf5af | |||
| d062352de7 | |||
| b4f87bb8fc | |||
| 225b492109 | |||
| 7825caa1fd | |||
| b79196f911 | |||
| d8cbd5554f | |||
| b644c72eb0 | |||
| 0b8296e525 | |||
| 651f6d8b57 | |||
| 13b19612d6 | |||
| c12a1c6898 |
@ -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" : [
|
"extends" : [
|
||||||
"standard",
|
"standard",
|
||||||
"plugin:promise/recommended"
|
"plugin:promise/recommended",
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"promise"
|
"mocha-no-only",
|
||||||
|
"promise",
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"browser" : true,
|
"browser" : true,
|
||||||
"node" : true,
|
"node" : true,
|
||||||
"mocha" : true,
|
"mocha" : true,
|
||||||
"jest" : true
|
"jest" : true,
|
||||||
},
|
},
|
||||||
"globals" : {
|
"globals" : {
|
||||||
"artifacts": false,
|
"artifacts": false,
|
||||||
"contract": false,
|
"contract": false,
|
||||||
"assert": false,
|
"assert": false,
|
||||||
"web3": false
|
"web3": false,
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
|
|
||||||
@ -49,6 +50,8 @@
|
|||||||
"semi": ["error", "always"],
|
"semi": ["error", "always"],
|
||||||
"space-before-function-paren": ["error", "always"],
|
"space-before-function-paren": ["error", "always"],
|
||||||
|
|
||||||
|
"mocha-no-only/mocha-no-only": ["error"],
|
||||||
|
|
||||||
"promise/always-return": "off",
|
"promise/always-return": "off",
|
||||||
"promise/avoid-new": "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 -->
|
||||||
24
.github/PULL_REQUEST_TEMPLATE.md
vendored
24
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,17 +1,21 @@
|
|||||||
<!-- 0. 🎉 Thank you for submitting a PR! -->
|
<!-- 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 #
|
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. -->
|
<!-- Include any context necessary for understanding the PR's purpose. -->
|
||||||
|
|
||||||
<!-- 3. Before submitting, please review the following checklist: -->
|
<!-- 3. Before submitting, please make sure that you have:
|
||||||
|
- reviewed the OpenZeppelin Contributor Guidelines
|
||||||
- [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](../blob/master/CONTRIBUTING.md)
|
(https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/CONTRIBUTING.md),
|
||||||
- [ ] ✅ I've added tests where applicable to test my new functionality.
|
- added tests where applicable to test new functionality,
|
||||||
- [ ] 📖 I've made sure that my contracts are well-documented.
|
- made sure that your contracts are well-documented,
|
||||||
- [ ] 🎨 I've run the JS/Solidity linters and fixed any issues (`npm run lint:fix`).
|
- run the JS/Solidity linters and fixed any issues (`npm run lint:fix`), and
|
||||||
|
- updated the changelog, if applicable.
|
||||||
|
-->
|
||||||
|
|||||||
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"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
30
.travis.yml
30
.travis.yml
@ -15,29 +15,27 @@ jobs:
|
|||||||
# --elopio - 20180531
|
# --elopio - 20180531
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- env: SOLIDITY_COVERAGE=true
|
|
||||||
- env: SOLC_NIGHTLY=true
|
- env: SOLC_NIGHTLY=true
|
||||||
include:
|
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
|
- stage: tests
|
||||||
name: "unit tests"
|
name: "Linter"
|
||||||
|
script: npm run lint
|
||||||
|
|
||||||
|
- stage: tests
|
||||||
|
name: "Unit tests"
|
||||||
script: npm run test
|
script: npm run test
|
||||||
|
|
||||||
|
# solidity-coverage fails at parsing 0.5.x code
|
||||||
|
# - stage: tests
|
||||||
|
# name: "Unit tests with coverage report"
|
||||||
|
# script: npm run test
|
||||||
|
# env: SOLIDITY_COVERAGE=true
|
||||||
|
|
||||||
- stage: tests
|
- stage: tests
|
||||||
name: "unit tests with coverage"
|
name: "Unit tests using solc nightly"
|
||||||
script: npm run test
|
|
||||||
env: SOLIDITY_COVERAGE=true
|
|
||||||
- stage: tests
|
|
||||||
name: "unit tests with solc nightly"
|
|
||||||
script: npm run test
|
script: npm run test
|
||||||
env: SOLC_NIGHTLY=true
|
env: SOLC_NIGHTLY=true
|
||||||
# solidity and javascript style tests.
|
|
||||||
- stage: tests
|
|
||||||
name: "static tests"
|
|
||||||
script: npm run lint
|
|
||||||
- stage: update docs
|
- stage: update docs
|
||||||
if: tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$
|
if: tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$
|
||||||
addons:
|
addons:
|
||||||
|
|||||||
40
CHANGELOG.md
Normal file
40
CHANGELOG.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2.2.0 (unreleased)
|
||||||
|
|
||||||
|
## 2.1.3 (2019-26-02)
|
||||||
|
* Backported `SafeERC20.safeApprove` bugfix. ([#1647](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1647))
|
||||||
|
|
||||||
|
## 2.1.2 (2019-17-01)
|
||||||
|
* 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-04-01)
|
||||||
|
* Version bump to avoid conflict in the npm registry.
|
||||||
|
|
||||||
|
## 2.1.0 (2019-04-01)
|
||||||
|
|
||||||
|
### 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))
|
||||||
@ -1,8 +1,8 @@
|
|||||||
# <img src="logo.png" alt="OpenZeppelin" width="400px">
|
# <img src="logo.png" alt="OpenZeppelin" width="400px">
|
||||||
|
|
||||||
[](https://www.npmjs.org/package/openzeppelin-solidity)
|
[](https://www.npmjs.org/package/openzeppelin-solidity)
|
||||||
[](https://travis-ci.org/OpenZeppelin/openzeppelin-solidity)
|
[](https://travis-ci.com/OpenZeppelin/openzeppelin-solidity)
|
||||||
[](https://coveralls.io/github/OpenZeppelin/openzeppelin-solidity?branch=master)
|
[](https://coveralls.io/github/OpenZeppelin/openzeppelin-solidity?branch=master)
|
||||||
|
|
||||||
**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.
|
**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.
|
||||||
|
|
||||||
|
|||||||
@ -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.
|
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
|
npm publish --tag next
|
||||||
@ -62,7 +62,7 @@ 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.
|
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
|
npm publish
|
||||||
|
|||||||
@ -1,44 +1,40 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Roles
|
* @title Roles
|
||||||
* @dev Library for managing addresses assigned to a Role.
|
* @dev Library for managing addresses assigned to a Role.
|
||||||
*/
|
*/
|
||||||
library Roles {
|
library Roles {
|
||||||
struct Role {
|
struct Role {
|
||||||
mapping (address => bool) bearer;
|
mapping (address => bool) bearer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev give an account access to this role
|
* @dev give an account access to this role
|
||||||
*/
|
*/
|
||||||
function add(Role storage role, address account) internal {
|
function add(Role storage role, address account) internal {
|
||||||
require(account != address(0));
|
require(account != address(0));
|
||||||
require(!has(role, account));
|
require(!has(role, account));
|
||||||
|
|
||||||
role.bearer[account] = true;
|
role.bearer[account] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev remove an account's access to this role
|
* @dev remove an account's access to this role
|
||||||
*/
|
*/
|
||||||
function remove(Role storage role, address account) internal {
|
function remove(Role storage role, address account) internal {
|
||||||
require(account != address(0));
|
require(account != address(0));
|
||||||
require(has(role, account));
|
require(has(role, account));
|
||||||
|
|
||||||
role.bearer[account] = false;
|
role.bearer[account] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev check if an account has this role
|
* @dev check if an account has this role
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
function has(Role storage role, address account)
|
function has(Role storage role, address account) internal view returns (bool) {
|
||||||
internal
|
require(account != address(0));
|
||||||
view
|
return role.bearer[account];
|
||||||
returns (bool)
|
}
|
||||||
{
|
|
||||||
require(account != address(0));
|
|
||||||
return role.bearer[account];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,43 +1,43 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../Roles.sol";
|
import "../Roles.sol";
|
||||||
|
|
||||||
contract CapperRole {
|
contract CapperRole {
|
||||||
using Roles for Roles.Role;
|
using Roles for Roles.Role;
|
||||||
|
|
||||||
event CapperAdded(address indexed account);
|
event CapperAdded(address indexed account);
|
||||||
event CapperRemoved(address indexed account);
|
event CapperRemoved(address indexed account);
|
||||||
|
|
||||||
Roles.Role private cappers;
|
Roles.Role private _cappers;
|
||||||
|
|
||||||
constructor() internal {
|
constructor () internal {
|
||||||
_addCapper(msg.sender);
|
_addCapper(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier onlyCapper() {
|
modifier onlyCapper() {
|
||||||
require(isCapper(msg.sender));
|
require(isCapper(msg.sender));
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCapper(address account) public view returns (bool) {
|
function isCapper(address account) public view returns (bool) {
|
||||||
return cappers.has(account);
|
return _cappers.has(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCapper(address account) public onlyCapper {
|
function addCapper(address account) public onlyCapper {
|
||||||
_addCapper(account);
|
_addCapper(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renounceCapper() public {
|
function renounceCapper() public {
|
||||||
_removeCapper(msg.sender);
|
_removeCapper(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _addCapper(address account) internal {
|
function _addCapper(address account) internal {
|
||||||
cappers.add(account);
|
_cappers.add(account);
|
||||||
emit CapperAdded(account);
|
emit CapperAdded(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _removeCapper(address account) internal {
|
function _removeCapper(address account) internal {
|
||||||
cappers.remove(account);
|
_cappers.remove(account);
|
||||||
emit CapperRemoved(account);
|
emit CapperRemoved(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,43 +1,43 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../Roles.sol";
|
import "../Roles.sol";
|
||||||
|
|
||||||
contract MinterRole {
|
contract MinterRole {
|
||||||
using Roles for Roles.Role;
|
using Roles for Roles.Role;
|
||||||
|
|
||||||
event MinterAdded(address indexed account);
|
event MinterAdded(address indexed account);
|
||||||
event MinterRemoved(address indexed account);
|
event MinterRemoved(address indexed account);
|
||||||
|
|
||||||
Roles.Role private minters;
|
Roles.Role private _minters;
|
||||||
|
|
||||||
constructor() internal {
|
constructor () internal {
|
||||||
_addMinter(msg.sender);
|
_addMinter(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier onlyMinter() {
|
modifier onlyMinter() {
|
||||||
require(isMinter(msg.sender));
|
require(isMinter(msg.sender));
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMinter(address account) public view returns (bool) {
|
function isMinter(address account) public view returns (bool) {
|
||||||
return minters.has(account);
|
return _minters.has(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMinter(address account) public onlyMinter {
|
function addMinter(address account) public onlyMinter {
|
||||||
_addMinter(account);
|
_addMinter(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renounceMinter() public {
|
function renounceMinter() public {
|
||||||
_removeMinter(msg.sender);
|
_removeMinter(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _addMinter(address account) internal {
|
function _addMinter(address account) internal {
|
||||||
minters.add(account);
|
_minters.add(account);
|
||||||
emit MinterAdded(account);
|
emit MinterAdded(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _removeMinter(address account) internal {
|
function _removeMinter(address account) internal {
|
||||||
minters.remove(account);
|
_minters.remove(account);
|
||||||
emit MinterRemoved(account);
|
emit MinterRemoved(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,43 +1,43 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../Roles.sol";
|
import "../Roles.sol";
|
||||||
|
|
||||||
contract PauserRole {
|
contract PauserRole {
|
||||||
using Roles for Roles.Role;
|
using Roles for Roles.Role;
|
||||||
|
|
||||||
event PauserAdded(address indexed account);
|
event PauserAdded(address indexed account);
|
||||||
event PauserRemoved(address indexed account);
|
event PauserRemoved(address indexed account);
|
||||||
|
|
||||||
Roles.Role private pausers;
|
Roles.Role private _pausers;
|
||||||
|
|
||||||
constructor() internal {
|
constructor () internal {
|
||||||
_addPauser(msg.sender);
|
_addPauser(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier onlyPauser() {
|
modifier onlyPauser() {
|
||||||
require(isPauser(msg.sender));
|
require(isPauser(msg.sender));
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPauser(address account) public view returns (bool) {
|
function isPauser(address account) public view returns (bool) {
|
||||||
return pausers.has(account);
|
return _pausers.has(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPauser(address account) public onlyPauser {
|
function addPauser(address account) public onlyPauser {
|
||||||
_addPauser(account);
|
_addPauser(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renouncePauser() public {
|
function renouncePauser() public {
|
||||||
_removePauser(msg.sender);
|
_removePauser(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _addPauser(address account) internal {
|
function _addPauser(address account) internal {
|
||||||
pausers.add(account);
|
_pausers.add(account);
|
||||||
emit PauserAdded(account);
|
emit PauserAdded(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _removePauser(address account) internal {
|
function _removePauser(address account) internal {
|
||||||
pausers.remove(account);
|
_pausers.remove(account);
|
||||||
emit PauserRemoved(account);
|
emit PauserRemoved(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,43 +1,43 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../Roles.sol";
|
import "../Roles.sol";
|
||||||
|
|
||||||
contract SignerRole {
|
contract SignerRole {
|
||||||
using Roles for Roles.Role;
|
using Roles for Roles.Role;
|
||||||
|
|
||||||
event SignerAdded(address indexed account);
|
event SignerAdded(address indexed account);
|
||||||
event SignerRemoved(address indexed account);
|
event SignerRemoved(address indexed account);
|
||||||
|
|
||||||
Roles.Role private signers;
|
Roles.Role private _signers;
|
||||||
|
|
||||||
constructor() internal {
|
constructor () internal {
|
||||||
_addSigner(msg.sender);
|
_addSigner(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier onlySigner() {
|
modifier onlySigner() {
|
||||||
require(isSigner(msg.sender));
|
require(isSigner(msg.sender));
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSigner(address account) public view returns (bool) {
|
function isSigner(address account) public view returns (bool) {
|
||||||
return signers.has(account);
|
return _signers.has(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSigner(address account) public onlySigner {
|
function addSigner(address account) public onlySigner {
|
||||||
_addSigner(account);
|
_addSigner(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renounceSigner() public {
|
function renounceSigner() public {
|
||||||
_removeSigner(msg.sender);
|
_removeSigner(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _addSigner(address account) internal {
|
function _addSigner(address account) internal {
|
||||||
signers.add(account);
|
_signers.add(account);
|
||||||
emit SignerAdded(account);
|
emit SignerAdded(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _removeSigner(address account) internal {
|
function _removeSigner(address account) internal {
|
||||||
signers.remove(account);
|
_signers.remove(account);
|
||||||
emit SignerRemoved(account);
|
emit SignerRemoved(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
contracts/access/roles/WhitelistAdminRole.sol
Normal file
47
contracts/access/roles/WhitelistAdminRole.sol
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
import "../Roles.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title WhitelistAdminRole
|
||||||
|
* @dev WhitelistAdmins are responsible for assigning and removing Whitelisted accounts.
|
||||||
|
*/
|
||||||
|
contract WhitelistAdminRole {
|
||||||
|
using Roles for Roles.Role;
|
||||||
|
|
||||||
|
event WhitelistAdminAdded(address indexed account);
|
||||||
|
event WhitelistAdminRemoved(address indexed account);
|
||||||
|
|
||||||
|
Roles.Role private _whitelistAdmins;
|
||||||
|
|
||||||
|
constructor () internal {
|
||||||
|
_addWhitelistAdmin(msg.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
50
contracts/access/roles/WhitelistedRole.sol
Normal file
50
contracts/access/roles/WhitelistedRole.sol
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
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 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 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/IERC20.sol";
|
import "../token/ERC20/IERC20.sol";
|
||||||
import "../math/SafeMath.sol";
|
import "../math/SafeMath.sol";
|
||||||
@ -18,224 +18,181 @@ import "../utils/ReentrancyGuard.sol";
|
|||||||
* behavior.
|
* behavior.
|
||||||
*/
|
*/
|
||||||
contract Crowdsale is ReentrancyGuard {
|
contract Crowdsale is ReentrancyGuard {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
// The token being sold
|
// The token being sold
|
||||||
IERC20 private _token;
|
IERC20 private _token;
|
||||||
|
|
||||||
// Address where funds are collected
|
// Address where funds are collected
|
||||||
address private _wallet;
|
address payable private _wallet;
|
||||||
|
|
||||||
// How many token units a buyer gets per wei.
|
// How many token units a buyer gets per wei.
|
||||||
// The rate is the conversion between wei and the smallest and indivisible token unit.
|
// 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
|
// 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.
|
// 1 wei will give you 1 unit, or 0.001 TOK.
|
||||||
uint256 private _rate;
|
uint256 private _rate;
|
||||||
|
|
||||||
// Amount of wei raised
|
// Amount of wei raised
|
||||||
uint256 private _weiRaised;
|
uint256 private _weiRaised;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event for token purchase logging
|
* Event for token purchase logging
|
||||||
* @param purchaser who paid for the tokens
|
* @param purchaser who paid for the tokens
|
||||||
* @param beneficiary who got the tokens
|
* @param beneficiary who got the tokens
|
||||||
* @param value weis paid for purchase
|
* @param value weis paid for purchase
|
||||||
* @param amount amount of tokens purchased
|
* @param amount amount of tokens purchased
|
||||||
*/
|
*/
|
||||||
event TokensPurchased(
|
event TokensPurchased(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
|
||||||
address indexed purchaser,
|
|
||||||
address indexed beneficiary,
|
|
||||||
uint256 value,
|
|
||||||
uint256 amount
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param rate Number of token units a buyer gets per wei
|
* @param rate Number of token units a buyer gets per wei
|
||||||
* @dev The rate is the conversion between wei and the smallest and indivisible
|
* @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
|
* 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.
|
* 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 wallet Address where collected funds will be forwarded to
|
||||||
* @param token Address of the token being sold
|
* @param token Address of the token being sold
|
||||||
*/
|
*/
|
||||||
constructor(uint256 rate, address wallet, IERC20 token) internal {
|
constructor (uint256 rate, address payable wallet, IERC20 token) public {
|
||||||
require(rate > 0);
|
require(rate > 0);
|
||||||
require(wallet != address(0));
|
require(wallet != address(0));
|
||||||
require(token != address(0));
|
require(address(token) != address(0));
|
||||||
|
|
||||||
_rate = rate;
|
_rate = rate;
|
||||||
_wallet = wallet;
|
_wallet = wallet;
|
||||||
_token = token;
|
_token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
/**
|
||||||
// Crowdsale external interface
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev fallback function ***DO NOT OVERRIDE***
|
* @return the token being sold.
|
||||||
* Note that other contracts will transfer fund with a base gas stipend
|
*/
|
||||||
* of 2300, which is not enough to call buyTokens. Consider calling
|
function token() public view returns (IERC20) {
|
||||||
* buyTokens directly when purchasing tokens from a contract.
|
return _token;
|
||||||
*/
|
}
|
||||||
function () external payable {
|
|
||||||
buyTokens(msg.sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the token being sold.
|
* @return the address where funds are collected.
|
||||||
*/
|
*/
|
||||||
function token() public view returns(IERC20) {
|
function wallet() public view returns (address payable) {
|
||||||
return _token;
|
return _wallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the address where funds are collected.
|
* @return the number of token units a buyer gets per wei.
|
||||||
*/
|
*/
|
||||||
function wallet() public view returns(address) {
|
function rate() public view returns (uint256) {
|
||||||
return _wallet;
|
return _rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the number of token units a buyer gets per wei.
|
* @return the amount of wei raised.
|
||||||
*/
|
*/
|
||||||
function rate() public view returns(uint256) {
|
function weiRaised() public view returns (uint256) {
|
||||||
return _rate;
|
return _weiRaised;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the amount of wei raised.
|
* @dev low level token purchase ***DO NOT OVERRIDE***
|
||||||
*/
|
* This function has a non-reentrancy guard, so it shouldn't be called by
|
||||||
function weiRaised() public view returns (uint256) {
|
* another `nonReentrant` function.
|
||||||
return _weiRaised;
|
* @param beneficiary Recipient of the token purchase
|
||||||
}
|
*/
|
||||||
|
function buyTokens(address beneficiary) public nonReentrant payable {
|
||||||
|
uint256 weiAmount = msg.value;
|
||||||
|
_preValidatePurchase(beneficiary, weiAmount);
|
||||||
|
|
||||||
/**
|
// calculate token amount to be created
|
||||||
* @dev low level token purchase ***DO NOT OVERRIDE***
|
uint256 tokens = _getTokenAmount(weiAmount);
|
||||||
* 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;
|
// update state
|
||||||
_preValidatePurchase(beneficiary, weiAmount);
|
_weiRaised = _weiRaised.add(weiAmount);
|
||||||
|
|
||||||
// calculate token amount to be created
|
_processPurchase(beneficiary, tokens);
|
||||||
uint256 tokens = _getTokenAmount(weiAmount);
|
emit TokensPurchased(msg.sender, beneficiary, weiAmount, tokens);
|
||||||
|
|
||||||
// update state
|
_updatePurchasingState(beneficiary, weiAmount);
|
||||||
_weiRaised = _weiRaised.add(weiAmount);
|
|
||||||
|
|
||||||
_processPurchase(beneficiary, tokens);
|
_forwardFunds();
|
||||||
emit TokensPurchased(
|
_postValidatePurchase(beneficiary, weiAmount);
|
||||||
msg.sender,
|
}
|
||||||
beneficiary,
|
|
||||||
weiAmount,
|
|
||||||
tokens
|
|
||||||
);
|
|
||||||
|
|
||||||
_updatePurchasingState(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);
|
||||||
|
}
|
||||||
|
|
||||||
_forwardFunds();
|
/**
|
||||||
_postValidatePurchase(beneficiary, weiAmount);
|
* @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
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
/**
|
||||||
// Internal interface (extensible)
|
* @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 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.
|
* @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send
|
||||||
* Example from CappedCrowdsale.sol's _preValidatePurchase method:
|
* tokens.
|
||||||
* super._preValidatePurchase(beneficiary, weiAmount);
|
* @param beneficiary Address receiving the tokens
|
||||||
* require(weiRaised().add(weiAmount) <= cap);
|
* @param tokenAmount Number of tokens to be purchased
|
||||||
* @param beneficiary Address performing the token purchase
|
*/
|
||||||
* @param weiAmount Value in wei involved in the purchase
|
function _processPurchase(address beneficiary, uint256 tokenAmount) internal {
|
||||||
*/
|
_deliverTokens(beneficiary, tokenAmount);
|
||||||
function _preValidatePurchase(
|
}
|
||||||
address beneficiary,
|
|
||||||
uint256 weiAmount
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
{
|
|
||||||
require(beneficiary != address(0));
|
|
||||||
require(weiAmount != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met.
|
* @dev Override for extensions that require an internal state to check for validity (current user contributions,
|
||||||
* @param beneficiary Address performing the token purchase
|
* etc.)
|
||||||
* @param weiAmount Value in wei involved in the purchase
|
* @param beneficiary Address receiving the tokens
|
||||||
*/
|
* @param weiAmount Value in wei involved in the purchase
|
||||||
function _postValidatePurchase(
|
*/
|
||||||
address beneficiary,
|
function _updatePurchasingState(address beneficiary, uint256 weiAmount) internal {
|
||||||
uint256 weiAmount
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
)
|
}
|
||||||
internal
|
|
||||||
view
|
|
||||||
{
|
|
||||||
// optional override
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
|
* @dev Override to extend the way in which ether is converted to tokens.
|
||||||
* @param beneficiary Address performing the token purchase
|
* @param weiAmount Value in wei to be converted into tokens
|
||||||
* @param tokenAmount Number of tokens to be emitted
|
* @return Number of tokens that can be purchased with the specified _weiAmount
|
||||||
*/
|
*/
|
||||||
function _deliverTokens(
|
function _getTokenAmount(uint256 weiAmount) internal view returns (uint256) {
|
||||||
address beneficiary,
|
return weiAmount.mul(_rate);
|
||||||
uint256 tokenAmount
|
}
|
||||||
)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
_token.safeTransfer(beneficiary, tokenAmount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send tokens.
|
* @dev Determines how ETH is stored/forwarded on purchases.
|
||||||
* @param beneficiary Address receiving the tokens
|
*/
|
||||||
* @param tokenAmount Number of tokens to be purchased
|
function _forwardFunds() internal {
|
||||||
*/
|
_wallet.transfer(msg.value);
|
||||||
function _processPurchase(
|
}
|
||||||
address beneficiary,
|
|
||||||
uint256 tokenAmount
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
_deliverTokens(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
|
|
||||||
{
|
|
||||||
// optional override
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../../math/SafeMath.sol";
|
import "../../math/SafeMath.sol";
|
||||||
import "../validation/TimedCrowdsale.sol";
|
import "../validation/TimedCrowdsale.sol";
|
||||||
@ -9,42 +9,43 @@ import "../validation/TimedCrowdsale.sol";
|
|||||||
* can do extra work after finishing.
|
* can do extra work after finishing.
|
||||||
*/
|
*/
|
||||||
contract FinalizableCrowdsale is TimedCrowdsale {
|
contract FinalizableCrowdsale is TimedCrowdsale {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
|
|
||||||
bool private _finalized;
|
bool private _finalized;
|
||||||
|
|
||||||
event CrowdsaleFinalized();
|
event CrowdsaleFinalized();
|
||||||
|
|
||||||
constructor() internal {
|
constructor () internal {
|
||||||
_finalized = false;
|
_finalized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the crowdsale is finalized, false otherwise.
|
* @return true if the crowdsale is finalized, false otherwise.
|
||||||
*/
|
*/
|
||||||
function finalized() public view returns (bool) {
|
function finalized() public view returns (bool) {
|
||||||
return _finalized;
|
return _finalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Must be called after crowdsale ends, to do some extra finalization
|
* @dev Must be called after crowdsale ends, to do some extra finalization
|
||||||
* work. Calls the contract's finalization function.
|
* work. Calls the contract's finalization function.
|
||||||
*/
|
*/
|
||||||
function finalize() public {
|
function finalize() public {
|
||||||
require(!_finalized);
|
require(!_finalized);
|
||||||
require(hasClosed());
|
require(hasClosed());
|
||||||
|
|
||||||
_finalized = true;
|
_finalized = true;
|
||||||
|
|
||||||
_finalization();
|
_finalization();
|
||||||
emit CrowdsaleFinalized();
|
emit CrowdsaleFinalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Can be overridden to add finalization logic. The overriding function
|
* @dev Can be overridden to add finalization logic. The overriding function
|
||||||
* should call super._finalization() to ensure the chain of finalization is
|
* should call super._finalization() to ensure the chain of finalization is
|
||||||
* executed entirely.
|
* executed entirely.
|
||||||
*/
|
*/
|
||||||
function _finalization() internal {
|
function _finalization() internal {
|
||||||
}
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../validation/TimedCrowdsale.sol";
|
import "../validation/TimedCrowdsale.sol";
|
||||||
import "../../math/SafeMath.sol";
|
import "../../math/SafeMath.sol";
|
||||||
@ -8,43 +8,36 @@ import "../../math/SafeMath.sol";
|
|||||||
* @dev Crowdsale that locks tokens from withdrawal until it ends.
|
* @dev Crowdsale that locks tokens from withdrawal until it ends.
|
||||||
*/
|
*/
|
||||||
contract PostDeliveryCrowdsale is TimedCrowdsale {
|
contract PostDeliveryCrowdsale is TimedCrowdsale {
|
||||||
using SafeMath for uint256;
|
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.
|
* @return the balance of an account.
|
||||||
* @param beneficiary Whose tokens will be withdrawn.
|
*/
|
||||||
*/
|
function balanceOf(address account) public view returns (uint256) {
|
||||||
function withdrawTokens(address beneficiary) public {
|
return _balances[account];
|
||||||
require(hasClosed());
|
}
|
||||||
uint256 amount = _balances[beneficiary];
|
|
||||||
require(amount > 0);
|
|
||||||
_balances[beneficiary] = 0;
|
|
||||||
_deliverTokens(beneficiary, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the balance of an account.
|
* @dev Overrides parent by storing balances instead of issuing tokens right away.
|
||||||
*/
|
* @param beneficiary Token purchaser
|
||||||
function balanceOf(address account) public view returns(uint256) {
|
* @param tokenAmount Amount of tokens purchased
|
||||||
return _balances[account];
|
*/
|
||||||
}
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../../math/SafeMath.sol";
|
import "../../math/SafeMath.sol";
|
||||||
import "./FinalizableCrowdsale.sol";
|
import "./FinalizableCrowdsale.sol";
|
||||||
@ -6,86 +6,77 @@ import "../../payment/escrow/RefundEscrow.sol";
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @title RefundableCrowdsale
|
* @title RefundableCrowdsale
|
||||||
* @dev Extension of Crowdsale contract that adds a funding goal, and
|
* @dev Extension of Crowdsale contract that adds a funding goal, and the possibility of users getting a refund if goal
|
||||||
* the possibility of users getting a refund if goal is not met.
|
* 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
|
* Deprecated, use RefundablePostDeliveryCrowdsale instead. Note that if you allow tokens to be traded before the goal
|
||||||
* tokens from the crowdsale and when they sees that the goal is
|
* is met, then an attack is possible in which the attacker purchases tokens from the crowdsale and when they sees that
|
||||||
* unlikely to be met, they sell their tokens (possibly at a discount).
|
* the goal is unlikely to be met, they sell their tokens (possibly at a discount). The attacker will be refunded when
|
||||||
* The attacker will be refunded when the crowdsale is finalized, and
|
* the crowdsale is finalized, and the users that purchased from them will be left with worthless tokens.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
contract RefundableCrowdsale is FinalizableCrowdsale {
|
contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
|
|
||||||
// minimum amount of funds to be raised in weis
|
// minimum amount of funds to be raised in weis
|
||||||
uint256 private _goal;
|
uint256 private _goal;
|
||||||
|
|
||||||
// refund escrow used to hold funds while crowdsale is running
|
// refund escrow used to hold funds while crowdsale is running
|
||||||
RefundEscrow private _escrow;
|
RefundEscrow private _escrow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Constructor, creates RefundEscrow.
|
* @dev Constructor, creates RefundEscrow.
|
||||||
* @param goal Funding goal
|
* @param goal Funding goal
|
||||||
*/
|
*/
|
||||||
constructor(uint256 goal) internal {
|
constructor (uint256 goal) public {
|
||||||
require(goal > 0);
|
require(goal > 0);
|
||||||
_escrow = new RefundEscrow(wallet());
|
_escrow = new RefundEscrow(wallet());
|
||||||
_goal = goal;
|
_goal = goal;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
* @dev Investors can claim refunds here if crowdsale is unsuccessful
|
||||||
*/
|
* @param refundee Whose refund will be claimed.
|
||||||
function _forwardFunds() internal {
|
*/
|
||||||
_escrow.deposit.value(msg.value)(msg.sender);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
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 RefundableCrowdsale, PostDeliveryCrowdsale {
|
||||||
|
function withdrawTokens(address beneficiary) public {
|
||||||
|
require(finalized());
|
||||||
|
require(goalReached());
|
||||||
|
|
||||||
|
super.withdrawTokens(beneficiary);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../Crowdsale.sol";
|
import "../Crowdsale.sol";
|
||||||
import "../../token/ERC20/IERC20.sol";
|
import "../../token/ERC20/IERC20.sol";
|
||||||
@ -11,49 +11,41 @@ import "../../math/Math.sol";
|
|||||||
* @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale.
|
* @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale.
|
||||||
*/
|
*/
|
||||||
contract AllowanceCrowdsale is Crowdsale {
|
contract AllowanceCrowdsale is Crowdsale {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
address private _tokenWallet;
|
address private _tokenWallet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Constructor, takes token wallet address.
|
* @dev Constructor, takes token wallet address.
|
||||||
* @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale
|
* @param tokenWallet Address holding the tokens, which has approved allowance to the crowdsale
|
||||||
*/
|
*/
|
||||||
constructor(address tokenWallet) internal {
|
constructor (address tokenWallet) public {
|
||||||
require(tokenWallet != address(0));
|
require(tokenWallet != address(0));
|
||||||
_tokenWallet = tokenWallet;
|
_tokenWallet = tokenWallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the address of the wallet that will hold the tokens.
|
* @return the address of the wallet that will hold the tokens.
|
||||||
*/
|
*/
|
||||||
function tokenWallet() public view returns(address) {
|
function tokenWallet() public view returns (address) {
|
||||||
return _tokenWallet;
|
return _tokenWallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Checks the amount of tokens left in the allowance.
|
* @dev Checks the amount of tokens left in the allowance.
|
||||||
* @return Amount of tokens left in the allowance
|
* @return Amount of tokens left in the allowance
|
||||||
*/
|
*/
|
||||||
function remainingTokens() public view returns (uint256) {
|
function remainingTokens() public view returns (uint256) {
|
||||||
return Math.min(
|
return Math.min(token().balanceOf(_tokenWallet), token().allowance(_tokenWallet, address(this)));
|
||||||
token().balanceOf(_tokenWallet),
|
}
|
||||||
token().allowance(_tokenWallet, this)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Overrides parent behavior by transferring tokens from wallet.
|
* @dev Overrides parent behavior by transferring tokens from wallet.
|
||||||
* @param beneficiary Token purchaser
|
* @param beneficiary Token purchaser
|
||||||
* @param tokenAmount Amount of tokens purchased
|
* @param tokenAmount Amount of tokens purchased
|
||||||
*/
|
*/
|
||||||
function _deliverTokens(
|
function _deliverTokens(address beneficiary, uint256 tokenAmount) internal {
|
||||||
address beneficiary,
|
token().safeTransferFrom(_tokenWallet, beneficiary, tokenAmount);
|
||||||
uint256 tokenAmount
|
}
|
||||||
)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
token().safeTransferFrom(_tokenWallet, beneficiary, tokenAmount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../Crowdsale.sol";
|
import "../Crowdsale.sol";
|
||||||
import "../../token/ERC20/ERC20Mintable.sol";
|
import "../../token/ERC20/ERC20Mintable.sol";
|
||||||
@ -9,21 +9,13 @@ import "../../token/ERC20/ERC20Mintable.sol";
|
|||||||
* Token ownership should be transferred to MintedCrowdsale for minting.
|
* Token ownership should be transferred to MintedCrowdsale for minting.
|
||||||
*/
|
*/
|
||||||
contract MintedCrowdsale is Crowdsale {
|
contract MintedCrowdsale is Crowdsale {
|
||||||
constructor() internal {}
|
/**
|
||||||
|
* @dev Overrides delivery by minting tokens upon purchase.
|
||||||
/**
|
* @param beneficiary Token purchaser
|
||||||
* @dev Overrides delivery by minting tokens upon purchase.
|
* @param tokenAmount Number of tokens to be minted
|
||||||
* @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.
|
||||||
function _deliverTokens(
|
require(ERC20Mintable(address(token())).mint(beneficiary, tokenAmount));
|
||||||
address beneficiary,
|
}
|
||||||
uint256 tokenAmount
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
// Potentially dangerous assumption about the type of the token.
|
|
||||||
require(
|
|
||||||
ERC20Mintable(address(token())).mint(beneficiary, tokenAmount));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../validation/TimedCrowdsale.sol";
|
import "../validation/TimedCrowdsale.sol";
|
||||||
import "../../math/SafeMath.sol";
|
import "../../math/SafeMath.sol";
|
||||||
@ -10,72 +10,69 @@ import "../../math/SafeMath.sol";
|
|||||||
* the amount of tokens per wei contributed. Thus, the initial rate must be greater than the final rate.
|
* the amount of tokens per wei contributed. Thus, the initial rate must be greater than the final rate.
|
||||||
*/
|
*/
|
||||||
contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
|
|
||||||
uint256 private _initialRate;
|
uint256 private _initialRate;
|
||||||
uint256 private _finalRate;
|
uint256 private _finalRate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Constructor, takes initial and final rates of tokens received per wei contributed.
|
* @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 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
|
* @param finalRate Number of tokens a buyer gets per wei at the end of the crowdsale
|
||||||
*/
|
*/
|
||||||
constructor(uint256 initialRate, uint256 finalRate) internal {
|
constructor (uint256 initialRate, uint256 finalRate) public {
|
||||||
require(finalRate > 0);
|
require(finalRate > 0);
|
||||||
require(initialRate > finalRate);
|
require(initialRate > finalRate);
|
||||||
_initialRate = initialRate;
|
_initialRate = initialRate;
|
||||||
_finalRate = finalRate;
|
_finalRate = finalRate;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// solium-disable-next-line security/no-block-members
|
/**
|
||||||
uint256 elapsedTime = block.timestamp.sub(openingTime());
|
* The base rate function is overridden to revert, since this crowdsale doens't use it, and
|
||||||
uint256 timeRange = closingTime().sub(openingTime());
|
* all calls to it are a mistake.
|
||||||
uint256 rateRange = _initialRate.sub(_finalRate);
|
*/
|
||||||
return _initialRate.sub(elapsedTime.mul(rateRange).div(timeRange));
|
function rate() public view returns (uint256) {
|
||||||
}
|
revert();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Overrides parent method taking into account variable rate.
|
* @return the initial rate of the crowdsale.
|
||||||
* @param weiAmount The value in wei to be converted into tokens
|
*/
|
||||||
* @return The number of tokens _weiAmount wei will buy at present time
|
function initialRate() public view returns (uint256) {
|
||||||
*/
|
return _initialRate;
|
||||||
function _getTokenAmount(uint256 weiAmount)
|
}
|
||||||
internal view returns (uint256)
|
|
||||||
{
|
|
||||||
uint256 currentRate = getCurrentRate();
|
|
||||||
return currentRate.mul(weiAmount);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../../math/SafeMath.sol";
|
import "../../math/SafeMath.sol";
|
||||||
import "../Crowdsale.sol";
|
import "../Crowdsale.sol";
|
||||||
@ -8,48 +8,41 @@ import "../Crowdsale.sol";
|
|||||||
* @dev Crowdsale with a limit for total contributions.
|
* @dev Crowdsale with a limit for total contributions.
|
||||||
*/
|
*/
|
||||||
contract CappedCrowdsale is Crowdsale {
|
contract CappedCrowdsale is Crowdsale {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
|
|
||||||
uint256 private _cap;
|
uint256 private _cap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Constructor, takes maximum amount of wei accepted in the crowdsale.
|
* @dev Constructor, takes maximum amount of wei accepted in the crowdsale.
|
||||||
* @param cap Max amount of wei to be contributed
|
* @param cap Max amount of wei to be contributed
|
||||||
*/
|
*/
|
||||||
constructor(uint256 cap) internal {
|
constructor (uint256 cap) public {
|
||||||
require(cap > 0);
|
require(cap > 0);
|
||||||
_cap = cap;
|
_cap = cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the cap of the crowdsale.
|
* @return the cap of the crowdsale.
|
||||||
*/
|
*/
|
||||||
function cap() public view returns(uint256) {
|
function cap() public view returns (uint256) {
|
||||||
return _cap;
|
return _cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Checks whether the cap has been reached.
|
* @dev Checks whether the cap has been reached.
|
||||||
* @return Whether the cap was reached
|
* @return Whether the cap was reached
|
||||||
*/
|
*/
|
||||||
function capReached() public view returns (bool) {
|
function capReached() public view returns (bool) {
|
||||||
return weiRaised() >= _cap;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../../math/SafeMath.sol";
|
import "../../math/SafeMath.sol";
|
||||||
import "../Crowdsale.sol";
|
import "../Crowdsale.sol";
|
||||||
@ -9,73 +9,55 @@ import "../../access/roles/CapperRole.sol";
|
|||||||
* @dev Crowdsale with per-beneficiary caps.
|
* @dev Crowdsale with per-beneficiary caps.
|
||||||
*/
|
*/
|
||||||
contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole {
|
contract IndividuallyCappedCrowdsale is Crowdsale, CapperRole {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
|
|
||||||
mapping(address => uint256) private _contributions;
|
mapping(address => uint256) private _contributions;
|
||||||
mapping(address => uint256) private _caps;
|
mapping(address => uint256) private _caps;
|
||||||
|
|
||||||
constructor() internal {}
|
/**
|
||||||
|
* @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 Sets a specific beneficiary's maximum contribution.
|
* @dev Returns the cap of a specific beneficiary.
|
||||||
* @param beneficiary Address to be capped
|
* @param beneficiary Address whose cap is to be checked
|
||||||
* @param cap Wei limit for individual contribution
|
* @return Current cap for individual beneficiary
|
||||||
*/
|
*/
|
||||||
function setCap(address beneficiary, uint256 cap) external onlyCapper {
|
function getCap(address beneficiary) public view returns (uint256) {
|
||||||
_caps[beneficiary] = cap;
|
return _caps[beneficiary];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Returns the cap of a specific beneficiary.
|
* @dev Returns the amount contributed so far by a specific beneficiary.
|
||||||
* @param beneficiary Address whose cap is to be checked
|
* @param beneficiary Address of contributor
|
||||||
* @return Current cap for individual beneficiary
|
* @return Beneficiary contribution so far
|
||||||
*/
|
*/
|
||||||
function getCap(address beneficiary) public view returns (uint256) {
|
function getContribution(address beneficiary) public view returns (uint256) {
|
||||||
return _caps[beneficiary];
|
return _contributions[beneficiary];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Returns the amount contributed so far by a specific beneficiary.
|
* @dev Extend parent behavior requiring purchase to respect the beneficiary's funding cap.
|
||||||
* @param beneficiary Address of contributor
|
* @param beneficiary Token purchaser
|
||||||
* @return Beneficiary contribution so far
|
* @param weiAmount Amount of wei contributed
|
||||||
*/
|
*/
|
||||||
function getContribution(address beneficiary)
|
function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
|
||||||
public view returns (uint256)
|
super._preValidatePurchase(beneficiary, weiAmount);
|
||||||
{
|
require(_contributions[beneficiary].add(weiAmount) <= _caps[beneficiary]);
|
||||||
return _contributions[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 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 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
contracts/crowdsale/validation/PausableCrowdsale.sol
Normal file
21
contracts/crowdsale/validation/PausableCrowdsale.sol
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
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 Crowdsale, Pausable {
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../../math/SafeMath.sol";
|
import "../../math/SafeMath.sol";
|
||||||
import "../Crowdsale.sol";
|
import "../Crowdsale.sol";
|
||||||
@ -8,78 +8,70 @@ import "../Crowdsale.sol";
|
|||||||
* @dev Crowdsale accepting contributions only within a time frame.
|
* @dev Crowdsale accepting contributions only within a time frame.
|
||||||
*/
|
*/
|
||||||
contract TimedCrowdsale is Crowdsale {
|
contract TimedCrowdsale is Crowdsale {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
|
|
||||||
uint256 private _openingTime;
|
uint256 private _openingTime;
|
||||||
uint256 private _closingTime;
|
uint256 private _closingTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Reverts if not in crowdsale time range.
|
* @dev Reverts if not in crowdsale time range.
|
||||||
*/
|
*/
|
||||||
modifier onlyWhileOpen {
|
modifier onlyWhileOpen {
|
||||||
require(isOpen());
|
require(isOpen());
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Constructor, takes crowdsale opening and closing times.
|
* @dev Constructor, takes crowdsale opening and closing times.
|
||||||
* @param openingTime Crowdsale opening time
|
* @param openingTime Crowdsale opening time
|
||||||
* @param closingTime Crowdsale closing time
|
* @param closingTime Crowdsale closing time
|
||||||
*/
|
*/
|
||||||
constructor(uint256 openingTime, uint256 closingTime) internal {
|
constructor (uint256 openingTime, uint256 closingTime) public {
|
||||||
// solium-disable-next-line security/no-block-members
|
// solhint-disable-next-line not-rely-on-time
|
||||||
require(openingTime >= block.timestamp);
|
require(openingTime >= block.timestamp);
|
||||||
require(closingTime > openingTime);
|
require(closingTime > openingTime);
|
||||||
|
|
||||||
_openingTime = openingTime;
|
_openingTime = openingTime;
|
||||||
_closingTime = closingTime;
|
_closingTime = closingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the crowdsale opening time.
|
* @return the crowdsale opening time.
|
||||||
*/
|
*/
|
||||||
function openingTime() public view returns(uint256) {
|
function openingTime() public view returns (uint256) {
|
||||||
return _openingTime;
|
return _openingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the crowdsale closing time.
|
* @return the crowdsale closing time.
|
||||||
*/
|
*/
|
||||||
function closingTime() public view returns(uint256) {
|
function closingTime() public view returns (uint256) {
|
||||||
return _closingTime;
|
return _closingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the crowdsale is open, false otherwise.
|
* @return true if the crowdsale is open, false otherwise.
|
||||||
*/
|
*/
|
||||||
function isOpen() public view returns (bool) {
|
function isOpen() public view returns (bool) {
|
||||||
// solium-disable-next-line security/no-block-members
|
// solhint-disable-next-line not-rely-on-time
|
||||||
return block.timestamp >= _openingTime && block.timestamp <= _closingTime;
|
return block.timestamp >= _openingTime && block.timestamp <= _closingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Checks whether the period in which the crowdsale is open has already elapsed.
|
* @dev Checks whether the period in which the crowdsale is open has already elapsed.
|
||||||
* @return Whether crowdsale period has elapsed
|
* @return Whether crowdsale period has elapsed
|
||||||
*/
|
*/
|
||||||
function hasClosed() public view returns (bool) {
|
function hasClosed() public view returns (bool) {
|
||||||
// solium-disable-next-line security/no-block-members
|
// solhint-disable-next-line not-rely-on-time
|
||||||
return block.timestamp > _closingTime;
|
return block.timestamp > _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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
contracts/crowdsale/validation/WhitelistCrowdsale.sol
Normal file
21
contracts/crowdsale/validation/WhitelistCrowdsale.sol
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
import "../Crowdsale.sol";
|
||||||
|
import "../../access/roles/WhitelistedRole.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title WhitelistCrowdsale
|
||||||
|
* @dev Crowdsale in which only whitelisted users can contribute.
|
||||||
|
*/
|
||||||
|
contract WhitelistCrowdsale is WhitelistedRole, Crowdsale {
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Elliptic curve signature operations
|
* @title Elliptic curve signature operations
|
||||||
@ -8,64 +8,52 @@ pragma solidity ^0.4.24;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
library ECDSA {
|
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) {
|
||||||
|
bytes32 r;
|
||||||
|
bytes32 s;
|
||||||
|
uint8 v;
|
||||||
|
|
||||||
/**
|
// Check the signature length
|
||||||
* @dev Recover signer address from a message by using their signature
|
if (signature.length != 65) {
|
||||||
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
|
return (address(0));
|
||||||
* @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;
|
|
||||||
|
|
||||||
// Check the signature length
|
// Divide the signature in r, s and v variables
|
||||||
if (signature.length != 65) {
|
// ecrecover takes the signature parameters, and the only way to get them
|
||||||
return (address(0));
|
// 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)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
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
|
* toEthSignedMessageHash
|
||||||
// currently is to use assembly.
|
* @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
|
||||||
// solium-disable-next-line security/no-inline-assembly
|
* and hash the result
|
||||||
assembly {
|
*/
|
||||||
r := mload(add(signature, 0x20))
|
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
|
||||||
s := mload(add(signature, 0x40))
|
// 32 is the length in bytes of hash,
|
||||||
v := byte(0, mload(add(signature, 0x60)))
|
// 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.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title MerkleProof
|
* @title MerkleProof
|
||||||
@ -6,37 +6,29 @@ pragma solidity ^0.4.24;
|
|||||||
* https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
|
* https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
|
||||||
*/
|
*/
|
||||||
library MerkleProof {
|
library MerkleProof {
|
||||||
/**
|
/**
|
||||||
* @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
|
* @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.
|
* 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 proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree
|
||||||
* @param root Merkle root
|
* @param root Merkle root
|
||||||
* @param leaf Leaf of Merkle tree
|
* @param leaf Leaf of Merkle tree
|
||||||
*/
|
*/
|
||||||
function verify(
|
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
|
||||||
bytes32[] proof,
|
bytes32 computedHash = leaf;
|
||||||
bytes32 root,
|
|
||||||
bytes32 leaf
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
bytes32 computedHash = leaf;
|
|
||||||
|
|
||||||
for (uint256 i = 0; i < proof.length; i++) {
|
for (uint256 i = 0; i < proof.length; i++) {
|
||||||
bytes32 proofElement = proof[i];
|
bytes32 proofElement = proof[i];
|
||||||
|
|
||||||
if (computedHash < proofElement) {
|
if (computedHash < proofElement) {
|
||||||
// Hash(current computed hash + current element of the proof)
|
// Hash(current computed hash + current element of the proof)
|
||||||
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
|
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
|
||||||
} else {
|
} else {
|
||||||
// Hash(current element of the proof + current computed hash)
|
// Hash(current element of the proof + current computed hash)
|
||||||
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
|
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,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Counter
|
* @title Counter
|
||||||
@ -13,16 +13,12 @@ pragma solidity ^0.4.24;
|
|||||||
* so it's not something you have to worry about.)
|
* so it's not something you have to worry about.)
|
||||||
*/
|
*/
|
||||||
library Counter {
|
library Counter {
|
||||||
|
struct Counter {
|
||||||
|
uint256 current; // default: 0
|
||||||
|
}
|
||||||
|
|
||||||
struct Counter {
|
function next(Counter storage index) internal returns (uint256) {
|
||||||
uint256 current; // default: 0
|
index.current += 1;
|
||||||
}
|
return index.current;
|
||||||
|
}
|
||||||
function next(Counter storage index)
|
|
||||||
internal
|
|
||||||
returns (uint256)
|
|
||||||
{
|
|
||||||
index.current += 1;
|
|
||||||
return index.current;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../../token/ERC20/IERC20.sol";
|
import "../../token/ERC20/IERC20.sol";
|
||||||
|
|
||||||
@ -6,22 +6,19 @@ import "../../token/ERC20/IERC20.sol";
|
|||||||
* @title ERC-1047 Token Metadata
|
* @title ERC-1047 Token Metadata
|
||||||
* @dev See https://eips.ethereum.org/EIPS/eip-1046
|
* @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 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 {
|
contract ERC20TokenMetadata is IERC20 {
|
||||||
function tokenURI() external view returns (string);
|
function tokenURI() external view returns (string memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
contract ERC20WithMetadata is ERC20TokenMetadata {
|
contract ERC20WithMetadata is ERC20TokenMetadata {
|
||||||
string private _tokenURI;
|
string private _tokenURI;
|
||||||
|
|
||||||
constructor(string tokenURI)
|
constructor (string memory tokenURI) public {
|
||||||
public
|
_tokenURI = tokenURI;
|
||||||
{
|
}
|
||||||
_tokenURI = tokenURI;
|
|
||||||
}
|
|
||||||
|
|
||||||
function tokenURI() external view returns (string) {
|
function tokenURI() external view returns (string memory) {
|
||||||
return _tokenURI;
|
return _tokenURI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/IERC20.sol";
|
import "../token/ERC20/IERC20.sol";
|
||||||
import "../token/ERC20/ERC20Mintable.sol";
|
import "../token/ERC20/ERC20Mintable.sol";
|
||||||
@ -32,69 +32,69 @@ import "../math/Math.sol";
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
contract ERC20Migrator {
|
contract ERC20Migrator {
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
/// Address of the old token contract
|
/// Address of the old token contract
|
||||||
IERC20 private _legacyToken;
|
IERC20 private _legacyToken;
|
||||||
|
|
||||||
/// Address of the new token contract
|
/// Address of the new token contract
|
||||||
ERC20Mintable private _newToken;
|
ERC20Mintable private _newToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param legacyToken address of the old token contract
|
* @param legacyToken address of the old token contract
|
||||||
*/
|
*/
|
||||||
constructor(IERC20 legacyToken) public {
|
constructor (IERC20 legacyToken) public {
|
||||||
require(legacyToken != address(0));
|
require(address(legacyToken) != address(0));
|
||||||
_legacyToken = legacyToken;
|
_legacyToken = legacyToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Returns the legacy token that is being migrated.
|
* @dev Returns the legacy token that is being migrated.
|
||||||
*/
|
*/
|
||||||
function legacyToken() public view returns (IERC20) {
|
function legacyToken() public view returns (IERC20) {
|
||||||
return _legacyToken;
|
return _legacyToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Returns the new token to which we are migrating.
|
* @dev Returns the new token to which we are migrating.
|
||||||
*/
|
*/
|
||||||
function newToken() public view returns (IERC20) {
|
function newToken() public view returns (IERC20) {
|
||||||
return _newToken;
|
return _newToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Begins the migration by setting which is the new token that will be
|
* @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.
|
* minted. This contract must be a minter for the new token.
|
||||||
* @param newToken the token that will be minted
|
* @param newToken the token that will be minted
|
||||||
*/
|
*/
|
||||||
function beginMigration(ERC20Mintable newToken) public {
|
function beginMigration(ERC20Mintable newToken) public {
|
||||||
require(_newToken == address(0));
|
require(address(_newToken) == address(0));
|
||||||
require(newToken != address(0));
|
require(address(newToken) != address(0));
|
||||||
require(newToken.isMinter(this));
|
require(newToken.isMinter(address(this)));
|
||||||
|
|
||||||
_newToken = newToken;
|
_newToken = newToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Transfers part of an account's balance in the old token to this
|
* @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.
|
* contract, and mints the same amount of new tokens for that account.
|
||||||
* @param account whose tokens will be migrated
|
* @param account whose tokens will be migrated
|
||||||
* @param amount amount of tokens to be migrated
|
* @param amount amount of tokens to be migrated
|
||||||
*/
|
*/
|
||||||
function migrate(address account, uint256 amount) public {
|
function migrate(address account, uint256 amount) public {
|
||||||
_legacyToken.safeTransferFrom(account, this, amount);
|
_legacyToken.safeTransferFrom(account, address(this), amount);
|
||||||
_newToken.mint(account, amount);
|
_newToken.mint(account, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Transfers all of an account's allowed balance in the old token to
|
* @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.
|
* this contract, and mints the same amount of new tokens for that account.
|
||||||
* @param account whose tokens will be migrated
|
* @param account whose tokens will be migrated
|
||||||
*/
|
*/
|
||||||
function migrateAll(address account) public {
|
function migrateAll(address account) public {
|
||||||
uint256 balance = _legacyToken.balanceOf(account);
|
uint256 balance = _legacyToken.balanceOf(account);
|
||||||
uint256 allowance = _legacyToken.allowance(account, this);
|
uint256 allowance = _legacyToken.allowance(account, address(this));
|
||||||
uint256 amount = Math.min(balance, allowance);
|
uint256 amount = Math.min(balance, allowance);
|
||||||
migrate(account, amount);
|
migrate(account, amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../access/roles/SignerRole.sol";
|
import "../access/roles/SignerRole.sol";
|
||||||
import "../cryptography/ECDSA.sol";
|
import "../cryptography/ECDSA.sol";
|
||||||
@ -35,112 +35,86 @@ import "../cryptography/ECDSA.sol";
|
|||||||
* See https://ethereum.stackexchange.com/a/50616 for more details.
|
* See https://ethereum.stackexchange.com/a/50616 for more details.
|
||||||
*/
|
*/
|
||||||
contract SignatureBouncer is SignerRole {
|
contract SignatureBouncer is SignerRole {
|
||||||
using ECDSA for bytes32;
|
using ECDSA for bytes32;
|
||||||
|
|
||||||
// Function selectors are 4 bytes long, as documented in
|
// Function selectors are 4 bytes long, as documented in
|
||||||
// https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector
|
// https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector
|
||||||
uint256 private constant _METHOD_ID_SIZE = 4;
|
uint256 private constant _METHOD_ID_SIZE = 4;
|
||||||
// Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes
|
// Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes
|
||||||
uint256 private constant _SIGNATURE_SIZE = 96;
|
uint256 private constant _SIGNATURE_SIZE = 96;
|
||||||
|
|
||||||
constructor() internal {}
|
constructor () internal {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
/**
|
|
||||||
* @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];
|
|
||||||
}
|
}
|
||||||
return _isValidDataHash(
|
|
||||||
keccak256(abi.encodePacked(address(this), account, data)),
|
|
||||||
signature
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev is the signature of `this + sender + methodId + params(s)` from a signer?
|
* @dev requires that a valid signature of a signer was provided
|
||||||
* @notice the signature parameter of the method being validated must be the "last" parameter
|
*/
|
||||||
* @return bool
|
modifier onlyValidSignature(bytes memory signature) {
|
||||||
*/
|
require(_isValidSignature(msg.sender, signature));
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
return _isValidDataHash(
|
|
||||||
keccak256(abi.encodePacked(address(this), account, data)),
|
|
||||||
signature
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev internal function to convert a hash to an eth signed message
|
* @dev requires that a valid signature with a specifed method of a signer was provided
|
||||||
* and then recover the signature and check it against the signer role
|
*/
|
||||||
* @return bool
|
modifier onlyValidSignatureAndMethod(bytes memory signature) {
|
||||||
*/
|
require(_isValidSignatureAndMethod(msg.sender, signature));
|
||||||
function _isValidDataHash(bytes32 hash, bytes signature)
|
_;
|
||||||
internal
|
}
|
||||||
view
|
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
address signer = hash
|
|
||||||
.toEthSignedMessageHash()
|
|
||||||
.recover(signature);
|
|
||||||
|
|
||||||
return signer != address(0) && isSigner(signer);
|
/**
|
||||||
}
|
* @dev requires that a valid signature with a specifed method and params of a signer was provided
|
||||||
|
*/
|
||||||
|
modifier onlyValidSignatureAndData(bytes memory signature) {
|
||||||
|
require(_isValidSignatureAndData(msg.sender, signature));
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev is the signature of `this + sender` 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 + sender + 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 + 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 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
60
contracts/drafts/SignedSafeMath.sol
Normal file
60
contracts/drafts/SignedSafeMath.sol
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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,6 +1,4 @@
|
|||||||
/* solium-disable security/no-block-members */
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
pragma solidity ^0.4.24;
|
|
||||||
|
|
||||||
import "../token/ERC20/SafeERC20.sol";
|
import "../token/ERC20/SafeERC20.sol";
|
||||||
import "../ownership/Ownable.sol";
|
import "../ownership/Ownable.sol";
|
||||||
@ -13,163 +11,162 @@ import "../math/SafeMath.sol";
|
|||||||
* owner.
|
* owner.
|
||||||
*/
|
*/
|
||||||
contract TokenVesting is Ownable {
|
contract TokenVesting is Ownable {
|
||||||
using SafeMath for uint256;
|
// The vesting schedule is time-based (i.e. using block timestamps as opposed to e.g. block numbers), and is
|
||||||
using SafeERC20 for IERC20;
|
// 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);
|
using SafeMath for uint256;
|
||||||
event TokenVestingRevoked(address token);
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
// beneficiary of tokens after they are released
|
event TokensReleased(address token, uint256 amount);
|
||||||
address private _beneficiary;
|
event TokenVestingRevoked(address token);
|
||||||
|
|
||||||
uint256 private _cliff;
|
// beneficiary of tokens after they are released
|
||||||
uint256 private _start;
|
address private _beneficiary;
|
||||||
uint256 private _duration;
|
|
||||||
|
|
||||||
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;
|
bool private _revocable;
|
||||||
mapping (address => bool) private _revoked;
|
|
||||||
|
|
||||||
/**
|
mapping (address => uint256) private _released;
|
||||||
* @dev Creates a vesting contract that vests its balance of any ERC20 token to the
|
mapping (address => bool) private _revoked;
|
||||||
* 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);
|
|
||||||
|
|
||||||
_beneficiary = beneficiary;
|
/**
|
||||||
_revocable = revocable;
|
* @dev Creates a vesting contract that vests its balance of any ERC20 token to the
|
||||||
_duration = duration;
|
* beneficiary, gradually in a linear fashion until start + duration. By then all
|
||||||
_cliff = start.add(cliffDuration);
|
* of the balance will have vested.
|
||||||
_start = start;
|
* @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);
|
||||||
|
|
||||||
/**
|
_beneficiary = beneficiary;
|
||||||
* @return the beneficiary of the tokens.
|
_revocable = revocable;
|
||||||
*/
|
_duration = duration;
|
||||||
function beneficiary() public view returns(address) {
|
_cliff = start.add(cliffDuration);
|
||||||
return _beneficiary;
|
_start = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the cliff time of the token vesting.
|
* @return the beneficiary of the tokens.
|
||||||
*/
|
*/
|
||||||
function cliff() public view returns(uint256) {
|
function beneficiary() public view returns (address) {
|
||||||
return _cliff;
|
return _beneficiary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the start time of the token vesting.
|
* @return the cliff time of the token vesting.
|
||||||
*/
|
*/
|
||||||
function start() public view returns(uint256) {
|
function cliff() public view returns (uint256) {
|
||||||
return _start;
|
return _cliff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the duration of the token vesting.
|
* @return the start time of the token vesting.
|
||||||
*/
|
*/
|
||||||
function duration() public view returns(uint256) {
|
function start() public view returns (uint256) {
|
||||||
return _duration;
|
return _start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the vesting is revocable.
|
* @return the duration of the token vesting.
|
||||||
*/
|
*/
|
||||||
function revocable() public view returns(bool) {
|
function duration() public view returns (uint256) {
|
||||||
return _revocable;
|
return _duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the amount of the token released.
|
* @return true if the vesting is revocable.
|
||||||
*/
|
*/
|
||||||
function released(address token) public view returns(uint256) {
|
function revocable() public view returns (bool) {
|
||||||
return _released[token];
|
return _revocable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the token is revoked.
|
* @return the amount of the token released.
|
||||||
*/
|
*/
|
||||||
function revoked(address token) public view returns(bool) {
|
function released(address token) public view returns (uint256) {
|
||||||
return _revoked[token];
|
return _released[token];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice Transfers vested tokens to beneficiary.
|
* @return true if the token is revoked.
|
||||||
* @param token ERC20 token which is being vested
|
*/
|
||||||
*/
|
function revoked(address token) public view returns (bool) {
|
||||||
function release(IERC20 token) public {
|
return _revoked[token];
|
||||||
uint256 unreleased = _releasableAmount(token);
|
}
|
||||||
|
|
||||||
require(unreleased > 0);
|
/**
|
||||||
|
* @notice Transfers vested tokens to beneficiary.
|
||||||
_released[token] = _released[token].add(unreleased);
|
* @param token ERC20 token which is being vested
|
||||||
|
*/
|
||||||
token.safeTransfer(_beneficiary, unreleased);
|
function release(IERC20 token) public {
|
||||||
|
uint256 unreleased = _releasableAmount(token);
|
||||||
emit TokensReleased(token, unreleased);
|
|
||||||
}
|
require(unreleased > 0);
|
||||||
|
|
||||||
/**
|
_released[address(token)] = _released[address(token)].add(unreleased);
|
||||||
* @notice Allows the owner to revoke the vesting. Tokens already vested
|
|
||||||
* remain in the contract, the rest are returned to the owner.
|
token.safeTransfer(_beneficiary, unreleased);
|
||||||
* @param token ERC20 token which is being vested
|
|
||||||
*/
|
emit TokensReleased(address(token), unreleased);
|
||||||
function revoke(IERC20 token) public onlyOwner {
|
}
|
||||||
require(_revocable);
|
|
||||||
require(!_revoked[token]);
|
/**
|
||||||
|
* @notice Allows the owner to revoke the vesting. Tokens already vested
|
||||||
uint256 balance = token.balanceOf(address(this));
|
* remain in the contract, the rest are returned to the owner.
|
||||||
|
* @param token ERC20 token which is being vested
|
||||||
uint256 unreleased = _releasableAmount(token);
|
*/
|
||||||
uint256 refund = balance.sub(unreleased);
|
function revoke(IERC20 token) public onlyOwner {
|
||||||
|
require(_revocable);
|
||||||
_revoked[token] = true;
|
require(!_revoked[address(token)]);
|
||||||
|
|
||||||
token.safeTransfer(owner(), refund);
|
uint256 balance = token.balanceOf(address(this));
|
||||||
|
|
||||||
emit TokenVestingRevoked(token);
|
uint256 unreleased = _releasableAmount(token);
|
||||||
}
|
uint256 refund = balance.sub(unreleased);
|
||||||
|
|
||||||
/**
|
_revoked[address(token)] = true;
|
||||||
* @dev Calculates the amount that has already vested but hasn't been released yet.
|
|
||||||
* @param token ERC20 token which is being vested
|
token.safeTransfer(owner(), refund);
|
||||||
*/
|
|
||||||
function _releasableAmount(IERC20 token) private view returns (uint256) {
|
emit TokenVestingRevoked(address(token));
|
||||||
return _vestedAmount(token).sub(_released[token]);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* @dev Calculates the amount that has already vested but hasn't been released yet.
|
||||||
* @dev Calculates the amount that has already vested.
|
* @param token ERC20 token which is being vested
|
||||||
* @param token ERC20 token which is being vested
|
*/
|
||||||
*/
|
function _releasableAmount(IERC20 token) private view returns (uint256) {
|
||||||
function _vestedAmount(IERC20 token) private view returns (uint256) {
|
return _vestedAmount(token).sub(_released[address(token)]);
|
||||||
uint256 currentBalance = token.balanceOf(this);
|
}
|
||||||
uint256 totalBalance = currentBalance.add(_released[token]);
|
|
||||||
|
/**
|
||||||
if (block.timestamp < _cliff) {
|
* @dev Calculates the amount that has already vested.
|
||||||
return 0;
|
* @param token ERC20 token which is being vested
|
||||||
} else if (block.timestamp >= _start.add(_duration) || _revoked[token]) {
|
*/
|
||||||
return totalBalance;
|
function _vestedAmount(IERC20 token) private view returns (uint256) {
|
||||||
} else {
|
uint256 currentBalance = token.balanceOf(address(this));
|
||||||
return totalBalance.mul(block.timestamp.sub(_start)).div(_duration);
|
uint256 totalBalance = currentBalance.add(_released[address(token)]);
|
||||||
|
|
||||||
|
if (block.timestamp < _cliff) {
|
||||||
|
return 0;
|
||||||
|
} else if (block.timestamp >= _start.add(_duration) || _revoked[address(token)]) {
|
||||||
|
return totalBalance;
|
||||||
|
} else {
|
||||||
|
return totalBalance.mul(block.timestamp.sub(_start)).div(_duration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||||
@ -12,7 +12,9 @@ import "../token/ERC20/ERC20Detailed.sol";
|
|||||||
* It is meant to be used in a crowdsale contract.
|
* It is meant to be used in a crowdsale contract.
|
||||||
*/
|
*/
|
||||||
contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed {
|
contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed {
|
||||||
constructor() public ERC20Detailed("Sample Crowdsale Token", "SCT", 18) {}
|
constructor () public ERC20Detailed("Sample Crowdsale Token", "SCT", 18) {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,30 +30,24 @@ contract SampleCrowdsaleToken is ERC20Mintable, ERC20Detailed {
|
|||||||
* After adding multiple features it's good practice to run integration tests
|
* After adding multiple features it's good practice to run integration tests
|
||||||
* to ensure that subcontracts works together as intended.
|
* 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 CappedCrowdsale, RefundableCrowdsale, MintedCrowdsale {
|
||||||
|
constructor (
|
||||||
constructor(
|
uint256 openingTime,
|
||||||
uint256 openingTime,
|
uint256 closingTime,
|
||||||
uint256 closingTime,
|
uint256 rate,
|
||||||
uint256 rate,
|
address payable wallet,
|
||||||
address wallet,
|
uint256 cap,
|
||||||
uint256 cap,
|
ERC20Mintable token,
|
||||||
ERC20Mintable token,
|
uint256 goal
|
||||||
uint256 goal
|
)
|
||||||
)
|
public
|
||||||
public
|
Crowdsale(rate, wallet, token)
|
||||||
Crowdsale(rate, wallet, token)
|
CappedCrowdsale(cap)
|
||||||
CappedCrowdsale(cap)
|
TimedCrowdsale(openingTime, closingTime)
|
||||||
TimedCrowdsale(openingTime, closingTime)
|
RefundableCrowdsale(goal)
|
||||||
RefundableCrowdsale(goal)
|
{
|
||||||
{
|
//As goal needs to be met for a successful crowdsale
|
||||||
//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
|
||||||
//the value needs to less or equal than a cap which is limit for accepted funds
|
require(goal <= cap);
|
||||||
require(goal <= cap);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/ERC20.sol";
|
import "../token/ERC20/ERC20.sol";
|
||||||
|
import "../token/ERC20/ERC20Detailed.sol";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title SimpleToken
|
* @title SimpleToken
|
||||||
@ -8,19 +9,14 @@ import "../token/ERC20/ERC20.sol";
|
|||||||
* Note they can later distribute these tokens as they wish using `transfer` and other
|
* Note they can later distribute these tokens as they wish using `transfer` and other
|
||||||
* `ERC20` functions.
|
* `ERC20` functions.
|
||||||
*/
|
*/
|
||||||
contract SimpleToken is ERC20 {
|
contract SimpleToken is ERC20, ERC20Detailed {
|
||||||
|
uint8 public constant DECIMALS = 18;
|
||||||
string public constant name = "SimpleToken";
|
uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(DECIMALS));
|
||||||
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.
|
||||||
|
*/
|
||||||
|
constructor () public ERC20Detailed("SimpleToken", "SIM", DECIMALS) {
|
||||||
|
_mint(msg.sender, INITIAL_SUPPLY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "./IERC165.sol";
|
import "./IERC165.sol";
|
||||||
|
|
||||||
@ -8,46 +8,37 @@ import "./IERC165.sol";
|
|||||||
* @dev Implements ERC165 using a lookup table.
|
* @dev Implements ERC165 using a lookup table.
|
||||||
*/
|
*/
|
||||||
contract ERC165 is IERC165 {
|
contract ERC165 is IERC165 {
|
||||||
|
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||||
|
/**
|
||||||
|
* 0x01ffc9a7 ===
|
||||||
|
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||||
|
*/
|
||||||
|
|
||||||
bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7;
|
/**
|
||||||
/**
|
* @dev a mapping of interface id to whether or not it's supported
|
||||||
* 0x01ffc9a7 ===
|
*/
|
||||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
mapping(bytes4 => bool) private _supportedInterfaces;
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev a mapping of interface id to whether or not it's supported
|
* @dev A contract implementing SupportsInterfaceWithLookup
|
||||||
*/
|
* implement ERC165 itself
|
||||||
mapping(bytes4 => bool) private _supportedInterfaces;
|
*/
|
||||||
|
constructor () internal {
|
||||||
|
_registerInterface(_INTERFACE_ID_ERC165);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev A contract implementing SupportsInterfaceWithLookup
|
* @dev implement supportsInterface(bytes4) using a lookup table
|
||||||
* implement ERC165 itself
|
*/
|
||||||
*/
|
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
|
||||||
constructor()
|
return _supportedInterfaces[interfaceId];
|
||||||
internal
|
}
|
||||||
{
|
|
||||||
_registerInterface(_InterfaceId_ERC165);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev implement supportsInterface(bytes4) using a lookup table
|
* @dev internal method for registering an interface
|
||||||
*/
|
*/
|
||||||
function supportsInterface(bytes4 interfaceId)
|
function _registerInterface(bytes4 interfaceId) internal {
|
||||||
external
|
require(interfaceId != 0xffffffff);
|
||||||
view
|
_supportedInterfaces[interfaceId] = true;
|
||||||
returns (bool)
|
}
|
||||||
{
|
|
||||||
return _supportedInterfaces[interfaceId];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev internal method for registering an interface
|
|
||||||
*/
|
|
||||||
function _registerInterface(bytes4 interfaceId)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
require(interfaceId != 0xffffffff);
|
|
||||||
_supportedInterfaces[interfaceId] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title ERC165Checker
|
* @title ERC165Checker
|
||||||
@ -6,141 +6,118 @@ pragma solidity ^0.4.24;
|
|||||||
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
|
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
|
||||||
*/
|
*/
|
||||||
library ERC165Checker {
|
library ERC165Checker {
|
||||||
// As per the EIP-165 spec, no interface should ever match 0xffffffff
|
// As per the EIP-165 spec, no interface should ever match 0xffffffff
|
||||||
bytes4 private constant _InterfaceId_Invalid = 0xffffffff;
|
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
|
||||||
|
|
||||||
bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7;
|
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||||
/**
|
/**
|
||||||
* 0x01ffc9a7 ===
|
* 0x01ffc9a7 ===
|
||||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice Query if a contract supports ERC165
|
* @notice Query if a contract supports ERC165
|
||||||
* @param account The address of the contract to query for support of ERC165
|
* @param account The address of the contract to query for support of ERC165
|
||||||
* @return true if the contract at account implements ERC165
|
* @return true if the contract at account implements ERC165
|
||||||
*/
|
*/
|
||||||
function _supportsERC165(address account)
|
function _supportsERC165(address account) internal view returns (bool) {
|
||||||
internal
|
// Any contract that implements ERC165 must explicitly indicate support of
|
||||||
view
|
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
|
||||||
returns (bool)
|
return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) &&
|
||||||
{
|
!_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// query support of each interface in _interfaceIds
|
/**
|
||||||
for (uint256 i = 0; i < interfaceIds.length; i++) {
|
* @notice Query if a contract implements an interface, also checks support of ERC165
|
||||||
if (!_supportsERC165Interface(account, interfaceIds[i])) {
|
* @param account The address of the contract to query for support of an interface
|
||||||
return false;
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
// query support of each interface in _interfaceIds
|
||||||
* @notice Query if a contract implements an interface, does not check ERC165 support
|
for (uint256 i = 0; i < interfaceIds.length; i++) {
|
||||||
* @param account The address of the contract to query for support of an interface
|
if (!_supportsERC165Interface(account, interfaceIds[i])) {
|
||||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
return false;
|
||||||
* @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);
|
// all interfaces supported
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @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
|
* @notice Query if a contract implements an interface, does not check ERC165 support
|
||||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
* @param account The address of the contract to query for support of an interface
|
||||||
* @return success true if the STATICCALL succeeded, false otherwise
|
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||||
* @return result true if the STATICCALL succeeded and the contract at account
|
* @return true if the contract at account indicates support of the interface with
|
||||||
* indicates support of the interface with identifier interfaceId, false otherwise
|
* identifier interfaceId, false otherwise
|
||||||
*/
|
* @dev Assumes that account contains a contract that supports ERC165, otherwise
|
||||||
function _callERC165SupportsInterface(
|
* the behavior of this method is undefined. This precondition can be checked
|
||||||
address account,
|
* with the `supportsERC165` method in this library.
|
||||||
bytes4 interfaceId
|
* Interface identification is specified in ERC-165.
|
||||||
)
|
*/
|
||||||
private
|
function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
|
||||||
view
|
// success determines whether the staticcall succeeded and result determines
|
||||||
returns (bool success, bool result)
|
// whether the contract at account indicates support of _interfaceId
|
||||||
{
|
(bool success, bool result) = _callERC165SupportsInterface(account, interfaceId);
|
||||||
bytes memory encodedParams = abi.encodeWithSelector(
|
|
||||||
_InterfaceId_ERC165,
|
return (success && result);
|
||||||
interfaceId
|
}
|
||||||
);
|
|
||||||
|
/**
|
||||||
// solium-disable-next-line security/no-inline-assembly
|
* @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw
|
||||||
assembly {
|
* @param account The address of the contract to query for support of an interface
|
||||||
let encodedParams_data := add(0x20, encodedParams)
|
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||||
let encodedParams_size := mload(encodedParams)
|
* @return success true if the STATICCALL succeeded, false otherwise
|
||||||
|
* @return result true if the STATICCALL succeeded and the contract at account
|
||||||
let output := mload(0x40) // Find empty storage location using "free memory pointer"
|
* indicates support of the interface with identifier interfaceId, false otherwise
|
||||||
mstore(output, 0x0)
|
*/
|
||||||
|
function _callERC165SupportsInterface(address account, bytes4 interfaceId)
|
||||||
success := staticcall(
|
private
|
||||||
30000, // 30k gas
|
view
|
||||||
account, // To addr
|
returns (bool success, bool result)
|
||||||
encodedParams_data,
|
{
|
||||||
encodedParams_size,
|
bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId);
|
||||||
output,
|
|
||||||
0x20 // Outputs are 32 bytes long
|
// solhint-disable-next-line no-inline-assembly
|
||||||
)
|
assembly {
|
||||||
|
let encodedParams_data := add(0x20, encodedParams)
|
||||||
result := mload(output) // Load the result
|
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.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title IERC165
|
* @title IERC165
|
||||||
* @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
|
* @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
|
||||||
*/
|
*/
|
||||||
interface IERC165 {
|
interface IERC165 {
|
||||||
|
/**
|
||||||
/**
|
* @notice Query if a contract implements an interface
|
||||||
* @notice Query if a contract implements an interface
|
* @param interfaceId The interface identifier, as specified in ERC-165
|
||||||
* @param interfaceId The interface identifier, as specified in ERC-165
|
* @dev Interface identification is specified in ERC-165. This function
|
||||||
* @dev Interface identification is specified in ERC-165. This function
|
* uses less than 30,000 gas.
|
||||||
* uses less than 30,000 gas.
|
*/
|
||||||
*/
|
function supportsInterface(bytes4 interfaceId) external view returns (bool);
|
||||||
function supportsInterface(bytes4 interfaceId)
|
|
||||||
external
|
|
||||||
view
|
|
||||||
returns (bool);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../access/roles/PauserRole.sol";
|
import "../access/roles/PauserRole.sol";
|
||||||
|
|
||||||
@ -7,51 +7,51 @@ import "../access/roles/PauserRole.sol";
|
|||||||
* @dev Base contract which allows children to implement an emergency stop mechanism.
|
* @dev Base contract which allows children to implement an emergency stop mechanism.
|
||||||
*/
|
*/
|
||||||
contract Pausable is PauserRole {
|
contract Pausable is PauserRole {
|
||||||
event Paused(address account);
|
event Paused(address account);
|
||||||
event Unpaused(address account);
|
event Unpaused(address account);
|
||||||
|
|
||||||
bool private _paused;
|
bool private _paused;
|
||||||
|
|
||||||
constructor() internal {
|
constructor () internal {
|
||||||
_paused = false;
|
_paused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the contract is paused, false otherwise.
|
* @return true if the contract is paused, false otherwise.
|
||||||
*/
|
*/
|
||||||
function paused() public view returns(bool) {
|
function paused() public view returns (bool) {
|
||||||
return _paused;
|
return _paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Modifier to make a function callable only when the contract is not paused.
|
* @dev Modifier to make a function callable only when the contract is not paused.
|
||||||
*/
|
*/
|
||||||
modifier whenNotPaused() {
|
modifier whenNotPaused() {
|
||||||
require(!_paused);
|
require(!_paused);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Modifier to make a function callable only when the contract is paused.
|
* @dev Modifier to make a function callable only when the contract is paused.
|
||||||
*/
|
*/
|
||||||
modifier whenPaused() {
|
modifier whenPaused() {
|
||||||
require(_paused);
|
require(_paused);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev called by the owner to pause, triggers stopped state
|
* @dev called by the owner to pause, triggers stopped state
|
||||||
*/
|
*/
|
||||||
function pause() public onlyPauser whenNotPaused {
|
function pause() public onlyPauser whenNotPaused {
|
||||||
_paused = true;
|
_paused = true;
|
||||||
emit Paused(msg.sender);
|
emit Paused(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev called by the owner to unpause, returns to normal state
|
* @dev called by the owner to unpause, returns to normal state
|
||||||
*/
|
*/
|
||||||
function unpause() public onlyPauser whenPaused {
|
function unpause() public onlyPauser whenPaused {
|
||||||
_paused = false;
|
_paused = false;
|
||||||
emit Unpaused(msg.sender);
|
emit Unpaused(msg.sender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,31 +1,31 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Math
|
* @title Math
|
||||||
* @dev Assorted math operations
|
* @dev Assorted math operations
|
||||||
*/
|
*/
|
||||||
library Math {
|
library Math {
|
||||||
/**
|
/**
|
||||||
* @dev Returns the largest of two numbers.
|
* @dev Returns the largest of two numbers.
|
||||||
*/
|
*/
|
||||||
function max(uint256 a, uint256 b) internal pure returns (uint256) {
|
function max(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||||
return a >= b ? a : b;
|
return a >= b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Returns the smallest of two numbers.
|
* @dev Returns the smallest of two numbers.
|
||||||
*/
|
*/
|
||||||
function min(uint256 a, uint256 b) internal pure returns (uint256) {
|
function min(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Calculates the average of two numbers. Since these are integers,
|
* @dev Calculates the average of two numbers. Since these are integers,
|
||||||
* averages of an even and odd number cannot be represented, and will be
|
* averages of an even and odd number cannot be represented, and will be
|
||||||
* rounded down.
|
* rounded down.
|
||||||
*/
|
*/
|
||||||
function average(uint256 a, uint256 b) internal pure returns (uint256) {
|
function average(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||||
// (a + b) / 2 can overflow, so we distribute
|
// (a + b) / 2 can overflow, so we distribute
|
||||||
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
|
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,65 +1,65 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title SafeMath
|
* @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 {
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
uint256 c = a * b;
|
||||||
* @dev Multiplies two numbers, reverts on overflow.
|
require(c / a == b);
|
||||||
*/
|
|
||||||
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
|
return c;
|
||||||
// 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);
|
* @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.
|
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
|
||||||
*/
|
*/
|
||||||
function div(uint256 a, uint256 b) internal pure returns (uint256) {
|
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||||
require(b > 0); // Solidity only automatically asserts when dividing by 0
|
require(b <= a);
|
||||||
uint256 c = a / b;
|
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 Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
|
* @dev Adds two unsigned integers, reverts on overflow.
|
||||||
*/
|
*/
|
||||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||||
require(b <= a);
|
uint256 c = a + b;
|
||||||
uint256 c = a - b;
|
require(c >= a);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Adds two numbers, reverts on overflow.
|
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
|
||||||
*/
|
* reverts when dividing by zero.
|
||||||
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
*/
|
||||||
uint256 c = a + b;
|
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||||
require(c >= a);
|
require(b != 0);
|
||||||
|
return a % b;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
19
contracts/mocks/Acknowledger.sol
Normal file
19
contracts/mocks/Acknowledger.sol
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
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.0;
|
||||||
|
|
||||||
import "../utils/Address.sol";
|
import "../utils/Address.sol";
|
||||||
|
|
||||||
contract AddressImpl {
|
contract AddressImpl {
|
||||||
function isContract(address account)
|
function isContract(address account) external view returns (bool) {
|
||||||
external
|
return Address.isContract(account);
|
||||||
view
|
}
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
return Address.isContract(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,14 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/IERC20.sol";
|
import "../token/ERC20/IERC20.sol";
|
||||||
import "../crowdsale/emission/AllowanceCrowdsale.sol";
|
import "../crowdsale/emission/AllowanceCrowdsale.sol";
|
||||||
|
|
||||||
contract AllowanceCrowdsaleImpl is AllowanceCrowdsale {
|
contract AllowanceCrowdsaleImpl is AllowanceCrowdsale {
|
||||||
|
constructor (uint256 rate, address payable wallet, IERC20 token, address tokenWallet)
|
||||||
constructor (
|
public
|
||||||
uint256 rate,
|
Crowdsale(rate, wallet, token)
|
||||||
address wallet,
|
AllowanceCrowdsale(tokenWallet)
|
||||||
IERC20 token,
|
{
|
||||||
address tokenWallet
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
)
|
}
|
||||||
public
|
|
||||||
Crowdsale(rate, wallet, token)
|
|
||||||
AllowanceCrowdsale(tokenWallet)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,17 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../utils/Arrays.sol";
|
import "../utils/Arrays.sol";
|
||||||
|
|
||||||
contract ArraysImpl {
|
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 {
|
function findUpperBound(uint256 _element) external view returns (uint256) {
|
||||||
array = _array;
|
return array.findUpperBound(_element);
|
||||||
}
|
}
|
||||||
|
|
||||||
function findUpperBound(uint256 _element) external view returns (uint256) {
|
|
||||||
return array.findUpperBound(_element);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,14 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/IERC20.sol";
|
import "../token/ERC20/IERC20.sol";
|
||||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||||
|
|
||||||
contract CappedCrowdsaleImpl is CappedCrowdsale {
|
contract CappedCrowdsaleImpl is CappedCrowdsale {
|
||||||
|
constructor (uint256 rate, address payable wallet, IERC20 token, uint256 cap)
|
||||||
constructor (
|
public
|
||||||
uint256 rate,
|
Crowdsale(rate, wallet, token)
|
||||||
address wallet,
|
CappedCrowdsale(cap)
|
||||||
IERC20 token,
|
{
|
||||||
uint256 cap
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
)
|
}
|
||||||
public
|
|
||||||
Crowdsale(rate, wallet, token)
|
|
||||||
CappedCrowdsale(cap)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,18 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../access/roles/CapperRole.sol";
|
import "../access/roles/CapperRole.sol";
|
||||||
|
|
||||||
contract CapperRoleMock is CapperRole {
|
contract CapperRoleMock is CapperRole {
|
||||||
function removeCapper(address account) public {
|
function removeCapper(address account) public {
|
||||||
_removeCapper(account);
|
_removeCapper(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onlyCapperMock() public view onlyCapper {
|
function onlyCapperMock() public view onlyCapper {
|
||||||
}
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
|
|
||||||
// Causes a compilation error if super._removeCapper is not internal
|
// Causes a compilation error if super._removeCapper is not internal
|
||||||
function _removeCapper(address account) internal {
|
function _removeCapper(address account) internal {
|
||||||
super._removeCapper(account);
|
super._removeCapper(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../payment/escrow/ConditionalEscrow.sol";
|
import "../payment/escrow/ConditionalEscrow.sol";
|
||||||
|
|
||||||
// mock class using ConditionalEscrow
|
// mock class using ConditionalEscrow
|
||||||
contract ConditionalEscrowMock is ConditionalEscrow {
|
contract ConditionalEscrowMock is ConditionalEscrow {
|
||||||
mapping(address => bool) private _allowed;
|
mapping(address => bool) private _allowed;
|
||||||
|
|
||||||
function setAllowed(address payee, bool allowed) public {
|
function setAllowed(address payee, bool allowed) public {
|
||||||
_allowed[payee] = allowed;
|
_allowed[payee] = allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function withdrawalAllowed(address payee) public view returns (bool) {
|
function withdrawalAllowed(address payee) public view returns (bool) {
|
||||||
return _allowed[payee];
|
return _allowed[payee];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,17 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../drafts/Counter.sol";
|
import "../drafts/Counter.sol";
|
||||||
|
|
||||||
contract CounterImpl {
|
contract CounterImpl {
|
||||||
using Counter for Counter.Counter;
|
using Counter for Counter.Counter;
|
||||||
|
|
||||||
uint256 public theId;
|
uint256 public theId;
|
||||||
|
|
||||||
// use whatever key you want to track your counters
|
// use whatever key you want to track your counters
|
||||||
mapping(string => Counter.Counter) private _counters;
|
mapping(string => Counter.Counter) private _counters;
|
||||||
|
|
||||||
function doThing(string key)
|
function doThing(string memory key) public returns (uint256) {
|
||||||
public
|
theId = _counters[key].next();
|
||||||
returns (uint256)
|
return theId;
|
||||||
{
|
}
|
||||||
theId = _counters[key].next();
|
|
||||||
return theId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../crowdsale/Crowdsale.sol";
|
import "../crowdsale/Crowdsale.sol";
|
||||||
|
|
||||||
contract CrowdsaleMock is Crowdsale {
|
contract CrowdsaleMock is Crowdsale {
|
||||||
constructor(uint256 rate, address wallet, IERC20 token) public
|
constructor (uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) {
|
||||||
Crowdsale(rate, wallet, token) {
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,13 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/ERC20.sol";
|
import "../token/ERC20/ERC20.sol";
|
||||||
import "../token/ERC20/ERC20Detailed.sol";
|
import "../token/ERC20/ERC20Detailed.sol";
|
||||||
|
|
||||||
contract ERC20DetailedMock is ERC20, ERC20Detailed {
|
contract ERC20DetailedMock is ERC20, ERC20Detailed {
|
||||||
constructor(
|
constructor (string memory name, string memory symbol, uint8 decimals)
|
||||||
string name,
|
public
|
||||||
string symbol,
|
ERC20Detailed(name, symbol, decimals)
|
||||||
uint8 decimals
|
{
|
||||||
)
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
ERC20Detailed(name, symbol, decimals)
|
}
|
||||||
public
|
|
||||||
{}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,15 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../cryptography/ECDSA.sol";
|
import "../cryptography/ECDSA.sol";
|
||||||
|
|
||||||
contract ECDSAMock {
|
contract ECDSAMock {
|
||||||
using ECDSA for bytes32;
|
using ECDSA for bytes32;
|
||||||
|
|
||||||
function recover(bytes32 hash, bytes signature)
|
function recover(bytes32 hash, bytes memory signature) public pure returns (address) {
|
||||||
public
|
return hash.recover(signature);
|
||||||
pure
|
}
|
||||||
returns (address)
|
|
||||||
{
|
|
||||||
return hash.recover(signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
function toEthSignedMessageHash(bytes32 hash)
|
function toEthSignedMessageHash(bytes32 hash) public pure returns (bytes32) {
|
||||||
public
|
return hash.toEthSignedMessageHash();
|
||||||
pure
|
}
|
||||||
returns (bytes32)
|
|
||||||
{
|
|
||||||
return hash.toEthSignedMessageHash();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,66 +1,56 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../../introspection/IERC165.sol";
|
import "../../introspection/IERC165.sol";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-214.md#specification
|
* 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.
|
* > 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, [...]
|
* > 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)
|
* 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
|
* solidity-coverage ignores the /mocks folder, so we duplicate its implementation here to avoid instrumenting it
|
||||||
*/
|
*/
|
||||||
contract SupportsInterfaceWithLookupMock is IERC165 {
|
contract SupportsInterfaceWithLookupMock is IERC165 {
|
||||||
|
bytes4 public constant INTERFACE_ID_ERC165 = 0x01ffc9a7;
|
||||||
|
/**
|
||||||
|
* 0x01ffc9a7 ===
|
||||||
|
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||||
|
*/
|
||||||
|
|
||||||
bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7;
|
/**
|
||||||
/**
|
* @dev a mapping of interface id to whether or not it's supported
|
||||||
* 0x01ffc9a7 ===
|
*/
|
||||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
mapping(bytes4 => bool) private _supportedInterfaces;
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev a mapping of interface id to whether or not it's supported
|
* @dev A contract implementing SupportsInterfaceWithLookup
|
||||||
*/
|
* implement ERC165 itself
|
||||||
mapping(bytes4 => bool) private _supportedInterfaces;
|
*/
|
||||||
|
constructor () public {
|
||||||
|
_registerInterface(INTERFACE_ID_ERC165);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev A contract implementing SupportsInterfaceWithLookup
|
* @dev implement supportsInterface(bytes4) using a lookup table
|
||||||
* implement ERC165 itself
|
*/
|
||||||
*/
|
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
|
||||||
constructor()
|
return _supportedInterfaces[interfaceId];
|
||||||
public
|
}
|
||||||
{
|
|
||||||
_registerInterface(InterfaceId_ERC165);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev implement supportsInterface(bytes4) using a lookup table
|
* @dev private method for registering an interface
|
||||||
*/
|
*/
|
||||||
function supportsInterface(bytes4 interfaceId)
|
function _registerInterface(bytes4 interfaceId) internal {
|
||||||
external
|
require(interfaceId != 0xffffffff);
|
||||||
view
|
_supportedInterfaces[interfaceId] = true;
|
||||||
returns (bool)
|
}
|
||||||
{
|
|
||||||
return _supportedInterfaces[interfaceId];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev private method for registering an interface
|
|
||||||
*/
|
|
||||||
function _registerInterface(bytes4 interfaceId)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
require(interfaceId != 0xffffffff);
|
|
||||||
_supportedInterfaces[interfaceId] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
contract ERC165InterfacesSupported is SupportsInterfaceWithLookupMock {
|
contract ERC165InterfacesSupported is SupportsInterfaceWithLookupMock {
|
||||||
constructor (bytes4[] interfaceIds)
|
constructor (bytes4[] memory interfaceIds) public {
|
||||||
public
|
for (uint256 i = 0; i < interfaceIds.length; i++) {
|
||||||
{
|
_registerInterface(interfaceIds[i]);
|
||||||
for (uint256 i = 0; i < interfaceIds.length; i++) {
|
}
|
||||||
_registerInterface(interfaceIds[i]);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
contract ERC165NotSupported {
|
contract ERC165NotSupported {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,31 +1,19 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../introspection/ERC165Checker.sol";
|
import "../introspection/ERC165Checker.sol";
|
||||||
|
|
||||||
contract ERC165CheckerMock {
|
contract ERC165CheckerMock {
|
||||||
using ERC165Checker for address;
|
using ERC165Checker for address;
|
||||||
|
|
||||||
function supportsERC165(address account)
|
function supportsERC165(address account) public view returns (bool) {
|
||||||
public
|
return account._supportsERC165();
|
||||||
view
|
}
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
return account._supportsERC165();
|
|
||||||
}
|
|
||||||
|
|
||||||
function supportsInterface(address account, bytes4 interfaceId)
|
function supportsInterface(address account, bytes4 interfaceId) public view returns (bool) {
|
||||||
public
|
return account._supportsInterface(interfaceId);
|
||||||
view
|
}
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
return account._supportsInterface(interfaceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
function supportsAllInterfaces(address account, bytes4[] interfaceIds)
|
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) public view returns (bool) {
|
||||||
public
|
return account._supportsAllInterfaces(interfaceIds);
|
||||||
view
|
}
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
return account._supportsAllInterfaces(interfaceIds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../introspection/ERC165.sol";
|
import "../introspection/ERC165.sol";
|
||||||
|
|
||||||
contract ERC165Mock is ERC165 {
|
contract ERC165Mock is ERC165 {
|
||||||
function registerInterface(bytes4 interfaceId)
|
function registerInterface(bytes4 interfaceId) public {
|
||||||
public
|
_registerInterface(interfaceId);
|
||||||
{
|
}
|
||||||
_registerInterface(interfaceId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/ERC20Burnable.sol";
|
import "../token/ERC20/ERC20Burnable.sol";
|
||||||
|
|
||||||
contract ERC20BurnableMock is ERC20Burnable {
|
contract ERC20BurnableMock is ERC20Burnable {
|
||||||
|
constructor (address initialAccount, uint256 initialBalance) public {
|
||||||
constructor(address initialAccount, uint256 initialBalance) public {
|
_mint(initialAccount, initialBalance);
|
||||||
_mint(initialAccount, initialBalance);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/ERC20Mintable.sol";
|
import "../token/ERC20/ERC20Mintable.sol";
|
||||||
import "./MinterRoleMock.sol";
|
import "./MinterRoleMock.sol";
|
||||||
|
|
||||||
contract ERC20MintableMock is ERC20Mintable, MinterRoleMock {
|
contract ERC20MintableMock is ERC20Mintable, MinterRoleMock {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,22 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/ERC20.sol";
|
import "../token/ERC20/ERC20.sol";
|
||||||
|
|
||||||
// mock class using ERC20
|
// mock class using ERC20
|
||||||
contract ERC20Mock is ERC20 {
|
contract ERC20Mock is ERC20 {
|
||||||
|
constructor (address initialAccount, uint256 initialBalance) public {
|
||||||
|
_mint(initialAccount, initialBalance);
|
||||||
|
}
|
||||||
|
|
||||||
constructor(address initialAccount, uint256 initialBalance) public {
|
function mint(address account, uint256 amount) public {
|
||||||
_mint(initialAccount, initialBalance);
|
_mint(account, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mint(address account, uint256 amount) public {
|
function burn(address account, uint256 amount) public {
|
||||||
_mint(account, amount);
|
_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,11 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/ERC20Pausable.sol";
|
import "../token/ERC20/ERC20Pausable.sol";
|
||||||
import "./PauserRoleMock.sol";
|
import "./PauserRoleMock.sol";
|
||||||
|
|
||||||
// mock class using ERC20Pausable
|
// mock class using ERC20Pausable
|
||||||
contract ERC20PausableMock is ERC20Pausable, PauserRoleMock {
|
contract ERC20PausableMock is ERC20Pausable, PauserRoleMock {
|
||||||
|
constructor (address initialAccount, uint initialBalance) public {
|
||||||
constructor(address initialAccount, uint initialBalance) public {
|
_mint(initialAccount, initialBalance);
|
||||||
_mint(initialAccount, initialBalance);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/ERC20.sol";
|
import "../token/ERC20/ERC20.sol";
|
||||||
import "../drafts/ERC1046/TokenMetadata.sol";
|
import "../drafts/ERC1046/TokenMetadata.sol";
|
||||||
|
|
||||||
contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata {
|
contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata {
|
||||||
constructor(string tokenURI) public
|
constructor (string memory tokenURI) public ERC20WithMetadata(tokenURI) {
|
||||||
ERC20WithMetadata(tokenURI)
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
{
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC721/ERC721Full.sol";
|
import "../token/ERC721/ERC721Full.sol";
|
||||||
import "../token/ERC721/ERC721Mintable.sol";
|
import "../token/ERC721/ERC721Mintable.sol";
|
||||||
@ -7,26 +7,23 @@ import "../token/ERC721/ERC721Burnable.sol";
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @title ERC721FullMock
|
* @title ERC721FullMock
|
||||||
* This mock just provides a public mint and burn functions for testing purposes,
|
* This mock just provides public functions for setting metadata URI, getting all tokens of an owner,
|
||||||
* and a public setter for metadata URI
|
* checking token existence, removal of a token from an address
|
||||||
*/
|
*/
|
||||||
contract ERC721FullMock
|
contract ERC721FullMock is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable {
|
||||||
is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable {
|
constructor (string memory name, string memory symbol) public ERC721Mintable() ERC721Full(name, symbol) {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
|
|
||||||
constructor(string name, string symbol) public
|
function exists(uint256 tokenId) public view returns (bool) {
|
||||||
ERC721Mintable()
|
return _exists(tokenId);
|
||||||
ERC721Full(name, symbol)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
function exists(uint256 tokenId) public view returns (bool) {
|
function tokensOfOwner(address owner) public view returns (uint256[] memory) {
|
||||||
return _exists(tokenId);
|
return _tokensOfOwner(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTokenURI(uint256 tokenId, string uri) public {
|
function setTokenURI(uint256 tokenId, string memory uri) public {
|
||||||
_setTokenURI(tokenId, uri);
|
_setTokenURI(tokenId, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeTokenFrom(address from, uint256 tokenId) public {
|
|
||||||
_removeTokenFrom(from, tokenId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC721/ERC721Full.sol";
|
import "../token/ERC721/ERC721Full.sol";
|
||||||
import "../token/ERC721/ERC721Mintable.sol";
|
import "../token/ERC721/ERC721Mintable.sol";
|
||||||
@ -8,13 +8,8 @@ import "../token/ERC721/ERC721Burnable.sol";
|
|||||||
/**
|
/**
|
||||||
* @title ERC721MintableBurnableImpl
|
* @title ERC721MintableBurnableImpl
|
||||||
*/
|
*/
|
||||||
contract ERC721MintableBurnableImpl
|
contract ERC721MintableBurnableImpl is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable {
|
||||||
is ERC721Full, ERC721Mintable, ERC721MetadataMintable, ERC721Burnable {
|
constructor () public ERC721Mintable() ERC721Full("Test", "TEST") {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
constructor()
|
}
|
||||||
ERC721Mintable()
|
|
||||||
ERC721Full("Test", "TEST")
|
|
||||||
public
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC721/ERC721.sol";
|
import "../token/ERC721/ERC721.sol";
|
||||||
|
|
||||||
@ -7,11 +7,15 @@ import "../token/ERC721/ERC721.sol";
|
|||||||
* This mock just provides a public mint and burn functions for testing purposes
|
* This mock just provides a public mint and burn functions for testing purposes
|
||||||
*/
|
*/
|
||||||
contract ERC721Mock is ERC721 {
|
contract ERC721Mock is ERC721 {
|
||||||
function mint(address to, uint256 tokenId) public {
|
function mint(address to, uint256 tokenId) public {
|
||||||
_mint(to, tokenId);
|
_mint(to, tokenId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function burn(uint256 tokenId) public {
|
function burn(address owner, uint256 tokenId) public {
|
||||||
_burn(ownerOf(tokenId), tokenId);
|
_burn(owner, tokenId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function burn(uint256 tokenId) public {
|
||||||
|
_burn(tokenId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC721/ERC721Pausable.sol";
|
import "../token/ERC721/ERC721Pausable.sol";
|
||||||
import "./PauserRoleMock.sol";
|
import "./PauserRoleMock.sol";
|
||||||
@ -8,15 +8,15 @@ import "./PauserRoleMock.sol";
|
|||||||
* This mock just provides a public mint, burn and exists functions for testing purposes
|
* This mock just provides a public mint, burn and exists functions for testing purposes
|
||||||
*/
|
*/
|
||||||
contract ERC721PausableMock is ERC721Pausable, PauserRoleMock {
|
contract ERC721PausableMock is ERC721Pausable, PauserRoleMock {
|
||||||
function mint(address to, uint256 tokenId) public {
|
function mint(address to, uint256 tokenId) public {
|
||||||
super._mint(to, tokenId);
|
super._mint(to, tokenId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function burn(uint256 tokenId) public {
|
function burn(uint256 tokenId) public {
|
||||||
super._burn(ownerOf(tokenId), tokenId);
|
super._burn(tokenId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exists(uint256 tokenId) public view returns (bool) {
|
function exists(uint256 tokenId) public view returns (bool) {
|
||||||
return super._exists(tokenId);
|
return super._exists(tokenId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,41 +1,23 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC721/IERC721Receiver.sol";
|
import "../token/ERC721/IERC721Receiver.sol";
|
||||||
|
|
||||||
contract ERC721ReceiverMock is IERC721Receiver {
|
contract ERC721ReceiverMock is IERC721Receiver {
|
||||||
bytes4 private _retval;
|
bytes4 private _retval;
|
||||||
bool private _reverts;
|
bool private _reverts;
|
||||||
|
|
||||||
event Received(
|
event Received(address operator, address from, uint256 tokenId, bytes data, uint256 gas);
|
||||||
address operator,
|
|
||||||
address from,
|
|
||||||
uint256 tokenId,
|
|
||||||
bytes data,
|
|
||||||
uint256 gas
|
|
||||||
);
|
|
||||||
|
|
||||||
constructor(bytes4 retval, bool reverts) public {
|
constructor (bytes4 retval, bool reverts) public {
|
||||||
_retval = retval;
|
_retval = retval;
|
||||||
_reverts = reverts;
|
_reverts = reverts;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onERC721Received(
|
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
|
||||||
address operator,
|
public returns (bytes4)
|
||||||
address from,
|
{
|
||||||
uint256 tokenId,
|
require(!_reverts);
|
||||||
bytes data
|
emit Received(operator, from, tokenId, data, gasleft());
|
||||||
)
|
return _retval;
|
||||||
public
|
}
|
||||||
returns(bytes4)
|
|
||||||
{
|
|
||||||
require(!_reverts);
|
|
||||||
emit Received(
|
|
||||||
operator,
|
|
||||||
from,
|
|
||||||
tokenId,
|
|
||||||
data,
|
|
||||||
gasleft() // msg.gas was deprecated in solidityv0.4.21
|
|
||||||
);
|
|
||||||
return _retval;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,62 +1,73 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
contract EventEmitter {
|
contract EventEmitter {
|
||||||
event Argumentless();
|
event Argumentless();
|
||||||
event ShortUint(uint8 value);
|
event ShortUint(uint8 value);
|
||||||
event ShortInt(int8 value);
|
event ShortInt(int8 value);
|
||||||
event LongUint(uint256 value);
|
event LongUint(uint256 value);
|
||||||
event LongInt(int256 value);
|
event LongInt(int256 value);
|
||||||
event Address(address value);
|
event Address(address value);
|
||||||
event Boolean(bool value);
|
event Boolean(bool value);
|
||||||
event String(string value);
|
event String(string value);
|
||||||
event LongUintBooleanString(
|
event LongUintBooleanString(uint256 uintValue, bool booleanValue, string stringValue);
|
||||||
uint256 uintValue,
|
|
||||||
bool booleanValue,
|
|
||||||
string stringValue
|
|
||||||
);
|
|
||||||
|
|
||||||
function emitArgumentless() public {
|
constructor (uint8 uintValue, bool booleanValue, string memory stringValue) public {
|
||||||
emit Argumentless();
|
emit ShortUint(uintValue);
|
||||||
}
|
emit Boolean(booleanValue);
|
||||||
|
emit String(stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
function emitShortUint(uint8 value) public {
|
function emitArgumentless() public {
|
||||||
emit ShortUint(value);
|
emit Argumentless();
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitShortInt(int8 value) public {
|
function emitShortUint(uint8 value) public {
|
||||||
emit ShortInt(value);
|
emit ShortUint(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitLongUint(uint256 value) public {
|
function emitShortInt(int8 value) public {
|
||||||
emit LongUint(value);
|
emit ShortInt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitLongInt(int256 value) public {
|
function emitLongUint(uint256 value) public {
|
||||||
emit LongInt(value);
|
emit LongUint(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitAddress(address value) public {
|
function emitLongInt(int256 value) public {
|
||||||
emit Address(value);
|
emit LongInt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitBoolean(bool value) public {
|
function emitAddress(address value) public {
|
||||||
emit Boolean(value);
|
emit Address(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitString(string value) public {
|
function emitBoolean(bool value) public {
|
||||||
emit String(value);
|
emit Boolean(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitLongUintBooleanString(
|
function emitString(string memory value) public {
|
||||||
uint256 uintValue,
|
emit String(value);
|
||||||
bool booleanValue,
|
}
|
||||||
string stringValue)
|
|
||||||
public {
|
|
||||||
emit LongUintBooleanString(uintValue, booleanValue, stringValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
function emitLongUintAndBoolean(uint256 uintValue, bool boolValue) public {
|
function emitLongUintBooleanString(uint256 uintValue, bool booleanValue, string memory stringValue) public {
|
||||||
emit LongUint(uintValue);
|
emit LongUintBooleanString(uintValue, booleanValue, stringValue);
|
||||||
emit Boolean(boolValue);
|
}
|
||||||
}
|
|
||||||
|
function emitLongUintAndBoolean(uint256 uintValue, bool boolValue) public {
|
||||||
|
emit LongUint(uintValue);
|
||||||
|
emit Boolean(boolValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function emitStringAndEmitIndirectly(string memory value, IndirectEventEmitter emitter) public {
|
||||||
|
emit String(value);
|
||||||
|
emitter.emitStringIndirectly(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract IndirectEventEmitter {
|
||||||
|
event IndirectString(string value);
|
||||||
|
|
||||||
|
function emitStringIndirectly(string memory value) public {
|
||||||
|
emit IndirectString(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
contracts/mocks/Failer.sol
Normal file
23
contracts/mocks/Failer.sol
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
contract Failer {
|
||||||
|
uint256[] private array;
|
||||||
|
|
||||||
|
function dontFail() public pure {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
function failWithRevert() public pure {
|
||||||
|
revert();
|
||||||
|
}
|
||||||
|
|
||||||
|
function failWithThrow() public pure {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function failWithOutOfGas() public {
|
||||||
|
for (uint256 i = 0; i < 2**200; ++i) {
|
||||||
|
array.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,21 +1,14 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/IERC20.sol";
|
import "../token/ERC20/IERC20.sol";
|
||||||
import "../crowdsale/distribution/FinalizableCrowdsale.sol";
|
import "../crowdsale/distribution/FinalizableCrowdsale.sol";
|
||||||
|
|
||||||
contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
|
contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
|
||||||
|
constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address payable wallet, IERC20 token)
|
||||||
constructor (
|
public
|
||||||
uint256 openingTime,
|
Crowdsale(rate, wallet, token)
|
||||||
uint256 closingTime,
|
TimedCrowdsale(openingTime, closingTime)
|
||||||
uint256 rate,
|
{
|
||||||
address wallet,
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
IERC20 token
|
}
|
||||||
)
|
|
||||||
public
|
|
||||||
Crowdsale(rate, wallet, token)
|
|
||||||
TimedCrowdsale(openingTime, closingTime)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,22 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../crowdsale/price/IncreasingPriceCrowdsale.sol";
|
import "../crowdsale/price/IncreasingPriceCrowdsale.sol";
|
||||||
import "../math/SafeMath.sol";
|
import "../math/SafeMath.sol";
|
||||||
|
|
||||||
contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale {
|
contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale {
|
||||||
|
constructor (
|
||||||
constructor (
|
uint256 openingTime,
|
||||||
uint256 openingTime,
|
uint256 closingTime,
|
||||||
uint256 closingTime,
|
address payable wallet,
|
||||||
address wallet,
|
IERC20 token,
|
||||||
IERC20 token,
|
uint256 initialRate,
|
||||||
uint256 initialRate,
|
uint256 finalRate
|
||||||
uint256 finalRate
|
)
|
||||||
)
|
public
|
||||||
public
|
Crowdsale(initialRate, wallet, token)
|
||||||
Crowdsale(initialRate, wallet, token)
|
TimedCrowdsale(openingTime, closingTime)
|
||||||
TimedCrowdsale(openingTime, closingTime)
|
IncreasingPriceCrowdsale(initialRate, finalRate)
|
||||||
IncreasingPriceCrowdsale(initialRate, finalRate)
|
{
|
||||||
{
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,11 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/IERC20.sol";
|
import "../token/ERC20/IERC20.sol";
|
||||||
import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol";
|
import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol";
|
||||||
import "./CapperRoleMock.sol";
|
import "./CapperRoleMock.sol";
|
||||||
|
|
||||||
contract IndividuallyCappedCrowdsaleImpl
|
contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale, CapperRoleMock {
|
||||||
is IndividuallyCappedCrowdsale, CapperRoleMock {
|
constructor (uint256 rate, address payable wallet, IERC20 token) public Crowdsale(rate, wallet, token) {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
constructor(
|
}
|
||||||
uint256 rate,
|
|
||||||
address wallet,
|
|
||||||
IERC20 token
|
|
||||||
)
|
|
||||||
public
|
|
||||||
Crowdsale(rate, wallet, token)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../math/Math.sol";
|
import "../math/Math.sol";
|
||||||
|
|
||||||
contract MathMock {
|
contract MathMock {
|
||||||
function max(uint256 a, uint256 b) public pure returns (uint256) {
|
function max(uint256 a, uint256 b) public pure returns (uint256) {
|
||||||
return Math.max(a, b);
|
return Math.max(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
function min(uint256 a, uint256 b) public pure returns (uint256) {
|
function min(uint256 a, uint256 b) public pure returns (uint256) {
|
||||||
return Math.min(a, b);
|
return Math.min(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
function average(uint256 a, uint256 b) public pure returns (uint256) {
|
function average(uint256 a, uint256 b) public pure returns (uint256) {
|
||||||
return Math.average(a, b);
|
return Math.average(a, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,9 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import { MerkleProof } from "../cryptography/MerkleProof.sol";
|
import { MerkleProof } from "../cryptography/MerkleProof.sol";
|
||||||
|
|
||||||
contract MerkleProofWrapper {
|
contract MerkleProofWrapper {
|
||||||
|
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) public pure returns (bool) {
|
||||||
function verify(
|
return MerkleProof.verify(proof, root, leaf);
|
||||||
bytes32[] proof,
|
}
|
||||||
bytes32 root,
|
|
||||||
bytes32 leaf
|
|
||||||
)
|
|
||||||
public
|
|
||||||
pure
|
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
return MerkleProof.verify(proof, root, leaf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,10 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/ERC20Mintable.sol";
|
import "../token/ERC20/ERC20Mintable.sol";
|
||||||
import "../crowdsale/emission/MintedCrowdsale.sol";
|
import "../crowdsale/emission/MintedCrowdsale.sol";
|
||||||
|
|
||||||
contract MintedCrowdsaleImpl is MintedCrowdsale {
|
contract MintedCrowdsaleImpl is MintedCrowdsale {
|
||||||
|
constructor (uint256 rate, address payable wallet, ERC20Mintable token) public Crowdsale(rate, wallet, token) {
|
||||||
constructor (
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
uint256 rate,
|
}
|
||||||
address wallet,
|
|
||||||
ERC20Mintable token
|
|
||||||
)
|
|
||||||
public
|
|
||||||
Crowdsale(rate, wallet, token)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,18 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../access/roles/MinterRole.sol";
|
import "../access/roles/MinterRole.sol";
|
||||||
|
|
||||||
contract MinterRoleMock is MinterRole {
|
contract MinterRoleMock is MinterRole {
|
||||||
function removeMinter(address account) public {
|
function removeMinter(address account) public {
|
||||||
_removeMinter(account);
|
_removeMinter(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onlyMinterMock() public view onlyMinter {
|
function onlyMinterMock() public view onlyMinter {
|
||||||
}
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
|
|
||||||
// Causes a compilation error if super._removeMinter is not internal
|
// Causes a compilation error if super._removeMinter is not internal
|
||||||
function _removeMinter(address account) internal {
|
function _removeMinter(address account) internal {
|
||||||
super._removeMinter(account);
|
super._removeMinter(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
contracts/mocks/OwnableInterfaceId.sol
Normal file
15
contracts/mocks/OwnableInterfaceId.sol
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
import "../ownership/Ownable.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Ownable interface id calculator.
|
||||||
|
* @dev See the EIP165 specification for more information:
|
||||||
|
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md#specification
|
||||||
|
*/
|
||||||
|
contract OwnableInterfaceId {
|
||||||
|
function getInterfaceId() public pure returns (bytes4) {
|
||||||
|
Ownable i;
|
||||||
|
return i.owner.selector ^ i.isOwner.selector ^ i.renounceOwnership.selector ^ i.transferOwnership.selector;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../ownership/Ownable.sol";
|
import "../ownership/Ownable.sol";
|
||||||
|
|
||||||
contract OwnableMock is Ownable {
|
contract OwnableMock is Ownable {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
}
|
}
|
||||||
|
|||||||
10
contracts/mocks/PausableCrowdsaleImpl.sol
Normal file
10
contracts/mocks/PausableCrowdsaleImpl.sol
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
import "../token/ERC20/ERC20.sol";
|
||||||
|
import "../crowdsale/validation/PausableCrowdsale.sol";
|
||||||
|
|
||||||
|
contract PausableCrowdsaleImpl is PausableCrowdsale {
|
||||||
|
constructor (uint256 _rate, address payable _wallet, ERC20 _token) public Crowdsale(_rate, _wallet, _token) {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,24 +1,23 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../lifecycle/Pausable.sol";
|
import "../lifecycle/Pausable.sol";
|
||||||
import "./PauserRoleMock.sol";
|
import "./PauserRoleMock.sol";
|
||||||
|
|
||||||
// mock class using Pausable
|
// mock class using Pausable
|
||||||
contract PausableMock is Pausable, PauserRoleMock {
|
contract PausableMock is Pausable, PauserRoleMock {
|
||||||
bool public drasticMeasureTaken;
|
bool public drasticMeasureTaken;
|
||||||
uint256 public count;
|
uint256 public count;
|
||||||
|
|
||||||
constructor() public {
|
constructor () public {
|
||||||
drasticMeasureTaken = false;
|
drasticMeasureTaken = false;
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalProcess() external whenNotPaused {
|
function normalProcess() external whenNotPaused {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
function drasticMeasure() external whenPaused {
|
|
||||||
drasticMeasureTaken = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
function drasticMeasure() external whenPaused {
|
||||||
|
drasticMeasureTaken = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,18 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../access/roles/PauserRole.sol";
|
import "../access/roles/PauserRole.sol";
|
||||||
|
|
||||||
contract PauserRoleMock is PauserRole {
|
contract PauserRoleMock is PauserRole {
|
||||||
function removePauser(address account) public {
|
function removePauser(address account) public {
|
||||||
_removePauser(account);
|
_removePauser(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onlyPauserMock() public view onlyPauser {
|
function onlyPauserMock() public view onlyPauser {
|
||||||
}
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
|
|
||||||
// Causes a compilation error if super._removePauser is not internal
|
// Causes a compilation error if super._removePauser is not internal
|
||||||
function _removePauser(address account) internal {
|
function _removePauser(address account) internal {
|
||||||
super._removePauser(account);
|
super._removePauser(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,14 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/IERC20.sol";
|
import "../token/ERC20/IERC20.sol";
|
||||||
import "../crowdsale/distribution/PostDeliveryCrowdsale.sol";
|
import "../crowdsale/distribution/PostDeliveryCrowdsale.sol";
|
||||||
|
|
||||||
contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale {
|
contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale {
|
||||||
|
constructor (uint256 openingTime, uint256 closingTime, uint256 rate, address payable wallet, IERC20 token)
|
||||||
constructor (
|
public
|
||||||
uint256 openingTime,
|
TimedCrowdsale(openingTime, closingTime)
|
||||||
uint256 closingTime,
|
Crowdsale(rate, wallet, token)
|
||||||
uint256 rate,
|
{
|
||||||
address wallet,
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
IERC20 token
|
}
|
||||||
)
|
|
||||||
public
|
|
||||||
TimedCrowdsale(openingTime, closingTime)
|
|
||||||
Crowdsale(rate, wallet, token)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../payment/PullPayment.sol";
|
import "../payment/PullPayment.sol";
|
||||||
|
|
||||||
// mock class using PullPayment
|
// mock class using PullPayment
|
||||||
contract PullPaymentMock is PullPayment {
|
contract PullPaymentMock is PullPayment {
|
||||||
|
constructor () public payable {
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
|
|
||||||
constructor() public payable { }
|
// test helper function to call asyncTransfer
|
||||||
|
function callTransfer(address dest, uint256 amount) public {
|
||||||
// test helper function to call asyncTransfer
|
_asyncTransfer(dest, amount);
|
||||||
function callTransfer(address dest, uint256 amount) public {
|
}
|
||||||
_asyncTransfer(dest, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
contract ReentrancyAttack {
|
contract ReentrancyAttack {
|
||||||
|
function callSender(bytes4 data) public {
|
||||||
function callSender(bytes4 data) public {
|
// solhint-disable-next-line avoid-low-level-calls
|
||||||
// solium-disable-next-line security/no-low-level-calls
|
(bool success,) = msg.sender.call(abi.encodeWithSelector(data));
|
||||||
require(msg.sender.call(abi.encodeWithSelector(data)));
|
require(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,44 +1,42 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../utils/ReentrancyGuard.sol";
|
import "../utils/ReentrancyGuard.sol";
|
||||||
import "./ReentrancyAttack.sol";
|
import "./ReentrancyAttack.sol";
|
||||||
|
|
||||||
contract ReentrancyMock is ReentrancyGuard {
|
contract ReentrancyMock is ReentrancyGuard {
|
||||||
|
uint256 public counter;
|
||||||
|
|
||||||
uint256 public counter;
|
constructor () public {
|
||||||
|
counter = 0;
|
||||||
constructor() public {
|
|
||||||
counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function callback() external nonReentrant {
|
|
||||||
count();
|
|
||||||
}
|
|
||||||
|
|
||||||
function countLocalRecursive(uint256 n) public nonReentrant {
|
|
||||||
if (n > 0) {
|
|
||||||
count();
|
|
||||||
countLocalRecursive(n - 1);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function countThisRecursive(uint256 n) public nonReentrant {
|
function callback() external nonReentrant {
|
||||||
if (n > 0) {
|
count();
|
||||||
count();
|
|
||||||
// solium-disable-next-line security/no-low-level-calls
|
|
||||||
bool result = address(this).call(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1));
|
|
||||||
require(result == true);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function countAndCall(ReentrancyAttack attacker) public nonReentrant {
|
function countLocalRecursive(uint256 n) public nonReentrant {
|
||||||
count();
|
if (n > 0) {
|
||||||
bytes4 func = bytes4(keccak256("callback()"));
|
count();
|
||||||
attacker.callSender(func);
|
countLocalRecursive(n - 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function count() private {
|
function countThisRecursive(uint256 n) public nonReentrant {
|
||||||
counter += 1;
|
if (n > 0) {
|
||||||
}
|
count();
|
||||||
|
// solhint-disable-next-line avoid-low-level-calls
|
||||||
|
(bool success,) = address(this).call(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1));
|
||||||
|
require(success);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function countAndCall(ReentrancyAttack attacker) public nonReentrant {
|
||||||
|
count();
|
||||||
|
bytes4 func = bytes4(keccak256("callback()"));
|
||||||
|
attacker.callSender(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
function count() private {
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,22 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/ERC20Mintable.sol";
|
import "../token/ERC20/IERC20.sol";
|
||||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||||
|
|
||||||
contract RefundableCrowdsaleImpl is RefundableCrowdsale {
|
contract RefundableCrowdsaleImpl is RefundableCrowdsale {
|
||||||
|
constructor (
|
||||||
constructor (
|
uint256 openingTime,
|
||||||
uint256 openingTime,
|
uint256 closingTime,
|
||||||
uint256 closingTime,
|
uint256 rate,
|
||||||
uint256 rate,
|
address payable wallet,
|
||||||
address wallet,
|
IERC20 token,
|
||||||
ERC20Mintable token,
|
uint256 goal
|
||||||
uint256 goal
|
)
|
||||||
)
|
public
|
||||||
public
|
Crowdsale(rate, wallet, token)
|
||||||
Crowdsale(rate, wallet, token)
|
TimedCrowdsale(openingTime, closingTime)
|
||||||
TimedCrowdsale(openingTime, closingTime)
|
RefundableCrowdsale(goal)
|
||||||
RefundableCrowdsale(goal)
|
{
|
||||||
{
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
22
contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol
Normal file
22
contracts/mocks/RefundablePostDeliveryCrowdsaleImpl.sol
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
import "../token/ERC20/IERC20.sol";
|
||||||
|
import "../crowdsale/distribution/RefundablePostDeliveryCrowdsale.sol";
|
||||||
|
|
||||||
|
contract RefundablePostDeliveryCrowdsaleImpl is RefundablePostDeliveryCrowdsale {
|
||||||
|
constructor (
|
||||||
|
uint256 openingTime,
|
||||||
|
uint256 closingTime,
|
||||||
|
uint256 rate,
|
||||||
|
address payable wallet,
|
||||||
|
IERC20 token,
|
||||||
|
uint256 goal
|
||||||
|
)
|
||||||
|
public
|
||||||
|
Crowdsale(rate, wallet, token)
|
||||||
|
TimedCrowdsale(openingTime, closingTime)
|
||||||
|
RefundableCrowdsale(goal)
|
||||||
|
{
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,21 +1,21 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../access/Roles.sol";
|
import "../access/Roles.sol";
|
||||||
|
|
||||||
contract RolesMock {
|
contract RolesMock {
|
||||||
using Roles for Roles.Role;
|
using Roles for Roles.Role;
|
||||||
|
|
||||||
Roles.Role private dummyRole;
|
Roles.Role private dummyRole;
|
||||||
|
|
||||||
function add(address account) public {
|
function add(address account) public {
|
||||||
dummyRole.add(account);
|
dummyRole.add(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove(address account) public {
|
function remove(address account) public {
|
||||||
dummyRole.remove(account);
|
dummyRole.remove(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
function has(address account) public view returns (bool) {
|
function has(address account) public view returns (bool) {
|
||||||
return dummyRole.has(account);
|
return dummyRole.has(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,112 +1,108 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../token/ERC20/IERC20.sol";
|
import "../token/ERC20/IERC20.sol";
|
||||||
import "../token/ERC20/SafeERC20.sol";
|
import "../token/ERC20/SafeERC20.sol";
|
||||||
|
|
||||||
contract ERC20FailingMock {
|
contract ERC20FailingMock {
|
||||||
uint256 private _allowance;
|
uint256 private _allowance;
|
||||||
|
|
||||||
function transfer(address, uint256) public returns (bool) {
|
function transfer(address, uint256) public returns (bool) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function transferFrom(address, address, uint256) public returns (bool) {
|
function transferFrom(address, address, uint256) public returns (bool) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function approve(address, uint256) public returns (bool) {
|
function approve(address, uint256) public returns (bool) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function allowance(address, address) public view returns (uint256) {
|
function allowance(address, address) public view returns (uint256) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract ERC20SucceedingMock {
|
contract ERC20SucceedingMock {
|
||||||
mapping (address => uint256) private _allowances;
|
mapping (address => uint256) private _allowances;
|
||||||
|
|
||||||
function transfer(address, uint256) public returns (bool) {
|
function transfer(address, uint256) public returns (bool) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function transferFrom(address, address, uint256) public returns (bool) {
|
function transferFrom(address, address, uint256) public returns (bool) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function approve(address, uint256) public returns (bool) {
|
function approve(address, uint256) public returns (bool) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAllowance(uint256 allowance_) public {
|
function setAllowance(uint256 allowance_) public {
|
||||||
_allowances[msg.sender] = allowance_;
|
_allowances[msg.sender] = allowance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function allowance(address owner, address) public view returns (uint256) {
|
function allowance(address owner, address) public view returns (uint256) {
|
||||||
return _allowances[owner];
|
return _allowances[owner];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract SafeERC20Helper {
|
contract SafeERC20Helper {
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
IERC20 private _failing;
|
IERC20 private _failing;
|
||||||
IERC20 private _succeeding;
|
IERC20 private _succeeding;
|
||||||
|
|
||||||
constructor() public {
|
constructor () public {
|
||||||
_failing = IERC20(new ERC20FailingMock());
|
_failing = IERC20(address(new ERC20FailingMock()));
|
||||||
_succeeding = IERC20(new ERC20SucceedingMock());
|
_succeeding = IERC20(address(new ERC20SucceedingMock()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using _failing
|
function doFailingTransfer() public {
|
||||||
|
_failing.safeTransfer(address(0), 0);
|
||||||
|
}
|
||||||
|
|
||||||
function doFailingTransfer() public {
|
function doFailingTransferFrom() public {
|
||||||
_failing.safeTransfer(address(0), 0);
|
_failing.safeTransferFrom(address(0), address(0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doFailingTransferFrom() public {
|
function doFailingApprove() public {
|
||||||
_failing.safeTransferFrom(address(0), address(0), 0);
|
_failing.safeApprove(address(0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doFailingApprove() public {
|
function doFailingIncreaseAllowance() public {
|
||||||
_failing.safeApprove(address(0), 0);
|
_failing.safeIncreaseAllowance(address(0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doFailingIncreaseAllowance() public {
|
function doFailingDecreaseAllowance() public {
|
||||||
_failing.safeIncreaseAllowance(address(0), 0);
|
_failing.safeDecreaseAllowance(address(0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doFailingDecreaseAllowance() public {
|
function doSucceedingTransfer() public {
|
||||||
_failing.safeDecreaseAllowance(address(0), 0);
|
_succeeding.safeTransfer(address(0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using _succeeding
|
function doSucceedingTransferFrom() public {
|
||||||
|
_succeeding.safeTransferFrom(address(0), address(0), 0);
|
||||||
|
}
|
||||||
|
|
||||||
function doSucceedingTransfer() public {
|
function doSucceedingApprove(uint256 amount) public {
|
||||||
_succeeding.safeTransfer(address(0), 0);
|
_succeeding.safeApprove(address(0), amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doSucceedingTransferFrom() public {
|
function doSucceedingIncreaseAllowance(uint256 amount) public {
|
||||||
_succeeding.safeTransferFrom(address(0), address(0), 0);
|
_succeeding.safeIncreaseAllowance(address(0), amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doSucceedingApprove(uint256 amount) public {
|
function doSucceedingDecreaseAllowance(uint256 amount) public {
|
||||||
_succeeding.safeApprove(address(0), amount);
|
_succeeding.safeDecreaseAllowance(address(0), amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doSucceedingIncreaseAllowance(uint256 amount) public {
|
function setAllowance(uint256 allowance_) public {
|
||||||
_succeeding.safeIncreaseAllowance(address(0), amount);
|
ERC20SucceedingMock(address(_succeeding)).setAllowance(allowance_);
|
||||||
}
|
}
|
||||||
|
|
||||||
function doSucceedingDecreaseAllowance(uint256 amount) public {
|
function allowance() public view returns (uint256) {
|
||||||
_succeeding.safeDecreaseAllowance(address(0), amount);
|
return _succeeding.allowance(address(0), address(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAllowance(uint256 allowance_) public {
|
|
||||||
ERC20SucceedingMock(_succeeding).setAllowance(allowance_);
|
|
||||||
}
|
|
||||||
|
|
||||||
function allowance() public view returns (uint256) {
|
|
||||||
return _succeeding.allowance(address(0), address(0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +1,25 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../math/SafeMath.sol";
|
import "../math/SafeMath.sol";
|
||||||
|
|
||||||
contract SafeMathMock {
|
contract SafeMathMock {
|
||||||
|
function mul(uint256 a, uint256 b) public pure returns (uint256) {
|
||||||
|
return SafeMath.mul(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
function mul(uint256 a, uint256 b) public pure returns (uint256) {
|
function div(uint256 a, uint256 b) public pure returns (uint256) {
|
||||||
return SafeMath.mul(a, b);
|
return SafeMath.div(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
function div(uint256 a, uint256 b) public pure returns (uint256) {
|
function sub(uint256 a, uint256 b) public pure returns (uint256) {
|
||||||
return SafeMath.div(a, b);
|
return SafeMath.sub(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sub(uint256 a, uint256 b) public pure returns (uint256) {
|
function add(uint256 a, uint256 b) public pure returns (uint256) {
|
||||||
return SafeMath.sub(a, b);
|
return SafeMath.add(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
function add(uint256 a, uint256 b) public pure returns (uint256) {
|
function mod(uint256 a, uint256 b) public pure returns (uint256) {
|
||||||
return SafeMath.add(a, b);
|
return SafeMath.mod(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mod(uint256 a, uint256 b) public pure returns (uint256) {
|
|
||||||
return SafeMath.mod(a, b);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../ownership/Secondary.sol";
|
import "../ownership/Secondary.sol";
|
||||||
|
|
||||||
contract SecondaryMock is Secondary {
|
contract SecondaryMock is Secondary {
|
||||||
function onlyPrimaryMock() public view onlyPrimary {
|
function onlyPrimaryMock() public view onlyPrimary {
|
||||||
}
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,73 +1,50 @@
|
|||||||
pragma solidity ^0.4.24;
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
import "../drafts/SignatureBouncer.sol";
|
import "../drafts/SignatureBouncer.sol";
|
||||||
import "./SignerRoleMock.sol";
|
import "./SignerRoleMock.sol";
|
||||||
|
|
||||||
contract SignatureBouncerMock is SignatureBouncer, SignerRoleMock {
|
contract SignatureBouncerMock is SignatureBouncer, SignerRoleMock {
|
||||||
function checkValidSignature(address account, bytes signature)
|
function checkValidSignature(address account, bytes memory signature)
|
||||||
public
|
public view returns (bool)
|
||||||
view
|
{
|
||||||
returns (bool)
|
return _isValidSignature(account, signature);
|
||||||
{
|
}
|
||||||
return _isValidSignature(account, signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onlyWithValidSignature(bytes signature)
|
function onlyWithValidSignature(bytes memory signature)
|
||||||
public
|
public onlyValidSignature(signature) view
|
||||||
onlyValidSignature(signature)
|
{
|
||||||
view
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
{
|
}
|
||||||
|
|
||||||
}
|
function checkValidSignatureAndMethod(address account, bytes memory signature)
|
||||||
|
public view returns (bool)
|
||||||
|
{
|
||||||
|
return _isValidSignatureAndMethod(account, signature);
|
||||||
|
}
|
||||||
|
|
||||||
function checkValidSignatureAndMethod(address account, bytes signature)
|
function onlyWithValidSignatureAndMethod(bytes memory signature)
|
||||||
public
|
public onlyValidSignatureAndMethod(signature) view
|
||||||
view
|
{
|
||||||
returns (bool)
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
{
|
}
|
||||||
return _isValidSignatureAndMethod(account, signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onlyWithValidSignatureAndMethod(bytes signature)
|
function checkValidSignatureAndData(address account, bytes memory, uint, bytes memory signature)
|
||||||
public
|
public view returns (bool)
|
||||||
onlyValidSignatureAndMethod(signature)
|
{
|
||||||
view
|
return _isValidSignatureAndData(account, signature);
|
||||||
{
|
}
|
||||||
|
|
||||||
}
|
function onlyWithValidSignatureAndData(uint, bytes memory signature)
|
||||||
|
public onlyValidSignatureAndData(signature) view
|
||||||
|
{
|
||||||
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
|
}
|
||||||
|
|
||||||
function checkValidSignatureAndData(
|
function theWrongMethod(bytes memory) public pure {
|
||||||
address account,
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
bytes,
|
}
|
||||||
uint,
|
|
||||||
bytes signature
|
|
||||||
)
|
|
||||||
public
|
|
||||||
view
|
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
return _isValidSignatureAndData(account, signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onlyWithValidSignatureAndData(uint, bytes signature)
|
function tooShortMsgData() public onlyValidSignatureAndData("") view {
|
||||||
public
|
// solhint-disable-previous-line no-empty-blocks
|
||||||
onlyValidSignatureAndData(signature)
|
}
|
||||||
view
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function theWrongMethod(bytes)
|
|
||||||
public
|
|
||||||
pure
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function tooShortMsgData()
|
|
||||||
public
|
|
||||||
onlyValidSignatureAndData("")
|
|
||||||
view
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
21
contracts/mocks/SignedSafeMathMock.sol
Normal file
21
contracts/mocks/SignedSafeMathMock.sol
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
pragma solidity ^0.5.0;
|
||||||
|
|
||||||
|
import "../drafts/SignedSafeMath.sol";
|
||||||
|
|
||||||
|
contract SignedSafeMathMock {
|
||||||
|
function mul(int256 a, int256 b) public pure returns (int256) {
|
||||||
|
return SignedSafeMath.mul(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function div(int256 a, int256 b) public pure returns (int256) {
|
||||||
|
return SignedSafeMath.div(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sub(int256 a, int256 b) public pure returns (int256) {
|
||||||
|
return SignedSafeMath.sub(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function add(int256 a, int256 b) public pure returns (int256) {
|
||||||
|
return SignedSafeMath.add(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user