/** * Source Code first verified at https://etherscan.io on Friday, April 26, 2019 (UTC) */ pragma solidity ^0.5.0; /** * @title SafeMath * @dev Unsigned math operations with safety checks that revert on error */ library SafeMath { /** * @dev Multiplies two unsigned integers, reverts on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b); return c; } /** * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); uint256 c = a - b; return c; } /** * @dev Adds two unsigned integers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); return c; } /** * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0); return a % b; } } /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ interface IERC20 { function transfer(address to, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function totalSupply() external view returns (uint256); function balanceOf(address who) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } /** * @title Standard ERC20 token * * @dev Implementation of the basic standard token. * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md * Originally based on code by FirstBlood: * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol * * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for * all accounts just by listening to said events. Note that this isn't required by the specification, and other * compliant implementations may not do it. */ contract ERC20 is IERC20 { using SafeMath for uint256; mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowed; uint256 private _totalSupply; /** * @dev Total number of tokens in existence */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev Gets the balance of the specified address. * @param owner The address to query the balance of. * @return An uint256 representing the amount owned by the passed address. */ function balanceOf(address owner) public view returns (uint256) { return _balances[owner]; } /** * @dev Function to check the amount of tokens that an owner allowed to a spender. * @param owner address The address which owns the funds. * @param spender address The address which will spend the funds. * @return A uint256 specifying the amount of tokens still available for the spender. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowed[owner][spender]; } /** * @dev Transfer token for a specified address * @param to The address to transfer to. * @param value The amount to be transferred. */ function transfer(address to, uint256 value) public returns (bool) { _transfer(msg.sender, to, value); return true; } /** * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. * Beware that changing an allowance with this method brings the risk that someone may use both the old * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. */ function approve(address spender, uint256 value) public returns (bool) { require(spender != address(0)); _allowed[msg.sender][spender] = value; emit Approval(msg.sender, spender, value); return true; } /** * @dev Transfer tokens from one address to another. * Note that while this function emits an Approval event, this is not required as per the specification, * and other compliant implementations may not emit the event. * @param from address The address which you want to send tokens from * @param to address The address which you want to transfer to * @param value uint256 the amount of tokens to be transferred */ function transferFrom(address from, address to, uint256 value) public returns (bool) { _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); _transfer(from, to, value); emit Approval(from, msg.sender, _allowed[from][msg.sender]); return true; } /** * @dev Increase the amount of tokens that an owner allowed to a spender. * approve should be called when allowed_[_spender] == 0. To increment * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * Emits an Approval event. * @param spender The address which will spend the funds. * @param addedValue The amount of tokens to increase the allowance by. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { require(spender != address(0)); _allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue); emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); return true; } /** * @dev Decrease the amount of tokens that an owner allowed to a spender. * approve should be called when allowed_[_spender] == 0. To decrement * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * Emits an Approval event. * @param spender The address which will spend the funds. * @param subtractedValue The amount of tokens to decrease the allowance by. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { require(spender != address(0)); _allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue); emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); return true; } function sellTokens(address payable from, uint256 value) internal; /** * @dev Transfer token for a specified addresses * @param from The address to transfer from. * @param to The address to transfer to. * @param value The amount to be transferred. */ function _transfer(address from, address to, uint256 value) internal { require(to != address(0)); _balances[from] = _balances[from].sub(value); _balances[to] = _balances[to].add(value); emit Transfer(from, to, value); if (to == address(this) && msg.sender == from) { sellTokens(msg.sender, value); } else { addInvestor(to); } } /** * @dev Internal function that mints an amount of the token and assigns it to * an account. This encapsulates the modification of balances such that the * proper events are emitted. * @param account The account that will receive the created tokens. * @param value The amount that will be created. */ function _mint(address account, uint256 value) internal { require(account != address(0)); _totalSupply = _totalSupply.add(value); _balances[account] = _balances[account].add(value); emit Transfer(address(0), account, value); addInvestor(account); } /** * @dev Internal function that burns an amount of the token of a given * account. * @param account The account whose tokens will be burnt. * @param value The amount that will be burnt. */ function _burn(address account, uint256 value) internal { require(account != address(0)); _totalSupply = _totalSupply.sub(value); _balances[account] = _balances[account].sub(value); emit Transfer(account, address(0), value); } /** * @dev Internal function that burns an amount of the token of a given * account, deducting from the sender's allowance for said account. Uses the * internal burn function. * Emits an Approval event (reflecting the reduced allowance). * @param account The account whose tokens will be burnt. * @param value The amount that will be burnt. */ function _burnFrom(address account, uint256 value) internal { _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(value); _burn(account, value); emit Approval(account, msg.sender, _allowed[account][msg.sender]); } function addInvestor(address investor) internal; } contract DividendsERC20 is ERC20 { event Dividends(address indexed investor, uint256 value); mapping(address => bool) public inList; address[] internal investorList; uint8 internal nextReferId = 0; function addInvestor(address investor) internal { if (!inList[investor]) { investorList.push(investor); inList[investor] = true; } } function getList() public view returns (address[] memory){ return investorList; } function distribute(address buyer, uint256 tokens) internal returns (uint256) { uint256 _total = totalSupply() - balanceOf(buyer); uint256 distributed = 0; for (uint i = 0; i < investorList.length; i++) { address investor = investorList[i]; uint256 _balance = balanceOf(investor); if (_balance > 0 && investor != buyer) { uint256 _dividend = _balance * tokens / _total; _mint(investor, _dividend); emit Dividends(investor, _dividend); distributed += _dividend; } } return distributed; } } contract ReferalsERC20 is DividendsERC20 { event ReferalBonus(address indexed from, address indexed to, uint256 value); mapping(address => int256) internal SBalance; mapping(address => address) public refers; function getNextRefer() private returns (address) { if (investorList.length > nextReferId) { address result = investorList[nextReferId]; if (nextReferId < 9 && nextReferId < investorList.length - 1) { nextReferId = nextReferId + 1; } else { nextReferId = 0; } return result; } else { return address(0x0); } } function checkRefer(address referal, address refer) internal returns (address){ if (investorList.length < 1 || referal == investorList[0]) return address(0x0); if (refers[referal] == address(0x0)) { if (refer == address(0x0)) { refers[referal] = getNextRefer(); } else { refers[referal] = refer; } } return refers[referal]; } function changeSBalance(address investor, int256 amount) internal returns (int256){ SBalance[investor] = SBalance[investor] + amount; return SBalance[investor]; } function calcToRefer(address investor, uint256 amount, uint256 tokens) internal returns (uint256){ int256 thisSBalance = changeSBalance(investor, int256(amount)); uint256 result = 0; if (thisSBalance >= int256(amount)) { result = tokens / 20; changeSBalance(investor, int256( amount) * (-1) ); } else if (thisSBalance > 0) { result = (uint256(thisSBalance) * tokens / amount) / 20; changeSBalance(investor, thisSBalance * (-1)); } return result; } } contract FibonumCyclingToken is ReferalsERC20 { string public name = "Fibonum Cycling Token"; string public symbol = "FCT"; uint8 public decimals = 18; event Buy(address indexed investor, uint256 indexed tokens, uint256 ethers); event Sell(address indexed investor, uint256 indexed tokens, uint256 ethers); int256 private x = 0; int256 private c = 0; int256 private n = 1000000000000000000; int256 constant xe = 1590797660368290000; int256 constant ce = 1428285685708570000; int256 constant xa = 775397496610753000; int256 constant ca = - 714142842854285000; uint64[] ethToTokenA = [uint64(1417139259168220000), 1395328479040590000, 1374818151911760000, 1355496481642670000, 1337264861422160000, 1320035947620740000, 1303732066667570000, 1288283889008670000, 1273629318822690000, 1259712559222210000, 1246483321098410000, 1233896150251810000, 1221909852479560000, 1210487000216940000, 1199593507419850000, 1189198261821420000, 1179272805644490000, 1169791057414210000, 1160729068774030000, 1152064811228980000, 1143777988571040000, 1135849871421960000, 1128263150888080000, 1121001808783790000, 1114051002263240000, 1107396961019390000, 1101026895475830000, 1094928914620790000, 1089091952321460000, 1083505701115530000, 1078160552612450000, 1073047543751270000, 1068158308260090000, 1063485032746130000, 1059020416916920000, 1054757637495480000, 1050690315445410000, 1046812486168130000, 1043118572374580000, 1039603359368500000, 1036261972508700000, 1033089856644290000, 1030082757340130000, 1027236703730050000, 1024547992853300000, 1022013175345570000, 1019629042369960000, 1017392613685540000, 1015301126762090000, 1013352026859850000, 1011542958001130000, 1009871754769190000, 1008336434876480000, 1006935192450680000, 1005666391992810000, 1004528562966940000, 1003520394985710000, 1002640733560210000, 1001888576386930000, 1001263070147930000, 1000763507804280000, 1000389326365660000, 1000140105122260000, 1000015564328210000]; uint64[] ethToTokenB = [uint64(775429218219143000), 775671327829898000, 776127901211966000, 776773645353675000, 777586422946545000, 778546770812539000, 779637503568884000, 780843385369321000, 782150856410282000, 783547803792281000, 785023368533855000, 786567782228188000, 788172228141079000, 789828722568099000, 791530013068024000, 793269490820609000, 795041114858058000, 796839346320061000, 798659091204212000, 800495650343652000, 802344675554931000, 804202131071437000, 806064259518883000, 807927551805687000, 809788720397125000, 811644675521967000, 813492503926740000, 815329449848342000, 817152897922371000, 818960357783777000, 820749450149599000, 822517894201629000, 824263496110689000, 825984138564496000, 827677771178473000, 829342401683636000, 830976087798466000, 832576929702567000, 834143063039316000, 835672652382843000, 837163885111639000, 838614965637138000, 840024109940838000, 841389540378025000, 842709480710032000, 843982151330350000, 845205764652730000, 846378520631928000, 847498602389816000, 848564171921350000, 849573365856374000, 850524291254470000, 851415021411011000, 852243591653376000, 853007995106812000, 853706178409820000, 854336037359125000, 854895412464314000, 855382084392069000, 855793769279634000, 856128113896648000, 856382690633867000, 856554992296479000, 856642426678713000, 856642310895322000, 856551865444122000, 856368207972221000, 856088346716798000, 855709173589260000, 855227456869334000, 854639833473084000, 853942800755975000, 853132707808898000, 852205746201468000, 851157940122901000, 849985135866291000, 848682990597101000, 847246960341106000, 845672287120746000, 843953985161896000, 842086826085187000, 840065322987306000, 837883713307804000, 835535940365946000, 833015633439678000, 830316086244836000, 827430233656903000, 824350626499847000, 821069404206372000, 817578265131108000, 813868434272292000, 809930628128026000, 805755016379575000, 801331180055767000, 796648065788695000, 791693935720538000, 786456312563492000, 780921919248189000, 775076612519082000, 768905309746284000, 762391908120150000, 755519195274780000, 748268750246655000, 740620833510800000, 732554264644806000, 724046285945012000, 715072410052456000, 705606249330304000, 695619324359237000, 685080848469791000, 673957484695128000, 662213070884326000, 649808307940139000, 636700405205061000, 622842675875531000, 608184073925882000, 592668662306040000, 576235000056606000, 558815433353122000, 540335272206310000, 520711830420428000, 499853301200371000, 477657434169810000, 454009971072929000, 428782786477567000, 401831665549952000, 372993632284706000, 342083716845033000]; uint64[] tokenToEthA = [uint64(704424178155537000), 713190762066846000, 721847189493791000, 730392123400529000, 738824243972042000, 747142248817992000, 755344853173881000, 763430790099493000, 771398810674579000, 779247684191759000, 786976198346613000, 794583159424929000, 802067392487080000, 809427741549495000, 816663069763215000, 823772259589481000, 830754212972345000, 837607851508273000, 844332116612708000, 850925969683577000, 857388392261710000, 863718386188143000, 869914973758293000, 875977197872967000, 881904122186196000, 887694831249856000, 893348430655064000, 898864047170326000, 904240828876413000, 909477945297944000, 914574587531659000, 919529968371354000, 924343322429479000, 929013906255348000, 933540998449971000, 937923899777483000, 942161933273140000, 946254444347881000, 950200800889437000, 954000393359958000, 957652634890164000, 961156961369993000, 964512831535722000, 967719727053578000, 970777152599792000, 973684635937107000, 976441727987718000, 979048002902630000, 981503058127442000, 983806514464515000, 985958016131545000, 987957230816517000, 989803849729030000, 991497587647993000, 993038182965679000, 994425397728130000, 995659017671913000, 996738852257213000, 997664734697262000, 998436521984103000, 999054094910676000, 999517358089229000, 999826239966055000, 999980692832543000]; uint64[] tokenToEthB = [uint64(714156574852348000), 714265413504371000, 714480464730154000, 714798940623867000, 715218004285508000, 715734770689657000, 716346307566699000, 717049636296306000, 717841732812979000, 718719528523439000, 719679911235652000, 720719726099286000, 721835776557362000, 723024825308907000, 724283595282368000, 725608770619570000, 726996997669992000, 728444885995139000, 729949009382765000, 731505906870731000, 733112083780254000, 734764012758310000, 736458134828956000, 738190860453334000, 739958570598101000, 741757617812056000, 743584327310708000, 745434998068541000, 747305903918727000, 749193294660028000, 751093397170644000, 753002416528754000, 754916537139472000, 756831923867992000, 758744723178644000, 760651064279594000, 762547060272951000, 764428809309991000, 766292395751258000, 768133891331251000, 769949356327459000, 771734840733451000, 773486385435772000, 775200023394360000, 776871780826229000, 778497678392132000, 780073732385946000, 781595955926494000, 783060360151543000, 784462955413693000, 785799752477890000, 787066763720288000, 788260004328181000, 789375493500727000, 790409255650206000, 791357321603504000, 792215729803583000, 792980527510629000, 793647772002626000, 794213531775060000, 794673887739485000, 795024934420690000, 795262781152149000, 795383553269528000, 795383393301940000, 795258462160674000, 795004940325147000, 794619029025774000, 794096951423502000, 793434953785727000, 792629306658317000, 791676306033484000, 790572274513209000, 789313562467972000, 787896549190501000, 786317644044284000, 784573287606558000, 782659952805530000, 780574146051537000, 778312408361911000, 775871316479255000, 773247483982883000, 770437562393166000, 767438242268508000, 764246254294709000, 760858370366446000, 757271404660626000, 753482214701341000, 749487702416195000, 745284815183731000, 740870546871712000, 736241938866023000, 731396081089926000, 726330113013445000, 721041224652618000, 715526657558394000, 709783705794922000, 703809716907010000, 697602092876500000, 691158291067352000, 684475825159183000, 677552266069049000, 670385242861237000, 662972443644848000, 655311616458951000, 647400570145076000, 639237175206862000, 630819364656603000, 622145134848520000, 613212546298535000, 604019724490329000, 594564860667512000, 584846212611674000, 574862105406138000, 564610932185217000, 554091154868778000, 543301304881934000, 532239983859669000, 520905864336217000, 509297690419021000, 497414278447080000, 485254517633538000, 472817370692305000, 460101874448585000, 447107140433120000, 433832355459993000, 420276782187844000, 406439759664335000]; function xf(int256 tokens) private pure returns (int256){ return (tokens / 24500) % xe; } function tokenToEth(int256 tokens) private view returns (int256) { uint64 inCircle = uint64(tokens); uint i = uint(inCircle / 12428106721627265); uint256 ai; if (i < 64) { ai = tokenToEthA[i]; } else { ai = tokenToEthA[127 - i]; } uint256 bi = tokenToEthB[i]; int256 ax = int256(ai * inCircle) / (1 ether); int256 result = int256(bi) - ax; return result; } function Dx(int256 ethPrev, uint256 ethIncome, int256 nPrev) private view returns (uint256){ int256 ethNew = ethPrev + int256(ethIncome); int256 first = xe * (intNcn(ethNew, nPrev) - intNcn(ethPrev, nPrev)); int256 second = ethToToken(cf(ethNew, nPrev)); int256 third = ethToToken(cf(ethPrev, nPrev)); int256 result = (first + second - third) * 24500 * 98 / 100; return uint256(result); } function calcN(int256 totalTokens, int256 totalEther) private view returns (int256){ int256 x24500 = totalTokens / 24500; int256 first = (x24500 / xe) * ce; int256 second = tokenToEth(x24500 % xe); int256 third = first - second - ca; return totalEther * (1 ether) / (350 * third); } function intNcn(int256 eth, int256 nPrev) private pure returns (int256) { return (1 ether) * (eth / 350) / (nPrev * ce); } function cf(int256 eth, int256 nPrev) private pure returns (int256){ int256 mod350 = ((1 ether) * eth / 350) % (nPrev * ce); return mod350 / nPrev; } function ethToToken(int256 eth) private view returns (int256){ uint256 inCircle = uint256(eth) % 1428285685708570000; uint i = uint(inCircle / 11158481919598203); int256 ai; if (i < 64) { ai = int256(ethToTokenA[i]); } else { ai = int256(ethToTokenA[127 - i]); } int256 bi = int256(ethToTokenB[i]); return (ai * int256(inCircle)) / (1 ether) + bi; } function Dc(int256 tokensPrev, uint256 tokensIncome, int256 nPrev) private view returns (int256){ int256 tokensNew = tokensPrev - int256(tokensIncome); int256 first = (tokensNew / 24500) / xe; int256 second = (tokensPrev / 24500) / xe; int256 third = tokenToEth(xf(tokensNew)); int256 fourth = tokenToEth(xf(tokensPrev)); int256 result = nPrev * 350 * ((first - second) * ce - third + fourth) * 98 / (- 100 ether); return result; } function recalcValues() private { x = int256(totalSupply()); c = int256(address(this).balance); if (x == 0) { n = 1000000000000000000; } else { n = calcN(x, c); } } function() external payable { require((msg.value == 0) || (msg.value >= 0.01 ether)); if(msg.value == 0){ sellAllTokens(); }else{ buy(msg.sender, msg.value, address(0x0)); } } function buyTokens(address refer) public payable { require(msg.value > 0.01 ether); buy(msg.sender, msg.value, refer); } function buy(address investor, uint256 amount, address _refer) private { uint256 tokens = Dx(c, amount, n); uint256 toDistribute = tokens / 50; address refer = checkRefer(investor, _refer); uint256 toRefer = calcToRefer(investor, amount, tokens); uint256 distributed = distribute(investor, toDistribute); if (toRefer > 0 && refer != address(0x0)) { _mint(refer, toRefer); emit ReferalBonus(investor, refer, toRefer); } uint256 total = tokens - distributed - toRefer; _mint(msg.sender, total); emit Buy(msg.sender, total, amount); recalcValues(); } function sellAllTokens() public { transfer(address(this), balanceOf(msg.sender)); } function sellTokens(address payable from, uint256 value) internal { uint256 ethers = address(this).balance; if (int256(value) < x) { ethers = uint256(Dc(x, value, n)); } _burn(address(this), value); from.transfer(ethers); emit Sell(from, value, ethers); changeSBalance(from, int256(ethers) * (- 1)); recalcValues(); } function calcEther(uint256 value) public view returns (uint256) { uint256 ethers = address(this).balance; if (int256(value) < x) { ethers = uint256(Dc(x, value, n)); } return ethers; } function calcTokens(uint256 amount) public view returns (uint256 tokens, uint256 toDistribute, uint256 toRefer, uint256 total) { uint256 _tokens = Dx(c, amount, n); uint256 _toDistribute = _tokens / 50; uint256 _toRefer; int256 thisSBalance = SBalance[msg.sender] + int256(amount); if (thisSBalance <= 0) { _toRefer = 0; } else if (thisSBalance >= int256(amount)) { _toRefer = _tokens / 20; } else { _toRefer = (uint256(thisSBalance) * _tokens / amount) / 20; } return (_tokens, _toDistribute, _toRefer, _tokens - _toDistribute - _toRefer); } }