Compare commits
445 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e65947efb | |||
| 59cb2e2d0f | |||
| 418a6b5791 | |||
| 3806d6128e | |||
| 4d799f3cbe | |||
| 07a27f0e5e | |||
| ca9e317259 | |||
| 9638ecd87a | |||
| 56735a706c | |||
| 2765350248 | |||
| 1200969eb6 | |||
| 90b98a7bef | |||
| 16429b1522 | |||
| ae2980b072 | |||
| f5b0bb3246 | |||
| 4c6575bf2f | |||
| 2f6c8b05f6 | |||
| 567b773242 | |||
| 6e19ed47be | |||
| e6c15b34da | |||
| afe9113b18 | |||
| 73be06412f | |||
| 23074676c4 | |||
| 3c69cf658c | |||
| 6bd8842ab5 | |||
| d20d03c149 | |||
| ebd4b5e73d | |||
| 1ecda54449 | |||
| 67b67b791e | |||
| ce0c3274ee | |||
| 90b3050ad7 | |||
| c95ea5125d | |||
| 11266b0d56 | |||
| 45d6943913 | |||
| 5f6d511af9 | |||
| 7dbb7a8b8e | |||
| 3318b91697 | |||
| cea2a85a42 | |||
| 99e4b081dc | |||
| b120b9aff7 | |||
| cc9fa57777 | |||
| 40b5594f52 | |||
| 4575a240f7 | |||
| eb4dfea6e9 | |||
| 8fd072cf8e | |||
| c2ad8c3f57 | |||
| fd253d6b8d | |||
| 7d8e3ca8b2 | |||
| 6b37ba36a1 | |||
| dc1e352cc4 | |||
| f18c3bc438 | |||
| 0047e79681 | |||
| 74a62a1314 | |||
| 92b695f2fb | |||
| ee78f67985 | |||
| 07020e9544 | |||
| b4406d385f | |||
| 78e39aa2ad | |||
| e4ed8f0705 | |||
| 5daaf60d11 | |||
| e1dc1411fc | |||
| 9f1d294ba4 | |||
| 9951acf6d8 | |||
| 72792a724d | |||
| b0292cf628 | |||
| 39385f9f4e | |||
| 7a61371b19 | |||
| 259b9da3e6 | |||
| 5326e7c36e | |||
| feb665136c | |||
| 7fb84b42d5 | |||
| 5db0d7d1a0 | |||
| 512e8218ca | |||
| 9d6ffae8cb | |||
| 2a997a8e92 | |||
| 5651538045 | |||
| 10e84aecaf | |||
| 2637bd89be | |||
| 32ec8b5398 | |||
| a0c03ee61c | |||
| e3f866c982 | |||
| 5ab9024b6a | |||
| d5f06ab32f | |||
| 746673a94f | |||
| ba4cf03da7 | |||
| 39370ff690 | |||
| ad12381549 | |||
| 20b85be6aa | |||
| 4223c9d50e | |||
| f0eea31bdf | |||
| ce0a928a6c | |||
| 85f079ee89 | |||
| 7e44204d9b | |||
| 4a10f727c4 | |||
| e79dc645e4 | |||
| 0e5799c93b | |||
| 90413e75f1 | |||
| 9c262571ae | |||
| 76fe1548ae | |||
| 8f2a4785cb | |||
| 16535fbb87 | |||
| 77cc33fc5c | |||
| 0b33d29e41 | |||
| 61dfdde6c4 | |||
| e8be9a7bd0 | |||
| dd8758fedf | |||
| c63b203c1d | |||
| c191757c6e | |||
| f4bdaf49a1 | |||
| 6a7114fdb4 | |||
| 0926729c8f | |||
| 9e1c934ffd | |||
| a7e91856f3 | |||
| 06666be93a | |||
| 915f74c5f6 | |||
| 3d3f20f7e3 | |||
| 03a3302abd | |||
| bd5f7f5774 | |||
| a6bef44790 | |||
| a9c777faa6 | |||
| 44a404aae5 | |||
| 1d2d18f9da | |||
| 82ce197e44 | |||
| 42787e2a75 | |||
| 9bc43c8d0f | |||
| cacf03641c | |||
| e96164feea | |||
| 9f52e94339 | |||
| c9936e231d | |||
| e299a7950e | |||
| b33260ac44 | |||
| 3fb8ecad76 | |||
| c3cbdb4599 | |||
| 7586e383c2 | |||
| d1146e8c8b | |||
| 8d4eee412d | |||
| 903751ce0d | |||
| 9fd61177c3 | |||
| 3c48912730 | |||
| b3a8602928 | |||
| 5ef8554727 | |||
| 9ea4bae313 | |||
| c05918c3cc | |||
| 108d5f3b4a | |||
| 61b6a733c8 | |||
| 6ad275befb | |||
| 7a0bfdfbb4 | |||
| f4228f1b49 | |||
| a5d5867092 | |||
| 4d7c3cca75 | |||
| 0541347034 | |||
| c5d66183ab | |||
| 1eea95f9ac | |||
| e16c4042c1 | |||
| e1d32acae8 | |||
| 3b499a9cc3 | |||
| 4e77aaa0c3 | |||
| 4be30dc3ae | |||
| 370e6a882a | |||
| 9cc55ef2a5 | |||
| 48594890cf | |||
| 6979e3c83a | |||
| 96e0d35f11 | |||
| 66402e9fec | |||
| 5b40202dd3 | |||
| da95df6be5 | |||
| 250572f48d | |||
| ff9e9c4d85 | |||
| c8c0f21a3f | |||
| 3a9a2c8888 | |||
| a5ea0af65c | |||
| 42553ec0c0 | |||
| c01203b0b7 | |||
| 9d005b492d | |||
| 22c1403e5b | |||
| 3009553925 | |||
| 5ea9bd44a1 | |||
| 51c2c50437 | |||
| 52b6181d78 | |||
| fe712c678a | |||
| c70ee937e6 | |||
| 46736da489 | |||
| 82c85121bb | |||
| e5960465a7 | |||
| 5716492ebd | |||
| c7807c5b58 | |||
| 433213537f | |||
| 560a855dc7 | |||
| 80ae074c57 | |||
| d808e49b51 | |||
| a8afb20c20 | |||
| a613cd03c9 | |||
| b709206f9f | |||
| 2a560ad82f | |||
| 4fe2157e36 | |||
| 5a42a450ac | |||
| 49adfea68b | |||
| a29fce9cbd | |||
| 7f591a9181 | |||
| 23afc74b59 | |||
| dcf1f8d22d | |||
| c7f2138da1 | |||
| b67856c69d | |||
| 4fbd44fd40 | |||
| 2887393712 | |||
| af337047a4 | |||
| b0522b9c58 | |||
| 969466b8fd | |||
| 2b008f4cb6 | |||
| d060d29912 | |||
| 75439c1dd3 | |||
| c8878adcbd | |||
| d95c3ade8f | |||
| 7811370000 | |||
| b1e1aadba1 | |||
| 7ddd66fb74 | |||
| 0cdc5e13ce | |||
| 5b50e99a0d | |||
| b09d7aada4 | |||
| 5fc5ded661 | |||
| 146a22cd96 | |||
| b925b2dae6 | |||
| 87f5916341 | |||
| 8854966847 | |||
| 685d2087ca | |||
| 7532dab17d | |||
| 73a8be1449 | |||
| c9fff647f4 | |||
| ec2f7ba8d1 | |||
| a4029e7472 | |||
| ad5edd329f | |||
| 955517dc2e | |||
| 3b48a671fd | |||
| bd2f1773cd | |||
| e60aee61f2 | |||
| b2e2d9ab1c | |||
| 4d263b7fc3 | |||
| e0f3fea97f | |||
| d4dc4b25c8 | |||
| c1244d6297 | |||
| 462c52bcbf | |||
| 9f68c00855 | |||
| 4dcf8f5bd0 | |||
| ea1cb5c54e | |||
| 49b42e8696 | |||
| beea818f4e | |||
| 13b75bd5af | |||
| e911b4d556 | |||
| 7bd95b1e31 | |||
| 4ecdf312df | |||
| f36f8e96dc | |||
| e57f4be1fb | |||
| a806520d6f | |||
| a4b1cd6e31 | |||
| 21297e2b2c | |||
| 94697726f5 | |||
| a58e3e151a | |||
| 790b3b20c2 | |||
| ed6e51494e | |||
| 17884e91a1 | |||
| 59cd714b84 | |||
| a24031854b | |||
| 6cd84ffceb | |||
| 29edd4e15e | |||
| 6af6efc198 | |||
| 586c88802d | |||
| edbc64f337 | |||
| c73861d8b3 | |||
| d78bcbbae5 | |||
| 326df13bf3 | |||
| 7852583fde | |||
| 5993f5b371 | |||
| 04946211a5 | |||
| 2f2ef68652 | |||
| ebdba08218 | |||
| a74b7bd4b1 | |||
| 090e2fca16 | |||
| dbe8898d00 | |||
| 52b2a619c7 | |||
| 58ecbd6104 | |||
| 9aa61ad273 | |||
| 7aa6f21147 | |||
| 323d1fa941 | |||
| 4073cf6585 | |||
| 4ce0e211c5 | |||
| 9af6ad5ddf | |||
| 2f336f7aaf | |||
| 5751eac444 | |||
| cda518d353 | |||
| f446f5c5cd | |||
| 1455a5a942 | |||
| 207b92f63c | |||
| b217ef6314 | |||
| 687dc19a4a | |||
| 161f25fc12 | |||
| 4bb26c32b6 | |||
| d91f4d4bc1 | |||
| ddcae6254e | |||
| fdfd90e6a4 | |||
| f162638cde | |||
| 8375b6085f | |||
| 83b941c76c | |||
| 63c8751e06 | |||
| 306132f823 | |||
| 677d05743c | |||
| aef0f63aee | |||
| 5e55569db6 | |||
| 9bb2c958ec | |||
| e931c1cbfc | |||
| dd1fd0002a | |||
| ac3808885a | |||
| 258c001f7f | |||
| d07bdccc0c | |||
| 227a335399 | |||
| 58abd66969 | |||
| 8662846838 | |||
| 6ea0577bfe | |||
| b9b26e1d8a | |||
| 887c1bb925 | |||
| cc5e898250 | |||
| 1cef36b5c0 | |||
| c95be493c3 | |||
| bddc8755c1 | |||
| 3ad555bb01 | |||
| 846b0714ad | |||
| f79f7b00e3 | |||
| 47585b1117 | |||
| b7e7c765e0 | |||
| 9e1da49f23 | |||
| c29dd086d3 | |||
| b9cbea1c9c | |||
| b254b74b87 | |||
| bb1736e376 | |||
| 11349835e9 | |||
| c6e0edb268 | |||
| b50391862c | |||
| 0bcf0a2001 | |||
| 0eaa5f50ac | |||
| ce86029f6a | |||
| 815d9e1f45 | |||
| e6213767fa | |||
| f28c245a3c | |||
| 12303ceaf5 | |||
| 9001ce9d3a | |||
| 492ef4a419 | |||
| 5f67dd7868 | |||
| 3c5a268da4 | |||
| db5a12cfdd | |||
| 03ad0efd29 | |||
| 5fc53b6f2f | |||
| 99f3e26f83 | |||
| 151371cc86 | |||
| 376208bd96 | |||
| 11b63d4fc1 | |||
| 39ae5b4cca | |||
| 670b843b63 | |||
| 070d25dc9e | |||
| 9684ce76c5 | |||
| d919f0dde2 | |||
| 689e18aab5 | |||
| 8765e2a53f | |||
| 7a19bcf6d9 | |||
| 088897150e | |||
| 34be16d939 | |||
| 14ae881e26 | |||
| 666a3a73e0 | |||
| 84bffb854a | |||
| 365c875ced | |||
| 7dd0ee6212 | |||
| 7123faff9f | |||
| 61b5921ab2 | |||
| e72c7ce91b | |||
| c4ca7f03e3 | |||
| 9be77ddd54 | |||
| 70a17d0b96 | |||
| ad2282456e | |||
| fe3e360483 | |||
| 5a857fc1a7 | |||
| c5cd35b2ea | |||
| a808b0b03f | |||
| 4e8f422a81 | |||
| 070226d624 | |||
| 2413f83504 | |||
| be692e59eb | |||
| e74652415f | |||
| 5ad07e1892 | |||
| 575372f660 | |||
| 7a26a0ecf1 | |||
| 8e01dd14f9 | |||
| 5088c64140 | |||
| ac4a19dd7d | |||
| 09b1926c41 | |||
| d7b67eca52 | |||
| e4427befbb | |||
| ca1babe1f7 | |||
| 1d54b86a7c | |||
| 2d83c557b1 | |||
| dfb9ebd647 | |||
| b60e434e0b | |||
| 39d6c92069 | |||
| eb9f88bafc | |||
| aa431dfb20 | |||
| fff8e040b7 | |||
| 74636b7333 | |||
| 647fc13963 | |||
| d5e0714faf | |||
| a184013d1e | |||
| 7d08c4da7f | |||
| 01b92d1d56 | |||
| 790833e5d4 | |||
| 2cb2799a51 | |||
| 9dcf37dd19 | |||
| 0d89e99ceb | |||
| a5a1be7219 | |||
| 5aba967db9 | |||
| ffd1090718 | |||
| 22b9263674 | |||
| d21d35ca6f | |||
| 4e39f50aec | |||
| 9e0e80e820 | |||
| 562fb6945f | |||
| 822de45bfc | |||
| bd56163900 | |||
| 696615d392 | |||
| 645edfc936 | |||
| a227b212f5 | |||
| c11265e694 | |||
| 6344a76f83 | |||
| 3da7c31484 | |||
| 998c72ab5b | |||
| 00f323d132 | |||
| 80e591f487 | |||
| 1333f45cdc | |||
| 2ad88b59f6 | |||
| a9055f5ce2 | |||
| 9b0e89c4bf | |||
| 27f8609ac9 | |||
| 5cf503673f | |||
| 3837319141 | |||
| e70dd18734 | |||
| 158a7a881d | |||
| 3733c069c9 | |||
| dc1017c929 | |||
| 69e83e5086 | |||
| 8336785a9b |
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@ -0,0 +1,12 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
5
.env.example
Normal file
5
.env.example
Normal file
@ -0,0 +1,5 @@
|
||||
# configure your infura api key (not technically required)
|
||||
INFURA_API_KEY=
|
||||
|
||||
# change the mnemonic that your hd wallet is seeded with
|
||||
MNEMONIC=
|
||||
54
.eslintrc
Normal file
54
.eslintrc
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"extends" : [
|
||||
"standard",
|
||||
"plugin:promise/recommended"
|
||||
],
|
||||
"plugins": [
|
||||
"promise"
|
||||
],
|
||||
"env": {
|
||||
"browser" : true,
|
||||
"node" : true,
|
||||
"mocha" : true,
|
||||
"jest" : true
|
||||
},
|
||||
"globals" : {
|
||||
"artifacts": false,
|
||||
"contract": false,
|
||||
"assert": false,
|
||||
"web3": false
|
||||
},
|
||||
"rules": {
|
||||
|
||||
// Strict mode
|
||||
"strict": ["error", "global"],
|
||||
|
||||
// Code style
|
||||
"camelcase": ["error", {"properties": "always"}],
|
||||
"comma-dangle": ["warn", "always-multiline"],
|
||||
"comma-spacing": ["error", {"before": false, "after": true}],
|
||||
"dot-notation": ["error", {"allowKeywords": true, "allowPattern": ""}],
|
||||
"eol-last": ["error", "always"],
|
||||
"eqeqeq": ["error", "smart"],
|
||||
"generator-star-spacing": ["error", "before"],
|
||||
"indent": ["error", 2],
|
||||
"max-len": ["error", 120, 2],
|
||||
"no-debugger": "off",
|
||||
"no-dupe-args": "error",
|
||||
"no-dupe-keys": "error",
|
||||
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
|
||||
"no-redeclare": ["error", {"builtinGlobals": true}],
|
||||
"no-trailing-spaces": ["error", { "skipBlankLines": false }],
|
||||
"no-undef": "error",
|
||||
"no-use-before-define": "off",
|
||||
"no-var": "error",
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"prefer-const": "error",
|
||||
"quotes": ["error", "single"],
|
||||
"semi": ["error", "always"],
|
||||
"space-before-function-paren": ["error", "always"],
|
||||
|
||||
"promise/always-return": "off",
|
||||
"promise/avoid-new": "off",
|
||||
}
|
||||
}
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.sol linguist-language=Solidity
|
||||
34
.github/ISSUE_TEMPLATE.md
vendored
Normal file
34
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
## 🎉 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. -->
|
||||
17
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
17
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<!-- 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. -->
|
||||
|
||||
Fixes #
|
||||
|
||||
# 🚀 Description
|
||||
|
||||
<!-- 2. Describe the changes introduced in this pull request -->
|
||||
<!-- Include any context necessary for understanding the PR's purpose. -->
|
||||
|
||||
<!-- 3. Before submitting, please review the following checklist: -->
|
||||
|
||||
- [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](../blob/master/CONTRIBUTING.md)
|
||||
- [ ] ✅ I've added tests where applicable to test my new functionality.
|
||||
- [ ] 📖 I've made sure that my contracts are well-documented.
|
||||
- [ ] 🎨 I've run the JS/Solidity linters and fixed any issues (`npm run lint:all:fix`).
|
||||
40
.gitignore
vendored
40
.gitignore
vendored
@ -1,9 +1,39 @@
|
||||
*.swp
|
||||
*.swo
|
||||
node_modules/
|
||||
build/
|
||||
.DS_Store/
|
||||
/coverage
|
||||
coverage.json
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
allFiredEvents
|
||||
scTopics
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
coverage.json
|
||||
coverageEnv
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Dependency directory
|
||||
node_modules
|
||||
|
||||
# Debug log from npm
|
||||
npm-debug.log
|
||||
|
||||
# local env variables
|
||||
.env
|
||||
|
||||
# truffle build directory
|
||||
build/
|
||||
|
||||
# lol macs
|
||||
.DS_Store/
|
||||
|
||||
# truffle
|
||||
.node-xmlhttprequest-*
|
||||
|
||||
48
.jshintrc
48
.jshintrc
@ -1,48 +0,0 @@
|
||||
{
|
||||
"bitwise": false, // Prohibit bitwise operators (&, |, ^, etc.).
|
||||
"browser": true, // Standard browser globals e.g. `window`, `document`.
|
||||
"camelcase": false, // Permit only camelcase for `var` and `object indexes`.
|
||||
"curly": true, // Require {} for every new block or scope.
|
||||
"devel": false, // Allow development statements e.g. `console.log();`.
|
||||
"eqeqeq": true, // Require triple equals i.e. `===`.
|
||||
"esnext": true, // Allow ES.next specific features such as `const` and `let`.
|
||||
"freeze": true, // Forbid overwriting prototypes of native objects such as Array, Date and so on.
|
||||
"immed": true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
|
||||
"indent": 2, // Specify indentation spacing
|
||||
"latedef": true, // Prohibit variable use before definition.
|
||||
"newcap": false, // Require capitalization of all constructor functions e.g. `new F()`.
|
||||
"noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`.
|
||||
"node": true, // Enable globals available when code is running inside of the NodeJS runtime environment.
|
||||
"noempty": true, // Prohibit use of empty blocks.
|
||||
"nonew": true, // Prohibits the use of constructor functions for side-effects
|
||||
"quotmark": "single", // Define quotes to string values.
|
||||
"regexp": true, // Prohibit `.` and `[^...]` in regular expressions.
|
||||
"smarttabs": false, // Supress warnings about mixed tabs and spaces
|
||||
"strict": true, // Require `use strict` pragma in every file.
|
||||
"trailing": true, // Prohibit trailing whitespaces.
|
||||
"undef": true, // Require all non-global variables be declared before they are used.
|
||||
"unused": true, // Warn unused variables.
|
||||
|
||||
"maxparams": 4, // Maximum number of parameters for a function
|
||||
"maxstatements": 15, // Maximum number of statements in a function
|
||||
"maxcomplexity": 10, // Cyclomatic complexity (http://en.wikipedia.org/wiki/Cyclomatic_complexity)
|
||||
"maxdepth": 4, // Maximum depth of nested control structures
|
||||
"maxlen": 120, // Maximum number of cols in a line
|
||||
"multistr": true, // Allow use of multiline EOL escaping
|
||||
"experimental": ["asyncawait", "asyncreqawait"],
|
||||
|
||||
"predef": [ // Extra globals.
|
||||
"after",
|
||||
"afterEach",
|
||||
"before",
|
||||
"beforeEach",
|
||||
"define",
|
||||
"describe",
|
||||
"exports",
|
||||
"it",
|
||||
"web3",
|
||||
"artifacts",
|
||||
"contract",
|
||||
"assert"
|
||||
]
|
||||
}
|
||||
1
.node-version
Normal file
1
.node-version
Normal file
@ -0,0 +1 @@
|
||||
v8.9.1
|
||||
@ -1,5 +1,9 @@
|
||||
module.exports = {
|
||||
norpc: true,
|
||||
testCommand: 'node --max-old-space-size=4096 ../node_modules/.bin/truffle test --network coverage',
|
||||
skipFiles: ['lifecycle/Migrations.sol']
|
||||
compileCommand: 'node --max-old-space-size=4096 ../node_modules/.bin/truffle compile --network coverage',
|
||||
skipFiles: [
|
||||
'lifecycle/Migrations.sol',
|
||||
'mocks'
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,22 +1,17 @@
|
||||
{
|
||||
"custom-rules-filename": null,
|
||||
"extends": "solium:all",
|
||||
"plugins": ["security"],
|
||||
"rules": {
|
||||
"imports-on-top": true,
|
||||
"variable-declarations": true,
|
||||
"array-declarations": true,
|
||||
"operator-whitespace": true,
|
||||
"lbrace": true,
|
||||
"mixedcase": false,
|
||||
"camelcase": true,
|
||||
"uppercase": true,
|
||||
"no-with": true,
|
||||
"no-empty-blocks": true,
|
||||
"no-unused-vars": true,
|
||||
"double-quotes": true,
|
||||
"blank-lines": true,
|
||||
"indentation": true,
|
||||
"whitespace": true,
|
||||
"deprecated-suicide": true,
|
||||
"pragma-on-top": true
|
||||
"error-reason": "off",
|
||||
"indentation": ["error", 2],
|
||||
"max-len": ["warning", 79],
|
||||
"no-constant": ["error"],
|
||||
"no-empty-blocks": "off",
|
||||
"quotes": ["error", "double"],
|
||||
"uppercase": "off",
|
||||
|
||||
"security/enforce-explicit-visibility": ["error"],
|
||||
"security/no-block-members": ["warning"],
|
||||
"security/no-inline-assembly": ["warning"]
|
||||
}
|
||||
}
|
||||
|
||||
20
.travis.yml
20
.travis.yml
@ -3,15 +3,29 @@ sudo: required
|
||||
group: beta
|
||||
language: node_js
|
||||
node_js:
|
||||
- "6"
|
||||
- "8"
|
||||
cache:
|
||||
yarn: true
|
||||
directories:
|
||||
- node_modules
|
||||
env:
|
||||
-
|
||||
- SOLIDITY_COVERAGE=true
|
||||
- SOLC_NIGHTLY=true
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- env: SOLIDITY_COVERAGE=true
|
||||
- env: SOLC_NIGHTLY=true
|
||||
before_script:
|
||||
- truffle version
|
||||
script:
|
||||
- yarn test
|
||||
- npm run lint
|
||||
- npm run lint:sol
|
||||
- npm run test
|
||||
notifications:
|
||||
slack:
|
||||
rooms:
|
||||
- secure: uEhwUkuwJp5pBNh+VTEytPHz3FDKsnPrKO+8MTAKv5hKi4PCRoVhLv6pklr82HUpL6pvSvJbUPA0HVebOXA+MMSxdny/BHZTh2mtw5Y78l2Ad0svDTWuV2Lus2pmhYigRhT0Wo00/SRX9+pxm0kg4EIFJSTS+uR9G76x0l9NljpEGXrqxlDxjxoHBgk8Ciru2LHaLzX/utE3jlABts4Sb1F3wc2BwFkjd6BDCRTGAPhVJwwFk41ZfnmLVbgSNUyk46Cb38oG5oXHb0FI3d3jV/k1OUhRyFfmA2fLXRk0wavibW8TG1gGJJWZ7xTCKzw/Cvup6mpehSAeQef8eekMdjpWEhF9hYRq1BvOs0384UU8NQ0O+BtdXU+X3Nyr84TMJN/iIfgN7gYX7AsvXH3jC0JfNUcIkWlJvyXdE6l2GV1hMmhL09GFEBbSpuSXRIWlOXTcYBlp5NbvE8xO8PUW+T6N5RG2XXjv1g8wCpr6Wwk1+LmRkX5trv8MFBZ2pM8p4H5da5++Ov8egLonNGK2jbx6aBLBX3tPf+g70LZEkiQ4eBfZw8VIgXIvKreisicppNuCD27gNmSEPNt0NkwiEBcTCJ9GSVAO0CU2g4ggvHDX2A+RW5XPET9bGkBXKLfFyV7Qe+MSQjXkCnW3bIRh7Wo1V31XiUiYOLuZPIiH3EQ=
|
||||
on_success: change
|
||||
on_failure: always
|
||||
on_pull_requests: false
|
||||
|
||||
73
CODE_OF_CONDUCT.md
Normal file
73
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,73 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at maintainers@openzeppelin.org. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
121
CONTRIBUTING.md
121
CONTRIBUTING.md
@ -1,107 +1,58 @@
|
||||
Contributing to Zeppelin
|
||||
Contributing to OpenZeppelin
|
||||
=======
|
||||
|
||||
## Design Guidelines
|
||||
We really appreciate and value contributions to OpenZeppelin. Please take 5' to review the items listed below to make sure that your contributions are merged as soon as possible.
|
||||
|
||||
These are some global design goals in Zeppelin.
|
||||
## Contribution guidelines
|
||||
|
||||
### D0 - Security in Depth
|
||||
We strive to provide secure, tested, audited code. To achieve this, we need to match intention with function. Thus, documentation, code clarity, community review and security discussions are fundamental.
|
||||
Smart contracts manage value and are highly vulnerable to errors and attacks. We have very strict guidelines, please make sure to review them: ["Contribution guidelines wiki entry"](https://github.com/OpenZeppelin/openzeppelin-solidity/wiki/Contribution-guidelines).
|
||||
|
||||
### D1 - Simple and Modular
|
||||
Simpler code means easier audits, and better understanding of what each component does. We look for small files, small contracts, and small functions. If you can separate a contract into two independent functionalities you should probably do it.
|
||||
## Creating Pull Requests (PRs)
|
||||
|
||||
### D2 - Naming Matters
|
||||
As a contributor, you are expected to fork this repository, work on your own fork and then submit pull requests. The pull requests will be reviewed and eventually merged into the main repo. See ["Fork-a-Repo"](https://help.github.com/articles/fork-a-repo/) for how this works.
|
||||
|
||||
We take our time with picking names. Code is going to be written once, and read hundreds of times. Renaming for clarity is encouraged.
|
||||
*IMPORTANT*
|
||||
* Please see ["Git flow wiki entry"](https://github.com/OpenZeppelin/openzeppelin-solidity/wiki/Git-flow) for understanding how to use branches in this repository.
|
||||
|
||||
### D3 - Tests
|
||||
## A typical workflow
|
||||
|
||||
Write tests for all your code. We encourage Test Driven Development so we know when our code is right. Even though not all code in the repository is tested at the moment, we aim to test every line of code in the future.
|
||||
1) Make sure your fork is up to date with the main repository:
|
||||
|
||||
### D4 - Check preconditions and post-conditions
|
||||
```
|
||||
cd openzeppelin-solidity
|
||||
git remote add upstream https://github.com/OpenZeppelin/openzeppelin-solidity.git
|
||||
git fetch upstream
|
||||
git pull --rebase upstream master
|
||||
```
|
||||
NOTE: The directory `openzeppelin-solidity` represents your fork's local copy.
|
||||
|
||||
A very important way to prevent vulnerabilities is to catch a contract’s inconsistent state as early as possible. This is why we want functions to check pre- and post-conditions for executing its logic. When writing code, ask yourself what you are expecting to be true before and after the function runs, and express it in code.
|
||||
|
||||
### D5 - Code Consistency
|
||||
|
||||
Consistency on the way classes are used is paramount to an easier understanding of the library. The codebase should be as unified as possible. Read existing code and get inspired before you write your own. Follow the style guidelines. Don’t hesitate to ask for help on how to best write a specific piece of code.
|
||||
|
||||
### D6 - Regular Audits
|
||||
Following good programming practices is a way to reduce the risk of vulnerabilities, but professional code audits are still needed. We will perform regular code audits on major releases, and hire security professionals to provide independent review.
|
||||
|
||||
## Style Guidelines
|
||||
|
||||
The design guidelines have quite a high abstraction level. These style guidelines are more concrete and easier to apply, and also more opinionated.
|
||||
|
||||
### General
|
||||
|
||||
#### G0 - Default to Solidity's official style guide.
|
||||
|
||||
Follow the official Solidity style guide: http://solidity.readthedocs.io/en/latest/style-guide.html
|
||||
|
||||
#### G1 - No Magic Constants
|
||||
|
||||
Avoid constants in the code as much as possible. Magic strings are also magic constants.
|
||||
|
||||
#### G2 - Code that Fails Early
|
||||
|
||||
We ask our code to fail as soon as possible when an unexpected input was provided or unexpected state was found.
|
||||
|
||||
#### G3 - Internal Amounts Must be Signed Integers and Represent the Smallest Units.
|
||||
|
||||
Avoid representation errors by always dealing with weis when handling ether. GUIs can convert to more human-friendly representations. Use Signed Integers (int) to prevent underflow problems.
|
||||
|
||||
|
||||
### Testing
|
||||
|
||||
#### T1 - Tests Must be Written Elegantly
|
||||
|
||||
Style guidelines are not relaxed for tests. Tests are a good way to show how to use the library, and maintaining them is extremely necessary.
|
||||
|
||||
Don't write long tests, write helper functions to make them be as short and concise as possible (they should take just a few lines each), and use good variable names.
|
||||
|
||||
#### T2 - Tests Must not be Random
|
||||
|
||||
Inputs for tests should not be generated randomly. Accounts used to create test contracts are an exception, those can be random. Also, the type and structure of outputs should be checked.
|
||||
|
||||
|
||||
### Documentation
|
||||
|
||||
TODO
|
||||
|
||||
## Pull Request Workflow
|
||||
|
||||
Our workflow is based on GitHub's pull requests. We use feature branches, prepended with: `test`, `feature`, `fix`, `refactor`, or `remove` according to the change the branch introduces. Some examples for such branches are:
|
||||
```sh
|
||||
git checkout -b test/some-module
|
||||
git checkout -b feature/some-new-stuff
|
||||
git checkout -b fix/some-bug
|
||||
git checkout -b remove/some-file
|
||||
2) Branch out from `master` into `fix/some-bug-#123`:
|
||||
(Postfixing #123 will associate your PR with the issue #123 and make everyone's life easier =D)
|
||||
```
|
||||
git checkout -b fix/some-bug-#123
|
||||
```
|
||||
|
||||
We expect pull requests to be rebased to the master branch before merging:
|
||||
```sh
|
||||
git remote add zep git@github.com:OpenZeppelin/zeppelin-solidity.git
|
||||
git pull --rebase zep master
|
||||
3) Make your changes, add your files, commit and push to your fork.
|
||||
|
||||
```
|
||||
git add SomeFile.js
|
||||
git commit "Fix some bug #123"
|
||||
git push origin fix/some-bug-#123
|
||||
```
|
||||
|
||||
Note that we require rebasing your branch instead of merging it, for commit readability reasons.
|
||||
4) Go to [github.com/OpenZeppelin/openzeppelin-solidity](https://github.com/OpenZeppelin/zeppelin-solidity) in your web browser and issue a new pull request.
|
||||
|
||||
After that, you can push the changes to your fork, by doing:
|
||||
```sh
|
||||
git push origin your_branch_name
|
||||
git push origin feature/some-new-stuff
|
||||
git push origin fix/some-bug
|
||||
```
|
||||
*IMPORTANT* Read the PR template very carefully and make sure to follow all the instructions. These instructions
|
||||
refer to some very important conditions that your PR must meet in order to be accepted, such as making sure that all tests pass, JS linting tests pass, solidity linting tests pass, etc.
|
||||
|
||||
Finally go to [github.com/OpenZeppelin/zeppelin-solidity](https://github.com/OpenZeppelin/zeppelin-solidity) in your web browser and issue a new pull request.
|
||||
5) Maintainers will review your code and possibly ask for changes before your code is pulled in to the main repository. We'll check that all tests pass, review the coding style, and check for general code correctness. If everything is OK, we'll merge your pull request and your code will be part of OpenZeppelin.
|
||||
|
||||
Main contributors will review your code and possibly ask for changes before your code is pulled in to the main repository. We'll check that all tests pass, review the coding style, and check for general code correctness. If everything is OK, we'll merge your pull request and your code will be part of Zeppelin.
|
||||
*IMPORTANT* Please pay attention to the maintainer's feedback, since its a necessary step to keep up with the standards OpenZeppelin attains to.
|
||||
|
||||
If you have any questions feel free to post them to
|
||||
[github.com/OpenZeppelin/zeppelin-solidity/issues](https://github.com/OpenZeppelin/zeppelin-solidity/issues).
|
||||
## All set!
|
||||
|
||||
Finally, if you're looking to collaborate and want to find easy tasks to start, [look at the issues we marked as easy](https://github.com/OpenZeppelin/zeppelin-solidity/labels/easy).
|
||||
If you have any questions feel free to post them to github.com/OpenZeppelin/openzeppelin-solidity/issues.
|
||||
|
||||
Finally, if you're looking to collaborate and want to find easy tasks to start, look at the issues we marked as ["Good first issue"](https://github.com/OpenZeppelin/openzeppelin-solidity/labels/good%20first%20issue).
|
||||
|
||||
Thanks for your time and code!
|
||||
|
||||
122
README.md
122
README.md
@ -1,19 +1,23 @@
|
||||
# Zeppelin Solidity
|
||||
[](https://www.npmjs.org/package/zeppelin-solidity)
|
||||
[](https://travis-ci.org/OpenZeppelin/zeppelin-solidity)
|
||||
[](https://coveralls.io/github/OpenZeppelin/zeppelin-solidity?branch=master)
|
||||
# OpenZeppelin Solidity
|
||||
[](https://www.npmjs.org/package/openzeppelin-solidity)
|
||||
[](https://travis-ci.org/OpenZeppelin/openzeppelin-solidity)
|
||||
[](https://coveralls.io/github/OpenZeppelin/openzeppelin-solidity?branch=master)
|
||||
|
||||
OpenZeppelin is a library for writing secure [Smart Contracts](https://en.wikipedia.org/wiki/Smart_contract) on Ethereum.
|
||||
|
||||
With OpenZeppelin, you can build distributed applications, protocols and organizations:
|
||||
- using common contract security patterns (See [Onward with Ethereum Smart Contract Security](https://medium.com/bitcorps-blog/onward-with-ethereum-smart-contract-security-97a827e47702#.y3kvdetbz))
|
||||
- in the [Solidity language](http://solidity.readthedocs.io/en/develop/).
|
||||
- in the [Solidity language](https://solidity.readthedocs.io/en/develop/).
|
||||
|
||||
> NOTE: New to smart contract development? Check our [introductory guide](https://medium.com/zeppelin-blog/the-hitchhikers-guide-to-smart-contracts-in-ethereum-848f08001f05#.cox40d2ut).
|
||||
|
||||
## Getting Started
|
||||
|
||||
OpenZeppelin integrates with [Truffle](https://github.com/ConsenSys/truffle), an Ethereum development environment. Please install Truffle and initialize your project with `truffle init`.
|
||||
OpenZeppelin integrates with [Truffle](https://github.com/ConsenSys/truffle) and [Embark](https://github.com/embark-framework/embark/).
|
||||
|
||||
## truffle
|
||||
|
||||
To use with Truffle, first install it and initialize your project with `truffle init`.
|
||||
|
||||
```sh
|
||||
npm install -g truffle
|
||||
@ -21,61 +25,107 @@ mkdir myproject && cd myproject
|
||||
truffle init
|
||||
```
|
||||
|
||||
To install the OpenZeppelin library, run:
|
||||
```sh
|
||||
npm install zeppelin-solidity
|
||||
## Embark
|
||||
|
||||
# If you are using yarn, add dependency like this -
|
||||
yarn add zeppelin-solidity
|
||||
To use with Embark, first install it and initialize your project with `embark new MyApp`.
|
||||
|
||||
```sh
|
||||
npm install -g embark
|
||||
embark new MyApp
|
||||
cd MyApp
|
||||
```
|
||||
|
||||
After that, you'll get all the library's contracts in the `node_modules/zeppelin-solidity/contracts` folder. You can use the contracts in the library like so:
|
||||
## Installing OpenZeppelin
|
||||
|
||||
```js
|
||||
import 'zeppelin-solidity/contracts/ownership/Ownable.sol';
|
||||
After installing either Framework, to install the OpenZeppelin library, run the following in your Solidity project root directory:
|
||||
|
||||
```sh
|
||||
npm init -y
|
||||
npm install -E openzeppelin-solidity
|
||||
```
|
||||
|
||||
**Note that OpenZeppelin does not currently follow semantic versioning.** You may encounter breaking changes upon a minor version bump. We recommend pinning the version of OpenZeppelin you use, as done by the `-E` (`--save-exact`) option.
|
||||
|
||||
After that, you'll get all the library's contracts in the `node_modules/openzeppelin-solidity/contracts` folder. You can use the contracts in the library like so:
|
||||
|
||||
```solidity
|
||||
import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';
|
||||
|
||||
contract MyContract is Ownable {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
If you are using Embark, you can also import directly from github:
|
||||
|
||||
```solidity
|
||||
import "github.com/OpenZeppelin/openzeppelin-solidity/contracts/ownership/Ownable.sol#v1.9.0";
|
||||
|
||||
contract MyContract is Ownable {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Architecture
|
||||
The following provides visibility into how OpenZeppelin's contracts are organized:
|
||||
|
||||
- **access** - Smart contracts that enable functionality that can be used for selective restrictions and basic authorization control functions. Includes address whitelisting and signature-based permissions management.
|
||||
- **rbac** - A library used to manage addresses assigned to different user roles and an example Role-Based Access Control (RBAC) interface that demonstrates how to handle setters and getters for roles and addresses.
|
||||
- **crowdsale** - A collection of smart contracts used to manage token crowdsales that allow investors to purchase tokens with ETH. Includes a base contract which implements fundamental crowdsale functionality in its simplest form. The base contract can be extended in order to satisfy your crowdsale’s specific requirements.
|
||||
- **distribution** - Includes extensions of the base crowdsale contract which can be used to customize the completion of a crowdsale.
|
||||
- **emission** - Includes extensions of the base crowdsale contract which can be used to mint and manage how tokens are issued to purchasers.
|
||||
- **price** - Includes extensions of the crowdsale contract that can be used to manage changes in token prices.
|
||||
- **validation** - Includes extensions of the crowdsale contract that can be used to enforce restraints and limit access to token purchases.
|
||||
- **examples** - A collection of simple smart contracts that demonstrate how to add new features to base contracts through multiple inheritance.
|
||||
- **introspection** - An interface that can be used to make a contract comply with the ERC-165 standard as well as a contract that implements ERC-165 using a lookup table.
|
||||
- **lifecycle** - A collection of base contracts used to manage the existence and behavior of your contracts and their funds.
|
||||
- **math** - Libraries with safety checks on operations that throw on errors.
|
||||
- **mocks** - A collection of abstract contracts that are primarily used for unit testing. They also serve as good usage examples and demonstrate how to combine contracts with inheritence when developing your own custom applciations.
|
||||
- **ownership** - A collection of smart contracts that can be used to manage contract and token ownership
|
||||
- **payment** - A collection of smart contracts that can be used to manage payments through escrow arrangements, withdrawals, and claims. Includes support for both single payees and multiple payees.
|
||||
- **proposals** - A collection of smart contracts that reflect community Ethereum Improvement Proposals (EIPs). These contracts are under development and standardization. They are not recommended for production, but they are useful for experimentation with pending EIP standards. Go [here](https://github.com/OpenZeppelin/openzeppelin-solidity/wiki/ERC-Process) for more information.
|
||||
|
||||
- **token** - A collection of approved ERC standard tokens -- their interfaces and implementations.
|
||||
- **ERC20** - A standard interface for fungible tokens:
|
||||
- *Interfaces* - Includes the ERC-20 token standard basic interface. I.e., what the contract’s ABI can represent.
|
||||
- *Implementations* - Includes ERC-20 token implementations that include all required and some optional ERC-20 functionality.
|
||||
- **ERC721** - A standard interface for non-fungible tokens
|
||||
- *Interfaces* - Includes the ERC-721 token standard basic interface. I.e., what the contract’s ABI can represent.
|
||||
- *Implementations* - Includes ERC-721 token implementations that include all required and some optional ERC-721 functionality.
|
||||
|
||||
## Tests
|
||||
Unit test are critical to the OpenZeppelin framework. They help ensure code quality and mitigate against security vulnerabilities. The directory structure within the `/tests` directory corresponds to the `/contracts` directory. OpenZeppelin uses Mocha’s JavaScript testing framework and Chai’s assertion library. To learn more about how to tests are structured, please reference OpenZeppelin’s Testing Guide.
|
||||
|
||||
## How To Use And Modify OpenZeppelin Contracts
|
||||
When using OpenZeppelin to build your own distributed applications, for security reasons we encourage you NOT to modify the framework’s base contracts, libraries, and interfaces. In order to leverage and extend their functionality, we encourage you to inherit from them or compose them together with your own contracts.
|
||||
|
||||
The Solidity programming language supports multiple inheritance. This is very powerful yet it can also be confusing: the more complexity you introduce to your distributed applications through multiple inheritance, the greater your application’s attack surface is.
|
||||
|
||||
You’ll notice in the `/mocks` directory there are a collection of abstract contracts used primarily for unit testing purposes that can also be used as the foundation for your own custom implementations. These mock contracts demonstrate how OpenZeppelin’s secure base contracts can be used with multiple inheritance.
|
||||
|
||||
To learn more about combining OpenZeppelin contracts with your own custom contracts using multiple inheritance we encourage you to read the following: [On crowdsales and multiple inheritance](https://blog.zeppelin.solutions/on-crowdsales-and-multiple-inheritance-af90c694e35f)
|
||||
|
||||
## Security
|
||||
OpenZeppelin is meant to provide secure, tested and community-audited code, but please use common sense when doing anything that deals with real money! We take no responsibility for your implementation decisions and any security problem you might experience.
|
||||
|
||||
The core development principles and strategies that OpenZeppelin is based on include: security in depth, simple and modular code, clarity-driven naming conventions, comprehensive unit testing, pre-and-post-condition sanity checks, code consistency, and regular audits.
|
||||
|
||||
If you find a security issue, please email [security@openzeppelin.org](mailto:security@openzeppelin.org).
|
||||
|
||||
## Developer Resources
|
||||
|
||||
Building a distributed application, protocol or organization with OpenZeppelin?
|
||||
|
||||
- Read documentation: http://zeppelin-solidity.readthedocs.io/en/latest/
|
||||
- Read documentation: https://openzeppelin.org/api/docs/open-zeppelin.html
|
||||
|
||||
- Ask for help and follow progress at: https://slack.openzeppelin.org/
|
||||
|
||||
Interested in contributing to OpenZeppelin?
|
||||
|
||||
- Framework proposal and roadmap: https://medium.com/zeppelin-blog/zeppelin-framework-proposal-and-development-roadmap-fdfa9a3a32ab#.iain47pak
|
||||
- Issue tracker: https://github.com/OpenZeppelin/zeppelin-solidity/issues
|
||||
- Contribution guidelines: https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/CONTRIBUTING.md
|
||||
|
||||
## Collaborating organizations and audits by OpenZeppelin
|
||||
- [Golem](https://golem.network/)
|
||||
- [Mediachain](http://www.mediachain.io/)
|
||||
- [Truffle](http://truffleframework.com/)
|
||||
- [Firstblood](http://firstblood.io/)
|
||||
- [Rootstock](http://www.rsk.co/)
|
||||
- [Consensys](https://consensys.net/)
|
||||
- [DigixGlobal](https://www.dgx.io/)
|
||||
- [Coinfund](https://coinfund.io/)
|
||||
- [DemocracyEarth](http://democracy.earth/)
|
||||
- [Signatura](https://signatura.co/)
|
||||
- [Ether.camp](http://www.ether.camp/)
|
||||
- [Aragon](https://aragon.one/)
|
||||
- [Wings](https://wings.ai/)
|
||||
|
||||
among others...
|
||||
|
||||
- Issue tracker: https://github.com/OpenZeppelin/openzeppelin-solidity/issues
|
||||
- Contribution guidelines: https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/CONTRIBUTING.md
|
||||
- Wiki: https://github.com/OpenZeppelin/openzeppelin-solidity/wiki
|
||||
|
||||
## License
|
||||
Code released under the [MIT License](https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/LICENSE).
|
||||
Code released under the [MIT License](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/LICENSE).
|
||||
2
contracts/.npmignore
Normal file
2
contracts/.npmignore
Normal file
@ -0,0 +1,2 @@
|
||||
mocks
|
||||
examples
|
||||
29
contracts/AddressUtils.sol
Normal file
29
contracts/AddressUtils.sol
Normal file
@ -0,0 +1,29 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* Utility library of inline functions on addresses
|
||||
*/
|
||||
library AddressUtils {
|
||||
|
||||
/**
|
||||
* Returns whether the target address is a contract
|
||||
* @dev This function will return false if invoked during the constructor of a contract,
|
||||
* as the code is not actually created until after the constructor finishes.
|
||||
* @param _addr address to check
|
||||
* @return whether the target address is a contract
|
||||
*/
|
||||
function isContract(address _addr) internal view returns (bool) {
|
||||
uint256 size;
|
||||
// XXX Currently there is no better way to check if there is a contract in an address
|
||||
// than to check the size of the code at that address.
|
||||
// See https://ethereum.stackexchange.com/a/14016/36603
|
||||
// for more details about how this works.
|
||||
// TODO Check this again before the Serenity release, because all addresses will be
|
||||
// contracts then.
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly { size := extcodesize(_addr) }
|
||||
return size > 0;
|
||||
}
|
||||
|
||||
}
|
||||
29
contracts/AutoIncrementing.sol
Normal file
29
contracts/AutoIncrementing.sol
Normal file
@ -0,0 +1,29 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @title AutoIncrementing
|
||||
* @author Matt Condon (@shrugs)
|
||||
* @dev Provides an auto-incrementing uint256 id acquired by the `Counter#nextId` getter.
|
||||
* Use this for issuing ERC721Token ids or keeping track of request ids, anything you want, really.
|
||||
*
|
||||
* Include with `using AutoIncrementing for AutoIncrementing.Counter;`
|
||||
* @notice Does not allow an Id of 0, which is popularly used to signify a null state in solidity.
|
||||
* Does not protect from overflows, but if you have 2^256 ids, you have other problems.
|
||||
* (But actually, it's generally impossible to increment a counter this many times, energy wise
|
||||
* so it's not something you have to worry about.)
|
||||
*/
|
||||
library AutoIncrementing {
|
||||
|
||||
struct Counter {
|
||||
uint256 prevId; // default: 0
|
||||
}
|
||||
|
||||
function nextId(Counter storage _counter)
|
||||
internal
|
||||
returns (uint256)
|
||||
{
|
||||
_counter.prevId = _counter.prevId + 1;
|
||||
return _counter.prevId;
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import './payment/PullPayment.sol';
|
||||
import './lifecycle/Destructible.sol';
|
||||
import "./payment/PullPayment.sol";
|
||||
import "./lifecycle/Destructible.sol";
|
||||
|
||||
|
||||
/**
|
||||
@ -18,7 +18,7 @@ contract Bounty is PullPayment, Destructible {
|
||||
/**
|
||||
* @dev Fallback function allowing the contract to receive funds, if they haven't already been claimed.
|
||||
*/
|
||||
function() payable {
|
||||
function() external payable {
|
||||
require(!claimed);
|
||||
}
|
||||
|
||||
@ -30,29 +30,29 @@ contract Bounty is PullPayment, Destructible {
|
||||
function createTarget() public returns(Target) {
|
||||
Target target = Target(deployContract());
|
||||
researchers[target] = msg.sender;
|
||||
TargetCreated(target);
|
||||
emit TargetCreated(target);
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers the contract funds to the researcher that proved the contract is broken.
|
||||
* @param _target contract
|
||||
*/
|
||||
function claim(Target _target) public {
|
||||
address researcher = researchers[_target];
|
||||
require(researcher != address(0));
|
||||
// Check Target contract invariants
|
||||
require(!_target.checkInvariant());
|
||||
asyncTransfer(researcher, address(this).balance);
|
||||
claimed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Internal function to deploy the target contract.
|
||||
* @return A target contract address
|
||||
*/
|
||||
function deployContract() internal returns(address);
|
||||
|
||||
/**
|
||||
* @dev Sends the contract funds to the researcher that proved the contract is broken.
|
||||
* @param target contract
|
||||
*/
|
||||
function claim(Target target) public {
|
||||
address researcher = researchers[target];
|
||||
require(researcher != 0);
|
||||
// Check Target contract invariants
|
||||
require(!target.checkInvariant());
|
||||
asyncSend(researcher, this.balance);
|
||||
claimed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,73 +0,0 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
/**
|
||||
* @title DayLimit
|
||||
* @dev Base contract that enables methods to be protected by placing a linear limit (specifiable)
|
||||
* on a particular resource per calendar day. Is multiowned to allow the limit to be altered.
|
||||
*/
|
||||
contract DayLimit {
|
||||
|
||||
uint256 public dailyLimit;
|
||||
uint256 public spentToday;
|
||||
uint256 public lastDay;
|
||||
|
||||
/**
|
||||
* @dev Constructor that sets the passed value as a dailyLimit.
|
||||
* @param _limit uint256 to represent the daily limit.
|
||||
*/
|
||||
function DayLimit(uint256 _limit) {
|
||||
dailyLimit = _limit;
|
||||
lastDay = today();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev sets the daily limit. Does not alter the amount already spent today.
|
||||
* @param _newLimit uint256 to represent the new limit.
|
||||
*/
|
||||
function _setDailyLimit(uint256 _newLimit) internal {
|
||||
dailyLimit = _newLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Resets the amount already spent today.
|
||||
*/
|
||||
function _resetSpentToday() internal {
|
||||
spentToday = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks to see if there is enough resource to spend today. If true, the resource may be expended.
|
||||
* @param _value uint256 representing the amount of resource to spend.
|
||||
* @return A boolean that is True if the resource was spent and false otherwise.
|
||||
*/
|
||||
function underLimit(uint256 _value) internal returns (bool) {
|
||||
// reset the spend limit if we're on a different day to last time.
|
||||
if (today() > lastDay) {
|
||||
spentToday = 0;
|
||||
lastDay = today();
|
||||
}
|
||||
// check to see if there's enough left - if so, subtract and return true.
|
||||
// overflow protection // dailyLimit check
|
||||
if (spentToday + _value >= spentToday && spentToday + _value <= dailyLimit) {
|
||||
spentToday += _value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Private function to determine today's index
|
||||
* @return uint256 of today's index.
|
||||
*/
|
||||
function today() private constant returns (uint256) {
|
||||
return now / 1 days;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Simple modifier for daily limit.
|
||||
*/
|
||||
modifier limitedDaily(uint256 _value) {
|
||||
require(underLimit(_value));
|
||||
_;
|
||||
}
|
||||
}
|
||||
@ -1,34 +1,42 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @title Eliptic curve signature operations
|
||||
*
|
||||
* @title Elliptic curve signature operations
|
||||
* @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
|
||||
* TODO Remove this library once solidity supports passing a signature to ecrecover.
|
||||
* See https://github.com/ethereum/solidity/issues/864
|
||||
*/
|
||||
|
||||
library ECRecovery {
|
||||
|
||||
/**
|
||||
* @dev Recover signer address from a message by using his signature
|
||||
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
|
||||
* @param sig bytes signature, the signature is generated using web3.eth.sign()
|
||||
* @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 _sig bytes signature, the signature is generated using web3.eth.sign()
|
||||
*/
|
||||
function recover(bytes32 hash, bytes sig) public constant returns (address) {
|
||||
function recover(bytes32 _hash, bytes _sig)
|
||||
internal
|
||||
pure
|
||||
returns (address)
|
||||
{
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
uint8 v;
|
||||
|
||||
//Check the signature length
|
||||
if (sig.length != 65) {
|
||||
// Check the signature length
|
||||
if (_sig.length != 65) {
|
||||
return (address(0));
|
||||
}
|
||||
|
||||
// Divide the signature in r, s and v variables
|
||||
// ecrecover takes the signature parameters, and the only way to get them
|
||||
// currently is to use assembly.
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
r := mload(add(sig, 32))
|
||||
s := mload(add(sig, 64))
|
||||
v := byte(0, mload(add(sig, 96)))
|
||||
r := mload(add(_sig, 32))
|
||||
s := mload(add(_sig, 64))
|
||||
v := byte(0, mload(add(_sig, 96)))
|
||||
}
|
||||
|
||||
// Version of signature should be 27 or 28, but 0 and 1 are also possible versions
|
||||
@ -40,8 +48,25 @@ library ECRecovery {
|
||||
if (v != 27 && v != 28) {
|
||||
return (address(0));
|
||||
} else {
|
||||
return ecrecover(hash, v, r, s);
|
||||
// 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,11 +1,11 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @title LimitBalance
|
||||
* @dev Simple contract to limit the balance of child contract.
|
||||
* @dev Note this doesn't prevent other contracts to send funds by using selfdestruct(address);
|
||||
* @dev See: https://github.com/ConsenSys/smart-contract-best-practices#remember-that-ether-can-be-forcibly-sent-to-an-account
|
||||
* Note this doesn't prevent other contracts to send funds by using selfdestruct(address);
|
||||
* See: https://github.com/ConsenSys/smart-contract-best-practices#remember-that-ether-can-be-forcibly-sent-to-an-account
|
||||
*/
|
||||
contract LimitBalance {
|
||||
|
||||
@ -15,7 +15,7 @@ contract LimitBalance {
|
||||
* @dev Constructor that sets the passed value as a limit.
|
||||
* @param _limit uint256 to represent the limit.
|
||||
*/
|
||||
function LimitBalance(uint256 _limit) {
|
||||
constructor(uint256 _limit) public {
|
||||
limit = _limit;
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ contract LimitBalance {
|
||||
* @dev Checks if limit was reached. Case true, it throws.
|
||||
*/
|
||||
modifier limitedPayable() {
|
||||
require(this.balance <= limit);
|
||||
require(address(this).balance <= limit);
|
||||
_;
|
||||
|
||||
}
|
||||
|
||||
@ -1,37 +1,39 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
/*
|
||||
|
||||
/**
|
||||
* @title MerkleProof
|
||||
* @dev Merkle proof verification
|
||||
* @note Based on https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
|
||||
* @dev Merkle proof verification based on
|
||||
* https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
|
||||
*/
|
||||
library MerkleProof {
|
||||
/*
|
||||
/**
|
||||
* @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
|
||||
* and each pair of pre-images is 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 _root Merkle root
|
||||
* @param _leaf Leaf of Merkle tree
|
||||
*/
|
||||
function verifyProof(bytes _proof, bytes32 _root, bytes32 _leaf) constant returns (bool) {
|
||||
// Check if proof length is a multiple of 32
|
||||
if (_proof.length % 32 != 0) return false;
|
||||
|
||||
bytes32 proofElement;
|
||||
function verifyProof(
|
||||
bytes32[] _proof,
|
||||
bytes32 _root,
|
||||
bytes32 _leaf
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool)
|
||||
{
|
||||
bytes32 computedHash = _leaf;
|
||||
|
||||
for (uint256 i = 32; i <= _proof.length; i += 32) {
|
||||
assembly {
|
||||
// Load the current element of the proof
|
||||
proofElement := mload(add(_proof, i))
|
||||
}
|
||||
for (uint256 i = 0; i < _proof.length; i++) {
|
||||
bytes32 proofElement = _proof[i];
|
||||
|
||||
if (computedHash < proofElement) {
|
||||
// Hash(current computed hash + current element of the proof)
|
||||
computedHash = keccak256(computedHash, proofElement);
|
||||
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
|
||||
} else {
|
||||
// Hash(current element of the proof + current computed hash)
|
||||
computedHash = keccak256(proofElement, computedHash);
|
||||
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,31 +1,39 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @title Helps contracts guard agains rentrancy attacks.
|
||||
* @author Remco Bloemen <remco@2π.com>
|
||||
* @notice If you mark a function `nonReentrant`, you should also
|
||||
* @title Helps contracts guard against reentrancy attacks.
|
||||
* @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io>
|
||||
* @dev If you mark a function `nonReentrant`, you should also
|
||||
* mark it `external`.
|
||||
*/
|
||||
contract ReentrancyGuard {
|
||||
|
||||
/// @dev Constant for unlocked guard state - non-zero to prevent extra gas costs.
|
||||
/// See: https://github.com/OpenZeppelin/openzeppelin-solidity/issues/1056
|
||||
uint private constant REENTRANCY_GUARD_FREE = 1;
|
||||
|
||||
/// @dev Constant for locked guard state
|
||||
uint private constant REENTRANCY_GUARD_LOCKED = 2;
|
||||
|
||||
/**
|
||||
* @dev We use a single lock for the whole contract.
|
||||
*/
|
||||
bool private rentrancy_lock = false;
|
||||
uint private reentrancyLock = REENTRANCY_GUARD_FREE;
|
||||
|
||||
/**
|
||||
* @dev Prevents a contract from calling itself, directly or indirectly.
|
||||
* @notice If you mark a function `nonReentrant`, you should also
|
||||
* mark it `external`. Calling one nonReentrant function from
|
||||
* If you mark a function `nonReentrant`, you should also
|
||||
* mark it `external`. Calling one `nonReentrant` function from
|
||||
* another is not supported. Instead, you can implement a
|
||||
* `private` function doing the actual work, and a `external`
|
||||
* `private` function doing the actual work, and an `external`
|
||||
* wrapper marked as `nonReentrant`.
|
||||
*/
|
||||
modifier nonReentrant() {
|
||||
require(!rentrancy_lock);
|
||||
rentrancy_lock = true;
|
||||
require(reentrancyLock == REENTRANCY_GUARD_FREE);
|
||||
reentrancyLock = REENTRANCY_GUARD_LOCKED;
|
||||
_;
|
||||
rentrancy_lock = false;
|
||||
reentrancyLock = REENTRANCY_GUARD_FREE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
159
contracts/access/SignatureBouncer.sol
Normal file
159
contracts/access/SignatureBouncer.sol
Normal file
@ -0,0 +1,159 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../access/rbac/RBAC.sol";
|
||||
import "../ECRecovery.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title SignatureBouncer
|
||||
* @author PhABC, Shrugs and aflesher
|
||||
* @dev Bouncer allows users to submit a signature as a permission to do an action.
|
||||
* If the signature is from one of the authorized bouncer addresses, the signature
|
||||
* is valid. The owner of the contract adds/removes bouncers.
|
||||
* Bouncer addresses can be individual servers signing grants or different
|
||||
* users within a decentralized club that have permission to invite other members.
|
||||
* This technique is useful for whitelists and airdrops; instead of putting all
|
||||
* valid addresses on-chain, simply sign a grant of the form
|
||||
* keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a valid bouncer address.
|
||||
* Then restrict access to your crowdsale/whitelist/airdrop using the
|
||||
* `onlyValidSignature` modifier (or implement your own using isValidSignature).
|
||||
* In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and
|
||||
* `onlyValidSignatureAndData` can be used to restrict access to only a given method
|
||||
* or a given method with given parameters respectively.
|
||||
* See the tests Bouncer.test.js for specific usage examples.
|
||||
* @notice A method that uses the `onlyValidSignatureAndData` modifier must make the _sig
|
||||
* parameter the "last" parameter. You cannot sign a message that has its own
|
||||
* signature in it so the last 128 bytes of msg.data (which represents the
|
||||
* length of the _sig data and the _sig data itself) is ignored when validating.
|
||||
* Also non fixed sized parameters make constructing the data in the signature
|
||||
* much more complex. See https://ethereum.stackexchange.com/a/50616 for more details.
|
||||
*/
|
||||
contract SignatureBouncer is Ownable, RBAC {
|
||||
using ECRecovery for bytes32;
|
||||
|
||||
string public constant ROLE_BOUNCER = "bouncer";
|
||||
uint constant METHOD_ID_SIZE = 4;
|
||||
// signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes
|
||||
uint constant SIGNATURE_SIZE = 96;
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature of a bouncer was provided
|
||||
*/
|
||||
modifier onlyValidSignature(bytes _sig)
|
||||
{
|
||||
require(isValidSignature(msg.sender, _sig));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature with a specifed method of a bouncer was provided
|
||||
*/
|
||||
modifier onlyValidSignatureAndMethod(bytes _sig)
|
||||
{
|
||||
require(isValidSignatureAndMethod(msg.sender, _sig));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev requires that a valid signature with a specifed method and params of a bouncer was provided
|
||||
*/
|
||||
modifier onlyValidSignatureAndData(bytes _sig)
|
||||
{
|
||||
require(isValidSignatureAndData(msg.sender, _sig));
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev allows the owner to add additional bouncer addresses
|
||||
*/
|
||||
function addBouncer(address _bouncer)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
require(_bouncer != address(0));
|
||||
addRole(_bouncer, ROLE_BOUNCER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev allows the owner to remove bouncer addresses
|
||||
*/
|
||||
function removeBouncer(address _bouncer)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
require(_bouncer != address(0));
|
||||
removeRole(_bouncer, ROLE_BOUNCER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + sender` from a bouncer?
|
||||
* @return bool
|
||||
*/
|
||||
function isValidSignature(address _address, bytes _sig)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return isValidDataHash(
|
||||
keccak256(abi.encodePacked(address(this), _address)),
|
||||
_sig
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + sender + methodId` from a bouncer?
|
||||
* @return bool
|
||||
*/
|
||||
function isValidSignatureAndMethod(address _address, bytes _sig)
|
||||
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), _address, data)),
|
||||
_sig
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + sender + methodId + params(s)` from a bouncer?
|
||||
* @notice the _sig parameter of the method being validated must be the "last" parameter
|
||||
* @return bool
|
||||
*/
|
||||
function isValidSignatureAndData(address _address, bytes _sig)
|
||||
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), _address, data)),
|
||||
_sig
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev internal function to convert a hash to an eth signed message
|
||||
* and then recover the signature and check it against the bouncer role
|
||||
* @return bool
|
||||
*/
|
||||
function isValidDataHash(bytes32 _hash, bytes _sig)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
address signer = _hash
|
||||
.toEthSignedMessageHash()
|
||||
.recover(_sig);
|
||||
return hasRole(signer, ROLE_BOUNCER);
|
||||
}
|
||||
}
|
||||
91
contracts/access/Whitelist.sol
Normal file
91
contracts/access/Whitelist.sol
Normal file
@ -0,0 +1,91 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../access/rbac/RBAC.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Whitelist
|
||||
* @dev The Whitelist contract has a whitelist of addresses, and provides basic authorization control functions.
|
||||
* This simplifies the implementation of "user permissions".
|
||||
*/
|
||||
contract Whitelist is Ownable, RBAC {
|
||||
string public constant ROLE_WHITELISTED = "whitelist";
|
||||
|
||||
/**
|
||||
* @dev Throws if operator is not whitelisted.
|
||||
* @param _operator address
|
||||
*/
|
||||
modifier onlyIfWhitelisted(address _operator) {
|
||||
checkRole(_operator, ROLE_WHITELISTED);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add an address to the whitelist
|
||||
* @param _operator address
|
||||
* @return true if the address was added to the whitelist, false if the address was already in the whitelist
|
||||
*/
|
||||
function addAddressToWhitelist(address _operator)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
addRole(_operator, ROLE_WHITELISTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev getter to determine if address is in whitelist
|
||||
*/
|
||||
function whitelist(address _operator)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return hasRole(_operator, ROLE_WHITELISTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add addresses to the whitelist
|
||||
* @param _operators addresses
|
||||
* @return true if at least one address was added to the whitelist,
|
||||
* false if all addresses were already in the whitelist
|
||||
*/
|
||||
function addAddressesToWhitelist(address[] _operators)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
for (uint256 i = 0; i < _operators.length; i++) {
|
||||
addAddressToWhitelist(_operators[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove an address from the whitelist
|
||||
* @param _operator address
|
||||
* @return true if the address was removed from the whitelist,
|
||||
* false if the address wasn't in the whitelist in the first place
|
||||
*/
|
||||
function removeAddressFromWhitelist(address _operator)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
removeRole(_operator, ROLE_WHITELISTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove addresses from the whitelist
|
||||
* @param _operators addresses
|
||||
* @return true if at least one address was removed from the whitelist,
|
||||
* false if all addresses weren't in the whitelist in the first place
|
||||
*/
|
||||
function removeAddressesFromWhitelist(address[] _operators)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
for (uint256 i = 0; i < _operators.length; i++) {
|
||||
removeAddressFromWhitelist(_operators[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
106
contracts/access/rbac/RBAC.sol
Normal file
106
contracts/access/rbac/RBAC.sol
Normal file
@ -0,0 +1,106 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "./Roles.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title RBAC (Role-Based Access Control)
|
||||
* @author Matt Condon (@Shrugs)
|
||||
* @dev Stores and provides setters and getters for roles and addresses.
|
||||
* Supports unlimited numbers of roles and addresses.
|
||||
* See //contracts/mocks/RBACMock.sol for an example of usage.
|
||||
* This RBAC method uses strings to key roles. It may be beneficial
|
||||
* for you to write your own implementation of this interface using Enums or similar.
|
||||
*/
|
||||
contract RBAC {
|
||||
using Roles for Roles.Role;
|
||||
|
||||
mapping (string => Roles.Role) private roles;
|
||||
|
||||
event RoleAdded(address indexed operator, string role);
|
||||
event RoleRemoved(address indexed operator, string role);
|
||||
|
||||
/**
|
||||
* @dev reverts if addr does not have role
|
||||
* @param _operator address
|
||||
* @param _role the name of the role
|
||||
* // reverts
|
||||
*/
|
||||
function checkRole(address _operator, string _role)
|
||||
public
|
||||
view
|
||||
{
|
||||
roles[_role].check(_operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev determine if addr has role
|
||||
* @param _operator address
|
||||
* @param _role the name of the role
|
||||
* @return bool
|
||||
*/
|
||||
function hasRole(address _operator, string _role)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return roles[_role].has(_operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add a role to an address
|
||||
* @param _operator address
|
||||
* @param _role the name of the role
|
||||
*/
|
||||
function addRole(address _operator, string _role)
|
||||
internal
|
||||
{
|
||||
roles[_role].add(_operator);
|
||||
emit RoleAdded(_operator, _role);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove a role from an address
|
||||
* @param _operator address
|
||||
* @param _role the name of the role
|
||||
*/
|
||||
function removeRole(address _operator, string _role)
|
||||
internal
|
||||
{
|
||||
roles[_role].remove(_operator);
|
||||
emit RoleRemoved(_operator, _role);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev modifier to scope access to a single role (uses msg.sender as addr)
|
||||
* @param _role the name of the role
|
||||
* // reverts
|
||||
*/
|
||||
modifier onlyRole(string _role)
|
||||
{
|
||||
checkRole(msg.sender, _role);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev modifier to scope access to a set of roles (uses msg.sender as addr)
|
||||
* @param _roles the names of the roles to scope access to
|
||||
* // reverts
|
||||
*
|
||||
* @TODO - when solidity supports dynamic arrays as arguments to modifiers, provide this
|
||||
* see: https://github.com/ethereum/solidity/issues/2467
|
||||
*/
|
||||
// modifier onlyRoles(string[] _roles) {
|
||||
// bool hasAnyRole = false;
|
||||
// for (uint8 i = 0; i < _roles.length; i++) {
|
||||
// if (hasRole(msg.sender, _roles[i])) {
|
||||
// hasAnyRole = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// require(hasAnyRole);
|
||||
|
||||
// _;
|
||||
// }
|
||||
}
|
||||
55
contracts/access/rbac/Roles.sol
Normal file
55
contracts/access/rbac/Roles.sol
Normal file
@ -0,0 +1,55 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @title Roles
|
||||
* @author Francisco Giordano (@frangio)
|
||||
* @dev Library for managing addresses assigned to a Role.
|
||||
* See RBAC.sol for example usage.
|
||||
*/
|
||||
library Roles {
|
||||
struct Role {
|
||||
mapping (address => bool) bearer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev give an address access to this role
|
||||
*/
|
||||
function add(Role storage _role, address _addr)
|
||||
internal
|
||||
{
|
||||
_role.bearer[_addr] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove an address' access to this role
|
||||
*/
|
||||
function remove(Role storage _role, address _addr)
|
||||
internal
|
||||
{
|
||||
_role.bearer[_addr] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev check if an address has this role
|
||||
* // reverts
|
||||
*/
|
||||
function check(Role storage _role, address _addr)
|
||||
internal
|
||||
view
|
||||
{
|
||||
require(has(_role, _addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev check if an address has this role
|
||||
* @return bool
|
||||
*/
|
||||
function has(Role storage _role, address _addr)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return _role.bearer[_addr];
|
||||
}
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import '../math/SafeMath.sol';
|
||||
import './Crowdsale.sol';
|
||||
|
||||
/**
|
||||
* @title CappedCrowdsale
|
||||
* @dev Extension of Crowdsale with a max amount of funds raised
|
||||
*/
|
||||
contract CappedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public cap;
|
||||
|
||||
function CappedCrowdsale(uint256 _cap) {
|
||||
require(_cap > 0);
|
||||
cap = _cap;
|
||||
}
|
||||
|
||||
// overriding Crowdsale#validPurchase to add extra cap logic
|
||||
// @return true if investors can buy at the moment
|
||||
function validPurchase() internal constant returns (bool) {
|
||||
bool withinCap = weiRaised.add(msg.value) <= cap;
|
||||
return super.validPurchase() && withinCap;
|
||||
}
|
||||
|
||||
// overriding Crowdsale#hasEnded to add cap logic
|
||||
// @return true if crowdsale event has ended
|
||||
function hasEnded() public constant returns (bool) {
|
||||
bool capReached = weiRaised >= cap;
|
||||
return super.hasEnded() || capReached;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,106 +1,203 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
|
||||
import '../token/MintableToken.sol';
|
||||
import '../math/SafeMath.sol';
|
||||
|
||||
/**
|
||||
* @title Crowdsale
|
||||
* @dev Crowdsale is a base contract for managing a token crowdsale.
|
||||
* Crowdsales have a start and end timestamps, where investors can make
|
||||
* token purchases and the crowdsale will assign them tokens based
|
||||
* on a token per ETH rate. Funds collected are forwarded to a wallet
|
||||
* as they arrive.
|
||||
* @dev Crowdsale is a base contract for managing a token crowdsale,
|
||||
* allowing investors to purchase tokens with ether. This contract implements
|
||||
* such functionality in its most fundamental form and can be extended to provide additional
|
||||
* functionality and/or custom behavior.
|
||||
* The external interface represents the basic interface for purchasing tokens, and conform
|
||||
* the base architecture for crowdsales. They are *not* intended to be modified / overridden.
|
||||
* The internal interface conforms the extensible and modifiable surface of crowdsales. Override
|
||||
* the methods to add functionality. Consider using 'super' where appropriate to concatenate
|
||||
* behavior.
|
||||
*/
|
||||
contract Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for ERC20;
|
||||
|
||||
// The token being sold
|
||||
MintableToken public token;
|
||||
ERC20 public token;
|
||||
|
||||
// start and end timestamps where investments are allowed (both inclusive)
|
||||
uint256 public startTime;
|
||||
uint256 public endTime;
|
||||
|
||||
// address where funds are collected
|
||||
// Address where funds are collected
|
||||
address public 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.
|
||||
// So, if you are using a rate of 1 with a DetailedERC20 token with 3 decimals called TOK
|
||||
// 1 wei will give you 1 unit, or 0.001 TOK.
|
||||
uint256 public rate;
|
||||
|
||||
// amount of raised money in wei
|
||||
// Amount of wei raised
|
||||
uint256 public weiRaised;
|
||||
|
||||
/**
|
||||
* event for token purchase logging
|
||||
* Event for token purchase logging
|
||||
* @param purchaser who paid for the tokens
|
||||
* @param beneficiary who got the tokens
|
||||
* @param value weis paid for purchase
|
||||
* @param amount amount of tokens purchased
|
||||
*/
|
||||
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
|
||||
event TokenPurchase(
|
||||
address indexed purchaser,
|
||||
address indexed beneficiary,
|
||||
uint256 value,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
|
||||
function Crowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet) {
|
||||
require(_startTime >= now);
|
||||
require(_endTime >= _startTime);
|
||||
/**
|
||||
* @param _rate Number of token units a buyer gets per wei
|
||||
* @param _wallet Address where collected funds will be forwarded to
|
||||
* @param _token Address of the token being sold
|
||||
*/
|
||||
constructor(uint256 _rate, address _wallet, ERC20 _token) public {
|
||||
require(_rate > 0);
|
||||
require(_wallet != 0x0);
|
||||
require(_wallet != address(0));
|
||||
require(_token != address(0));
|
||||
|
||||
token = createTokenContract();
|
||||
startTime = _startTime;
|
||||
endTime = _endTime;
|
||||
rate = _rate;
|
||||
wallet = _wallet;
|
||||
token = _token;
|
||||
}
|
||||
|
||||
// creates the token to be sold.
|
||||
// override this method to have crowdsale of a specific mintable token.
|
||||
function createTokenContract() internal returns (MintableToken) {
|
||||
return new MintableToken();
|
||||
}
|
||||
// -----------------------------------------
|
||||
// Crowdsale external interface
|
||||
// -----------------------------------------
|
||||
|
||||
|
||||
// fallback function can be used to buy tokens
|
||||
function () payable {
|
||||
/**
|
||||
* @dev fallback function ***DO NOT OVERRIDE***
|
||||
*/
|
||||
function () external payable {
|
||||
buyTokens(msg.sender);
|
||||
}
|
||||
|
||||
// low level token purchase function
|
||||
function buyTokens(address beneficiary) public payable {
|
||||
require(beneficiary != 0x0);
|
||||
require(validPurchase());
|
||||
/**
|
||||
* @dev low level token purchase ***DO NOT OVERRIDE***
|
||||
* @param _beneficiary Address performing the token purchase
|
||||
*/
|
||||
function buyTokens(address _beneficiary) public payable {
|
||||
|
||||
uint256 weiAmount = msg.value;
|
||||
_preValidatePurchase(_beneficiary, weiAmount);
|
||||
|
||||
// calculate token amount to be created
|
||||
uint256 tokens = weiAmount.mul(rate);
|
||||
uint256 tokens = _getTokenAmount(weiAmount);
|
||||
|
||||
// update state
|
||||
weiRaised = weiRaised.add(weiAmount);
|
||||
|
||||
token.mint(beneficiary, tokens);
|
||||
TokenPurchase(msg.sender, beneficiary, weiAmount, tokens);
|
||||
_processPurchase(_beneficiary, tokens);
|
||||
emit TokenPurchase(
|
||||
msg.sender,
|
||||
_beneficiary,
|
||||
weiAmount,
|
||||
tokens
|
||||
);
|
||||
|
||||
forwardFunds();
|
||||
_updatePurchasingState(_beneficiary, weiAmount);
|
||||
|
||||
_forwardFunds();
|
||||
_postValidatePurchase(_beneficiary, weiAmount);
|
||||
}
|
||||
|
||||
// send ether to the fund collection wallet
|
||||
// override to create custom fund forwarding mechanisms
|
||||
function forwardFunds() internal {
|
||||
// -----------------------------------------
|
||||
// Internal interface (extensible)
|
||||
// -----------------------------------------
|
||||
|
||||
/**
|
||||
* @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
|
||||
{
|
||||
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.
|
||||
* @param _beneficiary Address performing the token purchase
|
||||
* @param _weiAmount Value in wei involved in the purchase
|
||||
*/
|
||||
function _postValidatePurchase(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
// optional override
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens.
|
||||
* @param _beneficiary Address receiving the tokens
|
||||
* @param _tokenAmount Number of tokens to be purchased
|
||||
*/
|
||||
function _processPurchase(
|
||||
address _beneficiary,
|
||||
uint256 _tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
_deliverTokens(_beneficiary, _tokenAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Override 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);
|
||||
}
|
||||
|
||||
// @return true if the transaction can buy tokens
|
||||
function validPurchase() internal constant returns (bool) {
|
||||
bool withinPeriod = now >= startTime && now <= endTime;
|
||||
bool nonZeroPurchase = msg.value != 0;
|
||||
return withinPeriod && nonZeroPurchase;
|
||||
}
|
||||
|
||||
// @return true if crowdsale event has ended
|
||||
function hasEnded() public constant returns (bool) {
|
||||
return now > endTime;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import '../math/SafeMath.sol';
|
||||
import '../ownership/Ownable.sol';
|
||||
|
||||
/**
|
||||
* @title RefundVault
|
||||
* @dev This contract is used for storing funds while a crowdsale
|
||||
* is in progress. Supports refunding the money if crowdsale fails,
|
||||
* and forwarding it if crowdsale is successful.
|
||||
*/
|
||||
contract RefundVault is Ownable {
|
||||
using SafeMath for uint256;
|
||||
|
||||
enum State { Active, Refunding, Closed }
|
||||
|
||||
mapping (address => uint256) public deposited;
|
||||
address public wallet;
|
||||
State public state;
|
||||
|
||||
event Closed();
|
||||
event RefundsEnabled();
|
||||
event Refunded(address indexed beneficiary, uint256 weiAmount);
|
||||
|
||||
function RefundVault(address _wallet) {
|
||||
require(_wallet != 0x0);
|
||||
wallet = _wallet;
|
||||
state = State.Active;
|
||||
}
|
||||
|
||||
function deposit(address investor) onlyOwner public payable {
|
||||
require(state == State.Active);
|
||||
deposited[investor] = deposited[investor].add(msg.value);
|
||||
}
|
||||
|
||||
function close() onlyOwner public {
|
||||
require(state == State.Active);
|
||||
state = State.Closed;
|
||||
Closed();
|
||||
wallet.transfer(this.balance);
|
||||
}
|
||||
|
||||
function enableRefunds() onlyOwner public {
|
||||
require(state == State.Active);
|
||||
state = State.Refunding;
|
||||
RefundsEnabled();
|
||||
}
|
||||
|
||||
function refund(address investor) public {
|
||||
require(state == State.Refunding);
|
||||
uint256 depositedValue = deposited[investor];
|
||||
deposited[investor] = 0;
|
||||
investor.transfer(depositedValue);
|
||||
Refunded(investor, depositedValue);
|
||||
}
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
|
||||
import '../math/SafeMath.sol';
|
||||
import './FinalizableCrowdsale.sol';
|
||||
import './RefundVault.sol';
|
||||
|
||||
|
||||
/**
|
||||
* @title RefundableCrowdsale
|
||||
* @dev Extension of Crowdsale contract that adds a funding goal, and
|
||||
* the possibility of users getting a refund if goal is not met.
|
||||
* Uses a RefundVault as the crowdsale's vault.
|
||||
*/
|
||||
contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
// minimum amount of funds to be raised in weis
|
||||
uint256 public goal;
|
||||
|
||||
// refund vault used to hold funds while crowdsale is running
|
||||
RefundVault public vault;
|
||||
|
||||
function RefundableCrowdsale(uint256 _goal) {
|
||||
require(_goal > 0);
|
||||
vault = new RefundVault(wallet);
|
||||
goal = _goal;
|
||||
}
|
||||
|
||||
// We're overriding the fund forwarding from Crowdsale.
|
||||
// In addition to sending the funds, we want to call
|
||||
// the RefundVault deposit function
|
||||
function forwardFunds() internal {
|
||||
vault.deposit.value(msg.value)(msg.sender);
|
||||
}
|
||||
|
||||
// if crowdsale is unsuccessful, investors can claim refunds here
|
||||
function claimRefund() public {
|
||||
require(isFinalized);
|
||||
require(!goalReached());
|
||||
|
||||
vault.refund(msg.sender);
|
||||
}
|
||||
|
||||
// vault finalization task, called when owner calls finalize()
|
||||
function finalization() internal {
|
||||
if (goalReached()) {
|
||||
vault.close();
|
||||
} else {
|
||||
vault.enableRefunds();
|
||||
}
|
||||
|
||||
super.finalization();
|
||||
}
|
||||
|
||||
function goalReached() public constant returns (bool) {
|
||||
return weiRaised >= goal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,15 +1,16 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../../ownership/Ownable.sol";
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
|
||||
import '../math/SafeMath.sol';
|
||||
import '../ownership/Ownable.sol';
|
||||
import './Crowdsale.sol';
|
||||
|
||||
/**
|
||||
* @title FinalizableCrowdsale
|
||||
* @dev Extension of Crowdsale where an owner can do extra work
|
||||
* after finishing.
|
||||
*/
|
||||
contract FinalizableCrowdsale is Crowdsale, Ownable {
|
||||
contract FinalizableCrowdsale is Ownable, TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
bool public isFinalized = false;
|
||||
@ -20,12 +21,12 @@ contract FinalizableCrowdsale is Crowdsale, Ownable {
|
||||
* @dev Must be called after crowdsale ends, to do some extra finalization
|
||||
* work. Calls the contract's finalization function.
|
||||
*/
|
||||
function finalize() onlyOwner public {
|
||||
function finalize() public onlyOwner {
|
||||
require(!isFinalized);
|
||||
require(hasEnded());
|
||||
require(hasClosed());
|
||||
|
||||
finalization();
|
||||
Finalized();
|
||||
emit Finalized();
|
||||
|
||||
isFinalized = true;
|
||||
}
|
||||
@ -37,4 +38,5 @@ contract FinalizableCrowdsale is Crowdsale, Ownable {
|
||||
*/
|
||||
function finalization() internal {
|
||||
}
|
||||
|
||||
}
|
||||
42
contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol
Normal file
42
contracts/crowdsale/distribution/PostDeliveryCrowdsale.sol
Normal file
@ -0,0 +1,42 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../token/ERC20/ERC20.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title PostDeliveryCrowdsale
|
||||
* @dev Crowdsale that locks tokens from withdrawal until it ends.
|
||||
*/
|
||||
contract PostDeliveryCrowdsale is TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping(address => uint256) public balances;
|
||||
|
||||
/**
|
||||
* @dev Withdraw tokens only after crowdsale ends.
|
||||
*/
|
||||
function withdrawTokens() public {
|
||||
require(hasClosed());
|
||||
uint256 amount = balances[msg.sender];
|
||||
require(amount > 0);
|
||||
balances[msg.sender] = 0;
|
||||
_deliverTokens(msg.sender, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
||||
72
contracts/crowdsale/distribution/RefundableCrowdsale.sol
Normal file
72
contracts/crowdsale/distribution/RefundableCrowdsale.sol
Normal file
@ -0,0 +1,72 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "./FinalizableCrowdsale.sol";
|
||||
import "../../payment/RefundEscrow.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title RefundableCrowdsale
|
||||
* @dev Extension of Crowdsale contract that adds a funding goal, and
|
||||
* the possibility of users getting a refund if goal is not met.
|
||||
*/
|
||||
contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
// minimum amount of funds to be raised in weis
|
||||
uint256 public goal;
|
||||
|
||||
// refund escrow used to hold funds while crowdsale is running
|
||||
RefundEscrow private escrow;
|
||||
|
||||
/**
|
||||
* @dev Constructor, creates RefundEscrow.
|
||||
* @param _goal Funding goal
|
||||
*/
|
||||
constructor(uint256 _goal) public {
|
||||
require(_goal > 0);
|
||||
escrow = new RefundEscrow(wallet);
|
||||
goal = _goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Investors can claim refunds here if crowdsale is unsuccessful
|
||||
*/
|
||||
function claimRefund() public {
|
||||
require(isFinalized);
|
||||
require(!goalReached());
|
||||
|
||||
escrow.withdraw(msg.sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 owner calls finalize()
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
50
contracts/crowdsale/emission/AllowanceCrowdsale.sol
Normal file
50
contracts/crowdsale/emission/AllowanceCrowdsale.sol
Normal file
@ -0,0 +1,50 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/ERC20.sol";
|
||||
import "../../token/ERC20/ERC20Basic.sol";
|
||||
import "../../token/ERC20/SafeERC20.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title AllowanceCrowdsale
|
||||
* @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale.
|
||||
*/
|
||||
contract AllowanceCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
using SafeERC20 for ERC20;
|
||||
|
||||
address public tokenWallet;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes token wallet address.
|
||||
* @param _tokenWallet Address holding the tokens, which has approved allowance to the crowdsale
|
||||
*/
|
||||
constructor(address _tokenWallet) public {
|
||||
require(_tokenWallet != address(0));
|
||||
tokenWallet = _tokenWallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks the amount of tokens left in the allowance.
|
||||
* @return Amount of tokens left in the allowance
|
||||
*/
|
||||
function remainingTokens() public view returns (uint256) {
|
||||
return token.allowance(tokenWallet, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Overrides parent behavior by transferring tokens from wallet.
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _tokenAmount Amount of tokens purchased
|
||||
*/
|
||||
function _deliverTokens(
|
||||
address _beneficiary,
|
||||
uint256 _tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
token.safeTransferFrom(tokenWallet, _beneficiary, _tokenAmount);
|
||||
}
|
||||
}
|
||||
28
contracts/crowdsale/emission/MintedCrowdsale.sol
Normal file
28
contracts/crowdsale/emission/MintedCrowdsale.sol
Normal file
@ -0,0 +1,28 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../token/ERC20/MintableToken.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title MintedCrowdsale
|
||||
* @dev Extension of Crowdsale contract whose tokens are minted in each purchase.
|
||||
* Token ownership should be transferred to MintedCrowdsale for minting.
|
||||
*/
|
||||
contract MintedCrowdsale is Crowdsale {
|
||||
|
||||
/**
|
||||
* @dev Overrides delivery by minting tokens upon purchase.
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _tokenAmount Number of tokens to be minted
|
||||
*/
|
||||
function _deliverTokens(
|
||||
address _beneficiary,
|
||||
uint256 _tokenAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
// Potentially dangerous assumption about the type of the token.
|
||||
require(MintableToken(address(token)).mint(_beneficiary, _tokenAmount));
|
||||
}
|
||||
}
|
||||
56
contracts/crowdsale/price/IncreasingPriceCrowdsale.sol
Normal file
56
contracts/crowdsale/price/IncreasingPriceCrowdsale.sol
Normal file
@ -0,0 +1,56 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../validation/TimedCrowdsale.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title IncreasingPriceCrowdsale
|
||||
* @dev Extension of Crowdsale contract that increases the price of tokens linearly in time.
|
||||
* Note that what should be provided to the constructor is the initial and final _rates_, that is,
|
||||
* the amount of tokens per wei contributed. Thus, the initial rate must be greater than the final rate.
|
||||
*/
|
||||
contract IncreasingPriceCrowdsale is TimedCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public initialRate;
|
||||
uint256 public finalRate;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes initial and final rates of tokens received per wei contributed.
|
||||
* @param _initialRate Number of tokens a buyer gets per wei at the start of the crowdsale
|
||||
* @param _finalRate Number of tokens a buyer gets per wei at the end of the crowdsale
|
||||
*/
|
||||
constructor(uint256 _initialRate, uint256 _finalRate) public {
|
||||
require(_initialRate >= _finalRate);
|
||||
require(_finalRate > 0);
|
||||
initialRate = _initialRate;
|
||||
finalRate = _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) {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
uint256 elapsedTime = block.timestamp.sub(openingTime);
|
||||
uint256 timeRange = closingTime.sub(openingTime);
|
||||
uint256 rateRange = initialRate.sub(finalRate);
|
||||
return initialRate.sub(elapsedTime.mul(rateRange).div(timeRange));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
||||
48
contracts/crowdsale/validation/CappedCrowdsale.sol
Normal file
48
contracts/crowdsale/validation/CappedCrowdsale.sol
Normal file
@ -0,0 +1,48 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title CappedCrowdsale
|
||||
* @dev Crowdsale with a limit for total contributions.
|
||||
*/
|
||||
contract CappedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public cap;
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes maximum amount of wei accepted in the crowdsale.
|
||||
* @param _cap Max amount of wei to be contributed
|
||||
*/
|
||||
constructor(uint256 _cap) public {
|
||||
require(_cap > 0);
|
||||
cap = _cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether the cap has been reached.
|
||||
* @return Whether the cap was reached
|
||||
*/
|
||||
function capReached() public view returns (bool) {
|
||||
return weiRaised >= cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
{
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
require(weiRaised.add(_weiAmount) <= cap);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
import "../../ownership/Ownable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title IndividuallyCappedCrowdsale
|
||||
* @dev Crowdsale with per-user caps.
|
||||
*/
|
||||
contract IndividuallyCappedCrowdsale is Ownable, Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping(address => uint256) public contributions;
|
||||
mapping(address => uint256) public caps;
|
||||
|
||||
/**
|
||||
* @dev Sets a specific user's maximum contribution.
|
||||
* @param _beneficiary Address to be capped
|
||||
* @param _cap Wei limit for individual contribution
|
||||
*/
|
||||
function setUserCap(address _beneficiary, uint256 _cap) external onlyOwner {
|
||||
caps[_beneficiary] = _cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sets a group of users' maximum contribution.
|
||||
* @param _beneficiaries List of addresses to be capped
|
||||
* @param _cap Wei limit for individual contribution
|
||||
*/
|
||||
function setGroupCap(
|
||||
address[] _beneficiaries,
|
||||
uint256 _cap
|
||||
)
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
for (uint256 i = 0; i < _beneficiaries.length; i++) {
|
||||
caps[_beneficiaries[i]] = _cap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the cap of a specific user.
|
||||
* @param _beneficiary Address whose cap is to be checked
|
||||
* @return Current cap for individual user
|
||||
*/
|
||||
function getUserCap(address _beneficiary) public view returns (uint256) {
|
||||
return caps[_beneficiary];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the amount contributed so far by a sepecific user.
|
||||
* @param _beneficiary Address of contributor
|
||||
* @return User contribution so far
|
||||
*/
|
||||
function getUserContribution(address _beneficiary)
|
||||
public view returns (uint256)
|
||||
{
|
||||
return contributions[_beneficiary];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior requiring purchase to respect the user's funding cap.
|
||||
* @param _beneficiary Token purchaser
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
internal
|
||||
{
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
require(contributions[_beneficiary].add(_weiAmount) <= caps[_beneficiary]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Extend parent behavior to update user 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);
|
||||
}
|
||||
|
||||
}
|
||||
64
contracts/crowdsale/validation/TimedCrowdsale.sol
Normal file
64
contracts/crowdsale/validation/TimedCrowdsale.sol
Normal file
@ -0,0 +1,64 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../math/SafeMath.sol";
|
||||
import "../Crowdsale.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title TimedCrowdsale
|
||||
* @dev Crowdsale accepting contributions only within a time frame.
|
||||
*/
|
||||
contract TimedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public openingTime;
|
||||
uint256 public closingTime;
|
||||
|
||||
/**
|
||||
* @dev Reverts if not in crowdsale time range.
|
||||
*/
|
||||
modifier onlyWhileOpen {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
require(block.timestamp >= openingTime && block.timestamp <= closingTime);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Constructor, takes crowdsale opening and closing times.
|
||||
* @param _openingTime Crowdsale opening time
|
||||
* @param _closingTime Crowdsale closing time
|
||||
*/
|
||||
constructor(uint256 _openingTime, uint256 _closingTime) public {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
require(_openingTime >= block.timestamp);
|
||||
require(_closingTime >= _openingTime);
|
||||
|
||||
openingTime = _openingTime;
|
||||
closingTime = _closingTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks whether the period in which the crowdsale is open has already elapsed.
|
||||
* @return Whether crowdsale period has elapsed
|
||||
*/
|
||||
function hasClosed() public view returns (bool) {
|
||||
// solium-disable-next-line security/no-block-members
|
||||
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
|
||||
{
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
|
||||
}
|
||||
27
contracts/crowdsale/validation/WhitelistedCrowdsale.sol
Normal file
27
contracts/crowdsale/validation/WhitelistedCrowdsale.sol
Normal file
@ -0,0 +1,27 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../Crowdsale.sol";
|
||||
import "../../access/Whitelist.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title WhitelistedCrowdsale
|
||||
* @dev Crowdsale in which only whitelisted users can contribute.
|
||||
*/
|
||||
contract WhitelistedCrowdsale is Whitelist, Crowdsale {
|
||||
/**
|
||||
* @dev Extend parent behavior requiring beneficiary to be in whitelist.
|
||||
* @param _beneficiary Token beneficiary
|
||||
* @param _weiAmount Amount of wei contributed
|
||||
*/
|
||||
function _preValidatePurchase(
|
||||
address _beneficiary,
|
||||
uint256 _weiAmount
|
||||
)
|
||||
internal
|
||||
onlyIfWhitelisted(_beneficiary)
|
||||
{
|
||||
super._preValidatePurchase(_beneficiary, _weiAmount);
|
||||
}
|
||||
|
||||
}
|
||||
66
contracts/examples/RBACWithAdmin.sol
Normal file
66
contracts/examples/RBACWithAdmin.sol
Normal file
@ -0,0 +1,66 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../access/rbac/RBAC.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title RBACWithAdmin
|
||||
* @author Matt Condon (@Shrugs)
|
||||
* @dev It's recommended that you define constants in the contract,
|
||||
* like ROLE_ADMIN below, to avoid typos.
|
||||
* @notice RBACWithAdmin is probably too expansive and powerful for your
|
||||
* application; an admin is actually able to change any address to any role
|
||||
* which is a very large API surface. It's recommended that you follow a strategy
|
||||
* of strictly defining the abilities of your roles
|
||||
* and the API-surface of your contract.
|
||||
* This is just an example for example's sake.
|
||||
*/
|
||||
contract RBACWithAdmin is RBAC {
|
||||
/**
|
||||
* A constant role name for indicating admins.
|
||||
*/
|
||||
string public constant ROLE_ADMIN = "admin";
|
||||
|
||||
/**
|
||||
* @dev modifier to scope access to admins
|
||||
* // reverts
|
||||
*/
|
||||
modifier onlyAdmin()
|
||||
{
|
||||
checkRole(msg.sender, ROLE_ADMIN);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev constructor. Sets msg.sender as admin by default
|
||||
*/
|
||||
constructor()
|
||||
public
|
||||
{
|
||||
addRole(msg.sender, ROLE_ADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add a role to an address
|
||||
* @param _addr address
|
||||
* @param _roleName the name of the role
|
||||
*/
|
||||
function adminAddRole(address _addr, string _roleName)
|
||||
public
|
||||
onlyAdmin
|
||||
{
|
||||
addRole(_addr, _roleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove a role from an address
|
||||
* @param _addr address
|
||||
* @param _roleName the name of the role
|
||||
*/
|
||||
function adminRemoveRole(address _addr, string _roleName)
|
||||
public
|
||||
onlyAdmin
|
||||
{
|
||||
removeRole(_addr, _roleName);
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,10 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||
import "../crowdsale/emission/MintedCrowdsale.sol";
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
|
||||
import "../crowdsale/CappedCrowdsale.sol";
|
||||
import "../crowdsale/RefundableCrowdsale.sol";
|
||||
import "../token/MintableToken.sol";
|
||||
|
||||
/**
|
||||
* @title SampleCrowdsaleToken
|
||||
@ -17,6 +19,7 @@ contract SampleCrowdsaleToken is MintableToken {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @title SampleCrowdsale
|
||||
* @dev This is an example of a fully fledged crowdsale.
|
||||
@ -28,21 +31,30 @@ contract SampleCrowdsaleToken is MintableToken {
|
||||
* After adding multiple features it's good practice to run integration tests
|
||||
* to ensure that subcontracts works together as intended.
|
||||
*/
|
||||
contract SampleCrowdsale is CappedCrowdsale, RefundableCrowdsale {
|
||||
// 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 {
|
||||
|
||||
function SampleCrowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, uint256 _goal, uint256 _cap, address _wallet)
|
||||
constructor(
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
uint256 _cap,
|
||||
MintableToken _token,
|
||||
uint256 _goal
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
CappedCrowdsale(_cap)
|
||||
FinalizableCrowdsale()
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
RefundableCrowdsale(_goal)
|
||||
Crowdsale(_startTime, _endTime, _rate, _wallet)
|
||||
{
|
||||
//As goal needs to be met for a successful crowdsale
|
||||
//the value needs to less or equal than a cap which is limit for accepted funds
|
||||
require(_goal <= _cap);
|
||||
}
|
||||
|
||||
function createTokenContract() internal returns (MintableToken) {
|
||||
return new SampleCrowdsaleToken();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
40
contracts/examples/SimpleSavingsWallet.sol
Normal file
40
contracts/examples/SimpleSavingsWallet.sol
Normal file
@ -0,0 +1,40 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../ownership/Heritable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title SimpleSavingsWallet
|
||||
* @dev Simplest form of savings wallet whose ownership can be claimed by a heir
|
||||
* if owner dies.
|
||||
* In this example, we take a very simple savings wallet providing two operations
|
||||
* (to send and receive funds) and extend its capabilities by making it Heritable.
|
||||
* The account that creates the contract is set as owner, who has the authority to
|
||||
* choose an heir account. Heir account can reclaim the contract ownership in the
|
||||
* case that the owner dies.
|
||||
*/
|
||||
contract SimpleSavingsWallet is Heritable {
|
||||
|
||||
event Sent(address indexed payee, uint256 amount, uint256 balance);
|
||||
event Received(address indexed payer, uint256 amount, uint256 balance);
|
||||
|
||||
|
||||
constructor(uint256 _heartbeatTimeout) Heritable(_heartbeatTimeout) public {}
|
||||
|
||||
/**
|
||||
* @dev wallet can receive funds.
|
||||
*/
|
||||
function () external payable {
|
||||
emit Received(msg.sender, msg.value, address(this).balance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev wallet can send funds
|
||||
*/
|
||||
function sendTo(address _payee, uint256 _amount) public onlyOwner {
|
||||
require(_payee != address(0) && _payee != address(this));
|
||||
require(_amount > 0);
|
||||
_payee.transfer(_amount);
|
||||
emit Sent(_payee, _amount, address(this).balance);
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../token/StandardToken.sol";
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
|
||||
|
||||
/**
|
||||
@ -21,9 +21,10 @@ contract SimpleToken is StandardToken {
|
||||
/**
|
||||
* @dev Constructor that gives msg.sender all of existing tokens.
|
||||
*/
|
||||
function SimpleToken() {
|
||||
totalSupply = INITIAL_SUPPLY;
|
||||
constructor() public {
|
||||
totalSupply_ = INITIAL_SUPPLY;
|
||||
balances[msg.sender] = INITIAL_SUPPLY;
|
||||
emit Transfer(address(0), msg.sender, INITIAL_SUPPLY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
20
contracts/introspection/ERC165.sol
Normal file
20
contracts/introspection/ERC165.sol
Normal file
@ -0,0 +1,20 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC165
|
||||
* @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
|
||||
*/
|
||||
interface ERC165 {
|
||||
|
||||
/**
|
||||
* @notice Query if a contract implements an interface
|
||||
* @param _interfaceId The interface identifier, as specified in ERC-165
|
||||
* @dev Interface identification is specified in ERC-165. This function
|
||||
* uses less than 30,000 gas.
|
||||
*/
|
||||
function supportsInterface(bytes4 _interfaceId)
|
||||
external
|
||||
view
|
||||
returns (bool);
|
||||
}
|
||||
54
contracts/introspection/SupportsInterfaceWithLookup.sol
Normal file
54
contracts/introspection/SupportsInterfaceWithLookup.sol
Normal file
@ -0,0 +1,54 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "./ERC165.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title SupportsInterfaceWithLookup
|
||||
* @author Matt Condon (@shrugs)
|
||||
* @dev Implements ERC165 using a lookup table.
|
||||
*/
|
||||
contract SupportsInterfaceWithLookup is ERC165 {
|
||||
|
||||
bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7;
|
||||
/**
|
||||
* 0x01ffc9a7 ===
|
||||
* bytes4(keccak256('supportsInterface(bytes4)'))
|
||||
*/
|
||||
|
||||
/**
|
||||
* @dev a mapping of interface id to whether or not it's supported
|
||||
*/
|
||||
mapping(bytes4 => bool) internal supportedInterfaces;
|
||||
|
||||
/**
|
||||
* @dev A contract implementing SupportsInterfaceWithLookup
|
||||
* implement ERC165 itself
|
||||
*/
|
||||
constructor()
|
||||
public
|
||||
{
|
||||
_registerInterface(InterfaceId_ERC165);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev implement supportsInterface(bytes4) using a lookup table
|
||||
*/
|
||||
function supportsInterface(bytes4 _interfaceId)
|
||||
external
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return supportedInterfaces[_interfaceId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev private method for registering an interface
|
||||
*/
|
||||
function _registerInterface(bytes4 _interfaceId)
|
||||
internal
|
||||
{
|
||||
require(_interfaceId != 0xffffffff);
|
||||
supportedInterfaces[_interfaceId] = true;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
@ -9,17 +9,14 @@ import "../ownership/Ownable.sol";
|
||||
* @dev Base contract that can be destroyed by owner. All funds in contract will be sent to the owner.
|
||||
*/
|
||||
contract Destructible is Ownable {
|
||||
|
||||
function Destructible() payable { }
|
||||
|
||||
/**
|
||||
* @dev Transfers the current balance to the owner and terminates the contract.
|
||||
*/
|
||||
function destroy() onlyOwner public {
|
||||
function destroy() public onlyOwner {
|
||||
selfdestruct(owner);
|
||||
}
|
||||
|
||||
function destroyAndSend(address _recipient) onlyOwner public {
|
||||
function destroyAndSend(address _recipient) public onlyOwner {
|
||||
selfdestruct(_recipient);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
|
||||
import '../ownership/Ownable.sol';
|
||||
|
||||
/**
|
||||
* @title Migrations
|
||||
* @dev This is a truffle contract, needed for truffle integration, not meant for use by Zeppelin users.
|
||||
*/
|
||||
contract Migrations is Ownable {
|
||||
uint256 public lastCompletedMigration;
|
||||
|
||||
function setCompleted(uint256 completed) onlyOwner public {
|
||||
lastCompletedMigration = completed;
|
||||
}
|
||||
|
||||
function upgrade(address newAddress) onlyOwner public {
|
||||
Migrations upgraded = Migrations(newAddress);
|
||||
upgraded.setCompleted(lastCompletedMigration);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
@ -34,16 +34,16 @@ contract Pausable is Ownable {
|
||||
/**
|
||||
* @dev called by the owner to pause, triggers stopped state
|
||||
*/
|
||||
function pause() onlyOwner whenNotPaused public {
|
||||
function pause() public onlyOwner whenNotPaused {
|
||||
paused = true;
|
||||
Pause();
|
||||
emit Pause();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev called by the owner to unpause, returns to normal state
|
||||
*/
|
||||
function unpause() onlyOwner whenPaused public {
|
||||
function unpause() public onlyOwner whenPaused {
|
||||
paused = false;
|
||||
Unpause();
|
||||
emit Unpause();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../ownership/Ownable.sol";
|
||||
import "../token/ERC20Basic.sol";
|
||||
import "../token/ERC20/ERC20Basic.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title TokenDestructible:
|
||||
@ -12,20 +12,20 @@ import "../token/ERC20Basic.sol";
|
||||
*/
|
||||
contract TokenDestructible is Ownable {
|
||||
|
||||
function TokenDestructible() payable { }
|
||||
constructor() public payable { }
|
||||
|
||||
/**
|
||||
* @notice Terminate contract and refund to owner
|
||||
* @param tokens List of addresses of ERC20 or ERC20Basic token contracts to
|
||||
* @param _tokens List of addresses of ERC20 or ERC20Basic token contracts to
|
||||
refund.
|
||||
* @notice The called token contracts could try to re-enter this contract. Only
|
||||
supply token contracts you trust.
|
||||
*/
|
||||
function destroy(address[] tokens) onlyOwner public {
|
||||
function destroy(address[] _tokens) public onlyOwner {
|
||||
|
||||
// Transfer tokens to owner
|
||||
for(uint256 i = 0; i < tokens.length; i++) {
|
||||
ERC20Basic token = ERC20Basic(tokens[i]);
|
||||
for (uint256 i = 0; i < _tokens.length; i++) {
|
||||
ERC20Basic token = ERC20Basic(_tokens[i]);
|
||||
uint256 balance = token.balanceOf(this);
|
||||
token.transfer(owner, balance);
|
||||
}
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
* @title Math
|
||||
* @dev Assorted math operations
|
||||
*/
|
||||
|
||||
library Math {
|
||||
function max64(uint64 a, uint64 b) internal constant returns (uint64) {
|
||||
return a >= b ? a : b;
|
||||
function max64(uint64 _a, uint64 _b) internal pure returns (uint64) {
|
||||
return _a >= _b ? _a : _b;
|
||||
}
|
||||
|
||||
function min64(uint64 a, uint64 b) internal constant returns (uint64) {
|
||||
return a < b ? a : b;
|
||||
function min64(uint64 _a, uint64 _b) internal pure returns (uint64) {
|
||||
return _a < _b ? _a : _b;
|
||||
}
|
||||
|
||||
function max256(uint256 a, uint256 b) internal constant returns (uint256) {
|
||||
return a >= b ? a : b;
|
||||
function max256(uint256 _a, uint256 _b) internal pure returns (uint256) {
|
||||
return _a >= _b ? _a : _b;
|
||||
}
|
||||
|
||||
function min256(uint256 a, uint256 b) internal constant returns (uint256) {
|
||||
return a < b ? a : b;
|
||||
function min256(uint256 _a, uint256 _b) internal pure returns (uint256) {
|
||||
return _a < _b ? _a : _b;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
/**
|
||||
@ -6,27 +6,47 @@ pragma solidity ^0.4.11;
|
||||
* @dev Math operations with safety checks that throw on error
|
||||
*/
|
||||
library SafeMath {
|
||||
function mul(uint256 a, uint256 b) internal constant returns (uint256) {
|
||||
uint256 c = a * b;
|
||||
assert(a == 0 || c / a == b);
|
||||
|
||||
/**
|
||||
* @dev Multiplies two numbers, throws on overflow.
|
||||
*/
|
||||
function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
|
||||
// Gas optimization: this is cheaper than asserting '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;
|
||||
}
|
||||
|
||||
c = _a * _b;
|
||||
assert(c / _a == _b);
|
||||
return c;
|
||||
}
|
||||
|
||||
function div(uint256 a, uint256 b) internal constant returns (uint256) {
|
||||
// assert(b > 0); // Solidity automatically throws when dividing by 0
|
||||
uint256 c = a / b;
|
||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
||||
return c;
|
||||
/**
|
||||
* @dev Integer division of two numbers, truncating the quotient.
|
||||
*/
|
||||
function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
|
||||
// assert(_b > 0); // Solidity automatically throws when dividing by 0
|
||||
// uint256 c = _a / _b;
|
||||
// assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
|
||||
return _a / _b;
|
||||
}
|
||||
|
||||
function sub(uint256 a, uint256 b) internal constant returns (uint256) {
|
||||
assert(b <= a);
|
||||
return a - b;
|
||||
/**
|
||||
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
|
||||
*/
|
||||
function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
|
||||
assert(_b <= _a);
|
||||
return _a - _b;
|
||||
}
|
||||
|
||||
function add(uint256 a, uint256 b) internal constant returns (uint256) {
|
||||
uint256 c = a + b;
|
||||
assert(c >= a);
|
||||
/**
|
||||
* @dev Adds two numbers, throws on overflow.
|
||||
*/
|
||||
function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
|
||||
c = _a + _b;
|
||||
assert(c >= _a);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
21
contracts/mocks/AllowanceCrowdsaleImpl.sol
Normal file
21
contracts/mocks/AllowanceCrowdsaleImpl.sol
Normal file
@ -0,0 +1,21 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/emission/AllowanceCrowdsale.sol";
|
||||
|
||||
|
||||
contract AllowanceCrowdsaleImpl is AllowanceCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token,
|
||||
address _tokenWallet
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
AllowanceCrowdsale(_tokenWallet)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
21
contracts/mocks/AutoIncrementingImpl.sol
Normal file
21
contracts/mocks/AutoIncrementingImpl.sol
Normal file
@ -0,0 +1,21 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../AutoIncrementing.sol";
|
||||
|
||||
|
||||
contract AutoIncrementingImpl {
|
||||
using AutoIncrementing for AutoIncrementing.Counter;
|
||||
|
||||
uint256 public theId;
|
||||
|
||||
// use whatever key you want to track your counters
|
||||
mapping(string => AutoIncrementing.Counter) private counters;
|
||||
|
||||
function doThing(string _key)
|
||||
public
|
||||
returns (uint256)
|
||||
{
|
||||
theId = counters[_key].nextId();
|
||||
return theId;
|
||||
}
|
||||
}
|
||||
15
contracts/mocks/BasicTokenMock.sol
Normal file
15
contracts/mocks/BasicTokenMock.sol
Normal file
@ -0,0 +1,15 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../token/ERC20/BasicToken.sol";
|
||||
|
||||
|
||||
// mock class using BasicToken
|
||||
contract BasicTokenMock is BasicToken {
|
||||
|
||||
constructor(address _initialAccount, uint256 _initialBalance) public {
|
||||
balances[_initialAccount] = _initialBalance;
|
||||
totalSupply_ = _initialBalance;
|
||||
}
|
||||
|
||||
}
|
||||
66
contracts/mocks/BouncerMock.sol
Normal file
66
contracts/mocks/BouncerMock.sol
Normal file
@ -0,0 +1,66 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../access/SignatureBouncer.sol";
|
||||
|
||||
|
||||
contract SignatureBouncerMock is SignatureBouncer {
|
||||
function checkValidSignature(address _address, bytes _sig)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return isValidSignature(_address, _sig);
|
||||
}
|
||||
|
||||
function onlyWithValidSignature(bytes _sig)
|
||||
public
|
||||
onlyValidSignature(_sig)
|
||||
view
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
function checkValidSignatureAndMethod(address _address, bytes _sig)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return isValidSignatureAndMethod(_address, _sig);
|
||||
}
|
||||
|
||||
function onlyWithValidSignatureAndMethod(bytes _sig)
|
||||
public
|
||||
onlyValidSignatureAndMethod(_sig)
|
||||
view
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
function checkValidSignatureAndData(
|
||||
address _address,
|
||||
bytes,
|
||||
uint,
|
||||
bytes _sig
|
||||
)
|
||||
public
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
return isValidSignatureAndData(_address, _sig);
|
||||
}
|
||||
|
||||
function onlyWithValidSignatureAndData(uint, bytes _sig)
|
||||
public
|
||||
onlyValidSignatureAndData(_sig)
|
||||
view
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
function theWrongMethod(bytes)
|
||||
public
|
||||
pure
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
13
contracts/mocks/BurnableTokenMock.sol
Normal file
13
contracts/mocks/BurnableTokenMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/BurnableToken.sol";
|
||||
|
||||
|
||||
contract BurnableTokenMock is BurnableToken {
|
||||
|
||||
constructor(address _initialAccount, uint _initialBalance) public {
|
||||
balances[_initialAccount] = _initialBalance;
|
||||
totalSupply_ = _initialBalance;
|
||||
}
|
||||
|
||||
}
|
||||
21
contracts/mocks/CappedCrowdsaleImpl.sol
Normal file
21
contracts/mocks/CappedCrowdsaleImpl.sol
Normal file
@ -0,0 +1,21 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/CappedCrowdsale.sol";
|
||||
|
||||
|
||||
contract CappedCrowdsaleImpl is CappedCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token,
|
||||
uint256 _cap
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
CappedCrowdsale(_cap)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
18
contracts/mocks/ConditionalEscrowMock.sol
Normal file
18
contracts/mocks/ConditionalEscrowMock.sol
Normal file
@ -0,0 +1,18 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../payment/ConditionalEscrow.sol";
|
||||
|
||||
|
||||
// mock class using ConditionalEscrow
|
||||
contract ConditionalEscrowMock is ConditionalEscrow {
|
||||
mapping(address => bool) public allowed;
|
||||
|
||||
function setAllowed(address _payee, bool _allowed) public {
|
||||
allowed[_payee] = _allowed;
|
||||
}
|
||||
|
||||
function withdrawalAllowed(address _payee) public view returns (bool) {
|
||||
return allowed[_payee];
|
||||
}
|
||||
}
|
||||
8
contracts/mocks/DestructibleMock.sol
Normal file
8
contracts/mocks/DestructibleMock.sol
Normal file
@ -0,0 +1,8 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../lifecycle/Destructible.sol";
|
||||
|
||||
|
||||
contract DestructibleMock is Destructible {
|
||||
function() public payable {}
|
||||
}
|
||||
16
contracts/mocks/DetailedERC20Mock.sol
Normal file
16
contracts/mocks/DetailedERC20Mock.sol
Normal file
@ -0,0 +1,16 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
import "../token/ERC20/DetailedERC20.sol";
|
||||
|
||||
|
||||
contract DetailedERC20Mock is StandardToken, DetailedERC20 {
|
||||
constructor(
|
||||
string _name,
|
||||
string _symbol,
|
||||
uint8 _decimals
|
||||
)
|
||||
DetailedERC20(_name, _symbol, _decimals)
|
||||
public
|
||||
{}
|
||||
}
|
||||
25
contracts/mocks/ECRecoveryMock.sol
Normal file
25
contracts/mocks/ECRecoveryMock.sol
Normal file
@ -0,0 +1,25 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../ECRecovery.sol";
|
||||
|
||||
|
||||
contract ECRecoveryMock {
|
||||
using ECRecovery for bytes32;
|
||||
|
||||
function recover(bytes32 _hash, bytes _sig)
|
||||
public
|
||||
pure
|
||||
returns (address)
|
||||
{
|
||||
return _hash.recover(_sig);
|
||||
}
|
||||
|
||||
function toEthSignedMessageHash(bytes32 _hash)
|
||||
public
|
||||
pure
|
||||
returns (bytes32)
|
||||
{
|
||||
return _hash.toEthSignedMessageHash();
|
||||
}
|
||||
}
|
||||
12
contracts/mocks/ERC20WithMetadataMock.sol
Normal file
12
contracts/mocks/ERC20WithMetadataMock.sol
Normal file
@ -0,0 +1,12 @@
|
||||
pragma solidity ^0.4.21;
|
||||
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
import "../proposals/ERC1046/TokenMetadata.sol";
|
||||
|
||||
|
||||
contract ERC20WithMetadataMock is StandardToken, ERC20WithMetadata {
|
||||
constructor(string _tokenURI) public
|
||||
ERC20WithMetadata(_tokenURI)
|
||||
{
|
||||
}
|
||||
}
|
||||
34
contracts/mocks/ERC223TokenMock.sol
Normal file
34
contracts/mocks/ERC223TokenMock.sol
Normal file
@ -0,0 +1,34 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/BasicToken.sol";
|
||||
|
||||
|
||||
contract ERC223ContractInterface {
|
||||
function tokenFallback(address _from, uint256 _value, bytes _data) external;
|
||||
}
|
||||
|
||||
|
||||
contract ERC223TokenMock is BasicToken {
|
||||
|
||||
constructor(address _initialAccount, uint256 _initialBalance) public {
|
||||
balances[_initialAccount] = _initialBalance;
|
||||
totalSupply_ = _initialBalance;
|
||||
}
|
||||
|
||||
// ERC223 compatible transfer function (except the name)
|
||||
function transferERC223(address _to, uint256 _value, bytes _data) public
|
||||
returns (bool success)
|
||||
{
|
||||
transfer(_to, _value);
|
||||
bool isContract = false;
|
||||
// solium-disable-next-line security/no-inline-assembly
|
||||
assembly {
|
||||
isContract := not(iszero(extcodesize(_to)))
|
||||
}
|
||||
if (isContract) {
|
||||
ERC223ContractInterface receiver = ERC223ContractInterface(_to);
|
||||
receiver.tokenFallback(msg.sender, _value, _data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
18
contracts/mocks/ERC721BasicTokenMock.sol
Normal file
18
contracts/mocks/ERC721BasicTokenMock.sol
Normal file
@ -0,0 +1,18 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC721/ERC721BasicToken.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC721BasicTokenMock
|
||||
* This mock just provides a public mint and burn functions for testing purposes
|
||||
*/
|
||||
contract ERC721BasicTokenMock is ERC721BasicToken {
|
||||
function mint(address _to, uint256 _tokenId) public {
|
||||
super._mint(_to, _tokenId);
|
||||
}
|
||||
|
||||
function burn(uint256 _tokenId) public {
|
||||
super._burn(ownerOf(_tokenId), _tokenId);
|
||||
}
|
||||
}
|
||||
42
contracts/mocks/ERC721ReceiverMock.sol
Normal file
42
contracts/mocks/ERC721ReceiverMock.sol
Normal file
@ -0,0 +1,42 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC721/ERC721Receiver.sol";
|
||||
|
||||
|
||||
contract ERC721ReceiverMock is ERC721Receiver {
|
||||
bytes4 retval;
|
||||
bool reverts;
|
||||
|
||||
event Received(
|
||||
address _operator,
|
||||
address _from,
|
||||
uint256 _tokenId,
|
||||
bytes _data,
|
||||
uint256 _gas
|
||||
);
|
||||
|
||||
constructor(bytes4 _retval, bool _reverts) public {
|
||||
retval = _retval;
|
||||
reverts = _reverts;
|
||||
}
|
||||
|
||||
function onERC721Received(
|
||||
address _operator,
|
||||
address _from,
|
||||
uint256 _tokenId,
|
||||
bytes _data
|
||||
)
|
||||
public
|
||||
returns(bytes4)
|
||||
{
|
||||
require(!reverts);
|
||||
emit Received(
|
||||
_operator,
|
||||
_from,
|
||||
_tokenId,
|
||||
_data,
|
||||
gasleft() // msg.gas was deprecated in solidityv0.4.21
|
||||
);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
31
contracts/mocks/ERC721TokenMock.sol
Normal file
31
contracts/mocks/ERC721TokenMock.sol
Normal file
@ -0,0 +1,31 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC721/ERC721Token.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title ERC721TokenMock
|
||||
* This mock just provides a public mint and burn functions for testing purposes,
|
||||
* and a public setter for metadata URI
|
||||
*/
|
||||
contract ERC721TokenMock is ERC721Token {
|
||||
constructor(string name, string symbol) public
|
||||
ERC721Token(name, symbol)
|
||||
{ }
|
||||
|
||||
function mint(address _to, uint256 _tokenId) public {
|
||||
super._mint(_to, _tokenId);
|
||||
}
|
||||
|
||||
function burn(uint256 _tokenId) public {
|
||||
super._burn(ownerOf(_tokenId), _tokenId);
|
||||
}
|
||||
|
||||
function setTokenURI(uint256 _tokenId, string _uri) public {
|
||||
super._setTokenURI(_tokenId, _uri);
|
||||
}
|
||||
|
||||
function _removeTokenFrom(address _from, uint256 _tokenId) public {
|
||||
super.removeTokenFrom(_from, _tokenId);
|
||||
}
|
||||
}
|
||||
22
contracts/mocks/FinalizableCrowdsaleImpl.sol
Normal file
22
contracts/mocks/FinalizableCrowdsaleImpl.sol
Normal file
@ -0,0 +1,22 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
import "../crowdsale/distribution/FinalizableCrowdsale.sol";
|
||||
|
||||
|
||||
contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
MintableToken _token
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,15 +1,16 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
// @title Force Ether into a contract.
|
||||
// @notice even
|
||||
// if the contract is not payable.
|
||||
// @notice To use, construct the contract with the target as argument.
|
||||
// @author Remco Bloemen <remco@neufund.org>
|
||||
contract ForceEther {
|
||||
contract ForceEther {
|
||||
|
||||
function ForceEther() payable { }
|
||||
constructor() public payable { }
|
||||
|
||||
function destroyAndSend(address _recipient) {
|
||||
function destroyAndSend(address _recipient) public {
|
||||
selfdestruct(_recipient);
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,12 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../../contracts/ownership/HasNoEther.sol";
|
||||
|
||||
|
||||
contract HasNoEtherTest is HasNoEther {
|
||||
|
||||
// Constructor with explicit payable — should still fail
|
||||
function HasNoEtherTest() payable {
|
||||
constructor() public payable {
|
||||
}
|
||||
|
||||
}
|
||||
24
contracts/mocks/IncreasingPriceCrowdsaleImpl.sol
Normal file
24
contracts/mocks/IncreasingPriceCrowdsaleImpl.sol
Normal file
@ -0,0 +1,24 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../crowdsale/price/IncreasingPriceCrowdsale.sol";
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
|
||||
contract IncreasingPriceCrowdsaleImpl is IncreasingPriceCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
address _wallet,
|
||||
ERC20 _token,
|
||||
uint256 _initialRate,
|
||||
uint256 _finalRate
|
||||
)
|
||||
public
|
||||
Crowdsale(_initialRate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
IncreasingPriceCrowdsale(_initialRate, _finalRate)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
19
contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol
Normal file
19
contracts/mocks/IndividuallyCappedCrowdsaleImpl.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/IndividuallyCappedCrowdsale.sol";
|
||||
|
||||
|
||||
contract IndividuallyCappedCrowdsaleImpl is IndividuallyCappedCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,15 +1,15 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import {Bounty, Target} from "../../contracts/Bounty.sol";
|
||||
|
||||
|
||||
contract InsecureTargetMock is Target {
|
||||
function checkInvariant() returns(bool){
|
||||
function checkInvariant() public returns(bool) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract InsecureTargetBounty is Bounty {
|
||||
function deployContract() internal returns (address) {
|
||||
return new InsecureTargetMock();
|
||||
13
contracts/mocks/LimitBalanceMock.sol
Normal file
13
contracts/mocks/LimitBalanceMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../LimitBalance.sol";
|
||||
|
||||
|
||||
// mock class using LimitBalance
|
||||
contract LimitBalanceMock is LimitBalance(1000) {
|
||||
|
||||
function limitedDeposit() public payable limitedPayable {
|
||||
}
|
||||
|
||||
}
|
||||
26
contracts/mocks/MathMock.sol
Normal file
26
contracts/mocks/MathMock.sol
Normal file
@ -0,0 +1,26 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../../contracts/math/Math.sol";
|
||||
|
||||
|
||||
contract MathMock {
|
||||
uint64 public result64;
|
||||
uint256 public result256;
|
||||
|
||||
function max64(uint64 _a, uint64 _b) public {
|
||||
result64 = Math.max64(_a, _b);
|
||||
}
|
||||
|
||||
function min64(uint64 _a, uint64 _b) public {
|
||||
result64 = Math.min64(_a, _b);
|
||||
}
|
||||
|
||||
function max256(uint256 _a, uint256 _b) public {
|
||||
result256 = Math.max256(_a, _b);
|
||||
}
|
||||
|
||||
function min256(uint256 _a, uint256 _b) public {
|
||||
result256 = Math.min256(_a, _b);
|
||||
}
|
||||
}
|
||||
19
contracts/mocks/MerkleProofWrapper.sol
Normal file
19
contracts/mocks/MerkleProofWrapper.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import { MerkleProof } from "../MerkleProof.sol";
|
||||
|
||||
|
||||
contract MerkleProofWrapper {
|
||||
|
||||
function verifyProof(
|
||||
bytes32[] _proof,
|
||||
bytes32 _root,
|
||||
bytes32 _leaf
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bool)
|
||||
{
|
||||
return MerkleProof.verifyProof(_proof, _root, _leaf);
|
||||
}
|
||||
}
|
||||
50
contracts/mocks/MessageHelper.sol
Normal file
50
contracts/mocks/MessageHelper.sol
Normal file
@ -0,0 +1,50 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
contract MessageHelper {
|
||||
|
||||
event Show(bytes32 b32, uint256 number, string text);
|
||||
event Buy(bytes32 b32, uint256 number, string text, uint256 value);
|
||||
|
||||
function showMessage(
|
||||
bytes32 _message,
|
||||
uint256 _number,
|
||||
string _text
|
||||
)
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
emit Show(_message, _number, _text);
|
||||
return true;
|
||||
}
|
||||
|
||||
function buyMessage(
|
||||
bytes32 _message,
|
||||
uint256 _number,
|
||||
string _text
|
||||
)
|
||||
public
|
||||
payable
|
||||
returns (bool)
|
||||
{
|
||||
emit Buy(
|
||||
_message,
|
||||
_number,
|
||||
_text,
|
||||
msg.value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function fail() public {
|
||||
require(false);
|
||||
}
|
||||
|
||||
function call(address _to, bytes _data) public returns (bool) {
|
||||
// solium-disable-next-line security/no-low-level-calls
|
||||
if (_to.call(_data))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
19
contracts/mocks/MintedCrowdsaleImpl.sol
Normal file
19
contracts/mocks/MintedCrowdsaleImpl.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
import "../crowdsale/emission/MintedCrowdsale.sol";
|
||||
|
||||
|
||||
contract MintedCrowdsaleImpl is MintedCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
MintableToken _token
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import '../../contracts/lifecycle/Pausable.sol';
|
||||
import "../lifecycle/Pausable.sol";
|
||||
|
||||
|
||||
// mock class using Pausable
|
||||
@ -9,7 +9,7 @@ contract PausableMock is Pausable {
|
||||
bool public drasticMeasureTaken;
|
||||
uint256 public count;
|
||||
|
||||
function PausableMock() {
|
||||
constructor() public {
|
||||
drasticMeasureTaken = false;
|
||||
count = 0;
|
||||
}
|
||||
13
contracts/mocks/PausableTokenMock.sol
Normal file
13
contracts/mocks/PausableTokenMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/PausableToken.sol";
|
||||
|
||||
|
||||
// mock class using PausableToken
|
||||
contract PausableTokenMock is PausableToken {
|
||||
|
||||
constructor(address _initialAccount, uint _initialBalance) public {
|
||||
balances[_initialAccount] = _initialBalance;
|
||||
}
|
||||
|
||||
}
|
||||
22
contracts/mocks/PostDeliveryCrowdsaleImpl.sol
Normal file
22
contracts/mocks/PostDeliveryCrowdsaleImpl.sol
Normal file
@ -0,0 +1,22 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/distribution/PostDeliveryCrowdsale.sol";
|
||||
|
||||
|
||||
contract PostDeliveryCrowdsaleImpl is PostDeliveryCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
public
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
17
contracts/mocks/PullPaymentMock.sol
Normal file
17
contracts/mocks/PullPaymentMock.sol
Normal file
@ -0,0 +1,17 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../payment/PullPayment.sol";
|
||||
|
||||
|
||||
// mock class using PullPayment
|
||||
contract PullPaymentMock is PullPayment {
|
||||
|
||||
constructor() public payable { }
|
||||
|
||||
// test helper function to call asyncTransfer
|
||||
function callTransfer(address _dest, uint256 _amount) public {
|
||||
asyncTransfer(_dest, _amount);
|
||||
}
|
||||
|
||||
}
|
||||
12
contracts/mocks/RBACCappedTokenMock.sol
Normal file
12
contracts/mocks/RBACCappedTokenMock.sol
Normal file
@ -0,0 +1,12 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/RBACMintableToken.sol";
|
||||
import "../token/ERC20/CappedToken.sol";
|
||||
|
||||
|
||||
contract RBACCappedTokenMock is CappedToken, RBACMintableToken {
|
||||
constructor(uint256 _cap)
|
||||
CappedToken(_cap)
|
||||
public
|
||||
{}
|
||||
}
|
||||
69
contracts/mocks/RBACMock.sol
Normal file
69
contracts/mocks/RBACMock.sol
Normal file
@ -0,0 +1,69 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../examples/RBACWithAdmin.sol";
|
||||
|
||||
|
||||
contract RBACMock is RBACWithAdmin {
|
||||
|
||||
string constant ROLE_ADVISOR = "advisor";
|
||||
|
||||
modifier onlyAdminOrAdvisor()
|
||||
{
|
||||
require(
|
||||
hasRole(msg.sender, ROLE_ADMIN) ||
|
||||
hasRole(msg.sender, ROLE_ADVISOR)
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
constructor(address[] _advisors)
|
||||
public
|
||||
{
|
||||
addRole(msg.sender, ROLE_ADVISOR);
|
||||
|
||||
for (uint256 i = 0; i < _advisors.length; i++) {
|
||||
addRole(_advisors[i], ROLE_ADVISOR);
|
||||
}
|
||||
}
|
||||
|
||||
function onlyAdminsCanDoThis()
|
||||
external
|
||||
onlyAdmin
|
||||
view
|
||||
{
|
||||
}
|
||||
|
||||
function onlyAdvisorsCanDoThis()
|
||||
external
|
||||
onlyRole(ROLE_ADVISOR)
|
||||
view
|
||||
{
|
||||
}
|
||||
|
||||
function eitherAdminOrAdvisorCanDoThis()
|
||||
external
|
||||
onlyAdminOrAdvisor
|
||||
view
|
||||
{
|
||||
}
|
||||
|
||||
function nobodyCanDoThis()
|
||||
external
|
||||
onlyRole("unknown")
|
||||
view
|
||||
{
|
||||
}
|
||||
|
||||
// admins can remove advisor's role
|
||||
function removeAdvisor(address _addr)
|
||||
public
|
||||
onlyAdmin
|
||||
{
|
||||
// revert if the user isn't an advisor
|
||||
// (perhaps you want to soft-fail here instead?)
|
||||
checkRole(_addr, ROLE_ADVISOR);
|
||||
|
||||
// remove the advisor's role
|
||||
removeRole(_addr, ROLE_ADVISOR);
|
||||
}
|
||||
}
|
||||
11
contracts/mocks/ReentrancyAttack.sol
Normal file
11
contracts/mocks/ReentrancyAttack.sol
Normal file
@ -0,0 +1,11 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
contract ReentrancyAttack {
|
||||
|
||||
function callSender(bytes4 _data) public {
|
||||
// solium-disable-next-line security/no-low-level-calls
|
||||
require(msg.sender.call(abi.encodeWithSelector(_data)));
|
||||
}
|
||||
|
||||
}
|
||||
45
contracts/mocks/ReentrancyMock.sol
Normal file
45
contracts/mocks/ReentrancyMock.sol
Normal file
@ -0,0 +1,45 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../ReentrancyGuard.sol";
|
||||
import "./ReentrancyAttack.sol";
|
||||
|
||||
|
||||
contract ReentrancyMock is ReentrancyGuard {
|
||||
|
||||
uint256 public counter;
|
||||
|
||||
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 {
|
||||
if (_n > 0) {
|
||||
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 {
|
||||
count();
|
||||
bytes4 func = bytes4(keccak256("callback()"));
|
||||
_attacker.callSender(func);
|
||||
}
|
||||
|
||||
function count() private {
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
}
|
||||
24
contracts/mocks/RefundableCrowdsaleImpl.sol
Normal file
24
contracts/mocks/RefundableCrowdsaleImpl.sol
Normal file
@ -0,0 +1,24 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/MintableToken.sol";
|
||||
import "../crowdsale/distribution/RefundableCrowdsale.sol";
|
||||
|
||||
|
||||
contract RefundableCrowdsaleImpl is RefundableCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
MintableToken _token,
|
||||
uint256 _goal
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
RefundableCrowdsale(_goal)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
95
contracts/mocks/SafeERC20Helper.sol
Normal file
95
contracts/mocks/SafeERC20Helper.sol
Normal file
@ -0,0 +1,95 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
|
||||
|
||||
contract ERC20FailingMock is ERC20 {
|
||||
function totalSupply() public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function transfer(address, uint256) public returns (bool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function transferFrom(address, address, uint256) public returns (bool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function approve(address, uint256) public returns (bool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function balanceOf(address) public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function allowance(address, address) public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract ERC20SucceedingMock is ERC20 {
|
||||
function totalSupply() public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function transfer(address, uint256) public returns (bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function transferFrom(address, address, uint256) public returns (bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function approve(address, uint256) public returns (bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function balanceOf(address) public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function allowance(address, address) public view returns (uint256) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract SafeERC20Helper {
|
||||
using SafeERC20 for ERC20;
|
||||
|
||||
ERC20 failing;
|
||||
ERC20 succeeding;
|
||||
|
||||
constructor() public {
|
||||
failing = new ERC20FailingMock();
|
||||
succeeding = new ERC20SucceedingMock();
|
||||
}
|
||||
|
||||
function doFailingTransfer() public {
|
||||
failing.safeTransfer(address(0), 0);
|
||||
}
|
||||
|
||||
function doFailingTransferFrom() public {
|
||||
failing.safeTransferFrom(address(0), address(0), 0);
|
||||
}
|
||||
|
||||
function doFailingApprove() public {
|
||||
failing.safeApprove(address(0), 0);
|
||||
}
|
||||
|
||||
function doSucceedingTransfer() public {
|
||||
succeeding.safeTransfer(address(0), 0);
|
||||
}
|
||||
|
||||
function doSucceedingTransferFrom() public {
|
||||
succeeding.safeTransferFrom(address(0), address(0), 0);
|
||||
}
|
||||
|
||||
function doSucceedingApprove() public {
|
||||
succeeding.safeApprove(address(0), 0);
|
||||
}
|
||||
}
|
||||
24
contracts/mocks/SafeMathMock.sol
Normal file
24
contracts/mocks/SafeMathMock.sol
Normal file
@ -0,0 +1,24 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import "../math/SafeMath.sol";
|
||||
|
||||
|
||||
contract SafeMathMock {
|
||||
|
||||
function mul(uint256 _a, uint256 _b) public pure returns (uint256) {
|
||||
return SafeMath.mul(_a, _b);
|
||||
}
|
||||
|
||||
function div(uint256 _a, uint256 _b) public pure returns (uint256) {
|
||||
return SafeMath.div(_a, _b);
|
||||
}
|
||||
|
||||
function sub(uint256 _a, uint256 _b) public pure returns (uint256) {
|
||||
return SafeMath.sub(_a, _b);
|
||||
}
|
||||
|
||||
function add(uint256 _a, uint256 _b) public pure returns (uint256) {
|
||||
return SafeMath.add(_a, _b);
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,15 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import {Bounty, Target} from "../../contracts/Bounty.sol";
|
||||
|
||||
|
||||
contract SecureTargetMock is Target {
|
||||
function checkInvariant() returns(bool) {
|
||||
function checkInvariant() public returns(bool) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract SecureTargetBounty is Bounty {
|
||||
function deployContract() internal returns (address) {
|
||||
return new SecureTargetMock();
|
||||
13
contracts/mocks/StandardBurnableTokenMock.sol
Normal file
13
contracts/mocks/StandardBurnableTokenMock.sol
Normal file
@ -0,0 +1,13 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/StandardBurnableToken.sol";
|
||||
|
||||
|
||||
contract StandardBurnableTokenMock is StandardBurnableToken {
|
||||
|
||||
constructor(address _initialAccount, uint _initialBalance) public {
|
||||
balances[_initialAccount] = _initialBalance;
|
||||
totalSupply_ = _initialBalance;
|
||||
}
|
||||
|
||||
}
|
||||
14
contracts/mocks/StandardTokenMock.sol
Normal file
14
contracts/mocks/StandardTokenMock.sol
Normal file
@ -0,0 +1,14 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/StandardToken.sol";
|
||||
|
||||
|
||||
// mock class using StandardToken
|
||||
contract StandardTokenMock is StandardToken {
|
||||
|
||||
constructor(address _initialAccount, uint256 _initialBalance) public {
|
||||
balances[_initialAccount] = _initialBalance;
|
||||
totalSupply_ = _initialBalance;
|
||||
}
|
||||
|
||||
}
|
||||
12
contracts/mocks/SupportsInterfaceWithLookupMock.sol
Normal file
12
contracts/mocks/SupportsInterfaceWithLookupMock.sol
Normal file
@ -0,0 +1,12 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../introspection/SupportsInterfaceWithLookup.sol";
|
||||
|
||||
|
||||
contract SupportsInterfaceWithLookupMock is SupportsInterfaceWithLookup {
|
||||
function registerInterface(bytes4 _interfaceId)
|
||||
public
|
||||
{
|
||||
_registerInterface(_interfaceId);
|
||||
}
|
||||
}
|
||||
22
contracts/mocks/TimedCrowdsaleImpl.sol
Normal file
22
contracts/mocks/TimedCrowdsaleImpl.sol
Normal file
@ -0,0 +1,22 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/TimedCrowdsale.sol";
|
||||
|
||||
|
||||
contract TimedCrowdsaleImpl is TimedCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 _openingTime,
|
||||
uint256 _closingTime,
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
public
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
TimedCrowdsale(_openingTime, _closingTime)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
14
contracts/mocks/WhitelistMock.sol
Normal file
14
contracts/mocks/WhitelistMock.sol
Normal file
@ -0,0 +1,14 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../access/Whitelist.sol";
|
||||
|
||||
|
||||
contract WhitelistMock is Whitelist {
|
||||
|
||||
function onlyWhitelistedCanDoThis()
|
||||
external
|
||||
onlyIfWhitelisted(msg.sender)
|
||||
view
|
||||
{
|
||||
}
|
||||
}
|
||||
19
contracts/mocks/WhitelistedCrowdsaleImpl.sol
Normal file
19
contracts/mocks/WhitelistedCrowdsaleImpl.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "../token/ERC20/ERC20.sol";
|
||||
import "../crowdsale/validation/WhitelistedCrowdsale.sol";
|
||||
import "../crowdsale/Crowdsale.sol";
|
||||
|
||||
|
||||
contract WhitelistedCrowdsaleImpl is Crowdsale, WhitelistedCrowdsale {
|
||||
|
||||
constructor (
|
||||
uint256 _rate,
|
||||
address _wallet,
|
||||
ERC20 _token
|
||||
)
|
||||
Crowdsale(_rate, _wallet, _token)
|
||||
public
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "./Ownable.sol";
|
||||
import "../token/ERC20Basic.sol";
|
||||
import "../token/SafeERC20.sol";
|
||||
import "../token/ERC20/ERC20Basic.sol";
|
||||
import "../token/ERC20/SafeERC20.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Contracts that should be able to recover tokens
|
||||
@ -15,11 +16,11 @@ contract CanReclaimToken is Ownable {
|
||||
|
||||
/**
|
||||
* @dev Reclaim all ERC20Basic compatible tokens
|
||||
* @param token ERC20Basic The address of the token contract
|
||||
* @param _token ERC20Basic The address of the token contract
|
||||
*/
|
||||
function reclaimToken(ERC20Basic token) external onlyOwner {
|
||||
uint256 balance = token.balanceOf(this);
|
||||
token.safeTransfer(owner, balance);
|
||||
function reclaimToken(ERC20Basic _token) external onlyOwner {
|
||||
uint256 balance = _token.balanceOf(this);
|
||||
_token.safeTransfer(owner, balance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
pragma solidity ^0.4.11;
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
|
||||
import './Ownable.sol';
|
||||
import "./Ownable.sol";
|
||||
|
||||
|
||||
/**
|
||||
@ -24,16 +24,16 @@ contract Claimable is Ownable {
|
||||
* @dev Allows the current owner to set the pendingOwner address.
|
||||
* @param newOwner The address to transfer ownership to.
|
||||
*/
|
||||
function transferOwnership(address newOwner) onlyOwner public {
|
||||
function transferOwnership(address newOwner) public onlyOwner {
|
||||
pendingOwner = newOwner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Allows the pendingOwner address to finalize the transfer.
|
||||
*/
|
||||
function claimOwnership() onlyPendingOwner public {
|
||||
OwnershipTransferred(owner, pendingOwner);
|
||||
function claimOwnership() public onlyPendingOwner {
|
||||
emit OwnershipTransferred(owner, pendingOwner);
|
||||
owner = pendingOwner;
|
||||
pendingOwner = 0x0;
|
||||
pendingOwner = address(0);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user