Initial import

This commit is contained in:
Richard Ramos 2018-10-03 08:45:56 -04:00
parent f4052ec339
commit 11f8cdb625
34 changed files with 14401 additions and 1 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.embark/
node_modules/
dist/
config/production/password
config/livenet/password
codes.txt
orbitdb/

View File

@ -1 +1,21 @@
# hackathon-registration-dapp
# hackathon-registration-dapp
TODO - Add docs
Installation:
```
git clone https://github.com/status-im/hackathon-registration-dapp.git
cd hackathon-registration-dapp
npm install
```
To generate the codes, `node server/codegen.js` will generate a `codes.txt` file, and the proof and merkle root used for the contract
```
embark run
```

0
app/css/.gitkeep Normal file
View File

0
app/images/.gitkeep Normal file
View File

11
app/index.html Normal file
View File

@ -0,0 +1,11 @@
<html>
<head>
<title>Embark</title>
<link rel="stylesheet" href="css/app.css">
<script src="js/app.js"></script>
</head>
<body>
<h3>Welcome to Embark!</h3>
<p>See the <a href="http://embark.readthedocs.io/en/latest/index.html" target="_blank">Embark's documentation</a> to see what you can do with Embark!</p>
</body>
</html>

0
app/js/.gitkeep Normal file
View File

6
app/js/index.js Normal file
View File

@ -0,0 +1,6 @@
import EmbarkJS from 'Embark/EmbarkJS';
// import your contracts
// e.g if you have a contract named SimpleStorage:
//import SimpleStorage from 'Embark/contracts/SimpleStorage';

506
app/js/merkle.js Normal file
View File

@ -0,0 +1,506 @@
module.exports = {
merkleRoot: '0x4c32c53daab7a7f956875136420801c9f1bdebf783cdeb6aefbe8412abe57b2c',
elements: [
'0x08a658dc0162837ceca8794bb6088ffb2037ef8929fbeedb8b2f985da1e5cf82',
'0x4453efc5a9d41c30e6e84d7892c2025e36e035148587c239d0c42bc443c78ada',
'0x7750a850dea3cefb380a3837a21795373c298828f5e54078f6af2fad1966d092',
'0x2f6a593a14c740400eca6392bab688017067bf750c04fb897e9b918f9d9671fb',
'0x0671d5775de596f54aeb62051422bc40382ffebf1e7eecfe90a3b0cb67c72a49',
'0x02637a7956f583223c57ebfcfd69f310a6c10502e7f7309743659fb20495698e',
'0x47aa19ac1d8d5a451827145c60650c4f9261bb0e1309a326e62e1c9d33c62c37',
'0x859c0a72182752a3da765a563bf005ea0cd8de7b3301ef4d8caf8f9fd3262e1e',
'0x65cc77aec115bdd5711551422a7fdf640d5ead930b3a98563741bab5bbd41177',
'0xeea8648d5671db998aab20f0fae1d5272940ad07e4f713ce622582c2df2a0d04',
'0x33e33727973e5715855fbff502c8e66e190677bc70dd74bcc723acadd64289a7',
'0xad7e8ee1331c49e68aaa92d3b73a33ea2cef9a17d1c2c3f527bcfbfeeddfc150',
'0x0d0d4d88ac07403c2ae42198aaa468a8147114ed8beef5ea0807e611c154c4b9',
'0xdd6eee47fea657bda2d69e22fe5234b7b8e5ef811f5319d649af020b134d4503',
'0x6f98862626ee0326543657f0cf92b3e4cbd5b3ce5cc3a28e453e76f89f6983c8',
'0xdc532b54bd075cfc5999b6d8efc200d71d324216acebabe406ba2412d139b324',
'0x2690eb068466223f0466f810d5a238c98c03e080f37bd596e83d4948cc0fc585',
'0x9330d023d36f7b3eebc347334ccaa1a376c82be3a6cab6e2289a967401132fbb',
'0xf845fed7149d6d796d7078236c07c78861cd662cf911ccc97574d0c4de8d9656',
'0x1a1df19ceddfb096a90e70c8b169584147b88ac8a153209fbcc7e84eb93a07ac',
'0x21fa3171d1c8d8cbb2b1968bcc1f865af8239a062dc9a145f2c6fe0754f90865',
'0xae2c3e657c7c21eab99353898cf40121a11f4f2db973003939ea3eaad0093a2c',
'0xe009bc65e191af656e79d82afe75675e0e46e433a7c9ce23e21ad9dd349837f0',
'0x30d01f8a0bb37766cfa21b8a72778a8aff14b007e257452f12b0496a0b2fb1bb',
'0xf754b2513c740eed9260575edd9627a049203d83750031a3a898552bb11897b1',
'0xdfbc1bff2d7765049658953787dd355d93aef8330d5c158ad26c6b9dfd8877c7',
'0x2a58afd0be00dace6bc8bdc9d14d8117c35e57869647d661f9c052fc44d5a1af',
'0x96918760d48af334c9e454b0009718cbc288ebb1846d1ae36773d7ffb708f4a0',
'0x3ce161c217fd91046ef6fc67522c255bb9c1d66e6c7998f7b8f20542e45b4de0',
'0x606b2f2f832ed3a22a5e291db0f36ad7c9d3d1fb4212d86fa5e632832b9fa924',
'0xff04fa10743b3a60b89677db85bd68d109582bca1bf0733f6f529dcb534604e7',
'0xea73058a6ceaa1f1a2737f8e465867a5c8d3a19b3650ed36beac566f17daa7b3',
'0xf6143c9c8f34962a67835cf391e60cf6fb4666c14d4821198630cdcdde0d1923',
'0x051a29d48f8d657589a968d9dfca8217868df2f7dca5e652f18faefa6280ec87',
'0x3e784c984d8b19120e2a034b2b9fb80b937cf5d316f77193a86677bc18b07c6c',
'0x9b03e2aac1cc8ab5a5602ca20e82f9d8e3ab186d12a5bc095d12b6d90c3bef3e',
'0x7bf90ab1f5770ebad84c0943d0d864ebb129a01a4fe6e656ddf761286f5f86c0',
'0xb816b0105e5379bf91429879a53f036cdc0e7f63e5da7b08e3ba81f8cfa9c9d8',
'0x8caa7983e426f2c4b30625ab6e40247b4a98feb31703d652448bf712f5acb919',
'0xb6e9b0d3439efc9ee2a8b3a95487f238f3cd7f6b7689000a59264f5183399f27',
'0x2f8a5880b22ebc8a00636a487b95b4200237fc34edc8c463c5d29278368b9cac',
'0x00cd2cf29aa003d6faf36d827791a131ebfce353df1efbddb643732a49e50b02',
'0x23a8740248fdf6414c06ae88172463cd8953be7d8dd3e18df1997b55ab4ef156',
'0x24124dddba18520ef1e99848bf0e73d2aa51440ead69791358dfba36f77a6912',
'0x0ec5eb638d5b9d12df3495cadae2e7bc90c22fc6e8f24dadc65c102a255c50d0',
'0xe249e3175c797b0bda524e748218d1715f08232d58a0ece6fb42c966df8a1b25',
'0x8212b24626eefa8b516fb696f083319938c23891072d610464f3e3c60e798700',
'0xa7e8deabc204b0a51635dbadb659da5062b8c0bb1c4ed5c4702b3b765072ba56',
'0x71b1449092889d2c2373b9cbfa8437eb4b4af1dc6278e948369ce2af2c97a14f',
'0xc3c52e7a96df33035d0f5cc35279962a4d2c3c93f83637b6aa9aa377bf63c836',
'0xbb0ba7f3ceb7b36612daa9858f6ab3eeec8f74556ab6899ae88798cf99b1cbe5',
'0xdf3feef7c758184d8b5d4330f20989dfd1f087aa7e899bc0380e82aaf979dc66',
'0xff62e7e6e6d4b7702ef4fd4cb3cb020f413aaa5cfccaeddd0e709ac4f2b0211c',
'0x25cf00966b72bf410cc1a68cf804f6ddf21ee3f02ea505d90f0109e1f0bee200',
'0xe0ba69274fd7a7bbaddbcdfba7bc6cb213952eefb0c49b26b8e41e9056e69eb5',
'0x9fd14c893151f82c55000ef82f7d8bdfad4b1bacda9176ed115e7e6ac343c383',
'0x8a0df59561579d3ce088ce54b15eac619e7e30aa0b41cd38642c2341eeebf11a',
'0x28658a28a3c7dd33fee782daab68d07de53c304479623105e44dae82d199126b',
'0x458d3a487bb8a0bcfab5df754c51e0074ca57d727958c559274e1ff963ea9b55',
'0xc0b06af103b47dc0a22e9f06b92bc03677a5271b654181706fb6336c80fd8c16',
'0x4d8029ac9f2b3272da55de6a3b4789a445b9e6c70ec981085532240f83eb96bc',
'0x0c3771af2cab7f6b99f8be309416418149660b85e52b833ba257c4232f07f409',
'0xd7c8df1de6b07d51432b47910d16978b7023f2ab86e28597aaff57963e64810e',
'0x56edc597e7ce21a9a304683f05b8c92ff43d46f2f94b684cc10adfa937975834',
'0x0a1537ddb1988fb648ebb1720ef7dd444c9c3aa3858c19178155d18e71935592',
'0x69f6ea94df2ec32ffb7124cc9f455255261816dd6220fec1e06cd7af22f3efd8',
'0xc1b4f9a5ffc88a473d74b27f71c24f8c45d089393727cd7838993dd2ead7630d',
'0xbf80743b113d1aa0c6148623526f9b4ea4b82cf584ed8179aef6a4b46022ea9e',
'0x216eebc8aba8d14282a545772e46805c685722b0538548ffbd834a97d0084771',
'0x4ebd1e7690a0a7fcf97dee76ac49fbc3f99644212073e359c98617c6ff83b5de',
'0x81d025fb58a07fad8b986349acb4420884bfe7912bd309e73c66affedb8bf52a',
'0x32fa1bd721691971f21b3dd283065578815d0f5fa21732035530340093ad2161',
'0xce44c4921d49d745a8113b1e473968008df2b5af287a8b083ca29b703d6064ee',
'0xa13f19e04e81e622c650974c935d140c0a7f7f1f3792e4008e6de00a48cfef19',
'0xc7dfdd1f0fd46bf8b28bc04f8d624d5129f06bbedd2a1191264362997f89d9c4',
'0x4ee8ecba96b1d6cef618ec784150484b49b2c745bde5368631fdc323ed867214',
'0x98a087c49e6574cea56589a097d05ecbccbd16d925eb68f5f6b970ff2d23a605',
'0xc3026946e9156eca20d57d5f829a1791ba986cd34f27cc59aff7331aa2c35100',
'0x0da2dc8e24cdd519bb5ea078f56e129190ebd0f9ff123d7727dd8fddb04a4192',
'0xe4c298bf032ca8300c1a25102fa2874e4ce38b354debc30cfe5df0491a8c7a6e',
'0x1688333946581465620bf06e7560419c61cc942a4207e638d9ce01eebed5ff49',
'0x4dd8500a465a7bd445a7d98a26056f773b08860c02f2696426cb54ac7fa2e6b2',
'0x94091c229bd78b6b4448f70aaccfbb5f458e4b407ea32adefd9171aef3d1b8f7',
'0xcf66726aab1f03d57ce9a88802c9fa7899fcd4a4b148a09a30d80f2351d3d1a7',
'0x3bce53e20a9cdca7ea7b2543c8f09cbd81732290b6e4b35104815bd976603d9c',
'0x57ee9bdf607a3ef1de24e61076e0ecc4534b6da6ad61a9a2ed9a2c5dcbec16a6',
'0x59a86c1d651ebbd2051b13632a92037acc32641966c361741214c3cb98469930',
'0xdee514e37875f1a77f8ceabe1e1af6fa3a9ade79acc78dcad0fe8b24212811ea',
'0x8601b0f492cd50d437569139edc306c1293ae572c407e38083d61597c9023f15',
'0xbf37ad569db855b61f54cf55041cdb3d76a4db5b11b20e44aeb81a2757fc280c',
'0x404f0f40d4e3f8ea0fb1477df2c14ad77ee04c3ed85ddbc24332a84a4fabd9b8',
'0xeedc2cc189b3ce11a4fcbc2be9aaa6013a7fee1b82942f7eda44dc3e48488352',
'0x346077d339e3fa221303ae1d744cfccb410ac282e93b372c1e2504b6af402710',
'0x62c866f69c9d4f5cdf2508e6212dd1cd84c41f15eaaa216a5c37fabc15060108',
'0x957e600be17934f67c3a23bb5a7e51472106f0b32e47721860693c74db34c71f',
'0x435a9dce6e858d344c9d8441eaeea17d71edc5fafcad835edc62e2c81f91b60b',
'0x9aa508ecc8e367282466d2025e472368abb3fe6bb9d3098266216d859ba75e52',
'0x56098bf0d071e2e05796388d8bcc13d4f3e2a4f54979b258830bae4450787edc',
'0x323464ff91737979fee3f066c201e739712794dfa6adfe152acc077cd3ff7bd0',
'0x7d0afbe167ef91ebcf6731507c9aab1390e4e1570967587df3228868510689b9',
'0xdf862e41eb03dc93afc893fb4b42c6192e5c39b74a2cea215fe2b24567067059',
'0xba2846049b4009aab1afa24952d7d50791b4b03898b5900bd2ffdfd916faa6da',
'0x938e195af1d8b8bcefee7623c2d5c5d43646665e83d5134966d90c7cfd78c837',
'0x1a50f82987fada22d1ee251aff458b2fe5bc047cf8578e1e12a6d6c414d006a4',
'0x1893f601f9558b3bd7f07bb5dbf4632b0357306b343b38d81c8accedfefea657',
'0x0ace1d9bafd1503f734d2a678f2a30a365876b71d5667f4a22f5803df2e2533e',
'0xde083d226489cee12b02a5d8a8d2425e5fce05e916626fb4cc7cb86e62414cc8',
'0x1c955bebd806dffe45030d1d7f491f571ae05ed66cd14b7117668da515e8775f',
'0x20263ca27cbb0ca140739e3674c89280e3311267c543dcc960a3461ce6ab71a0',
'0x3884e163772419b7746719b09117e611ce2ebe2d61de49662d32e2aeb6cfea5b',
'0x9187965907348d89f91c1bc25460bbea76ef787949b19fd4e8875f1e5effabce',
'0x73e2ef723da240db49f4fb88a5edf280acd2503d291c8834c7000d18b720ca0c',
'0x6303477b816acf9ba61dc12ab4326ce379801164a7ffa146ea3fd4552c251341',
'0x25dbf4f5cd11e18cf08f9c48317a69188cdd1a09253977b530c382ecce5f3576',
'0x595d344060296442356a9b0ced6ca136216d69e7f1ce6cf5d758f40b3242b9a7',
'0x97c19adf3b5a3f612f66cd66726755f91b51637aceaecafce287567af71ff0e0',
'0x45747125c6f8b0672c37b6e5666794342b846031e82bc3e233ace6b78c3e7616',
'0x4da48a456279ec97aaa9f677e7da821467f73bede1b3b94a71b038e843403144',
'0x373cba19ddde964ff248cdf1bb458540cf971dd31fb64a4f66e93506971c0f5b',
'0x9736c5747dbb19dfc0c22b8c84b7afc52592ad0b4f0553a61d7fed1d2e88cf09',
'0xa3e16b2820487e5fe8bade0cb4ae5365b7259e6793e71b99467c74c3a55237b0',
'0x5d3113be6eedda2a0ff3a9b4bdf552d6307b576f5d6741293840a7f8277e51bc',
'0x463d315b0cf1945c26c97e15b667e8eee7c4e661ecb287e593d3680ff9c0379d',
'0x6cd62cfaade37ac10cd7ac5ae6400cf29cac53c8127b7d302f17f138ed60b576',
'0xd6739a1e3f2ded5f15cdd929f065b19c4fc589213e979cc77dcf55436486e891',
'0x0dbe0ad1db855ab770a8e9cdd1465b8dddb48a255a7c6e3f102a2e9df836d6b1',
'0x5938cd434d2e64ad11e4b48d35d9b71a798ce9e7b1a58443f22e6d29991ce189',
'0x2e46e0fe64faf9c785107b6990ff428ceb870240ff94a4165e834830279a523c',
'0xe69fca3c519afa4eb74f9ee7c2f9e484da1980987a29101c2c6b83ca617a2940',
'0x386f10d45cecb20066a997a17c05bafae296edac9b64c6d40fcc0eb0995f6d69',
'0x401a36babd982ca48941d4a61046bbac8a5ec5642f32ef5b7ed7933d892a3509',
'0x25b71257924756f70968a5c653a26ed027864317f1fae354be316c509b81d139',
'0x8f6dd66965c40d4635f2f95dbd35ae201831d5529c309447cb7c20cc5a7ead32',
'0x45d71d87171c701c7888bd1956881787121de3083c8134053b58adc3c8bc45e3',
'0x02938a2eb1aa9ca17a5513ba312428c215518927ad98c3d2ed06848f78b8fac4',
'0x814f67266ea41bf3f78f1e7ef5db0241e15906932f226c5ad9698e39345d7ddc',
'0xb6e0c402c1ccb06ffd098826aa450559601f648f202a0e6c78d53ffb3c7863f5',
'0x006465122aec5c111b94b73041a88223d6d1adfb092398b9949401cf78a84788',
'0xbfd5b726b4091a27e003a8d788eaa1e37c4047b97354813d3499dabdfd0b7e79',
'0x1ae7898a1fde1665ec7ed0cae3b42a63aad5cbdc246fc1e74b42f133961022a1',
'0x339d992d156d4e63cd8e6dcf6cfb5853f780985dba5aa598171973db8ec07226',
'0xe30d4515e8e509137a15fa57fc522bdfabeb200c9662399f8430c841d4a9b520',
'0x06d3f011f8cb9b2c7e548dcad3f6f24d2c0eb6390da579be2a31d81e36928d4b',
'0xe2890582a2d07de123f63c79a58d9383c2ea450299d65eb559bffc5a6701fc30',
'0x091ac30f19c021f008f91cecc3c9e929d7fa7c216257deed36a5d5924be997f0',
'0x8185220cfb96f468402e4abf57e9192ffcbc297e1095ced877578f550db940ca',
'0xb017b0171d2bfb4245928181f79e1cac0b01036b48e40e85017d1390d5467385',
'0x24ba9bc428d686e591fd831d4abb5bf67c7f315f62334ba45a4f920bc4fc77dd',
'0x96a162179145dd4cd79df6d2f79f082ef6c636d2de7b83cef700245291d6c776',
'0x98790b041c3e9f937d6595a8c6fb9c1a6ab2d30c99d5b83464311df986133132',
'0x20a5f30dd82cab4d35af9712eef9b214acd7ef031657404706d2744a53e70509',
'0xbc0747aab20ada0a896424ef4a603786848c6b19cc220a2f9c8f2738a84dcbbc',
'0x93a15224b77e822ce92159439673f8d07bb9bd004ebc573c81f602f1ab7c14da',
'0x21bafd7e71718439e5f81f73d0b3e9b7b5b668cd1b034840e3c37b5514b718ec',
'0x15b4607d88181394928525b3cf1f3d82e95fa79eecc265c8c1edabdf4ad99670',
'0x158401bac24dac4ddccdc97a2b84cc11e384ae5e722bc45ffa939c6aa7481f1a',
'0xca9aab479a04ff5c8f4386fcd125e7994e6d99d30ad48000f55747fcfc98377d',
'0x1ef01746868f792cb838e83f3d5fe647ae863994e3bc171e2db95dd40b5fc895',
'0xfdac26f4e73c17c2cd0dff5c4a1959b8531bbb3c4e9329c477b0da9eda9fa2d8',
'0x9c4dd87962e406777ea52455375a66d68fbac1173ca6d41743a328bf56d845db',
'0x7b36be579a243d9dedced4a333e817f4a8ea04ed53797700e28790c6607733c0',
'0xbaf0da61f295022f70228ba72dafea05e6b3637989c41695537ef1081c4329b1',
'0x288caddc75bd8c19781a4e7de972d072f74eb2620ccad48ca6c79050d9c859df',
'0xfbeb0e651e4063c22c95ea5444d7a0f73c161dbe162c89aca302559a1c35a1e2',
'0x9ab6407800b6e9c4e74f90b6a471577e225f4dff9c4aebbc6be21e3e6430b8b3',
'0xb8e6a6b1cbfd33d1fb9dcbc6ec114b5c4ef3061e9be8162342c203bd21b32e98',
'0x89cdaef85d076bc13bdaa2414818db9f7af0996483315298bf31bc95f4139eea',
'0x3742ba24c3d831f2c9a80c2218a5d410fb556e461b02f8f81fdf439b743d8b77',
'0x5caa35ad904ffbea6cf3ed0c5f63b8c066e5c41cc22219db533bdd9a6d4a1a1c',
'0x524d31e4ea10ae84673c97d535d46d68bbfe4813025c1201d088ae1365310f24',
'0x76b01a1e9308ed5c9d0308869890c8e3391911d23110aea28f33182f521c7e97',
'0x1e6724c88a94c64c71767fc4cceedbc2a9d110f0857833890d5027a3b72679d0',
'0xe652912e80249ce1a6ab6938a497b7049ac014a5c84a28a68e77bcc779d7b936',
'0xae0a7f39b903356b7541948ab8e6e6639cfc31e8475c1980c8e2158c24b90951',
'0x6c3720563525cac5ca8d107bf93d621f6bad14a1a6f9e154cc35fbcd61a620ba',
'0xecfe7bfaf55ceafc1ada71b2d81a571ede4169df882c60fd785713db898157ea',
'0x911218bce72213aa37056d2887ec1ab67b00d1c958869b7f4d4486d4db5b8bf4',
'0xfa0a0cd30bffea06cc58a6bf386ca757c4520373da27461e9a4d7a408164ce8b',
'0x8fa8b33fcafc09ed4fea0c63f821ad35d27d5491bd4674b7c41b9798f7f1cc3b',
'0x9f003f677d5c239c5310d10f5652ca6ce44d2ab93a6da0e3ddb975367255d98c',
'0xd3851e00d0626c0f3381d645be9c637f6b3b6bf3ded490220fb191c7fb9b23d9',
'0xce67e16748ef8839b7d4d2dd47697e6371520bee2cb2de9dae5d12dcbb53aa22',
'0xe6970526935f94d16d698b2219c8cb81a5add1dba3592bd0203d4609dae2c981',
'0x07ca6441f76681b26ccf2eb517cd52d4ff1bbfccb6a5a7e321a797f34f1057f5',
'0xeed987a05cc3d9b2c25b2f5af5ca91ea99c971ca2c2eb7a4573f2fe259020ad9',
'0xfdcdec60f4cfb951e3240f3819f14936453069b5292c0f00954167ff539bd83a',
'0x4bbbde94b2c7b4ecc977eb87142b0c658679b2af4a345c5bdbd3d9b804f68504',
'0x466baaa93c16622db8208e1d20e7339e63e23363ddbc0a60c285ab7206f3e61a',
'0x22aa3494e8deca0acec0daae9f4617096a21c7679f0c40dcf7df44acb768a82a',
'0xa279a33508fba3362b869b073d6032cc42f364d42ae4006352b8dc2b1e152042',
'0x6f37eecb5e2755920c003382f7fbb3f0da442b2e905af5404d17977528c379de',
'0x1c2b9b0500925b2307660bfc754cce8acaec95e2b865c8c66508f61bdf53db68',
'0x97b4ec0bd95cfdf1c6ded7965edd00d16c0a17affc083bd624007a4848ef9499',
'0x8b5c8da6d2fa953523e1a768f2a347ae5d0b373c063d22767f64cf40483b3213',
'0xdeb5023d17b9c706e3b9e8355d40891fd46cc6cc6e6b811f10485bce8ab6f35b',
'0x50be95af92730e1d6080e6e51daedf7d6879bcece076f4dead5f7870e4ea96a3',
'0x4bc5c47a1a9b925837183fa64ebc680bf0ca68ed2fbb9241b2e0769ad5ecbe7c',
'0xab1237a84f614d0a27913562878bdf6d67ea8927449ccc4d269af29eb7371be6',
'0xaf667b7e18da43ca80a8226fab6f436dd79f786866205719e29f5d67d77d9c09',
'0x375e9b3af0e242865678e1935e1935863c2ad98c2ec0cc085fcafdff5bc15388',
'0x8fbc4f5914b976748e98c2f6d9215d7281eff5bb189e1fe6053a2472b91bad2d',
'0xd29ee14183c30af4fecbf53bf596a4b0ec6270c2e73ccfa920d56a75d15fc56d',
'0x94636f5f680340a0406b3606e3bd1adfb5934955e7c3de31f3832fdb29c93e3d',
'0x56073fa916238b6036bd894cba7e935f95369a949abf1dacd562df2f3930a438',
'0xa802692dedbda8ee0775b1e86a8832f1baf2bb0542949142be3ee2f4c43c383f',
'0x7448748b8823e9fab1ad67512f311e8a4055cee933130cf8f12e73fd3dc1e6b3',
'0x47c6844c55fbfdebe14058253502d82fc7aae88b3175aa9f6d6f0faa0c05505c',
'0x06aa5d7b29ca978745d42b969a97571d97cedad8bc55c51138ccf1da508e161a',
'0x05148da4df7e07b6c80bc4233eaa7934122ddc16c3a06bd61b5d89634f7c6fba',
'0x08a91878c729c570ffb334ef425a5a280e49e0b3ed1942094ed7bda3b7dfc27f',
'0x8d0720e07b3c3c2f1fc4fe74fe7073b45eb31de2517b89a789ffb9bc0b7b229a',
'0xd6be230714bd5f748e2be64c6d2eac3c78d52a872ffca44efdb1b609026c8762',
'0xdd9159c82fb92007947d0bb37d73b37b5e458f0febdf401998da85119f933aff',
'0xb532a809fb9c5deb15890223a58e7396e46aa6f13f40dfb2787280899cbfefc8',
'0x39dd20a58a4aa438172030a40a23e3661329fd923197f73192f3b9c1418e915e',
'0x742c6cd9bf876a6b77d51b88e8ac8c6ede94042aa652a75d50ca923e7e234c71',
'0xab049bbf1ce16f202fedc980652ebc22b19c596bf33c1a7b001183f5ec536a0c',
'0x8ecccb011caa18ac7233b757b65ed180df491ec7d00851623a31635cc53ef227',
'0xa73e226a348e55cd8a5ac70c441da149e11b1da032d5e725e22002691acaef4d',
'0xcc9c5ca049c3cd2e547ec72edb7815cd6dfcca6f61389ff47f3d7d2c1976c4e5',
'0x20262f417d6c0d7a4c5305d471b433633d337d3d153695e06402ecb2a68cd36b',
'0xa10e095e3b63dbfd72f723d9864dce36db6982a5ecb4ae9b037ad7ddef29ac2e',
'0x72a30279a0e4663d575809a478c654783eb526623108cb674e8fe3e4544eb457',
'0xdfa3fc6137ebc9d1ee7dce27b5a4e0a8e3fb7976b4e8bd5dd50ecc54be112871',
'0xbd7b245bf504fe1ec042bdbaf15de87c96beb5b56442f8c05a806641caf29c5c',
'0x96afb20c3dfe472e864722d271f96788d17d99d1508031c759f3face960795cd',
'0x442520aa93338b8e0d489abed2a932176525b1077d5d3e06f1823ed6688fc71c',
'0x45cc4313e89cc372dde48848cbb1326de8015bb8137b47a7b00ed38b293cbd8a',
'0x0314aff27e896299a271535a7c6c74f9887e12fd881f529bf4a47545a9fbfeb1',
'0xf22000afafac31fad7c79c19a0c397f9af7c1af0ed091753b9b48750fc705526',
'0xb300734864cbbd64e13c5be7bdc3ec7c824acb3ae913d25fa52be3f5fc2d9325',
'0xefd054f879ccc9a9df514500d105e167e232c69b88de0d71f8046db1ca33ec93',
'0x3c60c6c9adf022857a62c9f60abeea5dd2ff379e5f0ac9df559bae9a979269db',
'0x607564ca83c27468a5df1fe1dc49ebabf2f63ff6b4a4302fae579b9309a7c327',
'0x6e96adca5c9351e11389075ce8c99cec80f74454b9c8b3eb65f18b89a231361e',
'0xdecc0689088d471081888ed73f312cd4681332320222052aa0591b2b758ba4e9',
'0x9afd2cd483c8df22a0af4cc8d2548b06948f1c1cecb32ed98e1fa24addab09f4',
'0x9db2e8c42a356fbfedaccee75266b426526dbf690b5f79f4f5d230428a78e36f',
'0x554585125d5699e8c790741ed01b44742606e55b945c86569df4b8caa541c2e3',
'0xaa6b05c0e0b787ac693945fe07abc38533cb633812d0c6d2fea956dbf02d0951',
'0x31c28ecd152ec85cd2de300968920e29b2e469a6edfb086f108aaaa8df6d751c',
'0x1403eac921eedfe4f7259317ce8b097d38f8efd2331998e658b5ecf6e7ed5d13',
'0xa14e8563b8cb29fdca0be62eae4ff4c32eb04214a08e496c0062cef3ddc86c6b',
'0x002716f20b47d9f3d6dd944e3777e0d4f1ab2867308534fc1fb23dc03a926b33',
'0xcc515a233ac0b6225f87aeffcf6841c61a8f9cd73de96cf137370abd48cc582f',
'0x8e57677a82634553999ad895052d396c3aedf0ef78578060492bc4d630bee953',
'0x590885b89e3d3a0de89da13a219255cdb236415a9a1c4e857fdaa8f0126d878c',
'0x0524268bd452ca92f2f2be92312016e2ac6738096e62169319ffcf538ca909ae',
'0x3a9c7fe2e18e8ece3940f30f22222b6ccac857ad8e07b782ef64c105718f9b37',
'0x305d1d157ed6948fb3d570044236c034943cf17801c8614638d2203a3a3c81c2',
'0xff42c3bce8e86bf7e8d0b37bfcff49213a88feccc60b6b8165af25656c241741',
'0xab4845d9ed77d7c1517ec3df586aa006d529d3ab2acc0060c38b0d6b602dea4e',
'0x6d1fa07fb1853f5b8d33e3c90bde3ab9eea1c9fd0fe10246c909ced94bec62dd',
'0x736d81a8e9c6907052218e4b33cbc22da4e7bcf16d3ac4999d3b0857a3935b1e',
'0x6e877f3400f1d9858114858940efa1fc6aed9db9ac165bdaf4c6f2143aa2ae4a',
'0xae1d367cc949ff8cb62b3dce0f381a60e0903b0e96735bec2979d7d32337786b',
'0x5e800eabbfdcaa60bf983346793f16e1abae9a0c06922377f16e7d15c4a816fa',
'0x3bb83df7da17fc1faf62748bc76c2bb932e6cefb608f30a4436c083f4770aee1',
'0x86a37614d5f9e05147d1e0787b192c4bf8ddc89c9d997db369e392251b117b39',
'0x9195662bb20e8ed19362068e89103d6a692a756beff7bb1217b98c3a4f4a60c7',
'0xe4b7d752d3740149adb8a1723e3ffaa565c8274e71c845445813039462b583c6',
'0x40e699ba51623a6aa8d04d125028d9f82d5e0cb9aca7e373dbe5f5624449daa4',
'0x63f43e227a6089d3f7a6faef6237def6609a004a325f585138882aaa673266b0',
'0x003e450fe7c75cf7de2f02b97bfd9fc4e9d653ec8f9781effbe6c41a48cdb9bd',
'0x76afd10481fc95640f4b0639624ef02348337dd2aa8c6a3d5badf0961f512954',
'0x93d6d41d7e2f5b0fd3f3f5a2ae366c8fefecfd3d34bf2ab551deb73af52ab801',
'0x933811cc073b99d7ea79f3e1d24657684de52392e9c06d6d7e03550abfe1da06',
'0x08ce6c8185a4c02b1032a96048902199966836f5b56c92f60366efe6a417a164',
'0x5e19f80b1b60495dbbd9a3ef4f793f1cd135126f4291e5e335283c3f32f9ca29',
'0xb3f08bf7784e2e620dcb522ee5e08864a238e60cbd2bbc9e6aea5df713ee81f5',
'0x5d5a5cb73d86fed7011262826d13d8778edad00bb9d4e7b5b187eae1693fd4d4',
'0x384cd7a7ab563aa3fe7bf402e95a334007bdd378a1f52449b8994f9da799aef9',
'0xf04e5cd25f6899f210581efc0f33bc8a3735e70d7cc7befaf963f12f146a0907',
'0x7a04704dbc81b1a2145028a1603c8243bc21b4ac2c32d655ecd4ee24c04981ae',
'0xafc216243ce4a6878523fb2029320c487aeb72cedea001f080d41e2433f0712c',
'0x7d8efe00a48aad3c3fcaa93d775d73d3ce5060e357c8d8cfaddd74a9bf68791c',
'0xef4e4661acec05f47d48a590a103d76005bb454c87a5adb396f93c29930d050b',
'0xa14e47bd859d017ec3ec5fb36bc710a1d991b920153c9e65ef2f3656dfe06384',
'0xf8d4f222ebbbd384eee48e8b9445c58fd17e334167de5b66d8cca258e3f3c784',
'0x464392a72abbe1a71dbba153573e8ba54ec61a0c35f1cd2a50223c3513721d73',
'0x0a65371cbbd13c43cc3260509f1b50c70a60363b97209754e5d5d1bb9d3c2dec',
'0xef5e8ea0e5d130c0bcd6a8aa831c9468d9c0ded02d0ad75ddb6a614535e253ab',
'0x75c0fea242dcb7904a288649f0184b9ff21a6837af2cba6b195f4a8e4b024a43',
'0x40c6df3cc937a24f7ae005bdf0051f9975c850d4216eeb17a1cf1fd069d1c9cd',
'0xfcceff80ee78046021dbd9ef2816979046f771b61dcdd7eddb5c3ec93d1a129c',
'0xa28da742154c2695cab2a2e2e149e46966d368a863276e21bc20680e4361188d',
'0xbc2d1fc3793341662e7844b0d143bbe3151ae4b2d75b5781a8e12b2f9018835f',
'0x640d2cac0d761055a7bd128e571c53479a8b91bb24596766e26d138256f8bc63',
'0x30c09025ae12c8b7eb0308811b09c66e4796d13a80862b3f17fe7e0fff962b8d',
'0xaaee26111084739eb61980b184ee2158497ed390c33000e487467f0d19482528',
'0x9c900db799c7f730fea556b5ef753fb97f86bca5191c4356dd5d1d1e8fb00263',
'0xf82092c319e27e6183cdd4603138724c1de320c87835538b15560ed5fc415ad1',
'0x90012567049a76de8b165aff617dcd35d7072b3b18c96c5ee2f1f22826f39de1',
'0xaed8a84b435288b1415fc4e0257c8efcb4152d26ca86e051f77e70529a30d1df',
'0x6d853420a930a1f835c308acaa2e2688010329cb8a140f3a460db6a4ce8b311d',
'0xd1988168825ca994c977a8699a139f00fb37755e21e7ab8391fad4881b59ce2c',
'0x22e7881a23a1310a625e8fdcd1117477353b3136957d79883d0529e84ae2eca9',
'0x2de5d040ee6f9cd89990784ad1391332a0455fd3a6173d370fcbcdcd34d1008e',
'0x45f0be90a97845e76297b1e724b6faf714f3dc2e7f7f51d9f1b4fa367a6baf41',
'0x50ea990710cae7edd6b3ec178fd41954898968baa65f8681412c07a5254c2c54',
'0x389ddc107fc5f18ebdb0b7fe6399c407ee3404b2125a26ea9dea6d6d95472715',
'0xda5ece28cb9ab135470860c0a3cafcc5aef157b8583d64d30505c52b8babbbf7',
'0x3f5437392c6ab8cb0f94cf76c6d2263ddce201a42cec890f4dcf2c31a38a81e6',
'0xd9f2a529fa97a703eb28c75851ae2eb0dc99d41b70138905d9206ebe9e39f1b9',
'0xdb0cdb34595d3591a26ceaabc8b126cd7728ab98eca44b1874f175c3a4d559b5',
'0xe8e9d23885bcd734f013a7c864b745367488275befb1870450fde30497ffd60a',
'0xb05b9c98c44d22d69c253bd92cce9321ee4eb13586cbd0f6412a7dc644f21dc4',
'0x9dcc91d9d4bb7dd792ecba77403bde36ec2fe3edff117302b356d49d576e6365',
'0x231a3c059e82e5cc87b59a37c5c3c51631ded94906bc69d222e150c1b7a259cc',
'0xa08f985db4db278f2320f8e61c98a8f131fade0af42c0b865e40f69dc96e310c',
'0xe54338ed1fc7481122b83b33939b37abba874d96ae1cd10ec0a9c03c438feb36',
'0x38ead2d7491a63657147b3ee49310b065f78425343a740b973abdf9b3a1ba392',
'0x0dbdd57116ed9fb97d36d09603689f59fd9d8b6436fc8826f78d1fe7fc339943',
'0x1069e50f36360bfc554ee19e2bbf760add3bc07fca473110656a240fe3542bce',
'0x3f463b9addb28837b889528561f31c397ed55e730aa42455d2ab2cb987636277',
'0x92ce0deeccb517672e073a3292630b400ddea3e69e3df1cd1f6e69fd886ab8ee',
'0xa0d86f5132a92422284d965a4f057e07eee5227eed006c700ecbe11838954fea',
'0xc0760294e6fce4bfc78884a1ceb3c1a72641ec19f7bbd7ee04edb7ea686a8e4f',
'0xc57ce0b02f786744604a8b79631311fa9d388e1bb2993fe3ead87411a048ccf4',
'0x9ca865a1ef30ebe2a1dc62087c494e022758f2c2bb484eb568f0b734933eae6d',
'0xc61b977a4d6cb7aed5692e0659205cf9c6340454bf1c1644582055e0d0c30f74',
'0x6f8b0d4feaf555f9e7b717486c8e9fae562e1b58f4ebe0a9068829d09a113a7d',
'0x6ba3879ee921bc6d5a22d0332e0627d98ee91417482d17e9b5d89494c51fae73',
'0x2ad9e04e01a479414157a6f14de721be3a400246c62a5a4328b1c9709cbc8ad7',
'0x29ac4aff1a3b3f552a8c1b489ae52dde10066634685c3da55610fa8e5d10c58c',
'0x7abd1c5208cee9f0175ae5ad6a1c35e452a5aadb1e1b5037fdae849666837aee',
'0x933c26fb0e5f166d53d76a69be029478f5f8d8589c005e90c0abcc00988770c8',
'0xd0f6fe6c35a09669948069d2d510a6f81eadad3c36158bdf73b9b3a0ef8ad6f5',
'0xf642bc367871c74754876d9d4d53fcea6167c89e6b740d9ae0605c228e614869',
'0xd8c05119abc1de22259c209ca1067cecd280b67d78f10fb2b87a5ed587c2bf01',
'0x7b7ba478b52149727980b6d0452f5527b709aa1f57e1aebdfd10fb30ce9b6497',
'0xbdad12ce42faac5fad7c3b95b82222bf551c2026baa77d6fc283ab2c5bfd6cb9',
'0xfb306991c7d617783852866f44cdf268065ef76f152b4b206662f7523d15be5c',
'0x68719a3f3b84a0f98985e363dd0ec5aa6377d4e66dca7d5c6aa5fbcde7c77e8c',
'0xdb2955ae772c90faed9fc40b361be4f509e7856ab88a7a89b4b0ac540a4de839',
'0xc0e1df604b8a38eebb61b7984c0bb35381d665d542088720ae51389030333971',
'0x787432de4f01273b6fe87d4a20727314c57ebf81d447200232569b0fbe52784f',
'0x5f9bfede9e21cb5fe79924515b70c0d4485f7cb5d99ee9056e70ce8cf020979e',
'0x2169bbe806f67e5cafdd9a2968dcdd8cc71bbfc926e2b45324e846dbd93bfdb5',
'0xa6630460d78acff6f5b0fc18e669336b9a5a4f6d5de8caf9bb7fa8a1ba45a05c',
'0x5e33454a995b1f86a4340449fef13d093bbf8e36fe6b095b8674564371638a83',
'0x6aa9931233bb684ee6eeb1d775d093c296e559c2335b37a805d647f8dc3d0bb2',
'0xcea9a0b0985185f2aae2b1733e4f0d5a03e24fde80b7072ad168d6a84a7171a1',
'0xd8b655f8a7cf5f7e710711b172ed79c7a92a580feb766aa273d7c2db2845b7a4',
'0xec7614994879d408f57aa867c896cd109fd76d94a32aa4f84ed48c0abfcbc45a',
'0x2d9eb7ebfcf2dc957c2d03055dc18d1c789661bd0f7fcb0defd3f2921520083e',
'0xd92c0f56e6eb6a51d17cdee5ea392d7fe42d58cd43867641441268627640ca48',
'0xfaebe8ee996052d1d13dda98882b4f105045d894d70a66757ab1ed1988391e91',
'0x8954d34e07fc4f1d2789df6ee02f8edea78b07802a421b44108f7ba0143b4898',
'0xfe3f7eaf40c04f0a1fe3aaa53331e4d798e8dbaa571ccc22fe77d36f8425f952',
'0xb634f8724d844ba64d306fc66fbdecd6a3b39bd2c5e4732e7b4722f744d58ae2',
'0xab6a4a53742847a3990e9a0a158e65e5ee8eb6d6c668ab5946232308e6809081',
'0xae3f56a8625599d3bb4e9da696ef7720aa6f65f05cd6c906d3ef3c726e19e383',
'0xaad197d0f659f444fd0bf73361a5153d038e25aae7ab3af34d9a725042cd8ea1',
'0x5d8640370cebfb402c5ab1361a74be0f1636eb495d7e4c6358629cd1d821e08e',
'0x72a0befb92333e8694d7fce12a191be5d424a4da9a32831eb27540ee345b2825',
'0xd38e9dd91b78d9f646d8f8c526fa03a35e66fb77b95322cdceaebcd99e22fbd2',
'0x23ec81adc638445342a3c8c1b88c8c8196953238e6ff55f7671087ef1f6f697f',
'0xc463cead51d6f87dc56fb8cf2f823740fd8734b2fe1d0077dfaf1cff990ce379',
'0xd8d59aec92c041cecf0f7d8ec20388a4f4a2aac88d541d76388ee083c0ef0f59',
'0x0c05a080103c5db55031eb6c9ae32b2e1f7ac98d52409e47d121391f21e822f4',
'0x0187146fe1dae7dfec25905d962e199c4f86fa605674a7490918a442cca122cf',
'0xe0d28e3ebcf9ae79bbd637cbe92ff05fba99fe16a3e7a6bcbf0153392fca1db5',
'0x8f9ad9f02e51134ef7b7d2aae29fcd4fde4fc61dba906922460025da641c09a7',
'0xeb071e6bc567a971c8b9f8c89ab824dbfc2d1f6e3cf95c3612e8424c14d89ac5',
'0x8f167e1f9a806581b3451f63a4faf9609d30640040edcf694a9225281127bbb9',
'0x725d52c44ad1263e42317f5292a8be75ff54e721eef660b2bbe0c3144f0e5562',
'0xc35493feecc8275dc86d575a23eabae063d2cf973d1d88d90818a64a43d136e6',
'0xc4b8d183554a97fbc8bb0da31d93d16f525fe6ae2a6db531d93691f752bcae25',
'0xc39623a9999bf484b938075421859dc4ea0745d8d6f8f7dd068614f2002054ef',
'0xf1911ccb34ec39798f0d6a01f5074e00de15f7cc6d24cae87e48910bb14f383a',
'0x822dd09c7b4984b1f42392ee4287eff57e748b61ecfb461fbafe70bd916ed03c',
'0x5608d3163326a58f05f874db1178c0f47d6a5e88923ea200d835d833ca11a3a0',
'0xe1102cca06f8b614602c7704682eca05a516f02538208b8fea79e4c84411d1c7',
'0xab612e5fdfcee0b401e7b9d3234d5488d8bdba096cec0a0a0665b43e7c97a635',
'0xe53434613a07f1e226b8e4154cdca35f97bf0f9819721fbe5e8c25cdd86fb1bf',
'0xa3f6a9d87d15606de0c8d1ef09f0d415fb6571ff9d49eb391f014324e1bb1111',
'0x9a0c80fc1aad729a4b11e5242adeb7c3f6ea6014ccbb7d8803f5ebf1d0e383f6',
'0xae8738510f944c27b4f3d83856559a276d94aa5b9a0502251ecc41e77be4970b',
'0x7374476ce47f1de40b04ceb14571b52f47ae54d01b96c3ea08d1c60714163f3e',
'0x7d826d5cd70c95518738a98554d06267c0d1ca162317e56f995319457483f9c1',
'0xaac822ec698624cedaf881a4eaa19e486cd5ab28449912c60ec9f9878f3044ab',
'0xaffb2dd02316ae415be23ac24c939031dce78220c2e620b98522435fea2d333e',
'0x5233bee1bdfe0ee3b993ad06a87d269c2929acd66ce41358cdf9fc687bb945f1',
'0x0cea4d92c24ef107563dc729d65d7aa56077107569ce0e45e41829675aea3022',
'0x3667e44e2d30500fa70a05ee7fcf80afb26579720aab16a4f77337d73446ec1b',
'0x186919d78a3183f86b67b0047273c4487af3923a107bbbe49137885c9093c0e6',
'0x05a691a68cc1e0e6df9f8b55127c5bac590aff37811201e4defe7887a873cfc9',
'0x1917b5921b7a70a6f892434eef9b442d67706e3ac3675c6c2b5d2d9debcd12a7',
'0x2a595da5c37c99b25e8f534154d05a0ca08ea8b37d829dd8d1309df3614c4387',
'0xdaba375f399abd6d2e92fecc6a218acb7bd3c0f9685f9c512f942386be5bbc6c',
'0xfcfe71066ba5926d11193fed5027c02fdce0a450a08fb4f8a4211ae09b16e756',
'0xec2791d0c98881628c8f4c27ac49576d328dff851da45768a868006e41724ba5',
'0xa0777dd93e266376e2caf48614406b77a524864f7e2328208aa9b7930c8a9b06',
'0x1ad1c9ccdb5083f468bff04c4ac9a74d82c9bcc499f0f19af8e9471282b633a4',
'0x5b043443c47d06507b94598e86e7db40f32b4aef2709619021bbebd8f17e7261',
'0xff4aa2b6f8613b484b699f30d71355ddbd888da46932441b4932d31dcff35723',
'0xb0e81350cbfd01ebaaac2cf93ae24fbdee8f482943669853d40c5eb1298f93e3',
'0x2d19a72a5d678b78988592e8dceda34f47590465e01ddf40777a267068367d47',
'0x529d587a315f6446109edbcf54ba136268368148c2ffca2b9871780e622b3e52',
'0xc362de43cfb1462724078bb7a7106126e22987608720c4ebb567b93b78a59d5f',
'0x74c53ebb9aa40d995410fc340e5eaa9fae4a80851caf2316a70cbc339e805250',
'0x25dce31548b2340c398184257e15c38c66d0fec3bfa8a33c13c422ccfa6ffcdf',
'0x786603b905581a4585ceafe041153b56d54f4bc5e702ae9f543b24554f701498',
'0xc86c7fc9d7f4ecbd78f356854392b4df9f731ea326d00f1a8b3dacf2da4b9a01',
'0x11bc7da0ad6b2b0bb38eac290980ff433b434757bba67086971b89057aabca6a',
'0x2fe0498d7013ba523b4298a3d4ab873a3996a70dc660b7bf8fdbf6c2c387993a',
'0x8d3963cc9c3549e4d4541364c9657d7cfdee501401d8721ed449aebc551ca001',
'0x845b4e2dd34951bfa7d9e82c21322459f83ad7d68dc371a75dc1c73c1076704e',
'0x168a1783ed9fd5a65b3b6334670d4e8742e3e70fd8d2b6b1505d2ab465a2a0ce',
'0x89e3727348dc03713a3e1c788d58b827f2183a212eda1c9c61c658825327d9e0',
'0xd461481a04ca34c2ffef5aa4b8176bc253991d6cf54f0f65103296370075ac72',
'0x9d86a54c7c548c461133ed8b5268ca99161cdce2c51285b0869ab0b3a797ce4d',
'0x17a22243012337e50cfdf253f373a985934ce6fd98b2f02a8e41b394d7f038aa',
'0x12cf7e0740586c5a6fc3ef3a844ca3571b218d910eba46412b07054fe355664c',
'0x861d3e7ee2be099f22574d4fa4af3b9a98c1c753243f180c5dd6dfca7b48f46b',
'0xb6286161c6d20c44e92ba956062c31f8a42eac3a98706269a13c88a389fb090f',
'0x16a0688414ab06c683e0d50f4b8068b253aa03465d2c9c5a3abf0d231396feff',
'0x1642d93c4d5241f88739bfddbaea6162122b27f0710a0bc1b0be0b40d7bf16a9',
'0xa20c8f8991dbc5248a2ad0c888470b6afa52aca12bdf212f990332b341831237',
'0xc1f3821e8492e1c5356a0b0ca933e281e0617c4d6788de2af078f47fcd0998e7',
'0x112396da4dc8dae445d6b5fa6c8446ed4995d4aba1ca2fae5e465d6246d34a94',
'0x0ddac6120ce5e114d9be5fc3c768d0af87892fa9308baee261c48aa32d624fb1',
'0xa701cc57f3667263e671422e849f3bca3ceac10e346178582438b028138a504f',
'0xfa339e4dea7405df815aac387b7010d57951e0a778ab486036181c1cadebc897',
'0x9cd3778960d282898259469e337b6ea80038dbbbe02df4f1e1b854c065b84ecd',
'0x990f1a5743d1185d317a38e8147c73b763ca47137514a33a2cbae12329720ff5',
'0x3606bd3696e11f2722a8f42e157e9b188f388a0a8f1f75ed78fe34cbe6586f39',
'0xef4998c2bdc7f3b3209ebcf4640682710e07100d9e248fb1b10504b00ddc307d',
'0xac2f46c602b43df83bada17b5dc5068cc2ef1265b2da8618a7869c73666d4338',
'0x94ad02f0111b48b5ad2f79be28089fad508b4a7602b03f2bc7d727184c8b3bf1',
'0x0d632ec515cb1b39239aa3154da4775f154d58aecbac04d2ab979e0ba883a696',
'0x41b32421aec4f543c35e4a34e990a03e5361c05cb2e147bcfc5683a1f26bfc33',
'0x45c13232eb9031035d7d0e3778e4ade08289942e26f7753f149295d6615e5c3c',
'0x86e628f52e859873268d421a822cf9897ca92db61c7a5100fc047b3563e1a196',
'0x3fb2a24c0125164149b5e6888c85d196f8b8380a02767391a35cf3258eaedd67',
'0x92965d1693caff6bd09fd4505e7082418ac59bd93a26ea9bc30f94c1601600ec',
'0x1b61eb4d80ca97245c39273a5e3869ac6db6d4d0d14b77af1ceb3fab460474a1',
'0xbcae251af72923a7224a55542051eed1a24bfd7ac01ef75f50e219db06ebfd55',
'0x28c50f4fdf89c4ceaf2f0308df978c646874e9e947d23450cddbbdd0622f42d2',
'0xc2070f5a4d661c8f8c8dd2f0817a7ba14c5ee3311b644048bff22b414170ebbf',
'0x18451cf3d77c1e8d5fc2a3f686a91aadfa8c27d96e23f8ae6d8072641e48f771',
'0x65c6cb6fe36c9bf8f5b01efa710fe5d0601a0f291dadd75d0c173bb32522e5f6',
'0x124bbf3a0f3aa98c3073f4f220369c53109be5b1e0f835c7df4ceac86cfeb620',
'0x70cf5585625a68fb97460990631331dea9a06309aa39d4348f90a8d0034a441d',
'0x46203648d800a718d4fd5de4690b7de52aeb59ff4a75099aa646423542d72755',
'0x645d3103d67b9880cf1b1a1e8691dd36ea0b2f4c4dcb9956cc3dc523058c396f',
'0xe1d79592a0fec55dd05f0b0c0a14ab053912b8c0b9248890f18677875694e6e6',
'0xdd46d276d883f110ccf19066b4b5ca235d2b40c275edcb620e5fdab65c2a78a2',
'0xb4e5c14dec6a4149173ddf49bcc3a0d7d1c19602a8d2973130167b8cb59891df',
'0x9c10e9da8fa9f11a1b85454e70f4bb69cd18a22980d787b76a5201ae167522af',
'0x8288d760442857a2634d27b0933c76d3453799142fae1af3b729a2303da603c1',
'0x38a07c6b291d6446bc66de4b098a89091ca455dc4313d5c18004d99749c0de57',
'0x2b14c81aa5580a21eedfb21e5baf9334079bdd838a1caadc6e02b0fd050073fe',
'0x4fb2b6e202139026507087f7dbae5b838c840719443eaa6a68eb8d797c85e7c4',
'0x1c55c50514d7f5f3ec999f7bd17e09853cc0bac5660c7641dba447def15a8d68',
'0x845f1b7420af1af1278d2420b7d053509e50b063e795e7f241cae444b6a264a5',
'0xfae0ac4934318c1b087099a981558aa939461aea8768b5cb0567b39e220e5c31',
'0x70ff9a059323f2ede2e5452211f57c3528b53716aa415482c8b17d3ee05f571d',
'0xa638e88b83252302f7bb6312e6a83701df8d54e9fed6c1e53b01e5e95c9e78f2',
'0xb25651a21af2ee7d0c53156999271df85ad72d0af7070d87464468cf76d14058',
'0x3b9c92721c6ef016f61f114f46ed4c10c541c68dadc4965aea00a8c36ee272f4',
'0xf8890dc86ec439adf7b47b4c4c3e13919007939c7211339adefe37d80f605a9f',
'0xeed79eedb1124f62e71719df219a6bf42b37d71db1ca8bf0ced594e52b1726dd',
'0x5e71610d3acea4fd629bde47845698043e90f395d04fcb0fce998a9246c319b6',
'0x389a2d86b49013abd2810bf407048cfce6163c0ddaa54887bb89089168b1d67d',
'0xcaf02f2d8f1194c444c3a7d0c363015ad8445b869477c7813126e79bfaf5383b',
'0xff0bef9153385282b40dcb93bb3076a6c0211262816405373b10dad5a1f00a28',
'0x29852ac63cba3e221a95defcb03ebd5802322117bf1265de16734f6eacfefafa',
'0x458975512e8706075bbde18dfc8b0bd04c0413165ca3bf105338fc2ef3395c48',
'0x90c5023cb819fdd771a081b8af2991035f67655b9c78d46d84206925510396bb',
'0x878510ed37cb6a7d410860ca01867af9a3e677e0d830c51f15cec9731685e55f',
'0xfa7a0596b7455f088646ed8ac24bfb7551812e7779a756355c2235f0e21df5b8',
'0x977fd8151cffcaff5fec7d3b5b2139b1306e67772f601d8aa47fcd0a906e26dc',
'0x5e3f15f6c6afc9cca95488809cc4faa2242c8856995ebb870c179bbc94b03ac7',
'0xc78a7e1d298864477e08b59d64c385151d61342d180361569763053374f39ba7',
'0x89e0f0c04eea3f440a0f39a020fa1ccf152d0bdf76aa66a7d1845a95e164a6f5',
'0xbede7f1ace8fd984d475d71c158a9508b09c4aa4fb50186efc06313b2ffbfd55',
'0x9670776e1014d87a7b58fb2190ccb13d0b5bb487786a3f447a29ff39c8cd8f2f',
'0xd6e8bb637e31bd3720b20c0377e264f8703fe4cb5633fc955e7543f126482974',
'0x893c4e7c3b500b1144436c57860e29c39608cfcf391a2b8b76bc767a492f9de7',
'0xea9baad3e66af51d83ab2dd4e0db7fde29ea4f2fa353a3b50a903ed8b791c054',
'0x020e7f26dfb0595f92c60d0114c7ee99c14f66715f51bc47f2ce44d938294c33',
'0xfd6c86153f53a5ee16eb076ce4cf14aae9fb9adf8b08c5cbcadf180c80219af9',
'0x797d3c82ab7479302fa7c7a04a7354324f3d23f2a8311b40aed29b8b92ff3132',
'0xb631adc53d9b75af7871269368b61261b5ad2da5a5396a273825b807cccc3a62',
'0xa2a15caea9659c4a77dd12d39fcc7bc05eb24bc64f568c8a1dc6733eebf3dbf6',
'0x3ea84f751a682e71231d7edab3298ad1ea00a7491d918955e773dc8d829bf16f',
'0xc48630f5c6289b251484566552c99faf4baa85ef525398f0c49e155525229a70',
'0xbca790d220f7c563dbf3821d0ed932a7e6f71c5f6a9e9651f05ae3af8bce5572',
'0xffdd145ce842676066c041d38cb218d83654f3a19880497cac1964fdf7d2be2d',
'0x713a2ae03dceace4c7701ee2af77e2dd7aa2112bcf1b855a97256db00c891b6a',
'0xa51953f4aeb204970fda2eca1c9c0a1b4392a6deec5d49376b1fea4e30c64623',
'0xf233364f9231e594d206dd57b5d082cb4296bdf50f224b39e356c609d9b5232e',
'0x62212d19f363aec450c7c66fc0ec683108005a774d999b98c7230170b1ed2f15',
'0xa44ff97c08c0e1ffdf7c1ccb252e6dbbcf3aaa135a22e381c57e9d167fa37557',
'0x3ec29cb197b5066fa9935fe9f9d11117052becb7ecf8d36e5d8f159116090715',
'0x73761373a14fe5bb24fb7da41fd590b935b5ba3b862f2d4f44345ff906d747af',
'0x7945a43b281dec9945babb62d1e6c7eabce572774bffd17a0dd0d0843ef0fa3e',
'0x06f817d0967e63386b42e1b5be512a99bd039f47d577c39682a4befbe4967da4'
]
};

97
config/blockchain.js Normal file
View File

@ -0,0 +1,97 @@
module.exports = {
// applies to all environments
default: {
enabled: true,
rpcHost: "localhost", // HTTP-RPC server listening interface (default: "localhost")
rpcPort: 8545, // HTTP-RPC server listening port (default: 8545)
rpcCorsDomain: "auto", // Comma separated list of domains from which to accept cross origin requests (browser enforced)
// When set to "auto", Embark will automatically set the cors to the address of the webserver
wsRPC: true, // Enable the WS-RPC server
wsOrigins: "auto", // Origins from which to accept websockets requests
// When set to "auto", Embark will automatically set the cors to the address of the webserver
wsHost: "localhost", // WS-RPC server listening interface (default: "localhost")
wsPort: 8546 // WS-RPC server listening port (default: 8546)
},
// default environment, merges with the settings in default
// assumed to be the intended environment by `embark run` and `embark blockchain`
development: {
networkType: "custom", // Can be: testnet, rinkeby, livenet or custom, in which case, it will use the specified networkId
networkId: "1337", // Network id used when networkType is custom
isDev: true, // Uses and ephemeral proof-of-authority network with a pre-funded developer account, mining enabled
datadir: ".embark/development/datadir", // Data directory for the databases and keystore
mineWhenNeeded: true, // Uses our custom script (if isDev is false) to mine only when needed
nodiscover: true, // Disables the peer discovery mechanism (manual peer addition)
maxpeers: 0, // Maximum number of network peers (network disabled if set to 0) (default: 25)
proxy: true, // Proxy is used to present meaningful information about transactions
targetGasLimit: 8000000, // Target gas limit sets the artificial target gas floor for the blocks to mine
simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm", // Mnemonic used by the simulator to generate a wallet
simulatorBlocktime: 0, // Specify blockTime in seconds for automatic mining. Default is 0 and no auto-mining.
account: {
// numAccounts: 3, // When specified, creates accounts for use in the dapp. This option only works in the development environment, and can be used as a quick start option that bypasses the need for MetaMask in development. These accounts are unlocked and funded with the below settings.
// password: "config/development/password", // Password for the created accounts (as specified in the `numAccounts` setting). If `mineWhenNeeded` is enabled (and isDev is not), this password is used to create a development account controlled by the node.
// balance: "5 ether" // Balance to be given to the created accounts (as specified in the `numAccounts` setting)
}
},
// merges with the settings in default
// used with "embark run privatenet" and/or "embark blockchain privatenet"
privatenet: {
networkType: "custom",
networkId: "1337",
isDev: false,
datadir: ".embark/privatenet/datadir",
// -- mineWhenNeeded --
// This options is only valid when isDev is false.
// Enabling this option uses our custom script to mine only when needed.
// Embark creates a development account for you (using `geth account new`) and funds the account. This account can be used for
// development (and even imported in to MetaMask). To enable correct usage, a password for this account must be specified
// in the `account > password` setting below.
// NOTE: once `mineWhenNeeded` is enabled, you must run an `embark reset` on your dApp before running
// `embark blockchain` or `embark run` for the first time.
mineWhenNeeded: true,
// -- genesisBlock --
// This option is only valid when mineWhenNeeded is true (which is only valid if isDev is false).
// When enabled, geth uses POW to mine transactions as it would normally, instead of using POA as it does in --dev mode.
// On the first `embark blockchain or embark run` after this option is enabled, geth will create a new chain with a
// genesis block, which can be configured using the `genesisBlock` configuration option below.
genesisBlock: "config/privatenet/genesis.json", // Genesis block to initiate on first creation of a development node
nodiscover: true,
maxpeers: 0,
proxy: true,
account: {
// "address": "", // When specified, uses that address instead of the default one for the network
password: "config/privatenet/password" // Password to unlock the account. If `mineWhenNeeded` is enabled (and isDev is not), this password is used to create a development account controlled by the node.
},
targetGasLimit: 8000000,
simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm",
simulatorBlocktime: 0
},
// merges with the settings in default
// used with "embark run testnet" and/or "embark blockchain testnet"
testnet: {
networkType: "testnet",
syncMode: "light",
account: {
password: "config/testnet/password"
}
},
// merges with the settings in default
// used with "embark run livenet" and/or "embark blockchain livenet"
livenet: {
networkType: "livenet",
syncMode: "light",
rpcCorsDomain: "http://localhost:8000",
wsOrigins: "http://localhost:8000",
account: {
password: "config/livenet/password"
}
}
// you can name an environment with specific settings and then specify with
// "embark run custom_name" or "embark blockchain custom_name"
//custom_name: {
//}
};

40
config/communication.js Normal file
View File

@ -0,0 +1,40 @@
module.exports = {
// default applies to all environments
default: {
enabled: true,
provider: "whisper", // Communication provider. Currently, Embark only supports whisper
available_providers: ["whisper"], // Array of available providers
},
// default environment, merges with the settings in default
// assumed to be the intended environment by `embark run`
development: {
connection: {
host: "localhost", // Host of the blockchain node
port: 8546, // Port of the blockchain node
type: "ws" // Type of connection (ws or rpc)
}
},
// merges with the settings in default
// used with "embark run privatenet"
privatenet: {
},
// merges with the settings in default
// used with "embark run testnet"
testnet: {
},
// merges with the settings in default
// used with "embark run livenet"
livenet: {
},
// you can name an environment with specific settings and then specify with
// "embark run custom_name"
//custom_name: {
//}
};

91
config/contracts.js Normal file
View File

@ -0,0 +1,91 @@
const merkle = require("../app/js/merkle.js");
module.exports = {
// default applies to all environments
default: {
// Blockchain node to deploy the contracts
deployment: {
host: "localhost", // Host of the blockchain node
port: 8545, // Port of the blockchain node
type: "rpc" // Type of connection (ws or rpc),
// Accounts to use instead of the default account to populate your wallet
/*,accounts: [
{
privateKey: "your_private_key",
balance: "5 ether" // You can set the balance of the account in the dev environment
// Balances are in Wei, but you can specify the unit with its name
},
{
privateKeyFile: "path/to/file", // Either a keystore or a list of keys, separated by , or ;
password: "passwordForTheKeystore" // Needed to decrypt the keystore file
},
{
mnemonic: "12 word mnemonic",
addressIndex: "0", // Optionnal. The index to start getting the address
numAddresses: "1", // Optionnal. The number of addresses to get
hdpath: "m/44'/60'/0'/0/" // Optionnal. HD derivation path
}
]*/
},
// order of connections the dapp should connect to
dappConnection: [
"$WEB3", // uses pre existing web3 object if available (e.g in Mist)
"ws://localhost:8546",
"http://localhost:8545"
],
gas: "auto",
contracts: {
"ERC20Receiver": { "deploy": false },
"MiniMeToken": { "deploy": false },
"MiniMeTokenFactory": {
},
"SNT": {
"instanceOf": "MiniMeToken",
"args": [
"$MiniMeTokenFactory",
"0x0000000000000000000000000000000000000000",
0,
"TestMiniMeToken",
18,
"TST",
true
]
},
"SNTGiveaway": {
args: ["$SNT", "10", "10", merkle.merkleRoot]
}
}
},
// default environment, merges with the settings in default
// assumed to be the intended environment by `embark run`
development: {
dappConnection: [
"ws://localhost:8546",
"http://localhost:8545",
"$WEB3" // uses pre existing web3 object if available (e.g in Mist)
]
},
// merges with the settings in default
// used with "embark run privatenet"
privatenet: {
},
// merges with the settings in default
// used with "embark run testnet"
testnet: {
},
// merges with the settings in default
// used with "embark run livenet"
livenet: {
},
// you can name an environment with specific settings and then specify with
// "embark run custom_name" or "embark blockchain custom_name"
//custom_name: {
//}
};

39
config/namesystem.js Normal file
View File

@ -0,0 +1,39 @@
module.exports = {
// default applies to all environments
default: {
enabled: true,
available_providers: ["ens"],
provider: "ens"
},
// default environment, merges with the settings in default
// assumed to be the intended environment by `embark run`
development: {
register: {
rootDomain: "embark.eth",
subdomains: {
'status': '0x1a2f3b98e434c02363f3dac3174af93c1d690914'
}
}
},
// merges with the settings in default
// used with "embark run privatenet"
privatenet: {
},
// merges with the settings in default
// used with "embark run testnet"
testnet: {
},
// merges with the settings in default
// used with "embark run livenet"
livenet: {
},
// you can name an environment with specific settings and then specify with
// "embark run custom_name" or "embark blockchain custom_name"
//custom_name: {
//}
};

View File

@ -0,0 +1,18 @@
{
"config": {
"homesteadBlock": 0,
"byzantiumBlock": 0,
"daoForkSupport": true
},
"nonce": "0x0000000000000042",
"difficulty": "0x0",
"alloc": {
"0x3333333333333333333333333333333333333333": {"balance": "15000000000000000000"}
},
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x3333333333333333333333333333333333333333",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x7a1200"
}

View File

@ -0,0 +1 @@
dev_password

59
config/storage.js Normal file
View File

@ -0,0 +1,59 @@
module.exports = {
// default applies to all environments
default: {
enabled: true,
ipfs_bin: "ipfs",
provider: "ipfs",
available_providers: ["ipfs"],
upload: {
host: "localhost",
port: 5001
},
dappConnection: [
{
provider: "ipfs",
host: "localhost",
port: 5001,
getUrl: "http://localhost:8080/ipfs/"
}
]
// Configuration to start Swarm in the same terminal as `embark run`
/*,account: {
address: "YOUR_ACCOUNT_ADDRESS", // Address of account accessing Swarm
password: "PATH/TO/PASSWORD/FILE" // File containing the password of the account
},
swarmPath: "PATH/TO/SWARM/EXECUTABLE" // Path to swarm executable (default: swarm)*/
},
// default environment, merges with the settings in default
// assumed to be the intended environment by `embark run`
development: {
enabled: true,
provider: "ipfs",
upload: {
host: "localhost",
port: 5001,
getUrl: "http://localhost:8080/ipfs/"
}
},
// merges with the settings in default
// used with "embark run privatenet"
privatenet: {
},
// merges with the settings in default
// used with "embark run testnet"
testnet: {
},
// merges with the settings in default
// used with "embark run livenet"
livenet: {
},
// you can name an environment with specific settings and then specify with
// "embark run custom_name"
//custom_name: {
//}
};

1
config/testnet/password Normal file
View File

@ -0,0 +1 @@
test_password

6
config/webserver.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
enabled: true,
host: "localhost",
openBrowser: true,
port: 8000
};

0
contracts/.gitkeep Normal file
View File

75
contracts/SNTGiveaway.sol Normal file
View File

@ -0,0 +1,75 @@
pragma solidity ^0.4.24;
import "common/Controlled.sol";
import "token/MiniMeToken.sol";
import "common/MerkleProof.sol";
contract SNTGiveaway is Controlled {
mapping(address => bool) public sentToAddress;
mapping(bytes5 => bool) public codeUsed;
MiniMeToken public SNT;
uint public ethAmount;
uint public sntAmount;
bytes32 public root;
event AddressFunded(address dest, bytes5 code, uint ethAmount, uint sntAmount);
/// @notice Constructor
/// @param _sntAddress address SNT contract address
/// @param _ethAmount uint Amount of ETH in wei to send
/// @param _sntAmount uint Amount of SNT in wei to send
/// @param _root bytes32 Merkle tree root
constructor(address _sntAddress, uint _ethAmount, uint _sntAmount, bytes32 _root) public {
SNT = MiniMeToken(_sntAddress);
ethAmount = _ethAmount;
sntAmount = _sntAmount;
root = _root;
}
/// @notice Determine if a request to send SNT/ETH is valid based on merkle proof, and destination address
/// @param _proof bytes32[] Merkle proof
/// @param _code bytes5 Unhashed code
/// @param _dest address Destination address
function validRequest(bytes32[] _proof, bytes5 _code, address _dest) public view returns(bool) {
return !sentToAddress[_dest] && !codeUsed[_code] && MerkleProof.verifyProof(_proof, root, keccak256(abi.encodePacked(_code)));
}
/// @notice Process request for SNT/ETH and send it to destination address
/// @param _proof bytes32[] Merkle proof
/// @param _code bytes5 Unhashed code
/// @param _dest address Destination address
function processRequest(bytes32[] _proof, bytes5 _code, address _dest) public onlyController {
require(!sentToAddress[_dest] && !codeUsed[_code], "Funds already sent / Code already used");
require(MerkleProof.verifyProof(_proof, root, keccak256(abi.encodePacked(_code))), "Invalid code");
sentToAddress[_dest] = true;
codeUsed[_code] = true;
require(SNT.transfer(_dest, sntAmount), "Transfer did not work");
_dest.transfer(ethAmount);
emit AddressFunded(_dest, _code, ethAmount, sntAmount);
}
/// @notice Update configuration settings
/// @param _ethAmount uint Amount of ETH in wei to send
/// @param _sntAmount uint Amount of SNT in wei to send
/// @param _root bytes32 Merkle tree root
function updateSettings(uint _ethAmount, uint _sntAmount, bytes32 _root) public onlyController {
ethAmount = _ethAmount;
sntAmount = _sntAmount;
root = _root;
}
/// @notice Extract balance in ETH + SNT from the contract and destroy the contract
function boom() public onlyController {
uint sntBalance = SNT.balanceOf(address(this));
require(SNT.transfer(controller, sntBalance), "Transfer did not work");
selfdestruct(controller);
}
}

View File

@ -0,0 +1,22 @@
pragma solidity ^0.4.23;
contract Controlled {
/// @notice The address of the controller is the only address that can call
/// a function with this modifier
modifier onlyController {
require(msg.sender == controller);
_;
}
address public controller;
constructor() internal {
controller = msg.sender;
}
/// @notice Changes the controller of the contract
/// @param _newController The new controller of the contract
function changeController(address _newController) public onlyController {
controller = _newController;
}
}

View File

@ -0,0 +1,40 @@
/**
* @title MerkleProof
* @dev Merkle proof verification based on
* https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
*/
library MerkleProof {
/**
* @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
* and each pair of pre-images are sorted.
* @param _proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree
* @param _root Merkle root
* @param _leaf Leaf of Merkle tree
*/
function verifyProof(
bytes32[] _proof,
bytes32 _root,
bytes32 _leaf
)
internal
pure
returns (bool)
{
bytes32 computedHash = _leaf;
for (uint256 i = 0; i < _proof.length; i++) {
bytes32 proofElement = _proof[i];
if (computedHash < proofElement) {
// Hash(current computed hash + current element of the proof)
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
// Hash(current element of the proof + current computed hash)
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
// Check if the computed hash (root) is equal to the provided root
return computedHash == _root;
}
}

View File

@ -0,0 +1,10 @@
pragma solidity ^0.4.23;
interface ApproveAndCallFallBack {
function receiveApproval(
address from,
uint256 _amount,
address _token,
bytes _data
) external;
}

View File

@ -0,0 +1,90 @@
pragma solidity ^0.4.23;
import "./ERC20Token.sol";
contract ERC20Receiver {
event TokenDeposited(address indexed token, address indexed sender, uint256 amount);
event TokenWithdrawn(address indexed token, address indexed sender, uint256 amount);
mapping (address => mapping(address => uint256)) tokenBalances;
constructor() public {
}
function depositToken(
ERC20Token _token
)
external
{
_depositToken(
msg.sender,
_token,
_token.allowance(
msg.sender,
address(this)
)
);
}
function withdrawToken(
ERC20Token _token,
uint256 _amount
)
external
{
_withdrawToken(msg.sender, _token, _amount);
}
function depositToken(
ERC20Token _token,
uint256 _amount
)
external
{
require(_token.allowance(msg.sender, address(this)) >= _amount);
_depositToken(msg.sender, _token, _amount);
}
function tokenBalanceOf(
ERC20Token _token,
address _from
)
external
view
returns(uint256 fromTokenBalance)
{
return tokenBalances[address(_token)][_from];
}
function _depositToken(
address _from,
ERC20Token _token,
uint256 _amount
)
private
{
require(_amount > 0);
if (_token.transferFrom(_from, address(this), _amount)) {
tokenBalances[address(_token)][_from] += _amount;
emit TokenDeposited(address(_token), _from, _amount);
}
}
function _withdrawToken(
address _from,
ERC20Token _token,
uint256 _amount
)
private
{
require(_amount > 0);
require(tokenBalances[address(_token)][_from] >= _amount);
tokenBalances[address(_token)][_from] -= _amount;
require(_token.transfer(_from, _amount));
emit TokenWithdrawn(address(_token), _from, _amount);
}
}

View File

@ -0,0 +1,53 @@
pragma solidity ^0.4.23;
// Abstract contract for the full ERC 20 Token standard
// https://github.com/ethereum/EIPs/issues/20
interface ERC20Token {
/**
* @notice send `_value` token to `_to` from `msg.sender`
* @param _to The address of the recipient
* @param _value The amount of token to be transferred
* @return Whether the transfer was successful or not
*/
function transfer(address _to, uint256 _value) external returns (bool success);
/**
* @notice `msg.sender` approves `_spender` to spend `_value` tokens
* @param _spender The address of the account able to transfer the tokens
* @param _value The amount of tokens to be approved for transfer
* @return Whether the approval was successful or not
*/
function approve(address _spender, uint256 _value) external returns (bool success);
/**
* @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
* @param _from The address of the sender
* @param _to The address of the recipient
* @param _value The amount of token to be transferred
* @return Whether the transfer was successful or not
*/
function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
/**
* @param _owner The address from which the balance will be retrieved
* @return The balance
*/
function balanceOf(address _owner) external view returns (uint256 balance);
/**
* @param _owner The address of the account owning tokens
* @param _spender The address of the account able to transfer the tokens
* @return Amount of remaining tokens allowed to spent
*/
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
/**
* @notice return total supply of tokens
*/
function totalSupply() external view returns (uint256 supply);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

View File

@ -0,0 +1,638 @@
pragma solidity ^0.4.23;
/*
Copyright 2016, Jordi Baylina
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @title MiniMeToken Contract
* @author Jordi Baylina
* @dev This token contract's goal is to make it easy for anyone to clone this
* token using the token distribution at a given block, this will allow DAO's
* and DApps to upgrade their features in a decentralized manner without
* affecting the original token
* @dev It is ERC20 compliant, but still needs to under go further testing.
*/
import "../common/Controlled.sol";
import "./TokenController.sol";
import "./ApproveAndCallFallBack.sol";
import "./MiniMeTokenInterface.sol";
import "./MiniMeTokenFactory.sol";
/**
* @dev The actual token contract, the default controller is the msg.sender
* that deploys the contract, so usually this token will be deployed by a
* token controller contract, which Giveth will call a "Campaign"
*/
contract MiniMeToken is MiniMeTokenInterface, Controlled {
string public name; //The Token's name: e.g. DigixDAO Tokens
uint8 public decimals; //Number of decimals of the smallest unit
string public symbol; //An identifier: e.g. REP
string public version = "MMT_0.1"; //An arbitrary versioning scheme
/**
* @dev `Checkpoint` is the structure that attaches a block number to a
* given value, the block number attached is the one that last changed the
* value
*/
struct Checkpoint {
// `fromBlock` is the block number that the value was generated from
uint128 fromBlock;
// `value` is the amount of tokens at a specific block number
uint128 value;
}
// `parentToken` is the Token address that was cloned to produce this token;
// it will be 0x0 for a token that was not cloned
MiniMeToken public parentToken;
// `parentSnapShotBlock` is the block number from the Parent Token that was
// used to determine the initial distribution of the Clone Token
uint public parentSnapShotBlock;
// `creationBlock` is the block number that the Clone Token was created
uint public creationBlock;
// `balances` is the map that tracks the balance of each address, in this
// contract when the balance changes the block number that the change
// occurred is also included in the map
mapping (address => Checkpoint[]) balances;
// `allowed` tracks any extra transfer rights as in all ERC20 tokens
mapping (address => mapping (address => uint256)) allowed;
// Tracks the history of the `totalSupply` of the token
Checkpoint[] totalSupplyHistory;
// Flag that determines if the token is transferable or not.
bool public transfersEnabled;
// The factory used to create new clone tokens
MiniMeTokenFactory public tokenFactory;
////////////////
// Constructor
////////////////
/**
* @notice Constructor to create a MiniMeToken
* @param _tokenFactory The address of the MiniMeTokenFactory contract that
* will create the Clone token contracts, the token factory needs to be
* deployed first
* @param _parentToken Address of the parent token, set to 0x0 if it is a
* new token
* @param _parentSnapShotBlock Block of the parent token that will
* determine the initial distribution of the clone token, set to 0 if it
* is a new token
* @param _tokenName Name of the new token
* @param _decimalUnits Number of decimals of the new token
* @param _tokenSymbol Token Symbol for the new token
* @param _transfersEnabled If true, tokens will be able to be transferred
*/
constructor(
address _tokenFactory,
address _parentToken,
uint _parentSnapShotBlock,
string _tokenName,
uint8 _decimalUnits,
string _tokenSymbol,
bool _transfersEnabled
)
public
{
require(_tokenFactory != address(0)); //if not set, clone feature will not work properly
tokenFactory = MiniMeTokenFactory(_tokenFactory);
name = _tokenName; // Set the name
decimals = _decimalUnits; // Set the decimals
symbol = _tokenSymbol; // Set the symbol
parentToken = MiniMeToken(_parentToken);
parentSnapShotBlock = _parentSnapShotBlock;
transfersEnabled = _transfersEnabled;
creationBlock = block.number;
}
///////////////////
// ERC20 Methods
///////////////////
/**
* @notice Send `_amount` tokens to `_to` from `msg.sender`
* @param _to The address of the recipient
* @param _amount The amount of tokens to be transferred
* @return Whether the transfer was successful or not
*/
function transfer(address _to, uint256 _amount) public returns (bool success) {
require(transfersEnabled);
return doTransfer(msg.sender, _to, _amount);
}
/**
* @notice Send `_amount` tokens to `_to` from `_from` on the condition it
* is approved by `_from`
* @param _from The address holding the tokens being transferred
* @param _to The address of the recipient
* @param _amount The amount of tokens to be transferred
* @return True if the transfer was successful
*/
function transferFrom(
address _from,
address _to,
uint256 _amount
)
public
returns (bool success)
{
// The controller of this contract can move tokens around at will,
// this is important to recognize! Confirm that you trust the
// controller of this contract, which in most situations should be
// another open source smart contract or 0x0
if (msg.sender != controller) {
require(transfersEnabled);
// The standard ERC 20 transferFrom functionality
if (allowed[_from][msg.sender] < _amount) {
return false;
}
allowed[_from][msg.sender] -= _amount;
}
return doTransfer(_from, _to, _amount);
}
/**
* @dev This is the actual transfer function in the token contract, it can
* only be called by other functions in this contract.
* @param _from The address holding the tokens being transferred
* @param _to The address of the recipient
* @param _amount The amount of tokens to be transferred
* @return True if the transfer was successful
*/
function doTransfer(
address _from,
address _to,
uint _amount
)
internal
returns(bool)
{
if (_amount == 0) {
return true;
}
require(parentSnapShotBlock < block.number);
// Do not allow transfer to 0x0 or the token contract itself
require((_to != 0) && (_to != address(this)));
// If the amount being transfered is more than the balance of the
// account the transfer returns false
uint256 previousBalanceFrom = balanceOfAt(_from, block.number);
if (previousBalanceFrom < _amount) {
return false;
}
// Alerts the token controller of the transfer
if (isContract(controller)) {
require(TokenController(controller).onTransfer(_from, _to, _amount));
}
// First update the balance array with the new value for the address
// sending the tokens
updateValueAtNow(balances[_from], previousBalanceFrom - _amount);
// Then update the balance array with the new value for the address
// receiving the tokens
uint256 previousBalanceTo = balanceOfAt(_to, block.number);
require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
updateValueAtNow(balances[_to], previousBalanceTo + _amount);
// An event to make the transfer easy to find on the blockchain
emit Transfer(_from, _to, _amount);
return true;
}
function doApprove(
address _from,
address _spender,
uint256 _amount
)
internal
returns (bool)
{
require(transfersEnabled);
// To change the approve amount you first have to reduce the addresses`
// allowance to zero by calling `approve(_spender,0)` if it is not
// already 0 to mitigate the race condition described here:
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
require((_amount == 0) || (allowed[_from][_spender] == 0));
// Alerts the token controller of the approve function call
if (isContract(controller)) {
require(TokenController(controller).onApprove(_from, _spender, _amount));
}
allowed[_from][_spender] = _amount;
emit Approval(_from, _spender, _amount);
return true;
}
/**
* @param _owner The address that's balance is being requested
* @return The balance of `_owner` at the current block
*/
function balanceOf(address _owner) external view returns (uint256 balance) {
return balanceOfAt(_owner, block.number);
}
/**
* @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
* its behalf. This is a modified version of the ERC20 approve function
* to be a little bit safer
* @param _spender The address of the account able to transfer the tokens
* @param _amount The amount of tokens to be approved for transfer
* @return True if the approval was successful
*/
function approve(address _spender, uint256 _amount) external returns (bool success) {
doApprove(msg.sender, _spender, _amount);
}
/**
* @dev This function makes it easy to read the `allowed[]` map
* @param _owner The address of the account that owns the token
* @param _spender The address of the account able to transfer the tokens
* @return Amount of remaining tokens of _owner that _spender is allowed
* to spend
*/
function allowance(
address _owner,
address _spender
)
external
view
returns (uint256 remaining)
{
return allowed[_owner][_spender];
}
/**
* @notice `msg.sender` approves `_spender` to send `_amount` tokens on
* its behalf, and then a function is triggered in the contract that is
* being approved, `_spender`. This allows users to use their tokens to
* interact with contracts in one function call instead of two
* @param _spender The address of the contract able to transfer the tokens
* @param _amount The amount of tokens to be approved for transfer
* @return True if the function call was successful
*/
function approveAndCall(
address _spender,
uint256 _amount,
bytes _extraData
)
external
returns (bool success)
{
require(doApprove(msg.sender, _spender, _amount));
ApproveAndCallFallBack(_spender).receiveApproval(
msg.sender,
_amount,
this,
_extraData
);
return true;
}
/**
* @dev This function makes it easy to get the total number of tokens
* @return The total number of tokens
*/
function totalSupply() external view returns (uint) {
return totalSupplyAt(block.number);
}
////////////////
// Query balance and totalSupply in History
////////////////
/**
* @dev Queries the balance of `_owner` at a specific `_blockNumber`
* @param _owner The address from which the balance will be retrieved
* @param _blockNumber The block number when the balance is queried
* @return The balance at `_blockNumber`
*/
function balanceOfAt(
address _owner,
uint _blockNumber
)
public
view
returns (uint)
{
// These next few lines are used when the balance of the token is
// requested before a check point was ever created for this token, it
// requires that the `parentToken.balanceOfAt` be queried at the
// genesis block for that token as this contains initial balance of
// this token
if ((balances[_owner].length == 0) || (balances[_owner][0].fromBlock > _blockNumber)) {
if (address(parentToken) != 0) {
return parentToken.balanceOfAt(_owner, min(_blockNumber, parentSnapShotBlock));
} else {
// Has no parent
return 0;
}
// This will return the expected balance during normal situations
} else {
return getValueAt(balances[_owner], _blockNumber);
}
}
/**
* @notice Total amount of tokens at a specific `_blockNumber`.
* @param _blockNumber The block number when the totalSupply is queried
* @return The total amount of tokens at `_blockNumber`
*/
function totalSupplyAt(uint _blockNumber) public view returns(uint) {
// These next few lines are used when the totalSupply of the token is
// requested before a check point was ever created for this token, it
// requires that the `parentToken.totalSupplyAt` be queried at the
// genesis block for this token as that contains totalSupply of this
// token at this block number.
if ((totalSupplyHistory.length == 0) || (totalSupplyHistory[0].fromBlock > _blockNumber)) {
if (address(parentToken) != 0) {
return parentToken.totalSupplyAt(min(_blockNumber, parentSnapShotBlock));
} else {
return 0;
}
// This will return the expected totalSupply during normal situations
} else {
return getValueAt(totalSupplyHistory, _blockNumber);
}
}
////////////////
// Clone Token Method
////////////////
/**
* @notice Creates a new clone token with the initial distribution being
* this token at `_snapshotBlock`
* @param _cloneTokenName Name of the clone token
* @param _cloneDecimalUnits Number of decimals of the smallest unit
* @param _cloneTokenSymbol Symbol of the clone token
* @param _snapshotBlock Block when the distribution of the parent token is
* copied to set the initial distribution of the new clone token;
* if the block is zero than the actual block, the current block is used
* @param _transfersEnabled True if transfers are allowed in the clone
* @return The address of the new MiniMeToken Contract
*/
function createCloneToken(
string _cloneTokenName,
uint8 _cloneDecimalUnits,
string _cloneTokenSymbol,
uint _snapshotBlock,
bool _transfersEnabled
)
public
returns(address)
{
uint snapshotBlock = _snapshotBlock;
if (snapshotBlock == 0) {
snapshotBlock = block.number;
}
MiniMeToken cloneToken = tokenFactory.createCloneToken(
this,
snapshotBlock,
_cloneTokenName,
_cloneDecimalUnits,
_cloneTokenSymbol,
_transfersEnabled
);
cloneToken.changeController(msg.sender);
// An event to make the token easy to find on the blockchain
emit NewCloneToken(address(cloneToken), snapshotBlock);
return address(cloneToken);
}
////////////////
// Generate and destroy tokens
////////////////
/**
* @notice Generates `_amount` tokens that are assigned to `_owner`
* @param _owner The address that will be assigned the new tokens
* @param _amount The quantity of tokens generated
* @return True if the tokens are generated correctly
*/
function generateTokens(
address _owner,
uint _amount
)
public
onlyController
returns (bool)
{
uint curTotalSupply = totalSupplyAt(block.number);
require(curTotalSupply + _amount >= curTotalSupply); // Check for overflow
uint previousBalanceTo = balanceOfAt(_owner, block.number);
require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
updateValueAtNow(balances[_owner], previousBalanceTo + _amount);
emit Transfer(0, _owner, _amount);
return true;
}
/**
* @notice Burns `_amount` tokens from `_owner`
* @param _owner The address that will lose the tokens
* @param _amount The quantity of tokens to burn
* @return True if the tokens are burned correctly
*/
function destroyTokens(
address _owner,
uint _amount
)
public
onlyController
returns (bool)
{
uint curTotalSupply = totalSupplyAt(block.number);
require(curTotalSupply >= _amount);
uint previousBalanceFrom = balanceOfAt(_owner, block.number);
require(previousBalanceFrom >= _amount);
updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
updateValueAtNow(balances[_owner], previousBalanceFrom - _amount);
emit Transfer(_owner, 0, _amount);
return true;
}
////////////////
// Enable tokens transfers
////////////////
/**
* @notice Enables token holders to transfer their tokens freely if true
* @param _transfersEnabled True if transfers are allowed in the clone
*/
function enableTransfers(bool _transfersEnabled) public onlyController {
transfersEnabled = _transfersEnabled;
}
////////////////
// Internal helper functions to query and set a value in a snapshot array
////////////////
/**
* @dev `getValueAt` retrieves the number of tokens at a given block number
* @param checkpoints The history of values being queried
* @param _block The block number to retrieve the value at
* @return The number of tokens being queried
*/
function getValueAt(
Checkpoint[] storage checkpoints,
uint _block
)
view
internal
returns (uint)
{
if (checkpoints.length == 0) {
return 0;
}
// Shortcut for the actual value
if (_block >= checkpoints[checkpoints.length-1].fromBlock) {
return checkpoints[checkpoints.length-1].value;
}
if (_block < checkpoints[0].fromBlock) {
return 0;
}
// Binary search of the value in the array
uint min = 0;
uint max = checkpoints.length-1;
while (max > min) {
uint mid = (max + min + 1) / 2;
if (checkpoints[mid].fromBlock<=_block) {
min = mid;
} else {
max = mid-1;
}
}
return checkpoints[min].value;
}
/**
* @dev `updateValueAtNow` used to update the `balances` map and the
* `totalSupplyHistory`
* @param checkpoints The history of data being updated
* @param _value The new number of tokens
*/
function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value) internal {
if (
(checkpoints.length == 0) ||
(checkpoints[checkpoints.length - 1].fromBlock < block.number))
{
Checkpoint storage newCheckPoint = checkpoints[checkpoints.length++];
newCheckPoint.fromBlock = uint128(block.number);
newCheckPoint.value = uint128(_value);
} else {
Checkpoint storage oldCheckPoint = checkpoints[checkpoints.length-1];
oldCheckPoint.value = uint128(_value);
}
}
/**
* @dev Internal function to determine if an address is a contract
* @param _addr The address being queried
* @return True if `_addr` is a contract
*/
function isContract(address _addr) internal view returns(bool) {
uint size;
if (_addr == 0) {
return false;
}
assembly {
size := extcodesize(_addr)
}
return size > 0;
}
/**
* @dev Helper function to return a min betwen the two uints
*/
function min(uint a, uint b) internal returns (uint) {
return a < b ? a : b;
}
/**
* @notice The fallback function: If the contract's controller has not been
* set to 0, then the `proxyPayment` method is called which relays the
* ether and creates tokens as described in the token controller contract
*/
function () public payable {
require(isContract(controller));
require(TokenController(controller).proxyPayment.value(msg.value)(msg.sender));
}
//////////
// Safety Methods
//////////
/**
* @notice This method can be used by the controller to extract mistakenly
* sent tokens to this contract.
* @param _token The address of the token contract that you want to recover
* set to 0 in case you want to extract ether.
*/
function claimTokens(address _token) public onlyController {
if (_token == 0x0) {
controller.transfer(address(this).balance);
return;
}
MiniMeToken token = MiniMeToken(_token);
uint balance = token.balanceOf(address(this));
token.transfer(controller, balance);
emit ClaimedTokens(_token, controller, balance);
}
////////////////
// Events
////////////////
event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
event Transfer(address indexed _from, address indexed _to, uint256 _amount);
event NewCloneToken(address indexed _cloneToken, uint snapshotBlock);
event Approval(
address indexed _owner,
address indexed _spender,
uint256 _amount
);
}

View File

@ -0,0 +1,49 @@
pragma solidity ^0.4.23;
import "./MiniMeToken.sol";
////////////////
// MiniMeTokenFactory
////////////////
/**
* @dev This contract is used to generate clone contracts from a contract.
* In solidity this is the way to create a contract from a contract of the
* same class
*/
contract MiniMeTokenFactory {
/**
* @notice Update the DApp by creating a new token with new functionalities
* the msg.sender becomes the controller of this clone token
* @param _parentToken Address of the token being cloned
* @param _snapshotBlock Block of the parent token that will
* determine the initial distribution of the clone token
* @param _tokenName Name of the new token
* @param _decimalUnits Number of decimals of the new token
* @param _tokenSymbol Token Symbol for the new token
* @param _transfersEnabled If true, tokens will be able to be transferred
* @return The address of the new token contract
*/
function createCloneToken(
address _parentToken,
uint _snapshotBlock,
string _tokenName,
uint8 _decimalUnits,
string _tokenSymbol,
bool _transfersEnabled
) public returns (MiniMeToken) {
MiniMeToken newToken = new MiniMeToken(
this,
_parentToken,
_snapshotBlock,
_tokenName,
_decimalUnits,
_tokenSymbol,
_transfersEnabled
);
newToken.changeController(msg.sender);
return newToken;
}
}

View File

@ -0,0 +1,108 @@
pragma solidity ^0.4.23;
import "./ERC20Token.sol";
contract MiniMeTokenInterface is ERC20Token {
/**
* @notice `msg.sender` approves `_spender` to send `_amount` tokens on
* its behalf, and then a function is triggered in the contract that is
* being approved, `_spender`. This allows users to use their tokens to
* interact with contracts in one function call instead of two
* @param _spender The address of the contract able to transfer the tokens
* @param _amount The amount of tokens to be approved for transfer
* @return True if the function call was successful
*/
function approveAndCall(
address _spender,
uint256 _amount,
bytes _extraData
)
external
returns (bool success);
/**
* @notice Creates a new clone token with the initial distribution being
* this token at `_snapshotBlock`
* @param _cloneTokenName Name of the clone token
* @param _cloneDecimalUnits Number of decimals of the smallest unit
* @param _cloneTokenSymbol Symbol of the clone token
* @param _snapshotBlock Block when the distribution of the parent token is
* copied to set the initial distribution of the new clone token;
* if the block is zero than the actual block, the current block is used
* @param _transfersEnabled True if transfers are allowed in the clone
* @return The address of the new MiniMeToken Contract
*/
function createCloneToken(
string _cloneTokenName,
uint8 _cloneDecimalUnits,
string _cloneTokenSymbol,
uint _snapshotBlock,
bool _transfersEnabled
)
public
returns(address);
/**
* @notice Generates `_amount` tokens that are assigned to `_owner`
* @param _owner The address that will be assigned the new tokens
* @param _amount The quantity of tokens generated
* @return True if the tokens are generated correctly
*/
function generateTokens(
address _owner,
uint _amount
)
public
returns (bool);
/**
* @notice Burns `_amount` tokens from `_owner`
* @param _owner The address that will lose the tokens
* @param _amount The quantity of tokens to burn
* @return True if the tokens are burned correctly
*/
function destroyTokens(
address _owner,
uint _amount
)
public
returns (bool);
/**
* @notice Enables token holders to transfer their tokens freely if true
* @param _transfersEnabled True if transfers are allowed in the clone
*/
function enableTransfers(bool _transfersEnabled) public;
/**
* @notice This method can be used by the controller to extract mistakenly
* sent tokens to this contract.
* @param _token The address of the token contract that you want to recover
* set to 0 in case you want to extract ether.
*/
function claimTokens(address _token) public;
/**
* @dev Queries the balance of `_owner` at a specific `_blockNumber`
* @param _owner The address from which the balance will be retrieved
* @param _blockNumber The block number when the balance is queried
* @return The balance at `_blockNumber`
*/
function balanceOfAt(
address _owner,
uint _blockNumber
)
public
constant
returns (uint);
/**
* @notice Total amount of tokens at a specific `_blockNumber`.
* @param _blockNumber The block number when the totalSupply is queried
* @return The total amount of tokens at `_blockNumber`
*/
function totalSupplyAt(uint _blockNumber) public view returns(uint);
}

View File

@ -0,0 +1,33 @@
pragma solidity ^0.4.23;
/**
* @dev The token controller contract must implement these functions
*/
interface TokenController {
/**
* @notice Called when `_owner` sends ether to the MiniMe Token contract
* @param _owner The address that sent the ether to create tokens
* @return True if the ether is accepted, false if it throws
*/
function proxyPayment(address _owner) external payable returns(bool);
/**
* @notice Notifies the controller about a token transfer allowing the
* controller to react if desired
* @param _from The origin of the transfer
* @param _to The destination of the transfer
* @param _amount The amount of the transfer
* @return False if the controller does not authorize the transfer
*/
function onTransfer(address _from, address _to, uint _amount) external returns(bool);
/**
* @notice Notifies the controller about an approval allowing the
* controller to react if desired
* @param _owner The address that calls `approve()`
* @param _spender The spender in the `approve()` call
* @param _amount The amount in the `approve()` call
* @return False if the controller does not authorize the approval
*/
function onApprove(address _owner, address _spender, uint _amount) external
returns(bool);
}

24
embark.json Normal file
View File

@ -0,0 +1,24 @@
{
"contracts": ["contracts/**"],
"app": {
"css/app.css": ["app/css/**"],
"js/app.js": ["app/js/index.js"],
"images/": ["app/images/**"],
"index.html": "app/index.html"
},
"buildDir": "dist/",
"config": "config/",
"versions": {
"web3": "1.0.0-beta",
"solc": "0.4.25",
"ipfs-api": "17.2.4"
},
"plugins": {
},
"options": {
"solc": {
"optimize": true,
"optimize-runs": 200
}
}
}

12147
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

24
package.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "hackathon-onboarding",
"version": "0.0.1",
"description": "",
"scripts": {
"test": "embark test",
"start": "nodemon server/main.js"
},
"author": "",
"license": "ISC",
"homepage": "",
"devDependencies": {
"nodemon": "^1.18.4"
},
"dependencies": {
"crypto": "^1.0.1",
"ethereumjs-util": "^5.2.0",
"ipfs": "^0.32.3",
"ipfs-api": "^24.0.2",
"merkle-tree-solidity": "^1.0.8",
"orbit-db": "^0.19.9",
"web3": "^1.0.0-beta.34"
}
}

43
server/codegen.js Normal file
View File

@ -0,0 +1,43 @@
const crypto = require("crypto");
const MerkleTree = require('merkle-tree-solidity');
const { sha3 } = require('ethereumjs-util');
const fs = require('fs');
const numCodes = 500;
const codeLength = 5;
const codes = [];
const elements = [];
for(i = 0; i < numCodes; i++){
const code = crypto.randomBytes(codeLength).toString('hex');
codes.push(code);
elements.push(sha3(code));
}
const merkleTree = new MerkleTree.default(elements);
const stream1 = fs.createWriteStream("codes.txt");
stream1.once('open', function(fd) {
codes.map(el => {
stream1.write(el + "\n");
})
stream1.end();
});
const stream2 = fs.createWriteStream("./app/js/merkle.js");
stream2.once('open', function(fd) {
stream2.write("module.exports = {\n");
stream2.write("\tmerkleRoot: '0x" + merkleTree.getRoot().toString('hex') + "',\n");
stream2.write("\telements: [\n");
stream2.write(elements
.map(el => "\t\t'0x" + el.toString('hex') + "'")
.join(",\n"))
stream2.write("\n\t]\n};\n\n");
stream2.end();
});
console.log("Merkle Root: 0x%s", merkleTree.getRoot().toString('hex'));
console.log("./codes.txt generated");
console.log("./app/js/merkle.js generated");

99
server/main.js Normal file
View File

@ -0,0 +1,99 @@
const IPFS = require('ipfs')
const OrbitDB = require('orbit-db')
const Web3 = require('web3');
const EventEmitter = require('events');
const contractAddress = "0xA49e638dD086E38Dac737C9346909f62DDf7d387";
const connectionURL = `ws://localhost:8546`;
const abiDefinition = [{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"codeUsed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x39c6fe16"},{"constant":false,"inputs":[{"name":"_newController","type":"address"}],"name":"changeController","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x3cebb823"},{"constant":false,"inputs":[{"name":"_proof","type":"bytes32[]"},{"name":"code","type":"bytes32"},{"name":"_leaf","type":"bytes32"},{"name":"_dest","type":"address"}],"name":"send","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x6c1101c9"},{"constant":true,"inputs":[],"name":"sntAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x7f58fa14"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"sentToAddress","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x81e8706d"},{"constant":false,"inputs":[],"name":"boom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xa169ce09"},{"constant":false,"inputs":[{"name":"_ethAmount","type":"uint256"},{"name":"_sntAmount","type":"uint256"},{"name":"_root","type":"bytes32"}],"name":"updateSettings","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xa4438334"},{"constant":true,"inputs":[],"name":"SNT","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xc55a02a0"},{"constant":true,"inputs":[],"name":"ethAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xc98166c0"},{"constant":true,"inputs":[],"name":"root","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xebf0c717"},{"constant":true,"inputs":[],"name":"controller","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xf77c4791"},{"inputs":[{"name":"_tokenAddress","type":"address"},{"name":"_ethAmount","type":"uint256"},{"name":"_sntAmount","type":"uint256"},{"name":"_root","type":"bytes32"}],"payable":true,"stateMutability":"payable","type":"constructor","signature":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"dest","type":"address"},{"indexed":false,"name":"leaf","type":"bytes32"},{"indexed":false,"name":"ethAmount","type":"uint256"},{"indexed":false,"name":"sntAmount","type":"uint256"}],"name":"AddressFunded","type":"event","signature":"0xd692fa6f47b47bb192b78e1ec163f648fc83f1f87f1caf3dd4640106e052a3f2"}];
const events = new EventEmitter();
const ipfs = new IPFS({
EXPERIMENTAL: {
pubsub: true
}
})
let orbitdb;
let web3;
let contract;
ipfs.on('ready', async () => {
console.log("Connected to IPFS");
orbitdb = new OrbitDB(ipfs)
web3 = new Web3(new Web3.providers.WebsocketProvider(connectionURL, {headers: {Origin: "embark"}}));
web3.eth.net.isListening()
.then(async () => {
console.log("Connected to WEB3: '" + connectionURL + "'");
contract = new web3.eth.Contract(abiDefinition, contractAddress);
const accounts = await web3.eth.getAccounts();
web3.eth.defaultAccount = accounts[0];
events.emit('web3:connected')
})
.catch(error => {
console.error(error);
process.exit();
});
});
const start = async () => {
console.log("Connecting to data stores...");
const transactionStore = await orbitdb.keyvalue('rramos-transactions-adadasdasd');
const fundRequestStore = await orbitdb.log('rramos-funds-requests-adadasdasd');
let lastCodeProcessed;
let running = false;
setInterval(() => {
if(running) return;
console.log("Processing requests...");
running = true;
let conditions = {}
if(lastCodeProcessed){
conditions = ({gt: lastCodeProcessed});
}
// Query the database.
const all = fundRequestStore.iterator(conditions)
.collect()
.map(async (e) => {
const record = e.payload.value;
lastCodeProcessed = record.code;
const transaction = transactionStore.get(record.code);
if(!transaction) return;
const validRequest = await contract.methods.validRequest(record.proof, record.code, record.address).call();
if(!validRequest){
console.warn(record.address + "-" + record.code + " : INVALID REQUEST");
return;
}
// Add code to db to indicate that we're processing it
await transactionStore.put(record.code, record);
// Execute the contract function
const receipt = await contract.methods.processRequest(record.proof, record.code, record.address).send();
// Update the db with the transaction hash
record.transactionHash = receipt.transactionHash;
await transactionStore.put(record.code, record);
});
// Wait for all promises to be resolved
Promise.all(results).then((completed) => {
running = false;
});
}, 20000);
}
events.on('web3:connected', start);

43
test/contract_spec.js Normal file
View File

@ -0,0 +1,43 @@
// /*global contract, config, it, assert*/
/*
const SimpleStorage = require('Embark/contracts/SimpleStorage');
let accounts;
// For documentation please see https://embark.status.im/docs/contracts_testing.html
config({
//deployment: {
// accounts: [
// // you can configure custom accounts with a custom balance
// // see https://embark.status.im/docs/contracts_testing.html#Configuring-accounts
// ]
//},
contracts: {
"SimpleStorage": {
args: [100]
}
}
}, (_err, web3_accounts) => {
accounts = web3_accounts
});
contract("SimpleStorage", function () {
this.timeout(0);
it("should set constructor value", async function () {
let result = await SimpleStorage.methods.storedData().call();
assert.strictEqual(parseInt(result, 10), 100);
});
it("set storage value", async function () {
await SimpleStorage.methods.set(150).send();
let result = await SimpleStorage.methods.get().call();
assert.strictEqual(parseInt(result, 10), 150);
});
it("should have account with balance", async function() {
let balance = await web3.eth.getBalance(accounts[0]);
assert.ok(parseInt(balance, 10) > 0);
});
}
*/