Guest User

Untitled

a guest
Apr 5th, 2022
747
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.04 KB | None | 0 0
  1. pragma solidity ^ 0.6.6;
  2. /*
  3. ,/`.
  4. ,'/ __`.
  5. ,'_/__ _ _`.
  6. ,'__/__ _ _ _`.
  7. ,'_ /___ __ _ __ `.
  8. '-.._/___ _ __ __ __`.
  9. */
  10.  
  11. contract ColorToken{
  12.  
  13. mapping(address => uint256) public balances;
  14. mapping(address => uint256) public red;
  15. mapping(address => uint256) public green;
  16. mapping(address => uint256) public blue;
  17.  
  18. uint public _totalSupply;
  19.  
  20. mapping(address => mapping(address => uint)) approvals;
  21.  
  22. event Transfer(
  23. address indexed from,
  24. address indexed to,
  25. uint256 amount,
  26. bytes data
  27. );
  28. event Transfer(
  29. address indexed from,
  30. address indexed to,
  31. uint256 amount
  32. );
  33.  
  34. function totalSupply() public view returns (uint256) {
  35. return _totalSupply;
  36. }
  37.  
  38. function balanceOf(address _owner) public view returns (uint256 balance) {
  39. return balances[_owner];
  40. }
  41.  
  42. function addColor(address addr, uint amount, uint _red, uint _green, uint _blue) internal {
  43. //adding color values to balance
  44. red[addr] += _red * amount;
  45. green[addr] += _green * amount;
  46. blue[addr] += _blue * amount;
  47. }
  48.  
  49.  
  50. function RGB_Ratio() public view returns(uint,uint,uint){
  51. return RGB_Ratio(msg.sender);
  52. }
  53.  
  54. function RGB_Ratio(address addr) public view returns(uint,uint,uint){
  55. //returns the color of one's tokens
  56. uint weight = balances[addr];
  57. if (weight == 0){
  58. return (0,0,0);
  59. }
  60. return ( red[addr]/weight, green[addr]/weight, blue[addr]/weight);
  61. }
  62.  
  63. function RGB_scale(address addr, uint numerator, uint denominator) internal view returns(uint,uint,uint){
  64. return (red[addr] * numerator / denominator, green[addr] * numerator / denominator, blue[addr] * numerator / denominator);
  65. }
  66.  
  67. // Function that is called when a user or another contract wants to transfer funds.
  68. function transfer(address _to, uint _value, bytes memory _data) public virtual returns (bool) {
  69. if( isContract(_to) ){
  70. return transferToContract(_to, _value, _data);
  71. }else{
  72. return transferToAddress(_to, _value, _data);
  73. }
  74. }
  75.  
  76. // Standard function transfer similar to ERC20 transfer with no _data.
  77. // Added due to backwards compatibility reasons.
  78. function transfer(address _to, uint _value) public virtual returns (bool) {
  79. //standard function transfer similar to ERC20 transfer with no _data
  80. //added due to backwards compatibility reasons
  81. bytes memory empty;
  82. if(isContract(_to)){
  83. return transferToContract(_to, _value, empty);
  84. }else{
  85. return transferToAddress(_to, _value, empty);
  86. }
  87. }
  88.  
  89.  
  90.  
  91. //function that is called when transaction target is an address
  92. function transferToAddress(address _to, uint _value, bytes memory _data) private returns (bool) {
  93. moveTokens(msg.sender, _to, _value);
  94. emit Transfer(msg.sender, _to, _value, _data);
  95. emit Transfer(msg.sender, _to, _value);
  96. return true;
  97. }
  98.  
  99. //function that is called when transaction target is a contract
  100. function transferToContract(address _to, uint _value, bytes memory _data) private returns (bool) {
  101. moveTokens(msg.sender, _to, _value);
  102. ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
  103. receiver.tokenFallback(msg.sender, _value, _data);
  104. emit Transfer(msg.sender, _to, _value, _data);
  105. emit Transfer(msg.sender, _to, _value);
  106. return true;
  107. }
  108.  
  109. function colorTransfer(address _to, uint _value) public virtual returns(uint R, uint G, uint B){
  110. (R, G, B) = moveTokens(msg.sender, _to, _value);
  111. ColorReceivingContract(_to).colorFallback(msg.sender, _value, R, G, B);
  112.  
  113. emit Transfer(msg.sender, _to, _value);
  114. }
  115.  
  116. function moveTokens(address _from, address _to, uint _amount) internal virtual returns(uint red_ratio, uint green_ratio, uint blue_ratio){
  117. require( _amount <= balances[_from] );
  118.  
  119. //mix colors
  120. (red_ratio, green_ratio, blue_ratio) = RGB_scale( _from, _amount, balances[_from] );
  121. red[_from] -= red_ratio;
  122. green[_from] -= green_ratio;
  123. blue[_from] -= blue_ratio;
  124. red[_to] += red_ratio;
  125. green[_to] += green_ratio;
  126. blue[_to] += blue_ratio;
  127.  
  128. //update balances
  129. balances[_from] -= _amount;
  130. balances[_to] += _amount;
  131. }
  132.  
  133. function allowance(address source, address spender) public view returns (uint) {
  134. return approvals[source][spender];
  135. }
  136.  
  137. function transferFrom(address source, address destination, uint amount) public returns (bool){
  138. address sender = msg.sender;
  139. require(approvals[source][sender] >= amount);
  140. require(balances[source] >= amount);
  141. approvals[source][sender] -= amount;
  142. moveTokens(source,destination,amount);
  143. bytes memory empty;
  144. emit Transfer(sender, destination, amount, empty);
  145. return true;
  146. }
  147.  
  148. event Approval(address indexed source, address indexed spender, uint amount);
  149. function approve(address spender, uint amount) public returns (bool) {
  150. address sender = msg.sender;
  151. approvals[sender][spender] = amount;
  152.  
  153. emit Approval( sender, spender, amount );
  154. return true;
  155. }
  156.  
  157. function isContract(address _addr) public view returns (bool is_contract) {
  158. uint length;
  159. assembly {
  160. //retrieve the size of the code on target address, this needs assembly
  161. length := extcodesize(_addr)
  162. }
  163. if(length>0) {
  164. return true;
  165. }else {
  166. return false;
  167. }
  168. }
  169. }
  170.  
  171. contract DAO_Core is ColorToken{
  172. // scaleFactor is used to convert Poly into bonds and vice-versa: they're of different
  173. // orders of magnitude, hence the need to bridge between the two.
  174. uint256 constant scaleFactor = 0x10000000000000000;
  175. address payable address0 = address(0);
  176.  
  177. // Slope of bonding curve
  178. uint256 constant internal tokenPriceInitial = 0.0000001 ether;
  179. uint256 constant internal tokenPriceIncremental = 0.00000001 ether;
  180.  
  181. // ERC20 standard
  182. string constant public name = "Bonds";
  183. string constant public symbol = "BOND";
  184. uint8 constant public decimals = 18;
  185.  
  186. mapping(address => uint256) public averagePolySpent;
  187. // For calculating hodl multiplier that factors into resolves minted
  188. mapping(address => uint256) public averageBuyInTimeSum;
  189. // Array between each address and their number of resolves being staked.
  190. mapping(address => uint256) public resolveWeight;
  191.  
  192. function viewAccount(address acc) public view returns(uint _balance,uint _resolveBalance, uint _resolveWeight, uint resolveEarnings, uint _averagePolySpent, uint _averageBuyInTimeSum){
  193. return (balanceOf(acc),resolveToken.balanceOf(acc),resolveWeight[acc],resolveEarnings(acc),averagePolySpent[acc],averageBuyInTimeSum[acc]);
  194. }
  195.  
  196.  
  197. // Array between each address and how much Poly has been paid out to it.
  198. // Note that this is scaled by the scaleFactor variable.
  199. mapping(address => int256) public payouts;
  200.  
  201. //Fee only happens on buy. Dividends happen on buy and sell
  202. mapping(address => uint256) public sellSideEarnings;
  203.  
  204. // The total number of resolves being staked in this contract
  205. uint256 public stakedResolves;
  206.  
  207. // For calculating the hodl multiplier. Weighted average release time
  208. uint public sumOfInputPOLY;
  209. uint public sumOfInputTime;
  210. uint public sumOfOutputPOLY;
  211. uint public sumOfOutputTime;
  212.  
  213. // Something about invarience.
  214. int256 public earningsOffset;
  215.  
  216. // Variable tracking how much Poly each token is currently worth
  217. // Note that this is scaled by the scaleFactor variable.
  218. uint256 public earningsPerResolve;
  219.  
  220. //The resolve token contract
  221. ResolveToken public resolveToken;
  222.  
  223. constructor() public{
  224. resolveToken = new ResolveToken( address(this) );
  225. }
  226.  
  227. function frictionFee(uint paidAmount) public view returns(uint fee) {
  228. //we're only going to count resolve tokens that haven't been burned.
  229. uint totalResolveSupply = resolveToken.totalSupply() - resolveToken.balanceOf( address(0) );
  230. if ( stakedResolves == 0 )
  231. return 0;
  232.  
  233. //the fee is the % of resolve tokens outside of the contract
  234. return paidAmount * ( totalResolveSupply - stakedResolves ) / totalResolveSupply * sumOfOutputPOLY / sumOfInputPOLY;
  235. }
  236.  
  237. // Converts the Poly accrued as resolveEarnings back into bonds without having to
  238. // withdraw it first. Saves on gas and potential price spike loss.
  239. event Reinvest( address indexed addr, uint256 reinvested, uint256 dissolved, uint256 bonds, uint256 resolveTax);
  240. function reinvestEarnings(uint amountFromEarnings) public returns(uint,uint){
  241. address sender = msg.sender;
  242. // Retrieve the resolveEarnings associated with the address the request came from.
  243. uint upScaleDividends = (uint)((int256)( earningsPerResolve * resolveWeight[sender] ) - payouts[sender]);
  244. uint totalEarnings = upScaleDividends / scaleFactor;//resolveEarnings(sender);
  245. require(amountFromEarnings <= totalEarnings, "the amount exceeds total earnings");
  246. uint oldWeight = resolveWeight[sender];
  247. resolveWeight[sender] = oldWeight * (totalEarnings - amountFromEarnings) / totalEarnings;
  248. uint weightDiff = oldWeight - resolveWeight[sender];
  249. resolveToken.transfer( address0, weightDiff );
  250. stakedResolves -= weightDiff;
  251.  
  252. // updating payouts based on weight of staked resolves
  253. int withdrawnEarnings = (int)(upScaleDividends * amountFromEarnings / totalEarnings) - (int)(weightDiff*earningsPerResolve);
  254. payouts[sender] += withdrawnEarnings;
  255. // Increase the total amount that's been paid out to maintain invariance.
  256. earningsOffset += withdrawnEarnings;
  257.  
  258. // Assign balance to a new variable.
  259. uint value_ = (uint) (amountFromEarnings);
  260.  
  261. // If your resolveEarnings are worth less than 1 szabo, abort.
  262. if (value_ < 0.000001 ether)
  263. revert();
  264.  
  265. // Calculate the fee
  266. uint fee = frictionFee(value_);
  267.  
  268. // The amount of Poly used to purchase new bonds for the caller
  269. uint numPoly = value_ - fee;
  270.  
  271. //resolve reward tracking
  272. averagePolySpent[sender] += numPoly;
  273. averageBuyInTimeSum[sender] += now * scaleFactor * numPoly;
  274. sumOfInputPOLY += numPoly;
  275. sumOfInputTime += now * scaleFactor * numPoly;
  276.  
  277. // The number of bonds which can be purchased for numPoly.
  278. uint createdBonds = PolyToTokens(numPoly);
  279. uint[] memory RGB = new uint[](3);
  280. (RGB[0], RGB[1], RGB[2]) = RGB_Ratio(sender);
  281.  
  282. addColor(sender, createdBonds, RGB[0], RGB[1], RGB[2]);
  283.  
  284. // the amount to be paid to stakers
  285. uint resolveFee;
  286.  
  287. // Check if we have resolves that are staked
  288. if ( stakedResolves > 0 ) {
  289. resolveFee = fee/2 * scaleFactor;
  290. sellSideEarnings[sender] += fee/2;
  291.  
  292. // Fee is distributed to all existing resolve stakers before the new bonds are purchased.
  293. // rewardPerResolve is the amount(POLY) gained per resolve token from this purchase.
  294. uint rewardPerResolve = resolveFee / stakedResolves;
  295.  
  296. // The Poly value per token is increased proportionally.
  297. earningsPerResolve += rewardPerResolve;
  298. }
  299.  
  300. // Add the createdBonds to the total supply.
  301. _totalSupply += createdBonds;
  302.  
  303. // Assign the bonds to the balance of the buyer.
  304. balances[sender] += createdBonds;
  305.  
  306. emit Reinvest(sender, value_, weightDiff, createdBonds, resolveFee);
  307. return (createdBonds, weightDiff);
  308. }
  309.  
  310. // Sells your bonds for Poly
  311. function sellAllBonds() public returns(uint returnedPoly, uint returned_resolves, uint initialInputPoly){
  312. return sell( balanceOf(msg.sender) );
  313. }
  314.  
  315. function sellBonds(uint amount) public returns(uint returnedPoly, uint returned_resolves, uint initialInputPoly){
  316. require(balanceOf(msg.sender) >= amount, "Amount is more than balance");
  317. ( returnedPoly, returned_resolves, initialInputPoly ) = sell(amount);
  318. return (returnedPoly, returned_resolves, initialInputPoly);
  319. }
  320.  
  321. // Big red exit button to pull all of a holder's Poly value from the contract
  322. function getMeOutOfHere() public {
  323. sellAllBonds();
  324. withdraw( resolveEarnings(msg.sender) );
  325. }
  326.  
  327. // Gatekeeper function to check if the amount of Poly being sent isn't too small
  328. function fund() payable public returns(uint createdBonds){
  329. uint[] memory RGB = new uint[](3);
  330. (RGB[0], RGB[1], RGB[2]) = RGB_Ratio(msg.sender);
  331. return buy(msg.sender, RGB[0], RGB[1], RGB[2]);
  332. }
  333.  
  334. // Calculate the current resolveEarnings associated with the caller address. This is the net result
  335. // of multiplying the number of resolves held by their current value in Poly and subtracting the
  336. // Poly that has already been paid out.
  337. function resolveEarnings(address _owner) public view returns (uint256 amount) {
  338. return (uint256) ((int256)(earningsPerResolve * resolveWeight[_owner]) - payouts[_owner]) / scaleFactor;
  339. }
  340.  
  341. event Buy( address indexed addr, uint256 spent, uint256 bonds, uint256 resolveTax);
  342. function buy(address addr, uint _red, uint _green, uint _blue) public payable returns(uint createdBonds){
  343. //make sure the color components don't exceed limits
  344. if(_red>1e18) _red = 1e18;
  345. if(_green>1e18) _green = 1e18;
  346. if(_blue>1e18) _blue = 1e18;
  347.  
  348. // Any transaction of less than 1 szabo is likely to be worth less than the gas used to send it.
  349. if ( msg.value < 0.000001 ether )
  350. revert();
  351.  
  352. // Calculate the fee
  353. uint fee = frictionFee(msg.value);
  354.  
  355. // The amount of Poly used to purchase new bonds for the caller.
  356. uint numPoly = msg.value;
  357.  
  358.  
  359. numPoly = numPoly - fee;
  360.  
  361. //resolve reward tracking stuff
  362. uint currentTime = now;
  363. averagePolySpent[addr] += numPoly;
  364. averageBuyInTimeSum[addr] += currentTime * scaleFactor * numPoly;
  365. sumOfInputPOLY += numPoly;
  366. sumOfInputTime += currentTime * scaleFactor * numPoly;
  367.  
  368. // The number of bonds which can be purchased for numPoly.
  369. createdBonds = PolyToTokens(numPoly);
  370. addColor(addr, createdBonds, _red, _green, _blue);
  371.  
  372. // Add the createdBonds to the total supply.
  373. _totalSupply += createdBonds;
  374.  
  375. // Assign the bonds to the balance of the buyer.
  376. balances[addr] += createdBonds;
  377.  
  378. // Check for resolves staked
  379. uint resolveFee;
  380. if (stakedResolves > 0) {
  381. resolveFee = fee/2 * scaleFactor;
  382. sellSideEarnings[addr] += fee/2;
  383.  
  384. // Fee is distributed to all existing resolve holders before the new bonds are purchased.
  385. // rewardPerResolve is the amount gained per resolve token from this purchase.
  386. uint rewardPerResolve = resolveFee/stakedResolves;
  387.  
  388. // The Poly value per resolve is increased proportionally.
  389. earningsPerResolve += rewardPerResolve;
  390. }
  391. emit Transfer(address(0), addr, createdBonds);
  392. emit Buy( addr, msg.value, createdBonds, resolveFee);
  393. return createdBonds;
  394. }
  395.  
  396. function avgHodl() public view returns(uint hodlTime){
  397. return now - (sumOfInputTime - sumOfOutputTime) / (sumOfInputPOLY - sumOfOutputPOLY) / scaleFactor;
  398. }
  399.  
  400. function getReturnsForBonds(address addr, uint bondsReleased) public view returns(uint PolyValue, uint mintedResolves, uint new_releaseTimeSum, uint new_releaseAmount, uint initialInputPoly){
  401. uint outputPoly = tokensToPoly(bondsReleased);
  402. uint inputPoly = averagePolySpent[addr] * bondsReleased / balances[addr];
  403. // hodl multiplier. because if you don't hodl at all, you shouldn't be rewarded resolves.
  404. // and the multiplier you get for hodling needs to be relative to the average hodl
  405. uint buyInTime = averageBuyInTimeSum[addr] / averagePolySpent[addr];
  406. uint cashoutTime = now * scaleFactor - buyInTime;
  407. uint new_sumOfOutputTime = sumOfOutputTime + averageBuyInTimeSum[addr] * bondsReleased / balances[addr];
  408. uint new_sumOfOutputPOLY = sumOfOutputPOLY + inputPoly;
  409. uint averageHoldingTime = now * scaleFactor - ( sumOfInputTime - sumOfOutputTime ) / ( sumOfInputPOLY - sumOfOutputPOLY );
  410. return (outputPoly,
  411.  
  412.  
  413.  
  414. inputPoly
  415. * cashoutTime / averageHoldingTime
  416. * inputPoly / outputPoly,
  417.  
  418.  
  419.  
  420. new_sumOfOutputTime, new_sumOfOutputPOLY, inputPoly);
  421. }
  422.  
  423. event Sell( address indexed addr, uint256 bondsSold, uint256 cashout, uint256 resolves, uint256 resolveTax, uint256 initialCash);
  424. function sell(uint256 amount) internal returns(uint poly, uint resolves, uint initialInput){
  425. address payable sender = msg.sender;
  426. // Calculate the amount of Poly & Resolves that the holder's bonds sell for at the current sell price.
  427.  
  428. uint _sellSideEarnings = sellSideEarnings[sender] * amount / balances[sender];
  429. sellSideEarnings[sender] -= _sellSideEarnings;
  430.  
  431. uint[] memory UINTs = new uint[](5);
  432. (
  433. UINTs[0]/*Poly out*/,
  434. UINTs[1]/*minted resolves*/,
  435. UINTs[2]/*new_sumOfOutputTime*/,
  436. UINTs[3]/*new_sumOfOutputPOLY*/,
  437. UINTs[4]/*initialInputPoly*/) = getReturnsForBonds(sender, amount);
  438.  
  439. // magic distribution
  440. uint[] memory RGB = new uint[](3);
  441. (RGB[0], RGB[1], RGB[2]) = RGB_Ratio(sender);
  442. resolveToken.mint(sender, UINTs[1]/*minted resolves*/, RGB[0], RGB[1], RGB[2]);
  443.  
  444. // update weighted average cashout time
  445. sumOfOutputTime = UINTs[2]/*new_sumOfOutputTime*/;
  446. sumOfOutputPOLY = UINTs[3] /*new_sumOfOutputPOLY*/;
  447.  
  448. // reduce the amount of "poly spent" based on the percentage of bonds being sold back into the contract
  449. averagePolySpent[sender] = averagePolySpent[sender] * ( balances[sender] - amount) / balances[sender];
  450. // reduce the "buyInTime" sum that's used for average buy in time
  451. averageBuyInTimeSum[sender] = averageBuyInTimeSum[sender] * (balances[sender] - amount) / balances[sender];
  452.  
  453. // Net Poly for the seller.
  454. uint numPolys = UINTs[0]/*Poly out*/;
  455.  
  456. // Burn the bonds which were just sold from the total supply.
  457. _totalSupply -= amount;
  458.  
  459.  
  460. // maintain color density
  461. thinColor( sender, balances[sender] - amount, balances[sender]);
  462. // Remove the bonds from the balance of the buyer.
  463. balances[sender] -= amount;
  464.  
  465. // Check if for resolves staked
  466. if ( stakedResolves > 0 ){
  467. // sellSideEarnings are distributed to all remaining resolve holders.
  468. // rewardPerResolve is the amount gained per resolve thanks to this sell.
  469. uint rewardPerResolve = _sellSideEarnings * scaleFactor/stakedResolves;
  470.  
  471. // The Poly value per resolve is increased proportionally.
  472. earningsPerResolve += rewardPerResolve;
  473. }
  474.  
  475.  
  476. (bool success, ) = sender.call{value:numPolys}("");
  477. require(success, "Transfer failed.");
  478.  
  479. emit Sell( sender, amount, numPolys, UINTs[1]/*minted resolves*/, _sellSideEarnings, UINTs[4] /*initialInputPoly*/);
  480. return (numPolys, UINTs[1]/*minted resolves*/, UINTs[4] /*initialInputPoly*/);
  481. }
  482.  
  483. function thinColor(address addr, uint newWeight, uint oldWeight) internal{
  484. //bonds cease to exist so the color density needs to be updated.
  485. (red[addr], green[addr], blue[addr]) = RGB_scale( addr, newWeight, oldWeight);
  486. }
  487.  
  488. // Allow contract to accept resolve tokens
  489. event StakeResolves( address indexed addr, uint256 amountStaked, bytes _data );
  490. function tokenFallback(address from, uint value, bytes calldata _data) external{
  491. if(msg.sender == address(resolveToken) ){
  492. resolveWeight[from] += value;
  493. stakedResolves += value;
  494.  
  495. // Then update the payouts array for the "resolve shareholder" with this amount
  496. int payoutDiff = (int256) (earningsPerResolve * value);
  497. payouts[from] += payoutDiff;
  498. earningsOffset += payoutDiff;
  499.  
  500. emit StakeResolves(from, value, _data);
  501. }else{
  502. revert("no want");
  503. }
  504. }
  505.  
  506. // Withdraws resolveEarnings held by the caller sending the transaction, updates
  507. // the requisite global variables, and transfers Poly back to the caller.
  508. event Withdraw( address indexed addr, uint256 earnings, uint256 dissolve );
  509. function withdraw(uint amount) public returns(uint){
  510. address payable sender = msg.sender;
  511. // Retrieve the resolveEarnings associated with the address the request came from.
  512. uint upScaleDividends = (uint)((int256)( earningsPerResolve * resolveWeight[sender] ) - payouts[sender]);
  513. uint totalEarnings = upScaleDividends / scaleFactor;
  514. require( amount <= totalEarnings && amount > 0 );
  515. uint oldWeight = resolveWeight[sender];
  516. resolveWeight[sender] = oldWeight * ( totalEarnings - amount ) / totalEarnings;
  517. uint weightDiff = oldWeight - resolveWeight[sender];
  518. resolveToken.transfer( address0, weightDiff);
  519. stakedResolves -= weightDiff;
  520.  
  521. // updating payouts based on weight of staked resolves
  522. int withdrawnEarnings = (int)(upScaleDividends * amount / totalEarnings) - (int)(weightDiff*earningsPerResolve);
  523. payouts[sender] += withdrawnEarnings;
  524. // Increase the total amount that's been paid out to maintain invariance.
  525. earningsOffset += withdrawnEarnings;
  526.  
  527.  
  528. // Send the resolveEarnings to the address that requested the withdraw.
  529. (bool success, ) = sender.call{value: amount}("");
  530. require(success, "Transfer failed.");
  531.  
  532. emit Withdraw( sender, amount, weightDiff);
  533. return weightDiff;
  534. }
  535.  
  536. function moveTokens(address _from, address _to, uint _amount) internal override returns(uint R, uint G, uint B){
  537. //mix multi-dimensional bond values
  538. uint totalBonds = balances[_from];
  539. uint polySpent = averagePolySpent[_from] * _amount / totalBonds;
  540. uint buyInTimeSum = averageBuyInTimeSum[_from] * _amount / totalBonds;
  541. averagePolySpent[_from] -= polySpent;
  542. averageBuyInTimeSum[_from] -= buyInTimeSum;
  543. averagePolySpent[_to] += polySpent;
  544. averageBuyInTimeSum[_to] += buyInTimeSum;
  545. return super.moveTokens(_from, _to, _amount);
  546. }
  547.  
  548. function clockTransfer(address _to, uint _value) public virtual returns(uint polySpent, uint buyInTimeSum, uint R, uint G, uint B){
  549. address sender = msg.sender;
  550. uint totalBonds = balances[sender];
  551. polySpent = averagePolySpent[sender] * _value / totalBonds;
  552. buyInTimeSum = averageBuyInTimeSum[sender] * _value / totalBonds;
  553.  
  554. (R, G, B) = moveTokens(sender, _to, _value);
  555. ClockReceivingContract receiver = ClockReceivingContract(_to);
  556. receiver.clockFallback(sender, _value, polySpent, buyInTimeSum, R, G, B);
  557.  
  558. emit Transfer(sender, _to, _value);
  559. }
  560.  
  561. function buyPrice()
  562. public
  563. view
  564. returns(uint256)
  565. {
  566. // calculation relies on the token supply.
  567. if(_totalSupply == 0){
  568. return tokenPriceInitial + tokenPriceIncremental;
  569. } else {
  570. uint256 Poly = tokensToPoly(1e18);
  571. uint256 dividends = frictionFee(Poly );
  572. uint256 _taxedPoly = Poly + dividends;
  573. return _taxedPoly;
  574. }
  575. }
  576.  
  577. function sellPrice()
  578. public
  579. view
  580. returns(uint256)
  581. {
  582. // calculation relies on the token supply.
  583. if(_totalSupply == 0){
  584. return tokenPriceInitial - tokenPriceIncremental;
  585. } else {
  586. uint256 Poly = tokensToPoly(1e18);
  587. uint256 dividends = frictionFee(Poly );
  588. uint256 _taxedPoly = subtract(Poly, dividends);
  589. return _taxedPoly;
  590. }
  591. }
  592.  
  593. function calculateTokensReceived(uint256 polyToSpend)
  594. public
  595. view
  596. returns(uint256)
  597. {
  598. uint256 dividends = frictionFee(polyToSpend);
  599. uint256 _taxedPoly = subtract(polyToSpend, dividends);
  600. uint256 _amountOfTokens = PolyToTokens(_taxedPoly);
  601.  
  602. return _amountOfTokens;
  603. }
  604.  
  605.  
  606. function calculatePolyReceived(uint256 tokensToSell)
  607. public
  608. view
  609. returns(uint256)
  610. {
  611. require(tokensToSell <= _totalSupply);
  612. uint256 polyValue = tokensToPoly(tokensToSell);
  613. uint256 dividends = frictionFee(polyValue );
  614. uint256 _taxedPoly = subtract(polyValue, dividends);
  615. return _taxedPoly;
  616. }
  617.  
  618. function PolyToTokens(uint256 polyValue)
  619. internal
  620. view
  621. returns(uint256)
  622. {
  623. uint256 _tokenPriceInitial = tokenPriceInitial * 1e18;
  624. uint256 _tokensReceived =
  625. (
  626. (
  627. // underflow immune
  628. subtract(
  629. (sqrt
  630. (
  631. (_tokenPriceInitial**2)
  632. +
  633. (2*(tokenPriceIncremental * 1e18)*(polyValue * 1e18))
  634. +
  635. (((tokenPriceIncremental)**2)*(_totalSupply**2))
  636. +
  637. (2*(tokenPriceIncremental)*_tokenPriceInitial*_totalSupply)
  638. )
  639. ), _tokenPriceInitial
  640. )
  641. )/(tokenPriceIncremental)
  642. )-(_totalSupply)
  643. ;
  644.  
  645. return _tokensReceived;
  646. }
  647.  
  648. function tokensToPoly(uint256 _tokens)
  649. internal
  650. view
  651. returns(uint256)
  652. {
  653.  
  654. uint256 tokens_ = (_tokens + 1e18);
  655. uint256 _tokenSupply = (_totalSupply + 1e18);
  656. uint256 PolyReceived =
  657. (
  658. // underflow immune
  659. subtract(
  660. (
  661. (
  662. (
  663. tokenPriceInitial +(tokenPriceIncremental * (_tokenSupply/1e18))
  664. )-tokenPriceIncremental
  665. )*(tokens_ - 1e18)
  666. ),(tokenPriceIncremental*((tokens_**2-tokens_)/1e18))/2
  667. )
  668. /1e18);
  669. return PolyReceived;
  670. }
  671.  
  672. function sqrt(uint x) internal pure returns (uint y) {
  673. uint z = (x + 1) / 2;
  674. y = x;
  675. while (z < y) {
  676. y = z;
  677. z = (x / z + z) / 2;
  678. }
  679. }
  680.  
  681. function subtract(uint256 a, uint256 b) internal pure returns (uint256) {
  682. assert(b <= a);
  683. return a - b;
  684. }
  685. }
  686.  
  687. contract ResolveToken is ColorToken{
  688.  
  689. string public name = "Resolve Token";
  690. string public symbol = "RSLV";
  691. uint8 constant public decimals = 18;
  692. address public hourglass;
  693.  
  694. constructor(address _hourglass) public{
  695. hourglass = _hourglass;
  696. }
  697.  
  698. modifier hourglassOnly{
  699. require(msg.sender == hourglass);
  700. _;
  701. }
  702.  
  703. function mint(address _address, uint _value, uint _red, uint _green, uint _blue) external hourglassOnly(){
  704. balances[_address] += _value;
  705. _totalSupply += _value;
  706. addColor(_address, _value, _red, _green, _blue);
  707. emit Transfer(address(0), _address, _value);
  708. }
  709. }
  710.  
  711. abstract contract ERC223ReceivingContract{
  712. function tokenFallback(address _from, uint _value, bytes calldata _data) external virtual;
  713. }
  714. abstract contract ColorReceivingContract{
  715. function colorFallback(address _from, uint _value, uint r, uint g, uint b) external virtual;
  716. }
  717. abstract contract ClockReceivingContract{
  718. function clockFallback(address _from, uint _value, uint polySpent, uint time, uint r, uint g, uint b) external virtual;
  719. }
Advertisement
Add Comment
Please, Sign In to add comment