├── .gitignore ├── box-img-lg.png ├── box-img-sm.png ├── bs-config.json ├── src └── images │ └── wechat.jpeg ├── contracts ├── F3DexternalSettings.sol ├── modularLong.sol ├── interface │ ├── otherFoMo3D.sol │ ├── DiviesInterface.sol │ ├── JIincInterfaceForForwarder.sol │ ├── PlayerBookReceiverInterface.sol │ ├── F3DexternalSettingsInterface.sol │ ├── JIincForwarderInterface.sol │ ├── TeamJustInterface.sol │ ├── HourglassInterface.sol │ └── PlayerBookInterface.sol ├── library │ ├── F3DKeysCalcLong.sol │ ├── SafeMath.sol │ ├── F3Ddatasets.sol │ ├── UintCompressor.sol │ ├── NameFilter.sol │ └── MSFun.sol ├── F3Devents.sol ├── JIincForwarder.sol ├── Divies.sol ├── TeamJust.sol ├── PlayerBook.sol ├── Hourglass.sol └── FoMo3Dlong.sol ├── migrations ├── 3_deploy_gene.js ├── 1_initial_migration.js └── 2_deploy_petcore.js ├── README.md ├── package.json ├── truffle.js └── flattener.sh /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | node_modules/* 3 | test/* 4 | -------------------------------------------------------------------------------- /box-img-lg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowkeys/fomo3d_clone/master/box-img-lg.png -------------------------------------------------------------------------------- /box-img-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowkeys/fomo3d_clone/master/box-img-sm.png -------------------------------------------------------------------------------- /bs-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": { 3 | "baseDir": ["./src", "./build/contracts"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/images/wechat.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowkeys/fomo3d_clone/master/src/images/wechat.jpeg -------------------------------------------------------------------------------- /contracts/F3DexternalSettings.sol: -------------------------------------------------------------------------------- 1 | // 看不到代码 0x32967D6c142c2F38AB39235994e2DDF11c37d590 2 | pragma solidity ^0.4.24; 3 | 4 | -------------------------------------------------------------------------------- /contracts/modularLong.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./F3Devents.sol"; 4 | 5 | contract modularLong is F3Devents {} -------------------------------------------------------------------------------- /contracts/interface/otherFoMo3D.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | interface otherFoMo3D { 4 | function potSwap() external payable; 5 | } -------------------------------------------------------------------------------- /contracts/interface/DiviesInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | interface DiviesInterface { 4 | function deposit() external payable; 5 | } -------------------------------------------------------------------------------- /migrations/3_deploy_gene.js: -------------------------------------------------------------------------------- 1 | var GenePet = artifacts.require("./GenePet.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(GenePet); 5 | }; 6 | -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /contracts/interface/JIincInterfaceForForwarder.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | interface JIincInterfaceForForwarder { 4 | function deposit(address _addr) external payable returns (bool); 5 | function migrationReceiver_setup() external returns (bool); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interface/PlayerBookReceiverInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | interface PlayerBookReceiverInterface { 4 | function receivePlayerInfo(uint256 _pID, address _addr, bytes32 _name, uint256 _laff) external; 5 | function receivePlayerNameList(uint256 _pID, bytes32 _name) external; 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interface/F3DexternalSettingsInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | interface F3DexternalSettingsInterface { 4 | function getFastGap() external returns(uint256); 5 | function getLongGap() external returns(uint256); 6 | function getFastExtra() external returns(uint256); 7 | function getLongExtra() external returns(uint256); 8 | } -------------------------------------------------------------------------------- /migrations/2_deploy_petcore.js: -------------------------------------------------------------------------------- 1 | var PetCore = artifacts.require("./PetCore.sol"); 2 | 3 | module.exports = function(deployer, network, accounts) { 4 | console.log('network is '+network); 5 | console.log(accounts); 6 | console.log(accounts[0]); 7 | console.log('deploy PetCore contract to develop network, account address is '+accounts[0]); 8 | deployer.deploy(PetCore); 9 | }; 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 说明 2 | 本项目通过fomo3d官网合约的入口,把相关所有的合约进行汇总。 3 | 在通过继承的机制就行分拆开。 4 | 5 | 现已经是一个truffle项目。可以通过命令: 6 | 7 | > truffle compile 8 | 9 | 直接编译 10 | 11 | 源码分析系列: 12 | 13 | 第一篇:[Fomo3D源码解密:框架篇](https://mp.weixin.qq.com/s/kT94y3kHZKa-JXXWWGqD_A) 14 | 15 | 16 | 欢迎交流咨询: 17 | 18 | ![](https://github.com/reedhong/fomo3d_clone/blob/master/src/images/wechat.jpeg) 19 | 20 | 有专门的开发交流群,各路大神都有,欢迎大家加入! 21 | 22 | 注:不回答关于环境搭建,简单报错等各种基础问题,发挥下自我学习能力吧!真心时间宝贵,望各位多多理解! 23 | -------------------------------------------------------------------------------- /contracts/interface/JIincForwarderInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | interface JIincForwarderInterface { 4 | function deposit() external payable returns(bool); 5 | function status() external view returns(address, address, bool); 6 | function startMigration(address _newCorpBank) external returns(bool); 7 | function cancelMigration() external returns(bool); 8 | function finishMigration() external returns(bool); 9 | function setup(address _firstCorpBank) external; 10 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "genePet", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "truffle.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "dev": "lite-server", 11 | "test": "echo \"Error: no test specified\" && exit 1", 12 | "flat": "sh ./flattener.sh" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "lite-server": "^2.3.0" 18 | }, 19 | "dependencies": { 20 | "zeppelin-solidity": "^1.4.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/interface/TeamJustInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | interface TeamJustInterface { 4 | function requiredSignatures() external view returns(uint256); 5 | function requiredDevSignatures() external view returns(uint256); 6 | function adminCount() external view returns(uint256); 7 | function devCount() external view returns(uint256); 8 | function adminName(address _who) external view returns(bytes32); 9 | function isAdmin(address _who) external view returns(bool); 10 | function isDev(address _who) external view returns(bool); 11 | } -------------------------------------------------------------------------------- /truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | develop: { 4 | host: "127.0.0.1", 5 | port: 7545, 6 | network_id: "*" // Match any network id 7 | }, 8 | 9 | test: { 10 | host: "127.0.0.1", 11 | port: 7545, 12 | network_id: "*" // Match any network id 13 | }, 14 | 15 | mine: { 16 | host: "127.0.0.1", 17 | port: 8545, 18 | network_id: "*", // Match any network id 19 | gas: 4712382 20 | }, 21 | ropsten: { 22 | network_id: 3, 23 | host: "localhost", 24 | port: 8545, 25 | gas: 4700000 26 | } 27 | } 28 | }; -------------------------------------------------------------------------------- /flattener.sh: -------------------------------------------------------------------------------- 1 | ######################################################################### 2 | # File Name: flattener.sh 3 | # Author: ma6174 4 | # mail: ma6174@163.com 5 | # Created Time: 六 12/30 00:54:25 2017 6 | ######################################################################### 7 | #!/bin/bash 8 | 9 | cd flat_contracts 10 | rm -rf * 11 | cd .. 12 | truffle-flattener contracts/PetCore.sol >flat_contracts/PetCoreFlat.sol 13 | truffle-flattener contracts/SaleClockAuction.sol >flat_contracts/SaleClockAuctionFlat.sol 14 | truffle-flattener contracts/SiringClockAuction.sol >flat_contracts/SiringClockAuctionFlat.sol 15 | truffle-flattener contracts/GenePet.sol >flat_contracts/GenePetFlat.sol 16 | -------------------------------------------------------------------------------- /contracts/interface/HourglassInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | interface HourglassInterface { 4 | function() payable external; 5 | function buy(address _playerAddress) payable external returns(uint256); 6 | function sell(uint256 _amountOfTokens) external; 7 | function reinvest() external; 8 | function withdraw() external; 9 | function exit() external; 10 | function dividendsOf(address _playerAddress) external view returns(uint256); 11 | function balanceOf(address _playerAddress) external view returns(uint256); 12 | function transfer(address _toAddress, uint256 _amountOfTokens) external returns(bool); 13 | function stakingRequirement() external view returns(uint256); 14 | } -------------------------------------------------------------------------------- /contracts/interface/PlayerBookInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | interface PlayerBookInterface { 4 | function getPlayerID(address _addr) external returns (uint256); 5 | function getPlayerName(uint256 _pID) external view returns (bytes32); 6 | function getPlayerLAff(uint256 _pID) external view returns (uint256); 7 | function getPlayerAddr(uint256 _pID) external view returns (address); 8 | function getNameFee() external view returns (uint256); 9 | function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256); 10 | function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256); 11 | function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256); 12 | } -------------------------------------------------------------------------------- /contracts/library/F3DKeysCalcLong.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import './SafeMath.sol'; 4 | 5 | //============================================================================== 6 | // | _ _ _ | _ . 7 | // |<(/_\/ (_(_||(_ . 8 | //=======/====================================================================== 9 | library F3DKeysCalcLong { 10 | using SafeMath for *; 11 | /** 12 | * @dev calculates number of keys received given X eth 13 | * @param _curEth current amount of eth in contract 14 | * @param _newEth eth being spent 15 | * @return amount of ticket purchased 16 | */ 17 | function keysRec(uint256 _curEth, uint256 _newEth) 18 | internal 19 | pure 20 | returns (uint256) 21 | { 22 | return(keys((_curEth).add(_newEth)).sub(keys(_curEth))); 23 | } 24 | 25 | /** 26 | * @dev calculates amount of eth received if you sold X keys 27 | * @param _curKeys current amount of keys that exist 28 | * @param _sellKeys amount of keys you wish to sell 29 | * @return amount of eth received 30 | */ 31 | function ethRec(uint256 _curKeys, uint256 _sellKeys) 32 | internal 33 | pure 34 | returns (uint256) 35 | { 36 | return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys)))); 37 | } 38 | 39 | /** 40 | * @dev calculates how many keys would exist with given an amount of eth 41 | * @param _eth eth "in contract" 42 | * @return number of keys that would exist 43 | */ 44 | function keys(uint256 _eth) 45 | internal 46 | pure 47 | returns(uint256) 48 | { 49 | return ((((((_eth).mul(1000000000000000000)).mul(312500000000000000000000000)).add(5624988281256103515625000000000000000000000000000000000000000000)).sqrt()).sub(74999921875000000000000000000000)) / (156250000); 50 | } 51 | 52 | /** 53 | * @dev calculates how much eth would be in contract given a number of keys 54 | * @param _keys number of keys "in contract" 55 | * @return eth that would exists 56 | */ 57 | function eth(uint256 _keys) 58 | internal 59 | pure 60 | returns(uint256) 61 | { 62 | return ((78125000).mul(_keys.sq()).add(((149999843750000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq()); 63 | } 64 | } -------------------------------------------------------------------------------- /contracts/library/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | /** 4 | * @title SafeMath v0.1.9 5 | * @dev Math operations with safety checks that throw on error 6 | * change notes: original SafeMath library from OpenZeppelin modified by Inventor 7 | * - added sqrt 8 | * - added sq 9 | * - added pwr 10 | * - changed asserts to requires with error log outputs 11 | * - removed div, its useless 12 | */ 13 | library SafeMath { 14 | 15 | /** 16 | * @dev Multiplies two numbers, throws on overflow. 17 | */ 18 | function mul(uint256 a, uint256 b) 19 | internal 20 | pure 21 | returns (uint256 c) 22 | { 23 | if (a == 0) { 24 | return 0; 25 | } 26 | c = a * b; 27 | require(c / a == b, "SafeMath mul failed"); 28 | return c; 29 | } 30 | 31 | /** 32 | * @dev Integer division of two numbers, truncating the quotient. 33 | */ 34 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 35 | // assert(b > 0); // Solidity automatically throws when dividing by 0 36 | uint256 c = a / b; 37 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 38 | return c; 39 | } 40 | 41 | /** 42 | * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). 43 | */ 44 | function sub(uint256 a, uint256 b) 45 | internal 46 | pure 47 | returns (uint256) 48 | { 49 | require(b <= a, "SafeMath sub failed"); 50 | return a - b; 51 | } 52 | 53 | /** 54 | * @dev Adds two numbers, throws on overflow. 55 | */ 56 | function add(uint256 a, uint256 b) 57 | internal 58 | pure 59 | returns (uint256 c) 60 | { 61 | c = a + b; 62 | require(c >= a, "SafeMath add failed"); 63 | return c; 64 | } 65 | 66 | /** 67 | * @dev gives square root of given x. 68 | */ 69 | function sqrt(uint256 x) 70 | internal 71 | pure 72 | returns (uint256 y) 73 | { 74 | uint256 z = ((add(x,1)) / 2); 75 | y = x; 76 | while (z < y) 77 | { 78 | y = z; 79 | z = ((add((x / z),z)) / 2); 80 | } 81 | } 82 | 83 | /** 84 | * @dev gives square. multiplies x by x 85 | */ 86 | function sq(uint256 x) 87 | internal 88 | pure 89 | returns (uint256) 90 | { 91 | return (mul(x,x)); 92 | } 93 | 94 | /** 95 | * @dev x to the power of y 96 | */ 97 | function pwr(uint256 x, uint256 y) 98 | internal 99 | pure 100 | returns (uint256) 101 | { 102 | if (x==0) 103 | return (0); 104 | else if (y==0) 105 | return (1); 106 | else 107 | { 108 | uint256 z = x; 109 | for (uint256 i=1; i < y; i++) 110 | z = mul(z,x); 111 | return (z); 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /contracts/library/F3Ddatasets.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | //============================================================================== 4 | // __|_ _ __|_ _ . 5 | // _\ | | |_|(_ | _\ . 6 | //============================================================================== 7 | library F3Ddatasets { 8 | //compressedData key 9 | // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0] 10 | // 0 - new player (bool) 11 | // 1 - joined round (bool) 12 | // 2 - new leader (bool) 13 | // 3-5 - air drop tracker (uint 0-999) 14 | // 6-16 - round end time 15 | // 17 - winnerTeam 16 | // 18 - 28 timestamp 17 | // 29 - team 18 | // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico) 19 | // 31 - airdrop happened bool 20 | // 32 - airdrop tier 21 | // 33 - airdrop amount won 22 | //compressedIDs key 23 | // [77-52][51-26][25-0] 24 | // 0-25 - pID 25 | // 26-51 - winPID 26 | // 52-77 - rID 27 | struct EventReturns { 28 | uint256 compressedData; 29 | uint256 compressedIDs; 30 | address winnerAddr; // winner address 31 | bytes32 winnerName; // winner name 32 | uint256 amountWon; // amount won 33 | uint256 newPot; // amount in new pot 34 | uint256 P3DAmount; // amount distributed to p3d 35 | uint256 genAmount; // amount distributed to gen 36 | uint256 potAmount; // amount added to pot 37 | } 38 | struct Player { 39 | address addr; // player address 40 | bytes32 name; // player name 41 | uint256 win; // winnings vault 42 | uint256 gen; // general vault 43 | uint256 aff; // affiliate vault 44 | uint256 lrnd; // last round played 45 | uint256 laff; // last affiliate id used 46 | } 47 | struct PlayerRounds { 48 | uint256 eth; // eth player has added to round (used for eth limiter) 49 | uint256 keys; // keys 50 | uint256 mask; // player mask 51 | uint256 ico; // ICO phase investment 52 | } 53 | struct Round { 54 | uint256 plyr; // pID of player in lead 55 | uint256 team; // tID of team in lead 56 | uint256 end; // time ends/ended 57 | bool ended; // has round end function been ran 58 | uint256 strt; // time round started 59 | uint256 keys; // keys 60 | uint256 eth; // total eth in 61 | uint256 pot; // eth to pot (during round) / final amount paid to winner (after round ends) 62 | uint256 mask; // global mask 63 | uint256 ico; // total eth sent in during ICO phase 64 | uint256 icoGen; // total eth for gen during ICO phase 65 | uint256 icoAvg; // average key price for ICO phase 66 | } 67 | struct TeamFee { 68 | uint256 gen; // % of buy in thats paid to key holders of current round 69 | uint256 p3d; // % of buy in thats paid to p3d holders 70 | } 71 | struct PotSplit { 72 | uint256 gen; // % of pot thats paid to key holders of current round 73 | uint256 p3d; // % of pot thats paid to p3d holders 74 | } 75 | } -------------------------------------------------------------------------------- /contracts/library/UintCompressor.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./SafeMath.sol"; 4 | 5 | /** 6 | * @title -UintCompressor- v0.1.9 7 | * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ 8 | * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ 9 | * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ 10 | * _____ _____ 11 | * (, / /) /) /) (, / /) /) 12 | * ┌─┐ / _ (/_ // // / _ // _ __ _(/ 13 | * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ 14 | * ┴ ┴ / / .-/ _____ (__ / 15 | * (__ / (_/ (, / /)™ 16 | * / __ __ __ __ _ __ __ _ _/_ _ _(/ 17 | * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ 18 | * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 19 | * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ 20 | * _ _ __ __ _ ____ ___ __ _ _ ____ ____ ____ ____ ____ __ ____ 21 | *===/ )( \ ( ) ( ( \(_ _)===/ __) / \ ( \/ )( _ \( _ \( __)/ ___)/ ___) / \ ( _ \===* 22 | * ) \/ ( )( / / )( ( (__ ( O )/ \/ \ ) __/ ) / ) _) \___ \\___ \( O ) ) / 23 | *===\____/ (__) \_)__) (__)====\___) \__/ \_)(_/(__) (__\_)(____)(____/(____/ \__/ (__\_)===* 24 | * 25 | * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ 26 | * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ 27 | * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ 28 | */ 29 | 30 | library UintCompressor { 31 | using SafeMath for *; 32 | 33 | function insert(uint256 _var, uint256 _include, uint256 _start, uint256 _end) 34 | internal 35 | pure 36 | returns(uint256) 37 | { 38 | // check conditions 39 | require(_end < 77 && _start < 77, "start/end must be less than 77"); 40 | require(_end >= _start, "end must be >= start"); 41 | 42 | // format our start/end points 43 | _end = exponent(_end).mul(10); 44 | _start = exponent(_start); 45 | 46 | // check that the include data fits into its segment 47 | require(_include < (_end / _start)); 48 | 49 | // build middle 50 | if (_include > 0) 51 | _include = _include.mul(_start); 52 | 53 | return((_var.sub((_var / _start).mul(_start))).add(_include).add((_var / _end).mul(_end))); 54 | } 55 | 56 | function extract(uint256 _input, uint256 _start, uint256 _end) 57 | internal 58 | pure 59 | returns(uint256) 60 | { 61 | // check conditions 62 | require(_end < 77 && _start < 77, "start/end must be less than 77"); 63 | require(_end >= _start, "end must be >= start"); 64 | 65 | // format our start/end points 66 | _end = exponent(_end).mul(10); 67 | _start = exponent(_start); 68 | 69 | // return requested section 70 | return((((_input / _start).mul(_start)).sub((_input / _end).mul(_end))) / _start); 71 | } 72 | 73 | function exponent(uint256 _position) 74 | private 75 | pure 76 | returns(uint256) 77 | { 78 | return((10).pwr(_position)); 79 | } 80 | } -------------------------------------------------------------------------------- /contracts/F3Devents.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | contract F3Devents { 4 | // fired whenever a player registers a name 5 | event onNewName 6 | ( 7 | uint256 indexed playerID, 8 | address indexed playerAddress, 9 | bytes32 indexed playerName, 10 | bool isNewPlayer, 11 | uint256 affiliateID, 12 | address affiliateAddress, 13 | bytes32 affiliateName, 14 | uint256 amountPaid, 15 | uint256 timeStamp 16 | ); 17 | 18 | // fired at end of buy or reload 19 | event onEndTx 20 | ( 21 | uint256 compressedData, 22 | uint256 compressedIDs, 23 | bytes32 playerName, 24 | address playerAddress, 25 | uint256 ethIn, 26 | uint256 keysBought, 27 | address winnerAddr, 28 | bytes32 winnerName, 29 | uint256 amountWon, 30 | uint256 newPot, 31 | uint256 P3DAmount, 32 | uint256 genAmount, 33 | uint256 potAmount, 34 | uint256 airDropPot 35 | ); 36 | 37 | // fired whenever theres a withdraw 38 | event onWithdraw 39 | ( 40 | uint256 indexed playerID, 41 | address playerAddress, 42 | bytes32 playerName, 43 | uint256 ethOut, 44 | uint256 timeStamp 45 | ); 46 | 47 | // fired whenever a withdraw forces end round to be ran 48 | event onWithdrawAndDistribute 49 | ( 50 | address playerAddress, 51 | bytes32 playerName, 52 | uint256 ethOut, 53 | uint256 compressedData, 54 | uint256 compressedIDs, 55 | address winnerAddr, 56 | bytes32 winnerName, 57 | uint256 amountWon, 58 | uint256 newPot, 59 | uint256 P3DAmount, 60 | uint256 genAmount 61 | ); 62 | 63 | // (fomo3d long only) fired whenever a player tries a buy after round timer 64 | // hit zero, and causes end round to be ran. 65 | event onBuyAndDistribute 66 | ( 67 | address playerAddress, 68 | bytes32 playerName, 69 | uint256 ethIn, 70 | uint256 compressedData, 71 | uint256 compressedIDs, 72 | address winnerAddr, 73 | bytes32 winnerName, 74 | uint256 amountWon, 75 | uint256 newPot, 76 | uint256 P3DAmount, 77 | uint256 genAmount 78 | ); 79 | 80 | // (fomo3d long only) fired whenever a player tries a reload after round timer 81 | // hit zero, and causes end round to be ran. 82 | event onReLoadAndDistribute 83 | ( 84 | address playerAddress, 85 | bytes32 playerName, 86 | uint256 compressedData, 87 | uint256 compressedIDs, 88 | address winnerAddr, 89 | bytes32 winnerName, 90 | uint256 amountWon, 91 | uint256 newPot, 92 | uint256 P3DAmount, 93 | uint256 genAmount 94 | ); 95 | 96 | // fired whenever an affiliate is paid 97 | event onAffiliatePayout 98 | ( 99 | uint256 indexed affiliateID, 100 | address affiliateAddress, 101 | bytes32 affiliateName, 102 | uint256 indexed roundID, 103 | uint256 indexed buyerID, 104 | uint256 amount, 105 | uint256 timeStamp 106 | ); 107 | 108 | // received pot swap deposit 109 | event onPotSwapDeposit 110 | ( 111 | uint256 roundID, 112 | uint256 amountAddedToPot 113 | ); 114 | } -------------------------------------------------------------------------------- /contracts/library/NameFilter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | /** 4 | * @title -Name Filter- v0.1.9 5 | * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ 6 | * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ 7 | * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ 8 | * _____ _____ 9 | * (, / /) /) /) (, / /) /) 10 | * ┌─┐ / _ (/_ // // / _ // _ __ _(/ 11 | * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ 12 | * ┴ ┴ / / .-/ _____ (__ / 13 | * (__ / (_/ (, / /)™ 14 | * / __ __ __ __ _ __ __ _ _/_ _ _(/ 15 | * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ 16 | * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 17 | * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ 18 | * _ __ _ ____ ____ _ _ _____ ____ ___ 19 | *=============| |\ | / /\ | |\/| | |_ =====| |_ | | | | | | | |_ | |_)==============* 20 | *=============|_| \| /_/--\ |_| | |_|__=====|_| |_| |_|__ |_| |_|__ |_| \==============* 21 | * 22 | * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ 23 | * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ 24 | * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ 25 | */ 26 | 27 | library NameFilter { 28 | /** 29 | * @dev filters name strings 30 | * -converts uppercase to lower case. 31 | * -makes sure it does not start/end with a space 32 | * -makes sure it does not contain multiple spaces in a row 33 | * -cannot be only numbers 34 | * -cannot start with 0x 35 | * -restricts characters to A-Z, a-z, 0-9, and space. 36 | * @return reprocessed string in bytes32 format 37 | */ 38 | function nameFilter(string _input) 39 | internal 40 | pure 41 | returns(bytes32) 42 | { 43 | bytes memory _temp = bytes(_input); 44 | uint256 _length = _temp.length; 45 | 46 | //sorry limited to 32 characters 47 | require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters"); 48 | // make sure it doesnt start with or end with space 49 | require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space"); 50 | // make sure first two characters are not 0x 51 | if (_temp[0] == 0x30) 52 | { 53 | require(_temp[1] != 0x78, "string cannot start with 0x"); 54 | require(_temp[1] != 0x58, "string cannot start with 0X"); 55 | } 56 | 57 | // create a bool to track if we have a non number character 58 | bool _hasNonNumber; 59 | 60 | // convert & check 61 | for (uint256 i = 0; i < _length; i++) 62 | { 63 | // if its uppercase A-Z 64 | if (_temp[i] > 0x40 && _temp[i] < 0x5b) 65 | { 66 | // convert to lower case a-z 67 | _temp[i] = byte(uint(_temp[i]) + 32); 68 | 69 | // we have a non number 70 | if (_hasNonNumber == false) 71 | _hasNonNumber = true; 72 | } else { 73 | require 74 | ( 75 | // require character is a space 76 | _temp[i] == 0x20 || 77 | // OR lowercase a-z 78 | (_temp[i] > 0x60 && _temp[i] < 0x7b) || 79 | // or 0-9 80 | (_temp[i] > 0x2f && _temp[i] < 0x3a), 81 | "string contains invalid characters" 82 | ); 83 | // make sure theres not 2x spaces in a row 84 | if (_temp[i] == 0x20) 85 | require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces"); 86 | 87 | // see if we have a character other than a number 88 | if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39)) 89 | _hasNonNumber = true; 90 | } 91 | } 92 | 93 | require(_hasNonNumber == true, "string cannot be only numbers"); 94 | 95 | bytes32 _ret; 96 | assembly { 97 | _ret := mload(add(_temp, 32)) 98 | } 99 | return (_ret); 100 | } 101 | } -------------------------------------------------------------------------------- /contracts/JIincForwarder.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | /* 3 | * @title -Jekyll Island- CORP BANK FORWARDER v0.4.6 4 | * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ 5 | * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ 6 | * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ 7 | * _____ _____ 8 | * (, / /) /) /) (, / /) /) 9 | * ┌─┐ / _ (/_ // // / _ // _ __ _(/ 10 | * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ 11 | * ┴ ┴ / / .-/ _____ (__ / 12 | * (__ / (_/ (, / /)™ 13 | * / __ __ __ __ _ __ __ _ _/_ _ _(/ 14 | * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ 15 | * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 16 | * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ 17 | *====/$$$$$===========/$$=================/$$ /$$====/$$$$$$===========/$$===========================/$$=* 18 | * |__ $$ | $$ | $$| $$ |_ $$_/ | $$ | $$ 19 | * | $$ /$$$$$$ | $$ /$$ /$$ /$$| $$| $$ | $$ /$$$$$$$| $$ /$$$$$$ /$$$$$$$ /$$$$$$$ 20 | * | $$ /$$__ $$| $$ /$$/| $$ | $$| $$| $$ | $$ /$$_____/| $$ |____ $$| $$__ $$ /$$__ $$ 21 | * /$$ | $$| $$$$$$$$| $$$$$$/ | $$ | $$| $$| $$ | $$ | $$$$$$ | $$ /$$$$$$$| $$ \ $$| $$ | $$ 22 | *| $$ | $$| $$_____/| $$_ $$ | $$ | $$| $$| $$ | $$ \____ $$| $$ /$$__ $$| $$ | $$| $$ | $$ 23 | *| $$$$$$/| $$$$$$$| $$ \ $$| $$$$$$$| $$| $$ /$$$$$$ /$$$$$$$/| $$| $$$$$$$| $$ | $$| $$$$$$$ 24 | * \______/ \_______/|__/ \__/ \____ $$|__/|__/ |______/|_______/ |__/ \_______/|__/ |__/ \_______/ 25 | *===============================/$$ | $$ Inc. ╔═╗╔═╗╦═╗╔═╗ ╔╗ ╔═╗╔╗╔╦╔═ ┌─┐┌─┐┬─┐┬ ┬┌─┐┬─┐┌┬┐┌─┐┬─┐ 26 | * | $$$$$$/=======║ ║ ║╠╦╝╠═╝ ╠╩╗╠═╣║║║╠╩╗ ├┤ │ │├┬┘│││├─┤├┬┘ ││├┤ ├┬┘ 27 | * \______/ ╚═╝╚═╝╩╚═╩ ╚═╝╩ ╩╝╚╝╩ ╩ └ └─┘┴└─└┴┘┴ ┴┴└──┴┘└─┘┴└─==* 28 | * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ 29 | * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ 30 | * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ 31 | *===========================================================================================* 32 | * ┌────────────────────┐ 33 | * │ Setup Instructions │ 34 | * └────────────────────┘ 35 | * (Step 1) import the Jekyll Island Inc Forwarder Interface into your contract 36 | * 37 | * import "./JIincForwarderInterface.sol"; 38 | * 39 | * (Step 2) set it to point to the forwarder 40 | * 41 | * JIincForwarderInterface private Jekyll_Island_Inc = JIincForwarderInterface(0xdd4950F977EE28D2C132f1353D1595035Db444EE); 42 | * ┌────────────────────┐ 43 | * │ Usage Instructions │ 44 | * └────────────────────┘ 45 | * whenever your contract needs to send eth to the corp bank, simply use the 46 | * the following command: 47 | * 48 | * Jekyll_Island_Inc.deposit.value(amount)() 49 | * 50 | * OPTIONAL: 51 | * if you need to be checking wither the transaction was successful, the deposit function returns 52 | * a bool indicating wither or not it was successful. so another way to call this function 53 | * would be: 54 | * 55 | * require(Jekyll_Island_Inc.deposit.value(amount)() == true, "Jekyll Island deposit failed"); 56 | * 57 | */ 58 | 59 | interface JIincInterfaceForForwarder { 60 | function deposit(address _addr) external payable returns (bool); 61 | function migrationReceiver_setup() external returns (bool); 62 | } 63 | 64 | contract JIincForwarder { 65 | string public name = "JIincForwarder"; 66 | JIincInterfaceForForwarder private currentCorpBank_; 67 | address private newCorpBank_; 68 | bool needsBank_ = true; 69 | 70 | constructor() 71 | public 72 | { 73 | //constructor does nothing. 74 | } 75 | 76 | function() 77 | public 78 | payable 79 | { 80 | // done so that if any one tries to dump eth into this contract, we can 81 | // just forward it to corp bank. 82 | currentCorpBank_.deposit.value(address(this).balance)(address(currentCorpBank_)); 83 | } 84 | 85 | function deposit() 86 | public 87 | payable 88 | returns(bool) 89 | { 90 | require(msg.value > 0, "Forwarder Deposit failed - zero deposits not allowed"); 91 | require(needsBank_ == false, "Forwarder Deposit failed - no registered bank"); 92 | if (currentCorpBank_.deposit.value(msg.value)(msg.sender) == true) 93 | return(true); 94 | else 95 | return(false); 96 | } 97 | //============================================================================== 98 | // _ _ . _ _ _ _|_. _ _ . 99 | // | | ||(_|| (_| | |(_)| | . 100 | //===========_|================================================================= 101 | function status() 102 | public 103 | view 104 | returns(address, address, bool) 105 | { 106 | return(address(currentCorpBank_), address(newCorpBank_), needsBank_); 107 | } 108 | 109 | function startMigration(address _newCorpBank) 110 | external 111 | returns(bool) 112 | { 113 | // make sure this is coming from current corp bank 114 | require(msg.sender == address(currentCorpBank_), "Forwarder startMigration failed - msg.sender must be current corp bank"); 115 | 116 | // communicate with the new corp bank and make sure it has the forwarder 117 | // registered 118 | if(JIincInterfaceForForwarder(_newCorpBank).migrationReceiver_setup() == true) 119 | { 120 | // save our new corp bank address 121 | newCorpBank_ = _newCorpBank; 122 | return (true); 123 | } else 124 | return (false); 125 | } 126 | 127 | function cancelMigration() 128 | external 129 | returns(bool) 130 | { 131 | // make sure this is coming from the current corp bank (also lets us know 132 | // that current corp bank has not been killed) 133 | require(msg.sender == address(currentCorpBank_), "Forwarder cancelMigration failed - msg.sender must be current corp bank"); 134 | 135 | // erase stored new corp bank address; 136 | newCorpBank_ = address(0x0); 137 | 138 | return (true); 139 | } 140 | 141 | function finishMigration() 142 | external 143 | returns(bool) 144 | { 145 | // make sure its coming from new corp bank 146 | require(msg.sender == newCorpBank_, "Forwarder finishMigration failed - msg.sender must be new corp bank"); 147 | 148 | // update corp bank address 149 | currentCorpBank_ = (JIincInterfaceForForwarder(newCorpBank_)); 150 | 151 | // erase new corp bank address 152 | newCorpBank_ = address(0x0); 153 | 154 | return (true); 155 | } 156 | //============================================================================== 157 | // . _ ._|_. _ | _ _ _|_ _ . 158 | // || || | |(_|| _\(/_ | |_||_) . (this only runs once ever) 159 | //==============================|=============================================== 160 | function setup(address _firstCorpBank) 161 | external 162 | { 163 | require(needsBank_ == true, "Forwarder setup failed - corp bank already registered"); 164 | currentCorpBank_ = JIincInterfaceForForwarder(_firstCorpBank); 165 | needsBank_ = false; 166 | } 167 | } -------------------------------------------------------------------------------- /contracts/Divies.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | /** title -Divies- v0.7.1 3 | * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ 4 | * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ 5 | * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ 6 | * _____ _____ 7 | * (, / /) /) /) (, / /) /) 8 | * ┌─┐ / _ (/_ // // / _ // _ __ _(/ 9 | * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ 10 | * ┴ ┴ / / .-/ _____ (__ / 11 | * (__ / (_/ (, / /)™ 12 | * / __ __ __ __ _ __ __ _ _/_ _ _(/ 13 | * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ 14 | * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 15 | * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ 16 | * ______ .-./`) ,---. ,---. .-./`) .-''-. .-'''-. .---. 17 | *=========| _ `''. \ .-.') | / | | \ .-.') .'_ _ \ / _ \ \ /=========* 18 | * | _ | ) _ \ / `-' \ | | | .' / `-' \ / ( ` ) ' (`' )/`--' | | 19 | * |( ''_' ) | `-'`"` | | _ | | `-'`"` . (_ o _) | (_ o _). \ / 20 | * | . (_) `. | .---. | _( )_ | .---. | (_,_)___| (_,_). '. v 21 | * |(_ ._) ' | | \ (_ o._) / | | ' \ .---. .---. \ : _ _ 22 | * | (_.\.' / | | \ (_,_) / | | \ `-' / \ `-' | (_I_) 23 | *=========| .' | | \ / | | \ / \ / (_(=)_)========* 24 | * '-----'` '---' `---` '---' `'-..-' `-...-' (_I_) 25 | * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ 26 | * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ 27 | * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ 28 | * ┌──────────────────────────────────────────────────────────────────────┐ 29 | * │ Divies!, is a contract that adds an external dividend system to P3D. │ 30 | * │ All eth sent to this contract, can be distributed to P3D holders. │ 31 | * │ Uses msg.sender as masternode for initial buy order. │ 32 | * └──────────────────────────────────────────────────────────────────────┘ 33 | * ┌────────────────────┐ 34 | * │ Setup Instructions │ 35 | * └────────────────────┘ 36 | * (Step 1) import this contracts interface into your contract 37 | * 38 | * import "./DiviesInterface.sol"; 39 | * 40 | * (Step 2) set up the interface and point it to this contract 41 | * 42 | * DiviesInterface private Divies = DiviesInterface(0xc7029Ed9EBa97A096e72607f4340c34049C7AF48); 43 | * ┌────────────────────┐ 44 | * │ Usage Instructions │ 45 | * └────────────────────┘ 46 | * call as follows anywhere in your code: 47 | * 48 | * Divies.deposit.value(amount)(); 49 | * ex: Divies.deposit.value(232000000000000000000)(); 50 | */ 51 | 52 | import "./interface/DiviesInterface.sol"; 53 | import "./library/SafeMath.sol"; 54 | import "./library/UintCompressor.sol"; 55 | import "./interface/HourglassInterface.sol"; 56 | 57 | contract Divies { 58 | using SafeMath for uint256; 59 | using UintCompressor for uint256; 60 | 61 | HourglassInterface constant P3Dcontract_ = HourglassInterface(0xB3775fB83F7D12A36E0475aBdD1FCA35c091efBe); 62 | 63 | uint256 public pusherTracker_ = 100; 64 | mapping (address => Pusher) public pushers_; 65 | struct Pusher 66 | { 67 | uint256 tracker; 68 | uint256 time; 69 | } 70 | uint256 public rateLimiter_; 71 | 72 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 73 | // MODIFIERS 74 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 75 | modifier isHuman() { 76 | address _addr = msg.sender; 77 | uint256 _codeLength; 78 | 79 | assembly {_codeLength := extcodesize(_addr)} 80 | require(_codeLength == 0, "sorry humans only"); 81 | _; 82 | } 83 | 84 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 85 | // BALANCE 86 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 87 | function balances() 88 | public 89 | view 90 | returns(uint256) 91 | { 92 | return (address(this).balance); 93 | } 94 | 95 | 96 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 97 | // DEPOSIT 98 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 99 | function deposit() 100 | external 101 | payable 102 | { 103 | 104 | } 105 | 106 | // used so the distribute function can call hourglass's withdraw 107 | function() external payable {} 108 | 109 | 110 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 111 | // EVENTS 112 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 113 | event onDistribute( 114 | address pusher, 115 | uint256 startingBalance, 116 | uint256 masternodePayout, 117 | uint256 finalBalance, 118 | uint256 compressedData 119 | ); 120 | /* compression key 121 | [0-14] - timestamp 122 | [15-29] - caller pusher tracker 123 | [30-44] - global pusher tracker 124 | [45-46] - percent 125 | [47] - greedy 126 | */ 127 | 128 | 129 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 130 | // DISTRIBUTE 131 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 132 | function distribute(uint256 _percent) 133 | public 134 | isHuman() 135 | { 136 | // make sure _percent is within boundaries 137 | require(_percent > 0 && _percent < 100, "please pick a percent between 1 and 99"); 138 | 139 | // data setup 140 | address _pusher = msg.sender; 141 | uint256 _bal = address(this).balance; 142 | uint256 _mnPayout; 143 | uint256 _compressedData; 144 | 145 | // limit pushers greed (use "if" instead of require for level 42 top kek) 146 | if ( 147 | pushers_[_pusher].tracker <= pusherTracker_.sub(100) && // pusher is greedy: wait your turn 148 | pushers_[_pusher].time.add(1 hours) < now // pusher is greedy: its not even been 1 hour 149 | ) 150 | { 151 | // update pushers wait que 152 | pushers_[_pusher].tracker = pusherTracker_; 153 | pusherTracker_++; 154 | 155 | // setup mn payout for event 156 | if (P3Dcontract_.balanceOf(_pusher) >= P3Dcontract_.stakingRequirement()) 157 | _mnPayout = (_bal / 10) / 3; 158 | 159 | // setup _stop. this will be used to tell the loop to stop 160 | uint256 _stop = (_bal.mul(100 - _percent)) / 100; 161 | 162 | // buy & sell 163 | P3Dcontract_.buy.value(_bal)(_pusher); 164 | P3Dcontract_.sell(P3Dcontract_.balanceOf(address(this))); 165 | 166 | // setup tracker. this will be used to tell the loop to stop 167 | uint256 _tracker = P3Dcontract_.dividendsOf(address(this)); 168 | 169 | // reinvest/sell loop 170 | while (_tracker >= _stop) 171 | { 172 | // lets burn some tokens to distribute dividends to p3d holders 173 | P3Dcontract_.reinvest(); 174 | P3Dcontract_.sell(P3Dcontract_.balanceOf(address(this))); 175 | 176 | // update our tracker with estimates (yea. not perfect, but cheaper on gas) 177 | _tracker = (_tracker.mul(81)) / 100; 178 | } 179 | 180 | // withdraw 181 | P3Dcontract_.withdraw(); 182 | } else { 183 | _compressedData = _compressedData.insert(1, 47, 47); 184 | } 185 | 186 | // update pushers timestamp (do outside of "if" for super saiyan level top kek) 187 | pushers_[_pusher].time = now; 188 | 189 | // prep event compression data 190 | _compressedData = _compressedData.insert(now, 0, 14); 191 | _compressedData = _compressedData.insert(pushers_[_pusher].tracker, 15, 29); 192 | _compressedData = _compressedData.insert(pusherTracker_, 30, 44); 193 | _compressedData = _compressedData.insert(_percent, 45, 46); 194 | 195 | // fire event 196 | emit onDistribute(_pusher, _bal, _mnPayout, address(this).balance, _compressedData); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /contracts/library/MSFun.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | /** @title -MSFun- v0.2.4 4 | * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ 5 | * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ 6 | * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ 7 | * _____ _____ 8 | * (, / /) /) /) (, / /) /) 9 | * ┌─┐ / _ (/_ // // / _ // _ __ _(/ 10 | * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ 11 | * ┴ ┴ / / .-/ _____ (__ / 12 | * (__ / (_/ (, / /)™ 13 | * / __ __ __ __ _ __ __ _ _/_ _ _(/ 14 | * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ 15 | * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 16 | * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ 17 | * _ _ _ _ _ _ _ _ _ _ _ 18 | *=(_) _ _ (_)==========_(_)(_)(_)(_)_==========(_)(_)(_)(_)(_)================================* 19 | * (_)(_) (_)(_) (_) (_) (_) _ _ _ _ _ _ 20 | * (_) (_)_(_) (_) (_)_ _ _ _ (_) _ _ (_) (_) (_)(_)(_)(_)_ 21 | * (_) (_) (_) (_)(_)(_)(_)_ (_)(_)(_)(_) (_) (_) (_) 22 | * (_) (_) _ _ _ (_) _ _ (_) (_) (_) (_) (_) _ _ 23 | *=(_)=========(_)=(_)(_)==(_)_ _ _ _(_)=(_)(_)==(_)======(_)_ _ _(_)_ (_)========(_)=(_)(_)==* 24 | * (_) (_) (_)(_) (_)(_)(_)(_) (_)(_) (_) (_)(_)(_) (_)(_) (_) (_)(_) 25 | * 26 | * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ 27 | * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ 28 | * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ 29 | * 30 | * ┌──────────────────────────────────────────────────────────────────────┐ 31 | * │ MSFun, is an importable library that gives your contract the ability │ 32 | * │ add multiSig requirement to functions. │ 33 | * └──────────────────────────────────────────────────────────────────────┘ 34 | * ┌────────────────────┐ 35 | * │ Setup Instructions │ 36 | * └────────────────────┘ 37 | * (Step 1) import the library into your contract 38 | * 39 | * import "./MSFun.sol"; 40 | * 41 | * (Step 2) set up the signature data for msFun 42 | * 43 | * MSFun.Data private msData; 44 | * ┌────────────────────┐ 45 | * │ Usage Instructions │ 46 | * └────────────────────┘ 47 | * at the beginning of a function 48 | * 49 | * function functionName() 50 | * { 51 | * if (MSFun.multiSig(msData, required signatures, "functionName") == true) 52 | * { 53 | * MSFun.deleteProposal(msData, "functionName"); 54 | * 55 | * // put function body here 56 | * } 57 | * } 58 | * ┌────────────────────────────────┐ 59 | * │ Optional Wrappers For TeamJust │ 60 | * └────────────────────────────────┘ 61 | * multiSig wrapper function (cuts down on inputs, improves readability) 62 | * this wrapper is HIGHLY recommended 63 | * 64 | * function multiSig(bytes32 _whatFunction) private returns (bool) {return(MSFun.multiSig(msData, TeamJust.requiredSignatures(), _whatFunction));} 65 | * function multiSigDev(bytes32 _whatFunction) private returns (bool) {return(MSFun.multiSig(msData, TeamJust.requiredDevSignatures(), _whatFunction));} 66 | * 67 | * wrapper for delete proposal (makes code cleaner) 68 | * 69 | * function deleteProposal(bytes32 _whatFunction) private {MSFun.deleteProposal(msData, _whatFunction);} 70 | * ┌────────────────────────────┐ 71 | * │ Utility & Vanity Functions │ 72 | * └────────────────────────────┘ 73 | * delete any proposal is highly recommended. without it, if an admin calls a multiSig 74 | * function, with argument inputs that the other admins do not agree upon, the function 75 | * can never be executed until the undesirable arguments are approved. 76 | * 77 | * function deleteAnyProposal(bytes32 _whatFunction) onlyDevs() public {MSFun.deleteProposal(msData, _whatFunction);} 78 | * 79 | * for viewing who has signed a proposal & proposal data 80 | * 81 | * function checkData(bytes32 _whatFunction) onlyAdmins() public view returns(bytes32, uint256) {return(MSFun.checkMsgData(msData, _whatFunction), MSFun.checkCount(msData, _whatFunction));} 82 | * 83 | * lets you check address of up to 3 signers (address) 84 | * 85 | * function checkSignersByAddress(bytes32 _whatFunction, uint256 _signerA, uint256 _signerB, uint256 _signerC) onlyAdmins() public view returns(address, address, address) {return(MSFun.checkSigner(msData, _whatFunction, _signerA), MSFun.checkSigner(msData, _whatFunction, _signerB), MSFun.checkSigner(msData, _whatFunction, _signerC));} 86 | * 87 | * same as above but will return names in string format. 88 | * 89 | * function checkSignersByName(bytes32 _whatFunction, uint256 _signerA, uint256 _signerB, uint256 _signerC) onlyAdmins() public view returns(bytes32, bytes32, bytes32) {return(TeamJust.adminName(MSFun.checkSigner(msData, _whatFunction, _signerA)), TeamJust.adminName(MSFun.checkSigner(msData, _whatFunction, _signerB)), TeamJust.adminName(MSFun.checkSigner(msData, _whatFunction, _signerC)));} 90 | * ┌──────────────────────────┐ 91 | * │ Functions In Depth Guide │ 92 | * └──────────────────────────┘ 93 | * In the following examples, the Data is the proposal set for this library. And 94 | * the bytes32 is the name of the function. 95 | * 96 | * MSFun.multiSig(Data, uint256, bytes32) - Manages creating/updating multiSig 97 | * proposal for the function being called. The uint256 is the required 98 | * number of signatures needed before the multiSig will return true. 99 | * Upon first call, multiSig will create a proposal and store the arguments 100 | * passed with the function call as msgData. Any admins trying to sign the 101 | * function call will need to send the same argument values. Once required 102 | * number of signatures is reached this will return a bool of true. 103 | * 104 | * MSFun.deleteProposal(Data, bytes32) - once multiSig unlocks the function body, 105 | * you will want to delete the proposal data. This does that. 106 | * 107 | * MSFun.checkMsgData(Data, bytes32) - checks the message data for any given proposal 108 | * 109 | * MSFun.checkCount(Data, bytes32) - checks the number of admins that have signed 110 | * the proposal 111 | * 112 | * MSFun.checkSigners(data, bytes32, uint256) - checks the address of a given signer. 113 | * the uint256, is the log number of the signer (ie 1st signer, 2nd signer) 114 | */ 115 | 116 | library MSFun { 117 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 118 | // DATA SETS 119 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 120 | // contact data setup 121 | struct Data 122 | { 123 | mapping (bytes32 => ProposalData) proposal_; 124 | } 125 | struct ProposalData 126 | { 127 | // a hash of msg.data 128 | bytes32 msgData; 129 | // number of signers 130 | uint256 count; 131 | // tracking of wither admins have signed 132 | mapping (address => bool) admin; 133 | // list of admins who have signed 134 | mapping (uint256 => address) log; 135 | } 136 | 137 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 138 | // MULTI SIG FUNCTIONS 139 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 140 | function multiSig(Data storage self, uint256 _requiredSignatures, bytes32 _whatFunction) 141 | internal 142 | returns(bool) 143 | { 144 | // our proposal key will be a hash of our function name + our contracts address 145 | // by adding our contracts address to this, we prevent anyone trying to circumvent 146 | // the proposal's security via external calls. 147 | bytes32 _whatProposal = whatProposal(_whatFunction); 148 | 149 | // this is just done to make the code more readable. grabs the signature count 150 | uint256 _currentCount = self.proposal_[_whatProposal].count; 151 | 152 | // store the address of the person sending the function call. we use msg.sender 153 | // here as a layer of security. in case someone imports our contract and tries to 154 | // circumvent function arguments. still though, our contract that imports this 155 | // library and calls multisig, needs to use onlyAdmin modifiers or anyone who 156 | // calls the function will be a signer. 157 | address _whichAdmin = msg.sender; 158 | 159 | // prepare our msg data. by storing this we are able to verify that all admins 160 | // are approving the same argument input to be executed for the function. we hash 161 | // it and store in bytes32 so its size is known and comparable 162 | bytes32 _msgData = keccak256(msg.data); 163 | 164 | // check to see if this is a new execution of this proposal or not 165 | if (_currentCount == 0) 166 | { 167 | // if it is, lets record the original signers data 168 | self.proposal_[_whatProposal].msgData = _msgData; 169 | 170 | // record original senders signature 171 | self.proposal_[_whatProposal].admin[_whichAdmin] = true; 172 | 173 | // update log (used to delete records later, and easy way to view signers) 174 | // also useful if the calling function wants to give something to a 175 | // specific signer. 176 | self.proposal_[_whatProposal].log[_currentCount] = _whichAdmin; 177 | 178 | // track number of signatures 179 | self.proposal_[_whatProposal].count += 1; 180 | 181 | // if we now have enough signatures to execute the function, lets 182 | // return a bool of true. we put this here in case the required signatures 183 | // is set to 1. 184 | if (self.proposal_[_whatProposal].count == _requiredSignatures) { 185 | return(true); 186 | } 187 | // if its not the first execution, lets make sure the msgData matches 188 | } else if (self.proposal_[_whatProposal].msgData == _msgData) { 189 | // msgData is a match 190 | // make sure admin hasnt already signed 191 | if (self.proposal_[_whatProposal].admin[_whichAdmin] == false) 192 | { 193 | // record their signature 194 | self.proposal_[_whatProposal].admin[_whichAdmin] = true; 195 | 196 | // update log (used to delete records later, and easy way to view signers) 197 | self.proposal_[_whatProposal].log[_currentCount] = _whichAdmin; 198 | 199 | // track number of signatures 200 | self.proposal_[_whatProposal].count += 1; 201 | } 202 | 203 | // if we now have enough signatures to execute the function, lets 204 | // return a bool of true. 205 | // we put this here for a few reasons. (1) in normal operation, if 206 | // that last recorded signature got us to our required signatures. we 207 | // need to return bool of true. (2) if we have a situation where the 208 | // required number of signatures was adjusted to at or lower than our current 209 | // signature count, by putting this here, an admin who has already signed, 210 | // can call the function again to make it return a true bool. but only if 211 | // they submit the correct msg data 212 | if (self.proposal_[_whatProposal].count == _requiredSignatures) { 213 | return(true); 214 | } 215 | } 216 | } 217 | 218 | 219 | // deletes proposal signature data after successfully executing a multiSig function 220 | function deleteProposal(Data storage self, bytes32 _whatFunction) 221 | internal 222 | { 223 | //done for readability sake 224 | bytes32 _whatProposal = whatProposal(_whatFunction); 225 | address _whichAdmin; 226 | 227 | //delete the admins votes & log. i know for loops are terrible. but we have to do this 228 | //for our data stored in mappings. simply deleting the proposal itself wouldn't accomplish this. 229 | for (uint256 i=0; i < self.proposal_[_whatProposal].count; i++) { 230 | _whichAdmin = self.proposal_[_whatProposal].log[i]; 231 | delete self.proposal_[_whatProposal].admin[_whichAdmin]; 232 | delete self.proposal_[_whatProposal].log[i]; 233 | } 234 | //delete the rest of the data in the record 235 | delete self.proposal_[_whatProposal]; 236 | } 237 | 238 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 239 | // HELPER FUNCTIONS 240 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 241 | 242 | function whatProposal(bytes32 _whatFunction) 243 | private 244 | view 245 | returns(bytes32) 246 | { 247 | return(keccak256(abi.encodePacked(_whatFunction,this))); 248 | } 249 | 250 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 251 | // VANITY FUNCTIONS 252 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 253 | // returns a hashed version of msg.data sent by original signer for any given function 254 | function checkMsgData (Data storage self, bytes32 _whatFunction) 255 | internal 256 | view 257 | returns (bytes32 msg_data) 258 | { 259 | bytes32 _whatProposal = whatProposal(_whatFunction); 260 | return (self.proposal_[_whatProposal].msgData); 261 | } 262 | 263 | // returns number of signers for any given function 264 | function checkCount (Data storage self, bytes32 _whatFunction) 265 | internal 266 | view 267 | returns (uint256 signature_count) 268 | { 269 | bytes32 _whatProposal = whatProposal(_whatFunction); 270 | return (self.proposal_[_whatProposal].count); 271 | } 272 | 273 | // returns address of an admin who signed for any given function 274 | function checkSigner (Data storage self, bytes32 _whatFunction, uint256 _signer) 275 | internal 276 | view 277 | returns (address signer) 278 | { 279 | require(_signer > 0, "MSFun checkSigner failed - 0 not allowed"); 280 | bytes32 _whatProposal = whatProposal(_whatFunction); 281 | return (self.proposal_[_whatProposal].log[_signer - 1]); 282 | } 283 | } -------------------------------------------------------------------------------- /contracts/TeamJust.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | /* -Team Just- v0.2.5 3 | * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ 4 | * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ 5 | * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ 6 | * _____ _____ 7 | * (, / /) /) /) (, / /) /) 8 | * ┌─┐ / _ (/_ // // / _ // _ __ _(/ 9 | * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ 10 | * ┴ ┴ / / .-/ _____ (__ / 11 | * (__ / (_/ (, / /)™ 12 | * / __ __ __ __ _ __ __ _ _/_ _ _(/ 13 | * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ 14 | * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 15 | * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ 16 | * JJJJJJJJJJUUUUUUUU UUUUUUUU SSSSSSSSSSSSSSSTTTTTTTTTTTTTTTTTTTTTTT 17 | *==============J:::::::::U::::::U=====U::::::USS:::::::::::::::T:::::::::::::::::::::T======* 18 | * J:::::::::U::::::U U::::::S:::::SSSSSS::::::T:::::::::::::::::::::T 19 | * JJ:::::::JUU:::::U U:::::US:::::S SSSSSST:::::TT:::::::TT:::::T 20 | * J:::::J U:::::U U:::::US:::::S TTTTTT T:::::T TTTTTT 21 | * J::_________ : ________::::US::_::S ____ ____ T:::::T 22 | * J:| _ _ |:|_ __ |:::U S/ \:SSSS |_ \ / _| T:::::T 23 | * J:|_/:| |U\_|::D| |_ \_|:::U / _ \::::SSS| \/ | T:::::T 24 | * J:::::| |U:::::D| _| _::::U/ ___ \::::::| |\ /| | T:::::T 25 | * JJJJJJJ J::::_| |_:::::_| |__/ |::_/ / \ \_SS _| |_\/_| |_ T:::::T 26 | * J:::::J J:::|_____|:::|________|:|____| |____| |_____||_____| T:::::T 27 | * J::::::J J::::::J U::::::U U::::::U S:::::S T:::::T 28 | * J:::::::JJJ:::::::J U:::::::UUU:::::::USSSSSSS S:::::S TT:::::::TT 29 | * JJ:::::::::::::JJ UU:::::::::::::UU S::::::SSSSSS:::::S T:::::::::T 30 | *=======JJ:::::::::JJ========UU:::::::::UU===S:::::::::::::::SS======T:::::::::T============* 31 | * JJJJJJJJJ UUUUUUUUU SSSSSSSSSSSSSSS TTTTTTTTTTT 32 | * 33 | * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ 34 | * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ 35 | * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ 36 | * 37 | * ┌──────────────────────────────────────────────────────────────────────┐ 38 | * │ Que up intensely spectacular intro music... In walks, Team Just. │ 39 | * │ Everyone goes crazy. │ 40 | * │ This is a companion to MSFun. It's a central database of Devs and │ 41 | * │ Admin's that we can import to any dapp to allow them management │ 42 | * │ permissions. │ 43 | * └──────────────────────────────────────────────────────────────────────┘ 44 | * ┌────────────────────┐ 45 | * │ Setup Instructions │ 46 | * └────────────────────┘ 47 | * (Step 1) import this contracts interface into your contract 48 | * 49 | * import "./TeamJustInterface.sol"; 50 | * 51 | * (Step 2) set up the interface to point to the TeamJust contract 52 | * 53 | * TeamJustInterface constant TeamJust = TeamJustInterface(0x464904238b5CdBdCE12722A7E6014EC1C0B66928); 54 | * 55 | * modifier onlyAdmins() {require(TeamJust.isAdmin(msg.sender) == true, "onlyAdmins failed - msg.sender is not an admin"); _;} 56 | * modifier onlyDevs() {require(TeamJust.isDev(msg.sender) == true, "onlyDevs failed - msg.sender is not a dev"); _;} 57 | * ┌────────────────────┐ 58 | * │ Usage Instructions │ 59 | * └────────────────────┘ 60 | * use onlyAdmins() and onlyDevs() modifiers as you normally would on any function 61 | * you wish to restrict to admins/devs registered with this contract. 62 | * 63 | * to get required signatures for admins or devs 64 | * uint256 x = TeamJust.requiredSignatures(); 65 | * uint256 x = TeamJust.requiredDevSignatures(); 66 | * 67 | * to get admin count or dev count 68 | * uint256 x = TeamJust.adminCount(); 69 | * uint256 x = TeamJust.devCount(); 70 | * 71 | * to get the name of an admin (in bytes32 format) 72 | * bytes32 x = TeamJust.adminName(address); 73 | */ 74 | 75 | 76 | import "./library/SafeMath.sol"; 77 | import "./library/NameFilter.sol"; 78 | import "./library/MSFun.sol"; 79 | 80 | import "./interface/TeamJustInterface.sol"; 81 | import "./interface/JIincForwarderInterface.sol"; 82 | import "./interface/PlayerBookReceiverInterface.sol"; 83 | 84 | 85 | contract TeamJust { 86 | JIincForwarderInterface private Jekyll_Island_Inc = JIincForwarderInterface(0x0); 87 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 88 | // SET UP MSFun (note, check signers by name is modified from MSFun sdk) 89 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 90 | MSFun.Data private msData; 91 | function deleteAnyProposal(bytes32 _whatFunction) onlyDevs() public {MSFun.deleteProposal(msData, _whatFunction);} 92 | function checkData(bytes32 _whatFunction) onlyAdmins() public view returns(bytes32 message_data, uint256 signature_count) {return(MSFun.checkMsgData(msData, _whatFunction), MSFun.checkCount(msData, _whatFunction));} 93 | function checkSignersByName(bytes32 _whatFunction, uint256 _signerA, uint256 _signerB, uint256 _signerC) onlyAdmins() public view returns(bytes32, bytes32, bytes32) {return(this.adminName(MSFun.checkSigner(msData, _whatFunction, _signerA)), this.adminName(MSFun.checkSigner(msData, _whatFunction, _signerB)), this.adminName(MSFun.checkSigner(msData, _whatFunction, _signerC)));} 94 | 95 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 96 | // DATA SETUP 97 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 98 | struct Admin { 99 | bool isAdmin; 100 | bool isDev; 101 | bytes32 name; 102 | } 103 | mapping (address => Admin) admins_; 104 | 105 | uint256 adminCount_; 106 | uint256 devCount_; 107 | uint256 requiredSignatures_; 108 | uint256 requiredDevSignatures_; 109 | 110 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 111 | // CONSTRUCTOR 112 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 113 | constructor() 114 | public 115 | { 116 | address inventor = 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C; 117 | address mantso = 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D; 118 | address justo = 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53; 119 | address sumpunk = 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C; 120 | address deployer = 0xF39e044e1AB204460e06E87c6dca2c6319fC69E3; 121 | 122 | admins_[inventor] = Admin(true, true, "inventor"); 123 | admins_[mantso] = Admin(true, true, "mantso"); 124 | admins_[justo] = Admin(true, true, "justo"); 125 | admins_[sumpunk] = Admin(true, true, "sumpunk"); 126 | admins_[deployer] = Admin(true, true, "deployer"); 127 | 128 | adminCount_ = 5; 129 | devCount_ = 5; 130 | requiredSignatures_ = 1; 131 | requiredDevSignatures_ = 1; 132 | } 133 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 134 | // FALLBACK, SETUP, AND FORWARD 135 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 136 | // there should never be a balance in this contract. but if someone 137 | // does stupidly send eth here for some reason. we can forward it 138 | // to jekyll island 139 | function () 140 | public 141 | payable 142 | { 143 | Jekyll_Island_Inc.deposit.value(address(this).balance)(); 144 | } 145 | 146 | function setup(address _addr) 147 | onlyDevs() 148 | public 149 | { 150 | require( address(Jekyll_Island_Inc) == address(0) ); 151 | Jekyll_Island_Inc = JIincForwarderInterface(_addr); 152 | } 153 | 154 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 155 | // MODIFIERS 156 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 157 | modifier onlyDevs() 158 | { 159 | require(admins_[msg.sender].isDev == true, "onlyDevs failed - msg.sender is not a dev"); 160 | _; 161 | } 162 | 163 | modifier onlyAdmins() 164 | { 165 | require(admins_[msg.sender].isAdmin == true, "onlyAdmins failed - msg.sender is not an admin"); 166 | _; 167 | } 168 | 169 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 170 | // DEV ONLY FUNCTIONS 171 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 172 | /** 173 | * @dev DEV - use this to add admins. this is a dev only function. 174 | * @param _who - address of the admin you wish to add 175 | * @param _name - admins name 176 | * @param _isDev - is this admin also a dev? 177 | */ 178 | function addAdmin(address _who, bytes32 _name, bool _isDev) 179 | public 180 | onlyDevs() 181 | { 182 | if (MSFun.multiSig(msData, requiredDevSignatures_, "addAdmin") == true) 183 | { 184 | MSFun.deleteProposal(msData, "addAdmin"); 185 | 186 | // must check this so we dont mess up admin count by adding someone 187 | // who is already an admin 188 | if (admins_[_who].isAdmin == false) 189 | { 190 | 191 | // set admins flag to true in admin mapping 192 | admins_[_who].isAdmin = true; 193 | 194 | // adjust admin count and required signatures 195 | adminCount_ += 1; 196 | requiredSignatures_ += 1; 197 | } 198 | 199 | // are we setting them as a dev? 200 | // by putting this outside the above if statement, we can upgrade existing 201 | // admins to devs. 202 | if (_isDev == true) 203 | { 204 | // bestow the honored dev status 205 | admins_[_who].isDev = _isDev; 206 | 207 | // increase dev count and required dev signatures 208 | devCount_ += 1; 209 | requiredDevSignatures_ += 1; 210 | } 211 | } 212 | 213 | // by putting this outside the above multisig, we can allow easy name changes 214 | // without having to bother with multisig. this will still create a proposal though 215 | // so use the deleteAnyProposal to delete it if you want to 216 | admins_[_who].name = _name; 217 | } 218 | 219 | /** 220 | * @dev DEV - use this to remove admins. this is a dev only function. 221 | * -requirements: never less than 1 admin 222 | * never less than 1 dev 223 | * never less admins than required signatures 224 | * never less devs than required dev signatures 225 | * @param _who - address of the admin you wish to remove 226 | */ 227 | function removeAdmin(address _who) 228 | public 229 | onlyDevs() 230 | { 231 | // we can put our requires outside the multisig, this will prevent 232 | // creating a proposal that would never pass checks anyway. 233 | require(adminCount_ > 1, "removeAdmin failed - cannot have less than 2 admins"); 234 | require(adminCount_ >= requiredSignatures_, "removeAdmin failed - cannot have less admins than number of required signatures"); 235 | if (admins_[_who].isDev == true) 236 | { 237 | require(devCount_ > 1, "removeAdmin failed - cannot have less than 2 devs"); 238 | require(devCount_ >= requiredDevSignatures_, "removeAdmin failed - cannot have less devs than number of required dev signatures"); 239 | } 240 | 241 | // checks passed 242 | if (MSFun.multiSig(msData, requiredDevSignatures_, "removeAdmin") == true) 243 | { 244 | MSFun.deleteProposal(msData, "removeAdmin"); 245 | 246 | // must check this so we dont mess up admin count by removing someone 247 | // who wasnt an admin to start with 248 | if (admins_[_who].isAdmin == true) { 249 | 250 | //set admins flag to false in admin mapping 251 | admins_[_who].isAdmin = false; 252 | 253 | //adjust admin count and required signatures 254 | adminCount_ -= 1; 255 | if (requiredSignatures_ > 1) 256 | { 257 | requiredSignatures_ -= 1; 258 | } 259 | } 260 | 261 | // were they also a dev? 262 | if (admins_[_who].isDev == true) { 263 | 264 | //set dev flag to false 265 | admins_[_who].isDev = false; 266 | 267 | //adjust dev count and required dev signatures 268 | devCount_ -= 1; 269 | if (requiredDevSignatures_ > 1) 270 | { 271 | requiredDevSignatures_ -= 1; 272 | } 273 | } 274 | } 275 | } 276 | 277 | /** 278 | * @dev DEV - change the number of required signatures. must be between 279 | * 1 and the number of admins. this is a dev only function 280 | * @param _howMany - desired number of required signatures 281 | */ 282 | function changeRequiredSignatures(uint256 _howMany) 283 | public 284 | onlyDevs() 285 | { 286 | // make sure its between 1 and number of admins 287 | require(_howMany > 0 && _howMany <= adminCount_, "changeRequiredSignatures failed - must be between 1 and number of admins"); 288 | 289 | if (MSFun.multiSig(msData, requiredDevSignatures_, "changeRequiredSignatures") == true) 290 | { 291 | MSFun.deleteProposal(msData, "changeRequiredSignatures"); 292 | 293 | // store new setting. 294 | requiredSignatures_ = _howMany; 295 | } 296 | } 297 | 298 | /** 299 | * @dev DEV - change the number of required dev signatures. must be between 300 | * 1 and the number of devs. this is a dev only function 301 | * @param _howMany - desired number of required dev signatures 302 | */ 303 | function changeRequiredDevSignatures(uint256 _howMany) 304 | public 305 | onlyDevs() 306 | { 307 | // make sure its between 1 and number of admins 308 | require(_howMany > 0 && _howMany <= devCount_, "changeRequiredDevSignatures failed - must be between 1 and number of devs"); 309 | 310 | if (MSFun.multiSig(msData, requiredDevSignatures_, "changeRequiredDevSignatures") == true) 311 | { 312 | MSFun.deleteProposal(msData, "changeRequiredDevSignatures"); 313 | 314 | // store new setting. 315 | requiredDevSignatures_ = _howMany; 316 | } 317 | } 318 | 319 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 320 | // EXTERNAL FUNCTIONS 321 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 322 | function requiredSignatures() external view returns(uint256) {return(requiredSignatures_);} 323 | function requiredDevSignatures() external view returns(uint256) {return(requiredDevSignatures_);} 324 | function adminCount() external view returns(uint256) {return(adminCount_);} 325 | function devCount() external view returns(uint256) {return(devCount_);} 326 | function adminName(address _who) external view returns(bytes32) {return(admins_[_who].name);} 327 | function isAdmin(address _who) external view returns(bool) {return(admins_[_who].isAdmin);} 328 | function isDev(address _who) external view returns(bool) {return(admins_[_who].isDev);} 329 | } -------------------------------------------------------------------------------- /contracts/PlayerBook.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | /* 3 | * -PlayerBook - v0.3.14 4 | * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ 5 | * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ 6 | * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ 7 | * _____ _____ 8 | * (, / /) /) /) (, / /) /) 9 | * ┌─┐ / _ (/_ // // / _ // _ __ _(/ 10 | * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ 11 | * ┴ ┴ / / .-/ _____ (__ / 12 | * (__ / (_/ (, / /)™ 13 | * / __ __ __ __ _ __ __ _ _/_ _ _(/ 14 | * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ 15 | * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 16 | * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ 17 | * ______ _ ______ _ 18 | *====(_____ \=| |===============================(____ \===============| |=============* 19 | * _____) )| | _____ _ _ _____ ____ ____) ) ___ ___ | | _ 20 | * | ____/ | | (____ || | | || ___ | / ___) | __ ( / _ \ / _ \ | |_/ ) 21 | * | | | | / ___ || |_| || ____|| | | |__) )| |_| || |_| || _ ( 22 | *====|_|=======\_)\_____|=\__ ||_____)|_|======|______/==\___/==\___/=|_|=\_)=========* 23 | * (____/ 24 | * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ 25 | * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ 26 | * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ 27 | */ 28 | 29 | import "./library/SafeMath.sol"; 30 | import "./library/NameFilter.sol"; 31 | import "./library/MSFun.sol"; 32 | 33 | import "./interface/TeamJustInterface.sol"; 34 | import "./interface/JIincForwarderInterface.sol"; 35 | import "./interface/PlayerBookReceiverInterface.sol"; 36 | 37 | 38 | 39 | contract PlayerBook { 40 | using NameFilter for string; 41 | using SafeMath for uint256; 42 | 43 | JIincForwarderInterface constant private Jekyll_Island_Inc = JIincForwarderInterface(0xdd4950F977EE28D2C132f1353D1595035Db444EE); 44 | TeamJustInterface constant private TeamJust = TeamJustInterface(0x464904238b5CdBdCE12722A7E6014EC1C0B66928); 45 | 46 | MSFun.Data private msData; 47 | function multiSigDev(bytes32 _whatFunction) private returns (bool) {return(MSFun.multiSig(msData, TeamJust.requiredDevSignatures(), _whatFunction));} 48 | function deleteProposal(bytes32 _whatFunction) private {MSFun.deleteProposal(msData, _whatFunction);} 49 | function deleteAnyProposal(bytes32 _whatFunction) onlyDevs() public {MSFun.deleteProposal(msData, _whatFunction);} 50 | function checkData(bytes32 _whatFunction) onlyDevs() public view returns(bytes32, uint256) {return(MSFun.checkMsgData(msData, _whatFunction), MSFun.checkCount(msData, _whatFunction));} 51 | function checkSignersByAddress(bytes32 _whatFunction, uint256 _signerA, uint256 _signerB, uint256 _signerC) onlyDevs() public view returns(address, address, address) {return(MSFun.checkSigner(msData, _whatFunction, _signerA), MSFun.checkSigner(msData, _whatFunction, _signerB), MSFun.checkSigner(msData, _whatFunction, _signerC));} 52 | function checkSignersByName(bytes32 _whatFunction, uint256 _signerA, uint256 _signerB, uint256 _signerC) onlyDevs() public view returns(bytes32, bytes32, bytes32) {return(TeamJust.adminName(MSFun.checkSigner(msData, _whatFunction, _signerA)), TeamJust.adminName(MSFun.checkSigner(msData, _whatFunction, _signerB)), TeamJust.adminName(MSFun.checkSigner(msData, _whatFunction, _signerC)));} 53 | //============================================================================== 54 | // _| _ _|_ _ _ _ _|_ _ . 55 | // (_|(_| | (_| _\(/_ | |_||_) . 56 | //=============================|================================================ 57 | uint256 public registrationFee_ = 10 finney; // price to register a name 58 | mapping(uint256 => PlayerBookReceiverInterface) public games_; // mapping of our game interfaces for sending your account info to games 59 | mapping(address => bytes32) public gameNames_; // lookup a games name 60 | mapping(address => uint256) public gameIDs_; // lokup a games ID 61 | uint256 public gID_; // total number of games 62 | uint256 public pID_; // total number of players 63 | mapping (address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address 64 | mapping (bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name 65 | mapping (uint256 => Player) public plyr_; // (pID => data) player data 66 | mapping (uint256 => mapping (bytes32 => bool)) public plyrNames_; // (pID => name => bool) list of names a player owns. (used so you can change your display name amoungst any name you own) 67 | mapping (uint256 => mapping (uint256 => bytes32)) public plyrNameList_; // (pID => nameNum => name) list of names a player owns 68 | struct Player { 69 | address addr; 70 | bytes32 name; 71 | uint256 laff; 72 | uint256 names; 73 | } 74 | //============================================================================== 75 | // _ _ _ __|_ _ __|_ _ _ . 76 | // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) 77 | //============================================================================== 78 | constructor() 79 | public 80 | { 81 | // premine the dev names (sorry not sorry) 82 | // No keys are purchased with this method, it's simply locking our addresses, 83 | // PID's and names for referral codes. 84 | plyr_[1].addr = 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53; 85 | plyr_[1].name = "justo"; 86 | plyr_[1].names = 1; 87 | pIDxAddr_[0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53] = 1; 88 | pIDxName_["justo"] = 1; 89 | plyrNames_[1]["justo"] = true; 90 | plyrNameList_[1][1] = "justo"; 91 | 92 | plyr_[2].addr = 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D; 93 | plyr_[2].name = "mantso"; 94 | plyr_[2].names = 1; 95 | pIDxAddr_[0x8b4DA1827932D71759687f925D17F81Fc94e3A9D] = 2; 96 | pIDxName_["mantso"] = 2; 97 | plyrNames_[2]["mantso"] = true; 98 | plyrNameList_[2][1] = "mantso"; 99 | 100 | plyr_[3].addr = 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C; 101 | plyr_[3].name = "sumpunk"; 102 | plyr_[3].names = 1; 103 | pIDxAddr_[0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C] = 3; 104 | pIDxName_["sumpunk"] = 3; 105 | plyrNames_[3]["sumpunk"] = true; 106 | plyrNameList_[3][1] = "sumpunk"; 107 | 108 | plyr_[4].addr = 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C; 109 | plyr_[4].name = "inventor"; 110 | plyr_[4].names = 1; 111 | pIDxAddr_[0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C] = 4; 112 | pIDxName_["inventor"] = 4; 113 | plyrNames_[4]["inventor"] = true; 114 | plyrNameList_[4][1] = "inventor"; 115 | 116 | pID_ = 4; 117 | } 118 | //============================================================================== 119 | // _ _ _ _|. |`. _ _ _ . 120 | // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) 121 | //============================================================================== 122 | /** 123 | * @dev prevents contracts from interacting with fomo3d 124 | */ 125 | modifier isHuman() { 126 | address _addr = msg.sender; 127 | uint256 _codeLength; 128 | 129 | assembly {_codeLength := extcodesize(_addr)} 130 | require(_codeLength == 0, "sorry humans only"); 131 | _; 132 | } 133 | 134 | modifier onlyDevs() 135 | { 136 | require(TeamJust.isDev(msg.sender) == true, "msg sender is not a dev"); 137 | _; 138 | } 139 | 140 | modifier isRegisteredGame() 141 | { 142 | require(gameIDs_[msg.sender] != 0); 143 | _; 144 | } 145 | //============================================================================== 146 | // _ _ _ _|_ _ . 147 | // (/_\/(/_| | | _\ . 148 | //============================================================================== 149 | // fired whenever a player registers a name 150 | event onNewName 151 | ( 152 | uint256 indexed playerID, 153 | address indexed playerAddress, 154 | bytes32 indexed playerName, 155 | bool isNewPlayer, 156 | uint256 affiliateID, 157 | address affiliateAddress, 158 | bytes32 affiliateName, 159 | uint256 amountPaid, 160 | uint256 timeStamp 161 | ); 162 | //============================================================================== 163 | // _ _ _|__|_ _ _ _ . 164 | // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) 165 | //=====_|======================================================================= 166 | function checkIfNameValid(string _nameStr) 167 | public 168 | view 169 | returns(bool) 170 | { 171 | bytes32 _name = _nameStr.nameFilter(); 172 | if (pIDxName_[_name] == 0) 173 | return (true); 174 | else 175 | return (false); 176 | } 177 | //============================================================================== 178 | // _ |_ |. _ |` _ __|_. _ _ _ . 179 | // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) 180 | //====|========================================================================= 181 | /** 182 | * @dev registers a name. UI will always display the last name you registered. 183 | * but you will still own all previously registered names to use as affiliate 184 | * links. 185 | * - must pay a registration fee. 186 | * - name must be unique 187 | * - names will be converted to lowercase 188 | * - name cannot start or end with a space 189 | * - cannot have more than 1 space in a row 190 | * - cannot be only numbers 191 | * - cannot start with 0x 192 | * - name must be at least 1 char 193 | * - max length of 32 characters long 194 | * - allowed characters: a-z, 0-9, and space 195 | * -functionhash- 0x921dec21 (using ID for affiliate) 196 | * -functionhash- 0x3ddd4698 (using address for affiliate) 197 | * -functionhash- 0x685ffd83 (using name for affiliate) 198 | * @param _nameString players desired name 199 | * @param _affCode affiliate ID, address, or name of who refered you 200 | * @param _all set to true if you want this to push your info to all games 201 | * (this might cost a lot of gas) 202 | */ 203 | function registerNameXID(string _nameString, uint256 _affCode, bool _all) 204 | isHuman() 205 | public 206 | payable 207 | { 208 | // make sure name fees paid 209 | require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); 210 | 211 | // filter name + condition checks 212 | bytes32 _name = NameFilter.nameFilter(_nameString); 213 | 214 | // set up address 215 | address _addr = msg.sender; 216 | 217 | // set up our tx event data and determine if player is new or not 218 | bool _isNewPlayer = determinePID(_addr); 219 | 220 | // fetch player id 221 | uint256 _pID = pIDxAddr_[_addr]; 222 | 223 | // manage affiliate residuals 224 | // if no affiliate code was given, no new affiliate code was given, or the 225 | // player tried to use their own pID as an affiliate code, lolz 226 | if (_affCode != 0 && _affCode != plyr_[_pID].laff && _affCode != _pID) 227 | { 228 | // update last affiliate 229 | plyr_[_pID].laff = _affCode; 230 | } else if (_affCode == _pID) { 231 | _affCode = 0; 232 | } 233 | 234 | // register name 235 | registerNameCore(_pID, _addr, _affCode, _name, _isNewPlayer, _all); 236 | } 237 | 238 | function registerNameXaddr(string _nameString, address _affCode, bool _all) 239 | isHuman() 240 | public 241 | payable 242 | { 243 | // make sure name fees paid 244 | require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); 245 | 246 | // filter name + condition checks 247 | bytes32 _name = NameFilter.nameFilter(_nameString); 248 | 249 | // set up address 250 | address _addr = msg.sender; 251 | 252 | // set up our tx event data and determine if player is new or not 253 | bool _isNewPlayer = determinePID(_addr); 254 | 255 | // fetch player id 256 | uint256 _pID = pIDxAddr_[_addr]; 257 | 258 | // manage affiliate residuals 259 | // if no affiliate code was given or player tried to use their own, lolz 260 | uint256 _affID; 261 | if (_affCode != address(0) && _affCode != _addr) 262 | { 263 | // get affiliate ID from aff Code 264 | _affID = pIDxAddr_[_affCode]; 265 | 266 | // if affID is not the same as previously stored 267 | if (_affID != plyr_[_pID].laff) 268 | { 269 | // update last affiliate 270 | plyr_[_pID].laff = _affID; 271 | } 272 | } 273 | 274 | // register name 275 | registerNameCore(_pID, _addr, _affID, _name, _isNewPlayer, _all); 276 | } 277 | 278 | function registerNameXname(string _nameString, bytes32 _affCode, bool _all) 279 | isHuman() 280 | public 281 | payable 282 | { 283 | // make sure name fees paid 284 | require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); 285 | 286 | // filter name + condition checks 287 | bytes32 _name = NameFilter.nameFilter(_nameString); 288 | 289 | // set up address 290 | address _addr = msg.sender; 291 | 292 | // set up our tx event data and determine if player is new or not 293 | bool _isNewPlayer = determinePID(_addr); 294 | 295 | // fetch player id 296 | uint256 _pID = pIDxAddr_[_addr]; 297 | 298 | // manage affiliate residuals 299 | // if no affiliate code was given or player tried to use their own, lolz 300 | uint256 _affID; 301 | if (_affCode != "" && _affCode != _name) 302 | { 303 | // get affiliate ID from aff Code 304 | _affID = pIDxName_[_affCode]; 305 | 306 | // if affID is not the same as previously stored 307 | if (_affID != plyr_[_pID].laff) 308 | { 309 | // update last affiliate 310 | plyr_[_pID].laff = _affID; 311 | } 312 | } 313 | 314 | // register name 315 | registerNameCore(_pID, _addr, _affID, _name, _isNewPlayer, _all); 316 | } 317 | 318 | /** 319 | * @dev players, if you registered a profile, before a game was released, or 320 | * set the all bool to false when you registered, use this function to push 321 | * your profile to a single game. also, if you've updated your name, you 322 | * can use this to push your name to games of your choosing. 323 | * -functionhash- 0x81c5b206 324 | * @param _gameID game id 325 | */ 326 | function addMeToGame(uint256 _gameID) 327 | isHuman() 328 | public 329 | { 330 | require(_gameID <= gID_, "silly player, that game doesn't exist yet"); 331 | address _addr = msg.sender; 332 | uint256 _pID = pIDxAddr_[_addr]; 333 | require(_pID != 0, "hey there buddy, you dont even have an account"); 334 | uint256 _totalNames = plyr_[_pID].names; 335 | 336 | // add players profile and most recent name 337 | games_[_gameID].receivePlayerInfo(_pID, _addr, plyr_[_pID].name, plyr_[_pID].laff); 338 | 339 | // add list of all names 340 | if (_totalNames > 1) 341 | for (uint256 ii = 1; ii <= _totalNames; ii++) 342 | games_[_gameID].receivePlayerNameList(_pID, plyrNameList_[_pID][ii]); 343 | } 344 | 345 | /** 346 | * @dev players, use this to push your player profile to all registered games. 347 | * -functionhash- 0x0c6940ea 348 | */ 349 | function addMeToAllGames() 350 | isHuman() 351 | public 352 | { 353 | address _addr = msg.sender; 354 | uint256 _pID = pIDxAddr_[_addr]; 355 | require(_pID != 0, "hey there buddy, you dont even have an account"); 356 | uint256 _laff = plyr_[_pID].laff; 357 | uint256 _totalNames = plyr_[_pID].names; 358 | bytes32 _name = plyr_[_pID].name; 359 | 360 | for (uint256 i = 1; i <= gID_; i++) 361 | { 362 | games_[i].receivePlayerInfo(_pID, _addr, _name, _laff); 363 | if (_totalNames > 1) 364 | for (uint256 ii = 1; ii <= _totalNames; ii++) 365 | games_[i].receivePlayerNameList(_pID, plyrNameList_[_pID][ii]); 366 | } 367 | 368 | } 369 | 370 | /** 371 | * @dev players use this to change back to one of your old names. tip, you'll 372 | * still need to push that info to existing games. 373 | * -functionhash- 0xb9291296 374 | * @param _nameString the name you want to use 375 | */ 376 | function useMyOldName(string _nameString) 377 | isHuman() 378 | public 379 | { 380 | // filter name, and get pID 381 | bytes32 _name = _nameString.nameFilter(); 382 | uint256 _pID = pIDxAddr_[msg.sender]; 383 | 384 | // make sure they own the name 385 | require(plyrNames_[_pID][_name] == true, "umm... thats not a name you own"); 386 | 387 | // update their current name 388 | plyr_[_pID].name = _name; 389 | } 390 | 391 | //============================================================================== 392 | // _ _ _ _ | _ _ . _ . 393 | // (_(_)| (/_ |(_)(_||(_ . 394 | //=====================_|======================================================= 395 | function registerNameCore(uint256 _pID, address _addr, uint256 _affID, bytes32 _name, bool _isNewPlayer, bool _all) 396 | private 397 | { 398 | // if names already has been used, require that current msg sender owns the name 399 | if (pIDxName_[_name] != 0) 400 | require(plyrNames_[_pID][_name] == true, "sorry that names already taken"); 401 | 402 | // add name to player profile, registry, and name book 403 | plyr_[_pID].name = _name; 404 | pIDxName_[_name] = _pID; 405 | if (plyrNames_[_pID][_name] == false) 406 | { 407 | plyrNames_[_pID][_name] = true; 408 | plyr_[_pID].names++; 409 | plyrNameList_[_pID][plyr_[_pID].names] = _name; 410 | } 411 | 412 | // registration fee goes directly to community rewards 413 | Jekyll_Island_Inc.deposit.value(address(this).balance)(); 414 | 415 | // push player info to games 416 | if (_all == true) 417 | for (uint256 i = 1; i <= gID_; i++) 418 | games_[i].receivePlayerInfo(_pID, _addr, _name, _affID); 419 | 420 | // fire event 421 | emit onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, msg.value, now); 422 | } 423 | //============================================================================== 424 | // _|_ _ _ | _ . 425 | // | (_)(_)|_\ . 426 | //============================================================================== 427 | function determinePID(address _addr) 428 | private 429 | returns (bool) 430 | { 431 | if (pIDxAddr_[_addr] == 0) 432 | { 433 | pID_++; 434 | pIDxAddr_[_addr] = pID_; 435 | plyr_[pID_].addr = _addr; 436 | 437 | // set the new player bool to true 438 | return (true); 439 | } else { 440 | return (false); 441 | } 442 | } 443 | //============================================================================== 444 | // _ _|_ _ _ _ _ | _ _ || _ . 445 | // (/_>< | (/_| | |(_|| (_(_|||_\ . 446 | //============================================================================== 447 | function getPlayerID(address _addr) 448 | isRegisteredGame() 449 | external 450 | returns (uint256) 451 | { 452 | determinePID(_addr); 453 | return (pIDxAddr_[_addr]); 454 | } 455 | function getPlayerName(uint256 _pID) 456 | external 457 | view 458 | returns (bytes32) 459 | { 460 | return (plyr_[_pID].name); 461 | } 462 | function getPlayerLAff(uint256 _pID) 463 | external 464 | view 465 | returns (uint256) 466 | { 467 | return (plyr_[_pID].laff); 468 | } 469 | function getPlayerAddr(uint256 _pID) 470 | external 471 | view 472 | returns (address) 473 | { 474 | return (plyr_[_pID].addr); 475 | } 476 | function getNameFee() 477 | external 478 | view 479 | returns (uint256) 480 | { 481 | return(registrationFee_); 482 | } 483 | function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) 484 | isRegisteredGame() 485 | external 486 | payable 487 | returns(bool, uint256) 488 | { 489 | // make sure name fees paid 490 | require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); 491 | 492 | // set up our tx event data and determine if player is new or not 493 | bool _isNewPlayer = determinePID(_addr); 494 | 495 | // fetch player id 496 | uint256 _pID = pIDxAddr_[_addr]; 497 | 498 | // manage affiliate residuals 499 | // if no affiliate code was given, no new affiliate code was given, or the 500 | // player tried to use their own pID as an affiliate code, lolz 501 | uint256 _affID = _affCode; 502 | if (_affID != 0 && _affID != plyr_[_pID].laff && _affID != _pID) 503 | { 504 | // update last affiliate 505 | plyr_[_pID].laff = _affID; 506 | } else if (_affID == _pID) { 507 | _affID = 0; 508 | } 509 | 510 | // register name 511 | registerNameCore(_pID, _addr, _affID, _name, _isNewPlayer, _all); 512 | 513 | return(_isNewPlayer, _affID); 514 | } 515 | function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) 516 | isRegisteredGame() 517 | external 518 | payable 519 | returns(bool, uint256) 520 | { 521 | // make sure name fees paid 522 | require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); 523 | 524 | // set up our tx event data and determine if player is new or not 525 | bool _isNewPlayer = determinePID(_addr); 526 | 527 | // fetch player id 528 | uint256 _pID = pIDxAddr_[_addr]; 529 | 530 | // manage affiliate residuals 531 | // if no affiliate code was given or player tried to use their own, lolz 532 | uint256 _affID; 533 | if (_affCode != address(0) && _affCode != _addr) 534 | { 535 | // get affiliate ID from aff Code 536 | _affID = pIDxAddr_[_affCode]; 537 | 538 | // if affID is not the same as previously stored 539 | if (_affID != plyr_[_pID].laff) 540 | { 541 | // update last affiliate 542 | plyr_[_pID].laff = _affID; 543 | } 544 | } 545 | 546 | // register name 547 | registerNameCore(_pID, _addr, _affID, _name, _isNewPlayer, _all); 548 | 549 | return(_isNewPlayer, _affID); 550 | } 551 | function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) 552 | isRegisteredGame() 553 | external 554 | payable 555 | returns(bool, uint256) 556 | { 557 | // make sure name fees paid 558 | require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); 559 | 560 | // set up our tx event data and determine if player is new or not 561 | bool _isNewPlayer = determinePID(_addr); 562 | 563 | // fetch player id 564 | uint256 _pID = pIDxAddr_[_addr]; 565 | 566 | // manage affiliate residuals 567 | // if no affiliate code was given or player tried to use their own, lolz 568 | uint256 _affID; 569 | if (_affCode != "" && _affCode != _name) 570 | { 571 | // get affiliate ID from aff Code 572 | _affID = pIDxName_[_affCode]; 573 | 574 | // if affID is not the same as previously stored 575 | if (_affID != plyr_[_pID].laff) 576 | { 577 | // update last affiliate 578 | plyr_[_pID].laff = _affID; 579 | } 580 | } 581 | 582 | // register name 583 | registerNameCore(_pID, _addr, _affID, _name, _isNewPlayer, _all); 584 | 585 | return(_isNewPlayer, _affID); 586 | } 587 | 588 | //============================================================================== 589 | // _ _ _|_ _ . 590 | // _\(/_ | |_||_) . 591 | //=============|================================================================ 592 | function addGame(address _gameAddress, string _gameNameStr) 593 | onlyDevs() 594 | public 595 | { 596 | require(gameIDs_[_gameAddress] == 0, "derp, that games already been registered"); 597 | 598 | if (multiSigDev("addGame") == true) 599 | {deleteProposal("addGame"); 600 | gID_++; 601 | bytes32 _name = _gameNameStr.nameFilter(); 602 | gameIDs_[_gameAddress] = gID_; 603 | gameNames_[_gameAddress] = _name; 604 | games_[gID_] = PlayerBookReceiverInterface(_gameAddress); 605 | 606 | games_[gID_].receivePlayerInfo(1, plyr_[1].addr, plyr_[1].name, 0); 607 | games_[gID_].receivePlayerInfo(2, plyr_[2].addr, plyr_[2].name, 0); 608 | games_[gID_].receivePlayerInfo(3, plyr_[3].addr, plyr_[3].name, 0); 609 | games_[gID_].receivePlayerInfo(4, plyr_[4].addr, plyr_[4].name, 0); 610 | } 611 | } 612 | 613 | function setRegistrationFee(uint256 _fee) 614 | onlyDevs() 615 | public 616 | { 617 | if (multiSigDev("setRegistrationFee") == true) 618 | {deleteProposal("setRegistrationFee"); 619 | registrationFee_ = _fee; 620 | } 621 | } 622 | 623 | } -------------------------------------------------------------------------------- /contracts/Hourglass.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | /* 5 | * Team JUST presents.. 6 | * ====================================* 7 | * _____ _ _ _ _____ ___ ____ * 8 | *| _ |___| | | | | | |_ | \ * 9 | *| __| . | | | | | |_ | | | * 10 | *|__| |___|_____|__|__| |___|____/ * 11 | * * 12 | * ====================================* 13 | * -> What? 14 | * The original autonomous pyramid, improved: 15 | * [x] More stable than ever, having withstood severe testnet abuse and attack attempts from our community!. 16 | * [x] Audited, tested, and approved by known community security specialists such as tocsick and Arc. 17 | * [X] New functionality; you can now perform partial sell orders. If you succumb to weak hands, you don't have to dump all of your bags! 18 | * [x] New functionality; you can now transfer tokens between wallets. Trading is now possible from within the contract! 19 | * [x] New Feature: PoS Masternodes! The first implementation of Ethereum Staking in the world! Vitalik is mad. 20 | * [x] Masternodes: Holding 100 PoWH3D Tokens allow you to generate a Masternode link, Masternode links are used as unique entry points to the contract! 21 | * [x] Masternodes: All players who enter the contract through your Masternode have 30% of their 10% dividends fee rerouted from the master-node, to the node-master! 22 | * 23 | * -> What about the last projects? 24 | * Every programming member of the old dev team has been fired and/or killed by 232. 25 | * The new dev team consists of seasoned, professional developers and has been audited by veteran solidity experts. 26 | * Additionally, two independent testnet iterations have been used by hundreds of people; not a single point of failure was found. 27 | * 28 | * -> Who worked on this project? 29 | * - PonziBot (math/memes/main site/master) 30 | * - Mantso (lead solidity dev/lead web3 dev) 31 | * - swagg (concept design/feedback/management) 32 | * - Anonymous#1 (main site/web3/test cases) 33 | * - Anonymous#2 (math formulae/whitepaper) 34 | * 35 | * -> Who has audited & approved the projected: 36 | * - Arc 37 | * - tocisck 38 | * - sumpunk 39 | */ 40 | import "./library/SafeMath.sol"; 41 | 42 | contract Hourglass { 43 | /*================================= 44 | = MODIFIERS = 45 | =================================*/ 46 | // only people with tokens 47 | modifier onlyBagholders() { 48 | require(myTokens() > 0); 49 | _; 50 | } 51 | 52 | // only people with profits 53 | modifier onlyStronghands() { 54 | require(myDividends(true) > 0); 55 | _; 56 | } 57 | 58 | // administrators can: 59 | // -> change the name of the contract 60 | // -> change the name of the token 61 | // -> change the PoS difficulty (How many tokens it costs to hold a masternode, in case it gets crazy high later) 62 | // they CANNOT: 63 | // -> take funds 64 | // -> disable withdrawals 65 | // -> kill the contract 66 | // -> change the price of tokens 67 | modifier onlyAdministrator(){ 68 | address _customerAddress = msg.sender; 69 | require(administrators[keccak256(_customerAddress)]); 70 | _; 71 | } 72 | 73 | 74 | // ensures that the first tokens in the contract will be equally distributed 75 | // meaning, no divine dump will be ever possible 76 | // result: healthy longevity. 77 | modifier antiEarlyWhale(uint256 _amountOfEthereum){ 78 | address _customerAddress = msg.sender; 79 | 80 | // are we still in the vulnerable phase? 81 | // if so, enact anti early whale protocol 82 | if( onlyAmbassadors && ((totalEthereumBalance() - _amountOfEthereum) <= ambassadorQuota_ )){ 83 | require( 84 | // is the customer in the ambassador list? 85 | ambassadors_[_customerAddress] == true && 86 | 87 | // does the customer purchase exceed the max ambassador quota? 88 | (ambassadorAccumulatedQuota_[_customerAddress] + _amountOfEthereum) <= ambassadorMaxPurchase_ 89 | 90 | ); 91 | 92 | // updated the accumulated quota 93 | ambassadorAccumulatedQuota_[_customerAddress] = SafeMath.add(ambassadorAccumulatedQuota_[_customerAddress], _amountOfEthereum); 94 | 95 | // execute 96 | _; 97 | } else { 98 | // in case the ether count drops low, the ambassador phase won't reinitiate 99 | onlyAmbassadors = false; 100 | _; 101 | } 102 | 103 | } 104 | 105 | 106 | /*============================== 107 | = EVENTS = 108 | ==============================*/ 109 | event onTokenPurchase( 110 | address indexed customerAddress, 111 | uint256 incomingEthereum, 112 | uint256 tokensMinted, 113 | address indexed referredBy 114 | ); 115 | 116 | event onTokenSell( 117 | address indexed customerAddress, 118 | uint256 tokensBurned, 119 | uint256 ethereumEarned 120 | ); 121 | 122 | event onReinvestment( 123 | address indexed customerAddress, 124 | uint256 ethereumReinvested, 125 | uint256 tokensMinted 126 | ); 127 | 128 | event onWithdraw( 129 | address indexed customerAddress, 130 | uint256 ethereumWithdrawn 131 | ); 132 | 133 | // ERC20 134 | event Transfer( 135 | address indexed from, 136 | address indexed to, 137 | uint256 tokens 138 | ); 139 | 140 | 141 | /*===================================== 142 | = CONFIGURABLES = 143 | =====================================*/ 144 | string public name = "PowH3D"; 145 | string public symbol = "P3D"; 146 | uint8 constant public decimals = 18; 147 | uint8 constant internal dividendFee_ = 10; 148 | uint256 constant internal tokenPriceInitial_ = 0.0000001 ether; 149 | uint256 constant internal tokenPriceIncremental_ = 0.00000001 ether; 150 | uint256 constant internal magnitude = 2**64; 151 | 152 | // proof of stake (defaults at 100 tokens) 153 | uint256 public stakingRequirement = 100e18; 154 | 155 | // ambassador program 156 | mapping(address => bool) internal ambassadors_; 157 | uint256 constant internal ambassadorMaxPurchase_ = 1 ether; 158 | uint256 constant internal ambassadorQuota_ = 20 ether; 159 | 160 | 161 | 162 | /*================================ 163 | = DATASETS = 164 | ================================*/ 165 | // amount of shares for each address (scaled number) 166 | mapping(address => uint256) internal tokenBalanceLedger_; 167 | mapping(address => uint256) internal referralBalance_; 168 | mapping(address => int256) internal payoutsTo_; 169 | mapping(address => uint256) internal ambassadorAccumulatedQuota_; 170 | uint256 internal tokenSupply_ = 0; 171 | uint256 internal profitPerShare_; 172 | 173 | // administrator list (see above on what they can do) 174 | mapping(bytes32 => bool) public administrators; 175 | 176 | // when this is set to true, only ambassadors can purchase tokens (this prevents a whale premine, it ensures a fairly distributed upper pyramid) 177 | bool public onlyAmbassadors = true; 178 | 179 | 180 | 181 | /*======================================= 182 | = PUBLIC FUNCTIONS = 183 | =======================================*/ 184 | /* 185 | * -- APPLICATION ENTRY POINTS -- 186 | */ 187 | function Hourglass() 188 | public 189 | { 190 | // add administrators here 191 | administrators[0xdd8bb99b13fe33e1c32254dfb8fff3e71193f6b730a89dd33bfe5dedc6d83002] = true; 192 | 193 | // add the ambassadors here. 194 | // mantso - lead solidity dev & lead web dev. 195 | ambassadors_[0x8b4DA1827932D71759687f925D17F81Fc94e3A9D] = true; 196 | 197 | // ponzibot - mathematics & website, and undisputed meme god. 198 | ambassadors_[0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53] = true; 199 | 200 | // swagg - concept design, feedback, management. 201 | ambassadors_[0x7563A35d5610eE7c9CD330E255Da0e779a644C19] = true; 202 | 203 | // k-dawgz - shilling machine, meme maestro, bizman. 204 | ambassadors_[0x215e3C713BADb158A457e61f99325bBB5d278E57] = true; 205 | 206 | // elmojo - all those pretty .GIFs & memes you see? you can thank this man for that. 207 | ambassadors_[0xaFF8B5CDCB339eEf5e1100597740a394C7B9c6cA] = true; 208 | 209 | // capex - community moderator. 210 | ambassadors_[0x8dc6569c28521560EAF1890bC41b2F3FC2010E1b] = true; 211 | 212 | // jörmungandr - pentests & twitter trendsetter. 213 | ambassadors_[0xf14BE3662FE4c9215c27698166759Db6967De94f] = true; 214 | 215 | // inventor - the source behind the non-intrusive referral model. 216 | ambassadors_[0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C] = true; 217 | 218 | // tocsick - pentesting, contract auditing. 219 | ambassadors_[0x49Aae4D923207e80Fc91E626BCb6532502264dfC] = true; 220 | 221 | // arc - pentesting, contract auditing. 222 | ambassadors_[0x3a0cca1A832644B60730E5D4c27947C5De609d62] = true; 223 | 224 | // sumpunk - contract auditing. 225 | ambassadors_[0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C] = true; 226 | 227 | // randall - charts & sheets, data dissector, advisor. 228 | ambassadors_[0x2b219C2178f099dE4E9A3667d5cCc2cc64da0763] = true; 229 | 230 | // ambius - 3d chart visualization. 231 | ambassadors_[0x2A04C7335f90a6bd4e9c4F713DD792200e27F2E6] = true; 232 | 233 | // contributors that need to remain private out of security concerns. 234 | ambassadors_[0x35668818ba8F768D4C21787a6f45C86C69394dfD] = true; //dp 235 | ambassadors_[0xa3120da52e604aC3Fc80A63813Ef15476e0B6AbD] = true; //tc 236 | ambassadors_[0x924E71bA600372e2410285423F1Fe66799b717EC] = true; //ja 237 | ambassadors_[0x6Ed450e062C20F929CB7Ee72fCc53e9697980a18] = true; //sf 238 | ambassadors_[0x18864A6682c8EB79EEA5B899F11bC94ef9a85ADb] = true; //tb 239 | ambassadors_[0x9cC1BdC994b7a847705D19106287C0BF94EF04B5] = true; //sm 240 | ambassadors_[0x6926572813ec1438088963f208C61847df435a74] = true; //mc 241 | ambassadors_[0xE16Ab764a02Ae03681E351Ac58FE79717c0eE8C6] = true; //et 242 | ambassadors_[0x276F4a79F22D1BfC51Bd8dc5b27Bfd934C823932] = true; //sn 243 | ambassadors_[0xA2b4ed3E2f4beF09FB35101B76Ef4cB9D3eeCaCf] = true; //bt 244 | ambassadors_[0x147fc6b04c95BCE47D013c8d7a200ee434323669] = true; //al 245 | 246 | 247 | } 248 | 249 | 250 | /** 251 | * Converts all incoming ethereum to tokens for the caller, and passes down the referral addy (if any) 252 | */ 253 | function buy(address _referredBy) 254 | public 255 | payable 256 | returns(uint256) 257 | { 258 | purchaseTokens(msg.value, _referredBy); 259 | } 260 | 261 | /** 262 | * Fallback function to handle ethereum that was send straight to the contract 263 | * Unfortunately we cannot use a referral address this way. 264 | */ 265 | function() 266 | payable 267 | public 268 | { 269 | purchaseTokens(msg.value, 0x0); 270 | } 271 | 272 | /** 273 | * Converts all of caller's dividends to tokens. 274 | */ 275 | function reinvest() 276 | onlyStronghands() 277 | public 278 | { 279 | // fetch dividends 280 | uint256 _dividends = myDividends(false); // retrieve ref. bonus later in the code 281 | 282 | // pay out the dividends virtually 283 | address _customerAddress = msg.sender; 284 | payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); 285 | 286 | // retrieve ref. bonus 287 | _dividends += referralBalance_[_customerAddress]; 288 | referralBalance_[_customerAddress] = 0; 289 | 290 | // dispatch a buy order with the virtualized "withdrawn dividends" 291 | uint256 _tokens = purchaseTokens(_dividends, 0x0); 292 | 293 | // fire event 294 | onReinvestment(_customerAddress, _dividends, _tokens); 295 | } 296 | 297 | /** 298 | * Alias of sell() and withdraw(). 299 | */ 300 | function exit() 301 | public 302 | { 303 | // get token count for caller & sell them all 304 | address _customerAddress = msg.sender; 305 | uint256 _tokens = tokenBalanceLedger_[_customerAddress]; 306 | if(_tokens > 0) sell(_tokens); 307 | 308 | // lambo delivery service 309 | withdraw(); 310 | } 311 | 312 | /** 313 | * Withdraws all of the callers earnings. 314 | */ 315 | function withdraw() 316 | onlyStronghands() 317 | public 318 | { 319 | // setup data 320 | address _customerAddress = msg.sender; 321 | uint256 _dividends = myDividends(false); // get ref. bonus later in the code 322 | 323 | // update dividend tracker 324 | payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); 325 | 326 | // add ref. bonus 327 | _dividends += referralBalance_[_customerAddress]; 328 | referralBalance_[_customerAddress] = 0; 329 | 330 | // lambo delivery service 331 | _customerAddress.transfer(_dividends); 332 | 333 | // fire event 334 | onWithdraw(_customerAddress, _dividends); 335 | } 336 | 337 | /** 338 | * Liquifies tokens to ethereum. 339 | */ 340 | function sell(uint256 _amountOfTokens) 341 | onlyBagholders() 342 | public 343 | { 344 | // setup data 345 | address _customerAddress = msg.sender; 346 | // russian hackers BTFO 347 | require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); 348 | uint256 _tokens = _amountOfTokens; 349 | uint256 _ethereum = tokensToEthereum_(_tokens); 350 | uint256 _dividends = SafeMath.div(_ethereum, dividendFee_); 351 | uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); 352 | 353 | // burn the sold tokens 354 | tokenSupply_ = SafeMath.sub(tokenSupply_, _tokens); 355 | tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _tokens); 356 | 357 | // update dividends tracker 358 | int256 _updatedPayouts = (int256) (profitPerShare_ * _tokens + (_taxedEthereum * magnitude)); 359 | payoutsTo_[_customerAddress] -= _updatedPayouts; 360 | 361 | // dividing by zero is a bad idea 362 | if (tokenSupply_ > 0) { 363 | // update the amount of dividends per token 364 | profitPerShare_ = SafeMath.add(profitPerShare_, (_dividends * magnitude) / tokenSupply_); 365 | } 366 | 367 | // fire event 368 | onTokenSell(_customerAddress, _tokens, _taxedEthereum); 369 | } 370 | 371 | 372 | /** 373 | * Transfer tokens from the caller to a new holder. 374 | * Remember, there's a 10% fee here as well. 375 | */ 376 | function transfer(address _toAddress, uint256 _amountOfTokens) 377 | onlyBagholders() 378 | public 379 | returns(bool) 380 | { 381 | // setup 382 | address _customerAddress = msg.sender; 383 | 384 | // make sure we have the requested tokens 385 | // also disables transfers until ambassador phase is over 386 | // ( we dont want whale premines ) 387 | require(!onlyAmbassadors && _amountOfTokens <= tokenBalanceLedger_[_customerAddress]); 388 | 389 | // withdraw all outstanding dividends first 390 | if(myDividends(true) > 0) withdraw(); 391 | 392 | // liquify 10% of the tokens that are transfered 393 | // these are dispersed to shareholders 394 | uint256 _tokenFee = SafeMath.div(_amountOfTokens, dividendFee_); 395 | uint256 _taxedTokens = SafeMath.sub(_amountOfTokens, _tokenFee); 396 | uint256 _dividends = tokensToEthereum_(_tokenFee); 397 | 398 | // burn the fee tokens 399 | tokenSupply_ = SafeMath.sub(tokenSupply_, _tokenFee); 400 | 401 | // exchange tokens 402 | tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); 403 | tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _taxedTokens); 404 | 405 | // update dividend trackers 406 | payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens); 407 | payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _taxedTokens); 408 | 409 | // disperse dividends among holders 410 | profitPerShare_ = SafeMath.add(profitPerShare_, (_dividends * magnitude) / tokenSupply_); 411 | 412 | // fire event 413 | Transfer(_customerAddress, _toAddress, _taxedTokens); 414 | 415 | // ERC20 416 | return true; 417 | 418 | } 419 | 420 | /*---------- ADMINISTRATOR ONLY FUNCTIONS ----------*/ 421 | /** 422 | * In case the amassador quota is not met, the administrator can manually disable the ambassador phase. 423 | */ 424 | function disableInitialStage() 425 | onlyAdministrator() 426 | public 427 | { 428 | onlyAmbassadors = false; 429 | } 430 | 431 | /** 432 | * In case one of us dies, we need to replace ourselves. 433 | */ 434 | function setAdministrator(bytes32 _identifier, bool _status) 435 | onlyAdministrator() 436 | public 437 | { 438 | administrators[_identifier] = _status; 439 | } 440 | 441 | /** 442 | * Precautionary measures in case we need to adjust the masternode rate. 443 | */ 444 | function setStakingRequirement(uint256 _amountOfTokens) 445 | onlyAdministrator() 446 | public 447 | { 448 | stakingRequirement = _amountOfTokens; 449 | } 450 | 451 | /** 452 | * If we want to rebrand, we can. 453 | */ 454 | function setName(string _name) 455 | onlyAdministrator() 456 | public 457 | { 458 | name = _name; 459 | } 460 | 461 | /** 462 | * If we want to rebrand, we can. 463 | */ 464 | function setSymbol(string _symbol) 465 | onlyAdministrator() 466 | public 467 | { 468 | symbol = _symbol; 469 | } 470 | 471 | 472 | /*---------- HELPERS AND CALCULATORS ----------*/ 473 | /** 474 | * Method to view the current Ethereum stored in the contract 475 | * Example: totalEthereumBalance() 476 | */ 477 | function totalEthereumBalance() 478 | public 479 | view 480 | returns(uint) 481 | { 482 | return this.balance; 483 | } 484 | 485 | /** 486 | * Retrieve the total token supply. 487 | */ 488 | function totalSupply() 489 | public 490 | view 491 | returns(uint256) 492 | { 493 | return tokenSupply_; 494 | } 495 | 496 | /** 497 | * Retrieve the tokens owned by the caller. 498 | */ 499 | function myTokens() 500 | public 501 | view 502 | returns(uint256) 503 | { 504 | address _customerAddress = msg.sender; 505 | return balanceOf(_customerAddress); 506 | } 507 | 508 | /** 509 | * Retrieve the dividends owned by the caller. 510 | * If `_includeReferralBonus` is to to 1/true, the referral bonus will be included in the calculations. 511 | * The reason for this, is that in the frontend, we will want to get the total divs (global + ref) 512 | * But in the internal calculations, we want them separate. 513 | */ 514 | function myDividends(bool _includeReferralBonus) 515 | public 516 | view 517 | returns(uint256) 518 | { 519 | address _customerAddress = msg.sender; 520 | return _includeReferralBonus ? dividendsOf(_customerAddress) + referralBalance_[_customerAddress] : dividendsOf(_customerAddress) ; 521 | } 522 | 523 | /** 524 | * Retrieve the token balance of any single address. 525 | */ 526 | function balanceOf(address _customerAddress) 527 | view 528 | public 529 | returns(uint256) 530 | { 531 | return tokenBalanceLedger_[_customerAddress]; 532 | } 533 | 534 | /** 535 | * Retrieve the dividend balance of any single address. 536 | */ 537 | function dividendsOf(address _customerAddress) 538 | view 539 | public 540 | returns(uint256) 541 | { 542 | return (uint256) ((int256)(profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude; 543 | } 544 | 545 | /** 546 | * Return the buy price of 1 individual token. 547 | */ 548 | function sellPrice() 549 | public 550 | view 551 | returns(uint256) 552 | { 553 | // our calculation relies on the token supply, so we need supply. Doh. 554 | if(tokenSupply_ == 0){ 555 | return tokenPriceInitial_ - tokenPriceIncremental_; 556 | } else { 557 | uint256 _ethereum = tokensToEthereum_(1e18); 558 | uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); 559 | uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); 560 | return _taxedEthereum; 561 | } 562 | } 563 | 564 | /** 565 | * Return the sell price of 1 individual token. 566 | */ 567 | function buyPrice() 568 | public 569 | view 570 | returns(uint256) 571 | { 572 | // our calculation relies on the token supply, so we need supply. Doh. 573 | if(tokenSupply_ == 0){ 574 | return tokenPriceInitial_ + tokenPriceIncremental_; 575 | } else { 576 | uint256 _ethereum = tokensToEthereum_(1e18); 577 | uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); 578 | uint256 _taxedEthereum = SafeMath.add(_ethereum, _dividends); 579 | return _taxedEthereum; 580 | } 581 | } 582 | 583 | /** 584 | * Function for the frontend to dynamically retrieve the price scaling of buy orders. 585 | */ 586 | function calculateTokensReceived(uint256 _ethereumToSpend) 587 | public 588 | view 589 | returns(uint256) 590 | { 591 | uint256 _dividends = SafeMath.div(_ethereumToSpend, dividendFee_); 592 | uint256 _taxedEthereum = SafeMath.sub(_ethereumToSpend, _dividends); 593 | uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); 594 | 595 | return _amountOfTokens; 596 | } 597 | 598 | /** 599 | * Function for the frontend to dynamically retrieve the price scaling of sell orders. 600 | */ 601 | function calculateEthereumReceived(uint256 _tokensToSell) 602 | public 603 | view 604 | returns(uint256) 605 | { 606 | require(_tokensToSell <= tokenSupply_); 607 | uint256 _ethereum = tokensToEthereum_(_tokensToSell); 608 | uint256 _dividends = SafeMath.div(_ethereum, dividendFee_); 609 | uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); 610 | return _taxedEthereum; 611 | } 612 | 613 | 614 | /*========================================== 615 | = INTERNAL FUNCTIONS = 616 | ==========================================*/ 617 | function purchaseTokens(uint256 _incomingEthereum, address _referredBy) 618 | antiEarlyWhale(_incomingEthereum) 619 | internal 620 | returns(uint256) 621 | { 622 | // data setup 623 | address _customerAddress = msg.sender; 624 | uint256 _undividedDividends = SafeMath.div(_incomingEthereum, dividendFee_); 625 | uint256 _referralBonus = SafeMath.div(_undividedDividends, 3); 626 | uint256 _dividends = SafeMath.sub(_undividedDividends, _referralBonus); 627 | uint256 _taxedEthereum = SafeMath.sub(_incomingEthereum, _undividedDividends); 628 | uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); 629 | uint256 _fee = _dividends * magnitude; 630 | 631 | // no point in continuing execution if OP is a poorfag russian hacker 632 | // prevents overflow in the case that the pyramid somehow magically starts being used by everyone in the world 633 | // (or hackers) 634 | // and yes we know that the safemath function automatically rules out the "greater then" equasion. 635 | require(_amountOfTokens > 0 && (SafeMath.add(_amountOfTokens,tokenSupply_) > tokenSupply_)); 636 | 637 | // is the user referred by a masternode? 638 | if( 639 | // is this a referred purchase? 640 | _referredBy != 0x0000000000000000000000000000000000000000 && 641 | 642 | // no cheating! 643 | _referredBy != _customerAddress && 644 | 645 | // does the referrer have at least X whole tokens? 646 | // i.e is the referrer a godly chad masternode 647 | tokenBalanceLedger_[_referredBy] >= stakingRequirement 648 | ){ 649 | // wealth redistribution 650 | referralBalance_[_referredBy] = SafeMath.add(referralBalance_[_referredBy], _referralBonus); 651 | } else { 652 | // no ref purchase 653 | // add the referral bonus back to the global dividends cake 654 | _dividends = SafeMath.add(_dividends, _referralBonus); 655 | _fee = _dividends * magnitude; 656 | } 657 | 658 | // we can't give people infinite ethereum 659 | if(tokenSupply_ > 0){ 660 | 661 | // add tokens to the pool 662 | tokenSupply_ = SafeMath.add(tokenSupply_, _amountOfTokens); 663 | 664 | // take the amount of dividends gained through this transaction, and allocates them evenly to each shareholder 665 | profitPerShare_ += (_dividends * magnitude / (tokenSupply_)); 666 | 667 | // calculate the amount of tokens the customer receives over his purchase 668 | _fee = _fee - (_fee-(_amountOfTokens * (_dividends * magnitude / (tokenSupply_)))); 669 | 670 | } else { 671 | // add tokens to the pool 672 | tokenSupply_ = _amountOfTokens; 673 | } 674 | 675 | // update circulating supply & the ledger address for the customer 676 | tokenBalanceLedger_[_customerAddress] = SafeMath.add(tokenBalanceLedger_[_customerAddress], _amountOfTokens); 677 | 678 | // Tells the contract that the buyer doesn't deserve dividends for the tokens before they owned them; 679 | //really i know you think you do but you don't 680 | int256 _updatedPayouts = (int256) ((profitPerShare_ * _amountOfTokens) - _fee); 681 | payoutsTo_[_customerAddress] += _updatedPayouts; 682 | 683 | // fire event 684 | onTokenPurchase(_customerAddress, _incomingEthereum, _amountOfTokens, _referredBy); 685 | 686 | return _amountOfTokens; 687 | } 688 | 689 | /** 690 | * Calculate Token price based on an amount of incoming ethereum 691 | * It's an algorithm, hopefully we gave you the whitepaper with it in scientific notation; 692 | * Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code. 693 | */ 694 | function ethereumToTokens_(uint256 _ethereum) 695 | internal 696 | view 697 | returns(uint256) 698 | { 699 | uint256 _tokenPriceInitial = tokenPriceInitial_ * 1e18; 700 | uint256 _tokensReceived = 701 | ( 702 | ( 703 | // underflow attempts BTFO 704 | SafeMath.sub( 705 | (sqrt 706 | ( 707 | (_tokenPriceInitial**2) 708 | + 709 | (2*(tokenPriceIncremental_ * 1e18)*(_ethereum * 1e18)) 710 | + 711 | (((tokenPriceIncremental_)**2)*(tokenSupply_**2)) 712 | + 713 | (2*(tokenPriceIncremental_)*_tokenPriceInitial*tokenSupply_) 714 | ) 715 | ), _tokenPriceInitial 716 | ) 717 | )/(tokenPriceIncremental_) 718 | )-(tokenSupply_) 719 | ; 720 | 721 | return _tokensReceived; 722 | } 723 | 724 | /** 725 | * Calculate token sell value. 726 | * It's an algorithm, hopefully we gave you the whitepaper with it in scientific notation; 727 | * Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code. 728 | */ 729 | function tokensToEthereum_(uint256 _tokens) 730 | internal 731 | view 732 | returns(uint256) 733 | { 734 | 735 | uint256 tokens_ = (_tokens + 1e18); 736 | uint256 _tokenSupply = (tokenSupply_ + 1e18); 737 | uint256 _etherReceived = 738 | ( 739 | // underflow attempts BTFO 740 | SafeMath.sub( 741 | ( 742 | ( 743 | ( 744 | tokenPriceInitial_ +(tokenPriceIncremental_ * (_tokenSupply/1e18)) 745 | )-tokenPriceIncremental_ 746 | )*(tokens_ - 1e18) 747 | ),(tokenPriceIncremental_*((tokens_**2-tokens_)/1e18))/2 748 | ) 749 | /1e18); 750 | return _etherReceived; 751 | } 752 | 753 | 754 | //This is where all your gas goes, sorry 755 | //Not sorry, you probably only paid 1 gwei 756 | function sqrt(uint x) internal pure returns (uint y) { 757 | uint z = (x + 1) / 2; 758 | y = x; 759 | while (z < y) { 760 | y = z; 761 | z = (x / z + z) / 2; 762 | } 763 | } 764 | } 765 | -------------------------------------------------------------------------------- /contracts/FoMo3Dlong.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | /** 4 | * @title -FoMo-3D v0.7.1 5 | * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ 6 | * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ 7 | * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ 8 | * _____ _____ 9 | * (, / /) /) /) (, / /) /) 10 | * ┌─┐ / _ (/_ // // / _ // _ __ _(/ 11 | * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ 12 | * ┴ ┴ / / .-/ _____ (__ / 13 | * (__ / (_/ (, / /)™ 14 | * / __ __ __ __ _ __ __ _ _/_ _ _(/ 15 | * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ 16 | * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 17 | * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ .--,-``-. 18 | *========,---,.======================____==========================/ / '.=======,---,====* 19 | * ,' .' | ,' , `. / ../ ; .' .' `\ 20 | * ,---.' | ,---. ,-+-,.' _ | ,---. \ ``\ .`- ' ,---.' \ 21 | * | | .' ' ,'\ ,-+-. ; , || ' ,'\ ,---,. \___\/ \ : | | .`\ | 22 | * : : : / / | ,--.'|' | || / / | ,' .' | \ : | : : | ' | 23 | * : | |-, . ; ,. : | | ,', | |, . ; ,. : ,---.' | / / / | ' ' ; : 24 | * | : ;/| ' | |: : | | / | |--' ' | |: : | | .' \ \ \ ' | ; . | 25 | * | | .' ' | .; : | : | | , ' | .; : : |.' ___ / : | | | : | ' 26 | * ' : ' | : | | : | |/ | : | `---' / /\ / : ' : | / ; 27 | * | | | \ \ / | | |`-' \ \ / / ,,/ ',- . | | '` ,/ 28 | * | : \ `----' | ;/ `----' \ ''\ ; ; : .' 29 | *====| | ,'=============='---'==========(long version)===========\ \ .'===| ,.'======* 30 | * `----' `--`-,,-' '---' 31 | * ╔═╗┌─┐┌─┐┬┌─┐┬┌─┐┬ ┌─────────────────────────┐ ╦ ╦┌─┐┌┐ ╔═╗┬┌┬┐┌─┐ 32 | * ║ ║├┤ ├┤ ││ │├─┤│ │ https://exitscam.me │ ║║║├┤ ├┴┐╚═╗│ │ ├┤ 33 | * ╚═╝└ └ ┴└─┘┴┴ ┴┴─┘ └─┬─────────────────────┬─┘ ╚╩╝└─┘└─┘╚═╝┴ ┴ └─┘ 34 | * ┌────────────────────────────────┘ └──────────────────────────────┐ 35 | * │╔═╗┌─┐┬ ┬┌┬┐┬┌┬┐┬ ┬ ╔╦╗┌─┐┌─┐┬┌─┐┌┐┌ ╦┌┐┌┌┬┐┌─┐┬─┐┌─┐┌─┐┌─┐┌─┐ ╔═╗┌┬┐┌─┐┌─┐┬┌─│ 36 | * │╚═╗│ ││ │ │││ │ └┬┘ ═ ║║├┤ └─┐││ ┬│││ ═ ║│││ │ ├┤ ├┬┘├┤ ├─┤│ ├┤ ═ ╚═╗ │ ├─┤│ ├┴┐│ 37 | * │╚═╝└─┘┴─┘┴─┴┘┴ ┴ ┴ ═╩╝└─┘└─┘┴└─┘┘└┘ ╩┘└┘ ┴ └─┘┴└─└ ┴ ┴└─┘└─┘ ╚═╝ ┴ ┴ ┴└─┘┴ ┴│ 38 | * │ ┌──────────┐ ┌───────┐ ┌─────────┐ ┌────────┐ │ 39 | * └────┤ Inventor ├───────────┤ Justo ├────────────┤ Sumpunk ├──────────────┤ Mantso ├──┘ 40 | * └──────────┘ └───────┘ └─────────┘ └────────┘ 41 | * ┌─────────────────────────────────────────────────────────┐ ╔╦╗┬ ┬┌─┐┌┐┌┬┌─┌─┐ ╔╦╗┌─┐ 42 | * │ Ambius, Aritz Cracker, Cryptoknight, Crypto McPump, │ ║ ├─┤├─┤│││├┴┐└─┐ ║ │ │ 43 | * │ Capex, JogFera, The Shocker, Daok, Randazzz, PumpRabbi, │ ╩ ┴ ┴┴ ┴┘└┘┴ ┴└─┘ ╩ └─┘ 44 | * │ Kadaz, Incognito Jo, Lil Stronghands, Ninja Turtle, └───────────────────────────┐ 45 | * │ Psaints, Satoshi, Vitalik, Nano 2nd, Bogdanoffs Isaac Newton, Nikola Tesla, │ 46 | * │ Le Comte De Saint Germain, Albert Einstein, Socrates, & all the volunteer moderator │ 47 | * │ & support staff, content, creators, autonomous agents, and indie devs for P3D. │ 48 | * │ Without your help, we wouldn't have the time to code this. │ 49 | * └─────────────────────────────────────────────────────────────────────────────────────┘ 50 | * 51 | * This product is protected under license. Any unauthorized copy, modification, or use without 52 | * express written consent from the creators is prohibited. 53 | * 54 | * WARNING: THIS PRODUCT IS HIGHLY ADDICTIVE. IF YOU HAVE AN ADDICTIVE NATURE. DO NOT PLAY. 55 | */ 56 | 57 | //============================================================================== 58 | // _ _ _ _|_ _ . 59 | // (/_\/(/_| | | _\ . 60 | //============================================================================== 61 | 62 | import "./interface/DiviesInterface.sol"; 63 | import "./interface/otherFoMo3D.sol"; 64 | import "./interface/JIincForwarderInterface.sol"; 65 | import "./interface/PlayerBookInterface.sol"; 66 | import "./interface/F3DexternalSettingsInterface.sol"; 67 | import "./interface/HourglassInterface.sol"; 68 | 69 | import "./library/SafeMath.sol"; 70 | import "./library/UintCompressor.sol"; 71 | import "./library/NameFilter.sol"; 72 | import "./library/UintCompressor.sol"; 73 | import "./library/F3DKeysCalcLong.sol"; 74 | import "./library/F3Ddatasets.sol"; 75 | 76 | 77 | import "./modularLong.sol"; 78 | 79 | contract FoMo3Dlong is modularLong { 80 | using SafeMath for *; 81 | using NameFilter for string; 82 | using F3DKeysCalcLong for uint256; 83 | 84 | otherFoMo3D private otherF3D_; 85 | DiviesInterface constant private Divies = DiviesInterface(0xc7029Ed9EBa97A096e72607f4340c34049C7AF48); 86 | JIincForwarderInterface constant private Jekyll_Island_Inc = JIincForwarderInterface(0xdd4950F977EE28D2C132f1353D1595035Db444EE); 87 | PlayerBookInterface constant private PlayerBook = PlayerBookInterface(0xD60d353610D9a5Ca478769D371b53CEfAA7B6E4c); 88 | F3DexternalSettingsInterface constant private extSettings = F3DexternalSettingsInterface(0x32967D6c142c2F38AB39235994e2DDF11c37d590); 89 | //============================================================================== 90 | // _ _ _ |`. _ _ _ |_ | _ _ . 91 | // (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings) 92 | //=================_|=========================================================== 93 | string constant public name = "FoMo3D Long Official"; 94 | string constant public symbol = "F3D"; 95 | uint256 private rndExtra_ = extSettings.getLongExtra(); // length of the very first ICO 96 | uint256 private rndGap_ = extSettings.getLongGap(); // length of ICO phase, set to 1 year for EOS. 97 | uint256 constant private rndInit_ = 1 hours; // round timer starts at this 98 | uint256 constant private rndInc_ = 30 seconds; // every full key purchased adds this much to the timer 99 | uint256 constant private rndMax_ = 24 hours; // max length a round timer can be 100 | //============================================================================== 101 | // _| _ _|_ _ _ _ _|_ _ . 102 | // (_|(_| | (_| _\(/_ | |_||_) . (data used to store game info that changes) 103 | //=============================|================================================ 104 | uint256 public airDropPot_; // person who gets the airdrop wins part of this pot 105 | uint256 public airDropTracker_ = 0; // incremented each time a "qualified" tx occurs. used to determine winning air drop 106 | uint256 public rID_; // round id number / total rounds that have happened 107 | //**************** 108 | // PLAYER DATA 109 | //**************** 110 | mapping (address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address 111 | mapping (bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name 112 | mapping (uint256 => F3Ddatasets.Player) public plyr_; // (pID => data) player data 113 | mapping (uint256 => mapping (uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_; // (pID => rID => data) player round data by player id & round id 114 | mapping (uint256 => mapping (bytes32 => bool)) public plyrNames_; // (pID => name => bool) list of names a player owns. (used so you can change your display name amongst any name you own) 115 | //**************** 116 | // ROUND DATA 117 | //**************** 118 | mapping (uint256 => F3Ddatasets.Round) public round_; // (rID => data) round data 119 | mapping (uint256 => mapping(uint256 => uint256)) public rndTmEth_; // (rID => tID => data) eth in per team, by round id and team id 120 | //**************** 121 | // TEAM FEE DATA 122 | //**************** 123 | mapping (uint256 => F3Ddatasets.TeamFee) public fees_; // (team => fees) fee distribution by team 124 | mapping (uint256 => F3Ddatasets.PotSplit) public potSplit_; // (team => fees) pot split distribution by team 125 | //============================================================================== 126 | // _ _ _ __|_ _ __|_ _ _ . 127 | // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) 128 | //============================================================================== 129 | constructor() 130 | public 131 | { 132 | // Team allocation structures 133 | // 0 = whales 134 | // 1 = bears 135 | // 2 = sneks 136 | // 3 = bulls 137 | 138 | // Team allocation percentages 139 | // (F3D, P3D) + (Pot , Referrals, Community) 140 | // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot. 141 | fees_[0] = F3Ddatasets.TeamFee(30,6); //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot 142 | fees_[1] = F3Ddatasets.TeamFee(43,0); //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot 143 | fees_[2] = F3Ddatasets.TeamFee(56,10); //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot 144 | fees_[3] = F3Ddatasets.TeamFee(43,8); //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot 145 | 146 | // how to split up the final pot based on which team was picked 147 | // (F3D, P3D) 148 | potSplit_[0] = F3Ddatasets.PotSplit(15,10); //48% to winner, 25% to next round, 2% to com 149 | potSplit_[1] = F3Ddatasets.PotSplit(25,0); //48% to winner, 25% to next round, 2% to com 150 | potSplit_[2] = F3Ddatasets.PotSplit(20,20); //48% to winner, 10% to next round, 2% to com 151 | potSplit_[3] = F3Ddatasets.PotSplit(30,10); //48% to winner, 10% to next round, 2% to com 152 | } 153 | //============================================================================== 154 | // _ _ _ _|. |`. _ _ _ . 155 | // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) 156 | //============================================================================== 157 | /** 158 | * @dev used to make sure no one can interact with contract until it has 159 | * been activated. 160 | */ 161 | modifier isActivated() { 162 | require(activated_ == true, "its not ready yet. check ?eta in discord"); 163 | _; 164 | } 165 | 166 | /** 167 | * @dev prevents contracts from interacting with fomo3d 168 | */ 169 | modifier isHuman() { 170 | address _addr = msg.sender; 171 | uint256 _codeLength; 172 | 173 | assembly {_codeLength := extcodesize(_addr)} 174 | require(_codeLength == 0, "sorry humans only"); 175 | _; 176 | } 177 | 178 | /** 179 | * @dev sets boundaries for incoming tx 180 | */ 181 | modifier isWithinLimits(uint256 _eth) { 182 | require(_eth >= 1000000000, "pocket lint: not a valid currency"); 183 | require(_eth <= 100000000000000000000000, "no vitalik, no"); 184 | _; 185 | } 186 | 187 | //============================================================================== 188 | // _ |_ |. _ |` _ __|_. _ _ _ . 189 | // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) 190 | //====|========================================================================= 191 | /** 192 | * @dev emergency buy uses last stored affiliate ID and team snek 193 | */ 194 | function() 195 | isActivated() 196 | isHuman() 197 | isWithinLimits(msg.value) 198 | public 199 | payable 200 | { 201 | // set up our tx event data and determine if player is new or not 202 | F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); 203 | 204 | // fetch player id 205 | uint256 _pID = pIDxAddr_[msg.sender]; 206 | 207 | // buy core 208 | buyCore(_pID, plyr_[_pID].laff, 2, _eventData_); 209 | } 210 | 211 | /** 212 | * @dev converts all incoming ethereum to keys. 213 | * -functionhash- 0x8f38f309 (using ID for affiliate) 214 | * -functionhash- 0x98a0871d (using address for affiliate) 215 | * -functionhash- 0xa65b37a1 (using name for affiliate) 216 | * @param _affCode the ID/address/name of the player who gets the affiliate fee 217 | * @param _team what team is the player playing for? 218 | */ 219 | function buyXid(uint256 _affCode, uint256 _team) 220 | isActivated() 221 | isHuman() 222 | isWithinLimits(msg.value) 223 | public 224 | payable 225 | { 226 | // set up our tx event data and determine if player is new or not 227 | F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); 228 | 229 | // fetch player id 230 | uint256 _pID = pIDxAddr_[msg.sender]; 231 | 232 | // manage affiliate residuals 233 | // if no affiliate code was given or player tried to use their own, lolz 234 | if (_affCode == 0 || _affCode == _pID) 235 | { 236 | // use last stored affiliate code 237 | _affCode = plyr_[_pID].laff; 238 | 239 | // if affiliate code was given & its not the same as previously stored 240 | } else if (_affCode != plyr_[_pID].laff) { 241 | // update last affiliate 242 | plyr_[_pID].laff = _affCode; 243 | } 244 | 245 | // verify a valid team was selected 246 | _team = verifyTeam(_team); 247 | 248 | // buy core 249 | buyCore(_pID, _affCode, _team, _eventData_); 250 | } 251 | 252 | function buyXaddr(address _affCode, uint256 _team) 253 | isActivated() 254 | isHuman() 255 | isWithinLimits(msg.value) 256 | public 257 | payable 258 | { 259 | // set up our tx event data and determine if player is new or not 260 | F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); 261 | 262 | // fetch player id 263 | uint256 _pID = pIDxAddr_[msg.sender]; 264 | 265 | // manage affiliate residuals 266 | uint256 _affID; 267 | // if no affiliate code was given or player tried to use their own, lolz 268 | if (_affCode == address(0) || _affCode == msg.sender) 269 | { 270 | // use last stored affiliate code 271 | _affID = plyr_[_pID].laff; 272 | 273 | // if affiliate code was given 274 | } else { 275 | // get affiliate ID from aff Code 276 | _affID = pIDxAddr_[_affCode]; 277 | 278 | // if affID is not the same as previously stored 279 | if (_affID != plyr_[_pID].laff) 280 | { 281 | // update last affiliate 282 | plyr_[_pID].laff = _affID; 283 | } 284 | } 285 | 286 | // verify a valid team was selected 287 | _team = verifyTeam(_team); 288 | 289 | // buy core 290 | buyCore(_pID, _affID, _team, _eventData_); 291 | } 292 | 293 | function buyXname(bytes32 _affCode, uint256 _team) 294 | isActivated() 295 | isHuman() 296 | isWithinLimits(msg.value) 297 | public 298 | payable 299 | { 300 | // set up our tx event data and determine if player is new or not 301 | F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); 302 | 303 | // fetch player id 304 | uint256 _pID = pIDxAddr_[msg.sender]; 305 | 306 | // manage affiliate residuals 307 | uint256 _affID; 308 | // if no affiliate code was given or player tried to use their own, lolz 309 | if (_affCode == '' || _affCode == plyr_[_pID].name) 310 | { 311 | // use last stored affiliate code 312 | _affID = plyr_[_pID].laff; 313 | 314 | // if affiliate code was given 315 | } else { 316 | // get affiliate ID from aff Code 317 | _affID = pIDxName_[_affCode]; 318 | 319 | // if affID is not the same as previously stored 320 | if (_affID != plyr_[_pID].laff) 321 | { 322 | // update last affiliate 323 | plyr_[_pID].laff = _affID; 324 | } 325 | } 326 | 327 | // verify a valid team was selected 328 | _team = verifyTeam(_team); 329 | 330 | // buy core 331 | buyCore(_pID, _affID, _team, _eventData_); 332 | } 333 | 334 | /** 335 | * @dev essentially the same as buy, but instead of you sending ether 336 | * from your wallet, it uses your unwithdrawn earnings. 337 | * -functionhash- 0x349cdcac (using ID for affiliate) 338 | * -functionhash- 0x82bfc739 (using address for affiliate) 339 | * -functionhash- 0x079ce327 (using name for affiliate) 340 | * @param _affCode the ID/address/name of the player who gets the affiliate fee 341 | * @param _team what team is the player playing for? 342 | * @param _eth amount of earnings to use (remainder returned to gen vault) 343 | */ 344 | function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth) 345 | isActivated() 346 | isHuman() 347 | isWithinLimits(_eth) 348 | public 349 | { 350 | // set up our tx event data 351 | F3Ddatasets.EventReturns memory _eventData_; 352 | 353 | // fetch player ID 354 | uint256 _pID = pIDxAddr_[msg.sender]; 355 | 356 | // manage affiliate residuals 357 | // if no affiliate code was given or player tried to use their own, lolz 358 | if (_affCode == 0 || _affCode == _pID) 359 | { 360 | // use last stored affiliate code 361 | _affCode = plyr_[_pID].laff; 362 | 363 | // if affiliate code was given & its not the same as previously stored 364 | } else if (_affCode != plyr_[_pID].laff) { 365 | // update last affiliate 366 | plyr_[_pID].laff = _affCode; 367 | } 368 | 369 | // verify a valid team was selected 370 | _team = verifyTeam(_team); 371 | 372 | // reload core 373 | reLoadCore(_pID, _affCode, _team, _eth, _eventData_); 374 | } 375 | 376 | function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth) 377 | isActivated() 378 | isHuman() 379 | isWithinLimits(_eth) 380 | public 381 | { 382 | // set up our tx event data 383 | F3Ddatasets.EventReturns memory _eventData_; 384 | 385 | // fetch player ID 386 | uint256 _pID = pIDxAddr_[msg.sender]; 387 | 388 | // manage affiliate residuals 389 | uint256 _affID; 390 | // if no affiliate code was given or player tried to use their own, lolz 391 | if (_affCode == address(0) || _affCode == msg.sender) 392 | { 393 | // use last stored affiliate code 394 | _affID = plyr_[_pID].laff; 395 | 396 | // if affiliate code was given 397 | } else { 398 | // get affiliate ID from aff Code 399 | _affID = pIDxAddr_[_affCode]; 400 | 401 | // if affID is not the same as previously stored 402 | if (_affID != plyr_[_pID].laff) 403 | { 404 | // update last affiliate 405 | plyr_[_pID].laff = _affID; 406 | } 407 | } 408 | 409 | // verify a valid team was selected 410 | _team = verifyTeam(_team); 411 | 412 | // reload core 413 | reLoadCore(_pID, _affID, _team, _eth, _eventData_); 414 | } 415 | 416 | function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth) 417 | isActivated() 418 | isHuman() 419 | isWithinLimits(_eth) 420 | public 421 | { 422 | // set up our tx event data 423 | F3Ddatasets.EventReturns memory _eventData_; 424 | 425 | // fetch player ID 426 | uint256 _pID = pIDxAddr_[msg.sender]; 427 | 428 | // manage affiliate residuals 429 | uint256 _affID; 430 | // if no affiliate code was given or player tried to use their own, lolz 431 | if (_affCode == '' || _affCode == plyr_[_pID].name) 432 | { 433 | // use last stored affiliate code 434 | _affID = plyr_[_pID].laff; 435 | 436 | // if affiliate code was given 437 | } else { 438 | // get affiliate ID from aff Code 439 | _affID = pIDxName_[_affCode]; 440 | 441 | // if affID is not the same as previously stored 442 | if (_affID != plyr_[_pID].laff) 443 | { 444 | // update last affiliate 445 | plyr_[_pID].laff = _affID; 446 | } 447 | } 448 | 449 | // verify a valid team was selected 450 | _team = verifyTeam(_team); 451 | 452 | // reload core 453 | reLoadCore(_pID, _affID, _team, _eth, _eventData_); 454 | } 455 | 456 | /** 457 | * @dev withdraws all of your earnings. 458 | * -functionhash- 0x3ccfd60b 459 | */ 460 | function withdraw() 461 | isActivated() 462 | isHuman() 463 | public 464 | { 465 | // setup local rID 466 | uint256 _rID = rID_; 467 | 468 | // grab time 469 | uint256 _now = now; 470 | 471 | // fetch player ID 472 | uint256 _pID = pIDxAddr_[msg.sender]; 473 | 474 | // setup temp var for player eth 475 | uint256 _eth; 476 | 477 | // check to see if round has ended and no one has run round end yet 478 | if (_now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) 479 | { 480 | // set up our tx event data 481 | F3Ddatasets.EventReturns memory _eventData_; 482 | 483 | // end the round (distributes pot) 484 | round_[_rID].ended = true; 485 | _eventData_ = endRound(_eventData_); 486 | 487 | // get their earnings 488 | _eth = withdrawEarnings(_pID); 489 | 490 | // gib moni 491 | if (_eth > 0) 492 | plyr_[_pID].addr.transfer(_eth); 493 | 494 | // build event data 495 | _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); 496 | _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; 497 | 498 | // fire withdraw and distribute event 499 | emit F3Devents.onWithdrawAndDistribute 500 | ( 501 | msg.sender, 502 | plyr_[_pID].name, 503 | _eth, 504 | _eventData_.compressedData, 505 | _eventData_.compressedIDs, 506 | _eventData_.winnerAddr, 507 | _eventData_.winnerName, 508 | _eventData_.amountWon, 509 | _eventData_.newPot, 510 | _eventData_.P3DAmount, 511 | _eventData_.genAmount 512 | ); 513 | 514 | // in any other situation 515 | } else { 516 | // get their earnings 517 | _eth = withdrawEarnings(_pID); 518 | 519 | // gib moni 520 | if (_eth > 0) 521 | plyr_[_pID].addr.transfer(_eth); 522 | 523 | // fire withdraw event 524 | emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now); 525 | } 526 | } 527 | 528 | /** 529 | * @dev use these to register names. they are just wrappers that will send the 530 | * registration requests to the PlayerBook contract. So registering here is the 531 | * same as registering there. UI will always display the last name you registered. 532 | * but you will still own all previously registered names to use as affiliate 533 | * links. 534 | * - must pay a registration fee. 535 | * - name must be unique 536 | * - names will be converted to lowercase 537 | * - name cannot start or end with a space 538 | * - cannot have more than 1 space in a row 539 | * - cannot be only numbers 540 | * - cannot start with 0x 541 | * - name must be at least 1 char 542 | * - max length of 32 characters long 543 | * - allowed characters: a-z, 0-9, and space 544 | * -functionhash- 0x921dec21 (using ID for affiliate) 545 | * -functionhash- 0x3ddd4698 (using address for affiliate) 546 | * -functionhash- 0x685ffd83 (using name for affiliate) 547 | * @param _nameString players desired name 548 | * @param _affCode affiliate ID, address, or name of who referred you 549 | * @param _all set to true if you want this to push your info to all games 550 | * (this might cost a lot of gas) 551 | */ 552 | function registerNameXID(string _nameString, uint256 _affCode, bool _all) 553 | isHuman() 554 | public 555 | payable 556 | { 557 | bytes32 _name = _nameString.nameFilter(); 558 | address _addr = msg.sender; 559 | uint256 _paid = msg.value; 560 | (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXIDFromDapp.value(_paid)(_addr, _name, _affCode, _all); 561 | 562 | uint256 _pID = pIDxAddr_[_addr]; 563 | 564 | // fire event 565 | emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); 566 | } 567 | 568 | function registerNameXaddr(string _nameString, address _affCode, bool _all) 569 | isHuman() 570 | public 571 | payable 572 | { 573 | bytes32 _name = _nameString.nameFilter(); 574 | address _addr = msg.sender; 575 | uint256 _paid = msg.value; 576 | (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXaddrFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); 577 | 578 | uint256 _pID = pIDxAddr_[_addr]; 579 | 580 | // fire event 581 | emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); 582 | } 583 | 584 | function registerNameXname(string _nameString, bytes32 _affCode, bool _all) 585 | isHuman() 586 | public 587 | payable 588 | { 589 | bytes32 _name = _nameString.nameFilter(); 590 | address _addr = msg.sender; 591 | uint256 _paid = msg.value; 592 | (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXnameFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); 593 | 594 | uint256 _pID = pIDxAddr_[_addr]; 595 | 596 | // fire event 597 | emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); 598 | } 599 | //============================================================================== 600 | // _ _ _|__|_ _ _ _ . 601 | // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) 602 | //=====_|======================================================================= 603 | /** 604 | * @dev return the price buyer will pay for next 1 individual key. 605 | * -functionhash- 0x018a25e8 606 | * @return price for next key bought (in wei format) 607 | */ 608 | function getBuyPrice() 609 | public 610 | view 611 | returns(uint256) 612 | { 613 | // setup local rID 614 | uint256 _rID = rID_; 615 | 616 | // grab time 617 | uint256 _now = now; 618 | 619 | // are we in a round? 620 | if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) 621 | return ( (round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000) ); 622 | else // rounds over. need price for new round 623 | return ( 75000000000000 ); // init 624 | } 625 | 626 | /** 627 | * @dev returns time left. dont spam this, you'll ddos yourself from your node 628 | * provider 629 | * -functionhash- 0xc7e284b8 630 | * @return time left in seconds 631 | */ 632 | function getTimeLeft() 633 | public 634 | view 635 | returns(uint256) 636 | { 637 | // setup local rID 638 | uint256 _rID = rID_; 639 | 640 | // grab time 641 | uint256 _now = now; 642 | 643 | if (_now < round_[_rID].end) 644 | if (_now > round_[_rID].strt + rndGap_) 645 | return( (round_[_rID].end).sub(_now) ); 646 | else 647 | return( (round_[_rID].strt + rndGap_).sub(_now) ); 648 | else 649 | return(0); 650 | } 651 | 652 | /** 653 | * @dev returns player earnings per vaults 654 | * -functionhash- 0x63066434 655 | * @return winnings vault 656 | * @return general vault 657 | * @return affiliate vault 658 | */ 659 | function getPlayerVaults(uint256 _pID) 660 | public 661 | view 662 | returns(uint256 ,uint256, uint256) 663 | { 664 | // setup local rID 665 | uint256 _rID = rID_; 666 | 667 | // if round has ended. but round end has not been run (so contract has not distributed winnings) 668 | if (now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) 669 | { 670 | // if player is winner 671 | if (round_[_rID].plyr == _pID) 672 | { 673 | return 674 | ( 675 | (plyr_[_pID].win).add( ((round_[_rID].pot).mul(48)) / 100 ), 676 | (plyr_[_pID].gen).add( getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask) ), 677 | plyr_[_pID].aff 678 | ); 679 | // if player is not the winner 680 | } else { 681 | return 682 | ( 683 | plyr_[_pID].win, 684 | (plyr_[_pID].gen).add( getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask) ), 685 | plyr_[_pID].aff 686 | ); 687 | } 688 | 689 | // if round is still going on, or round has ended and round end has been ran 690 | } else { 691 | return 692 | ( 693 | plyr_[_pID].win, 694 | (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), 695 | plyr_[_pID].aff 696 | ); 697 | } 698 | } 699 | 700 | /** 701 | * solidity hates stack limits. this lets us avoid that hate 702 | */ 703 | function getPlayerVaultsHelper(uint256 _pID, uint256 _rID) 704 | private 705 | view 706 | returns(uint256) 707 | { 708 | return( ((((round_[_rID].mask).add(((((round_[_rID].pot).mul(potSplit_[round_[_rID].team].gen)) / 100).mul(1000000000000000000)) / (round_[_rID].keys))).mul(plyrRnds_[_pID][_rID].keys)) / 1000000000000000000) ); 709 | } 710 | 711 | /** 712 | * @dev returns all current round info needed for front end 713 | * -functionhash- 0x747dff42 714 | * @return eth invested during ICO phase 715 | * @return round id 716 | * @return total keys for round 717 | * @return time round ends 718 | * @return time round started 719 | * @return current pot 720 | * @return current team ID & player ID in lead 721 | * @return current player in leads address 722 | * @return current player in leads name 723 | * @return whales eth in for round 724 | * @return bears eth in for round 725 | * @return sneks eth in for round 726 | * @return bulls eth in for round 727 | * @return airdrop tracker # & airdrop pot 728 | */ 729 | function getCurrentRoundInfo() 730 | public 731 | view 732 | returns(uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256) 733 | { 734 | // setup local rID 735 | uint256 _rID = rID_; 736 | 737 | return 738 | ( 739 | round_[_rID].ico, //0 740 | _rID, //1 741 | round_[_rID].keys, //2 742 | round_[_rID].end, //3 743 | round_[_rID].strt, //4 744 | round_[_rID].pot, //5 745 | (round_[_rID].team + (round_[_rID].plyr * 10)), //6 746 | plyr_[round_[_rID].plyr].addr, //7 747 | plyr_[round_[_rID].plyr].name, //8 748 | rndTmEth_[_rID][0], //9 749 | rndTmEth_[_rID][1], //10 750 | rndTmEth_[_rID][2], //11 751 | rndTmEth_[_rID][3], //12 752 | airDropTracker_ + (airDropPot_ * 1000) //13 753 | ); 754 | } 755 | 756 | /** 757 | * @dev returns player info based on address. if no address is given, it will 758 | * use msg.sender 759 | * -functionhash- 0xee0b5d8b 760 | * @param _addr address of the player you want to lookup 761 | * @return player ID 762 | * @return player name 763 | * @return keys owned (current round) 764 | * @return winnings vault 765 | * @return general vault 766 | * @return affiliate vault 767 | * @return player round eth 768 | */ 769 | function getPlayerInfoByAddress(address _addr) 770 | public 771 | view 772 | returns(uint256, bytes32, uint256, uint256, uint256, uint256, uint256) 773 | { 774 | // setup local rID 775 | uint256 _rID = rID_; 776 | 777 | if (_addr == address(0)) 778 | { 779 | _addr == msg.sender; 780 | } 781 | uint256 _pID = pIDxAddr_[_addr]; 782 | 783 | return 784 | ( 785 | _pID, //0 786 | plyr_[_pID].name, //1 787 | plyrRnds_[_pID][_rID].keys, //2 788 | plyr_[_pID].win, //3 789 | (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), //4 790 | plyr_[_pID].aff, //5 791 | plyrRnds_[_pID][_rID].eth //6 792 | ); 793 | } 794 | 795 | //============================================================================== 796 | // _ _ _ _ | _ _ . _ . 797 | // (_(_)| (/_ |(_)(_||(_ . (this + tools + calcs + modules = our softwares engine) 798 | //=====================_|======================================================= 799 | /** 800 | * @dev logic runs whenever a buy order is executed. determines how to handle 801 | * incoming eth depending on if we are in an active round or not 802 | */ 803 | function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) 804 | private 805 | { 806 | // setup local rID 807 | uint256 _rID = rID_; 808 | 809 | // grab time 810 | uint256 _now = now; 811 | 812 | // if round is active 813 | if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) 814 | { 815 | // call core 816 | core(_rID, _pID, msg.value, _affID, _team, _eventData_); 817 | 818 | // if round is not active 819 | } else { 820 | // check to see if end round needs to be ran 821 | if (_now > round_[_rID].end && round_[_rID].ended == false) 822 | { 823 | // end the round (distributes pot) & start new round 824 | round_[_rID].ended = true; 825 | _eventData_ = endRound(_eventData_); 826 | 827 | // build event data 828 | _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); 829 | _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; 830 | 831 | // fire buy and distribute event 832 | emit F3Devents.onBuyAndDistribute 833 | ( 834 | msg.sender, 835 | plyr_[_pID].name, 836 | msg.value, 837 | _eventData_.compressedData, 838 | _eventData_.compressedIDs, 839 | _eventData_.winnerAddr, 840 | _eventData_.winnerName, 841 | _eventData_.amountWon, 842 | _eventData_.newPot, 843 | _eventData_.P3DAmount, 844 | _eventData_.genAmount 845 | ); 846 | } 847 | 848 | // put eth in players vault 849 | plyr_[_pID].gen = plyr_[_pID].gen.add(msg.value); 850 | } 851 | } 852 | 853 | /** 854 | * @dev logic runs whenever a reload order is executed. determines how to handle 855 | * incoming eth depending on if we are in an active round or not 856 | */ 857 | function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_) 858 | private 859 | { 860 | // setup local rID 861 | uint256 _rID = rID_; 862 | 863 | // grab time 864 | uint256 _now = now; 865 | 866 | // if round is active 867 | if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) 868 | { 869 | // get earnings from all vaults and return unused to gen vault 870 | // because we use a custom safemath library. this will throw if player 871 | // tried to spend more eth than they have. 872 | plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth); 873 | 874 | // call core 875 | core(_rID, _pID, _eth, _affID, _team, _eventData_); 876 | 877 | // if round is not active and end round needs to be ran 878 | } else if (_now > round_[_rID].end && round_[_rID].ended == false) { 879 | // end the round (distributes pot) & start new round 880 | round_[_rID].ended = true; 881 | _eventData_ = endRound(_eventData_); 882 | 883 | // build event data 884 | _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); 885 | _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; 886 | 887 | // fire buy and distribute event 888 | emit F3Devents.onReLoadAndDistribute 889 | ( 890 | msg.sender, 891 | plyr_[_pID].name, 892 | _eventData_.compressedData, 893 | _eventData_.compressedIDs, 894 | _eventData_.winnerAddr, 895 | _eventData_.winnerName, 896 | _eventData_.amountWon, 897 | _eventData_.newPot, 898 | _eventData_.P3DAmount, 899 | _eventData_.genAmount 900 | ); 901 | } 902 | } 903 | 904 | /** 905 | * @dev this is the core logic for any buy/reload that happens while a round 906 | * is live. 907 | */ 908 | function core(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) 909 | private 910 | { 911 | // if player is new to round 912 | if (plyrRnds_[_pID][_rID].keys == 0) 913 | _eventData_ = managePlayer(_pID, _eventData_); 914 | 915 | // early round eth limiter 916 | if (round_[_rID].eth < 100000000000000000000 && plyrRnds_[_pID][_rID].eth.add(_eth) > 1000000000000000000) 917 | { 918 | uint256 _availableLimit = (1000000000000000000).sub(plyrRnds_[_pID][_rID].eth); 919 | uint256 _refund = _eth.sub(_availableLimit); 920 | plyr_[_pID].gen = plyr_[_pID].gen.add(_refund); 921 | _eth = _availableLimit; 922 | } 923 | 924 | // if eth left is greater than min eth allowed (sorry no pocket lint) 925 | if (_eth > 1000000000) 926 | { 927 | 928 | // mint the new keys 929 | uint256 _keys = (round_[_rID].eth).keysRec(_eth); 930 | 931 | // if they bought at least 1 whole key 932 | if (_keys >= 1000000000000000000) 933 | { 934 | updateTimer(_keys, _rID); 935 | 936 | // set new leaders 937 | if (round_[_rID].plyr != _pID) 938 | round_[_rID].plyr = _pID; 939 | if (round_[_rID].team != _team) 940 | round_[_rID].team = _team; 941 | 942 | // set the new leader bool to true 943 | _eventData_.compressedData = _eventData_.compressedData + 100; 944 | } 945 | 946 | // manage airdrops 947 | if (_eth >= 100000000000000000) 948 | { 949 | airDropTracker_++; 950 | if (airdrop() == true) 951 | { 952 | // gib muni 953 | uint256 _prize; 954 | if (_eth >= 10000000000000000000) 955 | { 956 | // calculate prize and give it to winner 957 | _prize = ((airDropPot_).mul(75)) / 100; 958 | plyr_[_pID].win = (plyr_[_pID].win).add(_prize); 959 | 960 | // adjust airDropPot 961 | airDropPot_ = (airDropPot_).sub(_prize); 962 | 963 | // let event know a tier 3 prize was won 964 | _eventData_.compressedData += 300000000000000000000000000000000; 965 | } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) { 966 | // calculate prize and give it to winner 967 | _prize = ((airDropPot_).mul(50)) / 100; 968 | plyr_[_pID].win = (plyr_[_pID].win).add(_prize); 969 | 970 | // adjust airDropPot 971 | airDropPot_ = (airDropPot_).sub(_prize); 972 | 973 | // let event know a tier 2 prize was won 974 | _eventData_.compressedData += 200000000000000000000000000000000; 975 | } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) { 976 | // calculate prize and give it to winner 977 | _prize = ((airDropPot_).mul(25)) / 100; 978 | plyr_[_pID].win = (plyr_[_pID].win).add(_prize); 979 | 980 | // adjust airDropPot 981 | airDropPot_ = (airDropPot_).sub(_prize); 982 | 983 | // let event know a tier 3 prize was won 984 | _eventData_.compressedData += 300000000000000000000000000000000; 985 | } 986 | // set airdrop happened bool to true 987 | _eventData_.compressedData += 10000000000000000000000000000000; 988 | // let event know how much was won 989 | _eventData_.compressedData += _prize * 1000000000000000000000000000000000; 990 | 991 | // reset air drop tracker 992 | airDropTracker_ = 0; 993 | } 994 | } 995 | 996 | // store the air drop tracker number (number of buys since last airdrop) 997 | _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000); 998 | 999 | // update player 1000 | plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys); 1001 | plyrRnds_[_pID][_rID].eth = _eth.add(plyrRnds_[_pID][_rID].eth); 1002 | 1003 | // update round 1004 | round_[_rID].keys = _keys.add(round_[_rID].keys); 1005 | round_[_rID].eth = _eth.add(round_[_rID].eth); 1006 | rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]); 1007 | 1008 | // distribute eth 1009 | _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_); 1010 | _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_); 1011 | 1012 | // call end tx function to fire end tx event. 1013 | endTx(_pID, _team, _eth, _keys, _eventData_); 1014 | } 1015 | } 1016 | //============================================================================== 1017 | // _ _ | _ | _ _|_ _ _ _ . 1018 | // (_(_||(_|_||(_| | (_)| _\ . 1019 | //============================================================================== 1020 | /** 1021 | * @dev calculates unmasked earnings (just calculates, does not update mask) 1022 | * @return earnings in wei format 1023 | */ 1024 | function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast) 1025 | private 1026 | view 1027 | returns(uint256) 1028 | { 1029 | return( (((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask) ); 1030 | } 1031 | 1032 | /** 1033 | * @dev returns the amount of keys you would get given an amount of eth. 1034 | * -functionhash- 0xce89c80c 1035 | * @param _rID round ID you want price for 1036 | * @param _eth amount of eth sent in 1037 | * @return keys received 1038 | */ 1039 | function calcKeysReceived(uint256 _rID, uint256 _eth) 1040 | public 1041 | view 1042 | returns(uint256) 1043 | { 1044 | // grab time 1045 | uint256 _now = now; 1046 | 1047 | // are we in a round? 1048 | if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) 1049 | return ( (round_[_rID].eth).keysRec(_eth) ); 1050 | else // rounds over. need keys for new round 1051 | return ( (_eth).keys() ); 1052 | } 1053 | 1054 | /** 1055 | * @dev returns current eth price for X keys. 1056 | * -functionhash- 0xcf808000 1057 | * @param _keys number of keys desired (in 18 decimal format) 1058 | * @return amount of eth needed to send 1059 | */ 1060 | function iWantXKeys(uint256 _keys) 1061 | public 1062 | view 1063 | returns(uint256) 1064 | { 1065 | // setup local rID 1066 | uint256 _rID = rID_; 1067 | 1068 | // grab time 1069 | uint256 _now = now; 1070 | 1071 | // are we in a round? 1072 | if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) 1073 | return ( (round_[_rID].keys.add(_keys)).ethRec(_keys) ); 1074 | else // rounds over. need price for new round 1075 | return ( (_keys).eth() ); 1076 | } 1077 | //============================================================================== 1078 | // _|_ _ _ | _ . 1079 | // | (_)(_)|_\ . 1080 | //============================================================================== 1081 | /** 1082 | * @dev receives name/player info from names contract 1083 | */ 1084 | function receivePlayerInfo(uint256 _pID, address _addr, bytes32 _name, uint256 _laff) 1085 | external 1086 | { 1087 | require (msg.sender == address(PlayerBook), "your not playerNames contract... hmmm.."); 1088 | if (pIDxAddr_[_addr] != _pID) 1089 | pIDxAddr_[_addr] = _pID; 1090 | if (pIDxName_[_name] != _pID) 1091 | pIDxName_[_name] = _pID; 1092 | if (plyr_[_pID].addr != _addr) 1093 | plyr_[_pID].addr = _addr; 1094 | if (plyr_[_pID].name != _name) 1095 | plyr_[_pID].name = _name; 1096 | if (plyr_[_pID].laff != _laff) 1097 | plyr_[_pID].laff = _laff; 1098 | if (plyrNames_[_pID][_name] == false) 1099 | plyrNames_[_pID][_name] = true; 1100 | } 1101 | 1102 | /** 1103 | * @dev receives entire player name list 1104 | */ 1105 | function receivePlayerNameList(uint256 _pID, bytes32 _name) 1106 | external 1107 | { 1108 | require (msg.sender == address(PlayerBook), "your not playerNames contract... hmmm.."); 1109 | if(plyrNames_[_pID][_name] == false) 1110 | plyrNames_[_pID][_name] = true; 1111 | } 1112 | 1113 | /** 1114 | * @dev gets existing or registers new pID. use this when a player may be new 1115 | * @return pID 1116 | */ 1117 | function determinePID(F3Ddatasets.EventReturns memory _eventData_) 1118 | private 1119 | returns (F3Ddatasets.EventReturns) 1120 | { 1121 | uint256 _pID = pIDxAddr_[msg.sender]; 1122 | // if player is new to this version of fomo3d 1123 | if (_pID == 0) 1124 | { 1125 | // grab their player ID, name and last aff ID, from player names contract 1126 | _pID = PlayerBook.getPlayerID(msg.sender); 1127 | bytes32 _name = PlayerBook.getPlayerName(_pID); 1128 | uint256 _laff = PlayerBook.getPlayerLAff(_pID); 1129 | 1130 | // set up player account 1131 | pIDxAddr_[msg.sender] = _pID; 1132 | plyr_[_pID].addr = msg.sender; 1133 | 1134 | if (_name != "") 1135 | { 1136 | pIDxName_[_name] = _pID; 1137 | plyr_[_pID].name = _name; 1138 | plyrNames_[_pID][_name] = true; 1139 | } 1140 | 1141 | if (_laff != 0 && _laff != _pID) 1142 | plyr_[_pID].laff = _laff; 1143 | 1144 | // set the new player bool to true 1145 | _eventData_.compressedData = _eventData_.compressedData + 1; 1146 | } 1147 | return (_eventData_); 1148 | } 1149 | 1150 | /** 1151 | * @dev checks to make sure user picked a valid team. if not sets team 1152 | * to default (sneks) 1153 | */ 1154 | function verifyTeam(uint256 _team) 1155 | private 1156 | pure 1157 | returns (uint256) 1158 | { 1159 | if (_team < 0 || _team > 3) 1160 | return(2); 1161 | else 1162 | return(_team); 1163 | } 1164 | 1165 | /** 1166 | * @dev decides if round end needs to be run & new round started. and if 1167 | * player unmasked earnings from previously played rounds need to be moved. 1168 | */ 1169 | function managePlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_) 1170 | private 1171 | returns (F3Ddatasets.EventReturns) 1172 | { 1173 | // if player has played a previous round, move their unmasked earnings 1174 | // from that round to gen vault. 1175 | if (plyr_[_pID].lrnd != 0) 1176 | updateGenVault(_pID, plyr_[_pID].lrnd); 1177 | 1178 | // update player's last round played 1179 | plyr_[_pID].lrnd = rID_; 1180 | 1181 | // set the joined round bool to true 1182 | _eventData_.compressedData = _eventData_.compressedData + 10; 1183 | 1184 | return(_eventData_); 1185 | } 1186 | 1187 | /** 1188 | * @dev ends the round. manages paying out winner/splitting up pot 1189 | */ 1190 | function endRound(F3Ddatasets.EventReturns memory _eventData_) 1191 | private 1192 | returns (F3Ddatasets.EventReturns) 1193 | { 1194 | // setup local rID 1195 | uint256 _rID = rID_; 1196 | 1197 | // grab our winning player and team id's 1198 | uint256 _winPID = round_[_rID].plyr; 1199 | uint256 _winTID = round_[_rID].team; 1200 | 1201 | // grab our pot amount 1202 | uint256 _pot = round_[_rID].pot; 1203 | 1204 | // calculate our winner share, community rewards, gen share, 1205 | // p3d share, and amount reserved for next pot 1206 | uint256 _win = (_pot.mul(48)) / 100; 1207 | uint256 _com = (_pot / 50); 1208 | uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100; 1209 | uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100; 1210 | uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d); 1211 | 1212 | // calculate ppt for round mask 1213 | uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); 1214 | uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000); 1215 | if (_dust > 0) 1216 | { 1217 | _gen = _gen.sub(_dust); 1218 | _res = _res.add(_dust); 1219 | } 1220 | 1221 | // pay our winner 1222 | plyr_[_winPID].win = _win.add(plyr_[_winPID].win); 1223 | 1224 | // community rewards 1225 | if (!address(Jekyll_Island_Inc).call.value(_com)(bytes4(keccak256("deposit()")))) 1226 | { 1227 | // This ensures Team Just cannot influence the outcome of FoMo3D with 1228 | // bank migrations by breaking outgoing transactions. 1229 | // Something we would never do. But that's not the point. 1230 | // We spent 2000$ in eth re-deploying just to patch this, we hold the 1231 | // highest belief that everything we create should be trustless. 1232 | // Team JUST, The name you shouldn't have to trust. 1233 | _p3d = _p3d.add(_com); 1234 | _com = 0; 1235 | } 1236 | 1237 | // distribute gen portion to key holders 1238 | round_[_rID].mask = _ppt.add(round_[_rID].mask); 1239 | 1240 | // send share for p3d to divies 1241 | if (_p3d > 0) 1242 | Divies.deposit.value(_p3d)(); 1243 | 1244 | // prepare event data 1245 | _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000); 1246 | _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000); 1247 | _eventData_.winnerAddr = plyr_[_winPID].addr; 1248 | _eventData_.winnerName = plyr_[_winPID].name; 1249 | _eventData_.amountWon = _win; 1250 | _eventData_.genAmount = _gen; 1251 | _eventData_.P3DAmount = _p3d; 1252 | _eventData_.newPot = _res; 1253 | 1254 | // start next round 1255 | rID_++; 1256 | _rID++; 1257 | round_[_rID].strt = now; 1258 | round_[_rID].end = now.add(rndInit_).add(rndGap_); 1259 | round_[_rID].pot = _res; 1260 | 1261 | return(_eventData_); 1262 | } 1263 | 1264 | /** 1265 | * @dev moves any unmasked earnings to gen vault. updates earnings mask 1266 | */ 1267 | function updateGenVault(uint256 _pID, uint256 _rIDlast) 1268 | private 1269 | { 1270 | uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast); 1271 | if (_earnings > 0) 1272 | { 1273 | // put in gen vault 1274 | plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen); 1275 | // zero out their earnings by updating mask 1276 | plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask); 1277 | } 1278 | } 1279 | 1280 | /** 1281 | * @dev updates round timer based on number of whole keys bought. 1282 | */ 1283 | function updateTimer(uint256 _keys, uint256 _rID) 1284 | private 1285 | { 1286 | // grab time 1287 | uint256 _now = now; 1288 | 1289 | // calculate time based on number of keys bought 1290 | uint256 _newTime; 1291 | if (_now > round_[_rID].end && round_[_rID].plyr == 0) 1292 | _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(_now); 1293 | else 1294 | _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end); 1295 | 1296 | // compare to max and set new end time 1297 | if (_newTime < (rndMax_).add(_now)) 1298 | round_[_rID].end = _newTime; 1299 | else 1300 | round_[_rID].end = rndMax_.add(_now); 1301 | } 1302 | 1303 | /** 1304 | * @dev generates a random number between 0-99 and checks to see if thats 1305 | * resulted in an airdrop win 1306 | * @return do we have a winner? 1307 | */ 1308 | function airdrop() 1309 | private 1310 | view 1311 | returns(bool) 1312 | { 1313 | uint256 seed = uint256(keccak256(abi.encodePacked( 1314 | 1315 | (block.timestamp).add 1316 | (block.difficulty).add 1317 | ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add 1318 | (block.gaslimit).add 1319 | ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add 1320 | (block.number) 1321 | 1322 | ))); 1323 | if((seed - ((seed / 1000) * 1000)) < airDropTracker_) 1324 | return(true); 1325 | else 1326 | return(false); 1327 | } 1328 | 1329 | /** 1330 | * @dev distributes eth based on fees to com, aff, and p3d 1331 | */ 1332 | function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) 1333 | private 1334 | returns(F3Ddatasets.EventReturns) 1335 | { 1336 | // pay 2% out to community rewards 1337 | uint256 _com = _eth / 50; 1338 | uint256 _p3d; 1339 | if (!address(Jekyll_Island_Inc).call.value(_com)(bytes4(keccak256("deposit()")))) 1340 | { 1341 | // This ensures Team Just cannot influence the outcome of FoMo3D with 1342 | // bank migrations by breaking outgoing transactions. 1343 | // Something we would never do. But that's not the point. 1344 | // We spent 2000$ in eth re-deploying just to patch this, we hold the 1345 | // highest belief that everything we create should be trustless. 1346 | // Team JUST, The name you shouldn't have to trust. 1347 | _p3d = _com; 1348 | _com = 0; 1349 | } 1350 | 1351 | // pay 1% out to FoMo3D short 1352 | uint256 _long = _eth / 100; 1353 | otherF3D_.potSwap.value(_long)(); 1354 | 1355 | // distribute share to affiliate 1356 | uint256 _aff = _eth / 10; 1357 | 1358 | // decide what to do with affiliate share of fees 1359 | // affiliate must not be self, and must have a name registered 1360 | if (_affID != _pID && plyr_[_affID].name != '') { 1361 | plyr_[_affID].aff = _aff.add(plyr_[_affID].aff); 1362 | emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _aff, now); 1363 | } else { 1364 | _p3d = _aff; 1365 | } 1366 | 1367 | // pay out p3d 1368 | _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100)); 1369 | if (_p3d > 0) 1370 | { 1371 | // deposit to divies contract 1372 | Divies.deposit.value(_p3d)(); 1373 | 1374 | // set up event data 1375 | _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount); 1376 | } 1377 | 1378 | return(_eventData_); 1379 | } 1380 | 1381 | function potSwap() 1382 | external 1383 | payable 1384 | { 1385 | // setup local rID 1386 | uint256 _rID = rID_ + 1; 1387 | 1388 | round_[_rID].pot = round_[_rID].pot.add(msg.value); 1389 | emit F3Devents.onPotSwapDeposit(_rID, msg.value); 1390 | } 1391 | 1392 | /** 1393 | * @dev distributes eth based on fees to gen and pot 1394 | */ 1395 | function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) 1396 | private 1397 | returns(F3Ddatasets.EventReturns) 1398 | { 1399 | // calculate gen share 1400 | uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100; 1401 | 1402 | // toss 1% into airdrop pot 1403 | uint256 _air = (_eth / 100); 1404 | airDropPot_ = airDropPot_.add(_air); 1405 | 1406 | // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) 1407 | _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100)); 1408 | 1409 | // calculate pot 1410 | uint256 _pot = _eth.sub(_gen); 1411 | 1412 | // distribute gen share (thats what updateMasks() does) and adjust 1413 | // balances for dust. 1414 | uint256 _dust = updateMasks(_rID, _pID, _gen, _keys); 1415 | if (_dust > 0) 1416 | _gen = _gen.sub(_dust); 1417 | 1418 | // add eth to pot 1419 | round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot); 1420 | 1421 | // set up event data 1422 | _eventData_.genAmount = _gen.add(_eventData_.genAmount); 1423 | _eventData_.potAmount = _pot; 1424 | 1425 | return(_eventData_); 1426 | } 1427 | 1428 | /** 1429 | * @dev updates masks for round and player when keys are bought 1430 | * @return dust left over 1431 | */ 1432 | function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys) 1433 | private 1434 | returns(uint256) 1435 | { 1436 | /* MASKING NOTES 1437 | earnings masks are a tricky thing for people to wrap their minds around. 1438 | the basic thing to understand here. is were going to have a global 1439 | tracker based on profit per share for each round, that increases in 1440 | relevant proportion to the increase in share supply. 1441 | 1442 | the player will have an additional mask that basically says "based 1443 | on the rounds mask, my shares, and how much i've already withdrawn, 1444 | how much is still owed to me?" 1445 | */ 1446 | 1447 | // calc profit per key & round mask based on this buy: (dust goes to pot) 1448 | uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); 1449 | round_[_rID].mask = _ppt.add(round_[_rID].mask); 1450 | 1451 | // calculate player earning from their own buy (only based on the keys 1452 | // they just bought). & update player earnings mask 1453 | uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000); 1454 | plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask); 1455 | 1456 | // calculate & return dust 1457 | return(_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000))); 1458 | } 1459 | 1460 | /** 1461 | * @dev adds up unmasked earnings, & vault earnings, sets them all to 0 1462 | * @return earnings in wei format 1463 | */ 1464 | function withdrawEarnings(uint256 _pID) 1465 | private 1466 | returns(uint256) 1467 | { 1468 | // update gen vault 1469 | updateGenVault(_pID, plyr_[_pID].lrnd); 1470 | 1471 | // from vaults 1472 | uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff); 1473 | if (_earnings > 0) 1474 | { 1475 | plyr_[_pID].win = 0; 1476 | plyr_[_pID].gen = 0; 1477 | plyr_[_pID].aff = 0; 1478 | } 1479 | 1480 | return(_earnings); 1481 | } 1482 | 1483 | /** 1484 | * @dev prepares compression data and fires event for buy or reload tx's 1485 | */ 1486 | function endTx(uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) 1487 | private 1488 | { 1489 | _eventData_.compressedData = _eventData_.compressedData + (now * 1000000000000000000) + (_team * 100000000000000000000000000000); 1490 | _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (rID_ * 10000000000000000000000000000000000000000000000000000); 1491 | 1492 | emit F3Devents.onEndTx 1493 | ( 1494 | _eventData_.compressedData, 1495 | _eventData_.compressedIDs, 1496 | plyr_[_pID].name, 1497 | msg.sender, 1498 | _eth, 1499 | _keys, 1500 | _eventData_.winnerAddr, 1501 | _eventData_.winnerName, 1502 | _eventData_.amountWon, 1503 | _eventData_.newPot, 1504 | _eventData_.P3DAmount, 1505 | _eventData_.genAmount, 1506 | _eventData_.potAmount, 1507 | airDropPot_ 1508 | ); 1509 | } 1510 | //============================================================================== 1511 | // (~ _ _ _._|_ . 1512 | // _)(/_(_|_|| | | \/ . 1513 | //====================/========================================================= 1514 | /** upon contract deploy, it will be deactivated. this is a one time 1515 | * use function that will activate the contract. we do this so devs 1516 | * have time to set things up on the web end **/ 1517 | bool public activated_ = false; 1518 | function activate() 1519 | public 1520 | { 1521 | // only team just can activate 1522 | require( 1523 | msg.sender == 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C || 1524 | msg.sender == 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D || 1525 | msg.sender == 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53 || 1526 | msg.sender == 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C || 1527 | msg.sender == 0xF39e044e1AB204460e06E87c6dca2c6319fC69E3, 1528 | "only team just can activate" 1529 | ); 1530 | 1531 | // make sure that its been linked. 1532 | require(address(otherF3D_) != address(0), "must link to other FoMo3D first"); 1533 | 1534 | // can only be ran once 1535 | require(activated_ == false, "fomo3d already activated"); 1536 | 1537 | // activate the contract 1538 | activated_ = true; 1539 | 1540 | // lets start first round 1541 | rID_ = 1; 1542 | round_[1].strt = now + rndExtra_ - rndGap_; 1543 | round_[1].end = now + rndInit_ + rndExtra_; 1544 | } 1545 | function setOtherFomo(address _otherF3D) 1546 | public 1547 | { 1548 | // only team just can activate 1549 | require( 1550 | msg.sender == 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C || 1551 | msg.sender == 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D || 1552 | msg.sender == 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53 || 1553 | msg.sender == 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C || 1554 | msg.sender == 0xF39e044e1AB204460e06E87c6dca2c6319fC69E3, 1555 | "only team just can activate" 1556 | ); 1557 | 1558 | // make sure that it HASNT yet been linked. 1559 | require(address(otherF3D_) == address(0), "silly dev, you already did that"); 1560 | 1561 | // set up other fomo3d (fast or long) for pot swap 1562 | otherF3D_ = otherFoMo3D(_otherF3D); 1563 | } 1564 | } --------------------------------------------------------------------------------