Advertisement
Guest User

Untitled

a guest
Feb 13th, 2017
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 48.13 KB | None | 0 0
  1. /*
  2. The MIT License (MIT)
  3.  
  4. Copyright (c) 2016 DFINITY Stiftung
  5.  
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12.  
  13. The above copyright notice and this permission notice shall be included in all
  14. copies or substantial portions of the Software.
  15.  
  16. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. SOFTWARE.
  23. */
  24.  
  25. /**
  26. * @title: The DFINITY Stiftung donation contract (FDC).
  27. * @author: Timo Hanke <timo.t.hanke@gmail.com>
  28. *
  29. * This contract
  30. * - accepts on-chain donations for the foundation in ether
  31. * - tracks on-chain and off-chain donations made to the foundation
  32. * - assigns unrestricted tokens to addresses provided by donors
  33. * - assigns restricted tokens to DFINITY Stiftung and early contributors
  34. *
  35. * On-chain donations are received in ether are converted to Swiss francs (CHF).
  36. * Off-chain donations are received and recorded directly in Swiss francs.
  37. * Tokens are assigned at a rate of 10 tokens per CHF.
  38. *
  39. * There are two types of tokens initially. Unrestricted tokens are assigned to
  40. * donors and restricted tokens are assigned to DFINITY Stiftung and early
  41. * contributors. Restricted tokens are converted to unrestricted tokens in the
  42. * finalization phase, after which only unrestricted tokens exist.
  43. *
  44. * After the finalization phase, tokens assigned to DFINITY Stiftung and early
  45. * contributors will make up a pre-defined share of all tokens. This is achieved
  46. * through burning excess restricted tokens before their restriction is removed.
  47. */
  48.  
  49. pragma solidity ^0.4.6;
  50.  
  51. /*
  52. The MIT License (MIT)
  53.  
  54. Copyright (c) 2016 DFINITY Stiftung
  55.  
  56. Permission is hereby granted, free of charge, to any person obtaining a copy
  57. of this software and associated documentation files (the "Software"), to deal
  58. in the Software without restriction, including without limitation the rights
  59. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  60. copies of the Software, and to permit persons to whom the Software is
  61. furnished to do so, subject to the following conditions:
  62.  
  63. The above copyright notice and this permission notice shall be included in all
  64. copies or substantial portions of the Software.
  65.  
  66. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  67. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  68. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  69. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  70. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  71. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  72. SOFTWARE.
  73. */
  74.  
  75. /**
  76. * @title: A contract that tracks numbers of tokens assigned to addresses.
  77. * @author: Timo Hanke <timo.t.hanke@gmail.com>
  78. *
  79. * Optionally, assignments can be chosen to be of "restricted type".
  80. * Being "restricted" means that the token assignment may later be partially
  81. * reverted (or the tokens "burned") by the contract.
  82. *
  83. * After all token assignments are completed the contract
  84. * - burns some restricted tokens
  85. * - releases the restriction on the remaining tokens
  86. * The percentage of tokens that burned out of each assignment of restricted
  87. * tokens is calculated to achieve the following condition:
  88. * - the remaining formerly restricted tokens combined have a pre-configured
  89. * share (percentage) among all remaining tokens.
  90. *
  91. * Once the conversion process has started the contract enters a state in which
  92. * no more assignments can be made.
  93. */
  94.  
  95. pragma solidity ^0.4.6;
  96.  
  97. contract TokenTracker {
  98. // Share of formerly restricted tokens among all tokens in percent
  99. uint public restrictedShare;
  100.  
  101. // Mapping from address to number of tokens assigned to the address
  102. mapping(address => uint) public tokens;
  103.  
  104. // Mapping from address to number of tokens assigned to the address that
  105. // underly a restriction
  106. mapping(address => uint) public restrictions;
  107.  
  108. // Total number of (un)restricted tokens currently in existence
  109. uint public totalRestrictedTokens;
  110. uint public totalUnrestrictedTokens;
  111.  
  112. // Total number of individual assignment calls have been for (un)restricted
  113. // tokens
  114. uint public totalRestrictedAssignments;
  115. uint public totalUnrestrictedAssignments;
  116.  
  117. // State flag. Assignments can only be made if false.
  118. // Starting the conversion (burn) process irreversibly sets this to true.
  119. bool public assignmentsClosed = false;
  120.  
  121. // The multiplier (defined by nominator and denominator) that defines the
  122. // fraction of all restricted tokens to be burned.
  123. // This is computed after assignments have ended and before the conversion
  124. // process starts.
  125. uint public burnMultDen;
  126. uint public burnMultNom;
  127.  
  128. function TokenTracker(uint _restrictedShare) {
  129. // Throw if restricted share >= 100
  130. if (_restrictedShare >= 100) { throw; }
  131.  
  132. restrictedShare = _restrictedShare;
  133. }
  134.  
  135. /**
  136. * PUBLIC functions
  137. *
  138. * - isUnrestricted (getter)
  139. * - multFracCeiling (library function)
  140. * - isRegistered(addr) (getter)
  141. */
  142.  
  143. /**
  144. * Return true iff the assignments are closed and there are no restricted
  145. * tokens left
  146. */
  147. function isUnrestricted() constant returns (bool) {
  148. return (assignmentsClosed && totalRestrictedTokens == 0);
  149. }
  150.  
  151. /**
  152. * Return the ceiling of (x*a)/b
  153. *
  154. * Edge cases:
  155. * a = 0: return 0
  156. * b = 0, a != 0: error (solidity throws on division by 0)
  157. */
  158. function multFracCeiling(uint x, uint a, uint b) returns (uint) {
  159. // Catch the case a = 0
  160. if (a == 0) { return 0; }
  161.  
  162. // Rounding up is the same as adding 1-epsilon and rounding down.
  163. // 1-epsilon is modeled as (b-1)/b below.
  164. return (x * a + (b - 1)) / b;
  165. }
  166.  
  167. /**
  168. * Return true iff the address has tokens assigned (resp. restricted tokens)
  169. */
  170. function isRegistered(address addr, bool restricted) constant returns (bool) {
  171. if (restricted) {
  172. return (restrictions[addr] > 0);
  173. } else {
  174. return (tokens[addr] > 0);
  175. }
  176. }
  177.  
  178. /**
  179. * INTERNAL functions
  180. *
  181. * - assign
  182. * - closeAssignments
  183. * - unrestrict
  184. */
  185.  
  186. /**
  187. * Assign (un)restricted tokens to given address
  188. */
  189. function assign(address addr, uint tokenAmount, bool restricted) internal {
  190. // Throw if assignments have been closed
  191. if (assignmentsClosed) { throw; }
  192.  
  193. // Assign tokens
  194. tokens[addr] += tokenAmount;
  195.  
  196. // Record restrictions and update total counters
  197. if (restricted) {
  198. totalRestrictedTokens += tokenAmount;
  199. totalRestrictedAssignments += 1;
  200. restrictions[addr] += tokenAmount;
  201. } else {
  202. totalUnrestrictedTokens += tokenAmount;
  203. totalUnrestrictedAssignments += 1;
  204. }
  205. }
  206.  
  207. /**
  208. * Close future assignments.
  209. *
  210. * This is irreversible and closes all future assignments.
  211. * The function can only be called once.
  212. *
  213. * A call triggers the calculation of what fraction of restricted tokens
  214. * should be burned by subsequent calls to the unrestrict() function.
  215. * The result of this calculation is a multiplication factor whose nominator
  216. * and denominator are stored in the contract variables burnMultNom,
  217. * burnMultDen.
  218. */
  219. function closeAssignmentsIfOpen() internal {
  220. // Return if assignments are not open
  221. if (assignmentsClosed) { return; }
  222.  
  223. // Set the state to "closed"
  224. assignmentsClosed = true;
  225.  
  226. /*
  227. * Calculate the total number of tokens that should remain after
  228. * conversion. This is based on the total number of unrestricted tokens
  229. * assigned so far and the pre-configured share that the remaining
  230. * formerly restricted tokens should have.
  231. */
  232. uint totalTokensTarget = (totalUnrestrictedTokens * 100) /
  233. (100 - restrictedShare);
  234.  
  235. // The total number of tokens in existence now.
  236. uint totalTokensExisting = totalRestrictedTokens + totalUnrestrictedTokens;
  237.  
  238. /*
  239. * The total number of tokens that need to be burned to bring the existing
  240. * number down to the target number. If the existing number is lower than
  241. * the target then we won't burn anything.
  242. */
  243. uint totalBurn = 0;
  244. if (totalTokensExisting > totalTokensTarget) {
  245. totalBurn = totalTokensExisting - totalTokensTarget;
  246. }
  247.  
  248. // The fraction of restricted tokens to be burned (by nominator and
  249. // denominator).
  250. burnMultNom = totalBurn;
  251. burnMultDen = totalRestrictedTokens;
  252.  
  253. /*
  254. * For verifying the correctness of the above calculation it may help to
  255. * note the following.
  256. * Given 0 <= restrictedShare < 100, we have:
  257. * - totalTokensTarget >= totalUnrestrictedTokens
  258. * - totalTokensExisting <= totalRestrictedTokens + totalTokensTarget
  259. * - totalBurn <= totalRestrictedTokens
  260. * - burnMultNom <= burnMultDen
  261. * Also note that burnMultDen = 0 means totalRestrictedTokens = 0, in which
  262. * burnMultNom = 0 as well.
  263. */
  264. }
  265.  
  266. /**
  267. * Unrestrict (convert) all restricted tokens assigned to the given address
  268. *
  269. * This function can only be called after assignments have been closed via
  270. * closeAssignments().
  271. * The return value is the number of restricted tokens that were burned in
  272. * the conversion.
  273. */
  274. function unrestrict(address addr) internal returns (uint) {
  275. // Throw is assignments are not yet closed
  276. if (!assignmentsClosed) { throw; }
  277.  
  278. // The balance of restricted tokens for the given address
  279. uint restrictionsForAddr = restrictions[addr];
  280.  
  281. // Throw if there are none
  282. if (restrictionsForAddr == 0) { throw; }
  283.  
  284. // Apply the burn multiplier to the balance of restricted tokens
  285. // The result is the ceiling of the value:
  286. // (restrictionForAddr * burnMultNom) / burnMultDen
  287. uint burn = multFracCeiling(restrictionsForAddr, burnMultNom, burnMultDen);
  288.  
  289. // Remove the tokens to be burned from the address's balance
  290. tokens[addr] -= burn;
  291.  
  292. // Delete record of restrictions
  293. delete restrictions[addr];
  294.  
  295. // Update the counters for total (un)restricted tokens
  296. totalRestrictedTokens -= restrictionsForAddr;
  297. totalUnrestrictedTokens += restrictionsForAddr - burn;
  298.  
  299. return burn;
  300. }
  301. }
  302.  
  303. /*
  304. The MIT License (MIT)
  305.  
  306. Copyright (c) 2016 DFINITY Stiftung
  307.  
  308. Permission is hereby granted, free of charge, to any person obtaining a copy
  309. of this software and associated documentation files (the "Software"), to deal
  310. in the Software without restriction, including without limitation the rights
  311. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  312. copies of the Software, and to permit persons to whom the Software is
  313. furnished to do so, subject to the following conditions:
  314.  
  315. The above copyright notice and this permission notice shall be included in all
  316. copies or substantial portions of the Software.
  317.  
  318. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  319. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  320. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  321. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  322. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  323. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  324. SOFTWARE.
  325. */
  326.  
  327. /*
  328. * @title: Contract that advances through multiple configurable phases over time
  329. * @author: Timo Hanke <timo.t.hanke@gmail.com>
  330. *
  331. * Phases are defined by their transition times. The moment one phase ends the
  332. * next one starts. Each time belongs to exactly one phase.
  333. *
  334. * The contract allows a limited set of changes to be applied to the phase
  335. * transitions while the contract is active. As a matter of principle, changes
  336. * are prohibited from effecting the past. They may only ever affect future
  337. * phase transitions.
  338. *
  339. * The permitted changes are:
  340. * - add a new phase after the last one
  341. * - end the current phase right now and transition to the next phase
  342. * immediately
  343. * - delay the start of a future phase (thereby pushing out all subsequent
  344. * phases by an equal amount of time)
  345. * - define a maximum delay for a specified phase
  346. */
  347.  
  348. pragma solidity ^0.4.6;
  349.  
  350. contract Phased {
  351. /**
  352. * Array of transition times defining the phases
  353. *
  354. * phaseEndTime[i] is the time when phase i has just ended.
  355. * Phase i is defined as the following time interval:
  356. * [ phaseEndTime[i-1], * phaseEndTime[i] )
  357. */
  358. uint[] public phaseEndTime;
  359.  
  360. /**
  361. * Number of phase transitions N = phaseEndTime.length
  362. *
  363. * There are N+1 phases, numbered 0,..,N.
  364. * The first phase has no start and the last phase has no end.
  365. */
  366. uint public N;
  367.  
  368. /**
  369. * Maximum delay for phase transitions
  370. *
  371. * maxDelay[i] is the maximum amount of time by which the transition
  372. * phaseEndTime[i] can be delayed.
  373. */
  374. mapping(uint => uint) public maxDelay;
  375.  
  376. /*
  377. * The contract has no constructor.
  378. * The contract initialized itself with no phase transitions (N = 0) and one
  379. * phase (N+1=1).
  380. *
  381. * There are two PUBLIC functions (getters):
  382. * - getPhaseAtTime
  383. * - isPhase
  384. * - getPhaseStartTime
  385. *
  386. * Note that both functions are guaranteed to return the same value when
  387. * called twice with the same argument (but at different times).
  388. */
  389.  
  390. /**
  391. * Return the number of the phase to which the given time belongs.
  392. *
  393. * Return value i means phaseEndTime[i-1] <= time < phaseEndTime[i].
  394. * The given time must not be in the future (because future phase numbers may
  395. * still be subject to change).
  396. */
  397. function getPhaseAtTime(uint time) constant returns (uint n) {
  398. // Throw if time is in the future
  399. if (time > now) { throw; }
  400.  
  401. // Loop until we have found the "active" phase
  402. while (n < N && phaseEndTime[n] <= time) {
  403. n++;
  404. }
  405. }
  406.  
  407. /**
  408. * Return true if the given time belongs to the given phase.
  409. *
  410. * Returns the logical equivalent of the expression
  411. * (phaseEndTime[i-1] <= time < phaseEndTime[i]).
  412. *
  413. * The given time must not be in the future (because future phase numbers may
  414. * still be subject to change).
  415. */
  416. function isPhase(uint time, uint n) constant returns (bool) {
  417. // Throw if time is in the future
  418. if (time > now) { throw; }
  419.  
  420. // Throw if index is out-of-range
  421. if (n >= N) { throw; }
  422.  
  423. // Condition 1
  424. if (n > 0 && phaseEndTime[n-1] > time) { return false; }
  425.  
  426. // Condition 2
  427. if (n < N && time >= phaseEndTime[n]) { return false; }
  428.  
  429. return true;
  430. }
  431.  
  432. /**
  433. * Return the start time of the given phase.
  434. *
  435. * This function is provided for convenience.
  436. * The given phase number must not be 0, as the first phase has no start time.
  437. * If calling for a future phase number the caller must be aware that future
  438. * phase times can be subject to change.
  439. */
  440. function getPhaseStartTime(uint n) constant returns (uint) {
  441. // Throw if phase is the first phase
  442. if (n == 0) { throw; }
  443.  
  444. return phaseEndTime[n-1];
  445. }
  446.  
  447. /*
  448. * There are 4 INTERNAL functions:
  449. * 1. addPhase
  450. * 2. setMaxDelay
  451. * 3. delayPhaseEndBy
  452. * 4. endCurrentPhaseIn
  453. *
  454. * This contract does not implement access control to these function, so
  455. * they are made internal.
  456. */
  457.  
  458. /**
  459. * 1. Add a phase after the last phase.
  460. *
  461. * The argument is the new endTime of the phase currently known as the last
  462. * phase, or, in other words the start time of the newly introduced phase.
  463. * All calls to addPhase() MUST be with strictly increasing time arguments.
  464. * It is not allowed to add a phase transition that lies in the past relative
  465. * to the current block time.
  466. */
  467. function addPhase(uint time) internal {
  468. // Throw if new transition time is not strictly increasing
  469. if (N > 0 && time <= phaseEndTime[N-1]) { throw; }
  470.  
  471. // Throw if new transition time is not in the future
  472. if (time <= now) { throw; }
  473.  
  474. // Append new transition time to array
  475. phaseEndTime.push(time);
  476. N++;
  477. }
  478.  
  479. /**
  480. * 2. Define a limit on the amount of time by which the given transition (i)
  481. * can be delayed.
  482. *
  483. * By default, transitions can not be delayed (limit = 0).
  484. */
  485. function setMaxDelay(uint i, uint timeDelta) internal {
  486. // Throw if index is out-of-range
  487. if (i >= N) { throw; }
  488.  
  489. maxDelay[i] = timeDelta;
  490. }
  491.  
  492. /**
  493. * 3. Delay the end of the given phase (n) by the given time delta.
  494. *
  495. * The given phase must not have ended.
  496. *
  497. * This function can be called multiple times for the same phase.
  498. * The defined maximum delay will be enforced across multiple calls.
  499. */
  500. function delayPhaseEndBy(uint n, uint timeDelta) internal {
  501. // Throw if index is out of range
  502. if (n >= N) { throw; }
  503.  
  504. // Throw if phase has already ended
  505. if (now >= phaseEndTime[n]) { throw; }
  506.  
  507. // Throw if the requested delay is higher than the defined maximum for the
  508. // transition
  509. if (timeDelta > maxDelay[n]) { throw; }
  510.  
  511. // Subtract from the current max delay, so maxDelay is honored across
  512. // multiple calls
  513. maxDelay[n] -= timeDelta;
  514.  
  515. // Push out all subsequent transitions by the same amount
  516. for (uint i = n; i < N; i++) {
  517. phaseEndTime[i] += timeDelta;
  518. }
  519. }
  520.  
  521. /**
  522. * 4. End the current phase early.
  523. *
  524. * The current phase must not be the last phase, as the last phase has no end.
  525. * The current phase will end at time now plus the given time delta.
  526. *
  527. * The minimal allowed time delta is 1. This is avoid a race condition for
  528. * other transactions that are processed in the same block.
  529. * Setting phaseEndTime[n] to now would push all later transactions from the
  530. * same block into the next phase.
  531. * If the specified timeDelta is 0 the function gracefully bumps it up to 1.
  532. */
  533. function endCurrentPhaseIn(uint timeDelta) internal {
  534. // Get the current phase number
  535. uint n = getPhaseAtTime(now);
  536.  
  537. // Throw if we are in the last phase
  538. if (n >= N) { throw; }
  539.  
  540. // Set timeDelta to the minimal allowed value
  541. if (timeDelta == 0) {
  542. timeDelta = 1;
  543. }
  544.  
  545. // The new phase end should be earlier than the currently defined phase
  546. // end, otherwise we don't change it.
  547. if (now + timeDelta < phaseEndTime[n]) {
  548. phaseEndTime[n] = now + timeDelta;
  549. }
  550. }
  551. }
  552.  
  553. /*
  554. The MIT License (MIT)
  555.  
  556. Copyright (c) 2016 DFINITY Stiftung
  557.  
  558. Permission is hereby granted, free of charge, to any person obtaining a copy
  559. of this software and associated documentation files (the "Software"), to deal
  560. in the Software without restriction, including without limitation the rights
  561. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  562. copies of the Software, and to permit persons to whom the Software is
  563. furnished to do so, subject to the following conditions:
  564.  
  565. The above copyright notice and this permission notice shall be included in all
  566. copies or substantial portions of the Software.
  567.  
  568. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  569. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  570. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  571. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  572. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  573. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  574. SOFTWARE.
  575. */
  576.  
  577. /*
  578. * @title: A configurable step function
  579. * @author: Timo Hanke <timo.t.hanke@gmail.com>
  580. *
  581. * The contract implements a step function going down from an initialValue to 0
  582. * in a number of steps (nSteps).
  583. * The steps are distributed equally over a given time (phaseLength).
  584. * Having n steps means that the time phaseLength is divided into n+1
  585. * sub-intervalls of equal length during each of which the function value is
  586. * constant.
  587. */
  588.  
  589. pragma solidity ^0.4.6;
  590.  
  591. contract StepFunction {
  592. uint public phaseLength;
  593. uint public nSteps;
  594. uint public step;
  595.  
  596. function StepFunction(uint _phaseLength, uint _initialValue, uint _nSteps) {
  597. // Throw if phaseLength does not leave enough room for number of steps
  598. if (_nSteps > _phaseLength) { throw; }
  599.  
  600. // The reduction in value per step
  601. step = _initialValue / _nSteps;
  602.  
  603. // Throw if _initialValue was not divisible by _nSteps
  604. if ( step * _nSteps != _initialValue) { throw; }
  605.  
  606. phaseLength = _phaseLength;
  607. nSteps = _nSteps;
  608. }
  609.  
  610. /*
  611. * Note the following edge cases.
  612. * initialValue = 0: is valid and will create the constant zero function
  613. * nSteps = 0: is valid and will create the constant zero function (only 1
  614. * sub-interval)
  615. * phaseLength < nSteps: is valid, but unlikely to be intended (so the
  616. * constructor throws)
  617. */
  618.  
  619. /**
  620. * Evaluate the step function at a given time
  621. *
  622. * elapsedTime MUST be in the intervall [0,phaseLength)
  623. * The return value is between initialValue and 0, never negative.
  624. */
  625. function getStepFunction(uint elapsedTime) constant returns (uint) {
  626. // Throw is elapsedTime is out-of-range
  627. if (elapsedTime >= phaseLength) { throw; }
  628.  
  629. // The function value will bel calculated from the end value backwards.
  630. // Hence we need the time left, which will lie in the intervall
  631. // [0,phaseLength)
  632. uint timeLeft = phaseLength - elapsedTime - 1;
  633.  
  634. // Calculate the number of steps away from reaching end value
  635. // When verifying the forumla below it may help to note:
  636. // at elapsedTime = 0 stepsLeft evaluates to nSteps,
  637. // at elapsedTime = -1 stepsLeft would evaluate to nSteps + 1.
  638. uint stepsLeft = ((nSteps + 1) * timeLeft) / phaseLength;
  639.  
  640. // Apply the step function
  641. return stepsLeft * step;
  642. }
  643. }
  644.  
  645. /*
  646. The MIT License (MIT)
  647.  
  648. Copyright (c) 2016 DFINITY Stiftung
  649.  
  650. Permission is hereby granted, free of charge, to any person obtaining a copy
  651. of this software and associated documentation files (the "Software"), to deal
  652. in the Software without restriction, including without limitation the rights
  653. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  654. copies of the Software, and to permit persons to whom the Software is
  655. furnished to do so, subject to the following conditions:
  656.  
  657. The above copyright notice and this permission notice shall be included in all
  658. copies or substantial portions of the Software.
  659.  
  660. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  661. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  662. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  663. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  664. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  665. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  666. SOFTWARE.
  667. */
  668.  
  669. /*
  670. * @title: Contract implementing counters with configurable targets
  671. * @author: Timo Hanke <timo.t.hanke@gmail.com>
  672. *
  673. * There is an arbitrary number of counters. Each counter is identified by its
  674. * counter id, a uint. Counters can never decrease.
  675. *
  676. * The contract has no constructor. The target values are set and re-set via
  677. * setTarget().
  678. */
  679.  
  680. pragma solidity ^0.4.6;
  681.  
  682. contract Targets {
  683.  
  684. // Mapping from counter id to counter value
  685. mapping(uint => uint) public counter;
  686.  
  687. // Mapping from counter id to target value
  688. mapping(uint => uint) public target;
  689.  
  690. // A public getter that returns whether the target was reached
  691. function targetReached(uint id) constant returns (bool) {
  692. return (counter[id] >= target[id]);
  693. }
  694.  
  695. /*
  696. * Modifying counter or target are internal functions.
  697. */
  698.  
  699. // (Re-)set the target
  700. function setTarget(uint id, uint _target) internal {
  701. target[id] = _target;
  702. }
  703.  
  704. // Add to the counter
  705. // The function returns whether this current addition makes the counter reach
  706. // or cross its target value
  707. function addTowardsTarget(uint id, uint amount)
  708. internal
  709. returns (bool firstReached)
  710. {
  711. firstReached = (counter[id] < target[id]) &&
  712. (counter[id] + amount >= target[id]);
  713. counter[id] += amount;
  714. }
  715. }
  716.  
  717. /*
  718. The MIT License (MIT)
  719.  
  720. Copyright (c) 2016 DFINITY Stiftung
  721.  
  722. Permission is hereby granted, free of charge, to any person obtaining a copy
  723. of this software and associated documentation files (the "Software"), to deal
  724. in the Software without restriction, including without limitation the rights
  725. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  726. copies of the Software, and to permit persons to whom the Software is
  727. furnished to do so, subject to the following conditions:
  728.  
  729. The above copyright notice and this permission notice shall be included in all
  730. copies or substantial portions of the Software.
  731.  
  732. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  733. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  734. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  735. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  736. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  737. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  738. SOFTWARE.
  739. */
  740.  
  741. /**
  742. * @title: Configuration parameters for the FDC
  743. * @author: Timo Hanke <timo.t.hanke@gmail.com>
  744. */
  745.  
  746. pragma solidity ^0.4.6;
  747.  
  748. contract Parameters {
  749.  
  750. /*
  751. * Time Constants
  752. *
  753. * Phases are, in this order:
  754. * earlyContribution (defined by end time)
  755. * pause
  756. * donation round0 (defined by start and end time)
  757. * pause
  758. * donation round1 (defined by start and end time)
  759. * pause
  760. * finalization (defined by start time, ends manually)
  761. * done
  762. */
  763.  
  764. // The start of round 0 is set to 2017-01-24 19:00 of timezone Europe/Zurich
  765. uint public constant round0StartTime = 1484676000 + 1 weeks;
  766.  
  767. // The start of round 1 is set to 2017-05-17 19:00 of timezone Europe/Zurich
  768. // TZ="Europe/Zurich" date -d "2017-05-17 19:00" "+%s"
  769. uint public constant round1StartTime = 1495040400;
  770.  
  771. // Transition times that are defined by duration
  772. uint public constant round0EndTime = round0StartTime + 6 weeks;
  773. uint public constant round1EndTime = round1StartTime + 6 weeks;
  774. uint public constant finalizeStartTime = round1EndTime + 1 weeks;
  775.  
  776. // The finalization phase has a dummy end time because it is ended manually
  777. uint public constant finalizeEndTime = finalizeStartTime + 1000 years;
  778.  
  779. // The maximum time by which donation round 1 can be delayed from the start
  780. // time defined above
  781. uint public constant maxRoundDelay = 270 days;
  782.  
  783. // The time for which donation rounds remain open after they reach their
  784. // respective targets
  785. uint public constant gracePeriodAfterRound0Target = 1 days;
  786. uint public constant gracePeriodAfterRound1Target = 0 days;
  787.  
  788. /*
  789. * Token issuance
  790. *
  791. * The following configuration parameters completely govern all aspects of the
  792. * token issuance.
  793. */
  794.  
  795. // Tokens assigned for the equivalent of 1 CHF in donations
  796. uint public constant tokensPerCHF = 10;
  797.  
  798. // Minimal donation amount for a single on-chain donation
  799. uint public constant minDonation = 1 ether;
  800.  
  801. // Bonus in percent added to donations throughout donation round 0
  802. uint public constant round0Bonus = 200;
  803.  
  804. // Bonus in percent added to donations at beginning of donation round 1
  805. uint public constant round1InitialBonus = 25;
  806.  
  807. // Number of down-steps for the bonus during donation round 1
  808. uint public constant round1BonusSteps = 5;
  809.  
  810. // The CHF targets for each of the donation rounds, measured in cents of CHF
  811. uint public constant millionInCents = 10**6 * 100;
  812. uint public constant round0Target = 1 * millionInCents;
  813. uint public constant round1Target = 20 * millionInCents;
  814.  
  815. // Share of tokens eventually assigned to DFINITY Stiftung and early
  816. // contributors in % of all tokens eventually in existence
  817. uint public constant earlyContribShare = 22;
  818. }
  819.  
  820.  
  821. contract FDC is TokenTracker, Phased, StepFunction, Targets, Parameters {
  822. // An identifying string, set by the constructor
  823. string public name;
  824.  
  825. /*
  826. * Phases
  827. *
  828. * The FDC over its lifetime runs through a number of phases. These phases are
  829. * tracked by the base contract Phased.
  830. *
  831. * The FDC maps the chronologically defined phase numbers to semantically
  832. * defined states.
  833. */
  834.  
  835. // The FDC states
  836. enum state {
  837. pause, // Pause without any activity
  838. earlyContrib, // Registration of DFINITY Stiftung/early contributions
  839. round0, // Donation round 0
  840. round1, // Donation round 1
  841. offChainReg, // Grace period for registration of off-chain donations
  842. finalization, // Adjustment of DFINITY Stiftung/early contribution tokens
  843. // down to their share
  844. done // Read-only phase
  845. }
  846.  
  847. // Mapping from phase number (from the base contract Phased) to FDC state
  848. mapping(uint => state) stateOfPhase;
  849.  
  850. /*
  851. * Tokens
  852. *
  853. * The FDC uses base contract TokenTracker to:
  854. * - track token assignments for
  855. * - donors (unrestricted tokens)
  856. * - DFINITY Stiftung/early contributors (restricted tokens)
  857. * - convert DFINITY Stiftung/early contributor tokens down to their share
  858. *
  859. * The FDC uses the base contract Targets to:
  860. * - track the targets measured in CHF for each donation round
  861. *
  862. * The FDC itself:
  863. * - tracks the memos of off-chain donations (and prevents duplicates)
  864. * - tracks donor and early contributor addresses in two lists
  865. */
  866.  
  867. // Mapping to store memos that have been used
  868. mapping(bytes32 => bool) memoUsed;
  869.  
  870. // List of registered addresses (each address will appear in one)
  871. address[] public donorList;
  872. address[] public earlyContribList;
  873.  
  874. /*
  875. * Exchange rate and ether handling
  876. *
  877. * The FDC keeps track of:
  878. * - the exchange rate between ether and Swiss francs
  879. * - the total and per address ether donations
  880. */
  881.  
  882. // Exchange rate between ether and Swiss francs
  883. uint public weiPerCHF;
  884.  
  885. // Total number of Wei donated on-chain so far
  886. uint public totalWeiDonated;
  887.  
  888. // Mapping from address to total number of Wei donated for the address
  889. mapping(address => uint) public weiDonated;
  890.  
  891. /*
  892. * Access control
  893. *
  894. * The following three addresses have access to restricted functions of the
  895. * FDC and to the donated funds.
  896. */
  897.  
  898. // Wallet address to which on-chain donations are being forwarded
  899. address public foundationWallet;
  900.  
  901. // Address that is allowed to register DFINITY Stiftung/early contributions
  902. // and off-chain donations and to delay donation round 1
  903. address public registrarAuth;
  904.  
  905. // Address that is allowed to update the exchange rate
  906. address public exchangeRateAuth;
  907.  
  908. // Address that is allowed to update the other authenticated addresses
  909. address public masterAuth;
  910.  
  911. /*
  912. * Global variables
  913. */
  914.  
  915. // The phase numbers of the donation phases (set by the constructor,
  916. // thereafter constant)
  917. uint phaseOfRound0;
  918. uint phaseOfRound1;
  919.  
  920. /*
  921. * Events
  922. *
  923. * - DonationReceipt: logs an on-chain or off-chain donation
  924. * - EarlyContribReceipt: logs the registration of early contribution
  925. * - BurnReceipt: logs the burning of token during finalization
  926. */
  927. event DonationReceipt (address indexed addr, // DFN address of donor
  928. string indexed currency, // donation currency
  929. uint indexed bonusMultiplierApplied, // depends stage
  930. uint timestamp, // time occurred
  931. uint tokenAmount, // DFN to b recommended
  932. bytes32 memo); // unique note e.g TxID
  933. event EarlyContribReceipt (address indexed addr, // DFN address of donor
  934. uint tokenAmount, // *restricted* tokens
  935. bytes32 memo); // arbitrary note
  936. event BurnReceipt (address indexed addr, // DFN address adjusted
  937. uint tokenAmountBurned); // DFN deleted by adj.
  938.  
  939. /**
  940. * Constructor
  941. *
  942. * The constructor defines
  943. * - the privileged addresses for access control
  944. * - the phases in base contract Phased
  945. * - the mapping between phase numbers and states
  946. * - the targets in base contract Targets
  947. * - the share for early contributors in base contract TokenTracker
  948. * - the step function for the bonus calculation in donation round 1
  949. *
  950. * All configuration parameters are taken from base contract Parameters.
  951. */
  952. function FDC(address _masterAuth, string _name)
  953. TokenTracker(earlyContribShare)
  954. StepFunction(round1EndTime-round1StartTime, round1InitialBonus,
  955. round1BonusSteps)
  956. {
  957. /*
  958. * Set identifying string
  959. */
  960. name = _name;
  961.  
  962. /*
  963. * Set privileged addresses for access control
  964. */
  965. foundationWallet = _masterAuth;
  966. masterAuth = _masterAuth;
  967. exchangeRateAuth = _masterAuth;
  968. registrarAuth = _masterAuth;
  969.  
  970. /*
  971. * Initialize base contract Phased
  972. *
  973. * |------------------------- Phase number (0-7)
  974. * | |-------------------- State name
  975. * | | |---- Transition number (0-6)
  976. * V V V
  977. */
  978. stateOfPhase[0] = state.earlyContrib;
  979. addPhase(round0StartTime); // 0
  980. stateOfPhase[1] = state.round0;
  981. addPhase(round0EndTime); // 1
  982. stateOfPhase[2] = state.offChainReg;
  983. addPhase(round1StartTime); // 2
  984. stateOfPhase[3] = state.round1;
  985. addPhase(round1EndTime); // 3
  986. stateOfPhase[4] = state.offChainReg;
  987. addPhase(finalizeStartTime); // 4
  988. stateOfPhase[5] = state.finalization;
  989. addPhase(finalizeEndTime); // 5
  990. stateOfPhase[6] = state.done;
  991.  
  992. // Let the other functions know what phase numbers the donation rounds were
  993. // assigned to
  994. phaseOfRound0 = 1;
  995. phaseOfRound1 = 3;
  996.  
  997. // Maximum delay for start of donation rounds
  998. setMaxDelay(phaseOfRound0 - 1, maxRoundDelay);
  999. setMaxDelay(phaseOfRound1 - 1, maxRoundDelay);
  1000.  
  1001. /*
  1002. * Initialize base contract Targets
  1003. */
  1004. setTarget(phaseOfRound0, round0Target);
  1005. setTarget(phaseOfRound1, round1Target);
  1006. }
  1007.  
  1008. /*
  1009. * PUBLIC functions
  1010. *
  1011. * Un-authenticated:
  1012. * - getState
  1013. * - getMultiplierAtTime
  1014. * - donateAsWithChecksum
  1015. * - finalize
  1016. * - empty
  1017. * - getStatus
  1018. *
  1019. * Authenticated:
  1020. * - registerEarlyContrib
  1021. * - registerOffChainDonation
  1022. * - setExchangeRate
  1023. * - delayRound1
  1024. * - setFoundationWallet
  1025. * - setRegistrarAuth
  1026. * - setExchangeRateAuth
  1027. * - setAdminAuth
  1028. */
  1029.  
  1030. /**
  1031. * Get current state at the current block time
  1032. */
  1033. function getState() constant returns (state) {
  1034. return stateOfPhase[getPhaseAtTime(now)];
  1035. }
  1036.  
  1037. /**
  1038. * Return the bonus multiplier at a given time
  1039. *
  1040. * The given time must
  1041. * - lie in one of the donation rounds,
  1042. * - not lie in the future.
  1043. * Otherwise there is no valid multiplier.
  1044. */
  1045. function getMultiplierAtTime(uint time) constant returns (uint) {
  1046. // Get phase number (will throw if time lies in the future)
  1047. uint n = getPhaseAtTime(time);
  1048.  
  1049. // If time lies in donation round 0 we return the constant multiplier
  1050. if (stateOfPhase[n] == state.round0) {
  1051. return 100 + round0Bonus;
  1052. }
  1053.  
  1054. // If time lies in donation round 1 we return the step function
  1055. if (stateOfPhase[n] == state.round1) {
  1056. return 100 + getStepFunction(time - getPhaseStartTime(n));
  1057. }
  1058.  
  1059. // Throw outside of donation rounds
  1060. throw;
  1061. }
  1062.  
  1063. /**
  1064. * Send donation in the name a the given address with checksum
  1065. *
  1066. * The second argument is a checksum which must equal the first 4 bytes of the
  1067. * SHA-256 digest of the byte representation of the address.
  1068. */
  1069. function donateAsWithChecksum(address addr, bytes4 checksum)
  1070. payable
  1071. returns (bool)
  1072. {
  1073. // Calculate SHA-256 digest of the address
  1074. bytes32 hash = sha256(addr);
  1075.  
  1076. // Throw is the checksum does not match the first 4 bytes
  1077. if (bytes4(hash) != checksum) { throw ; }
  1078.  
  1079. // Call un-checksummed donate function
  1080. return donateAs(addr);
  1081. }
  1082.  
  1083. /**
  1084. * Finalize the balance for the given address
  1085. *
  1086. * This function triggers the conversion (and burn) of the restricted tokens
  1087. * that are assigned to the given address.
  1088. *
  1089. * This function is only available during the finalization phase. It manages
  1090. * the calls to closeAssignments() and unrestrict() of TokenTracker.
  1091. */
  1092. function finalize(address addr) {
  1093. // Throw if we are not in the finalization phase
  1094. if (getState() != state.finalization) { throw; }
  1095.  
  1096. // Close down further assignments in TokenTracker
  1097. closeAssignmentsIfOpen();
  1098.  
  1099. // Burn tokens
  1100. uint tokensBurned = unrestrict(addr);
  1101.  
  1102. // Issue burn receipt
  1103. BurnReceipt(addr, tokensBurned);
  1104.  
  1105. // If no restricted tokens left
  1106. if (isUnrestricted()) {
  1107. // then end the finalization phase immediately
  1108. endCurrentPhaseIn(0);
  1109. }
  1110. }
  1111.  
  1112. /**
  1113. * Send any remaining balance to the foundation wallet
  1114. */
  1115. function empty() returns (bool) {
  1116. return foundationWallet.call.value(this.balance)();
  1117. }
  1118.  
  1119. /**
  1120. * Get status information from the FDC
  1121. *
  1122. * This function returns a mix of
  1123. * - global status of the FDC
  1124. * - global status of the FDC specific for one of the two donation rounds
  1125. * - status related to a specific token address (DFINITY address)
  1126. * - status (balance) of an external Ethereum account
  1127. *
  1128. * Arguments are:
  1129. * - donationRound: donation round to query (0 or 1)
  1130. * - dfnAddr: token address to query
  1131. * - fwdAddr: external Ethereum address to query
  1132. */
  1133. function getStatus(uint donationRound, address dfnAddr, address fwdAddr)
  1134. public constant
  1135. returns (
  1136. state currentState, // current state (an enum)
  1137. uint fxRate, // exchange rate of CHF -> ETH (Wei/CHF)
  1138. uint currentMultiplier, // current bonus multiplier (0 if invalid)
  1139. uint donationCount, // total individual donations made (a count)
  1140. uint totalTokenAmount, // total DFN planned allocated to donors
  1141. uint startTime, // expected start time of specified donation round
  1142. uint endTime, // expected end time of specified donation round
  1143. bool isTargetReached, // whether round target has been reached
  1144. uint chfCentsDonated, // total value donated in specified round as CHF
  1145. uint tokenAmount, // total DFN planned allocted to donor (user)
  1146. uint fwdBalance, // total ETH (in Wei) waiting in fowarding address
  1147. uint donated) // total ETH (in Wei) donated by DFN address
  1148. {
  1149. // The global status
  1150. currentState = getState();
  1151. if (currentState == state.round0 || currentState == state.round1) {
  1152. currentMultiplier = getMultiplierAtTime(now);
  1153. }
  1154. fxRate = weiPerCHF;
  1155. donationCount = totalUnrestrictedAssignments;
  1156. totalTokenAmount = totalUnrestrictedTokens;
  1157.  
  1158. // The round specific status
  1159. if (donationRound == 0) {
  1160. startTime = getPhaseStartTime(phaseOfRound0);
  1161. endTime = getPhaseStartTime(phaseOfRound0 + 1);
  1162. isTargetReached = targetReached(phaseOfRound0);
  1163. chfCentsDonated = counter[phaseOfRound0];
  1164. } else {
  1165. startTime = getPhaseStartTime(phaseOfRound1);
  1166. endTime = getPhaseStartTime(phaseOfRound1 + 1);
  1167. isTargetReached = targetReached(phaseOfRound1);
  1168. chfCentsDonated = counter[phaseOfRound1];
  1169. }
  1170.  
  1171. // The status specific to the DFN address
  1172. tokenAmount = tokens[dfnAddr];
  1173. donated = weiDonated[dfnAddr];
  1174.  
  1175. // The status specific to the Ethereum address
  1176. fwdBalance = fwdAddr.balance;
  1177. }
  1178.  
  1179. /**
  1180. * Set the exchange rate between ether and Swiss francs in Wei per CHF
  1181. *
  1182. * Must be called from exchangeRateAuth.
  1183. */
  1184. function setWeiPerCHF(uint weis) {
  1185. // Require permission
  1186. if (msg.sender != exchangeRateAuth) { throw; }
  1187.  
  1188. // Set the global state variable for exchange rate
  1189. weiPerCHF = weis;
  1190. }
  1191.  
  1192. /**
  1193. * Register early contribution in the name of the given address
  1194. *
  1195. * Must be called from registrarAuth.
  1196. *
  1197. * Arguments are:
  1198. * - addr: address to the tokens are assigned
  1199. * - tokenAmount: number of restricted tokens to assign
  1200. * - memo: optional dynamic bytes of data to appear in the receipt
  1201. */
  1202. function registerEarlyContrib(address addr, uint tokenAmount, bytes32 memo) {
  1203. // Require permission
  1204. if (msg.sender != registrarAuth) { throw; }
  1205.  
  1206. // Reject registrations outside the early contribution phase
  1207. if (getState() != state.earlyContrib) { throw; }
  1208.  
  1209. // Add address to list if new
  1210. if (!isRegistered(addr, true)) {
  1211. earlyContribList.push(addr);
  1212. }
  1213.  
  1214. // Assign restricted tokens in TokenTracker
  1215. assign(addr, tokenAmount, true);
  1216.  
  1217. // Issue early contribution receipt
  1218. EarlyContribReceipt(addr, tokenAmount, memo);
  1219. }
  1220.  
  1221. /**
  1222. * Register off-chain donation in the name of the given address
  1223. *
  1224. * Must be called from registrarAuth.
  1225. *
  1226. * Arguments are:
  1227. * - addr: address to the tokens are assigned
  1228. * - timestamp: time when the donation came in (determines round and bonus)
  1229. * - chfCents: value of the donation in cents of Swiss francs
  1230. * - currency: the original currency of the donation (three letter string)
  1231. * - memo: optional bytes of data to appear in the receipt
  1232. *
  1233. * The timestamp must not be in the future. This is because the timestamp
  1234. * defines the donation round and the multiplier and future phase times are
  1235. * still subject to change.
  1236. *
  1237. * If called during a donation round then the timestamp must lie in the same
  1238. * phase and if called during the extended period for off-chain donations then
  1239. * the timestamp must lie in the immediately preceding donation round.
  1240. */
  1241. function registerOffChainDonation(address addr, uint timestamp, uint chfCents,
  1242. string currency, bytes32 memo)
  1243. {
  1244. // Require permission
  1245. if (msg.sender != registrarAuth) { throw; }
  1246.  
  1247. // The current phase number and state corresponding state
  1248. uint currentPhase = getPhaseAtTime(now);
  1249. state currentState = stateOfPhase[currentPhase];
  1250.  
  1251. // Reject registrations outside the two donation rounds (incl. their
  1252. // extended registration periods for off-chain donations)
  1253. if (currentState != state.round0 && currentState != state.round1 &&
  1254. currentState != state.offChainReg) {
  1255. throw;
  1256. }
  1257.  
  1258. // Throw if timestamp is in the future
  1259. if (timestamp > now) { throw; }
  1260.  
  1261. // Phase number and corresponding state of the timestamp
  1262. uint timestampPhase = getPhaseAtTime(timestamp);
  1263. state timestampState = stateOfPhase[timestampPhase];
  1264.  
  1265. // Throw if called during a donation round and the timestamp does not match
  1266. // that phase.
  1267. if ((currentState == state.round0 || currentState == state.round1) &&
  1268. (timestampState != currentState)) {
  1269. throw;
  1270. }
  1271.  
  1272. // Throw if called during the extended period for off-chain donations and
  1273. // the timestamp does not lie in the immediately preceding donation phase.
  1274. if (currentState == state.offChainReg && timestampPhase != currentPhase-1) {
  1275. throw;
  1276. }
  1277.  
  1278. // Throw if the memo is duplicated
  1279. if (memoUsed[memo]) {
  1280. throw;
  1281. }
  1282.  
  1283. // Set the memo item to true
  1284. memoUsed[memo] = true;
  1285.  
  1286. // Do the book-keeping
  1287. bookDonation(addr, timestamp, chfCents, currency, memo);
  1288. }
  1289.  
  1290. /**
  1291. * Delay a donation round
  1292. *
  1293. * Must be called from the address registrarAuth.
  1294. *
  1295. * This function delays the start of donation round 1 by the given time delta
  1296. * unless the time delta is bigger than the configured maximum delay.
  1297. */
  1298. function delayDonPhase(uint donPhase, uint timedelta) {
  1299. // Require permission
  1300. if (msg.sender != registrarAuth) { throw; }
  1301.  
  1302. // Pass the call on to base contract Phased
  1303. // Delaying the start of a donation round is the same as delaying the end
  1304. // of the preceding phase
  1305. if (donPhase == 0) {
  1306. delayPhaseEndBy(phaseOfRound0 - 1, timedelta);
  1307. } else if (donPhase == 1) {
  1308. delayPhaseEndBy(phaseOfRound1 - 1, timedelta);
  1309. }
  1310. }
  1311.  
  1312. /**
  1313. * Set the forwarding address for donated ether
  1314. *
  1315. * Must be called from the address masterAuth before donation round 0 starts.
  1316. */
  1317. function setFoundationWallet(address newAddr) {
  1318. // Require permission
  1319. if (msg.sender != masterAuth) { throw; }
  1320.  
  1321. // Require phase before round 0
  1322. if (getPhaseAtTime(now) >= phaseOfRound0) { throw; }
  1323.  
  1324. foundationWallet = newAddr;
  1325. }
  1326.  
  1327. /**
  1328. * Set new authenticated address for setting exchange rate
  1329. *
  1330. * Must be called from the address masterAuth.
  1331. */
  1332. function setExchangeRateAuth(address newAuth) {
  1333. // Require permission
  1334. if (msg.sender != masterAuth) { throw; }
  1335.  
  1336. exchangeRateAuth = newAuth;
  1337. }
  1338.  
  1339. /**
  1340. * Set new authenticated address for registrations
  1341. *
  1342. * Must be called from the address masterAuth.
  1343. */
  1344. function setRegistrarAuth(address newAuth) {
  1345. // Require permission
  1346. if (msg.sender != masterAuth) { throw; }
  1347.  
  1348. registrarAuth = newAuth;
  1349. }
  1350.  
  1351. /**
  1352. * Set new authenticated address for admin
  1353. *
  1354. * Must be called from the address masterAuth.
  1355. */
  1356. function setMasterAuth(address newAuth) {
  1357. // Require permission
  1358. if (msg.sender != masterAuth) { throw; }
  1359.  
  1360. masterAuth = newAuth;
  1361. }
  1362.  
  1363. /*
  1364. * PRIVATE functions
  1365. *
  1366. * - donateAs
  1367. * - bookDonation
  1368. */
  1369.  
  1370. /**
  1371. * Process on-chain donation in the name of the given address
  1372. *
  1373. * This function is private because it shall only be called through its
  1374. * wrapper donateAsWithChecksum.
  1375. */
  1376. function donateAs(address addr) private returns (bool) {
  1377. // The current state
  1378. state st = getState();
  1379.  
  1380. // Throw if current state is not a donation round
  1381. if (st != state.round0 && st != state.round1) { throw; }
  1382.  
  1383. // Throw if donation amount is below minimum
  1384. if (msg.value < minDonation) { throw; }
  1385.  
  1386. // Throw if the exchange rate is not yet defined
  1387. if (weiPerCHF == 0) { throw; }
  1388.  
  1389. // Update counters for ether donations
  1390. totalWeiDonated += msg.value;
  1391. weiDonated[addr] += msg.value;
  1392.  
  1393. // Convert ether to Swiss francs
  1394. uint chfCents = (msg.value * 100) / weiPerCHF;
  1395.  
  1396. // Do the book-keeping
  1397. bookDonation(addr, now, chfCents, "ETH", "");
  1398.  
  1399. // Forward balance to the foundation wallet
  1400. return foundationWallet.call.value(this.balance)();
  1401. }
  1402.  
  1403. /**
  1404. * Put an accepted donation in the books.
  1405. *
  1406. * This function
  1407. * - cannot throw as all checks have been done before,
  1408. * - is agnostic to the source of the donation (on-chain or off-chain)
  1409. * - is agnostic to the currency
  1410. * (the currency argument is simply passed through to the DonationReceipt)
  1411. *
  1412. */
  1413. function bookDonation(address addr, uint timestamp, uint chfCents,
  1414. string currency, bytes32 memo) private
  1415. {
  1416. // The current phase
  1417. uint phase = getPhaseAtTime(timestamp);
  1418.  
  1419. // Add amount to the counter of the current phase
  1420. bool targetReached = addTowardsTarget(phase, chfCents);
  1421.  
  1422. // If the target was crossed then start the grace period
  1423. if (targetReached && phase == getPhaseAtTime(now)) {
  1424. if (phase == phaseOfRound0) {
  1425. endCurrentPhaseIn(gracePeriodAfterRound0Target);
  1426. } else if (phase == phaseOfRound1) {
  1427. endCurrentPhaseIn(gracePeriodAfterRound1Target);
  1428. }
  1429. }
  1430.  
  1431. // Bonus multiplier that was valid at the given time
  1432. uint bonusMultiplier = getMultiplierAtTime(timestamp);
  1433.  
  1434. // Apply bonus to amount in Swiss francs
  1435. chfCents = (chfCents * bonusMultiplier) / 100;
  1436.  
  1437. // Convert Swiss francs to amount of tokens
  1438. uint tokenAmount = (chfCents * tokensPerCHF) / 100;
  1439.  
  1440. // Add address to list if new
  1441. if (!isRegistered(addr, false)) {
  1442. donorList.push(addr);
  1443. }
  1444.  
  1445. // Assign unrestricted tokens in TokenTracker
  1446. assign(addr,tokenAmount,false);
  1447.  
  1448. // Issue donation receipt
  1449. DonationReceipt(addr, currency, bonusMultiplier, timestamp, tokenAmount,
  1450. memo);
  1451. }
  1452. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement