├── .dockerignore
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── Dockerfile
├── README.md
├── build
└── contracts
│ ├── ERC20.json
│ ├── GitToken.json
│ ├── GitTokenLib.json
│ ├── GitTokenRegistry.json
│ ├── Migrations.json
│ ├── Ownable.json
│ └── SafeMath.json
├── contracts
├── ERC20.sol
├── GitToken.sol
├── GitTokenLib.sol
├── GitTokenRegistry.sol
├── Migrations.sol
├── Ownable.sol
└── SafeMath.sol
├── gittoken.config.js
├── migrations
├── 1_initial_migration.js
└── 2_deploy_contracts.js
├── package.json
├── test
├── test_executeBid.js
├── test_initializeAuction.js
├── test_registerToken.js
├── test_rewardContribution.js
├── test_transfer.js
└── test_verifyContributor.js
└── truffle.js
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 |
3 | language: node_js
4 |
5 | node_js:
6 | - "7"
7 |
8 | services:
9 | - docker
10 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
GitToken Contracts Change Log
7 |
8 |
9 |
10 |
11 | ---
12 |
13 | ### DATE: *October 6, 2017*
14 | ### COMMIT: *ff0fb3f097e0edefbf4d7c4e05cd368def47bcfd*
15 | ### VERSION: *0.0.39*
16 |
17 | - Breaking Changes! Removed reward value mappings from GitTokenLib.sol
18 | - Planning to remove auction methods from GitToken.sol & GitTokenLib.sol
19 |
20 | ---
21 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:6.11.0
2 |
3 | RUN npm i -g truffle
4 |
5 | WORKDIR /gittoken-contracts
6 |
7 | ADD . .
8 |
9 | RUN npm install
10 |
11 | CMD ["truffle", "test"]
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | # GitToken Solidity Smart Contracts
15 |
16 | - GitToken.sol
17 | - GitTokenLib.sol
18 | - GitTokenRegistry.sol
19 | - GitTokenAuction.sol (TBW)
20 | - GitTokenExchange.sol (TBW)
21 |
22 |
23 | ## GitToken.sol & GitTokenLib.sol
24 |
25 | The GitToken contracts adhere to the Ethereum ERC20 Standard Token specification.
26 |
27 | The GitToken contracts provide methods for issuing and distributing ERC20 tokens to GitHub contributors in return
28 | for contributions made toward an Organization's repository.
29 |
30 |
31 | ## GitTokenRegistry.sol
32 |
33 | The GitToken Registry maintains a public record of organizations using GitToken contracts.
34 |
35 | Additionally, any GitToken project wanting to use the GitToken Exchange contract must be registered.
36 |
37 |
38 | ## GitTokenAuction.sol (To Be Written)
39 |
40 | ## GitTokenExchange.sol (To Be Written)
41 |
--------------------------------------------------------------------------------
/build/contracts/ERC20.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "ERC20",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "spender",
9 | "type": "address"
10 | },
11 | {
12 | "name": "value",
13 | "type": "uint256"
14 | }
15 | ],
16 | "name": "approve",
17 | "outputs": [],
18 | "payable": false,
19 | "type": "function"
20 | },
21 | {
22 | "constant": false,
23 | "inputs": [
24 | {
25 | "name": "from",
26 | "type": "address"
27 | },
28 | {
29 | "name": "to",
30 | "type": "address"
31 | },
32 | {
33 | "name": "value",
34 | "type": "uint256"
35 | }
36 | ],
37 | "name": "transferFrom",
38 | "outputs": [],
39 | "payable": false,
40 | "type": "function"
41 | },
42 | {
43 | "constant": true,
44 | "inputs": [
45 | {
46 | "name": "who",
47 | "type": "address"
48 | }
49 | ],
50 | "name": "balanceOf",
51 | "outputs": [
52 | {
53 | "name": "",
54 | "type": "uint256"
55 | }
56 | ],
57 | "payable": false,
58 | "type": "function"
59 | },
60 | {
61 | "constant": false,
62 | "inputs": [
63 | {
64 | "name": "to",
65 | "type": "address"
66 | },
67 | {
68 | "name": "value",
69 | "type": "uint256"
70 | }
71 | ],
72 | "name": "transfer",
73 | "outputs": [],
74 | "payable": false,
75 | "type": "function"
76 | },
77 | {
78 | "constant": true,
79 | "inputs": [
80 | {
81 | "name": "owner",
82 | "type": "address"
83 | },
84 | {
85 | "name": "spender",
86 | "type": "address"
87 | }
88 | ],
89 | "name": "allowance",
90 | "outputs": [
91 | {
92 | "name": "",
93 | "type": "uint256"
94 | }
95 | ],
96 | "payable": false,
97 | "type": "function"
98 | }
99 | ],
100 | "unlinked_binary": "0x",
101 | "networks": {},
102 | "schema_version": "0.0.5",
103 | "updated_at": 1505688288331
104 | }
--------------------------------------------------------------------------------
/build/contracts/GitToken.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "GitToken",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "_initialPrice",
9 | "type": "uint256"
10 | },
11 | {
12 | "name": "_delay",
13 | "type": "uint256"
14 | },
15 | {
16 | "name": "_tokenLimitFactor",
17 | "type": "uint256"
18 | },
19 | {
20 | "name": "_lockTokens",
21 | "type": "bool"
22 | }
23 | ],
24 | "name": "initializeAuction",
25 | "outputs": [
26 | {
27 | "name": "",
28 | "type": "bool"
29 | }
30 | ],
31 | "payable": false,
32 | "type": "function"
33 | },
34 | {
35 | "constant": true,
36 | "inputs": [],
37 | "name": "name",
38 | "outputs": [
39 | {
40 | "name": "_name",
41 | "type": "string"
42 | }
43 | ],
44 | "payable": false,
45 | "type": "function"
46 | },
47 | {
48 | "constant": false,
49 | "inputs": [
50 | {
51 | "name": "_spender",
52 | "type": "address"
53 | },
54 | {
55 | "name": "_value",
56 | "type": "uint256"
57 | }
58 | ],
59 | "name": "approve",
60 | "outputs": [
61 | {
62 | "name": "",
63 | "type": "bool"
64 | }
65 | ],
66 | "payable": false,
67 | "type": "function"
68 | },
69 | {
70 | "constant": true,
71 | "inputs": [],
72 | "name": "totalSupply",
73 | "outputs": [
74 | {
75 | "name": "_supply",
76 | "type": "uint256"
77 | }
78 | ],
79 | "payable": false,
80 | "type": "function"
81 | },
82 | {
83 | "constant": true,
84 | "inputs": [
85 | {
86 | "name": "_username",
87 | "type": "string"
88 | }
89 | ],
90 | "name": "getContributorAddress",
91 | "outputs": [
92 | {
93 | "name": "_contributorAddress",
94 | "type": "address"
95 | }
96 | ],
97 | "payable": false,
98 | "type": "function"
99 | },
100 | {
101 | "constant": false,
102 | "inputs": [
103 | {
104 | "name": "_from",
105 | "type": "address"
106 | },
107 | {
108 | "name": "_to",
109 | "type": "address"
110 | },
111 | {
112 | "name": "_value",
113 | "type": "uint256"
114 | }
115 | ],
116 | "name": "transferFrom",
117 | "outputs": [
118 | {
119 | "name": "",
120 | "type": "bool"
121 | }
122 | ],
123 | "payable": false,
124 | "type": "function"
125 | },
126 | {
127 | "constant": true,
128 | "inputs": [],
129 | "name": "organization",
130 | "outputs": [
131 | {
132 | "name": "_organization",
133 | "type": "string"
134 | }
135 | ],
136 | "payable": false,
137 | "type": "function"
138 | },
139 | {
140 | "constant": true,
141 | "inputs": [],
142 | "name": "decimals",
143 | "outputs": [
144 | {
145 | "name": "_decimals",
146 | "type": "uint256"
147 | }
148 | ],
149 | "payable": false,
150 | "type": "function"
151 | },
152 | {
153 | "constant": true,
154 | "inputs": [],
155 | "name": "getTokenLockUntilDate",
156 | "outputs": [
157 | {
158 | "name": "_lockedUntil",
159 | "type": "uint256"
160 | }
161 | ],
162 | "payable": false,
163 | "type": "function"
164 | },
165 | {
166 | "constant": true,
167 | "inputs": [
168 | {
169 | "name": "_contributorAddress",
170 | "type": "address"
171 | }
172 | ],
173 | "name": "getContributorUsername",
174 | "outputs": [
175 | {
176 | "name": "_username",
177 | "type": "string"
178 | }
179 | ],
180 | "payable": false,
181 | "type": "function"
182 | },
183 | {
184 | "constant": false,
185 | "inputs": [
186 | {
187 | "name": "_rewardValue",
188 | "type": "uint256"
189 | },
190 | {
191 | "name": "_rewardType",
192 | "type": "string"
193 | }
194 | ],
195 | "name": "setRewardValue",
196 | "outputs": [
197 | {
198 | "name": "",
199 | "type": "bool"
200 | }
201 | ],
202 | "payable": false,
203 | "type": "function"
204 | },
205 | {
206 | "constant": true,
207 | "inputs": [
208 | {
209 | "name": "",
210 | "type": "address"
211 | }
212 | ],
213 | "name": "owner",
214 | "outputs": [
215 | {
216 | "name": "",
217 | "type": "bool"
218 | }
219 | ],
220 | "payable": false,
221 | "type": "function"
222 | },
223 | {
224 | "constant": true,
225 | "inputs": [
226 | {
227 | "name": "_holder",
228 | "type": "address"
229 | }
230 | ],
231 | "name": "balanceOf",
232 | "outputs": [
233 | {
234 | "name": "_balance",
235 | "type": "uint256"
236 | }
237 | ],
238 | "payable": false,
239 | "type": "function"
240 | },
241 | {
242 | "constant": true,
243 | "inputs": [
244 | {
245 | "name": "_username",
246 | "type": "string"
247 | }
248 | ],
249 | "name": "getUnclaimedRewards",
250 | "outputs": [
251 | {
252 | "name": "_value",
253 | "type": "uint256"
254 | }
255 | ],
256 | "payable": false,
257 | "type": "function"
258 | },
259 | {
260 | "constant": true,
261 | "inputs": [
262 | {
263 | "name": "_rewardType",
264 | "type": "string"
265 | },
266 | {
267 | "name": "_reservedType",
268 | "type": "string"
269 | }
270 | ],
271 | "name": "getRewardDetails",
272 | "outputs": [
273 | {
274 | "name": "_rewardValue",
275 | "type": "uint256"
276 | },
277 | {
278 | "name": "_reservedValue",
279 | "type": "uint256"
280 | }
281 | ],
282 | "payable": false,
283 | "type": "function"
284 | },
285 | {
286 | "constant": true,
287 | "inputs": [],
288 | "name": "symbol",
289 | "outputs": [
290 | {
291 | "name": "_symbol",
292 | "type": "string"
293 | }
294 | ],
295 | "payable": false,
296 | "type": "function"
297 | },
298 | {
299 | "constant": false,
300 | "inputs": [
301 | {
302 | "name": "_to",
303 | "type": "address"
304 | },
305 | {
306 | "name": "_value",
307 | "type": "uint256"
308 | }
309 | ],
310 | "name": "transfer",
311 | "outputs": [
312 | {
313 | "name": "",
314 | "type": "bool"
315 | }
316 | ],
317 | "payable": false,
318 | "type": "function"
319 | },
320 | {
321 | "constant": false,
322 | "inputs": [
323 | {
324 | "name": "_auctionRound",
325 | "type": "uint256"
326 | },
327 | {
328 | "name": "_exchangeRate",
329 | "type": "uint256"
330 | }
331 | ],
332 | "name": "executeBid",
333 | "outputs": [
334 | {
335 | "name": "",
336 | "type": "bool"
337 | }
338 | ],
339 | "payable": true,
340 | "type": "function"
341 | },
342 | {
343 | "constant": true,
344 | "inputs": [],
345 | "name": "getAuctionRound",
346 | "outputs": [
347 | {
348 | "name": "",
349 | "type": "uint256"
350 | }
351 | ],
352 | "payable": false,
353 | "type": "function"
354 | },
355 | {
356 | "constant": false,
357 | "inputs": [
358 | {
359 | "name": "_reservedValue",
360 | "type": "uint256"
361 | },
362 | {
363 | "name": "_rewardType",
364 | "type": "string"
365 | },
366 | {
367 | "name": "_reservedType",
368 | "type": "string"
369 | }
370 | ],
371 | "name": "setReservedValue",
372 | "outputs": [
373 | {
374 | "name": "",
375 | "type": "bool"
376 | }
377 | ],
378 | "payable": false,
379 | "type": "function"
380 | },
381 | {
382 | "constant": false,
383 | "inputs": [
384 | {
385 | "name": "_contributor",
386 | "type": "address"
387 | },
388 | {
389 | "name": "_username",
390 | "type": "string"
391 | }
392 | ],
393 | "name": "verifyContributor",
394 | "outputs": [
395 | {
396 | "name": "",
397 | "type": "bool"
398 | }
399 | ],
400 | "payable": false,
401 | "type": "function"
402 | },
403 | {
404 | "constant": true,
405 | "inputs": [
406 | {
407 | "name": "_owner",
408 | "type": "address"
409 | },
410 | {
411 | "name": "_spender",
412 | "type": "address"
413 | }
414 | ],
415 | "name": "allowance",
416 | "outputs": [
417 | {
418 | "name": "_allowance",
419 | "type": "uint256"
420 | }
421 | ],
422 | "payable": false,
423 | "type": "function"
424 | },
425 | {
426 | "constant": false,
427 | "inputs": [
428 | {
429 | "name": "_username",
430 | "type": "string"
431 | },
432 | {
433 | "name": "_rewardType",
434 | "type": "string"
435 | },
436 | {
437 | "name": "_reservedType",
438 | "type": "string"
439 | },
440 | {
441 | "name": "_rewardBonus",
442 | "type": "uint256"
443 | },
444 | {
445 | "name": "_deliveryID",
446 | "type": "string"
447 | }
448 | ],
449 | "name": "rewardContributor",
450 | "outputs": [
451 | {
452 | "name": "",
453 | "type": "bool"
454 | }
455 | ],
456 | "payable": false,
457 | "type": "function"
458 | },
459 | {
460 | "constant": true,
461 | "inputs": [
462 | {
463 | "name": "auctionRound",
464 | "type": "uint256"
465 | }
466 | ],
467 | "name": "getAuctionDetails",
468 | "outputs": [
469 | {
470 | "name": "",
471 | "type": "uint256[11]"
472 | },
473 | {
474 | "name": "",
475 | "type": "uint256[]"
476 | },
477 | {
478 | "name": "",
479 | "type": "uint256[]"
480 | }
481 | ],
482 | "payable": false,
483 | "type": "function"
484 | },
485 | {
486 | "constant": false,
487 | "inputs": [
488 | {
489 | "name": "newOwner",
490 | "type": "address"
491 | }
492 | ],
493 | "name": "transferOwnership",
494 | "outputs": [],
495 | "payable": false,
496 | "type": "function"
497 | },
498 | {
499 | "inputs": [
500 | {
501 | "name": "_contributor",
502 | "type": "address"
503 | },
504 | {
505 | "name": "_name",
506 | "type": "string"
507 | },
508 | {
509 | "name": "_username",
510 | "type": "string"
511 | },
512 | {
513 | "name": "_organization",
514 | "type": "string"
515 | },
516 | {
517 | "name": "_symbol",
518 | "type": "string"
519 | },
520 | {
521 | "name": "_decimals",
522 | "type": "uint256"
523 | }
524 | ],
525 | "payable": false,
526 | "type": "constructor"
527 | },
528 | {
529 | "payable": false,
530 | "type": "fallback"
531 | },
532 | {
533 | "anonymous": false,
534 | "inputs": [
535 | {
536 | "indexed": true,
537 | "name": "owner",
538 | "type": "address"
539 | },
540 | {
541 | "indexed": true,
542 | "name": "spender",
543 | "type": "address"
544 | },
545 | {
546 | "indexed": false,
547 | "name": "value",
548 | "type": "uint256"
549 | }
550 | ],
551 | "name": "Approval",
552 | "type": "event"
553 | },
554 | {
555 | "anonymous": false,
556 | "inputs": [
557 | {
558 | "indexed": true,
559 | "name": "from",
560 | "type": "address"
561 | },
562 | {
563 | "indexed": true,
564 | "name": "to",
565 | "type": "address"
566 | },
567 | {
568 | "indexed": false,
569 | "name": "value",
570 | "type": "uint256"
571 | }
572 | ],
573 | "name": "Transfer",
574 | "type": "event"
575 | },
576 | {
577 | "anonymous": false,
578 | "inputs": [
579 | {
580 | "indexed": true,
581 | "name": "contributor",
582 | "type": "address"
583 | },
584 | {
585 | "indexed": false,
586 | "name": "username",
587 | "type": "string"
588 | },
589 | {
590 | "indexed": false,
591 | "name": "value",
592 | "type": "uint256"
593 | },
594 | {
595 | "indexed": false,
596 | "name": "reservedValue",
597 | "type": "uint256"
598 | },
599 | {
600 | "indexed": false,
601 | "name": "date",
602 | "type": "uint256"
603 | },
604 | {
605 | "indexed": false,
606 | "name": "rewardType",
607 | "type": "string"
608 | },
609 | {
610 | "indexed": false,
611 | "name": "reservedType",
612 | "type": "string"
613 | }
614 | ],
615 | "name": "Contribution",
616 | "type": "event"
617 | },
618 | {
619 | "anonymous": false,
620 | "inputs": [
621 | {
622 | "indexed": true,
623 | "name": "contributor",
624 | "type": "address"
625 | },
626 | {
627 | "indexed": false,
628 | "name": "username",
629 | "type": "string"
630 | },
631 | {
632 | "indexed": false,
633 | "name": "date",
634 | "type": "uint256"
635 | }
636 | ],
637 | "name": "ContributorVerified",
638 | "type": "event"
639 | },
640 | {
641 | "anonymous": false,
642 | "inputs": [
643 | {
644 | "indexed": false,
645 | "name": "rewardType",
646 | "type": "string"
647 | },
648 | {
649 | "indexed": false,
650 | "name": "reservedType",
651 | "type": "string"
652 | },
653 | {
654 | "indexed": false,
655 | "name": "value",
656 | "type": "uint256"
657 | },
658 | {
659 | "indexed": false,
660 | "name": "date",
661 | "type": "uint256"
662 | }
663 | ],
664 | "name": "RewardValueSet",
665 | "type": "event"
666 | },
667 | {
668 | "anonymous": false,
669 | "inputs": [
670 | {
671 | "indexed": false,
672 | "name": "auctionDetails",
673 | "type": "uint256[8]"
674 | }
675 | ],
676 | "name": "Auction",
677 | "type": "event"
678 | },
679 | {
680 | "anonymous": false,
681 | "inputs": [
682 | {
683 | "indexed": false,
684 | "name": "bidDetails",
685 | "type": "uint256[9]"
686 | }
687 | ],
688 | "name": "AuctionBid",
689 | "type": "event"
690 | }
691 | ],
692 | "unlinked_binary": "0x606060405234156200001057600080fd5b604051620040473803806200404783398101604052808051919060200180518201919060200180518201919060200180518201919060200180518201919060200180519150505b5b600160a060020a0333166000908152602081905260409020805460ff191660011790555b600160a060020a038616156200015457600160a060020a038616600090815260208181526040808320805460ff19166001179055600b9091529020848051620000ca92916020019062000c55565b5085600c856040518082805190602001908083835b602083106200010157805182525b601f199092019160209182019101620000df565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040519081900390208054600160a060020a031916600160a060020a03929092169190911790555b600060015560038580516200016e92916020019062000c55565b5060048380516200018492916020019062000c55565b5060058280516200019a92916020019062000c55565b5060028190556000600a6040517f6f7267616e697a6174696f6e00000000000000000000000000000000000000008152600c810191909152602c0160405180910390206040517f6d656d6265725f696e76697465640000000000000000000000000000000000008152600e810191909152602e0160405180910390208190555080600a0a613a980260016009016040517f6f7267616e697a6174696f6e00000000000000000000000000000000000000008152600c810191909152602c0160405180910390206040517f6d656d6265725f616464656400000000000000000000000000000000000000008152600c810191909152602c01604051908190039020556109c4600a82900a0260096040517f70696e6700000000000000000000000000000000000000000000000000000000815260048101919091526024016040519081900390205560fa600a82900a0260096040517f636f6d6d69745f636f6d6d656e740000000000000000000000000000000000008152600e810191909152602e01604051908190039020556109c4600a82900a0260096040517f63726561746500000000000000000000000000000000000000000000000000008152600681019190915260260160405190819003902055600060096040517f64656c65746500000000000000000000000000000000000000000000000000008152600681019190915260260160405190819003902055611388600a82900a0260096040517f6465706c6f796d656e74000000000000000000000000000000000000000000008152600a810191909152602a01604051908190039020556064600a82900a0260096040517f6465706c6f796d656e745f7374617475730000000000000000000000000000008152601181019190915260310160405190819003902055611388600a82900a0260096040517f666f726b0000000000000000000000000000000000000000000000000000000081526004810191909152602401604051908190039020556064600a82900a0260096040517f676f6c6c756d0000000000000000000000000000000000000000000000000000815260068101919091526026016040519081900390205560fa600a82900a0260096040517f696e7374616c6c6174696f6e00000000000000000000000000000000000000008152600c810191909152602c01604051908190039020556103e8600a82900a0260096040517f696e7374616c6c6174696f6e5f7265706f7369746f7269657300000000000000815260198101919091526039016040519081900390205560fa600a82900a0260096040517f69737375655f636f6d6d656e74000000000000000000000000000000000000008152600d810191909152602d01604051908190039020556101f4600a82900a0260096040517f697373756573000000000000000000000000000000000000000000000000000081526006810191909152602601604051908190039020556064600a82900a0260096040517f6c6162656c0000000000000000000000000000000000000000000000000000008152600581019190915260250160405190819003902055600060096040517f6d61726b6574706c6163655f707572636861736573000000000000000000000081526015810191909152603501604051908190039020556103e8600a82900a0260096040517f6d656d626572000000000000000000000000000000000000000000000000000081526006810191909152602601604051908190039020556103e8600a82900a0260096040517f6d656d62657273686970000000000000000000000000000000000000000000008152600a810191909152602a016040519081900390205560fa600a82900a0260096040517f6d696c6573746f6e65000000000000000000000000000000000000000000000081526009810191909152602901604051908190039020556103e8600a82900a0260096040517f6f7267616e697a6174696f6e00000000000000000000000000000000000000008152600c810191909152602c0160405190819003902055600060096040517f6f72675f626c6f636b000000000000000000000000000000000000000000000081526009810191909152602901604051908190039020556101f4600a82900a0260096040517f706167655f6275696c64000000000000000000000000000000000000000000008152600a810191909152602a016040519081900390205560fa600a82900a0260096040517f70726f6a6563745f6361726400000000000000000000000000000000000000008152600c810191909152602c01604051908190039020556032600a82900a0260096040517f70726f6a6563745f636f6c756d6e0000000000000000000000000000000000008152600e810191909152602e01604051908190039020556103e8600a82900a0260096040517f70726f6a656374000000000000000000000000000000000000000000000000008152600781019190915260270160405190819003902055612710600a82900a0260096040517f7075626c69630000000000000000000000000000000000000000000000000000815260068101919091526026016040519081900390205560fa600a82900a0260096040517f70756c6c5f726571756573745f7265766965775f636f6d6d656e7400000000008152601b810191909152603b016040519081900390205560fa600a82900a0260096040517f70756c6c5f726571756573745f7265766965770000000000000000000000000081526013810191909152603301604051908190039020556109c4600a82900a0260096040517f70756c6c5f7265717565737400000000000000000000000000000000000000008152600c810191909152602c01604051908190039020556103e8600a82900a0260096040517f707573680000000000000000000000000000000000000000000000000000000081526004810191909152602401604051908190039020556109c4600a82900a0260096040517f7265706f7369746f7279000000000000000000000000000000000000000000008152600a810191909152602a0160405190819003902055611388600a82900a0260096040517f72656c6561736500000000000000000000000000000000000000000000000000815260078101919091526027016040519081900390205560c8600a82900a0260096040517f737461747573000000000000000000000000000000000000000000000000000081526006810191909152602601604051908190039020556107d0600a82900a0260096040517f7465616d0000000000000000000000000000000000000000000000000000000081526004810191909152602401604051908190039020556107d0600a82900a0260096040517f7465616d5f61646400000000000000000000000000000000000000000000000081526008810191909152602801604051908190039020556064600a82900a0260096040517f77617463680000000000000000000000000000000000000000000000000000008152600581019190915260250160405180910390208190555080600a0a619c400260016009016040517f6d696c6573746f6e6500000000000000000000000000000000000000000000008152600981019190915260290160405180910390206040517f636c6f736564000000000000000000000000000000000000000000000000000081526006810191909152602601604051908190039020555b50505050505062000cff565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062000c9857805160ff191683800117855562000cc8565b8280016001018555821562000cc8579182015b8281111562000cc857825182559160200191906001019062000cab565b5b5062000cd792915062000cdb565b5090565b62000cfc91905b8082111562000cd7576000815560010162000ce2565b5090565b90565b6133388062000d0f6000396000f300606060405236156101465763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166302439dde811461015957806306fdde031461018e578063095ea7b31461021957806318160ddd1461024f5780631e923ded1461027457806323b872dd146102e157806323bd4d7a1461031d578063313ce567146103a857806355d67427146103cd57806355ded44d146103f257806366253c4414610489578063666e1b39146104f357806370a082311461052657806376500a7e1461055757806392956c1e146105ba57806395d89b4114610665578063a9059cbb146106f0578063a9c7c53614610726578063b763831c14610748578063cdf25db31461076d578063d85600ca14610819578063dd62ed3e1461088c578063e9dc1a95146108c3578063f20e5e35146109f7578063f2fde38b14610ad3575b341561015157600080fd5b5b600080fd5b005b341561016457600080fd5b61017a6004356024356044356064351515610af4565b604051901515815260200160405180910390f35b341561019957600080fd5b6101a1610b96565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156101de5780820151818401525b6020016101c5565b50505050905090810190601f16801561020b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561022457600080fd5b61017a600160a060020a0360043516602435610c40565b604051901515815260200160405180910390f35b341561025a57600080fd5b610262610cf6565b60405190815260200160405180910390f35b341561027f57600080fd5b6102c560046024813581810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610cfd95505050505050565b604051600160a060020a03909116815260200160405180910390f35b34156102ec57600080fd5b61017a600160a060020a0360043581169060243516604435610d78565b604051901515815260200160405180910390f35b341561032857600080fd5b6101a1610e0c565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156101de5780820151818401525b6020016101c5565b50505050905090810190601f16801561020b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103b357600080fd5b610262610eb6565b60405190815260200160405180910390f35b34156103d857600080fd5b610262610ebd565b60405190815260200160405180910390f35b34156103fd57600080fd5b6101a1600160a060020a0360043516610ec4565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156101de5780820151818401525b6020016101c5565b50505050905090810190601f16801561020b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561049457600080fd5b61017a600480359060446024803590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610f9595505050505050565b604051901515815260200160405180910390f35b34156104fe57600080fd5b61017a600160a060020a03600435166110ea565b604051901515815260200160405180910390f35b341561053157600080fd5b610262600160a060020a03600435166110ff565b60405190815260200160405180910390f35b341561056257600080fd5b61026260046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061111e95505050505050565b60405190815260200160405180910390f35b34156105c557600080fd5b61064d60046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284378201915050505050509190803590602001908201803590602001908080601f01602080910402602001604051908101604052818152929190602084018383808284375094965061118f95505050505050565b60405191825260208201526040908101905180910390f35b341561067057600080fd5b6101a16112d1565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156101de5780820151818401525b6020016101c5565b50505050905090810190601f16801561020b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156106fb57600080fd5b61017a600160a060020a036004351660243561137b565b604051901515815260200160405180910390f35b61017a6004356024356113fb565b604051901515815260200160405180910390f35b341561075357600080fd5b610262611473565b60405190815260200160405180910390f35b341561077857600080fd5b61017a600480359060446024803590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284378201915050505050509190803590602001908201803590602001908080601f01602080910402602001604051908101604052818152929190602084018383808284375094965061147a95505050505050565b604051901515815260200160405180910390f35b341561082457600080fd5b61017a60048035600160a060020a03169060446024803590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061168f95505050505050565b604051901515815260200160405180910390f35b341561089757600080fd5b610262600160a060020a036004358116906024351661178a565b60405190815260200160405180910390f35b34156108ce57600080fd5b61017a60046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284378201915050505050509190803590602001908201803590602001908080601f01602080910402602001604051908101604052818152929190602084018383808284378201915050505050509190803590602001908201803590602001908080601f01602080910402602001604051908101604052818152929190602084018383808284378201915050505050509190803590602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405281815292919060208401838380828437509496506117b795505050505050565b604051901515815260200160405180910390f35b3415610a0257600080fd5b610a0d600435611b46565b604051808461016080838360005b83811015610a345780820151818401525b602001610a1b565b505050509050018060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610a7c5780820151818401525b602001610a63565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610abc5780820151818401525b602001610aa3565b505050509050019550505050505060405180910390f35b3415610ade57600080fd5b610157600160a060020a0360043516611ca5565b005b600160a060020a03331660009081526020819052604081205460ff161515610b1b57600080fd5b7ff2c93682ed3c2de57c1a5b8d87987bc473b3c43950036e9b69234c19b24473ea610b5060018787878763ffffffff611d2b16565b604051808261010080838360005b83811015610b775780820151818401525b602001610b5e565b5050505090500191505060405180910390a15060015b5b949350505050565b610b9e6131a6565b60038054600260001961010060018416150201909116046020601f82018190048102016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c355780601f10610c0a57610100808354040283529160200191610c35565b820191906000526020600020905b815481529060010190602001808311610c1857829003601f168201915b505050505090505b90565b6000600236604414610c5157600080fd5b82158015610c825750600160a060020a033381166000908152600d6020908152604080832093881683529290522054155b1515610c8d57600080fd5b600160a060020a033381166000818152600d6020908152604080832094891680845294909152908190208690557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259086905190815260200160405180910390a35b5b5092915050565b6001545b90565b6000600c826040518082805190602001908083835b60208310610d3257805182525b601f199092019160209182019101610d12565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902054600160a060020a031690505b919050565b6007546000904211610d8957600080fd5b600336606414610d9857600080fd5b610dab600186868663ffffffff611fb916565b1515610db657600080fd5b83600160a060020a031685600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8560405190815260200160405180910390a3600191505b5b505b9392505050565b610e146131a6565b60048054600260001961010060018416150201909116046020601f82018190048102016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c355780601f10610c0a57610100808354040283529160200191610c35565b820191906000526020600020905b815481529060010190602001808311610c1857829003601f168201915b505050505090505b90565b6002545b90565b6007545b90565b610ecc6131a6565b6001600a01600083600160a060020a0316600160a060020a031681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610f885780601f10610f5d57610100808354040283529160200191610f88565b820191906000526020600020905b815481529060010190602001808311610f6b57829003601f168201915b505050505090505b919050565b600160a060020a03331660009081526020819052604081205460ff161515610fbc57600080fd5b826009836040518082805190602001908083835b60208310610ff057805182525b601f199092019160209182019101610fd0565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051908190039020557fbab878453bea46cf2222f6dd20b3fa8d80dc6ca2b5d4f854173f07227a21e1a6828442604051808060200180602001858152602001848152602001838103835286818151815260200191508051906020019080838360005b838110156110975780820151818401525b60200161107e565b50505050905090810190601f1680156110c45780820380516001836020036101000a031916815260200191505b5092830390525060008152604090810193509150505180910390a15060015b5b92915050565b60006020819052908152604090205460ff1681565b600160a060020a0381166000908152600e60205260409020545b919050565b6000600f826040518082805190602001908083835b6020831061115357805182525b601f199092019160209182019101611133565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390205490505b919050565b6000806009846040518082805190602001908083835b602083106111c557805182525b601f1990920191602091820191016111a5565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902054600a856040518082805190602001908083835b6020831061122d57805182525b601f19909201916020918201910161120d565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020846040518082805190602001908083835b6020831061129157805182525b601f199092019160209182019101611271565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902054915091505b9250929050565b6112d96131a6565b60058054600260001961010060018416150201909116046020601f82018190048102016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c355780601f10610c0a57610100808354040283529160200191610c35565b820191906000526020600020905b815481529060010190602001808311610c1857829003601f168201915b505050505090505b90565b600754600090421161138c57600080fd5b61139e6001848463ffffffff61209e16565b15156113a957600080fd5b82600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405190815260200160405180910390a35060015b5b92915050565b60007f71e9115058326fa6f488debb25321c912f2e9df24f42a99f4a976822672ffee46114306001858563ffffffff61212616565b604051808261012080838360005b838110156114575780820151818401525b60200161143e565b5050505090500191505060405180910390a15060015b92915050565b6006545b90565b600160a060020a03331660009081526020819052604081205460ff1615156114a157600080fd5b83600a846040518082805190602001908083835b602083106114d557805182525b601f1990920191602091820191016114b5565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020836040518082805190602001908083835b6020831061153957805182525b601f199092019160209182019101611519565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051908190039020557fbab878453bea46cf2222f6dd20b3fa8d80dc6ca2b5d4f854173f07227a21e1a683838642604051808060200180602001858152602001848152602001838103835287818151815260200191508051906020019080838360005b838110156115e15780820151818401525b6020016115c8565b50505050905090810190601f16801561160e5780820380516001836020036101000a031916815260200191505b50838103825286818151815260200191508051906020019080838360005b838110156116455780820151818401525b60200161162c565b50505050905090810190601f1680156116725780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a15060015b5b9392505050565b600160a060020a03331660009081526020819052604081205460ff1615156116b657600080fd5b6116c86001848463ffffffff61260d16565b15156116d357600080fd5b82600160a060020a03167fce96c271d8db9db4a90e538f30d7ec5a63f116893c4636688d9ce1502b5cc93683426040518080602001838152602001828103825284818151815260200191508051906020019080838360005b838110156117445780820151818401525b60200161172b565b50505050905090810190601f1680156117715780820380516001836020036101000a031916815260200191505b50935050505060405180910390a25060015b5b92915050565b600160a060020a038083166000908152600d60209081526040808320938516835292905220545b92915050565b600160a060020a03331660009081526020819052604081205460ff1615156117de57600080fd5b6117f36001878787878763ffffffff612b9216565b15156117fe57600080fd5b600c866040518082805190602001908083835b6020831061183157805182525b601f199092019160209182019101611811565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902054600160a060020a03167f40845d10695c318fe58c5b13b891c915e95824c7439f3e860354267b1cf5c41a876119098660098a6040518082805190602001908083835b602083106118c857805182525b601f1990920191602091820191016118a8565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051908190039020549063ffffffff61301d16565b600a896040518082805190602001908083835b6020831061193c57805182525b601f19909201916020918201910161191c565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020886040518082805190602001908083835b602083106119a057805182525b601f199092019160209182019101611980565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902054428a8a6040518080602001878152602001868152602001858152602001806020018060200184810384528a818151815260200191508051906020019080838360005b83811015611a2f5780820151818401525b602001611a16565b50505050905090810190601f168015611a5c5780820380516001836020036101000a031916815260200191505b50848103835286818151815260200191508051906020019080838360005b83811015611a935780820151818401525b602001611a7a565b50505050905090810190601f168015611ac05780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b83811015611af75780820151818401525b602001611ade565b50505050905090810190601f168015611b245780820380516001836020036101000a031916815260200191505b50995050505050505050505060405180910390a25060015b5b95945050505050565b611b4e6131b8565b611b566131a6565b611b5e6131a6565b6101606040519081016040908152600086815260086020818152838320805486526001810154828701526002810154858701526003810154606087015260048101546080870152600581015460a0870152600681015460c0870152600781015460e0870152808301546101008701526009810154610120870152600a81015461014087015292899052908152600b820180549093600c909301928492828102019051908101604052809291908181526020018280548015611c3e57602002820191906000526020600020905b815481526020019060010190808311611c2a575b5050505050915080805480602002602001604051908101604052809291908181526020018280548015611c9057602002820191906000526020600020905b815481526020019060010190808311611c7c575b505050505090509250925092505b9193909250565b600160a060020a03331660009081526020819052604090205460ff161515611ccc57600080fd5b600160a060020a03811660009081526020819052604090205460ff161515611d2657600160a060020a03808216600090815260208190526040808220805460ff199081166001179091553390931682529020805490911690555b5b5b50565b611d336131f2565b600160a060020a0330166000908152600d87016020526040812054819011611d5a57600080fd5b60008611611d6757600080fd5b600160a060020a0330166000908152600d88016020526040902054861115611d8e57600080fd5b6005870154611da490600163ffffffff61301d16565b600588015560008511611dba576203f480611dbc565b845b6005880154600081815260078a0160205260409020559050611de4428263ffffffff61301d16565b600588018054600090815260078a01602052604080822060019081019490945591548152200154611e1b908263ffffffff61301d16565b6005808901805460009081526007808c016020818152604080852060020197909755600160a060020a0330168452600d8e018152868420548554855291905285832060040155825482528482209093018a90558154815283812060060181905590548152918220015585670de0b6b3a7640000811515611e9757fe5b30600160a060020a03166000908152600d8a01602090815260408083205460058d018054855260078e019093528184209590940490930260089094019390935582548152818120600901819055915482529020600a01849055821515600114611f0857600087600601819055611f39565b60058701546000908152600788016020526040902060020154611f31908263ffffffff61301d16565b876006018190555b5061010060405190810160409081526005808a0154808452600081815260078c01602081815285832060018101548289015260028101549688019690965260068e01546060880152600486015460808801529385015460a0870152600885015460c08701529190529052600a015460e082015291505b5095945050505050565b600160a060020a038084166000908152600c86016020908152604080832033909416835292905290812054611ff4818463ffffffff61303716565b600160a060020a038087166000908152600c89016020908152604080832033851684528252808320949094559187168152600d8901909152205461203e908463ffffffff61301d16565b600160a060020a038086166000908152600d890160205260408082209390935590871681522054612075908463ffffffff61303716565b600160a060020a0386166000908152600d88016020526040902055600191505b50949350505050565b600160a060020a0333166000908152600d840160205260408120546120c9908363ffffffff61303716565b600160a060020a033381166000908152600d870160205260408082209390935590851681522054612100908363ffffffff61301d16565b600160a060020a0384166000908152600d860160205260409020555060015b9392505050565b61212e61321a565b60008381526007850160205260408120600101548190819081904290111561215557600080fd5b60008781526007890160205260409020600201544290101561217657600080fd5b60008781526007890160205260408120600801541161219457600080fd5b600034116121a157600080fd5b60008781526007890160205260409020600b018054600181016121c48382613242565b916000526020600020900160005b503490555060008781526007890160205260409020600c018054600181016121fa8382613242565b916000526020600020900160005b88909190915055506122ef886007016000898152602001908152602001600020600c0180548060200260200160405190810160405280929190818152602001828054801561227557602002820191906000526020600020905b815481526020019060010190808311612261575b50505050508960070160008a8152602001908152602001600020600b018054806020026020016040519081016040528092919081815260200182805480156122dc57602002820191906000526020600020905b8154815260200190600101908083116122c8575b505050505061304e90919063ffffffff16565b600088815260078a016020526040902060060181905586111561231157600080fd5b60008781526007890160205260409020600a8101546006909101546305f5e100909102908790031061234257600080fd5b60008781526007890160205260409020600a81015460049091015461236c9163ffffffff6130fd16565b600088815260078a016020526040902060060154909450670de0b6b3a764000081151561239557fe5b04840292508234116123a85760006123ac565b8234035b915060008211156123e857600160a060020a03331682156108fc0283604051600060405180830381858888f1935050505015156123e857600080fd5b5b81156123f557826123f7565b345b600088815260078a016020526040902060060154909150670de0b6b3a764000081151561242057fe5b048181151561242b57fe5b60058a015460009081526007808c01602052604090912001549190049450612459908263ffffffff61301d16565b600589015460009081526007808b01602052604080832090910192909255888152206008015461248f908263ffffffff61303716565b600088815260078a016020908152604080832060080193909355600160a060020a0330168252600d8b01905220546124cd908563ffffffff61303716565b600160a060020a033081166000908152600d8b016020526040808220939093553390911681522054612505908563ffffffff61301d16565b600160a060020a0333166000908152600d8a01602090815260408083209390935560058b0154825260078b0190522060040154612548908563ffffffff61303716565b6005890154600090815260078a01602052604080822060040192909255888152206009015461257e90600163ffffffff61301d16565b600088815260078a016020526040908190206009019190915561012090519081016040908152888252602080830189905260008a81526007808d01808452848320600681015495870195909552606086018a90526080860187905260a086018890529084015460c0860152908b905290526008015460e08201524261010082015294505b505050509392505050565b6000600160a060020a038316151561262457600080fd5b600084600e01836040518082805190602001908083835b6020831061265b57805182525b601f19909201916020918201910161263b565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390205411156127b85761272984600e01836040518082805190602001908083835b602083106126cd57805182525b601f1990920191602091820191016126ad565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902054600160a060020a0385166000908152600d870160205260409020549063ffffffff61301d16565b600160a060020a0384166000908152600d860160205260408082209290925590600e8601908490518082805190602001908083835b6020831061277e57805182525b601f19909201916020918201910161275e565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902055612b86565b82600160a060020a031684600b01836040518082805190602001908083835b602083106127f757805182525b601f1990920191602091820191016127d7565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902054600160a060020a0316148015906128cc5750600084600d01600086600b01856040518082805190602001908083835b6020831061287b57805182525b601f19909201916020918201910161285b565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902054600160a060020a03168152602081019190915260400160002054115b15612ac457600160a060020a0383166000908152600a8501602052604090208280516128fc92916020019061326c565b508284600b01836040518082805190602001908083835b6020831061293357805182525b601f199092019160209182019101612913565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051908190039020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055600d84016000600b8601846040518082805190602001908083835b602083106129cd57805182525b601f1990920191602091820191016129ad565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902054600160a060020a03908116825260208083019390935260409182016000908120549187168152600d8801938490528281209190915591908290600b8801908690518082805190602001908083835b60208310612a7057805182525b601f199092019160209182019101612a50565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902054600160a060020a03168152602081019190915260400160002055612b86565b600160a060020a0383166000908152600a850160205260409020828051612aef92916020019061326c565b508284600b01836040518082805190602001908083835b60208310612b2657805182525b601f199092019160209182019101612b06565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051908190039020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790555b5b5060015b9392505050565b600080600080612c12868b6008018a6040518082805190602001908083835b602083106118c857805182525b601f1990920191602091820191016118a8565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051908190039020549063ffffffff61301d16565b925089600901886040518082805190602001908083835b60208310612c4957805182525b601f199092019160209182019101612c29565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020876040518082805190602001908083835b60208310612cad57805182525b601f199092019160209182019101612c8d565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902054915089600b01896040518082805190602001908083835b60208310612d1857805182525b601f199092019160209182019101612cf8565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902054600160a060020a031690506000831180612d675750600082115b1515612d7257600080fd5b89600f01856040518082805190602001908083835b60208310612da757805182525b601f199092019160209182019101612d87565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040519081900390205460ff1615612de957600080fd5b8954612e0d908390612e01908663ffffffff61301d16565b9063ffffffff61301d16565b8a55600160a060020a0330166000908152600d8b016020526040902054612e3a908363ffffffff61301d16565b600160a060020a033081166000908152600d8d01602052604090209190915581161515612f4a57612edb838b600e018b6040518082805190602001908083835b602083106118c857805182525b601f1990920191602091820191016118a8565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051908190039020549063ffffffff61301d16565b8a600e018a6040518082805190602001908083835b60208310612f1057805182525b601f199092019160209182019101612ef0565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405190819003902055612f91565b600160a060020a0381166000908152600d8b016020526040902054612f75908463ffffffff61301d16565b600160a060020a0382166000908152600d8c0160205260409020555b60018a600f01866040518082805190602001908083835b60208310612fc857805182525b601f199092019160209182019101612fa8565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051908190039020805460ff1916911515919091179055600193505b5050509695505050505050565b60008282018381101561302c57fe5b8091505b5092915050565b60008282111561304357fe5b508082035b92915050565b600080600080600080600087511161306257fe5b600088511161306d57fe5b61307688613119565b945060009350600092505b86518310156130e45787838151811061309657fe5b9060200190602002015191508683815181106130ae57fe5b9060200190602002015190506130d6846130d16130cb8585613177565b886130fd565b61301d565b93505b600190920191613081565b600084116130ee57fe5b8395505b505050505092915050565b600080828481151561310b57fe5b0490508091505b5092915050565b60008060008084511161312857fe5b5060009050805b8351811015613162576131578285838151811061314857fe5b9060200190602002015161301d565b91505b60010161312f565b6000821161316c57fe5b8192505b5050919050565b6000828202831580613193575082848281151561319057fe5b04145b151561302c57fe5b8091505b5092915050565b60206040519081016040526000815290565b610160604051908101604052600b815b60008152602001906001900390816131c85790505090565b60206040519081016040526000815290565b6101006040519081016040526008815b60008152602001906001900390816131c85790505090565b6101206040519081016040526009815b60008152602001906001900390816131c85790505090565b815481835581811511613266576000838152602090206132669181019083016132eb565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106132ad57805160ff19168380011785556132da565b828001600101855582156132da579182015b828111156132da5782518255916020019190600101906132bf565b5b506132e79291506132eb565b5090565b610c3d91905b808211156132e757600081556001016132f1565b5090565b905600a165627a7a723058201326a99708eb5b199e37057cfe120e11a2b3c0b754e7bb9d9092a4f0447fce410029",
693 | "networks": {
694 | "9": {
695 | "events": {
696 | "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": {
697 | "anonymous": false,
698 | "inputs": [
699 | {
700 | "indexed": true,
701 | "name": "owner",
702 | "type": "address"
703 | },
704 | {
705 | "indexed": true,
706 | "name": "spender",
707 | "type": "address"
708 | },
709 | {
710 | "indexed": false,
711 | "name": "value",
712 | "type": "uint256"
713 | }
714 | ],
715 | "name": "Approval",
716 | "type": "event"
717 | },
718 | "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": {
719 | "anonymous": false,
720 | "inputs": [
721 | {
722 | "indexed": true,
723 | "name": "from",
724 | "type": "address"
725 | },
726 | {
727 | "indexed": true,
728 | "name": "to",
729 | "type": "address"
730 | },
731 | {
732 | "indexed": false,
733 | "name": "value",
734 | "type": "uint256"
735 | }
736 | ],
737 | "name": "Transfer",
738 | "type": "event"
739 | },
740 | "0x40845d10695c318fe58c5b13b891c915e95824c7439f3e860354267b1cf5c41a": {
741 | "anonymous": false,
742 | "inputs": [
743 | {
744 | "indexed": true,
745 | "name": "contributor",
746 | "type": "address"
747 | },
748 | {
749 | "indexed": false,
750 | "name": "username",
751 | "type": "string"
752 | },
753 | {
754 | "indexed": false,
755 | "name": "value",
756 | "type": "uint256"
757 | },
758 | {
759 | "indexed": false,
760 | "name": "reservedValue",
761 | "type": "uint256"
762 | },
763 | {
764 | "indexed": false,
765 | "name": "date",
766 | "type": "uint256"
767 | },
768 | {
769 | "indexed": false,
770 | "name": "rewardType",
771 | "type": "string"
772 | },
773 | {
774 | "indexed": false,
775 | "name": "reservedType",
776 | "type": "string"
777 | }
778 | ],
779 | "name": "Contribution",
780 | "type": "event"
781 | },
782 | "0xce96c271d8db9db4a90e538f30d7ec5a63f116893c4636688d9ce1502b5cc936": {
783 | "anonymous": false,
784 | "inputs": [
785 | {
786 | "indexed": true,
787 | "name": "contributor",
788 | "type": "address"
789 | },
790 | {
791 | "indexed": false,
792 | "name": "username",
793 | "type": "string"
794 | },
795 | {
796 | "indexed": false,
797 | "name": "date",
798 | "type": "uint256"
799 | }
800 | ],
801 | "name": "ContributorVerified",
802 | "type": "event"
803 | },
804 | "0xbab878453bea46cf2222f6dd20b3fa8d80dc6ca2b5d4f854173f07227a21e1a6": {
805 | "anonymous": false,
806 | "inputs": [
807 | {
808 | "indexed": false,
809 | "name": "rewardType",
810 | "type": "string"
811 | },
812 | {
813 | "indexed": false,
814 | "name": "reservedType",
815 | "type": "string"
816 | },
817 | {
818 | "indexed": false,
819 | "name": "value",
820 | "type": "uint256"
821 | },
822 | {
823 | "indexed": false,
824 | "name": "date",
825 | "type": "uint256"
826 | }
827 | ],
828 | "name": "RewardValueSet",
829 | "type": "event"
830 | },
831 | "0xf2c93682ed3c2de57c1a5b8d87987bc473b3c43950036e9b69234c19b24473ea": {
832 | "anonymous": false,
833 | "inputs": [
834 | {
835 | "indexed": false,
836 | "name": "auctionDetails",
837 | "type": "uint256[8]"
838 | }
839 | ],
840 | "name": "Auction",
841 | "type": "event"
842 | },
843 | "0x71e9115058326fa6f488debb25321c912f2e9df24f42a99f4a976822672ffee4": {
844 | "anonymous": false,
845 | "inputs": [
846 | {
847 | "indexed": false,
848 | "name": "bidDetails",
849 | "type": "uint256[9]"
850 | }
851 | ],
852 | "name": "AuctionBid",
853 | "type": "event"
854 | }
855 | },
856 | "links": {},
857 | "address": "0xe87b912e97fab3bced7e7672f428086a6359eb9a",
858 | "updated_at": 1505716975895
859 | }
860 | },
861 | "schema_version": "0.0.5",
862 | "updated_at": 1505716975895
863 | }
--------------------------------------------------------------------------------
/build/contracts/GitTokenLib.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "GitTokenLib",
3 | "abi": [],
4 | "unlinked_binary": "0x60606040523415600e57600080fd5b5b603680601c6000396000f30060606040525b600080fd00a165627a7a7230582050fc5dfa876a92106a2b6012a30ff13d147cc0575c34ec4f180e7b88e3af0b3a0029",
5 | "networks": {
6 | "9": {
7 | "events": {},
8 | "links": {},
9 | "address": "0x3f9546fccbc7f23a17d08003a73dcbe98f5d8e99",
10 | "updated_at": 1505716975894
11 | }
12 | },
13 | "schema_version": "0.0.5",
14 | "updated_at": 1507234651297
15 | }
--------------------------------------------------------------------------------
/build/contracts/GitTokenRegistry.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "GitTokenRegistry",
3 | "abi": [
4 | {
5 | "constant": true,
6 | "inputs": [
7 | {
8 | "name": "",
9 | "type": "address"
10 | }
11 | ],
12 | "name": "owner",
13 | "outputs": [
14 | {
15 | "name": "",
16 | "type": "bool"
17 | }
18 | ],
19 | "payable": false,
20 | "type": "function"
21 | },
22 | {
23 | "constant": false,
24 | "inputs": [
25 | {
26 | "name": "_organization",
27 | "type": "string"
28 | },
29 | {
30 | "name": "_token",
31 | "type": "address"
32 | }
33 | ],
34 | "name": "registerToken",
35 | "outputs": [
36 | {
37 | "name": "success",
38 | "type": "bool"
39 | }
40 | ],
41 | "payable": false,
42 | "type": "function"
43 | },
44 | {
45 | "constant": false,
46 | "inputs": [
47 | {
48 | "name": "newOwner",
49 | "type": "address"
50 | }
51 | ],
52 | "name": "transferOwnership",
53 | "outputs": [],
54 | "payable": false,
55 | "type": "function"
56 | },
57 | {
58 | "inputs": [
59 | {
60 | "name": "_owner",
61 | "type": "address"
62 | }
63 | ],
64 | "payable": false,
65 | "type": "constructor"
66 | },
67 | {
68 | "anonymous": false,
69 | "inputs": [
70 | {
71 | "indexed": false,
72 | "name": "_organization",
73 | "type": "string"
74 | },
75 | {
76 | "indexed": false,
77 | "name": "_token",
78 | "type": "address"
79 | },
80 | {
81 | "indexed": false,
82 | "name": "date",
83 | "type": "uint256"
84 | }
85 | ],
86 | "name": "Registration",
87 | "type": "event"
88 | }
89 | ],
90 | "unlinked_binary": "0x6060604052341561000f57600080fd5b6040516020806103b5833981016040528080519150505b5b600160a060020a0333166000908152602081905260409020805460ff191660011790555b6020604051016040908152600160a060020a0382166000908152602081905220805460ff191660011790555b505b61032d806100886000396000f300606060405263ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663666e1b39811461005357806369f667ed14610086578063f2fde38b146100f6575b600080fd5b341561005e57600080fd5b610072600160a060020a0360043516610117565b604051901515815260200160405180910390f35b341561009157600080fd5b61007260046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965050509235600160a060020a0316925061012c915050565b604051901515815260200160405180910390f35b341561010157600080fd5b610115600160a060020a036004351661027b565b005b60006020819052908152604090205460ff1681565b6000816001846040518082805190602001908083835b6020831061016257805182525b601f199092019160209182019101610142565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051908190039020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790557f9556c7df9ca896095f13e5a9d68dd39df7400ebb44dd9f952b14c4e986270ebe838342604051600160a060020a03831660208201526040810182905260608082528190810185818151815260200191508051906020019080838360005b838110156102385780820151818401525b60200161021f565b50505050905090810190601f1680156102655780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a15b92915050565b600160a060020a03331660009081526020819052604090205460ff1615156102a257600080fd5b600160a060020a03811660009081526020819052604090205460ff1615156102fc57600160a060020a03808216600090815260208190526040808220805460ff199081166001179091553390931682529020805490911690555b5b5b505600a165627a7a723058208cba08ba7e8df22798517ebf1a0d8b4a7a4c9f2abae8fab4b40e4f721205b1d20029",
91 | "networks": {},
92 | "schema_version": "0.0.5",
93 | "updated_at": 1505688288337
94 | }
--------------------------------------------------------------------------------
/build/contracts/Migrations.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "Migrations",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "new_address",
9 | "type": "address"
10 | }
11 | ],
12 | "name": "upgrade",
13 | "outputs": [],
14 | "payable": false,
15 | "type": "function"
16 | },
17 | {
18 | "constant": true,
19 | "inputs": [],
20 | "name": "last_completed_migration",
21 | "outputs": [
22 | {
23 | "name": "",
24 | "type": "uint256"
25 | }
26 | ],
27 | "payable": false,
28 | "type": "function"
29 | },
30 | {
31 | "constant": true,
32 | "inputs": [],
33 | "name": "owner",
34 | "outputs": [
35 | {
36 | "name": "",
37 | "type": "address"
38 | }
39 | ],
40 | "payable": false,
41 | "type": "function"
42 | },
43 | {
44 | "constant": false,
45 | "inputs": [
46 | {
47 | "name": "completed",
48 | "type": "uint256"
49 | }
50 | ],
51 | "name": "setCompleted",
52 | "outputs": [],
53 | "payable": false,
54 | "type": "function"
55 | },
56 | {
57 | "inputs": [],
58 | "payable": false,
59 | "type": "constructor"
60 | }
61 | ],
62 | "unlinked_binary": "0x6060604052341561000f57600080fd5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101e58061003c6000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630900f010811461005e578063445df0ac1461007f5780638da5cb5b146100a4578063fdacd576146100d3575b600080fd5b341561006957600080fd5b61007d600160a060020a03600435166100eb565b005b341561008a57600080fd5b610092610182565b60405190815260200160405180910390f35b34156100af57600080fd5b6100b7610188565b604051600160a060020a03909116815260200160405180910390f35b34156100de57600080fd5b61007d600435610197565b005b6000805433600160a060020a039081169116141561017c5781905080600160a060020a031663fdacd5766001546040517c010000000000000000000000000000000000000000000000000000000063ffffffff84160281526004810191909152602401600060405180830381600087803b151561016757600080fd5b6102c65a03f1151561017857600080fd5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a03908116911614156101b45760018190555b5b5b505600a165627a7a723058200513777b7d45afadbfddd9a39c72c1974abdfa735ca91ae97786404710561a8a0029",
63 | "networks": {
64 | "9": {
65 | "events": {},
66 | "links": {},
67 | "address": "0x23b761c6e8ee993df6b887d0a336be3eee0e3718",
68 | "updated_at": 1505716975894
69 | }
70 | },
71 | "schema_version": "0.0.5",
72 | "updated_at": 1505716975894
73 | }
--------------------------------------------------------------------------------
/build/contracts/Ownable.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "Ownable",
3 | "abi": [
4 | {
5 | "constant": true,
6 | "inputs": [
7 | {
8 | "name": "",
9 | "type": "address"
10 | }
11 | ],
12 | "name": "owner",
13 | "outputs": [
14 | {
15 | "name": "",
16 | "type": "bool"
17 | }
18 | ],
19 | "payable": false,
20 | "type": "function"
21 | },
22 | {
23 | "constant": false,
24 | "inputs": [
25 | {
26 | "name": "newOwner",
27 | "type": "address"
28 | }
29 | ],
30 | "name": "transferOwnership",
31 | "outputs": [],
32 | "payable": false,
33 | "type": "function"
34 | },
35 | {
36 | "inputs": [],
37 | "payable": false,
38 | "type": "constructor"
39 | }
40 | ],
41 | "unlinked_binary": "0x6060604052341561000f57600080fd5b5b600160a060020a0333166000908152602081905260409020805460ff191660011790555b5b6101a4806100446000396000f300606060405263ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663666e1b398114610048578063f2fde38b14610088575b600080fd5b341561005357600080fd5b61007473ffffffffffffffffffffffffffffffffffffffff600435166100b6565b604051901515815260200160405180910390f35b341561009357600080fd5b6100b473ffffffffffffffffffffffffffffffffffffffff600435166100cb565b005b60006020819052908152604090205460ff1681565b73ffffffffffffffffffffffffffffffffffffffff331660009081526020819052604090205460ff1615156100ff57600080fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526020819052604090205460ff1615156101735773ffffffffffffffffffffffffffffffffffffffff808216600090815260208190526040808220805460ff199081166001179091553390931682529020805490911690555b5b5b505600a165627a7a723058209818f3db3d9e00685b8bf2ae5aad5bf43d5f2a00ddaa433e087a512923096bf60029",
42 | "networks": {},
43 | "schema_version": "0.0.5",
44 | "updated_at": 1505688288337
45 | }
--------------------------------------------------------------------------------
/build/contracts/SafeMath.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "SafeMath",
3 | "abi": [],
4 | "unlinked_binary": "0x60606040523415600e57600080fd5b5b603680601c6000396000f30060606040525b600080fd00a165627a7a7230582092e219f3a1f83b210559de1291cf1b448ec185de3a38f786b1cf59bcc7f1e7160029",
5 | "networks": {},
6 | "schema_version": "0.0.5",
7 | "updated_at": 1507234651298
8 | }
--------------------------------------------------------------------------------
/contracts/ERC20.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.11;
2 |
3 | /**
4 | * @title ERC20 Interface
5 | * @dev Interface version of ERC20 interface
6 | * @dev see https://github.com/ethereum/EIPs/issues/20
7 | */
8 | contract ERC20 {
9 | function transfer(address to, uint value);
10 | function transferFrom(address from, address to, uint value);
11 | function approve(address spender, uint value);
12 |
13 | function balanceOf(address who) constant returns (uint);
14 | function allowance(address owner, address spender) constant returns (uint);
15 | }
16 |
--------------------------------------------------------------------------------
/contracts/GitToken.sol:
--------------------------------------------------------------------------------
1 | /**
2 | Copyright 2017 GitToken
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of
5 | this software and associated documentation files (the "Software"), to deal in
6 | the Software without restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8 | Software, and to permit persons to whom the Software is furnished to do so,
9 | subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | pragma solidity ^0.4.11;
23 |
24 | import './SafeMath.sol';
25 | import './GitTokenLib.sol';
26 | import './Ownable.sol';
27 |
28 |
29 | /**
30 | * @title GitToken Contract for distributing ERC20 tokens for Git contributions;
31 | * @author Ryan Michael Tate
32 | */
33 | contract GitToken is Ownable {
34 |
35 | using SafeMath for uint;
36 | using GitTokenLib for GitTokenLib.Data;
37 | GitTokenLib.Data gittoken;
38 |
39 | /**
40 | * ERC20 Approval Event | Emitted when a spender is approved by an owner
41 | * @param owner address Ethereum address of owner of tokens,
42 | * @param spender address Ethereum address of approved spender of tokens,
43 | * @param value uint Number of tokens to approve spender for;
44 | */
45 | event Approval(address indexed owner, address indexed spender, uint value);
46 |
47 | /**
48 | * ERC20 Transfer Event | Emitted when a transfer is made between accounts
49 | * @param from address Ethereum address of tokens sent from,
50 | * @param to address Ethereum address of tokens sent to,
51 | * @param value uint Number of tokens to transfer;
52 | */
53 | event Transfer(address indexed from, address indexed to, uint value);
54 |
55 | /**
56 | * Contribution Event | Emitted when a GitHub contribution is broadcasted by web hook,
57 | * @param contributor address Ethereum address of contributor,
58 | * @param username string GitHub username of contributor,
59 | * @param rewardType string GitHub web hook event type (e.g. push, pull_request)
60 | * @param rewardValue uint Number of tokens created and distributed to contributor,
61 | * @param reservedValue uint Number of tokens created and reserved for auction,
62 | * @param date uint Unix timestamp of when the contributor was rewarded,
63 |
64 | */
65 | event Contribution(
66 | address indexed contributor,
67 | string username,
68 | string rewardType,
69 | uint rewardValue,
70 | uint reservedValue,
71 | uint date
72 | );
73 |
74 | /**
75 | * ContributionVerified Event | Emitted when a user verifies themselves on the UI using GitHub OAuth
76 | * @param contributor address Ethereum address of verified contributor,
77 | * @param username string GitHub username associated with contributor Ethereum address,
78 | * @param date uint Unix timestamp when user was verified;
79 | */
80 | event ContributorVerified(address indexed contributor, string username, uint date);
81 |
82 | /* NOTE: Consider removing */
83 | event Auction(uint[8] auctionDetails);
84 | event AuctionBid(uint[9] bidDetails);
85 |
86 |
87 | /**
88 | * @dev Constructor method for GitToken Contract,
89 | * @param _contributor address Ethereum Address of the primary contributor or organization owner,
90 | * @param _username string GitHub username of the primary contributor or organization owner,
91 | * @param _name string Name of the GitToken contract (name of organization),
92 | * @param _organization string GitHub Organization as it appears in the GitHub organization URL (e.g. https://GitHub.com/git-token),
93 | * @param _symbol string Symbol of the GitToken contract,
94 | * @param _decimals uint Number of decimal representation for token balances;
95 | */
96 | function GitToken(
97 | address _contributor,
98 | string _username,
99 | string _name,
100 | string _organization,
101 | string _symbol,
102 | uint _decimals
103 | ) {
104 | if (_contributor != 0x0) {
105 | // Set initial contributor username & address
106 | owner[_contributor] = true;
107 | gittoken.contributorUsernames[_contributor] = _username;
108 | gittoken.contributorAddresses[_username] = _contributor;
109 | }
110 |
111 | gittoken.totalSupply = 0;
112 | gittoken.name = _name;
113 | gittoken.organization = _organization;
114 | gittoken.symbol = _symbol;
115 | gittoken.decimals = _decimals;
116 |
117 | }
118 |
119 | /**
120 | * @dev Returns the current total supply of tokens issued
121 | * @return _supply uint Supply of tokens currently issued
122 | * NOTE: Remember to adjust supply for decimals representation (e.g. supply / 10 ** decimals)
123 | */
124 | function totalSupply() constant returns (uint _supply) {
125 | return gittoken.totalSupply;
126 | }
127 |
128 | /**
129 | * @dev Returns the number of decimal places to adjust token values
130 | * @return _decimals uint Number of decimal places
131 | * NOTE: Remember to adjust token values for decimals representation (e.g. value / 10 ** decimals)
132 | */
133 | function decimals() constant returns (uint _decimals) {
134 | return gittoken.decimals;
135 | }
136 |
137 | /**
138 | * @dev Returns the string of the GitHub organization associated with the contract
139 | * @return _organization string GitHub organization (e.g. git-token)
140 | * NOTE: This value is used to make GitHub API calls; it must be associated with
141 | * the GitHub organization the web hook has been configured for.
142 | */
143 | function organization() constant returns (string _organization) {
144 | return gittoken.organization;
145 | }
146 |
147 | /**
148 | * @dev Returns the string of the token contract name
149 | * @return _name string Name of the token contract
150 | */
151 | function name() constant returns (string _name) {
152 | return gittoken.name;
153 | }
154 |
155 | /**
156 | * @dev Returns the string of the token contract symbol
157 | * @return _symbol string Symbol of the token contract
158 | */
159 | function symbol() constant returns (string _symbol) {
160 | return gittoken.symbol;
161 | }
162 |
163 | /**
164 | * @dev ERC20 `balanceOf` Method | Returns the balance of tokens associated with the address provided
165 | * @param _holder address Ethereum address to find token balance for
166 | * @return _balance uint Value of tokens held by ethereum address
167 | */
168 | function balanceOf(address _holder) constant returns (uint _balance) {
169 | return gittoken.balances[_holder];
170 | }
171 |
172 | /**
173 | * @dev ERC20 `transfer` Method | Transfer tokens to account from sender account
174 | * @param _to address Ethereum address to transfer tokens to,
175 | * @param _value uint Number of tokens to transfer,
176 | * @return bool Returns boolean value if method is called
177 | */
178 | function transfer(
179 | address _to,
180 | uint _value
181 | )
182 | externalTokenTransfersLocked
183 | public
184 | returns (bool)
185 | {
186 | require(gittoken._transfer(_to, _value));
187 | Transfer(msg.sender, _to, _value);
188 | return true;
189 | }
190 |
191 | /**
192 | * @dev ERC20 `transferFrom` Method | Allow approved spender (msg.sender) to transfer tokens from one account to another
193 | * @param _from address Ethereum address to move tokens from,
194 | * @param _to address Ethereum address to move tokens to,
195 | * @param _value uint Number of tokens to move between accounts,
196 | * @return bool Retrusn boolean value if method is called
197 | */
198 | function transferFrom(
199 | address _from,
200 | address _to,
201 | uint _value
202 | )
203 | externalTokenTransfersLocked
204 | public
205 | onlyPayloadSize(3)
206 | returns (bool)
207 | {
208 | require(gittoken._transferFrom(_from, _to, _value));
209 | Transfer(_from, _to, _value);
210 | return true;
211 | }
212 |
213 | /**
214 | * @dev ERC20 `approve` Method | Approve spender to transfer an amount of
215 | * tokens on behalf of another account
216 | * @param _spender address Ethereum address of spender to approve,
217 | * @param _value uint Number of tokens to approve spender to transfer,
218 | * @return bool Returns boolean value is method is called;
219 | * NOTE: Explicitly check if the approved address already has an allowance,
220 | * Ensure the approver must reset the approved value to 0 before changing to the desired amount.
221 | * see: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
222 | */
223 | function approve(
224 | address _spender,
225 | uint _value
226 | )
227 | public
228 | onlyPayloadSize(2)
229 | returns (bool)
230 | {
231 | require(_value == 0 && gittoken.allowed[msg.sender][_spender] == 0);
232 | gittoken.allowed[msg.sender][_spender] = _value;
233 | Approval(msg.sender, _spender, _value);
234 | }
235 |
236 | /**
237 | * @dev ERC20 `allowance` Method | Check the spender allowance for a token owner
238 | * @param _owner address Ethereum address of token owner,
239 | * @param _spender address Ethereum address of spender,
240 | * @return _allowance uint Number of tokens allowed by the owner to be
241 | * moved by the spender
242 | */
243 | function allowance(address _owner, address _spender) constant returns (uint _allowance) {
244 | return gittoken.allowed[_owner][_spender];
245 | }
246 |
247 |
248 | /**
249 | * @dev Verify contributor Ethereum address associated with GitHub username
250 | * @param _contributor address Ethereum address of GitHub organization contributor,
251 | * @param _username string GitHub username of contributor,
252 | * @return bool Returns boolean value if method is called;
253 | */
254 | function verifyContributor(
255 | address _contributor,
256 | string _username
257 | )
258 | onlyOwner
259 | public
260 | returns (bool)
261 | {
262 | require(gittoken._verifyContributor(_contributor, _username));
263 | ContributorVerified(_contributor, _username, now);
264 | return true;
265 | }
266 |
267 | /**
268 | * @dev Reward contributor when a GitHub web hook event is received
269 | * @param _username string GitHub username of contributor
270 | * @param _rewardType string GitHub Event Reward Type
271 | * @param _rewardValue uint Number of tokens rewarded to contributor
272 | * @param _reservedValue uint Number of tokens reserved for auction
273 | * @param _deliveryID string GitHub delivery ID of web hook request
274 | * @return bool Returns boolean value if method is called
275 | */
276 | function rewardContributor(
277 | string _username,
278 | string _rewardType,
279 | uint _rewardValue,
280 | uint _reservedValue,
281 | string _deliveryID
282 | )
283 | onlyOwner
284 | public
285 | returns (bool) {
286 | require(gittoken._rewardContributor(_username, _rewardValue, _reservedValue, _deliveryID));
287 | Contribution(
288 | gittoken.contributorAddresses[_username],
289 | _username,
290 | _rewardType,
291 | _rewardValue,
292 | _reservedValue,
293 | now
294 | );
295 |
296 | return true;
297 | }
298 |
299 | /**
300 | * @dev Initialize Auction & broadcast a NewAuction event
301 | * @param _initialPrice uint Token/ETH Exchange Rate (#Tokens / 1 ETH); adjusted for decimal representation;
302 | * @param _delay uint Time in milliseconds to delay each auction period (I - Pre, II - Start, III - End, IV - Post),
303 | * Must be greater than 86400 (1 day in unix time)
304 | * @param _lockTokens bool Boolean value to optionally lock all token transfers until the Post auction date.
305 | * @return bool Returns Boolean value if called from another contract;
306 | */
307 | function initializeAuction(
308 | uint _initialPrice,
309 | uint _delay,
310 | uint _tokenLimitFactor,
311 | bool _lockTokens
312 | ) onlyOwner public returns (bool) {
313 | Auction(gittoken._initializeAuction(_initialPrice, _delay, _tokenLimitFactor, _lockTokens));
314 | return true;
315 | }
316 |
317 | function executeBid(
318 | uint _auctionRound,
319 | uint _exchangeRate
320 | ) payable public returns (bool) {
321 | AuctionBid(gittoken._executeBid(_auctionRound, _exchangeRate));
322 | return true;
323 | }
324 |
325 | function getAuctionRound() constant returns (uint) {
326 | return gittoken.auctionRound;
327 | }
328 |
329 | function getAuctionDetails(uint auctionRound) constant returns(uint[11], uint[], uint[]) {
330 | return ([
331 | gittoken.auctionDetails[auctionRound].round,
332 | gittoken.auctionDetails[auctionRound].startDate,
333 | gittoken.auctionDetails[auctionRound].endDate,
334 | gittoken.auctionDetails[auctionRound].lockDate,
335 | gittoken.auctionDetails[auctionRound].tokensOffered,
336 | gittoken.auctionDetails[auctionRound].initialPrice,
337 | gittoken.auctionDetails[auctionRound].wtdAvgExRate,
338 | gittoken.auctionDetails[auctionRound].fundsCollected,
339 | gittoken.auctionDetails[auctionRound].fundLimit,
340 | gittoken.auctionDetails[auctionRound].numBids,
341 | gittoken.auctionDetails[auctionRound].tokenLimitFactor
342 | ],
343 | gittoken.auctionDetails[auctionRound].ethValues,
344 | gittoken.auctionDetails[auctionRound].exRateValues
345 | );
346 | }
347 |
348 |
349 | /**
350 | * @dev Get Ethereum address associated with contributor's GitHub username
351 | * @param _username string GitHub username of the contributor,
352 | * @return _contributorAddress address Ethereum address of the contributor associated
353 | * passed in GitHub username;
354 | */
355 | function getContributorAddress(string _username) constant returns (address _contributorAddress) {
356 | return gittoken.contributorAddresses[_username];
357 | }
358 |
359 | /**
360 | * @dev Get GitHub username from contributor's Ethereum address
361 | * @param _contributorAddress address Ethereum address of contributor,
362 | * @return _username string GitHub username associated with contributor address;
363 | */
364 | function getContributorUsername(address _contributorAddress) constant returns (string _username) {
365 | return gittoken.contributorUsernames[_contributorAddress];
366 | }
367 |
368 | /**
369 | * @dev Get the date timestamp of when tokens are locked until
370 | * @return _lockedUntil uint Timestamp of when tokens are locked until
371 | */
372 | function getTokenLockUntilDate() constant returns (uint _lockedUntil) {
373 | return gittoken.lockTokenTransfersUntil;
374 | }
375 |
376 | /**
377 | * @dev Get unclaimed (pre-verified) rewards associated with GitHub username
378 | * @param _username string GitHub username of contributor,
379 | * @return _value uint Number of tokens issued to GitHub username
380 | */
381 | function getUnclaimedRewards(string _username) constant returns (uint _value) {
382 | return gittoken.unclaimedRewards[_username];
383 | }
384 |
385 | function () {
386 | revert();
387 | }
388 |
389 | /**
390 | * @dev This modifier checks the data length to ensure that it matches the padded
391 | * length of the input data provided to the method.
392 | */
393 | modifier onlyPayloadSize(uint inputLength) {
394 | require(msg.data.length == inputLength * 32 + 4);
395 | _;
396 | }
397 |
398 | /**
399 | * @dev Disallow external token transfers if the current timestamp is less
400 | * than the `lockTokenTransfersUntil` date.
401 | * NOTE: Use `getTokenLockUntilDate` method to check date and mitigate
402 | * cost of gas throwing;
403 | */
404 | modifier externalTokenTransfersLocked() {
405 | require(now > gittoken.lockTokenTransfersUntil);
406 | _;
407 | }
408 |
409 |
410 | }
411 |
--------------------------------------------------------------------------------
/contracts/GitTokenLib.sol:
--------------------------------------------------------------------------------
1 | /**
2 | Copyright 2017 GitToken
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of
5 | this software and associated documentation files (the "Software"), to deal in
6 | the Software without restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8 | Software, and to permit persons to whom the Software is furnished to do so,
9 | subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | pragma solidity ^0.4.11;
23 |
24 | import './SafeMath.sol';
25 | /**
26 | * @title GitTokenLib Library for implementing GitToken contract methods
27 | * @author Ryan Michael Tate
28 | */
29 | library GitTokenLib {
30 |
31 | using SafeMath for uint;
32 | using SafeMath for uint[];
33 |
34 | struct Auction {
35 | uint round;
36 | uint startDate;
37 | uint endDate;
38 | uint lockDate;
39 | uint tokensOffered;
40 | uint initialPrice;
41 | uint wtdAvgExRate;
42 | uint fundsCollected;
43 | uint fundLimit;
44 | uint numBids;
45 | uint tokenLimitFactor;
46 | uint[] ethValues;
47 | uint[] exRateValues;
48 | }
49 |
50 | /**
51 | * @dev Data Solidity struct for data storage reference
52 | * @notice totalSupply uint Total supply of tokens issued;
53 | * @notice decimals uint Decimal representation of token values;
54 | * @notice name string Name of token;
55 | * @notice organization string GitHub organization name;
56 | * @notice symbol string Symbol of token;
57 | * @notice rewardValues mapping(string => uint256) Mapping of GitHub web hook
58 | * events to reward values;
59 | * @notice reservedValues mapping(string => mapping(string => uint256)) Double
60 | * mapping of GitHub web hook events and subtypes to reward values;
61 | * @notice contributorUsernames mapping(address => string) Mapping of Ethereum
62 | * addresses to GitHub usernames;
63 | * @notice contributorAddresses mapping(string => address) Mapping of GitHub
64 | * usernames to Ethereum addresses;
65 | * @notice allowed mapping(address => mapping(address => uint)) Double mapping
66 | *of Ethereum address to address of spender of an uint amount of tokens;
67 | * @notice balances mapping(address => uint) Mapping of Ethereum address to an
68 | * amount of tokens held;
69 | * @notice unclaimedRewards mapping(string => uint) Mapping of GitHub usernames
70 | * unclaimed (pre-verified) amount of tokens;
71 | * @notice receivedDelivery mapping(string => bool) Mapping of GitHub delivery
72 | * web hook IDs to boolean values; used to prevent/mitigate replay attack risk;
73 | */
74 | struct Data {
75 | uint totalSupply;
76 | uint decimals;
77 | string name;
78 | string organization;
79 | string symbol;
80 | uint auctionRound;
81 | uint lockTokenTransfersUntil;
82 | mapping(uint => Auction) auctionDetails;
83 | mapping(address => string) contributorUsernames;
84 | mapping(string => address) contributorAddresses;
85 | mapping(address => mapping(address => uint)) allowed;
86 | mapping(address => uint) balances;
87 | mapping(string => uint) unclaimedRewards;
88 | mapping(string => bool) receivedDelivery;
89 | }
90 |
91 |
92 | /**
93 | * @dev Internal transfer method for GitToken ERC20 transfer method
94 | * @param self Data Use the Data struct as the contract storage and reference
95 | * @param _to address Ethereum address of account to transfer tokens to
96 | * @param _value uint Amount of tokens to transfer
97 | * @return bool Returns boolean value when called from the parent contract;
98 | */
99 | function _transfer(Data storage self, address _to, uint _value) internal returns (bool) {
100 | self.balances[msg.sender] = self.balances[msg.sender].sub(_value);
101 | self.balances[_to] = self.balances[_to].add(_value);
102 | return true;
103 | }
104 |
105 | /**
106 | * @dev Internal transferFrom method for GitToken ERC20 transfer method
107 | * @param self Data Use the Data struct as the contract storage and reference
108 | * @param _from address Ethereum address to move tokens from,
109 | * @param _to address Ethereum address to move tokens to,
110 | * @param _value uint Number of tokens to move between accounts,
111 | * @return bool Returns boolean value when called from the parent contract;
112 | */
113 | function _transferFrom(
114 | Data storage self,
115 | address _from,
116 | address _to,
117 | uint _value
118 | ) internal returns (bool) {
119 | // Check if msg.sender has sufficient allowance;
120 | // Check is handled by SafeMath library _allowance.sub(_value);
121 | uint _allowance = self.allowed[_from][msg.sender];
122 | self.allowed[_from][msg.sender] = _allowance.sub(_value);
123 |
124 | // Update balances
125 | self.balances[_to] = self.balances[_to].add(_value);
126 | self.balances[_from] = self.balances[_from].sub(_value);
127 |
128 | return true;
129 | }
130 |
131 | /**
132 | * @dev Internal rewardContributor method for GitToken contract rewardContributor method
133 | * @param self Data Use the Data struct as the contract storage and reference
134 | * @param _username string GitHub username of contributor
135 | * @param _rewardValue uint Number of tokens rewarded to contributor
136 | * @param _reservedValue uint Number of tokens reserved for auction
137 | * @param _deliveryID string GitHub delivery ID of web hook request
138 | * @return bool Returns boolean value when called from the parent contract;
139 | */
140 | function _rewardContributor (
141 | Data storage self,
142 | string _username,
143 | uint _rewardValue,
144 | uint _reservedValue,
145 | string _deliveryID
146 | ) internal returns (bool) {
147 |
148 | // Get the contributor Ethereum address from GitHub username
149 | address _contributor = self.contributorAddresses[_username];
150 |
151 | // If no value is created, then throw the transaction;
152 | require(_rewardValue > 0 || _reservedValue > 0);
153 |
154 | // If the GitHub web hook event ID has already occured, then throw the transaction;
155 | require(self.receivedDelivery[_deliveryID] == false);
156 | // Update totalSupply with the added values created, including the reserved supply for auction;
157 | self.totalSupply = self.totalSupply.add(_rewardValue).add(_reservedValue);
158 |
159 | // Add to the balance of reserved tokens held for auction by the contract
160 | self.balances[address(this)] = self.balances[address(this)].add(_reservedValue);
161 |
162 | // If the contributor is not yet verified, increase the unclaimed rewards for the user until the user verifies herself/himself;
163 | if (_contributor == 0x0){
164 | self.unclaimedRewards[_username] = self.unclaimedRewards[_username].add(_rewardValue);
165 | } else {
166 | // If the contributor's address is set, update the contributor's balance;
167 | self.balances[_contributor] = self.balances[_contributor].add(_rewardValue);
168 | }
169 |
170 | // Set the received deliveries for this event to true to prevent/mitigate event replay attacks;
171 | self.receivedDelivery[_deliveryID] = true;
172 |
173 | // Return true to parent contract
174 | return true;
175 | }
176 |
177 | /**
178 | * @dev Internal method for GitToken contract verifyContributor method
179 | * @param self Data Use the Data struct as the contract storage and reference
180 | * @param _contributor address Ethereum address of GitHub organization contributor,
181 | * @param _username string GitHub username of contributor,
182 | * @return bool Returns boolean value when called from the parent contract;
183 | */
184 | function _verifyContributor(
185 | Data storage self,
186 | address _contributor,
187 | string _username
188 | ) internal returns (bool) {
189 |
190 | // If the contributor address does not exist, then throw the transaction
191 | require(_contributor != 0x0);
192 |
193 | if (self.unclaimedRewards[_username] > 0) {
194 | // Transfer all previously unclaimed rewards of an username to an address;
195 | // Add to existing balance in case contributor has multiple usernames
196 | self.balances[_contributor] = self.balances[_contributor].add(self.unclaimedRewards[_username]);
197 | self.unclaimedRewards[_username] = 0;
198 | } else if (
199 | self.contributorAddresses[_username] != _contributor &&
200 | self.balances[self.contributorAddresses[_username]] > 0
201 | ) {
202 | // Update the contributor address for the user
203 | self.contributorUsernames[_contributor] = _username;
204 | self.contributorAddresses[_username] = _contributor;
205 |
206 | // if the user switches his/her registered account to another account,
207 | // the balance of the prior account should be moved to the new account
208 | self.balances[_contributor] = self.balances[self.contributorAddresses[_username]];
209 |
210 | // Set the balance of the prior account to 0 after moving the balance;
211 | self.balances[self.contributorAddresses[_username]] = 0;
212 | } else {
213 | // establish username and address with contract;
214 | self.contributorUsernames[_contributor] = _username;
215 | self.contributorAddresses[_username] = _contributor;
216 | }
217 | return true;
218 | }
219 |
220 | /**
221 | * @dev Internal Initialize Auction
222 | * @param _initialPrice uint Token/ETH Exchange Rate (#Tokens / 1 ETH)
223 | * @param _delay uint Time in milliseconds to delay each auction period (I - Pre, II - Start, III - End, IV - Post)
224 | * @param _lockTokens bool Boolean value to optionally lock all token transfers until the Post auction date.
225 | * @return uint[8] AuctionData
226 | */
227 | function _initializeAuction(
228 | Data storage self,
229 | uint _initialPrice,
230 | uint _delay,
231 | uint _tokenLimitFactor,
232 | bool _lockTokens
233 | ) internal returns(uint[8]) {
234 | // Ensure the contract has enough tokens to move to auction;
235 |
236 | require(self.balances[address(this)] > 0);
237 | require(_initialPrice > 0);
238 | require(_initialPrice <= self.balances[address(this)]);
239 |
240 | self.auctionRound = self.auctionRound.add(1);
241 |
242 | /*uint delay = _delay > 60*60*24 ? _delay : 60*60*24*3;*/
243 | uint delay = _delay > 0 ? _delay : 60*60*24*3;
244 | self.auctionDetails[self.auctionRound].round = self.auctionRound;
245 | self.auctionDetails[self.auctionRound].startDate = now.add(delay);
246 | self.auctionDetails[self.auctionRound].endDate = self.auctionDetails[self.auctionRound].startDate.add(delay);
247 | self.auctionDetails[self.auctionRound].tokensOffered = self.balances[address(this)];
248 | self.auctionDetails[self.auctionRound].initialPrice = _initialPrice;
249 | self.auctionDetails[self.auctionRound].wtdAvgExRate = 0;
250 | self.auctionDetails[self.auctionRound].fundsCollected = 0;
251 | self.auctionDetails[self.auctionRound].fundLimit = self.balances[address(this)] * (10**18 / _initialPrice);
252 | self.auctionDetails[self.auctionRound].numBids = 0;
253 | self.auctionDetails[self.auctionRound].tokenLimitFactor = _tokenLimitFactor;
254 |
255 | _lockTokens == true ?
256 | self.lockTokenTransfersUntil = self.auctionDetails[self.auctionRound].endDate.add(delay) :
257 | self.lockTokenTransfersUntil = 0;
258 |
259 | return ([
260 | self.auctionRound,
261 | self.auctionDetails[self.auctionRound].startDate,
262 | self.auctionDetails[self.auctionRound].endDate,
263 | self.lockTokenTransfersUntil,
264 | self.auctionDetails[self.auctionRound].tokensOffered,
265 | self.auctionDetails[self.auctionRound].initialPrice,
266 | self.auctionDetails[self.auctionRound].fundLimit,
267 | self.auctionDetails[self.auctionRound].tokenLimitFactor
268 | ]);
269 | }
270 |
271 |
272 |
273 | /**
274 | * @dev Internal
275 | */
276 | function _executeBid(
277 | Data storage self,
278 | uint _auctionRound,
279 | uint _exRate
280 | ) internal returns (uint[9] bidData) {
281 | require(self.auctionDetails[_auctionRound].startDate <= now);
282 | require(self.auctionDetails[_auctionRound].endDate >= now);
283 | require(self.auctionDetails[_auctionRound].fundLimit > 0);
284 | require(msg.value > 0);
285 |
286 | self.auctionDetails[_auctionRound].ethValues.push(msg.value);
287 | self.auctionDetails[_auctionRound].exRateValues.push(_exRate);
288 |
289 | self.auctionDetails[_auctionRound].wtdAvgExRate =
290 | self.auctionDetails[_auctionRound].ethValues.wtdAvg(
291 | self.auctionDetails[_auctionRound].exRateValues
292 | );
293 |
294 | require(_exRate <= self.auctionDetails[_auctionRound].wtdAvgExRate);
295 |
296 | require(
297 | (self.auctionDetails[_auctionRound].wtdAvgExRate - _exRate) < self.auctionDetails[_auctionRound].tokenLimitFactor * 10**8
298 | );
299 |
300 | uint _adjTokens = self.auctionDetails[_auctionRound].tokensOffered.div(self.auctionDetails[_auctionRound].tokenLimitFactor);
301 | uint adjEth = _adjTokens * (10**18 / self.auctionDetails[_auctionRound].wtdAvgExRate);
302 | uint refundAmount = msg.value > adjEth ? msg.value - adjEth : 0;
303 |
304 | if (refundAmount > 0) { msg.sender.transfer(refundAmount); }
305 |
306 | uint _ethPaid = refundAmount == 0 ? msg.value : adjEth;
307 |
308 | _adjTokens = _ethPaid / (10**18 / self.auctionDetails[_auctionRound].wtdAvgExRate);
309 |
310 | self.auctionDetails[self.auctionRound].fundsCollected =
311 | self.auctionDetails[self.auctionRound].fundsCollected.add(_ethPaid);
312 |
313 | self.auctionDetails[_auctionRound].fundLimit =
314 | self.auctionDetails[_auctionRound].fundLimit.sub(_ethPaid);
315 |
316 | self.balances[address(this)] = self.balances[address(this)].sub(_adjTokens);
317 | self.balances[msg.sender] = self.balances[msg.sender].add(_adjTokens);
318 |
319 | self.auctionDetails[self.auctionRound].tokensOffered =
320 | self.auctionDetails[self.auctionRound].tokensOffered.sub(_adjTokens);
321 |
322 | self.auctionDetails[_auctionRound].numBids =
323 | self.auctionDetails[_auctionRound].numBids.add(1);
324 |
325 |
326 | return ([
327 | _auctionRound,
328 | _exRate,
329 | self.auctionDetails[_auctionRound].wtdAvgExRate,
330 | _adjTokens,
331 | _ethPaid,
332 | refundAmount,
333 | self.auctionDetails[_auctionRound].fundsCollected,
334 | self.auctionDetails[_auctionRound].fundLimit,
335 | now
336 | ]);
337 | }
338 |
339 | }
340 |
--------------------------------------------------------------------------------
/contracts/GitTokenRegistry.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.11;
2 |
3 | import './Ownable.sol';
4 |
5 | contract GitTokenRegistry is Ownable {
6 |
7 | struct Registry {
8 | mapping(string => address) organizations;
9 | }
10 |
11 | Registry registry;
12 |
13 | event Registration(string _organization, address _token, uint date);
14 |
15 | function GitTokenRegistry(address _owner) {
16 | registry = Registry({});
17 | owner[_owner] = true;
18 | }
19 |
20 | function registerToken(string _organization, address _token) returns (bool success) {
21 | registry.organizations[_organization] = _token;
22 | Registration(_organization, _token, now);
23 | return success;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.4;
2 |
3 | contract Migrations {
4 | address public owner;
5 | uint public last_completed_migration;
6 |
7 | modifier restricted() {
8 | if (msg.sender == owner) _;
9 | }
10 |
11 | function Migrations() {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/contracts/Ownable.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.11;
2 |
3 |
4 | /**
5 | * @title Ownable
6 | * @dev The Ownable contract has an owner address, and provides basic authorization control
7 | * functions, this simplifies the implementation of "user permissions".
8 | */
9 | contract Ownable {
10 | mapping(address => bool) public owner;
11 |
12 |
13 | /**
14 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender
15 | * account.
16 | */
17 | function Ownable() {
18 | owner[msg.sender] = true;
19 | }
20 |
21 |
22 | /**
23 | * @dev Throws if called by any account other than the owner.
24 | */
25 | modifier onlyOwner() {
26 | require(owner[msg.sender]);
27 | _;
28 | }
29 |
30 |
31 | /**
32 | * @dev Allows the current owner to transfer control of the contract to a newOwner.
33 | * @param newOwner The address to transfer ownership to.
34 | */
35 | function transferOwnership(address newOwner) onlyOwner {
36 | if (!owner[newOwner]) {
37 | owner[newOwner] = true;
38 | owner[msg.sender] = false;
39 | }
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/contracts/SafeMath.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.11;
2 |
3 | /**
4 | * Math operations with safety checks
5 | */
6 | library SafeMath {
7 | function mul(uint a, uint b) internal returns (uint) {
8 | uint c = a * b;
9 | assert(a == 0 || c / a == b);
10 | return c;
11 | }
12 |
13 | function div(uint a, uint b) internal returns (uint) {
14 | // assert(b > 0); // Solidity automatically throws when dividing by 0
15 | uint c = a / b;
16 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold
17 | return c;
18 | }
19 |
20 | function sub(uint a, uint b) internal returns (uint) {
21 | assert(b <= a);
22 | return a - b;
23 | }
24 |
25 | function add(uint a, uint b) internal returns (uint) {
26 | uint c = a + b;
27 | assert(c >= a);
28 | return c;
29 | }
30 |
31 | function max64(uint64 a, uint64 b) internal constant returns (uint64) {
32 | return a >= b ? a : b;
33 | }
34 |
35 | function min64(uint64 a, uint64 b) internal constant returns (uint64) {
36 | return a < b ? a : b;
37 | }
38 |
39 | function max256(uint256 a, uint256 b) internal constant returns (uint256) {
40 | return a >= b ? a : b;
41 | }
42 |
43 | function min256(uint256 a, uint256 b) internal constant returns (uint256) {
44 | return a < b ? a : b;
45 | }
46 |
47 | function sum(uint[] _values) internal constant returns (uint) {
48 | assert(_values.length > 0);
49 | uint s = 0;
50 | for (uint i = 0; i < _values.length; i++) {
51 | s = add(s, _values[i]);
52 | }
53 | assert(s > 0);
54 | return s;
55 | }
56 |
57 | function wtdAvg(uint[] _weights, uint[] _values) internal constant returns (uint) {
58 |
59 | assert(_values.length > 0);
60 | assert(_weights.length > 0);
61 |
62 | uint s = sum(_weights);
63 | uint m = 0;
64 |
65 | for (uint i = 0; i < _values.length; i++) {
66 | uint w = _weights[i];
67 | uint x = _values[i];
68 | m = add(m, div(mul(w, x), s));
69 | }
70 |
71 | assert(m > 0);
72 | return m;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/gittoken.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * NOTE CHANGE THE FOLLOWING CONFIGURATIONS FOR YOUR PROJECT
3 | */
4 |
5 | module.exports = {
6 | contributorAddress: '0x48299b423342db084b49d97c8b09392f6156cdc7',
7 | /* NOTE Email is case sensitive, and saved as a string in the contract */
8 | username: 'Ryanmtate',
9 | // Name of Token
10 | name: 'GitToken',
11 | // organization is your github organization url
12 | organization: 'git-token',
13 | // symbol is the desired symbol for your ERC20-compatible GitToken
14 | symbol: 'GTK',
15 | decimals: 8
16 | }
17 |
--------------------------------------------------------------------------------
/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | var Migrations = artifacts.require("./Migrations.sol");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Migrations);
5 | };
6 |
--------------------------------------------------------------------------------
/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | const GitTokenLib = artifacts.require('./GitTokenLib.sol');
2 | const GitToken = artifacts.require('./GitToken.sol');
3 |
4 | module.exports = function(deployer) {
5 | deployer.deploy(GitTokenLib);
6 | deployer.link(GitTokenLib, GitToken);
7 | deployer.deploy(
8 | GitToken,
9 | "0x8da299e2184ea12624cd588006e24a78f2f90594",
10 | "GitToken",
11 | "ryanmtate",
12 | "git-token",
13 | "GTK",
14 | 8
15 | )
16 | };
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gittoken-contracts",
3 | "version": "0.0.39",
4 | "description": "GitToken Solidity Smart Contracts",
5 | "main": "",
6 | "scripts": {
7 | "test": "truffle test",
8 | "build": "truffle build",
9 | "deploy": "rm -rf ./build/* && truffle migrate --reset"
10 | },
11 | "devDependencies": {
12 | "babel-core": "^6.24.1",
13 | "babel-loader": "^7.0.0",
14 | "babel-plugin-inline-import": "^2.0.5",
15 | "babel-plugin-transform-runtime": "^6.23.0",
16 | "babel-preset-env": "^1.5.1",
17 | "babel-preset-react": "^6.24.1",
18 | "babel-preset-stage-0": "^6.24.1",
19 | "babel-runtime": "^6.23.0",
20 | "chai": "^4.1.1"
21 | },
22 | "keywords": [
23 | "GitToken",
24 | "Ethereum",
25 | "ERC20",
26 | "GitHub",
27 | "Git"
28 | ],
29 | "author": "GitToken",
30 | "license": "MIT",
31 | "dependencies": {
32 | "bluebird": "^3.5.0",
33 | "ethereumjs-testrpc": "^4.1.3",
34 | "truffle": "^3.4.11",
35 | "web3": "^0.19.0"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/test/test_executeBid.js:
--------------------------------------------------------------------------------
1 | // TODO Refactor this test for the GitTokenAuction contract
2 |
3 |
4 | // var GitToken = artifacts.require("./GitToken.sol");
5 | // var Promise = require("bluebird")
6 | // const { contributorAddress, username, name, organization, symbol, decimals } = require('../gittoken.config')
7 | // const { networks: { development: { host, port } } } = require('../truffle.js');
8 | //
9 | // var Web3 = require('web3')
10 | // var web3 = new Web3(new Web3.providers.HttpProvider(`http://${host}:${port}`))
11 | //
12 | // function initContract() {
13 | // return new Promise((resolve, reject) => {
14 | // GitToken.new(
15 | // contributorAddress,
16 | // username,
17 | // name,
18 | // organization,
19 | // symbol,
20 | // decimals
21 | // ).then(function(gittoken) {
22 | // resolve(gittoken)
23 | // }).catch(function(error) {
24 | // reject(error)
25 | // })
26 | // })
27 | // }
28 | //
29 | // contract('GitToken', function(accounts) {
30 | // describe('GitToken::executeBid', function() {
31 | //
32 | // it("Should create a reserved supply of tokens, initialize a new auction, and execute a bid.", function() {
33 | // var gittoken;
34 | // var auctionRound;
35 | // var startDate;
36 | // var endDate;
37 | // var tokensOffered;
38 | // var initialExRate;
39 | // var fundLimit;
40 | // var fundsCollected;
41 | //
42 | // var exRate;
43 | // var wtdAvgExRate;
44 | // var tokensTransferred;
45 | // var etherPaid;
46 | // var refundAmount;
47 | //
48 | // return initContract().then((contract) => {
49 | // gittoken = contract
50 | //
51 | // return gittoken.verifyContributor(contributorAddress, username)
52 | // }).then(function(event) {
53 | // const { logs } = event
54 | // assert.equal(logs.length, 1, "Expect a logged event")
55 | // assert.equal(logs[0]['event'], "ContributorVerified", "Expected a `ContributorVerified` event")
56 | //
57 | // return gittoken.rewardContributor(username, "milestone_closed", 1000, 15000, "00000000-0000-0000-0000-000000000000")
58 | // }).then(function(event){
59 | // const { logs } = event
60 | // assert.equal(logs.length, 1, "Expect a logged event")
61 | // assert.equal(logs[0]['event'], "Contribution", "Expected a `Contribution` event")
62 | //
63 | // return gittoken.initializeAuction(5000 * Math.pow(10, decimals), 1, 20, true)
64 | // }).then(function(event){
65 | // const { logs } = event
66 | //
67 | //
68 | // auctionRound = logs[0]['args']['auctionDetails'][0]
69 | // startDate = logs[0]['args']['auctionDetails'][1]
70 | // endDate = logs[0]['args']['auctionDetails'][2]
71 | // tokensOffered = logs[0]['args']['auctionDetails'][4]
72 | // initialExRate = logs[0]['args']['auctionDetails'][5]
73 | // fundLimit = logs[0]['args']['auctionDetails'][6]
74 | //
75 | //
76 | // assert.equal(8, logs[0]['args']['auctionDetails'].length, "Expected the length of auctionDetails to be 9")
77 | // assert.equal(fundLimit, tokensOffered * (1e18 / initialExRate), "Expected the fund limit to equal tokensOffered * (1e18 / initialExRate)")
78 | // assert.equal(logs.length, 1, "Expected a logged event")
79 | // assert.equal(logs[0]['event'], "Auction", "Expected a `Auction` event")
80 | // assert.equal(auctionRound, 1, "Expected Auction Round to be 1")
81 | //
82 | // let delay = new Date(startDate * 1000).getTime() - new Date().getTime()
83 | // return Promise.delay(delay, gittoken.executeBid(auctionRound.toNumber(), 5000 * Math.pow(10, decimals), {
84 | // from: accounts[0],
85 | // value: 1e18,
86 | // gasPrice: 1e9
87 | // }))
88 | //
89 | // }).then(function(event) {
90 | // const { logs } = event
91 | //
92 | // auctionRound = logs[0]['args']['bidDetails'][0]
93 | // exRate = logs[0]['args']['bidDetails'][1]
94 | // wtdAvgExRate = logs[0]['args']['bidDetails'][2]
95 | // tokensTransferred = logs[0]['args']['bidDetails'][3]
96 | // etherPaid = logs[0]['args']['bidDetails'][4]
97 | // refundAmount = logs[0]['args']['bidDetails'][5]
98 | // fundsCollected = logs[0]['args']['bidDetails'][6]
99 | // fundLimit = logs[0]['args']['bidDetails'][7]
100 | // date = logs[0]['args']['bidDetails'][8]
101 | //
102 | // assert.equal(9, logs[0]['args']['bidDetails'].length, "Expected the length of bidDetails to be 9")
103 | // assert.equal(logs.length, 1, "Expected a logged event")
104 | // assert.equal(logs[0]['event'], "AuctionBid", "Expected a `AuctionBid` event")
105 | // assert.equal(fundsCollected, 4e17, "Expected funds collected to be equal to 0.4 ETH")
106 | // assert.isAtLeast(date.toNumber(), startDate.toNumber(), "Expected bid date to be greater than or equal to the start date")
107 | //
108 | // return gittoken.balanceOf(accounts[0])
109 | // }).then(function(balance) {
110 | // assert.equal(balance, tokensTransferred.toNumber(), `Expected the ${balance} of the user to be ${tokensTransferred}`)
111 | //
112 | // return web3.eth.getBalance(gittoken.address)
113 | // }).then(function(balance) {
114 | //
115 | // assert.equal(balance, fundsCollected, `Expected the ${balance} of the contract to be ${fundsCollected}`)
116 | //
117 | // return gittoken.getAuctionDetails(auctionRound.toNumber())
118 | // }).then((auctionDetails) => {
119 | //
120 | // assert.equal(wtdAvgExRate, auctionDetails[0][6].toNumber(), "Expected wtdAvgExRate to equal auction details value");
121 | // assert.equal(fundsCollected, auctionDetails[0][7].toNumber(), "Expected funds collected to equal auction details value");
122 | // assert.equal(fundLimit, auctionDetails[0][8].toNumber(), "Expected fund limit to equal auction details value");
123 | //
124 | // }).catch(function(error) {
125 | // assert.equal(error, null, error.message)
126 | // })
127 | // }).timeout(20000);
128 | //
129 | // })
130 | // })
131 |
--------------------------------------------------------------------------------
/test/test_initializeAuction.js:
--------------------------------------------------------------------------------
1 | // TODO Refactor this test for the GitTokenAuction contract
2 |
3 | // var GitToken = artifacts.require("./GitToken.sol");
4 | // var Promise = require("bluebird")
5 | // const { contributorAddress, username, name, organization, symbol, decimals } = require('../gittoken.config')
6 | //
7 | //
8 | // function initContract() {
9 | // return new Promise((resolve, reject) => {
10 | // GitToken.new(
11 | // contributorAddress,
12 | // username,
13 | // name,
14 | // organization,
15 | // symbol,
16 | // decimals
17 | // ).then(function(gittoken) {
18 | // resolve(gittoken)
19 | // }).catch(function(error) {
20 | // reject(error)
21 | // })
22 | // })
23 | // }
24 | //
25 | // contract('GitToken', function(accounts) {
26 | // describe('GitToken::initializeAuction', function() {
27 | //
28 | // it("Should create a reserved supply of tokens, initialize a new auction, and lock external token transfers.", function() {
29 | // var gittoken;
30 | // return initContract().then((contract) => {
31 | // gittoken = contract
32 | //
33 | // return gittoken.verifyContributor(accounts[0], username)
34 | // }).then(function(event) {
35 | // const { logs } = event
36 | // assert.equal(logs.length, 1, "Expect a logged event")
37 | // assert.equal(logs[0]['event'], "ContributorVerified", "Expected a `ContributorVerified` event")
38 | //
39 | // return gittoken.rewardContributor(username, "organization", "member_added", 0, "00000000-0000-0000-0000-000000000000")
40 | // }).then(function(event){
41 | // const { logs } = event
42 | // assert.equal(logs.length, 1, "Expect a logged event")
43 | // assert.equal(logs[0]['event'], "Contribution", "Expected a `Contribution` event")
44 | //
45 | // return gittoken.initializeAuction(5000 * Math.pow(10, decimals), 0, 20, true)
46 | // }).then(function(event){
47 | // const { logs } = event
48 | // assert.equal(logs.length, 1, "Expect a logged event")
49 | // assert.equal(logs[0]['event'], "Auction", "Expected a `Auction` event")
50 | //
51 | // return gittoken.transfer("0x8CB2CeBB0070b231d4BA4D3b747acAebDFbbD142", 100e8)
52 | // }).then(function(event) {
53 | // const { logs } = event
54 | // assert.equal(logs.length, 0, "Expected the transfer event to fail until auction end date has passed")
55 | //
56 | // return gittoken.balanceOf(accounts[0])
57 | // }).then(function(balance) {
58 | // assert(balance.toNumber(), 1000 * Math.pow(10, decimals), "Expected the balance of the user to be 1000 * Math.pow(10, decimals)")
59 | // }).catch(function(error) {
60 | // assert.equal(error, null, error.message)
61 | // })
62 | // })
63 | //
64 | // it("Should create a reserved supply of tokens, initialize a new auction, and allow external token transfers.", function() {
65 | // var gittoken;
66 | // return initContract().then((contract) => {
67 | // gittoken = contract
68 | //
69 | // return gittoken.verifyContributor(accounts[0], username)
70 | // }).then(function(event) {
71 | // const { logs } = event
72 | // assert.equal(logs.length, 1, "Expect a logged event")
73 | // assert.equal(logs[0]['event'], "ContributorVerified", "Expected a `ContributorVerified` event")
74 | //
75 | // return gittoken.rewardContributor(username, "organization", "member_added", 0, "00000000-0000-0000-0000-000000000000")
76 | // }).then(function(event){
77 | // const { logs } = event
78 | // assert.equal(logs.length, 1, "Expect a logged event")
79 | // assert.equal(logs[0]['event'], "Contribution", "Expected a `Contribution` event")
80 | //
81 | // return gittoken.initializeAuction(5000 * Math.pow(10, decimals), 0, 20, false)
82 | // }).then(function(event){
83 | // const { logs } = event
84 | // assert.equal(logs.length, 1, "Expect a logged event")
85 | // assert.equal(logs[0]['event'], "Auction", "Expected a `Auction` event")
86 | //
87 | // return gittoken.transfer("0x8CB2CeBB0070b231d4BA4D3b747acAebDFbbD142", 100e8)
88 | // }).then(function(event) {
89 | // const { logs } = event
90 | // assert.equal(logs.length, 1, "Expect a logged event")
91 | // assert.equal(logs[0]['event'], "Transfer", "Expected a `Transfer` event")
92 | //
93 | // return gittoken.balanceOf(accounts[0])
94 | // }).then(function(balance) {
95 | // assert(balance.toNumber(), 1000 * Math.pow(10, decimals), "Expected the balance of the user to be 1000")
96 | // }).catch(function(error) {
97 | // assert.equal(error, null, error.message)
98 | // })
99 | // })
100 | //
101 | // it("Should not allow an exchange rate greater than the total token supply", function() {
102 | // var gittoken;
103 | // return initContract().then((contract) => {
104 | // gittoken = contract
105 | //
106 | // return gittoken.verifyContributor(accounts[0], username)
107 | // }).then(function(event) {
108 | // const { logs } = event
109 | // assert.equal(logs.length, 1, "Expect a logged event")
110 | // assert.equal(logs[0]['event'], "ContributorVerified", "Expected a `ContributorVerified` event")
111 | //
112 | // return gittoken.rewardContributor(username, "organization", "member_added", 0, "00000000-0000-0000-0000-000000000000")
113 | // }).then(function(event){
114 | // const { logs } = event
115 | // assert.equal(logs.length, 1, "Expect a logged event")
116 | // assert.equal(logs[0]['event'], "Contribution", "Expected a `Contribution` event")
117 | //
118 | // return gittoken.initializeAuction(20000 * Math.pow(10, decimals), 0, 20, false)
119 | // }).then(function(event){
120 | // const { logs } = event
121 | // assert.equal(logs.length, 0, "Expected no events from transaction")
122 | //
123 | // }).catch(function(error) {
124 | // assert.equal(error, null, error.message)
125 | // })
126 | // })
127 | //
128 | // })
129 | // })
130 |
--------------------------------------------------------------------------------
/test/test_registerToken.js:
--------------------------------------------------------------------------------
1 | var GitTokenRegistry = artifacts.require("./GitTokenRegistry.sol");
2 | var Promise = require("bluebird")
3 | const { contributorAddress } = require('../gittoken.config')
4 |
5 |
6 | function initContract() {
7 | return new Promise((resolve, reject) => {
8 | GitTokenRegistry.new(contributorAddress).then(function(registry) {
9 | resolve(registry)
10 | }).catch(function(error) {
11 | reject(error)
12 | })
13 | })
14 | }
15 |
16 | contract('GitTokenRegistry', function(accounts) {
17 | describe('GitTokenRegistry::registerToken', function() {
18 |
19 | it("Should register an organization token and emit a Registration event.", function() {
20 | var registry;
21 | return initContract().then((contract) => {
22 | registry = contract
23 | return registry.registerToken('git-token', '0x8CB2CeBB0070b231d4BA4D3b747acAebDFbbD142')
24 | }).then(function(event) {
25 | const { logs } = event
26 | assert.equal(logs.length, 1, "Expect a logged event")
27 | assert.equal(logs[0]['event'], "Registration", "Expected a `Registration` event")
28 |
29 | }).catch(function(error) {
30 | assert.equal(error, null, error.message)
31 | })
32 | })
33 |
34 | })
35 | })
36 |
--------------------------------------------------------------------------------
/test/test_rewardContribution.js:
--------------------------------------------------------------------------------
1 | var GitToken = artifacts.require("./GitToken.sol");
2 | var Promise = require("bluebird")
3 | const { contributorAddress, username, name, organization, symbol, decimals } = require('../gittoken.config')
4 |
5 |
6 | function initContract() {
7 | return new Promise((resolve, reject) => {
8 | GitToken.new(
9 | contributorAddress,
10 | username,
11 | name,
12 | organization,
13 | symbol,
14 | decimals
15 | ).then(function(gittoken) {
16 | resolve(gittoken)
17 | }).catch(function(error) {
18 | reject(error)
19 | })
20 | })
21 | }
22 |
23 | function toBigNumber(value, decimals) {
24 | return value * Math.pow(10, decimals)
25 | }
26 |
27 | contract('GitToken', function(accounts) {
28 | describe('GitToken::rewardContributor', function() {
29 | it("Should reward a non-verified contributor for organization_member_added, verify the contributor, update the contributor's balance, then show 0 unclaimed rewards for the contributor", function() {
30 | var gittoken;
31 | return initContract().then((contract) => {
32 | gittoken = contract
33 |
34 | return gittoken.rewardContributor('NewUser', "organization_member_added", toBigNumber(2500, decimals), toBigNumber(2500, decimals), "00000000-0000-0000-0000-000000000000")
35 | }).then(function(event){
36 | const { logs } = event
37 | // console.log('logs', JSON.stringify(logs, null, 2))
38 | assert.equal(logs.length, 1, "Expect a logged event")
39 | assert.equal(logs[0]['event'], "Contribution", "Expected a `Contribution` event")
40 |
41 | return gittoken.getUnclaimedRewards('NewUser')
42 | }).then(function(unclaimedRewards) {
43 | assert.equal(unclaimedRewards.toNumber(), toBigNumber(2500, decimals), "Expected Unclaimed Rewards of contributor to be 2500")
44 |
45 | return gittoken.verifyContributor(contributorAddress, 'NewUser')
46 | }).then(function(event) {
47 | const { logs } = event
48 | assert.equal(logs[0]['event'], "ContributorVerified", "Expected a `ContributorVerified` event")
49 |
50 | return gittoken.balanceOf.call(contributorAddress)
51 | }).then(function(balance) {
52 | assert.equal(balance.toNumber(), toBigNumber(2500, decimals), "Expected balance of contributor to be 2500")
53 |
54 | return gittoken.getUnclaimedRewards('NewUser')
55 | }).then(function(unclaimedRewards) {
56 | assert.equal(unclaimedRewards.toNumber(), 0, "Expected Unclaimed Rewards of contributor to be 0")
57 |
58 | }).catch(function(error) {
59 | assert.equal(error, null, error.message)
60 | })
61 | })
62 |
63 | it("Should reward a pre-verified contributor for organization_member_added, update the contributor's balance, then show 0 unclaimed rewards for the contributor", function() {
64 | var gittoken;
65 | return initContract().then((contract) => {
66 | gittoken = contract
67 |
68 | return gittoken.rewardContributor(username, "organization_member_added", toBigNumber(2500, decimals), toBigNumber(2500, decimals), "00000000-0000-0000-0000-000000000000")
69 | }).then(function(event){
70 | const { logs } = event
71 | // console.log('logs', JSON.stringify(logs, null, 2))
72 | assert.equal(logs.length, 1, "Expect a logged event")
73 | assert.equal(logs[0]['event'], "Contribution", "Expected a `Contribution` event")
74 |
75 | return gittoken.balanceOf.call(contributorAddress)
76 | }).then(function(balance) {
77 | assert.equal(balance.toNumber(), toBigNumber(2500, decimals), "Expected balance of contributor to be 2500")
78 |
79 | return gittoken.getUnclaimedRewards(username)
80 | }).then(function(unclaimedRewards) {
81 | assert.equal(unclaimedRewards.toNumber(), 0, "Expected Unclaimed Rewards of contributor to be 0")
82 |
83 | }).catch(function(error) {
84 | assert.equal(error, null, error.message)
85 | })
86 | })
87 |
88 | it("Should prevent duplicate GitHub web hook events from rewarding tokens", function() {
89 | var gittoken;
90 | return initContract().then((contract) => {
91 | gittoken = contract
92 |
93 | return gittoken.verifyContributor(contributorAddress, username)
94 | }).then(function(event) {
95 | const { logs } = event
96 | assert.equal(logs[0]['event'], "ContributorVerified", "Expected a `ContributorVerified` event")
97 |
98 | return gittoken.rewardContributor(username, "organization_member_added", toBigNumber(2500, decimals), toBigNumber(2500, decimals), "00000000-0000-0000-0000-000000000000")
99 | }).then(function(event){
100 | const { logs } = event
101 | assert.equal(logs.length, 1, "Expect a logged event")
102 | assert.equal(logs[0]['event'], "Contribution", "Expected a `Contribution` event")
103 |
104 | return gittoken.rewardContributor(username, "organization_member_added", toBigNumber(2500, decimals), toBigNumber(2500, decimals), "00000000-0000-0000-0000-000000000000")
105 | }).then(function(event){
106 | const { logs } = event
107 | assert.equal(logs.length, 0, "Expected a thrown event")
108 |
109 | return gittoken.balanceOf(contributorAddress)
110 | }).then(function(balance) {
111 | assert.equal(balance.toNumber(), toBigNumber(2500, decimals), "Expected balance to be 2500")
112 |
113 | }).catch(function(error) {
114 | assert.notEqual(error, null, error.message)
115 | })
116 | })
117 |
118 | })
119 | })
120 |
--------------------------------------------------------------------------------
/test/test_transfer.js:
--------------------------------------------------------------------------------
1 | var GitToken = artifacts.require("./GitToken.sol");
2 | var Promise = require("bluebird")
3 | const { contributorAddress, username, name, organization, symbol, decimals } = require('../gittoken.config')
4 |
5 |
6 | function initContract() {
7 | return new Promise((resolve, reject) => {
8 | GitToken.new(
9 | contributorAddress,
10 | username,
11 | name,
12 | organization,
13 | symbol,
14 | decimals
15 | ).then(function(gittoken) {
16 | resolve(gittoken)
17 | }).catch(function(error) {
18 | reject(error)
19 | })
20 | })
21 | }
22 |
23 | function toBigNumber(value, decimals) {
24 | return value * Math.pow(10, decimals)
25 | }
26 |
27 | contract('GitToken', function(accounts) {
28 | describe('GitToken::transfer', function() {
29 |
30 | it("Should reward a contributor and allow that contributor to transfer one unit of the token", function() {
31 | var gittoken;
32 | return initContract().then((contract) => {
33 | gittoken = contract
34 | return gittoken.verifyContributor(accounts[0], username)
35 | }).then(function(event) {
36 | const { logs } = event
37 | assert.equal(logs.length, 1, "Expect a logged event")
38 | assert.equal(logs[0]['event'], "ContributorVerified", "Expected a `ContributorVerified` event")
39 |
40 | return gittoken.rewardContributor(username, "organization_member_added", toBigNumber(2500, decimals), toBigNumber(2500, decimals), "00000000-0000-0000-0000-000000000000")
41 | }).then(function(event){
42 | const { logs } = event
43 | assert.equal(logs.length, 1, "Expect a logged event")
44 | assert.equal(logs[0]['event'], "Contribution", "Expected a `Contribution` event")
45 |
46 | return gittoken.transfer("0x8CB2CeBB0070b231d4BA4D3b747acAebDFbbD142", 1e8)
47 | }).then(function(event) {
48 | const { logs } = event
49 | assert.equal(logs.length, 1, "Expect a logged event")
50 | assert.equal(logs[0]['event'], "Transfer", "Expected a `Transfer` event")
51 |
52 | }).catch(function(error) {
53 | assert.equal(error, null, error.message)
54 | })
55 | })
56 |
57 | })
58 | })
59 |
--------------------------------------------------------------------------------
/test/test_verifyContributor.js:
--------------------------------------------------------------------------------
1 | var GitToken = artifacts.require("./GitToken.sol");
2 | var Promise = require("bluebird")
3 | const { contributorAddress, username, name, organization, symbol, decimals } = require('../gittoken.config')
4 |
5 |
6 | function initContract() {
7 | return new Promise((resolve, reject) => {
8 | GitToken.new(
9 | contributorAddress,
10 | username,
11 | name,
12 | organization,
13 | symbol,
14 | decimals
15 | ).then(function(gittoken) {
16 | resolve(gittoken)
17 | }).catch(function(error) {
18 | reject(error)
19 | })
20 | })
21 | }
22 |
23 | function toBigNumber(value, decimals) {
24 | return value * Math.pow(10, decimals)
25 | }
26 |
27 | contract('GitToken', function(accounts) {
28 | describe('GitToken::verifyContributor', function() {
29 |
30 | it("Should verify the contributor, reward the contributor, update the contributor's balance, and show 0 unclaimed rewards for the contributor", function() {
31 | var gittoken;
32 | return initContract().then((contract) => {
33 | gittoken = contract
34 |
35 | return gittoken.verifyContributor(contributorAddress, username)
36 | }).then(function(event) {
37 | const { logs } = event
38 | assert.equal(logs[0]['event'], "ContributorVerified", "Expected a `ContributorVerified` event")
39 |
40 | return gittoken.rewardContributor(username, "organization_member_added", toBigNumber(2500, decimals), toBigNumber(2500, decimals), "00000000-0000-0000-0000-000000000000")
41 | }).then(function(event){
42 | const { logs } = event
43 | assert.equal(logs.length, 1, "Expect a logged event")
44 | assert.equal(logs[0]['event'], "Contribution", "Expected a `Contribution` event")
45 |
46 | return gittoken.balanceOf.call(contributorAddress)
47 | }).then(function(balance) {
48 | assert.equal(balance.toNumber(), toBigNumber(2500, decimals), "Expected balance of contributor to be toBigNumber(2500, decimals)")
49 |
50 | return gittoken.getUnclaimedRewards(username)
51 | }).then(function(unclaimedRewards) {
52 | assert.equal(unclaimedRewards.toNumber(), 0, "Expected Unclaimed Rewards of contributor to be 0")
53 |
54 | }).catch(function(error) {
55 | assert.equal(error, null, error.message)
56 | })
57 | })
58 | })
59 | })
60 |
--------------------------------------------------------------------------------
/truffle.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | networks: {
3 | development: {
4 | host: "138.68.225.133",
5 | port: 8745,
6 | network_id: "*", // Match any network id
7 | gasPrice: 4e9, // 20 Gwei gas price; lower == slower, cheaper; higher == faster, costly
8 | gas: 47e5
9 | }
10 | }
11 | };
12 |
--------------------------------------------------------------------------------