Compare commits
560 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| 725ed40a57 | |||
| 3733c069c9 | |||
| 1df75a951f | |||
| adfd8fb6a9 | |||
| 98f672b534 | |||
| e9068859b6 | |||
| 1203a2473d | |||
| 4a1ff913ab | |||
| 83918cad4b | |||
| d3c5ce268f | |||
| f60c5ad88a | |||
| bcda5bfe9b | |||
| 33eb8b1da5 | |||
| b069827bad | |||
| 74e416f04f | |||
| b395b06b65 | |||
| bd84db735d | |||
| bd99b207c9 | |||
| 2438557255 | |||
| 9f1826d83e | |||
| 676f5f6931 | |||
| 6d8bb497c8 | |||
| 5fd8684a5a | |||
| 1737555b0d | |||
| eda63c75c4 | |||
| 61f62eb3c7 | |||
| f96ebfca31 | |||
| fac580d1a9 | |||
| dc1017c929 | |||
| 07b688a0e6 | |||
| 20187f2970 | |||
| 84be318ca9 | |||
| 5035718e4b | |||
| fdc8fbaa45 | |||
| 99887da49a | |||
| 7a36a6c92a | |||
| 6beac0f215 | |||
| b59469c151 | |||
| b07466a477 | |||
| 0bd22e78d3 | |||
| 69e83e5086 | |||
| 8336785a9b | |||
| f073352632 | |||
| aad25205cd | |||
| dcdc453a55 | |||
| 5636575327 | |||
| 00f80c726a | |||
| 74db6c2b3b | |||
| d095ba84bf | |||
| 209e2de93b | |||
| c37c233d22 | |||
| 7b463769a5 | |||
| c7636bdc4c | |||
| 307d34e05a | |||
| 69e21dacb8 | |||
| f27a1ac040 | |||
| af6fdae3dd | |||
| 6ae22e084a | |||
| d463b26709 | |||
| 271e6192e8 | |||
| 51906bae6c | |||
| 406004a99a | |||
| b50894aabe | |||
| d6f07267ee | |||
| 1827cbfd2a | |||
| a0c0cb66c5 | |||
| 47aa4bbf8f | |||
| 33de70158c | |||
| f45a4e8243 | |||
| ac75f4e2ed | |||
| 631748480e | |||
| 3d5c759d62 | |||
| 2e0440e549 | |||
| 86beb5b730 | |||
| 289fd87ef8 | |||
| 8b11035b39 | |||
| 21f251eafb | |||
| e7b1c33955 | |||
| 1da0467820 | |||
| 05609de044 | |||
| 02fb43ff52 | |||
| 1626c0095f | |||
| 341ce621a9 | |||
| 52efe2412c | |||
| 84e3e76bb8 | |||
| 1d162e95c5 | |||
| 060843d912 | |||
| d3bc0a4ef7 | |||
| d1a82dde63 | |||
| 99efe80c61 | |||
| b12db57f34 | |||
| 9333fec5f1 | |||
| 6f94af9264 | |||
| 0ed98ea9b9 | |||
| 0b66144942 | |||
| b91a3eded3 | |||
| 7c9c0f6538 | |||
| 0d6846a882 | |||
| 84a68e0c25 | |||
| e82fa4eae0 | |||
| c79c6d76d8 | |||
| 36452136f1 | |||
| 17cfb0fc78 | |||
| e86ac90853 | |||
| 99e0f5b5cb | |||
| 4fc6bb7977 | |||
| 6e66ba321e | |||
| 2c2067ecc1 | |||
| e6a7a978d1 | |||
| 3e02f45f67 | |||
| b972f43513 | |||
| 30d02b1c78 | |||
| 479d01101d | |||
| 2b079136fb | |||
| 46c5759b88 | |||
| 7c883b6368 | |||
| 69daed7746 | |||
| 0b9afefa93 | |||
| 52490b92bf | |||
| 2261039d52 | |||
| 24323d3ce3 | |||
| c6e055689b | |||
| 2b5192b9ce | |||
| 77dfcb6e23 | |||
| 4fe837704b | |||
| cf58330936 | |||
| 287b873add | |||
| 115e7afe0b | |||
| a9e1fcd623 | |||
| 04e0b2e5c2 | |||
| 2403508e1b | |||
| b414545b6e | |||
| 3296471bda | |||
| eb5b6252bc | |||
| e5da857d4f | |||
| 09a8da5d6a | |||
| 863ad48a81 | |||
| de0e6ba222 | |||
| 91e5a925d9 | |||
| 5e7c168b25 | |||
| 6fccd202fe | |||
| 18e98fbba8 | |||
| a799d218fd | |||
| 9f0cbd3303 | |||
| 93fb8f35a8 | |||
| 2303fd51a3 | |||
| 910fc4915e | |||
| 002acb984e | |||
| bebe704688 | |||
| 9a006f3a68 | |||
| 58e2e4d742 | |||
| 60bc6a6da5 | |||
| b3f60b9320 | |||
| e9cf6dfb60 | |||
| 5e7847537a | |||
| 64787b1ac5 | |||
| 58fdb956b5 | |||
| 4d91118dd9 | |||
| ed872ca0a1 | |||
| 1bb1d41beb | |||
| 1db46aa5d5 | |||
| c991eaf916 | |||
| 86a69fd6d6 | |||
| 6735a3ccd6 | |||
| 6d565ef841 | |||
| b2e36314cb | |||
| 6904f12032 | |||
| c3a30e9be3 | |||
| 93b953fb48 | |||
| e2fdf09e9b | |||
| 4f44427966 | |||
| f8c0fab5d8 | |||
| 478d1b1a93 | |||
| a68eaa4e2d | |||
| 68c2bcb9dd | |||
| 635c04378d | |||
| 227c7aae0f | |||
| 641b751385 | |||
| 4201d50dcf | |||
| b05fb9c200 | |||
| 4f34d41523 | |||
| 91fc295a42 | |||
| 67d3a759a7 | |||
| 950b6a5e56 | |||
| db40fd314a | |||
| 6035bd522b | |||
| b8884687df | |||
| 18581f138f | |||
| f3867f8477 | |||
| 353285e5d9 | |||
| a56bcbf8fd | |||
| 81297fac88 | |||
| 6331dd125d | |||
| f8790c1ed7 | |||
| 5afbdf00db | |||
| 322a9598ab | |||
| ba86e8e095 | |||
| 5e423bc353 | |||
| 6eac859781 | |||
| f2c2c01f8e | |||
| 7434b3d6d2 | |||
| 63b5fc5971 | |||
| f507a0ea29 | |||
| c254d8703d | |||
| 981ec2dbdc | |||
| d5a75362ec | |||
| e748c3ea36 | |||
| 421ed4f8ab | |||
| 0b1f08043b | |||
| 759f8de81f | |||
| 96b550b722 | |||
| b961eea89d | |||
| d2dd6e40b6 | |||
| 070bcbcdbd | |||
| 46fe7ee76d | |||
| ba383a6d20 | |||
| a66f5f8f03 | |||
| 262b7dd7dd | |||
| 5d847ed4d9 | |||
| b3ca0c73b3 | |||
| d6a45ef14e | |||
| 54d74b1c26 | |||
| 657c56c650 | |||
| 50a903a62d | |||
| 0791e6639a | |||
| 59e9609926 | |||
| fadb2cf47e | |||
| 4d55d8fa8e | |||
| e31abffcb6 | |||
| cd47fbe953 | |||
| 42c6392533 | |||
| 3c9638b62e | |||
| 60ef284a9a | |||
| b40a01e97b | |||
| 34e3ce4ab4 | |||
| 4d6b48f39e | |||
| de99e7bf34 | |||
| 3430c7a289 | |||
| daf1784be4 | |||
| de92a02127 | |||
| 549590d105 | |||
| 82ca385725 | |||
| e33d9bb41b | |||
| 79b3a1b1a2 | |||
| c6a3c29eb4 | |||
| dd34d8df0f | |||
| 80d052d43f | |||
| 710f77dfe1 | |||
| b1e504d6c6 | |||
| 7deaee04c8 | |||
| 2020d56ba4 | |||
| a49fe53fa1 | |||
| bc3db5d4c1 | |||
| 30e202313d | |||
| 2e0bd06da2 | |||
| 3c4d0d0a77 | |||
| 403e7336a9 | |||
| fea2a8383c | |||
| ffe464a43e | |||
| 3fbcb1b282 | |||
| 28b2a0c881 | |||
| 7b9c1429d9 | |||
| d53ddd4a95 | |||
| 6ede3d9001 | |||
| c3cb0dcf80 | |||
| f214dccab9 | |||
| c0cce27703 | |||
| 2eded7a337 | |||
| 41a6f1cd84 |
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=
|
||||||
51
.eslintrc
Normal file
51
.eslintrc
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"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": [2, "global"],
|
||||||
|
|
||||||
|
// Code style
|
||||||
|
"indent": [2, 2],
|
||||||
|
"quotes": [2, "single"],
|
||||||
|
"semi": ["error", "always"],
|
||||||
|
"space-before-function-paren": ["error", "always"],
|
||||||
|
"no-use-before-define": 0,
|
||||||
|
"eqeqeq": [2, "smart"],
|
||||||
|
"dot-notation": [2, {"allowKeywords": true, "allowPattern": ""}],
|
||||||
|
"no-redeclare": [2, {"builtinGlobals": true}],
|
||||||
|
"no-trailing-spaces": [2, { "skipBlankLines": true }],
|
||||||
|
"eol-last": 1,
|
||||||
|
"comma-spacing": [2, {"before": false, "after": true}],
|
||||||
|
"camelcase": [2, {"properties": "always"}],
|
||||||
|
"no-mixed-spaces-and-tabs": [2, "smart-tabs"],
|
||||||
|
"comma-dangle": [1, "always-multiline"],
|
||||||
|
"no-dupe-args": 2,
|
||||||
|
"no-dupe-keys": 2,
|
||||||
|
"no-debugger": 0,
|
||||||
|
"no-undef": 2,
|
||||||
|
"object-curly-spacing": [2, "always"],
|
||||||
|
"max-len": [2, 120, 2],
|
||||||
|
"generator-star-spacing": ["error", "before"],
|
||||||
|
"promise/avoid-new": 0,
|
||||||
|
"promise/always-return": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.sol linguist-language=Solidity
|
||||||
32
.github/ISSUE_TEMPLATE.md
vendored
Normal file
32
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
- [ ] 🐛 This is a bug report.
|
||||||
|
- [ ] 📈 This is a feature request.
|
||||||
|
|
||||||
|
<!-- Please check one of the above by placing an x in the box. -->
|
||||||
|
|
||||||
|
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/).**
|
||||||
|
|
||||||
|
## 💻 Environment
|
||||||
|
|
||||||
|
First, we need to know what your environment looks like.
|
||||||
|
|
||||||
|
- Which version of OpenZeppelin are you using?
|
||||||
|
- What network are you deploying to? testrpc? 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 @@
|
|||||||
|
<!-- 🎉 Thank you for submitting a PR! Before submitting, please review the following checklist: -->
|
||||||
|
|
||||||
|
- [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](/docs/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 (`npm run lint:all:fix`) and fixed any issues.
|
||||||
|
|
||||||
|
<!-- **Does this close any open issues?** If so, list them here. -->
|
||||||
|
|
||||||
|
Fixes #
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 🚀 Description
|
||||||
|
|
||||||
|
<!-- Describe the changes introduced in this pull request -->
|
||||||
|
<!-- Include any context necessary for understanding the PR's purpose. -->
|
||||||
37
.gitignore
vendored
37
.gitignore
vendored
@ -1,7 +1,36 @@
|
|||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
node_modules/
|
|
||||||
build/
|
# Logs
|
||||||
.DS_Store/
|
logs
|
||||||
/coverage
|
*.log
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
allFiredEvents
|
||||||
|
scTopics
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
coverage.json
|
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/
|
||||||
|
|||||||
1
.node-version
Normal file
1
.node-version
Normal file
@ -0,0 +1 @@
|
|||||||
|
v8.9.1
|
||||||
9
.solcover.js
Normal file
9
.solcover.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module.exports = {
|
||||||
|
norpc: true,
|
||||||
|
testCommand: 'node --max-old-space-size=4096 ../node_modules/.bin/truffle test --network coverage',
|
||||||
|
compileCommand: 'node --max-old-space-size=4096 ../node_modules/.bin/truffle compile --network coverage',
|
||||||
|
skipFiles: [
|
||||||
|
'lifecycle/Migrations.sol',
|
||||||
|
'mocks'
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,22 +1,12 @@
|
|||||||
{
|
{
|
||||||
"custom-rules-filename": null,
|
"extends": "solium:all",
|
||||||
|
"plugins": ["security"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"imports-on-top": true,
|
"quotes": ["error", "double"],
|
||||||
"variable-declarations": true,
|
"indentation": ["error", 2],
|
||||||
"array-declarations": true,
|
"arg-overflow": ["warning", 3],
|
||||||
"operator-whitespace": true,
|
"security/enforce-explicit-visibility": ["error"],
|
||||||
"lbrace": true,
|
"security/no-block-members": ["warning"],
|
||||||
"mixedcase": false,
|
"security/no-inline-assembly": ["warning"]
|
||||||
"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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
.travis.yml
31
.travis.yml
@ -1,12 +1,29 @@
|
|||||||
dist: trusty
|
dist: trusty
|
||||||
sudo: false
|
sudo: required
|
||||||
group: beta
|
group: beta
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- "6"
|
- "8"
|
||||||
before_install:
|
cache:
|
||||||
- npm install truffle@3.1.9 -g
|
directories:
|
||||||
- npm i -g ethereumjs-testrpc
|
- node_modules
|
||||||
|
env:
|
||||||
|
-
|
||||||
|
- SOLIDITY_COVERAGE=true
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
allow_failures:
|
||||||
|
- env: SOLIDITY_COVERAGE=true
|
||||||
|
before_script:
|
||||||
|
- truffle version
|
||||||
script:
|
script:
|
||||||
- testrpc > /dev/null &
|
- npm run lint
|
||||||
- truffle test
|
- 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
|
||||||
|
|||||||
122
CONTRIBUTING.md
122
CONTRIBUTING.md
@ -1,107 +1,59 @@
|
|||||||
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
|
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/zeppelin-solidity/wiki/Contrbuting-guidelines).
|
||||||
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.
|
|
||||||
|
|
||||||
### D1 - Simple and Modular
|
## Creating Pull Requests (PRs)
|
||||||
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.
|
|
||||||
|
|
||||||
### 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 use `rebase` instead of `merge` when updating your fork.
|
||||||
|
* Please see ["Git flow wiki entry"](https://github.com/OpenZeppelin/zeppelin-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 zeppelin-solidity
|
||||||
|
git fetch upstream
|
||||||
|
git checkout development
|
||||||
|
git pull --rebase upstream development
|
||||||
|
```
|
||||||
|
NOTE: The directory `zeppelin-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.
|
2) Branch out from `development` into `fix/some-bug-#123`:
|
||||||
|
(Postfixing #123 will associate your PR with the issue #123 and make everyone's life easier =D)
|
||||||
### D5 - Code Consistency
|
```
|
||||||
|
git checkout -b fix/some-bug-#123
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
We expect pull requests to be rebased to the master branch before merging:
|
3) Make your changes, add your files, commit and push to your fork.
|
||||||
```sh
|
|
||||||
git remote add zep git@github.com:OpenZeppelin/zeppelin-solidity.git
|
```
|
||||||
git pull --rebase zep master
|
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/zeppelin-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:
|
*IMPORTANT* Read the PR template very carefully and make sure to follow all the instructions. These instructions
|
||||||
```sh
|
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.
|
||||||
git push origin your_branch_name
|
|
||||||
git push origin feature/some-new-stuff
|
|
||||||
git push origin fix/some-bug
|
|
||||||
```
|
|
||||||
|
|
||||||
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
|
## All set!
|
||||||
[github.com/OpenZeppelin/zeppelin-solidity/issues](https://github.com/OpenZeppelin/zeppelin-solidity/issues).
|
|
||||||
|
|
||||||
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/zeppelin-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/zeppelin-solidity/labels/good%20first%20issue).
|
||||||
|
|
||||||
Thanks for your time and code!
|
Thanks for your time and code!
|
||||||
|
|||||||
21
README.md
21
README.md
@ -1,12 +1,13 @@
|
|||||||
# Zeppelin Solidity
|
# Zeppelin Solidity
|
||||||
[](https://www.npmjs.org/package/zeppelin-solidity)
|
[](https://www.npmjs.org/package/zeppelin-solidity)
|
||||||
[](https://travis-ci.org/OpenZeppelin/zeppelin-solidity)
|
[](https://travis-ci.org/OpenZeppelin/zeppelin-solidity)
|
||||||
|
[](https://coveralls.io/github/OpenZeppelin/zeppelin-solidity?branch=master)
|
||||||
|
|
||||||
OpenZeppelin is a library for writing secure [Smart Contracts](https://en.wikipedia.org/wiki/Smart_contract) on Ethereum.
|
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:
|
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))
|
- 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).
|
> 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).
|
||||||
|
|
||||||
@ -15,16 +16,19 @@ With OpenZeppelin, you can build distributed applications, protocols and organiz
|
|||||||
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), an Ethereum development environment. Please install Truffle and initialize your project with `truffle init`.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm install -g truffle@beta
|
npm install -g truffle
|
||||||
mkdir myproject && cd myproject
|
mkdir myproject && cd myproject
|
||||||
truffle init
|
truffle init
|
||||||
```
|
```
|
||||||
|
|
||||||
To install the OpenZeppelin library, run:
|
To install the OpenZeppelin library, run the following in your Solidity project root directory:
|
||||||
```sh
|
```sh
|
||||||
npm install zeppelin-solidity
|
npm init -y
|
||||||
|
npm install -E zeppelin-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/zeppelin-solidity/contracts` folder. You can use the contracts in the library like so:
|
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:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -45,7 +49,7 @@ If you find a security issue, please email [security@openzeppelin.org](mailto:se
|
|||||||
|
|
||||||
Building a distributed application, protocol or organization with OpenZeppelin?
|
Building a distributed application, protocol or organization with OpenZeppelin?
|
||||||
|
|
||||||
- Read documentation: http://zeppelin-solidity.readthedocs.io/en/latest/
|
- Read documentation: https://zeppelin-solidity.readthedocs.io/en/latest/
|
||||||
|
|
||||||
- Ask for help and follow progress at: https://slack.openzeppelin.org/
|
- Ask for help and follow progress at: https://slack.openzeppelin.org/
|
||||||
|
|
||||||
@ -54,17 +58,18 @@ Interested in contributing to OpenZeppelin?
|
|||||||
- Framework proposal and roadmap: https://medium.com/zeppelin-blog/zeppelin-framework-proposal-and-development-roadmap-fdfa9a3a32ab#.iain47pak
|
- 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
|
- Issue tracker: https://github.com/OpenZeppelin/zeppelin-solidity/issues
|
||||||
- Contribution guidelines: https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/CONTRIBUTING.md
|
- Contribution guidelines: https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/CONTRIBUTING.md
|
||||||
|
- Wiki: https://github.com/OpenZeppelin/zeppelin-solidity/wiki
|
||||||
|
|
||||||
## Collaborating organizations and audits by OpenZeppelin
|
## Collaborating organizations and audits by OpenZeppelin
|
||||||
- [Golem](https://golem.network/)
|
- [Golem](https://golem.network/)
|
||||||
- [Mediachain](http://www.mediachain.io/)
|
- [Mediachain](http://www.mediachain.io/)
|
||||||
- [Truffle](http://truffleframework.com/)
|
- [Truffle](http://truffleframework.com/)
|
||||||
- [Firstblood](http://firstblood.io/)
|
- [Firstblood](https://firstblood.io/)
|
||||||
- [Rootstock](http://www.rsk.co/)
|
- [Rootstock](https://www.rsk.co/)
|
||||||
- [Consensys](https://consensys.net/)
|
- [Consensys](https://consensys.net/)
|
||||||
- [DigixGlobal](https://www.dgx.io/)
|
- [DigixGlobal](https://www.dgx.io/)
|
||||||
- [Coinfund](https://coinfund.io/)
|
- [Coinfund](https://coinfund.io/)
|
||||||
- [DemocracyEarth](http://democracy.earth/)
|
- [DemocracyEarth](https://democracy.earth/)
|
||||||
- [Signatura](https://signatura.co/)
|
- [Signatura](https://signatura.co/)
|
||||||
- [Ether.camp](http://www.ether.camp/)
|
- [Ether.camp](http://www.ether.camp/)
|
||||||
- [Aragon](https://aragon.one/)
|
- [Aragon](https://aragon.one/)
|
||||||
|
|||||||
@ -48,7 +48,7 @@ We think much more could be done here, and recommend the OpenZeppelin team keep
|
|||||||
|
|
||||||
## Solidity Version Updates Recommended
|
## Solidity Version Updates Recommended
|
||||||
|
|
||||||
Most of the code uses Solidity 0.4.8, but some files under `Ownership` are marked 0.4.0. These should be updated.
|
Most of the code uses Solidity 0.4.11, but some files under `Ownership` are marked 0.4.0. These should be updated.
|
||||||
|
|
||||||
Solidity 0.4.10 will add several features which could be useful in these contracts:
|
Solidity 0.4.10 will add several features which could be useful in these contracts:
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
import './payment/PullPayment.sol';
|
import "./payment/PullPayment.sol";
|
||||||
import './lifecycle/Destructible.sol';
|
import "./lifecycle/Destructible.sol";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,12 +16,10 @@ contract Bounty is PullPayment, Destructible {
|
|||||||
event TargetCreated(address createdAddress);
|
event TargetCreated(address createdAddress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Fallback function allowing the contract to recieve funds, if they haven't already been claimed.
|
* @dev Fallback function allowing the contract to receive funds, if they haven't already been claimed.
|
||||||
*/
|
*/
|
||||||
function() payable {
|
function() external payable {
|
||||||
if (claimed) {
|
require(!claimed);
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,36 +27,32 @@ contract Bounty is PullPayment, Destructible {
|
|||||||
* msg.sender as a researcher
|
* msg.sender as a researcher
|
||||||
* @return A target contract
|
* @return A target contract
|
||||||
*/
|
*/
|
||||||
function createTarget() returns(Target) {
|
function createTarget() public returns(Target) {
|
||||||
Target target = Target(deployContract());
|
Target target = Target(deployContract());
|
||||||
researchers[target] = msg.sender;
|
researchers[target] = msg.sender;
|
||||||
TargetCreated(target);
|
TargetCreated(target);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Internal function to deploy the target contract.
|
* @dev Internal function to deploy the target contract.
|
||||||
* @return A target contract address
|
* @return A target contract address
|
||||||
*/
|
*/
|
||||||
function deployContract() internal returns(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) {
|
|
||||||
address researcher = researchers[target];
|
|
||||||
if (researcher == 0) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
// Check Target contract invariants
|
|
||||||
if (target.checkInvariant()) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
asyncSend(researcher, this.balance);
|
|
||||||
claimed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -74,5 +68,5 @@ contract Target {
|
|||||||
* In order to win the bounty, security researchers will try to cause this broken state.
|
* In order to win the bounty, security researchers will try to cause this broken state.
|
||||||
* @return True if all invariant values are correct, false otherwise.
|
* @return True if all invariant values are correct, false otherwise.
|
||||||
*/
|
*/
|
||||||
function checkInvariant() returns(bool);
|
function checkInvariant() public returns(bool);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title DayLimit
|
* @title DayLimit
|
||||||
@ -7,24 +8,24 @@ pragma solidity ^0.4.8;
|
|||||||
*/
|
*/
|
||||||
contract DayLimit {
|
contract DayLimit {
|
||||||
|
|
||||||
uint public dailyLimit;
|
uint256 public dailyLimit;
|
||||||
uint public spentToday;
|
uint256 public spentToday;
|
||||||
uint public lastDay;
|
uint256 public lastDay;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Constructor that sets the passed value as a dailyLimit.
|
* @dev Constructor that sets the passed value as a dailyLimit.
|
||||||
* @param _limit Uint to represent the daily limit.
|
* @param _limit uint256 to represent the daily limit.
|
||||||
*/
|
*/
|
||||||
function DayLimit(uint _limit) {
|
function DayLimit(uint256 _limit) public {
|
||||||
dailyLimit = _limit;
|
dailyLimit = _limit;
|
||||||
lastDay = today();
|
lastDay = today();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev sets the daily limit. Does not alter the amount already spent today.
|
* @dev sets the daily limit. Does not alter the amount already spent today.
|
||||||
* @param _newLimit Uint to represent the new limit.
|
* @param _newLimit uint256 to represent the new limit.
|
||||||
*/
|
*/
|
||||||
function _setDailyLimit(uint _newLimit) internal {
|
function _setDailyLimit(uint256 _newLimit) internal {
|
||||||
dailyLimit = _newLimit;
|
dailyLimit = _newLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,10 +38,10 @@ contract DayLimit {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Checks to see if there is enough resource to spend today. If true, the resource may be expended.
|
* @dev Checks to see if there is enough resource to spend today. If true, the resource may be expended.
|
||||||
* @param _value Uint representing the amount of resource to spend.
|
* @param _value uint256 representing the amount of resource to spend.
|
||||||
* @return A boolean that is True if the resource was spended and false otherwise.
|
* @return A boolean that is True if the resource was spent and false otherwise.
|
||||||
*/
|
*/
|
||||||
function underLimit(uint _value) internal returns (bool) {
|
function underLimit(uint256 _value) internal returns (bool) {
|
||||||
// reset the spend limit if we're on a different day to last time.
|
// reset the spend limit if we're on a different day to last time.
|
||||||
if (today() > lastDay) {
|
if (today() > lastDay) {
|
||||||
spentToday = 0;
|
spentToday = 0;
|
||||||
@ -57,19 +58,17 @@ contract DayLimit {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Private function to determine today's index
|
* @dev Private function to determine today's index
|
||||||
* @return Uint of today's index.
|
* @return uint256 of today's index.
|
||||||
*/
|
*/
|
||||||
function today() private constant returns (uint) {
|
function today() private view returns (uint256) {
|
||||||
return now / 1 days;
|
return now / 1 days;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Simple modifier for daily limit.
|
* @dev Simple modifier for daily limit.
|
||||||
*/
|
*/
|
||||||
modifier limitedDaily(uint _value) {
|
modifier limitedDaily(uint256 _value) {
|
||||||
if (!underLimit(_value)) {
|
require(underLimit(_value));
|
||||||
throw;
|
|
||||||
}
|
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
contracts/ECRecovery.sol
Normal file
47
contracts/ECRecovery.sol
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Eliptic curve signature operations
|
||||||
|
*
|
||||||
|
* @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
|
||||||
|
*/
|
||||||
|
|
||||||
|
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()
|
||||||
|
*/
|
||||||
|
function recover(bytes32 hash, bytes sig) public pure returns (address) {
|
||||||
|
bytes32 r;
|
||||||
|
bytes32 s;
|
||||||
|
uint8 v;
|
||||||
|
|
||||||
|
//Check the signature length
|
||||||
|
if (sig.length != 65) {
|
||||||
|
return (address(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Divide the signature in r, s and v variables
|
||||||
|
assembly {
|
||||||
|
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
|
||||||
|
if (v < 27) {
|
||||||
|
v += 27;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the version is correct return the signer address
|
||||||
|
if (v != 27 && v != 28) {
|
||||||
|
return (address(0));
|
||||||
|
} else {
|
||||||
|
return ecrecover(hash, v, r, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9,13 +9,13 @@ pragma solidity ^0.4.8;
|
|||||||
*/
|
*/
|
||||||
contract LimitBalance {
|
contract LimitBalance {
|
||||||
|
|
||||||
uint public limit;
|
uint256 public limit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Constructor that sets the passed value as a limit.
|
* @dev Constructor that sets the passed value as a limit.
|
||||||
* @param _limit Uint to represent the limit.
|
* @param _limit uint256 to represent the limit.
|
||||||
*/
|
*/
|
||||||
function LimitBalance(uint _limit) {
|
function LimitBalance(uint256 _limit) public {
|
||||||
limit = _limit;
|
limit = _limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,9 +23,7 @@ contract LimitBalance {
|
|||||||
* @dev Checks if limit was reached. Case true, it throws.
|
* @dev Checks if limit was reached. Case true, it throws.
|
||||||
*/
|
*/
|
||||||
modifier limitedPayable() {
|
modifier limitedPayable() {
|
||||||
if (this.balance > limit) {
|
require(this.balance <= limit);
|
||||||
throw;
|
|
||||||
}
|
|
||||||
_;
|
_;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
44
contracts/MerkleProof.sol
Normal file
44
contracts/MerkleProof.sol
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @title MerkleProof
|
||||||
|
* @dev Merkle proof verification
|
||||||
|
* @note 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.
|
||||||
|
* @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) public pure returns (bool) {
|
||||||
|
// Check if proof length is a multiple of 32
|
||||||
|
if (_proof.length % 32 != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes32 proofElement;
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (computedHash < proofElement) {
|
||||||
|
// Hash(current computed hash + current element of the proof)
|
||||||
|
computedHash = keccak256(computedHash, proofElement);
|
||||||
|
} else {
|
||||||
|
// Hash(current element of the proof + current computed hash)
|
||||||
|
computedHash = keccak256(proofElement, computedHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the computed hash (root) is equal to the provided root
|
||||||
|
return computedHash == _root;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,127 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
|
|
||||||
import "./ownership/Multisig.sol";
|
|
||||||
import "./ownership/Shareable.sol";
|
|
||||||
import "./DayLimit.sol";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MultisigWallet
|
|
||||||
* Usage:
|
|
||||||
* bytes32 h = Wallet(w).from(oneOwner).execute(to, value, data);
|
|
||||||
* Wallet(w).from(anotherOwner).confirm(h);
|
|
||||||
*/
|
|
||||||
contract MultisigWallet is Multisig, Shareable, DayLimit {
|
|
||||||
|
|
||||||
struct Transaction {
|
|
||||||
address to;
|
|
||||||
uint value;
|
|
||||||
bytes data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor, sets the owners addresses, number of approvals required, and daily spending limit
|
|
||||||
* @param _owners A list of owners.
|
|
||||||
* @param _required The amount required for a transaction to be approved.
|
|
||||||
*/
|
|
||||||
function MultisigWallet(address[] _owners, uint _required, uint _daylimit)
|
|
||||||
Shareable(_owners, _required)
|
|
||||||
DayLimit(_daylimit) { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev destroys the contract sending everything to `_to`.
|
|
||||||
*/
|
|
||||||
function destroy(address _to) onlymanyowners(keccak256(msg.data)) external {
|
|
||||||
selfdestruct(_to);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Fallback function, receives value and emits a deposit event.
|
|
||||||
*/
|
|
||||||
function() payable {
|
|
||||||
// just being sent some cash?
|
|
||||||
if (msg.value > 0)
|
|
||||||
Deposit(msg.sender, msg.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Outside-visible transaction entry point. Executes transaction immediately if below daily
|
|
||||||
* spending limit. If not, goes into multisig process. We provide a hash on return to allow the
|
|
||||||
* sender to provide shortcuts for the other confirmations (allowing them to avoid replicating
|
|
||||||
* the _to, _value, and _data arguments). They still get the option of using them if they want,
|
|
||||||
* anyways.
|
|
||||||
* @param _to The receiver address
|
|
||||||
* @param _value The value to send
|
|
||||||
* @param _data The data part of the transaction
|
|
||||||
*/
|
|
||||||
function execute(address _to, uint _value, bytes _data) external onlyOwner returns (bytes32 _r) {
|
|
||||||
// first, take the opportunity to check that we're under the daily limit.
|
|
||||||
if (underLimit(_value)) {
|
|
||||||
SingleTransact(msg.sender, _value, _to, _data);
|
|
||||||
// yes - just execute the call.
|
|
||||||
if (!_to.call.value(_value)(_data)) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// determine our operation hash.
|
|
||||||
_r = keccak256(msg.data, block.number);
|
|
||||||
if (!confirm(_r) && txs[_r].to == 0) {
|
|
||||||
txs[_r].to = _to;
|
|
||||||
txs[_r].value = _value;
|
|
||||||
txs[_r].data = _data;
|
|
||||||
ConfirmationNeeded(_r, msg.sender, _value, _to, _data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Confirm a transaction by providing just the hash. We use the previous transactions map,
|
|
||||||
* txs, in order to determine the body of the transaction from the hash provided.
|
|
||||||
* @param _h The transaction hash to approve.
|
|
||||||
*/
|
|
||||||
function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) {
|
|
||||||
if (txs[_h].to != 0) {
|
|
||||||
if (!txs[_h].to.call.value(txs[_h].value)(txs[_h].data)) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
MultiTransact(msg.sender, _h, txs[_h].value, txs[_h].to, txs[_h].data);
|
|
||||||
delete txs[_h];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Updates the daily limit value.
|
|
||||||
* @param _newLimit
|
|
||||||
*/
|
|
||||||
function setDailyLimit(uint _newLimit) onlymanyowners(keccak256(msg.data)) external {
|
|
||||||
_setDailyLimit(_newLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Resets the value spent to enable more spending
|
|
||||||
*/
|
|
||||||
function resetSpentToday() onlymanyowners(keccak256(msg.data)) external {
|
|
||||||
_resetSpentToday();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// INTERNAL METHODS
|
|
||||||
/**
|
|
||||||
* @dev Clears the list of transactions pending approval.
|
|
||||||
*/
|
|
||||||
function clearPending() internal {
|
|
||||||
uint length = pendingsIndex.length;
|
|
||||||
for (uint i = 0; i < length; ++i) {
|
|
||||||
delete txs[pendingsIndex[i]];
|
|
||||||
}
|
|
||||||
super.clearPending();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// FIELDS
|
|
||||||
|
|
||||||
// pending transactions we have at present.
|
|
||||||
mapping (bytes32 => Transaction) txs;
|
|
||||||
}
|
|
||||||
@ -1,7 +1,8 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Helps contracts guard agains rentrancy attacks.
|
* @title Helps contracts guard agains reentrancy attacks.
|
||||||
* @author Remco Bloemen <remco@2π.com>
|
* @author Remco Bloemen <remco@2π.com>
|
||||||
* @notice If you mark a function `nonReentrant`, you should also
|
* @notice If you mark a function `nonReentrant`, you should also
|
||||||
* mark it `external`.
|
* mark it `external`.
|
||||||
@ -11,7 +12,7 @@ contract ReentrancyGuard {
|
|||||||
/**
|
/**
|
||||||
* @dev We use a single lock for the whole contract.
|
* @dev We use a single lock for the whole contract.
|
||||||
*/
|
*/
|
||||||
bool private rentrancy_lock = false;
|
bool private reentrancy_lock = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Prevents a contract from calling itself, directly or indirectly.
|
* @dev Prevents a contract from calling itself, directly or indirectly.
|
||||||
@ -22,13 +23,10 @@ contract ReentrancyGuard {
|
|||||||
* wrapper marked as `nonReentrant`.
|
* wrapper marked as `nonReentrant`.
|
||||||
*/
|
*/
|
||||||
modifier nonReentrant() {
|
modifier nonReentrant() {
|
||||||
if(rentrancy_lock == false) {
|
require(!reentrancy_lock);
|
||||||
rentrancy_lock = true;
|
reentrancy_lock = true;
|
||||||
_;
|
_;
|
||||||
rentrancy_lock = false;
|
reentrancy_lock = false;
|
||||||
} else {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,53 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Math operations with safety checks
|
|
||||||
*/
|
|
||||||
library SafeMath {
|
|
||||||
function mul(uint a, uint b) internal returns (uint) {
|
|
||||||
uint c = a * b;
|
|
||||||
assert(a == 0 || c / a == b);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
function div(uint a, uint b) internal returns (uint) {
|
|
||||||
// assert(b > 0); // Solidity automatically throws when dividing by 0
|
|
||||||
uint c = a / b;
|
|
||||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sub(uint a, uint b) internal returns (uint) {
|
|
||||||
assert(b <= a);
|
|
||||||
return a - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
function add(uint a, uint b) internal returns (uint) {
|
|
||||||
uint c = a + b;
|
|
||||||
assert(c >= a);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
function max64(uint64 a, uint64 b) internal constant returns (uint64) {
|
|
||||||
return a >= b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
function min64(uint64 a, uint64 b) internal constant returns (uint64) {
|
|
||||||
return a < b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
function max256(uint256 a, uint256 b) internal constant returns (uint256) {
|
|
||||||
return a >= b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
function min256(uint256 a, uint256 b) internal constant returns (uint256) {
|
|
||||||
return a < b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
function assert(bool assertion) internal {
|
|
||||||
if (!assertion) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
35
contracts/crowdsale/CappedCrowdsale.sol
Normal file
35
contracts/crowdsale/CappedCrowdsale.sol
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
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) public {
|
||||||
|
require(_cap > 0);
|
||||||
|
cap = _cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// overriding Crowdsale#hasEnded to add cap logic
|
||||||
|
// @return true if crowdsale event has ended
|
||||||
|
function hasEnded() public view returns (bool) {
|
||||||
|
bool capReached = weiRaised >= cap;
|
||||||
|
return capReached || super.hasEnded();
|
||||||
|
}
|
||||||
|
|
||||||
|
// overriding Crowdsale#validPurchase to add extra cap logic
|
||||||
|
// @return true if investors can buy at the moment
|
||||||
|
function validPurchase() internal view returns (bool) {
|
||||||
|
bool withinCap = weiRaised.add(msg.value) <= cap;
|
||||||
|
return withinCap && super.validPurchase();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
110
contracts/crowdsale/Crowdsale.sol
Normal file
110
contracts/crowdsale/Crowdsale.sol
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../token/ERC20/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.
|
||||||
|
*/
|
||||||
|
contract Crowdsale {
|
||||||
|
using SafeMath for uint256;
|
||||||
|
|
||||||
|
// The token being sold
|
||||||
|
MintableToken public token;
|
||||||
|
|
||||||
|
// start and end timestamps where investments are allowed (both inclusive)
|
||||||
|
uint256 public startTime;
|
||||||
|
uint256 public endTime;
|
||||||
|
|
||||||
|
// address where funds are collected
|
||||||
|
address public wallet;
|
||||||
|
|
||||||
|
// how many token units a buyer gets per wei
|
||||||
|
uint256 public rate;
|
||||||
|
|
||||||
|
// amount of raised money in wei
|
||||||
|
uint256 public weiRaised;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* event for token purchase logging
|
||||||
|
* @param purchaser who paid for the tokens
|
||||||
|
* @param beneficiary who got the tokens
|
||||||
|
* @param value weis paid for purchase
|
||||||
|
* @param amount amount of tokens purchased
|
||||||
|
*/
|
||||||
|
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
|
||||||
|
|
||||||
|
|
||||||
|
function Crowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet) public {
|
||||||
|
require(_startTime >= now);
|
||||||
|
require(_endTime >= _startTime);
|
||||||
|
require(_rate > 0);
|
||||||
|
require(_wallet != address(0));
|
||||||
|
|
||||||
|
token = createTokenContract();
|
||||||
|
startTime = _startTime;
|
||||||
|
endTime = _endTime;
|
||||||
|
rate = _rate;
|
||||||
|
wallet = _wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback function can be used to buy tokens
|
||||||
|
function () external payable {
|
||||||
|
buyTokens(msg.sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
// low level token purchase function
|
||||||
|
function buyTokens(address beneficiary) public payable {
|
||||||
|
require(beneficiary != address(0));
|
||||||
|
require(validPurchase());
|
||||||
|
|
||||||
|
uint256 weiAmount = msg.value;
|
||||||
|
|
||||||
|
// calculate token amount to be created
|
||||||
|
uint256 tokens = getTokenAmount(weiAmount);
|
||||||
|
|
||||||
|
// update state
|
||||||
|
weiRaised = weiRaised.add(weiAmount);
|
||||||
|
|
||||||
|
token.mint(beneficiary, tokens);
|
||||||
|
TokenPurchase(msg.sender, beneficiary, weiAmount, tokens);
|
||||||
|
|
||||||
|
forwardFunds();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @return true if crowdsale event has ended
|
||||||
|
function hasEnded() public view returns (bool) {
|
||||||
|
return now > endTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override this method to have a way to add business logic to your crowdsale when buying
|
||||||
|
function getTokenAmount(uint256 weiAmount) internal view returns(uint256) {
|
||||||
|
return weiAmount.mul(rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send ether to the fund collection wallet
|
||||||
|
// override to create custom fund forwarding mechanisms
|
||||||
|
function forwardFunds() internal {
|
||||||
|
wallet.transfer(msg.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @return true if the transaction can buy tokens
|
||||||
|
function validPurchase() internal view returns (bool) {
|
||||||
|
bool withinPeriod = now >= startTime && now <= endTime;
|
||||||
|
bool nonZeroPurchase = msg.value != 0;
|
||||||
|
return withinPeriod && nonZeroPurchase;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
41
contracts/crowdsale/FinalizableCrowdsale.sol
Normal file
41
contracts/crowdsale/FinalizableCrowdsale.sol
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
using SafeMath for uint256;
|
||||||
|
|
||||||
|
bool public isFinalized = false;
|
||||||
|
|
||||||
|
event Finalized();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Must be called after crowdsale ends, to do some extra finalization
|
||||||
|
* work. Calls the contract's finalization function.
|
||||||
|
*/
|
||||||
|
function finalize() onlyOwner public {
|
||||||
|
require(!isFinalized);
|
||||||
|
require(hasEnded());
|
||||||
|
|
||||||
|
finalization();
|
||||||
|
Finalized();
|
||||||
|
|
||||||
|
isFinalized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Can be overridden to add finalization logic. The overriding function
|
||||||
|
* should call super.finalization() to ensure the chain of finalization is
|
||||||
|
* executed entirely.
|
||||||
|
*/
|
||||||
|
function finalization() internal {
|
||||||
|
}
|
||||||
|
}
|
||||||
57
contracts/crowdsale/RefundVault.sol
Normal file
57
contracts/crowdsale/RefundVault.sol
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
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) public {
|
||||||
|
require(_wallet != address(0));
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
60
contracts/crowdsale/RefundableCrowdsale.sol
Normal file
60
contracts/crowdsale/RefundableCrowdsale.sol
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
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) public {
|
||||||
|
require(_goal > 0);
|
||||||
|
vault = new RefundVault(wallet);
|
||||||
|
goal = _goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if crowdsale is unsuccessful, investors can claim refunds here
|
||||||
|
function claimRefund() public {
|
||||||
|
require(isFinalized);
|
||||||
|
require(!goalReached());
|
||||||
|
|
||||||
|
vault.refund(msg.sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
function goalReached() public view returns (bool) {
|
||||||
|
return weiRaised >= goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vault finalization task, called when owner calls finalize()
|
||||||
|
function finalization() internal {
|
||||||
|
if (goalReached()) {
|
||||||
|
vault.close();
|
||||||
|
} else {
|
||||||
|
vault.enableRefunds();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.finalization();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
50
contracts/examples/SampleCrowdsale.sol
Normal file
50
contracts/examples/SampleCrowdsale.sol
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../crowdsale/CappedCrowdsale.sol";
|
||||||
|
import "../crowdsale/RefundableCrowdsale.sol";
|
||||||
|
import "../token/ERC20/MintableToken.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title SampleCrowdsaleToken
|
||||||
|
* @dev Very simple ERC20 Token that can be minted.
|
||||||
|
* It is meant to be used in a crowdsale contract.
|
||||||
|
*/
|
||||||
|
contract SampleCrowdsaleToken is MintableToken {
|
||||||
|
|
||||||
|
string public constant name = "Sample Crowdsale Token"; // solium-disable-line uppercase
|
||||||
|
string public constant symbol = "SCT"; // solium-disable-line uppercase
|
||||||
|
uint8 public constant decimals = 18; // solium-disable-line uppercase
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title SampleCrowdsale
|
||||||
|
* @dev This is an example of a fully fledged crowdsale.
|
||||||
|
* The way to add new features to a base crowdsale is by multiple inheritance.
|
||||||
|
* In this example we are providing following extensions:
|
||||||
|
* CappedCrowdsale - sets a max boundary for raised funds
|
||||||
|
* RefundableCrowdsale - set a min goal to be reached and returns funds if it's not met
|
||||||
|
*
|
||||||
|
* 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 {
|
||||||
|
|
||||||
|
function SampleCrowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, uint256 _goal, uint256 _cap, address _wallet) public
|
||||||
|
CappedCrowdsale(_cap)
|
||||||
|
FinalizableCrowdsale()
|
||||||
|
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.11;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
function SimpleSavingsWallet(uint256 _heartbeatTimeout) Heritable(_heartbeatTimeout) public {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev wallet can receive funds.
|
||||||
|
*/
|
||||||
|
function () public payable {
|
||||||
|
Received(msg.sender, msg.value, this.balance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev wallet can send funds
|
||||||
|
*/
|
||||||
|
function sendTo(address payee, uint256 amount) public onlyOwner {
|
||||||
|
require(payee != 0 && payee != address(this));
|
||||||
|
require(amount > 0);
|
||||||
|
payee.transfer(amount);
|
||||||
|
Sent(payee, amount, this.balance);
|
||||||
|
}
|
||||||
|
}
|
||||||
30
contracts/examples/SimpleToken.sol
Normal file
30
contracts/examples/SimpleToken.sol
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
import "../token/ERC20/StandardToken.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title SimpleToken
|
||||||
|
* @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
|
||||||
|
* Note they can later distribute these tokens as they wish using `transfer` and other
|
||||||
|
* `StandardToken` functions.
|
||||||
|
*/
|
||||||
|
contract SimpleToken is StandardToken {
|
||||||
|
|
||||||
|
string public constant name = "SimpleToken"; // solium-disable-line uppercase
|
||||||
|
string public constant symbol = "SIM"; // solium-disable-line uppercase
|
||||||
|
uint8 public constant decimals = 18; // solium-disable-line uppercase
|
||||||
|
|
||||||
|
uint256 public constant INITIAL_SUPPLY = 10000 * (10 ** uint256(decimals));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Constructor that gives msg.sender all of existing tokens.
|
||||||
|
*/
|
||||||
|
function SimpleToken() public {
|
||||||
|
totalSupply_ = INITIAL_SUPPLY;
|
||||||
|
balances[msg.sender] = INITIAL_SUPPLY;
|
||||||
|
Transfer(0x0, msg.sender, INITIAL_SUPPLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
import "../ownership/Ownable.sol";
|
import "../ownership/Ownable.sol";
|
||||||
@ -10,14 +10,16 @@ import "../ownership/Ownable.sol";
|
|||||||
*/
|
*/
|
||||||
contract Destructible is Ownable {
|
contract Destructible is Ownable {
|
||||||
|
|
||||||
|
function Destructible() public payable { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Transfers the current balance to the owner and terminates the contract.
|
* @dev Transfers the current balance to the owner and terminates the contract.
|
||||||
*/
|
*/
|
||||||
function destroy() onlyOwner {
|
function destroy() onlyOwner public {
|
||||||
selfdestruct(owner);
|
selfdestruct(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
function destroyAndSend(address _recipient) onlyOwner {
|
function destroyAndSend(address _recipient) onlyOwner public {
|
||||||
selfdestruct(_recipient);
|
selfdestruct(_recipient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,20 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../ownership/Ownable.sol";
|
||||||
|
|
||||||
import '../ownership/Ownable.sol';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Migrations
|
* @title Migrations
|
||||||
* @dev This is a truffle contract, needed for truffle integration, not meant for use by Zeppelin users.
|
* @dev This is a truffle contract, needed for truffle integration, not meant for use by Zeppelin users.
|
||||||
*/
|
*/
|
||||||
contract Migrations is Ownable {
|
contract Migrations is Ownable {
|
||||||
uint public lastCompletedMigration;
|
uint256 public lastCompletedMigration;
|
||||||
|
|
||||||
function setCompleted(uint completed) onlyOwner {
|
function setCompleted(uint256 completed) onlyOwner public {
|
||||||
lastCompletedMigration = completed;
|
lastCompletedMigration = completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function upgrade(address newAddress) onlyOwner {
|
function upgrade(address newAddress) onlyOwner public {
|
||||||
Migrations upgraded = Migrations(newAddress);
|
Migrations upgraded = Migrations(newAddress);
|
||||||
upgraded.setCompleted(lastCompletedMigration);
|
upgraded.setCompleted(lastCompletedMigration);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
import "../ownership/Ownable.sol";
|
import "../ownership/Ownable.sol";
|
||||||
@ -16,36 +16,34 @@ contract Pausable is Ownable {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev modifier to allow actions only when the contract IS paused
|
* @dev Modifier to make a function callable only when the contract is not paused.
|
||||||
*/
|
*/
|
||||||
modifier whenNotPaused() {
|
modifier whenNotPaused() {
|
||||||
if (paused) throw;
|
require(!paused);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev modifier to allow actions only when the contract IS NOT paused
|
* @dev Modifier to make a function callable only when the contract is paused.
|
||||||
*/
|
*/
|
||||||
modifier whenPaused {
|
modifier whenPaused() {
|
||||||
if (!paused) throw;
|
require(paused);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev called by the owner to pause, triggers stopped state
|
* @dev called by the owner to pause, triggers stopped state
|
||||||
*/
|
*/
|
||||||
function pause() onlyOwner whenNotPaused returns (bool) {
|
function pause() onlyOwner whenNotPaused public {
|
||||||
paused = true;
|
paused = true;
|
||||||
Pause();
|
Pause();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev called by the owner to unpause, returns to normal state
|
* @dev called by the owner to unpause, returns to normal state
|
||||||
*/
|
*/
|
||||||
function unpause() onlyOwner whenPaused returns (bool) {
|
function unpause() onlyOwner whenPaused public {
|
||||||
paused = false;
|
paused = false;
|
||||||
Unpause();
|
Unpause();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
import "../ownership/Ownable.sol";
|
import "../ownership/Ownable.sol";
|
||||||
import "../token/ERC20Basic.sol";
|
import "../token/ERC20/ERC20Basic.sol";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title TokenDestructible:
|
* @title TokenDestructible:
|
||||||
@ -12,6 +12,8 @@ import "../token/ERC20Basic.sol";
|
|||||||
*/
|
*/
|
||||||
contract TokenDestructible is Ownable {
|
contract TokenDestructible is Ownable {
|
||||||
|
|
||||||
|
function TokenDestructible() public payable { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice Terminate contract and refund to owner
|
* @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
|
||||||
@ -19,10 +21,10 @@ contract TokenDestructible is Ownable {
|
|||||||
* @notice The called token contracts could try to re-enter this contract. Only
|
* @notice The called token contracts could try to re-enter this contract. Only
|
||||||
supply token contracts you trust.
|
supply token contracts you trust.
|
||||||
*/
|
*/
|
||||||
function destroy(address[] tokens) onlyOwner {
|
function destroy(address[] tokens) onlyOwner public {
|
||||||
|
|
||||||
// Transfer tokens to owner
|
// Transfer tokens to owner
|
||||||
for(uint i = 0; i < tokens.length; i++) {
|
for (uint256 i = 0; i < tokens.length; i++) {
|
||||||
ERC20Basic token = ERC20Basic(tokens[i]);
|
ERC20Basic token = ERC20Basic(tokens[i]);
|
||||||
uint256 balance = token.balanceOf(this);
|
uint256 balance = token.balanceOf(this);
|
||||||
token.transfer(owner, balance);
|
token.transfer(owner, balance);
|
||||||
|
|||||||
24
contracts/math/Math.sol
Normal file
24
contracts/math/Math.sol
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Math
|
||||||
|
* @dev Assorted math operations
|
||||||
|
*/
|
||||||
|
library Math {
|
||||||
|
function max64(uint64 a, uint64 b) internal pure 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 pure returns (uint256) {
|
||||||
|
return a >= b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
function min256(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
contracts/math/SafeMath.sol
Normal file
48
contracts/math/SafeMath.sol
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title SafeMath
|
||||||
|
* @dev Math operations with safety checks that throw on error
|
||||||
|
*/
|
||||||
|
library SafeMath {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Multiplies two numbers, throws on overflow.
|
||||||
|
*/
|
||||||
|
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||||
|
if (a == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint256 c = a * b;
|
||||||
|
assert(c / a == b);
|
||||||
|
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 c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Substracts 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Adds two numbers, throws on overflow.
|
||||||
|
*/
|
||||||
|
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||||
|
uint256 c = a + b;
|
||||||
|
assert(c >= a);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
contracts/mocks/BasicTokenMock.sol
Normal file
15
contracts/mocks/BasicTokenMock.sol
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
import "../token/ERC20/BasicToken.sol";
|
||||||
|
|
||||||
|
|
||||||
|
// mock class using BasicToken
|
||||||
|
contract BasicTokenMock is BasicToken {
|
||||||
|
|
||||||
|
function BasicTokenMock(address initialAccount, uint256 initialBalance) public {
|
||||||
|
balances[initialAccount] = initialBalance;
|
||||||
|
totalSupply_ = initialBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
13
contracts/mocks/BurnableTokenMock.sol
Normal file
13
contracts/mocks/BurnableTokenMock.sol
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../token/ERC20/BurnableToken.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract BurnableTokenMock is BurnableToken {
|
||||||
|
|
||||||
|
function BurnableTokenMock(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.18;
|
||||||
|
|
||||||
|
|
||||||
|
import "../crowdsale/CappedCrowdsale.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract CappedCrowdsaleImpl is CappedCrowdsale {
|
||||||
|
|
||||||
|
function CappedCrowdsaleImpl (
|
||||||
|
uint256 _startTime,
|
||||||
|
uint256 _endTime,
|
||||||
|
uint256 _rate,
|
||||||
|
address _wallet,
|
||||||
|
uint256 _cap
|
||||||
|
) public
|
||||||
|
Crowdsale(_startTime, _endTime, _rate, _wallet)
|
||||||
|
CappedCrowdsale(_cap)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
25
contracts/mocks/DayLimitMock.sol
Normal file
25
contracts/mocks/DayLimitMock.sol
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../../contracts/DayLimit.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract DayLimitMock is DayLimit {
|
||||||
|
uint256 public totalSpending;
|
||||||
|
|
||||||
|
function DayLimitMock(uint256 _value) public DayLimit(_value) {
|
||||||
|
totalSpending = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function attemptSpend(uint256 _value) external limitedDaily(_value) {
|
||||||
|
totalSpending += _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDailyLimit(uint256 _newLimit) external {
|
||||||
|
_setDailyLimit(_newLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetSpentToday() external {
|
||||||
|
_resetSpentToday();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
9
contracts/mocks/DetailedERC20Mock.sol
Normal file
9
contracts/mocks/DetailedERC20Mock.sol
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../token/ERC20/StandardToken.sol";
|
||||||
|
import "../token/ERC20/DetailedERC20.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract DetailedERC20Mock is StandardToken, DetailedERC20 {
|
||||||
|
function DetailedERC20Mock(string _name, string _symbol, uint8 _decimals) DetailedERC20(_name, _symbol, _decimals) public {}
|
||||||
|
}
|
||||||
16
contracts/mocks/ECRecoveryMock.sol
Normal file
16
contracts/mocks/ECRecoveryMock.sol
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
import "../ECRecovery.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract ECRecoveryMock {
|
||||||
|
using ECRecovery for bytes32;
|
||||||
|
|
||||||
|
address public addrRecovered;
|
||||||
|
|
||||||
|
function recover(bytes32 hash, bytes sig) public returns (address) {
|
||||||
|
addrRecovered = hash.recover(sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
31
contracts/mocks/ERC223TokenMock.sol
Normal file
31
contracts/mocks/ERC223TokenMock.sol
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../token/ERC20/BasicToken.sol";
|
||||||
|
|
||||||
|
contract ERC223ContractInterface {
|
||||||
|
function tokenFallback(address _from, uint256 _value, bytes _data) external;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract ERC223TokenMock is BasicToken {
|
||||||
|
|
||||||
|
function ERC223TokenMock(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 is_contract = false;
|
||||||
|
assembly {
|
||||||
|
is_contract := not(iszero(extcodesize(_to)))
|
||||||
|
}
|
||||||
|
if (is_contract) {
|
||||||
|
ERC223ContractInterface receiver = ERC223ContractInterface(_to);
|
||||||
|
receiver.tokenFallback(msg.sender, _value, _data);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
contracts/mocks/ERC721TokenMock.sol
Normal file
19
contracts/mocks/ERC721TokenMock.sol
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../token/ERC721/ERC721Token.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title ERC721TokenMock
|
||||||
|
* This mock just provides a public mint and burn functions for testing purposes.
|
||||||
|
*/
|
||||||
|
contract ERC721TokenMock is ERC721Token {
|
||||||
|
function ERC721TokenMock() ERC721Token() public { }
|
||||||
|
|
||||||
|
function mint(address _to, uint256 _tokenId) public {
|
||||||
|
super._mint(_to, _tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function burn(uint256 _tokenId) public {
|
||||||
|
super._burn(_tokenId);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
contracts/mocks/ERC827TokenMock.sol
Normal file
15
contracts/mocks/ERC827TokenMock.sol
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
pragma solidity ^0.4.13;
|
||||||
|
|
||||||
|
|
||||||
|
import "../token/ERC827/ERC827Token.sol";
|
||||||
|
|
||||||
|
|
||||||
|
// mock class using ERC827 Token
|
||||||
|
contract ERC827TokenMock is ERC827Token {
|
||||||
|
|
||||||
|
function ERC827TokenMock(address initialAccount, uint256 initialBalance) public {
|
||||||
|
balances[initialAccount] = initialBalance;
|
||||||
|
totalSupply_ = initialBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
19
contracts/mocks/FinalizableCrowdsaleImpl.sol
Normal file
19
contracts/mocks/FinalizableCrowdsaleImpl.sol
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
import "../crowdsale/FinalizableCrowdsale.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
|
||||||
|
|
||||||
|
function FinalizableCrowdsaleImpl (
|
||||||
|
uint256 _startTime,
|
||||||
|
uint256 _endTime,
|
||||||
|
uint256 _rate,
|
||||||
|
address _wallet
|
||||||
|
) public
|
||||||
|
Crowdsale(_startTime, _endTime, _rate, _wallet)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,13 +1,16 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
// @title Force Ether into a contract.
|
// @title Force Ether into a contract.
|
||||||
// @notice even
|
// @notice even
|
||||||
// if the contract is not payable.
|
// if the contract is not payable.
|
||||||
// @notice To use, construct the contract with the target as argument.
|
// @notice To use, construct the contract with the target as argument.
|
||||||
// @author Remco Bloemen <remco@neufund.org>
|
// @author Remco Bloemen <remco@neufund.org>
|
||||||
contract ForceEther {
|
contract ForceEther {
|
||||||
function ForceEther(address target) payable {
|
|
||||||
// Selfdestruct transfers all Ether to the arget address
|
function ForceEther() public payable { }
|
||||||
selfdestruct(target);
|
|
||||||
|
function destroyAndSend(address _recipient) public {
|
||||||
|
selfdestruct(_recipient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,11 +1,12 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
import "../../contracts/ownership/HasNoEther.sol";
|
import "../../contracts/ownership/HasNoEther.sol";
|
||||||
|
|
||||||
|
|
||||||
contract HasNoEtherTest is HasNoEther {
|
contract HasNoEtherTest is HasNoEther {
|
||||||
|
|
||||||
// Constructor with explicit payable — should still fail
|
// Constructor with explicit payable — should still fail
|
||||||
function HasNoEtherTest() payable {
|
function HasNoEtherTest() public payable {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,15 +1,15 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
import {Bounty, Target} from "../../contracts/Bounty.sol";
|
import {Bounty, Target} from "../../contracts/Bounty.sol";
|
||||||
|
|
||||||
|
|
||||||
contract InsecureTargetMock is Target {
|
contract InsecureTargetMock is Target {
|
||||||
function checkInvariant() returns(bool){
|
function checkInvariant() public returns(bool) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
contract InsecureTargetBounty is Bounty {
|
contract InsecureTargetBounty is Bounty {
|
||||||
function deployContract() internal returns (address) {
|
function deployContract() internal returns (address) {
|
||||||
return new InsecureTargetMock();
|
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.18;
|
||||||
|
|
||||||
|
|
||||||
|
import "../LimitBalance.sol";
|
||||||
|
|
||||||
|
|
||||||
|
// mock class using LimitBalance
|
||||||
|
contract LimitBalanceMock is LimitBalance(1000) {
|
||||||
|
|
||||||
|
function limitedDeposit() public payable limitedPayable {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
23
contracts/mocks/MessageHelper.sol
Normal file
23
contracts/mocks/MessageHelper.sol
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
|
contract MessageHelper {
|
||||||
|
|
||||||
|
event Show(bytes32 b32, uint256 number, string text);
|
||||||
|
|
||||||
|
function showMessage( bytes32 message, uint256 number, string text ) public returns (bool) {
|
||||||
|
Show(message, number, text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail() public {
|
||||||
|
require(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function call(address to, bytes data) public returns (bool) {
|
||||||
|
if (to.call(data))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,15 +1,15 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
import '../../contracts/lifecycle/Pausable.sol';
|
import "../lifecycle/Pausable.sol";
|
||||||
|
|
||||||
|
|
||||||
// mock class using Pausable
|
// mock class using Pausable
|
||||||
contract PausableMock is Pausable {
|
contract PausableMock is Pausable {
|
||||||
bool public drasticMeasureTaken;
|
bool public drasticMeasureTaken;
|
||||||
uint public count;
|
uint256 public count;
|
||||||
|
|
||||||
function PausableMock() {
|
function PausableMock() public {
|
||||||
drasticMeasureTaken = false;
|
drasticMeasureTaken = false;
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
@ -1,11 +1,12 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../token/ERC20/PausableToken.sol";
|
||||||
|
|
||||||
import '../../contracts/token/PausableToken.sol';
|
|
||||||
|
|
||||||
// mock class using PausableToken
|
// mock class using PausableToken
|
||||||
contract PausableTokenMock is PausableToken {
|
contract PausableTokenMock is PausableToken {
|
||||||
|
|
||||||
function PausableTokenMock(address initialAccount, uint initialBalance) {
|
function PausableTokenMock(address initialAccount, uint initialBalance) public {
|
||||||
balances[initialAccount] = initialBalance;
|
balances[initialAccount] = initialBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
17
contracts/mocks/PullPaymentMock.sol
Normal file
17
contracts/mocks/PullPaymentMock.sol
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
import "../payment/PullPayment.sol";
|
||||||
|
|
||||||
|
|
||||||
|
// mock class using PullPayment
|
||||||
|
contract PullPaymentMock is PullPayment {
|
||||||
|
|
||||||
|
function PullPaymentMock() public payable { }
|
||||||
|
|
||||||
|
// test helper function to call asyncSend
|
||||||
|
function callSend(address dest, uint256 amount) public {
|
||||||
|
asyncSend(dest, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
69
contracts/mocks/RBACMock.sol
Normal file
69
contracts/mocks/RBACMock.sol
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
pragma solidity ^0.4.8;
|
||||||
|
|
||||||
|
import "../ownership/rbac/RBAC.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract RBACMock is RBAC {
|
||||||
|
|
||||||
|
string constant ROLE_ADVISOR = "advisor";
|
||||||
|
|
||||||
|
modifier onlyAdminOrAdvisor()
|
||||||
|
{
|
||||||
|
require(
|
||||||
|
hasRole(msg.sender, ROLE_ADMIN) ||
|
||||||
|
hasRole(msg.sender, ROLE_ADVISOR)
|
||||||
|
);
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
function RBACMock(address[] _advisors)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
addRole(msg.sender, ROLE_ADVISOR);
|
||||||
|
|
||||||
|
for (uint256 i = 0; i < _advisors.length; i++) {
|
||||||
|
addRole(_advisors[i], ROLE_ADVISOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onlyAdminsCanDoThis()
|
||||||
|
onlyAdmin
|
||||||
|
view
|
||||||
|
external
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
function onlyAdvisorsCanDoThis()
|
||||||
|
onlyRole(ROLE_ADVISOR)
|
||||||
|
view
|
||||||
|
external
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
function eitherAdminOrAdvisorCanDoThis()
|
||||||
|
onlyAdminOrAdvisor
|
||||||
|
view
|
||||||
|
external
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
function nobodyCanDoThis()
|
||||||
|
onlyRole("unknown")
|
||||||
|
view
|
||||||
|
external
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// admins can remove advisor's role
|
||||||
|
function removeAdvisor(address _addr)
|
||||||
|
onlyAdmin
|
||||||
|
public
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
contracts/mocks/ReentrancyAttack.sol
Normal file
10
contracts/mocks/ReentrancyAttack.sol
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
contract ReentrancyAttack {
|
||||||
|
|
||||||
|
function callSender(bytes4 data) public {
|
||||||
|
require(msg.sender.call(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,22 +1,23 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../ReentrancyGuard.sol";
|
||||||
|
import "./ReentrancyAttack.sol";
|
||||||
|
|
||||||
import '../../contracts/ReentrancyGuard.sol';
|
|
||||||
import './ReentrancyAttack.sol';
|
|
||||||
|
|
||||||
contract ReentrancyMock is ReentrancyGuard {
|
contract ReentrancyMock is ReentrancyGuard {
|
||||||
|
|
||||||
uint256 public counter;
|
uint256 public counter;
|
||||||
|
|
||||||
function ReentrancyMock() {
|
function ReentrancyMock() public {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function count() private {
|
function callback() external nonReentrant {
|
||||||
counter += 1;
|
count();
|
||||||
}
|
}
|
||||||
|
|
||||||
function countLocalRecursive(uint n) public nonReentrant {
|
function countLocalRecursive(uint256 n) public nonReentrant {
|
||||||
if(n > 0) {
|
if (n > 0) {
|
||||||
count();
|
count();
|
||||||
countLocalRecursive(n - 1);
|
countLocalRecursive(n - 1);
|
||||||
}
|
}
|
||||||
@ -24,12 +25,10 @@ contract ReentrancyMock is ReentrancyGuard {
|
|||||||
|
|
||||||
function countThisRecursive(uint256 n) public nonReentrant {
|
function countThisRecursive(uint256 n) public nonReentrant {
|
||||||
bytes4 func = bytes4(keccak256("countThisRecursive(uint256)"));
|
bytes4 func = bytes4(keccak256("countThisRecursive(uint256)"));
|
||||||
if(n > 0) {
|
if (n > 0) {
|
||||||
count();
|
count();
|
||||||
bool result = this.call(func, n - 1);
|
bool result = this.call(func, n - 1);
|
||||||
if(result != true) {
|
require(result == true);
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,8 +38,8 @@ contract ReentrancyMock is ReentrancyGuard {
|
|||||||
attacker.callSender(func);
|
attacker.callSender(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
function callback() external nonReentrant {
|
function count() private {
|
||||||
count();
|
counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
21
contracts/mocks/RefundableCrowdsaleImpl.sol
Normal file
21
contracts/mocks/RefundableCrowdsaleImpl.sol
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
import "../crowdsale/RefundableCrowdsale.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract RefundableCrowdsaleImpl is RefundableCrowdsale {
|
||||||
|
|
||||||
|
function RefundableCrowdsaleImpl (
|
||||||
|
uint256 _startTime,
|
||||||
|
uint256 _endTime,
|
||||||
|
uint256 _rate,
|
||||||
|
address _wallet,
|
||||||
|
uint256 _goal
|
||||||
|
) public
|
||||||
|
Crowdsale(_startTime, _endTime, _rate, _wallet)
|
||||||
|
RefundableCrowdsale(_goal)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
95
contracts/mocks/SafeERC20Helper.sol
Normal file
95
contracts/mocks/SafeERC20Helper.sol
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
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 constant returns (uint256) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function allowance(address, address) public constant 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 constant returns (uint256) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function allowance(address, address) public constant returns (uint256) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contract SafeERC20Helper {
|
||||||
|
using SafeERC20 for ERC20;
|
||||||
|
|
||||||
|
ERC20 failing;
|
||||||
|
ERC20 succeeding;
|
||||||
|
|
||||||
|
function SafeERC20Helper() public {
|
||||||
|
failing = new ERC20FailingMock();
|
||||||
|
succeeding = new ERC20SucceedingMock();
|
||||||
|
}
|
||||||
|
|
||||||
|
function doFailingTransfer() public {
|
||||||
|
failing.safeTransfer(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doFailingTransferFrom() public {
|
||||||
|
failing.safeTransferFrom(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doFailingApprove() public {
|
||||||
|
failing.safeApprove(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doSucceedingTransfer() public {
|
||||||
|
succeeding.safeTransfer(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doSucceedingTransferFrom() public {
|
||||||
|
succeeding.safeTransferFrom(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doSucceedingApprove() public {
|
||||||
|
succeeding.safeApprove(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
contracts/mocks/SafeMathMock.sol
Normal file
21
contracts/mocks/SafeMathMock.sol
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
import "../math/SafeMath.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract SafeMathMock {
|
||||||
|
uint256 public result;
|
||||||
|
|
||||||
|
function multiply(uint256 a, uint256 b) public {
|
||||||
|
result = SafeMath.mul(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function subtract(uint256 a, uint256 b) public {
|
||||||
|
result = SafeMath.sub(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function add(uint256 a, uint256 b) public {
|
||||||
|
result = SafeMath.add(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,15 +1,15 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
import {Bounty, Target} from "../../contracts/Bounty.sol";
|
import {Bounty, Target} from "../../contracts/Bounty.sol";
|
||||||
|
|
||||||
|
|
||||||
contract SecureTargetMock is Target {
|
contract SecureTargetMock is Target {
|
||||||
function checkInvariant() returns(bool) {
|
function checkInvariant() public returns(bool) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
contract SecureTargetBounty is Bounty {
|
contract SecureTargetBounty is Bounty {
|
||||||
function deployContract() internal returns (address) {
|
function deployContract() internal returns (address) {
|
||||||
return new SecureTargetMock();
|
return new SecureTargetMock();
|
||||||
13
contracts/mocks/StandardTokenMock.sol
Normal file
13
contracts/mocks/StandardTokenMock.sol
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../token/ERC20/StandardToken.sol";
|
||||||
|
|
||||||
|
// mock class using StandardToken
|
||||||
|
contract StandardTokenMock is StandardToken {
|
||||||
|
|
||||||
|
function StandardTokenMock(address initialAccount, uint256 initialBalance) public {
|
||||||
|
balances[initialAccount] = initialBalance;
|
||||||
|
totalSupply_ = initialBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
26
contracts/ownership/CanReclaimToken.sol
Normal file
26
contracts/ownership/CanReclaimToken.sol
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./Ownable.sol";
|
||||||
|
import "../token/ERC20/ERC20Basic.sol";
|
||||||
|
import "../token/ERC20/SafeERC20.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Contracts that should be able to recover tokens
|
||||||
|
* @author SylTi
|
||||||
|
* @dev This allow a contract to recover any ERC20 token received in a contract by transferring the balance to the contract owner.
|
||||||
|
* This will prevent any accidental loss of tokens.
|
||||||
|
*/
|
||||||
|
contract CanReclaimToken is Ownable {
|
||||||
|
using SafeERC20 for ERC20Basic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Reclaim all ERC20Basic compatible tokens
|
||||||
|
* @param token ERC20Basic The address of the token contract
|
||||||
|
*/
|
||||||
|
function reclaimToken(ERC20Basic token) external onlyOwner {
|
||||||
|
uint256 balance = token.balanceOf(this);
|
||||||
|
token.safeTransfer(owner, balance);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
import './Ownable.sol';
|
import "./Ownable.sol";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,9 +16,7 @@ contract Claimable is Ownable {
|
|||||||
* @dev Modifier throws if called by any account other than the pendingOwner.
|
* @dev Modifier throws if called by any account other than the pendingOwner.
|
||||||
*/
|
*/
|
||||||
modifier onlyPendingOwner() {
|
modifier onlyPendingOwner() {
|
||||||
if (msg.sender != pendingOwner) {
|
require(msg.sender == pendingOwner);
|
||||||
throw;
|
|
||||||
}
|
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,15 +24,16 @@ contract Claimable is Ownable {
|
|||||||
* @dev Allows the current owner to set the pendingOwner address.
|
* @dev Allows the current owner to set the pendingOwner address.
|
||||||
* @param newOwner The address to transfer ownership to.
|
* @param newOwner The address to transfer ownership to.
|
||||||
*/
|
*/
|
||||||
function transferOwnership(address newOwner) onlyOwner {
|
function transferOwnership(address newOwner) onlyOwner public {
|
||||||
pendingOwner = newOwner;
|
pendingOwner = newOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Allows the pendingOwner address to finalize the transfer.
|
* @dev Allows the pendingOwner address to finalize the transfer.
|
||||||
*/
|
*/
|
||||||
function claimOwnership() onlyPendingOwner {
|
function claimOwnership() onlyPendingOwner public {
|
||||||
|
OwnershipTransferred(owner, pendingOwner);
|
||||||
owner = pendingOwner;
|
owner = pendingOwner;
|
||||||
pendingOwner = 0x0;
|
pendingOwner = address(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,22 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./Ownable.sol";
|
||||||
|
|
||||||
import './Ownable.sol';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Contactable token
|
* @title Contactable token
|
||||||
* @dev Basic version of a contactable contract, allowing the owner to provide a string with their
|
* @dev Basic version of a contactable contract, allowing the owner to provide a string with their
|
||||||
* contact information.
|
* contact information.
|
||||||
*/
|
*/
|
||||||
contract Contactable is Ownable{
|
contract Contactable is Ownable {
|
||||||
|
|
||||||
string public contactInformation;
|
string public contactInformation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Allows the owner to set a string with their contact information.
|
* @dev Allows the owner to set a string with their contact information.
|
||||||
* @param info The contact information to attach to the contract.
|
* @param info The contact information to attach to the contract.
|
||||||
*/
|
*/
|
||||||
function setContactInformation(string info) onlyOwner{
|
function setContactInformation(string info) onlyOwner public {
|
||||||
contactInformation = info;
|
contactInformation = info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./Claimable.sol";
|
||||||
import './Claimable.sol';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,8 +10,8 @@ import './Claimable.sol';
|
|||||||
*/
|
*/
|
||||||
contract DelayedClaimable is Claimable {
|
contract DelayedClaimable is Claimable {
|
||||||
|
|
||||||
uint public end;
|
uint256 public end;
|
||||||
uint public start;
|
uint256 public start;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Used to specify the time period during which a pending
|
* @dev Used to specify the time period during which a pending
|
||||||
@ -20,23 +19,21 @@ contract DelayedClaimable is Claimable {
|
|||||||
* @param _start The earliest time ownership can be claimed.
|
* @param _start The earliest time ownership can be claimed.
|
||||||
* @param _end The latest time ownership can be claimed.
|
* @param _end The latest time ownership can be claimed.
|
||||||
*/
|
*/
|
||||||
function setLimits(uint _start, uint _end) onlyOwner {
|
function setLimits(uint256 _start, uint256 _end) onlyOwner public {
|
||||||
if (_start > _end)
|
require(_start <= _end);
|
||||||
throw;
|
|
||||||
end = _end;
|
end = _end;
|
||||||
start = _start;
|
start = _start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Allows the pendingOwner address to finalize the transfer, as long as it is called within
|
* @dev Allows the pendingOwner address to finalize the transfer, as long as it is called within
|
||||||
* the specified start and end time.
|
* the specified start and end time.
|
||||||
*/
|
*/
|
||||||
function claimOwnership() onlyPendingOwner {
|
function claimOwnership() onlyPendingOwner public {
|
||||||
if ((block.number > end) || (block.number < start))
|
require((block.number <= end) && (block.number >= start));
|
||||||
throw;
|
OwnershipTransferred(owner, pendingOwner);
|
||||||
owner = pendingOwner;
|
owner = pendingOwner;
|
||||||
pendingOwner = 0x0;
|
pendingOwner = address(0);
|
||||||
end = 0;
|
end = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
import "./Ownable.sol";
|
import "./Ownable.sol";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Contracts that should not own Contracts
|
* @title Contracts that should not own Contracts
|
||||||
* @author Remco Bloemen <remco@2π.com>
|
* @author Remco Bloemen <remco@2π.com>
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
import "./Ownable.sol";
|
import "./Ownable.sol";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Contracts that should not own Ether
|
* @title Contracts that should not own Ether
|
||||||
* @author Remco Bloemen <remco@2π.com>
|
* @author Remco Bloemen <remco@2π.com>
|
||||||
@ -21,10 +22,8 @@ contract HasNoEther is Ownable {
|
|||||||
* constructor. By doing it this way we prevent a payable constructor from working. Alternatively
|
* constructor. By doing it this way we prevent a payable constructor from working. Alternatively
|
||||||
* we could use assembly to access msg.value.
|
* we could use assembly to access msg.value.
|
||||||
*/
|
*/
|
||||||
function HasNoEther() payable {
|
function HasNoEther() public payable {
|
||||||
if(msg.value > 0) {
|
require(msg.value == 0);
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,8 +36,6 @@ contract HasNoEther is Ownable {
|
|||||||
* @dev Transfer all Ether held by the contract to the owner.
|
* @dev Transfer all Ether held by the contract to the owner.
|
||||||
*/
|
*/
|
||||||
function reclaimEther() external onlyOwner {
|
function reclaimEther() external onlyOwner {
|
||||||
if(!owner.send(this.balance)) {
|
assert(owner.send(this.balance));
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,34 +1,28 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./CanReclaimToken.sol";
|
||||||
|
|
||||||
import "./Ownable.sol";
|
|
||||||
import "../token/ERC20Basic.sol";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Contracts that should not own Tokens
|
* @title Contracts that should not own Tokens
|
||||||
* @author Remco Bloemen <remco@2π.com>
|
* @author Remco Bloemen <remco@2π.com>
|
||||||
* @dev This blocks incoming ERC23 tokens to prevent accidental loss of tokens.
|
* @dev This blocks incoming ERC223 tokens to prevent accidental loss of tokens.
|
||||||
* Should tokens (any ERC20Basic compatible) end up in the contract, it allows the
|
* Should tokens (any ERC20Basic compatible) end up in the contract, it allows the
|
||||||
* owner to reclaim the tokens.
|
* owner to reclaim the tokens.
|
||||||
*/
|
*/
|
||||||
contract HasNoTokens is Ownable {
|
contract HasNoTokens is CanReclaimToken {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Reject all ERC23 compatible tokens
|
* @dev Reject all ERC223 compatible tokens
|
||||||
* @param from_ address The address that is transferring the tokens
|
* @param from_ address The address that is transferring the tokens
|
||||||
* @param value_ Uint the amount of the specified token
|
* @param value_ uint256 the amount of the specified token
|
||||||
* @param data_ Bytes The data passed from the caller.
|
* @param data_ Bytes The data passed from the caller.
|
||||||
*/
|
*/
|
||||||
function tokenFallback(address from_, uint value_, bytes data_) external {
|
function tokenFallback(address from_, uint256 value_, bytes data_) external {
|
||||||
throw;
|
from_;
|
||||||
|
value_;
|
||||||
|
data_;
|
||||||
|
revert();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Reclaim all ERC20Basic compatible tokens
|
|
||||||
* @param tokenAddr address The address of the token contract
|
|
||||||
*/
|
|
||||||
function reclaimToken(address tokenAddr) external onlyOwner {
|
|
||||||
ERC20Basic tokenInst = ERC20Basic(tokenAddr);
|
|
||||||
uint256 balance = tokenInst.balanceOf(this);
|
|
||||||
tokenInst.transfer(owner, balance);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
99
contracts/ownership/Heritable.sol
Normal file
99
contracts/ownership/Heritable.sol
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
|
|
||||||
|
import "./Ownable.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Heritable
|
||||||
|
* @dev The Heritable contract provides ownership transfer capabilities, in the
|
||||||
|
* case that the current owner stops "heartbeating". Only the heir can pronounce the
|
||||||
|
* owner's death.
|
||||||
|
*/
|
||||||
|
contract Heritable is Ownable {
|
||||||
|
address public heir;
|
||||||
|
|
||||||
|
// Time window the owner has to notify they are alive.
|
||||||
|
uint256 public heartbeatTimeout;
|
||||||
|
|
||||||
|
// Timestamp of the owner's death, as pronounced by the heir.
|
||||||
|
uint256 public timeOfDeath;
|
||||||
|
|
||||||
|
event HeirChanged(address indexed owner, address indexed newHeir);
|
||||||
|
event OwnerHeartbeated(address indexed owner);
|
||||||
|
event OwnerProclaimedDead(address indexed owner, address indexed heir, uint256 timeOfDeath);
|
||||||
|
event HeirOwnershipClaimed(address indexed previousOwner, address indexed newOwner);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Throw an exception if called by any account other than the heir's.
|
||||||
|
*/
|
||||||
|
modifier onlyHeir() {
|
||||||
|
require(msg.sender == heir);
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Create a new Heritable Contract with heir address 0x0.
|
||||||
|
* @param _heartbeatTimeout time available for the owner to notify they are alive,
|
||||||
|
* before the heir can take ownership.
|
||||||
|
*/
|
||||||
|
function Heritable(uint256 _heartbeatTimeout) public {
|
||||||
|
setHeartbeatTimeout(_heartbeatTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHeir(address newHeir) public onlyOwner {
|
||||||
|
require(newHeir != owner);
|
||||||
|
heartbeat();
|
||||||
|
HeirChanged(owner, newHeir);
|
||||||
|
heir = newHeir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev set heir = 0x0
|
||||||
|
*/
|
||||||
|
function removeHeir() public onlyOwner {
|
||||||
|
heartbeat();
|
||||||
|
heir = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Heir can pronounce the owners death. To claim the ownership, they will
|
||||||
|
* have to wait for `heartbeatTimeout` seconds.
|
||||||
|
*/
|
||||||
|
function proclaimDeath() public onlyHeir {
|
||||||
|
require(ownerLives());
|
||||||
|
OwnerProclaimedDead(owner, heir, timeOfDeath);
|
||||||
|
timeOfDeath = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Owner can send a heartbeat if they were mistakenly pronounced dead.
|
||||||
|
*/
|
||||||
|
function heartbeat() public onlyOwner {
|
||||||
|
OwnerHeartbeated(owner);
|
||||||
|
timeOfDeath = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Allows heir to transfer ownership only if heartbeat has timed out.
|
||||||
|
*/
|
||||||
|
function claimHeirOwnership() public onlyHeir {
|
||||||
|
require(!ownerLives());
|
||||||
|
require(now >= timeOfDeath + heartbeatTimeout);
|
||||||
|
OwnershipTransferred(owner, heir);
|
||||||
|
HeirOwnershipClaimed(owner, heir);
|
||||||
|
owner = heir;
|
||||||
|
timeOfDeath = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHeartbeatTimeout(uint256 newHeartbeatTimeout) internal onlyOwner {
|
||||||
|
require(ownerLives());
|
||||||
|
heartbeatTimeout = newHeartbeatTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ownerLives() internal view returns (bool) {
|
||||||
|
return timeOfDeath == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,28 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @title Multisig
|
|
||||||
* @dev Interface contract for multisig proxy contracts; see below for docs.
|
|
||||||
*/
|
|
||||||
contract Multisig {
|
|
||||||
// EVENTS
|
|
||||||
|
|
||||||
// logged events:
|
|
||||||
// Funds has arrived into the wallet (record how much).
|
|
||||||
event Deposit(address _from, uint value);
|
|
||||||
// Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going).
|
|
||||||
event SingleTransact(address owner, uint value, address to, bytes data);
|
|
||||||
// Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going).
|
|
||||||
event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data);
|
|
||||||
// Confirmation still needed for a transaction.
|
|
||||||
event ConfirmationNeeded(bytes32 operation, address initiator, uint value, address to, bytes data);
|
|
||||||
|
|
||||||
|
|
||||||
// FUNCTIONS
|
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
function changeOwner(address _from, address _to) external;
|
|
||||||
function execute(address _to, uint _value, bytes _data) external returns (bytes32);
|
|
||||||
function confirm(bytes32 _h) returns (bool);
|
|
||||||
}
|
|
||||||
@ -1,9 +1,10 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
import "./HasNoEther.sol";
|
import "./HasNoEther.sol";
|
||||||
import "./HasNoTokens.sol";
|
import "./HasNoTokens.sol";
|
||||||
import "./HasNoContracts.sol";
|
import "./HasNoContracts.sol";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Base contract for contracts that should not own things.
|
* @title Base contract for contracts that should not own things.
|
||||||
* @author Remco Bloemen <remco@2π.com>
|
* @author Remco Bloemen <remco@2π.com>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,34 +10,33 @@ contract Ownable {
|
|||||||
address public owner;
|
address public owner;
|
||||||
|
|
||||||
|
|
||||||
|
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
|
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
|
||||||
* account.
|
* account.
|
||||||
*/
|
*/
|
||||||
function Ownable() {
|
function Ownable() public {
|
||||||
owner = msg.sender;
|
owner = msg.sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Throws if called by any account other than the owner.
|
* @dev Throws if called by any account other than the owner.
|
||||||
*/
|
*/
|
||||||
modifier onlyOwner() {
|
modifier onlyOwner() {
|
||||||
if (msg.sender != owner) {
|
require(msg.sender == owner);
|
||||||
throw;
|
|
||||||
}
|
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Allows the current owner to transfer control of the contract to a newOwner.
|
* @dev Allows the current owner to transfer control of the contract to a newOwner.
|
||||||
* @param newOwner The address to transfer ownership to.
|
* @param newOwner The address to transfer ownership to.
|
||||||
*/
|
*/
|
||||||
function transferOwnership(address newOwner) onlyOwner {
|
function transferOwnership(address newOwner) public onlyOwner {
|
||||||
if (newOwner != address(0)) {
|
require(newOwner != address(0));
|
||||||
owner = newOwner;
|
OwnershipTransferred(owner, newOwner);
|
||||||
}
|
owner = newOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,189 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @title Shareable
|
|
||||||
* @dev inheritable "property" contract that enables methods to be protected by requiring the
|
|
||||||
* acquiescence of either a single, or, crucially, each of a number of, designated owners.
|
|
||||||
* @dev Usage: use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by some number (specified in constructor) of the set of owners (specified in the constructor) before the interior is executed.
|
|
||||||
*/
|
|
||||||
contract Shareable {
|
|
||||||
|
|
||||||
// struct for the status of a pending operation.
|
|
||||||
struct PendingState {
|
|
||||||
uint yetNeeded;
|
|
||||||
uint ownersDone;
|
|
||||||
uint index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the number of owners that must confirm the same operation before it is run.
|
|
||||||
uint public required;
|
|
||||||
|
|
||||||
// list of owners
|
|
||||||
address[256] owners;
|
|
||||||
// index on the list of owners to allow reverse lookup
|
|
||||||
mapping(address => uint) ownerIndex;
|
|
||||||
// the ongoing operations.
|
|
||||||
mapping(bytes32 => PendingState) pendings;
|
|
||||||
bytes32[] pendingsIndex;
|
|
||||||
|
|
||||||
|
|
||||||
// this contract only has six types of events: it can accept a confirmation, in which case
|
|
||||||
// we record owner and operation (hash) alongside it.
|
|
||||||
event Confirmation(address owner, bytes32 operation);
|
|
||||||
event Revoke(address owner, bytes32 operation);
|
|
||||||
|
|
||||||
|
|
||||||
// simple single-sig function modifier.
|
|
||||||
modifier onlyOwner {
|
|
||||||
if (!isOwner(msg.sender)) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Modifier for multisig functions.
|
|
||||||
* @param _operation The operation must have an intrinsic hash in order that later attempts can be
|
|
||||||
* realised as the same underlying operation and thus count as confirmations.
|
|
||||||
*/
|
|
||||||
modifier onlymanyowners(bytes32 _operation) {
|
|
||||||
if (confirmAndCheck(_operation)) {
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Constructor is given the number of sigs required to do protected "onlymanyowners"
|
|
||||||
* transactions as well as the selection of addresses capable of confirming them.
|
|
||||||
* @param _owners A list of owners.
|
|
||||||
* @param _required The amount required for a transaction to be approved.
|
|
||||||
*/
|
|
||||||
function Shareable(address[] _owners, uint _required) {
|
|
||||||
owners[1] = msg.sender;
|
|
||||||
ownerIndex[msg.sender] = 1;
|
|
||||||
for (uint i = 0; i < _owners.length; ++i) {
|
|
||||||
owners[2 + i] = _owners[i];
|
|
||||||
ownerIndex[_owners[i]] = 2 + i;
|
|
||||||
}
|
|
||||||
required = _required;
|
|
||||||
if (required > owners.length) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Revokes a prior confirmation of the given operation.
|
|
||||||
* @param _operation A string identifying the operation.
|
|
||||||
*/
|
|
||||||
function revoke(bytes32 _operation) external {
|
|
||||||
uint index = ownerIndex[msg.sender];
|
|
||||||
// make sure they're an owner
|
|
||||||
if (index == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint ownerIndexBit = 2**index;
|
|
||||||
var pending = pendings[_operation];
|
|
||||||
if (pending.ownersDone & ownerIndexBit > 0) {
|
|
||||||
pending.yetNeeded++;
|
|
||||||
pending.ownersDone -= ownerIndexBit;
|
|
||||||
Revoke(msg.sender, _operation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Gets an owner by 0-indexed position (using numOwners as the count)
|
|
||||||
* @param ownerIndex Uint The index of the owner
|
|
||||||
* @return The address of the owner
|
|
||||||
*/
|
|
||||||
function getOwner(uint ownerIndex) external constant returns (address) {
|
|
||||||
return address(owners[ownerIndex + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Checks if given address is an owner.
|
|
||||||
* @param _addr address The address which you want to check.
|
|
||||||
* @return True if the address is an owner and fase otherwise.
|
|
||||||
*/
|
|
||||||
function isOwner(address _addr) constant returns (bool) {
|
|
||||||
return ownerIndex[_addr] > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Function to check is specific owner has already confirme the operation.
|
|
||||||
* @param _operation The operation identifier.
|
|
||||||
* @param _owner The owner address.
|
|
||||||
* @return True if the owner has confirmed and false otherwise.
|
|
||||||
*/
|
|
||||||
function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) {
|
|
||||||
var pending = pendings[_operation];
|
|
||||||
uint index = ownerIndex[_owner];
|
|
||||||
|
|
||||||
// make sure they're an owner
|
|
||||||
if (index == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine the bit to set for this owner.
|
|
||||||
uint ownerIndexBit = 2**index;
|
|
||||||
return !(pending.ownersDone & ownerIndexBit == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Confirm and operation and checks if it's already executable.
|
|
||||||
* @param _operation The operation identifier.
|
|
||||||
* @return Returns true when operation can be executed.
|
|
||||||
*/
|
|
||||||
function confirmAndCheck(bytes32 _operation) internal returns (bool) {
|
|
||||||
// determine what index the present sender is:
|
|
||||||
uint index = ownerIndex[msg.sender];
|
|
||||||
// make sure they're an owner
|
|
||||||
if (index == 0) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pending = pendings[_operation];
|
|
||||||
// if we're not yet working on this operation, switch over and reset the confirmation status.
|
|
||||||
if (pending.yetNeeded == 0) {
|
|
||||||
// reset count of confirmations needed.
|
|
||||||
pending.yetNeeded = required;
|
|
||||||
// reset which owners have confirmed (none) - set our bitmap to 0.
|
|
||||||
pending.ownersDone = 0;
|
|
||||||
pending.index = pendingsIndex.length++;
|
|
||||||
pendingsIndex[pending.index] = _operation;
|
|
||||||
}
|
|
||||||
// determine the bit to set for this owner.
|
|
||||||
uint ownerIndexBit = 2**index;
|
|
||||||
// make sure we (the message sender) haven't confirmed this operation previously.
|
|
||||||
if (pending.ownersDone & ownerIndexBit == 0) {
|
|
||||||
Confirmation(msg.sender, _operation);
|
|
||||||
// ok - check if count is enough to go ahead.
|
|
||||||
if (pending.yetNeeded <= 1) {
|
|
||||||
// enough confirmations: reset and run interior.
|
|
||||||
delete pendingsIndex[pendings[_operation].index];
|
|
||||||
delete pendings[_operation];
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// not enough: record that this owner in particular confirmed.
|
|
||||||
pending.yetNeeded--;
|
|
||||||
pending.ownersDone |= ownerIndexBit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Clear the pending list.
|
|
||||||
*/
|
|
||||||
function clearPending() internal {
|
|
||||||
uint length = pendingsIndex.length;
|
|
||||||
for (uint i = 0; i < length; ++i) {
|
|
||||||
if (pendingsIndex[i] != 0) {
|
|
||||||
delete pendings[pendingsIndex[i]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete pendingsIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
156
contracts/ownership/rbac/RBAC.sol
Normal file
156
contracts/ownership/rbac/RBAC.sol
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
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.
|
||||||
|
* It's also recommended that you define constants in the contract, like ROLE_ADMIN below,
|
||||||
|
* to avoid typos.
|
||||||
|
*/
|
||||||
|
contract RBAC {
|
||||||
|
using Roles for Roles.Role;
|
||||||
|
|
||||||
|
mapping (string => Roles.Role) private roles;
|
||||||
|
|
||||||
|
event RoleAdded(address addr, string roleName);
|
||||||
|
event RoleRemoved(address addr, string roleName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A constant role name for indicating admins.
|
||||||
|
*/
|
||||||
|
string public constant ROLE_ADMIN = "admin";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev constructor. Sets msg.sender as admin by default
|
||||||
|
*/
|
||||||
|
function RBAC()
|
||||||
|
public
|
||||||
|
{
|
||||||
|
addRole(msg.sender, ROLE_ADMIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev reverts if addr does not have role
|
||||||
|
* @param addr address
|
||||||
|
* @param roleName the name of the role
|
||||||
|
* // reverts
|
||||||
|
*/
|
||||||
|
function checkRole(address addr, string roleName)
|
||||||
|
view
|
||||||
|
public
|
||||||
|
{
|
||||||
|
roles[roleName].check(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev determine if addr has role
|
||||||
|
* @param addr address
|
||||||
|
* @param roleName the name of the role
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function hasRole(address addr, string roleName)
|
||||||
|
view
|
||||||
|
public
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return roles[roleName].has(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev add a role to an address
|
||||||
|
* @param addr address
|
||||||
|
* @param roleName the name of the role
|
||||||
|
*/
|
||||||
|
function adminAddRole(address addr, string roleName)
|
||||||
|
onlyAdmin
|
||||||
|
public
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
onlyAdmin
|
||||||
|
public
|
||||||
|
{
|
||||||
|
removeRole(addr, roleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev add a role to an address
|
||||||
|
* @param addr address
|
||||||
|
* @param roleName the name of the role
|
||||||
|
*/
|
||||||
|
function addRole(address addr, string roleName)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
roles[roleName].add(addr);
|
||||||
|
RoleAdded(addr, roleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev remove a role from an address
|
||||||
|
* @param addr address
|
||||||
|
* @param roleName the name of the role
|
||||||
|
*/
|
||||||
|
function removeRole(address addr, string roleName)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
roles[roleName].remove(addr);
|
||||||
|
RoleRemoved(addr, roleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev modifier to scope access to a single role (uses msg.sender as addr)
|
||||||
|
* @param roleName the name of the role
|
||||||
|
* // reverts
|
||||||
|
*/
|
||||||
|
modifier onlyRole(string roleName)
|
||||||
|
{
|
||||||
|
checkRole(msg.sender, roleName);
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev modifier to scope access to admins
|
||||||
|
* // reverts
|
||||||
|
*/
|
||||||
|
modifier onlyAdmin()
|
||||||
|
{
|
||||||
|
checkRole(msg.sender, ROLE_ADMIN);
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev modifier to scope access to a set of roles (uses msg.sender as addr)
|
||||||
|
* @param roleNames 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[] roleNames) {
|
||||||
|
// bool hasAnyRole = false;
|
||||||
|
// for (uint8 i = 0; i < roleNames.length; i++) {
|
||||||
|
// if (hasRole(msg.sender, roleNames[i])) {
|
||||||
|
// hasAnyRole = true;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// require(hasAnyRole);
|
||||||
|
|
||||||
|
// _;
|
||||||
|
// }
|
||||||
|
}
|
||||||
55
contracts/ownership/rbac/Roles.sol
Normal file
55
contracts/ownership/rbac/Roles.sol
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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)
|
||||||
|
view
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
require(has(role, addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev check if an address has this role
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function has(Role storage role, address addr)
|
||||||
|
view
|
||||||
|
internal
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return role.bearer[addr];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
import '../SafeMath.sol';
|
import "../math/SafeMath.sol";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,41 +10,34 @@ import '../SafeMath.sol';
|
|||||||
* contract and use asyncSend instead of send.
|
* contract and use asyncSend instead of send.
|
||||||
*/
|
*/
|
||||||
contract PullPayment {
|
contract PullPayment {
|
||||||
using SafeMath for uint;
|
using SafeMath for uint256;
|
||||||
|
|
||||||
mapping(address => uint) public payments;
|
mapping(address => uint256) public payments;
|
||||||
uint public totalPayments;
|
uint256 public totalPayments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev withdraw accumulated balance, called by payee.
|
||||||
|
*/
|
||||||
|
function withdrawPayments() public {
|
||||||
|
address payee = msg.sender;
|
||||||
|
uint256 payment = payments[payee];
|
||||||
|
|
||||||
|
require(payment != 0);
|
||||||
|
require(this.balance >= payment);
|
||||||
|
|
||||||
|
totalPayments = totalPayments.sub(payment);
|
||||||
|
payments[payee] = 0;
|
||||||
|
|
||||||
|
assert(payee.send(payment));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Called by the payer to store the sent amount as credit to be pulled.
|
* @dev Called by the payer to store the sent amount as credit to be pulled.
|
||||||
* @param dest The destination address of the funds.
|
* @param dest The destination address of the funds.
|
||||||
* @param amount The amount to transfer.
|
* @param amount The amount to transfer.
|
||||||
*/
|
*/
|
||||||
function asyncSend(address dest, uint amount) internal {
|
function asyncSend(address dest, uint256 amount) internal {
|
||||||
payments[dest] = payments[dest].add(amount);
|
payments[dest] = payments[dest].add(amount);
|
||||||
totalPayments = totalPayments.add(amount);
|
totalPayments = totalPayments.add(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev withdraw accumulated balance, called by payee.
|
|
||||||
*/
|
|
||||||
function withdrawPayments() {
|
|
||||||
address payee = msg.sender;
|
|
||||||
uint payment = payments[payee];
|
|
||||||
|
|
||||||
if (payment == 0) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.balance < payment) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
totalPayments = totalPayments.sub(payment);
|
|
||||||
payments[payee] = 0;
|
|
||||||
|
|
||||||
if (!payee.send(payment)) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
71
contracts/payment/SplitPayment.sol
Normal file
71
contracts/payment/SplitPayment.sol
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "../math/SafeMath.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title SplitPayment
|
||||||
|
* @dev Base contract that supports multiple payees claiming funds sent to this contract
|
||||||
|
* according to the proportion they own.
|
||||||
|
*/
|
||||||
|
contract SplitPayment {
|
||||||
|
using SafeMath for uint256;
|
||||||
|
|
||||||
|
uint256 public totalShares = 0;
|
||||||
|
uint256 public totalReleased = 0;
|
||||||
|
|
||||||
|
mapping(address => uint256) public shares;
|
||||||
|
mapping(address => uint256) public released;
|
||||||
|
address[] public payees;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Constructor
|
||||||
|
*/
|
||||||
|
function SplitPayment(address[] _payees, uint256[] _shares) public payable {
|
||||||
|
require(_payees.length == _shares.length);
|
||||||
|
|
||||||
|
for (uint256 i = 0; i < _payees.length; i++) {
|
||||||
|
addPayee(_payees[i], _shares[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev payable fallback
|
||||||
|
*/
|
||||||
|
function () public payable {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Claim your share of the balance.
|
||||||
|
*/
|
||||||
|
function claim() public {
|
||||||
|
address payee = msg.sender;
|
||||||
|
|
||||||
|
require(shares[payee] > 0);
|
||||||
|
|
||||||
|
uint256 totalReceived = this.balance.add(totalReleased);
|
||||||
|
uint256 payment = totalReceived.mul(shares[payee]).div(totalShares).sub(released[payee]);
|
||||||
|
|
||||||
|
require(payment != 0);
|
||||||
|
require(this.balance >= payment);
|
||||||
|
|
||||||
|
released[payee] = released[payee].add(payment);
|
||||||
|
totalReleased = totalReleased.add(payment);
|
||||||
|
|
||||||
|
payee.transfer(payment);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Add a new payee to the contract.
|
||||||
|
* @param _payee The address of the payee to add.
|
||||||
|
* @param _shares The number of shares owned by the payee.
|
||||||
|
*/
|
||||||
|
function addPayee(address _payee, uint256 _shares) internal {
|
||||||
|
require(_payee != address(0));
|
||||||
|
require(_shares > 0);
|
||||||
|
require(shares[_payee] == 0);
|
||||||
|
|
||||||
|
payees.push(_payee);
|
||||||
|
shares[_payee] = _shares;
|
||||||
|
totalShares = totalShares.add(_shares);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,47 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
|
|
||||||
import './ERC20Basic.sol';
|
|
||||||
import '../SafeMath.sol';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @title Basic token
|
|
||||||
* @dev Basic version of StandardToken, with no allowances.
|
|
||||||
*/
|
|
||||||
contract BasicToken is ERC20Basic {
|
|
||||||
using SafeMath for uint;
|
|
||||||
|
|
||||||
mapping(address => uint) balances;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Fix for the ERC20 short address attack.
|
|
||||||
*/
|
|
||||||
modifier onlyPayloadSize(uint size) {
|
|
||||||
if(msg.data.length < size + 4) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev transfer token for a specified address
|
|
||||||
* @param _to The address to transfer to.
|
|
||||||
* @param _value The amount to be transferred.
|
|
||||||
*/
|
|
||||||
function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) {
|
|
||||||
balances[msg.sender] = balances[msg.sender].sub(_value);
|
|
||||||
balances[_to] = balances[_to].add(_value);
|
|
||||||
Transfer(msg.sender, _to, _value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Gets the balance of the specified address.
|
|
||||||
* @param _owner The address to query the the balance of.
|
|
||||||
* @return An uint representing the amount owned by the passed address.
|
|
||||||
*/
|
|
||||||
function balanceOf(address _owner) constant returns (uint balance) {
|
|
||||||
return balances[_owner];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
|
|
||||||
import "./StandardToken.sol";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @title CrowdsaleToken
|
|
||||||
*
|
|
||||||
* @dev Simple ERC20 Token example, with crowdsale token creation
|
|
||||||
* @dev IMPORTANT NOTE: do not use or deploy this contract as-is. It needs some changes to be
|
|
||||||
* production ready.
|
|
||||||
*/
|
|
||||||
contract CrowdsaleToken is StandardToken {
|
|
||||||
|
|
||||||
string public constant name = "CrowdsaleToken";
|
|
||||||
string public constant symbol = "CRW";
|
|
||||||
uint public constant decimals = 18;
|
|
||||||
// replace with your fund collection multisig address
|
|
||||||
address public constant multisig = 0x0;
|
|
||||||
|
|
||||||
|
|
||||||
// 1 ether = 500 example tokens
|
|
||||||
uint public constant PRICE = 500;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Fallback function which receives ether and sends the appropriate number of tokens to the
|
|
||||||
* msg.sender.
|
|
||||||
*/
|
|
||||||
function () payable {
|
|
||||||
createTokens(msg.sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Creates tokens and send to the specified address.
|
|
||||||
* @param recipient The address which will recieve the new tokens.
|
|
||||||
*/
|
|
||||||
function createTokens(address recipient) payable {
|
|
||||||
if (msg.value == 0) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint tokens = msg.value.mul(getPrice());
|
|
||||||
totalSupply = totalSupply.add(tokens);
|
|
||||||
|
|
||||||
balances[recipient] = balances[recipient].add(tokens);
|
|
||||||
|
|
||||||
if (!multisig.send(msg.value)) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev replace this with any other price function
|
|
||||||
* @return The price per unit of token.
|
|
||||||
*/
|
|
||||||
function getPrice() constant returns (uint result) {
|
|
||||||
return PRICE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
|
|
||||||
import './ERC20Basic.sol';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @title ERC20 interface
|
|
||||||
* @dev see https://github.com/ethereum/EIPs/issues/20
|
|
||||||
*/
|
|
||||||
contract ERC20 is ERC20Basic {
|
|
||||||
function allowance(address owner, address spender) constant returns (uint);
|
|
||||||
function transferFrom(address from, address to, uint value);
|
|
||||||
function approve(address spender, uint value);
|
|
||||||
event Approval(address indexed owner, address indexed spender, uint value);
|
|
||||||
}
|
|
||||||
51
contracts/token/ERC20/BasicToken.sol
Normal file
51
contracts/token/ERC20/BasicToken.sol
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
import "./ERC20Basic.sol";
|
||||||
|
import "../../math/SafeMath.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Basic token
|
||||||
|
* @dev Basic version of StandardToken, with no allowances.
|
||||||
|
*/
|
||||||
|
contract BasicToken is ERC20Basic {
|
||||||
|
using SafeMath for uint256;
|
||||||
|
|
||||||
|
mapping(address => uint256) balances;
|
||||||
|
|
||||||
|
uint256 totalSupply_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev total number of tokens in existence
|
||||||
|
*/
|
||||||
|
function totalSupply() public view returns (uint256) {
|
||||||
|
return totalSupply_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev transfer token for a specified address
|
||||||
|
* @param _to The address to transfer to.
|
||||||
|
* @param _value The amount to be transferred.
|
||||||
|
*/
|
||||||
|
function transfer(address _to, uint256 _value) public returns (bool) {
|
||||||
|
require(_to != address(0));
|
||||||
|
require(_value <= balances[msg.sender]);
|
||||||
|
|
||||||
|
// SafeMath.sub will throw if there is not enough balance.
|
||||||
|
balances[msg.sender] = balances[msg.sender].sub(_value);
|
||||||
|
balances[_to] = balances[_to].add(_value);
|
||||||
|
Transfer(msg.sender, _to, _value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Gets the balance of the specified address.
|
||||||
|
* @param _owner The address to query the the balance of.
|
||||||
|
* @return An uint256 representing the amount owned by the passed address.
|
||||||
|
*/
|
||||||
|
function balanceOf(address _owner) public view returns (uint256 balance) {
|
||||||
|
return balances[_owner];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
28
contracts/token/ERC20/BurnableToken.sol
Normal file
28
contracts/token/ERC20/BurnableToken.sol
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./BasicToken.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Burnable Token
|
||||||
|
* @dev Token that can be irreversibly burned (destroyed).
|
||||||
|
*/
|
||||||
|
contract BurnableToken is BasicToken {
|
||||||
|
|
||||||
|
event Burn(address indexed burner, uint256 value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Burns a specific amount of tokens.
|
||||||
|
* @param _value The amount of token to be burned.
|
||||||
|
*/
|
||||||
|
function burn(uint256 _value) public {
|
||||||
|
require(_value <= balances[msg.sender]);
|
||||||
|
// no need to require value <= totalSupply, since that would imply the
|
||||||
|
// sender's balance is greater than the totalSupply, which *should* be an assertion failure
|
||||||
|
|
||||||
|
address burner = msg.sender;
|
||||||
|
balances[burner] = balances[burner].sub(_value);
|
||||||
|
totalSupply_ = totalSupply_.sub(_value);
|
||||||
|
Burn(burner, _value);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
contracts/token/ERC20/CappedToken.sol
Normal file
31
contracts/token/ERC20/CappedToken.sol
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
|
import "./MintableToken.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Capped token
|
||||||
|
* @dev Mintable token with a token cap.
|
||||||
|
*/
|
||||||
|
contract CappedToken is MintableToken {
|
||||||
|
|
||||||
|
uint256 public cap;
|
||||||
|
|
||||||
|
function CappedToken(uint256 _cap) public {
|
||||||
|
require(_cap > 0);
|
||||||
|
cap = _cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Function to mint tokens
|
||||||
|
* @param _to The address that will receive the minted tokens.
|
||||||
|
* @param _amount The amount of tokens to mint.
|
||||||
|
* @return A boolean that indicates if the operation was successful.
|
||||||
|
*/
|
||||||
|
function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
|
||||||
|
require(totalSupply_.add(_amount) <= cap);
|
||||||
|
|
||||||
|
return super.mint(_to, _amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
16
contracts/token/ERC20/DetailedERC20.sol
Normal file
16
contracts/token/ERC20/DetailedERC20.sol
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./ERC20.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract DetailedERC20 is ERC20 {
|
||||||
|
string public name;
|
||||||
|
string public symbol;
|
||||||
|
uint8 public decimals;
|
||||||
|
|
||||||
|
function DetailedERC20(string _name, string _symbol, uint8 _decimals) public {
|
||||||
|
name = _name;
|
||||||
|
symbol = _symbol;
|
||||||
|
decimals = _decimals;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
contracts/token/ERC20/ERC20.sol
Normal file
15
contracts/token/ERC20/ERC20.sol
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./ERC20Basic.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title ERC20 interface
|
||||||
|
* @dev see https://github.com/ethereum/EIPs/issues/20
|
||||||
|
*/
|
||||||
|
contract ERC20 is ERC20Basic {
|
||||||
|
function allowance(address owner, address spender) public view returns (uint256);
|
||||||
|
function transferFrom(address from, address to, uint256 value) public returns (bool);
|
||||||
|
function approve(address spender, uint256 value) public returns (bool);
|
||||||
|
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||||
|
}
|
||||||
14
contracts/token/ERC20/ERC20Basic.sol
Normal file
14
contracts/token/ERC20/ERC20Basic.sol
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title ERC20Basic
|
||||||
|
* @dev Simpler version of ERC20 interface
|
||||||
|
* @dev see https://github.com/ethereum/EIPs/issues/179
|
||||||
|
*/
|
||||||
|
contract ERC20Basic {
|
||||||
|
function totalSupply() public view returns (uint256);
|
||||||
|
function balanceOf(address who) public view returns (uint256);
|
||||||
|
function transfer(address to, uint256 value) public returns (bool);
|
||||||
|
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||||
|
}
|
||||||
@ -1,9 +1,7 @@
|
|||||||
pragma solidity ^0.4.8;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
|
||||||
import './StandardToken.sol';
|
|
||||||
import '../ownership/Ownable.sol';
|
|
||||||
|
|
||||||
|
import "./StandardToken.sol";
|
||||||
|
import "../../ownership/Ownable.sol";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,30 +10,29 @@ import '../ownership/Ownable.sol';
|
|||||||
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
|
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
|
||||||
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
|
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
|
||||||
*/
|
*/
|
||||||
|
|
||||||
contract MintableToken is StandardToken, Ownable {
|
contract MintableToken is StandardToken, Ownable {
|
||||||
event Mint(address indexed to, uint value);
|
event Mint(address indexed to, uint256 amount);
|
||||||
event MintFinished();
|
event MintFinished();
|
||||||
|
|
||||||
bool public mintingFinished = false;
|
bool public mintingFinished = false;
|
||||||
uint public totalSupply = 0;
|
|
||||||
|
|
||||||
|
|
||||||
modifier canMint() {
|
modifier canMint() {
|
||||||
if(mintingFinished) throw;
|
require(!mintingFinished);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Function to mint tokens
|
* @dev Function to mint tokens
|
||||||
* @param _to The address that will recieve the minted tokens.
|
* @param _to The address that will receive the minted tokens.
|
||||||
* @param _amount The amount of tokens to mint.
|
* @param _amount The amount of tokens to mint.
|
||||||
* @return A boolean that indicates if the operation was successful.
|
* @return A boolean that indicates if the operation was successful.
|
||||||
*/
|
*/
|
||||||
function mint(address _to, uint _amount) onlyOwner canMint returns (bool) {
|
function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
|
||||||
totalSupply = totalSupply.add(_amount);
|
totalSupply_ = totalSupply_.add(_amount);
|
||||||
balances[_to] = balances[_to].add(_amount);
|
balances[_to] = balances[_to].add(_amount);
|
||||||
Mint(_to, _amount);
|
Mint(_to, _amount);
|
||||||
|
Transfer(address(0), _to, _amount);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +40,7 @@ contract MintableToken is StandardToken, Ownable {
|
|||||||
* @dev Function to stop minting new tokens.
|
* @dev Function to stop minting new tokens.
|
||||||
* @return True if the operation was successful.
|
* @return True if the operation was successful.
|
||||||
*/
|
*/
|
||||||
function finishMinting() onlyOwner returns (bool) {
|
function finishMinting() onlyOwner canMint public returns (bool) {
|
||||||
mintingFinished = true;
|
mintingFinished = true;
|
||||||
MintFinished();
|
MintFinished();
|
||||||
return true;
|
return true;
|
||||||
32
contracts/token/ERC20/PausableToken.sol
Normal file
32
contracts/token/ERC20/PausableToken.sol
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./StandardToken.sol";
|
||||||
|
import "../../lifecycle/Pausable.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Pausable token
|
||||||
|
* @dev StandardToken modified with pausable transfers.
|
||||||
|
**/
|
||||||
|
contract PausableToken is StandardToken, Pausable {
|
||||||
|
|
||||||
|
function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) {
|
||||||
|
return super.transfer(_to, _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) {
|
||||||
|
return super.transferFrom(_from, _to, _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) {
|
||||||
|
return super.approve(_spender, _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function increaseApproval(address _spender, uint _addedValue) public whenNotPaused returns (bool success) {
|
||||||
|
return super.increaseApproval(_spender, _addedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function decreaseApproval(address _spender, uint _subtractedValue) public whenNotPaused returns (bool success) {
|
||||||
|
return super.decreaseApproval(_spender, _subtractedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
contracts/token/ERC20/SafeERC20.sol
Normal file
25
contracts/token/ERC20/SafeERC20.sol
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./ERC20Basic.sol";
|
||||||
|
import "./ERC20.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title SafeERC20
|
||||||
|
* @dev Wrappers around ERC20 operations that throw on failure.
|
||||||
|
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
|
||||||
|
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
|
||||||
|
*/
|
||||||
|
library SafeERC20 {
|
||||||
|
function safeTransfer(ERC20Basic token, address to, uint256 value) internal {
|
||||||
|
assert(token.transfer(to, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
|
||||||
|
assert(token.transferFrom(from, to, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeApprove(ERC20 token, address spender, uint256 value) internal {
|
||||||
|
assert(token.approve(spender, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
100
contracts/token/ERC20/StandardToken.sol
Normal file
100
contracts/token/ERC20/StandardToken.sol
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./BasicToken.sol";
|
||||||
|
import "./ERC20.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Standard ERC20 token
|
||||||
|
*
|
||||||
|
* @dev Implementation of the basic standard token.
|
||||||
|
* @dev https://github.com/ethereum/EIPs/issues/20
|
||||||
|
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
|
||||||
|
*/
|
||||||
|
contract StandardToken is ERC20, BasicToken {
|
||||||
|
|
||||||
|
mapping (address => mapping (address => uint256)) internal allowed;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Transfer tokens from one address to another
|
||||||
|
* @param _from address The address which you want to send tokens from
|
||||||
|
* @param _to address The address which you want to transfer to
|
||||||
|
* @param _value uint256 the amount of tokens to be transferred
|
||||||
|
*/
|
||||||
|
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
|
||||||
|
require(_to != address(0));
|
||||||
|
require(_value <= balances[_from]);
|
||||||
|
require(_value <= allowed[_from][msg.sender]);
|
||||||
|
|
||||||
|
balances[_from] = balances[_from].sub(_value);
|
||||||
|
balances[_to] = balances[_to].add(_value);
|
||||||
|
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
|
||||||
|
Transfer(_from, _to, _value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
|
||||||
|
*
|
||||||
|
* Beware that changing an allowance with this method brings the risk that someone may use both the old
|
||||||
|
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
|
||||||
|
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
|
||||||
|
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
|
||||||
|
* @param _spender The address which will spend the funds.
|
||||||
|
* @param _value The amount of tokens to be spent.
|
||||||
|
*/
|
||||||
|
function approve(address _spender, uint256 _value) public returns (bool) {
|
||||||
|
allowed[msg.sender][_spender] = _value;
|
||||||
|
Approval(msg.sender, _spender, _value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Function to check the amount of tokens that an owner allowed to a spender.
|
||||||
|
* @param _owner address The address which owns the funds.
|
||||||
|
* @param _spender address The address which will spend the funds.
|
||||||
|
* @return A uint256 specifying the amount of tokens still available for the spender.
|
||||||
|
*/
|
||||||
|
function allowance(address _owner, address _spender) public view returns (uint256) {
|
||||||
|
return allowed[_owner][_spender];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Increase the amount of tokens that an owner allowed to a spender.
|
||||||
|
*
|
||||||
|
* approve should be called when allowed[_spender] == 0. To increment
|
||||||
|
* allowed value is better to use this function to avoid 2 calls (and wait until
|
||||||
|
* the first transaction is mined)
|
||||||
|
* From MonolithDAO Token.sol
|
||||||
|
* @param _spender The address which will spend the funds.
|
||||||
|
* @param _addedValue The amount of tokens to increase the allowance by.
|
||||||
|
*/
|
||||||
|
function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
|
||||||
|
allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
|
||||||
|
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Decrease the amount of tokens that an owner allowed to a spender.
|
||||||
|
*
|
||||||
|
* approve should be called when allowed[_spender] == 0. To decrement
|
||||||
|
* allowed value is better to use this function to avoid 2 calls (and wait until
|
||||||
|
* the first transaction is mined)
|
||||||
|
* From MonolithDAO Token.sol
|
||||||
|
* @param _spender The address which will spend the funds.
|
||||||
|
* @param _subtractedValue The amount of tokens to decrease the allowance by.
|
||||||
|
*/
|
||||||
|
function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
|
||||||
|
uint oldValue = allowed[msg.sender][_spender];
|
||||||
|
if (_subtractedValue > oldValue) {
|
||||||
|
allowed[msg.sender][_spender] = 0;
|
||||||
|
} else {
|
||||||
|
allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
|
||||||
|
}
|
||||||
|
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
41
contracts/token/ERC20/TokenTimelock.sol
Normal file
41
contracts/token/ERC20/TokenTimelock.sol
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./SafeERC20.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title TokenTimelock
|
||||||
|
* @dev TokenTimelock is a token holder contract that will allow a
|
||||||
|
* beneficiary to extract the tokens after a given release time
|
||||||
|
*/
|
||||||
|
contract TokenTimelock {
|
||||||
|
using SafeERC20 for ERC20Basic;
|
||||||
|
|
||||||
|
// ERC20 basic token contract being held
|
||||||
|
ERC20Basic public token;
|
||||||
|
|
||||||
|
// beneficiary of tokens after they are released
|
||||||
|
address public beneficiary;
|
||||||
|
|
||||||
|
// timestamp when token release is enabled
|
||||||
|
uint256 public releaseTime;
|
||||||
|
|
||||||
|
function TokenTimelock(ERC20Basic _token, address _beneficiary, uint256 _releaseTime) public {
|
||||||
|
require(_releaseTime > now);
|
||||||
|
token = _token;
|
||||||
|
beneficiary = _beneficiary;
|
||||||
|
releaseTime = _releaseTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Transfers tokens held by timelock to beneficiary.
|
||||||
|
*/
|
||||||
|
function release() public {
|
||||||
|
require(now >= releaseTime);
|
||||||
|
|
||||||
|
uint256 amount = token.balanceOf(this);
|
||||||
|
require(amount > 0);
|
||||||
|
|
||||||
|
token.safeTransfer(beneficiary, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
115
contracts/token/ERC20/TokenVesting.sol
Normal file
115
contracts/token/ERC20/TokenVesting.sol
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./ERC20Basic.sol";
|
||||||
|
import "./SafeERC20.sol";
|
||||||
|
import "../../ownership/Ownable.sol";
|
||||||
|
import "../../math/SafeMath.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title TokenVesting
|
||||||
|
* @dev A token holder contract that can release its token balance gradually like a
|
||||||
|
* typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
|
||||||
|
* owner.
|
||||||
|
*/
|
||||||
|
contract TokenVesting is Ownable {
|
||||||
|
using SafeMath for uint256;
|
||||||
|
using SafeERC20 for ERC20Basic;
|
||||||
|
|
||||||
|
event Released(uint256 amount);
|
||||||
|
event Revoked();
|
||||||
|
|
||||||
|
// beneficiary of tokens after they are released
|
||||||
|
address public beneficiary;
|
||||||
|
|
||||||
|
uint256 public cliff;
|
||||||
|
uint256 public start;
|
||||||
|
uint256 public duration;
|
||||||
|
|
||||||
|
bool public revocable;
|
||||||
|
|
||||||
|
mapping (address => uint256) public released;
|
||||||
|
mapping (address => bool) public revoked;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Creates a vesting contract that vests its balance of any ERC20 token to the
|
||||||
|
* _beneficiary, gradually in a linear fashion until _start + _duration. By then all
|
||||||
|
* of the balance will have vested.
|
||||||
|
* @param _beneficiary address of the beneficiary to whom vested tokens are transferred
|
||||||
|
* @param _cliff duration in seconds of the cliff in which tokens will begin to vest
|
||||||
|
* @param _duration duration in seconds of the period in which the tokens will vest
|
||||||
|
* @param _revocable whether the vesting is revocable or not
|
||||||
|
*/
|
||||||
|
function TokenVesting(address _beneficiary, uint256 _start, uint256 _cliff, uint256 _duration, bool _revocable) public {
|
||||||
|
require(_beneficiary != address(0));
|
||||||
|
require(_cliff <= _duration);
|
||||||
|
|
||||||
|
beneficiary = _beneficiary;
|
||||||
|
revocable = _revocable;
|
||||||
|
duration = _duration;
|
||||||
|
cliff = _start.add(_cliff);
|
||||||
|
start = _start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Transfers vested tokens to beneficiary.
|
||||||
|
* @param token ERC20 token which is being vested
|
||||||
|
*/
|
||||||
|
function release(ERC20Basic token) public {
|
||||||
|
uint256 unreleased = releasableAmount(token);
|
||||||
|
|
||||||
|
require(unreleased > 0);
|
||||||
|
|
||||||
|
released[token] = released[token].add(unreleased);
|
||||||
|
|
||||||
|
token.safeTransfer(beneficiary, unreleased);
|
||||||
|
|
||||||
|
Released(unreleased);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Allows the owner to revoke the vesting. Tokens already vested
|
||||||
|
* remain in the contract, the rest are returned to the owner.
|
||||||
|
* @param token ERC20 token which is being vested
|
||||||
|
*/
|
||||||
|
function revoke(ERC20Basic token) public onlyOwner {
|
||||||
|
require(revocable);
|
||||||
|
require(!revoked[token]);
|
||||||
|
|
||||||
|
uint256 balance = token.balanceOf(this);
|
||||||
|
|
||||||
|
uint256 unreleased = releasableAmount(token);
|
||||||
|
uint256 refund = balance.sub(unreleased);
|
||||||
|
|
||||||
|
revoked[token] = true;
|
||||||
|
|
||||||
|
token.safeTransfer(owner, refund);
|
||||||
|
|
||||||
|
Revoked();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Calculates the amount that has already vested but hasn't been released yet.
|
||||||
|
* @param token ERC20 token which is being vested
|
||||||
|
*/
|
||||||
|
function releasableAmount(ERC20Basic token) public view returns (uint256) {
|
||||||
|
return vestedAmount(token).sub(released[token]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Calculates the amount that has already vested.
|
||||||
|
* @param token ERC20 token which is being vested
|
||||||
|
*/
|
||||||
|
function vestedAmount(ERC20Basic token) public view returns (uint256) {
|
||||||
|
uint256 currentBalance = token.balanceOf(this);
|
||||||
|
uint256 totalBalance = currentBalance.add(released[token]);
|
||||||
|
|
||||||
|
if (now < cliff) {
|
||||||
|
return 0;
|
||||||
|
} else if (now >= start.add(duration) || revoked[token]) {
|
||||||
|
return totalBalance;
|
||||||
|
} else {
|
||||||
|
return totalBalance.mul(now.sub(start)).div(duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @title ERC20Basic
|
|
||||||
* @dev Simpler version of ERC20 interface
|
|
||||||
* @dev see https://github.com/ethereum/EIPs/issues/20
|
|
||||||
*/
|
|
||||||
contract ERC20Basic {
|
|
||||||
uint public totalSupply;
|
|
||||||
function balanceOf(address who) constant returns (uint);
|
|
||||||
function transfer(address to, uint value);
|
|
||||||
event Transfer(address indexed from, address indexed to, uint value);
|
|
||||||
}
|
|
||||||
16
contracts/token/ERC721/ERC721.sol
Normal file
16
contracts/token/ERC721/ERC721.sol
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title ERC721 interface
|
||||||
|
* @dev see https://github.com/ethereum/eips/issues/721
|
||||||
|
*/
|
||||||
|
contract ERC721 {
|
||||||
|
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
|
||||||
|
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
|
||||||
|
|
||||||
|
function balanceOf(address _owner) public view returns (uint256 _balance);
|
||||||
|
function ownerOf(uint256 _tokenId) public view returns (address _owner);
|
||||||
|
function transfer(address _to, uint256 _tokenId) public;
|
||||||
|
function approve(address _to, uint256 _tokenId) public;
|
||||||
|
function takeOwnership(uint256 _tokenId) public;
|
||||||
|
}
|
||||||
214
contracts/token/ERC721/ERC721Token.sol
Normal file
214
contracts/token/ERC721/ERC721Token.sol
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./ERC721.sol";
|
||||||
|
import "../../math/SafeMath.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title ERC721Token
|
||||||
|
* Generic implementation for the required functionality of the ERC721 standard
|
||||||
|
*/
|
||||||
|
contract ERC721Token is ERC721 {
|
||||||
|
using SafeMath for uint256;
|
||||||
|
|
||||||
|
// Total amount of tokens
|
||||||
|
uint256 private totalTokens;
|
||||||
|
|
||||||
|
// Mapping from token ID to owner
|
||||||
|
mapping (uint256 => address) private tokenOwner;
|
||||||
|
|
||||||
|
// Mapping from token ID to approved address
|
||||||
|
mapping (uint256 => address) private tokenApprovals;
|
||||||
|
|
||||||
|
// Mapping from owner to list of owned token IDs
|
||||||
|
mapping (address => uint256[]) private ownedTokens;
|
||||||
|
|
||||||
|
// Mapping from token ID to index of the owner tokens list
|
||||||
|
mapping(uint256 => uint256) private ownedTokensIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Guarantees msg.sender is owner of the given token
|
||||||
|
* @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender
|
||||||
|
*/
|
||||||
|
modifier onlyOwnerOf(uint256 _tokenId) {
|
||||||
|
require(ownerOf(_tokenId) == msg.sender);
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Gets the total amount of tokens stored by the contract
|
||||||
|
* @return uint256 representing the total amount of tokens
|
||||||
|
*/
|
||||||
|
function totalSupply() public view returns (uint256) {
|
||||||
|
return totalTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Gets the balance of the specified address
|
||||||
|
* @param _owner address to query the balance of
|
||||||
|
* @return uint256 representing the amount owned by the passed address
|
||||||
|
*/
|
||||||
|
function balanceOf(address _owner) public view returns (uint256) {
|
||||||
|
return ownedTokens[_owner].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Gets the list of tokens owned by a given address
|
||||||
|
* @param _owner address to query the tokens of
|
||||||
|
* @return uint256[] representing the list of tokens owned by the passed address
|
||||||
|
*/
|
||||||
|
function tokensOf(address _owner) public view returns (uint256[]) {
|
||||||
|
return ownedTokens[_owner];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Gets the owner of the specified token ID
|
||||||
|
* @param _tokenId uint256 ID of the token to query the owner of
|
||||||
|
* @return owner address currently marked as the owner of the given token ID
|
||||||
|
*/
|
||||||
|
function ownerOf(uint256 _tokenId) public view returns (address) {
|
||||||
|
address owner = tokenOwner[_tokenId];
|
||||||
|
require(owner != address(0));
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Gets the approved address to take ownership of a given token ID
|
||||||
|
* @param _tokenId uint256 ID of the token to query the approval of
|
||||||
|
* @return address currently approved to take ownership of the given token ID
|
||||||
|
*/
|
||||||
|
function approvedFor(uint256 _tokenId) public view returns (address) {
|
||||||
|
return tokenApprovals[_tokenId];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Transfers the ownership of a given token ID to another address
|
||||||
|
* @param _to address to receive the ownership of the given token ID
|
||||||
|
* @param _tokenId uint256 ID of the token to be transferred
|
||||||
|
*/
|
||||||
|
function transfer(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
|
||||||
|
clearApprovalAndTransfer(msg.sender, _to, _tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Approves another address to claim for the ownership of the given token ID
|
||||||
|
* @param _to address to be approved for the given token ID
|
||||||
|
* @param _tokenId uint256 ID of the token to be approved
|
||||||
|
*/
|
||||||
|
function approve(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
|
||||||
|
address owner = ownerOf(_tokenId);
|
||||||
|
require(_to != owner);
|
||||||
|
if (approvedFor(_tokenId) != 0 || _to != 0) {
|
||||||
|
tokenApprovals[_tokenId] = _to;
|
||||||
|
Approval(owner, _to, _tokenId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Claims the ownership of a given token ID
|
||||||
|
* @param _tokenId uint256 ID of the token being claimed by the msg.sender
|
||||||
|
*/
|
||||||
|
function takeOwnership(uint256 _tokenId) public {
|
||||||
|
require(isApprovedFor(msg.sender, _tokenId));
|
||||||
|
clearApprovalAndTransfer(ownerOf(_tokenId), msg.sender, _tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Mint token function
|
||||||
|
* @param _to The address that will own the minted token
|
||||||
|
* @param _tokenId uint256 ID of the token to be minted by the msg.sender
|
||||||
|
*/
|
||||||
|
function _mint(address _to, uint256 _tokenId) internal {
|
||||||
|
require(_to != address(0));
|
||||||
|
addToken(_to, _tokenId);
|
||||||
|
Transfer(0x0, _to, _tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Burns a specific token
|
||||||
|
* @param _tokenId uint256 ID of the token being burned by the msg.sender
|
||||||
|
*/
|
||||||
|
function _burn(uint256 _tokenId) onlyOwnerOf(_tokenId) internal {
|
||||||
|
if (approvedFor(_tokenId) != 0) {
|
||||||
|
clearApproval(msg.sender, _tokenId);
|
||||||
|
}
|
||||||
|
removeToken(msg.sender, _tokenId);
|
||||||
|
Transfer(msg.sender, 0x0, _tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Tells whether the msg.sender is approved for the given token ID or not
|
||||||
|
* This function is not private so it can be extended in further implementations like the operatable ERC721
|
||||||
|
* @param _owner address of the owner to query the approval of
|
||||||
|
* @param _tokenId uint256 ID of the token to query the approval of
|
||||||
|
* @return bool whether the msg.sender is approved for the given token ID or not
|
||||||
|
*/
|
||||||
|
function isApprovedFor(address _owner, uint256 _tokenId) internal view returns (bool) {
|
||||||
|
return approvedFor(_tokenId) == _owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Internal function to clear current approval and transfer the ownership of a given token ID
|
||||||
|
* @param _from address which you want to send tokens from
|
||||||
|
* @param _to address which you want to transfer the token to
|
||||||
|
* @param _tokenId uint256 ID of the token to be transferred
|
||||||
|
*/
|
||||||
|
function clearApprovalAndTransfer(address _from, address _to, uint256 _tokenId) internal {
|
||||||
|
require(_to != address(0));
|
||||||
|
require(_to != ownerOf(_tokenId));
|
||||||
|
require(ownerOf(_tokenId) == _from);
|
||||||
|
|
||||||
|
clearApproval(_from, _tokenId);
|
||||||
|
removeToken(_from, _tokenId);
|
||||||
|
addToken(_to, _tokenId);
|
||||||
|
Transfer(_from, _to, _tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Internal function to clear current approval of a given token ID
|
||||||
|
* @param _tokenId uint256 ID of the token to be transferred
|
||||||
|
*/
|
||||||
|
function clearApproval(address _owner, uint256 _tokenId) private {
|
||||||
|
require(ownerOf(_tokenId) == _owner);
|
||||||
|
tokenApprovals[_tokenId] = 0;
|
||||||
|
Approval(_owner, 0, _tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Internal function to add a token ID to the list of a given address
|
||||||
|
* @param _to address representing the new owner of the given token ID
|
||||||
|
* @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
|
||||||
|
*/
|
||||||
|
function addToken(address _to, uint256 _tokenId) private {
|
||||||
|
require(tokenOwner[_tokenId] == address(0));
|
||||||
|
tokenOwner[_tokenId] = _to;
|
||||||
|
uint256 length = balanceOf(_to);
|
||||||
|
ownedTokens[_to].push(_tokenId);
|
||||||
|
ownedTokensIndex[_tokenId] = length;
|
||||||
|
totalTokens = totalTokens.add(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Internal function to remove a token ID from the list of a given address
|
||||||
|
* @param _from address representing the previous owner of the given token ID
|
||||||
|
* @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
|
||||||
|
*/
|
||||||
|
function removeToken(address _from, uint256 _tokenId) private {
|
||||||
|
require(ownerOf(_tokenId) == _from);
|
||||||
|
|
||||||
|
uint256 tokenIndex = ownedTokensIndex[_tokenId];
|
||||||
|
uint256 lastTokenIndex = balanceOf(_from).sub(1);
|
||||||
|
uint256 lastToken = ownedTokens[_from][lastTokenIndex];
|
||||||
|
|
||||||
|
tokenOwner[_tokenId] = 0;
|
||||||
|
ownedTokens[_from][tokenIndex] = lastToken;
|
||||||
|
ownedTokens[_from][lastTokenIndex] = 0;
|
||||||
|
// Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to
|
||||||
|
// be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping
|
||||||
|
// the lastToken to the first position, and then dropping the element placed in the last position of the list
|
||||||
|
|
||||||
|
ownedTokens[_from].length--;
|
||||||
|
ownedTokensIndex[_tokenId] = 0;
|
||||||
|
ownedTokensIndex[lastToken] = tokenIndex;
|
||||||
|
totalTokens = totalTokens.sub(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
contracts/token/ERC827/ERC827.sol
Normal file
20
contracts/token/ERC827/ERC827.sol
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
pragma solidity ^0.4.13;
|
||||||
|
|
||||||
|
|
||||||
|
import "../ERC20/ERC20.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@title ERC827 interface, an extension of ERC20 token standard
|
||||||
|
|
||||||
|
Interface of a ERC827 token, following the ERC20 standard with extra
|
||||||
|
methods to transfer value and data and execute calls in transfers and
|
||||||
|
approvals.
|
||||||
|
*/
|
||||||
|
contract ERC827 is ERC20 {
|
||||||
|
|
||||||
|
function approve( address _spender, uint256 _value, bytes _data ) public returns (bool);
|
||||||
|
function transfer( address _to, uint256 _value, bytes _data ) public returns (bool);
|
||||||
|
function transferFrom( address _from, address _to, uint256 _value, bytes _data ) public returns (bool);
|
||||||
|
|
||||||
|
}
|
||||||
126
contracts/token/ERC827/ERC827Token.sol
Normal file
126
contracts/token/ERC827/ERC827Token.sol
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
pragma solidity ^0.4.13;
|
||||||
|
|
||||||
|
import "./ERC827.sol";
|
||||||
|
import "../ERC20/StandardToken.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
@title ERC827, an extension of ERC20 token standard
|
||||||
|
|
||||||
|
Implementation the ERC827, following the ERC20 standard with extra
|
||||||
|
methods to transfer value and data and execute calls in transfers and
|
||||||
|
approvals.
|
||||||
|
Uses OpenZeppelin StandardToken.
|
||||||
|
*/
|
||||||
|
contract ERC827Token is ERC827, StandardToken {
|
||||||
|
|
||||||
|
/**
|
||||||
|
@dev Addition to ERC20 token methods. It allows to
|
||||||
|
approve the transfer of value and execute a call with the sent data.
|
||||||
|
|
||||||
|
Beware that changing an allowance with this method brings the risk that
|
||||||
|
someone may use both the old and the new allowance by unfortunate
|
||||||
|
transaction ordering. One possible solution to mitigate this race condition
|
||||||
|
is to first reduce the spender's allowance to 0 and set the desired value
|
||||||
|
afterwards:
|
||||||
|
https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
|
||||||
|
|
||||||
|
@param _spender The address that will spend the funds.
|
||||||
|
@param _value The amount of tokens to be spent.
|
||||||
|
@param _data ABI-encoded contract call to call `_to` address.
|
||||||
|
|
||||||
|
@return true if the call function was executed successfully
|
||||||
|
*/
|
||||||
|
function approve(address _spender, uint256 _value, bytes _data) public returns (bool) {
|
||||||
|
require(_spender != address(this));
|
||||||
|
|
||||||
|
super.approve(_spender, _value);
|
||||||
|
|
||||||
|
require(_spender.call(_data));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@dev Addition to ERC20 token methods. Transfer tokens to a specified
|
||||||
|
address and execute a call with the sent data on the same transaction
|
||||||
|
|
||||||
|
@param _to address The address which you want to transfer to
|
||||||
|
@param _value uint256 the amout of tokens to be transfered
|
||||||
|
@param _data ABI-encoded contract call to call `_to` address.
|
||||||
|
|
||||||
|
@return true if the call function was executed successfully
|
||||||
|
*/
|
||||||
|
function transfer(address _to, uint256 _value, bytes _data) public returns (bool) {
|
||||||
|
require(_to != address(this));
|
||||||
|
|
||||||
|
super.transfer(_to, _value);
|
||||||
|
|
||||||
|
require(_to.call(_data));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@dev Addition to ERC20 token methods. Transfer tokens from one address to
|
||||||
|
another and make a contract call on the same transaction
|
||||||
|
|
||||||
|
@param _from The address which you want to send tokens from
|
||||||
|
@param _to The address which you want to transfer to
|
||||||
|
@param _value The amout of tokens to be transferred
|
||||||
|
@param _data ABI-encoded contract call to call `_to` address.
|
||||||
|
|
||||||
|
@return true if the call function was executed successfully
|
||||||
|
*/
|
||||||
|
function transferFrom(address _from, address _to, uint256 _value, bytes _data) public returns (bool) {
|
||||||
|
require(_to != address(this));
|
||||||
|
|
||||||
|
super.transferFrom(_from, _to, _value);
|
||||||
|
|
||||||
|
require(_to.call(_data));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Addition to StandardToken methods. Increase the amount of tokens that
|
||||||
|
* an owner allowed to a spender and execute a call with the sent data.
|
||||||
|
*
|
||||||
|
* approve should be called when allowed[_spender] == 0. To increment
|
||||||
|
* allowed value is better to use this function to avoid 2 calls (and wait until
|
||||||
|
* the first transaction is mined)
|
||||||
|
* From MonolithDAO Token.sol
|
||||||
|
* @param _spender The address which will spend the funds.
|
||||||
|
* @param _addedValue The amount of tokens to increase the allowance by.
|
||||||
|
* @param _data ABI-encoded contract call to call `_spender` address.
|
||||||
|
*/
|
||||||
|
function increaseApproval(address _spender, uint _addedValue, bytes _data) public returns (bool) {
|
||||||
|
require(_spender != address(this));
|
||||||
|
|
||||||
|
super.increaseApproval(_spender, _addedValue);
|
||||||
|
|
||||||
|
require(_spender.call(_data));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Addition to StandardToken methods. Decrease the amount of tokens that
|
||||||
|
* an owner allowed to a spender and execute a call with the sent data.
|
||||||
|
*
|
||||||
|
* approve should be called when allowed[_spender] == 0. To decrement
|
||||||
|
* allowed value is better to use this function to avoid 2 calls (and wait until
|
||||||
|
* the first transaction is mined)
|
||||||
|
* From MonolithDAO Token.sol
|
||||||
|
* @param _spender The address which will spend the funds.
|
||||||
|
* @param _subtractedValue The amount of tokens to decrease the allowance by.
|
||||||
|
* @param _data ABI-encoded contract call to call `_spender` address.
|
||||||
|
*/
|
||||||
|
function decreaseApproval(address _spender, uint _subtractedValue, bytes _data) public returns (bool) {
|
||||||
|
require(_spender != address(this));
|
||||||
|
|
||||||
|
super.decreaseApproval(_spender, _subtractedValue);
|
||||||
|
|
||||||
|
require(_spender.call(_data));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,57 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
import "./ERC20.sol";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @title LimitedTransferToken
|
|
||||||
* @dev LimitedTransferToken defines the generic interface and the implementation to limit token
|
|
||||||
* transferability for different events. It is intended to be used as a base class for other token
|
|
||||||
* contracts.
|
|
||||||
* LimitedTransferToken has been designed to allow for different limiting factors,
|
|
||||||
* this can be achieved by recursively calling super.transferableTokens() until the base class is
|
|
||||||
* hit. For example:
|
|
||||||
* function transferableTokens(address holder, uint64 time) constant public returns (uint256) {
|
|
||||||
* return min256(unlockedTokens, super.transferableTokens(holder, time));
|
|
||||||
* }
|
|
||||||
* A working example is VestedToken.sol:
|
|
||||||
* https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/VestedToken.sol
|
|
||||||
*/
|
|
||||||
|
|
||||||
contract LimitedTransferToken is ERC20 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Checks whether it can transfer or otherwise throws.
|
|
||||||
*/
|
|
||||||
modifier canTransfer(address _sender, uint _value) {
|
|
||||||
if (_value > transferableTokens(_sender, uint64(now))) throw;
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Checks modifier and allows transfer if tokens are not locked.
|
|
||||||
* @param _to The address that will recieve the tokens.
|
|
||||||
* @param _value The amount of tokens to be transferred.
|
|
||||||
*/
|
|
||||||
function transfer(address _to, uint _value) canTransfer(msg.sender, _value) {
|
|
||||||
return super.transfer(_to, _value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Checks modifier and allows transfer if tokens are not locked.
|
|
||||||
* @param _from The address that will send the tokens.
|
|
||||||
* @param _to The address that will recieve the tokens.
|
|
||||||
* @param _value The amount of tokens to be transferred.
|
|
||||||
*/
|
|
||||||
function transferFrom(address _from, address _to, uint _value) canTransfer(_from, _value) {
|
|
||||||
return super.transferFrom(_from, _to, _value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Default transferable tokens function returns all tokens for a holder (no limit).
|
|
||||||
* @dev Overwriting transferableTokens(address holder, uint64 time) is the way to provide the
|
|
||||||
* specific logic for limiting token transferability for a holder over time.
|
|
||||||
*/
|
|
||||||
function transferableTokens(address holder, uint64 time) constant public returns (uint256) {
|
|
||||||
return balanceOf(holder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
import './StandardToken.sol';
|
|
||||||
import '../lifecycle/Pausable.sol';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pausable token
|
|
||||||
*
|
|
||||||
* Simple ERC20 Token example, with pausable token creation
|
|
||||||
* Issue:
|
|
||||||
* https://github.com/OpenZeppelin/zeppelin-solidity/issues/194
|
|
||||||
* Based on code by BCAPtoken:
|
|
||||||
* https://github.com/BCAPtoken/BCAPToken/blob/5cb5e76338cc47343ba9268663a915337c8b268e/sol/BCAPToken.sol#L27
|
|
||||||
**/
|
|
||||||
|
|
||||||
contract PausableToken is Pausable, StandardToken {
|
|
||||||
|
|
||||||
function transfer(address _to, uint _value) whenNotPaused {
|
|
||||||
return super.transfer(_to, _value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function transferFrom(address _from, address _to, uint _value) whenNotPaused {
|
|
||||||
return super.transferFrom(_from, _to, _value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
pragma solidity ^0.4.8;
|
|
||||||
|
|
||||||
|
|
||||||
import "./StandardToken.sol";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @title SimpleToken
|
|
||||||
* @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
|
|
||||||
* Note they can later distribute these tokens as they wish using `transfer` and other
|
|
||||||
* `StandardToken` functions.
|
|
||||||
*/
|
|
||||||
contract SimpleToken is StandardToken {
|
|
||||||
|
|
||||||
string public name = "SimpleToken";
|
|
||||||
string public symbol = "SIM";
|
|
||||||
uint public decimals = 18;
|
|
||||||
uint public INITIAL_SUPPLY = 10000;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Contructor that gives msg.sender all of existing tokens.
|
|
||||||
*/
|
|
||||||
function SimpleToken() {
|
|
||||||
totalSupply = INITIAL_SUPPLY;
|
|
||||||
balances[msg.sender] = INITIAL_SUPPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user