pruby

BidBasedCrowdSale.sol

Oct 25th, 2016
258
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.32 KB | None | 0 0
  1. contract Token {
  2.  
  3. /// @return total amount of tokens
  4. function totalSupply() constant returns (uint256 supply) {}
  5.  
  6. /// @param _owner The address from which the balance will be retrieved
  7. /// @return The balance
  8. function balanceOf(address _owner) constant returns (uint256 balance) {}
  9.  
  10. /// @notice send `_value` token to `_to` from `msg.sender`
  11. /// @param _to The address of the recipient
  12. /// @param _value The amount of token to be transferred
  13. /// @return Whether the transfer was successful or not
  14. function transfer(address _to, uint256 _value) returns (bool success) {}
  15.  
  16. /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
  17. /// @param _from The address of the sender
  18. /// @param _to The address of the recipient
  19. /// @param _value The amount of token to be transferred
  20. /// @return Whether the transfer was successful or not
  21. function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
  22.  
  23. /// @notice `msg.sender` approves `_addr` to spend `_value` tokens
  24. /// @param _spender The address of the account able to transfer the tokens
  25. /// @param _value The amount of wei to be approved for transfer
  26. /// @return Whether the approval was successful or not
  27. function approve(address _spender, uint256 _value) returns (bool success) {}
  28.  
  29. /// @param _owner The address of the account owning tokens
  30. /// @param _spender The address of the account able to transfer the tokens
  31. /// @return Amount of remaining tokens allowed to spent
  32. function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
  33.  
  34. event Transfer(address indexed _from, address indexed _to, uint256 _value);
  35. event Approval(address indexed _owner, address indexed _spender, uint256 _value);
  36. }
  37.  
  38. library Heap {
  39. function siftDown(uint[] storage entries, uint[] storage priorities, uint count, uint idx) internal {
  40. uint entry;
  41. uint priority;
  42. while (idx < count) {
  43. uint c1 = idx * 2 + 1;
  44. uint c2 = c1 + 1;
  45. if (c1 < count && priorities[c1] < priorities[idx]) {
  46. // Sift down to left child
  47. entry = entries[c1];
  48. priority = priorities[c1];
  49. entries[c1] = entries[idx];
  50. priorities[c1] = priorities[idx];
  51. entries[idx] = entry;
  52. priorities[idx] = priority;
  53. idx = c1;
  54. } else if (c2 < count && priorities[c2] < priorities[idx]) {
  55. // Sift down to right child
  56. entry = entries[c2];
  57. priority = priorities[c2];
  58. entries[c2] = entries[idx];
  59. priorities[c2] = priorities[idx];
  60. entries[idx] = entry;
  61. priorities[idx] = priority;
  62. idx = c2;
  63. } else {
  64. return;
  65. }
  66. }
  67. }
  68.  
  69. function bubbleUp(uint[] storage entries, uint[] storage priorities, uint idx) internal {
  70. uint maxIdx = entries.length - 1;
  71. uint entry;
  72. uint priority;
  73. while (idx > 0) {
  74. uint p = (idx - 1) / 2;
  75. if (priorities[p] >= priorities[idx]) {
  76. // Bubble up to the parent
  77. entry = entries[p];
  78. priority = priorities[p];
  79. entries[p] = entries[idx];
  80. priorities[p] = priorities[idx];
  81. entries[idx] = entry;
  82. priorities[idx] = priority;
  83. idx = p;
  84. } else {
  85. return;
  86. }
  87. }
  88. }
  89. }
  90.  
  91. contract BidBasedCrowdSale {
  92. uint public totalUnits;
  93. uint public unitsSold;
  94. uint public lotSize;
  95. uint public minimumPrice;
  96. uint public priceIncrement;
  97. uint public deadline;
  98. Token public currency;
  99. Token public reward;
  100.  
  101. struct Bid {
  102. address bidder;
  103. uint unitsBid;
  104. uint priceBid;
  105. uint unitsAllocated;
  106. bool redeemed;
  107. }
  108.  
  109. Bid[] public bids;
  110. uint[] public bidHeap;
  111. uint[] public bidHeapPriorities;
  112. uint public bidHeapCount;
  113.  
  114. function getBidCount() returns (uint) {
  115. return bids.length;
  116. }
  117.  
  118. function BidBasedCrowdSale(Token _reward, Token _currency, uint _totalUnits, uint _lotSize, uint _minimumPrice, uint _priceIncrement, uint _deadline) {
  119. reward = _reward;
  120. currency = _currency;
  121. totalUnits = _totalUnits;
  122. lotSize = _lotSize;
  123. minimumPrice = _minimumPrice;
  124. priceIncrement = _priceIncrement;
  125. unitsSold = 0;
  126. deadline = _deadline;
  127. }
  128.  
  129. modifier beforeDeadline() {
  130. if (now < deadline) _;
  131. }
  132.  
  133. modifier afterDeadline() {
  134. if (now >= deadline) _;
  135. }
  136.  
  137. event BidAccepted(uint, address, uint, uint);
  138. event BidExceeded(uint, address, uint);
  139. function bid(uint128 amount, uint128 price) beforeDeadline returns (uint) {
  140. if ((amount < lotSize) || (amount % lotSize != 0)) {
  141. throw;
  142. }
  143.  
  144. /*
  145. if (amount > totalUnits) {
  146. throw;
  147. }
  148. */
  149.  
  150. if ((price < minimumPrice) || (price % priceIncrement != 0)) {
  151. throw;
  152. }
  153.  
  154. if (!currency.transferFrom(msg.sender, this, amount * price)) {
  155. throw;
  156. }
  157.  
  158. uint freeUnits = totalUnits - unitsSold;
  159. if (freeUnits > amount) {
  160. freeUnits = amount;
  161. }
  162. unitsSold += freeUnits;
  163.  
  164. uint priority = (((uint) (price)) * 18446744073709551616) + ((uint64) (deadline - now));
  165. while (amount > freeUnits && bidHeapCount > 0 && bidHeapPriorities[0] < priority) {
  166. uint available = bids[bidHeap[0]].unitsAllocated;
  167. uint returnAmount;
  168. if (freeUnits + available > amount) {
  169. // Remove the amount required from this bid, leaves a non-zero amount
  170. returnAmount = amount - freeUnits;
  171. bids[bidHeap[0]].unitsAllocated -= returnAmount;
  172. BidExceeded(bidHeap[0], bids[bidHeap[0]].bidder, bids[bidHeap[0]].unitsAllocated);
  173. currency.transfer(bids[bidHeap[0]].bidder, (amount - freeUnits) * bids[bidHeap[0]].priceBid);
  174. freeUnits = amount;
  175. } else {
  176. // This bid must be removed to make way for the new one
  177. returnAmount = bids[bidHeap[0]].unitsAllocated;
  178. BidExceeded(bidHeap[0], bids[bidHeap[0]].bidder, 0);
  179. currency.transfer(bids[bidHeap[0]].bidder, (amount - freeUnits) * bids[bidHeap[0]].priceBid);
  180. bids[bidHeap[0]].unitsAllocated = 0;
  181.  
  182. // Remove the current minimum bid
  183. bidHeapCount--;
  184. bidHeap[0] = bidHeap[bidHeapCount];
  185. bidHeapPriorities[0] = bidHeapPriorities[bidHeapCount];
  186. Heap.siftDown(bidHeap, bidHeapPriorities, bidHeapCount, 0);
  187.  
  188. freeUnits += available;
  189. }
  190. }
  191.  
  192. if (freeUnits > 0) {
  193. // Insert the new bid
  194. uint bidId = bids.length;
  195. bids.push(Bid(msg.sender, amount, price, freeUnits, false));
  196. if (bidHeap.length <= bidHeapCount) {
  197. bidHeap.push(bidId);
  198. bidHeapPriorities.push(priority);
  199. } else {
  200. bidHeap[bidHeapCount] = bidId;
  201. bidHeapPriorities[bidHeapCount] = priority;
  202. }
  203. Heap.bubbleUp(bidHeap, bidHeapPriorities, bidHeapCount);
  204. bidHeapCount++;
  205.  
  206. BidAccepted(bidId, msg.sender, freeUnits, price);
  207. }
  208.  
  209. uint unallocated = amount - freeUnits;
  210. if (unallocated > 0) {
  211. currency.transfer(msg.sender, unallocated * price);
  212. }
  213. }
  214.  
  215. function recoverUnits(uint bidId) afterDeadline {
  216. if (bidId >= bids.length) {
  217. throw;
  218. }
  219.  
  220. Bid storage bid = bids[bidId];
  221. if (bid.unitsAllocated > 0 && !bid.redeemed) {
  222. bid.redeemed = true;
  223. reward.transfer(bid.bidder, bid.unitsAllocated);
  224. }
  225. }
  226. }
Advertisement
Add Comment
Please, Sign In to add comment